Thanks man. You've just organized a lot of mess that i've been struggling with after learning about solid, clean architecture, ddd and some other stuff. I think its important to dig through those concepts to not only to understand what they are, but why they are. And from understanding those underlying core things that drive everything else, you can gain a lot of understanding of what to do when and why
I like clean code. It really instilled in me the importance of sticking to my guns and taking some extra time to making things better than when I found them.
I would wish to know developers more like you. Pragmatic and specially avoid complexity. Sometimes what we need to do is so basic, and it seems we are building a spaceship for nothing. And then in the end don't even is able to take off..
I think you touched a point there. SOLID and Clean Architecture both encompass several principles. Buzz words, mostly. The terms are a ways to codify and popularize these principles. There is a lot of opinionated stuff besides that and a lot of “templates”. But once you understand coupling and cohesion from a pragmatic perspective then you can order your stuff around however you want since you understand how to handle complexity.
Great video. High cohesion and loose coupling are what make SOLID principles etc possible. A class having fat methods must be refactored to small SRP methods. I will reveals what methods that doesn't belong in that class. You can extract those methods to a separate class. Now both classes have single responsibility. Now we do the same with with collection of cohesive classes extract it to a service, and let services communicate to each other, but not directly , its via some interface.
I love the idea of Coupling and Cohesion so much more than SOLID. It's so much simpler and more elegant. I would add one more "C" to it, though. 'Continuity". Functionality should never break after you make a change. You can overload functions and add optional parameters, but old method signatures should continue to work and work the same way.
5:07 Assume my UI has Name, Price and Quantity which an user can initially define when creating a new product. Is the UI required to send the Create request to each Service? My idea was to only provide a Create REST Endpoint within the Catalog module and internally using Domain and Integration Events like ProductCreated which then can be consumed by Warehouse for example. But this approach would require the Catalog Module to pass the quantity within the ProductCreated event. How could one avoid this?
7:12 why are "Models" not organized under "Features" with the features that they belong to? (is the model as a whole separate from features for design reasons? for example, I'm wondering if e.g. Checkout might also need access to the ShoppingCart and maybe that's why? do you generally keep the model separate from the features, even if the codebase is organized by feature?)
Often they are shared between various features, but a very limited subset that are related. Eg, Adding, Removing, Updating items, and Checking out a shopping cart all require the shopping cart.
I do believe most people build simple apps that do not require any coupling fighting. But then, once you start trying to write an app that implements business processes, you need to start thinking about behavior, events, and coupling. Even though I had my fair share of experience, I enjoyed this vid. Great work.
Glad you enjoyed it. Ya, I don't really know what "most" people are building. When building LOB type systems, in my experience they are fairly large and often end up in less than an ideal place, primarily because of lack of cohesion and almost no concern for coupling.
Thanks, appreciate the comment. I don't think of them as bold or have any intent of being against the grain for views or whatever. Just speaking what I think.
Hi Derek! When you split your product entity to support different capability centric services, do you still keep one table on the database or you split it there too ? Can I have different aggregate roots or entities from the same table ? 🤔
Yes. So as long as your making that distinction and are aware that your logical separation is different than the physical storage. They don't need to be the same, so yes.
Hello, thanks for the video, the content is great and super usefull! Though, i still believe the solid Principles are quite usefull. I believe that, at a deeper level, they are all about coupling and coehision. For example, you have already mentioned s.r.p. Then, o.c.p encourages polymorphism and dependency inversion, Therefore allowing various implementations to stay in different modules or services rather than putting them into the same place. Also, i.s.p. can be understood as "you should only depend on what you need". Breaking the interfaces into smaller ones is also something that will lead to a higher coehision of the respective component.
I think they can be a guide, but unfortunately without understanding the root issue (coupling & cohesion), they turn into "rules" and people fail to be pragmatic and understand the tradeoffs.
very good, thx. But may be you can write with some code examples, start from functions, class, component, module, library, api service... Now i can understand, but for example then i look python functionc and php classes, then need think more about how to do that cohesion :) Video very good, best of all what i saw
this what i similarly do in the frontend. group to features, shared uis/utilities and data. Then inside a feature, will have all my codes, may also have shared folders within
First, Thanks for yours video. But I have question, the Product table is one-to-one relationship, my question is what about the performance? what about multi joins? I started use yours way in my monolith project.
th-cam.com/video/DjZepWrAKzM/w-d-xo.html and I saw this video from you, and you didn't put the part 2 😅😅, How can we compose and retrieve the data from it. If you can help me. Thanks
The example is simplistic but to illustrate that different boundaries care about different data depending on the behaviors they provide. Each boundary would own the schema and data and provide a means through an API/contract. I wouldn't integrate via the database (eg, joins).
Really makes sense. There's only one thing that bothers me: sometimes you have to distribute code that could be part of one class to separate classes just to be able to unit test them (move them from the private methods of the original class to the public ones of a new class). In one sense it lowers cohesion and creates a new coupled class with the functionality that would benefit from being in one cohesive unit, on the other hand this makes functionality a lot more unit testable. Or is this more about micro service boundaries? What's your take on this?
I kind of know what you're referring to but I don't really do much of moving private to public etc. for testing purposes. Having multiple types isn't a problem as it's about grouping them together in the right place.
@@CodeOpinion Sometimes you'll have a lot of branching happening in those private. That makes testing particularly difficult for 2 reasons: 1) it might be a lot of work to setup inputs so a given branch is explored, and 2) the exponential explosion of branches. If you decouple by injecting dependencies then you can test the branches independently, avoiding the exponential explosion and simplifying test setup. The problem is now you have lots of mocks, so your tests are coupled to the implementation. So there is a balance there too. Branches often are a sign an endpoint tries to do too much, but eh sometimes you can't ask your client(s) to change their code just to simplify yours. You have to contend with the contracts as they are: full of bells and whistles, options, bools, nullables = branches galore.
Not entirely. DDD has strategic and tactical patterns that ultimately are adressing coupling and cohesion. Almost everything resolves around them at the core.
Focusing on 'entities' should not be thought of as 'wrong'. Derek is probably trying to direct people to focus on certain aspects of a solution at certain levels of exposure. For example, if defining a public/private API to the business, this is where consumers of this service will rather see endpoints that make sense to them, so more in tune with their 'business needs' or their 'business workflows'. So that's one level. That layer will obviously at some point need to interact with data, and maybe you have a company policy where abstracting access to the underlying data-source needs to be forbidden or tightly controlled, and therefore, engineers would need to build a mechanism to expose 'entities' that represent the underlying source, and this is the fine-grained/micro level. Generally public facing API's should be more 'capability' driven and not needlessly 'data/entity' driven. Having said all this, when you look at Microsoft D365 OData API, they have ZERO capability level API's, they are all ENTITY based, at least from and endpoint pespective the terms are all 'entities'. So I gues it all depends on the type of thing you're building, and what type of consumer you are focusing on. :-)
I think the real value of SOLID and the like is simply to help talk around Coupling and Cohesion - especially with junior coders who seem to really struggle with this concept at an enterprise level.
Used as a guide they can be helpful. But if you don't understand the underlying reason they exist it turns into a pissing match. The number of times I get "but doesn't this violate X principle?" is pretty interesting.
how about simple code example illustrating the point. There is too much spaghetti definitions of coupling and cohesion online, what we need it cohesive and decoupled explanation which we can transfer and apply elsewhere...
Define one "thing". Everyone seemingly has a different definition. I'd guess most would use the "one reason to change" but think of it technically rather than business requirements, which is how I think of it.
@@CodeOpinion exactly. "Thing" here is could be business department. For example, Product in marketing department, is different than product in warehouse department. This is the kind of single responsibility where people often misunderstand. They put all the product related behaviour in the same class
I do proper solid with my C# and have done for many years. I get told …. ‘Nobody likes an uncle bob’ by those that wrote the most awful code I’ve seen in my 25yrs
That’s make sense, except for the catalog service. Why would you replicate your catalog to each service using events? Each service would have the entire catalog data…
Why would or wouldn't you? I covered this in a video about event-carried state transfer (th-cam.com/video/IzBEbfSg0uY/w-d-xo.html). But generally yes if it's more reference data from a supporting boundary, then sure. However often times most folks are concerned about replicating data when it's really just for View/UI composition, which is another topic that I need to cover.
It feels like there is a small group of people that understand and practice this. I also wonder if this problem exists in most language ecosystems, traditionally OO languages, or if it is .NET specific.
I feel like I completely don't get it after watching the video twice. The explanation jumps from high level to very high level and doesn't stop on explaining why high cohesion any better than low cohesion and strong coupling any worse than week coupling and what are the traid-offs. More abstract code often works out as a not needed and redundant layer which is easy to remove and get more imperative, simple code
Low cohesion will lead to high coupling. High coupling ultimately makes things more difficult to change. Check out this video, see if it helps: th-cam.com/video/wRVbHDkOMSM/w-d-xo.html
@@CodeOpinion "Low cohesion will lead to high coupling. " = "If the degree of how well things belong together is low, it will lead to the degree of interdependence between modules being high" If many modules are interdependent - it means that overall system is hard to change. So, to reframe this - if a thing doesn't belong somewhere firmly - it belongs to everywhere and a system becomes a ball of mud (difficult to change) if a thing belongs to a certain part of the system firmly - you have a limited number of dependencies on it and it is easier to change. I see that often the dependences are sort of bi-directional if a certain service doesn't bother to wrap the data in it's own abstraction. e.g. a details of CRM system leak to billing through sales, where sales doesn't change things. Then as long as billing gets some information, over time it starts to build dependencies on it, first accidentally and then as a lowest friction path. - it is faster to put data through the whole stack in a single format and schema, rather then create representation on each. Then it becomes that all parts of the system depend on CRM for example. So the "Ce" is hiddenly very high
I mean, you basically just paraphrased "Clean Code" and the core concepts of "Clean Architecture" using fewer words. SOLID itself is just a set of principles that effectively target coupling and cohesion. I don't think any seasoned developer "thinks" about the individual components of SOLID on a day-to-day basis, but instead has uses a mental model that they have built up over the years through both experience and studying/relating to principles and frameworks laid out by smart people before them.
My point is that if you started with coupling and cohesion, which I assume most don't, and you start with the ways to to deal with them, you don't really know why you're doing what you're doing. "I don't think any seasoned developer "thinks" about the individual components of SOLID on a day-to-day basis". I don't think anyone can agree on what "seasoned" is anymore. 😂
@@CodeOpinion I certainly agree with your point... I think that is sort of what I'm getting at. I don't think anybody can really agree with what the word "clean" means anymore. At least most people can have a relatively common understanding of what the words "coupling" and "cohesion" mean, so it makes for a good reference point
Thanks man. You've just organized a lot of mess that i've been struggling with after learning about solid, clean architecture, ddd and some other stuff. I think its important to dig through those concepts to not only to understand what they are, but why they are. And from understanding those underlying core things that drive everything else, you can gain a lot of understanding of what to do when and why
You just described why I created this channel and what I try to post videos about!
do you have top 10 books that you can recommend ? would love to hear from you 🙂
Good suggestion for a video!
I do and don't. The blue DDD book is one but hard to digest. I've been more into certain individuals perspectives and conference talks.
@@CodeOpinion that would be interesting to hear!
@@CodeOpinion It would be pretty interesting to see a video from you about talks, books, blogs, etc. that you have found useful and learn form.
I like clean code. It really instilled in me the importance of sticking to my guns and taking some extra time to making things better than when I found them.
I would wish to know developers more like you. Pragmatic and specially avoid complexity. Sometimes what we need to do is so basic, and it seems we are building a spaceship for nothing. And then in the end don't even is able to take off..
I think you touched a point there. SOLID and Clean Architecture both encompass several principles. Buzz words, mostly. The terms are a ways to codify and popularize these principles. There is a lot of opinionated stuff besides that and a lot of “templates”. But once you understand coupling and cohesion from a pragmatic perspective then you can order your stuff around however you want since you understand how to handle complexity.
Yup. There's many different approaches you can take if you narrow it down to coupling and cohesion
Great video! I would really love to hear your take on testing as well, unit testing, integration testing, TDD, etc. 😀
Great video.
High cohesion and loose coupling are what make SOLID principles etc possible.
A class having fat methods must be refactored to small SRP methods. I will reveals what methods that doesn't belong in that class. You can extract those methods to a separate class.
Now both classes have single responsibility.
Now we do the same with with collection of cohesive classes extract it to a service, and let services communicate to each other, but not directly , its via some interface.
I love the idea of Coupling and Cohesion so much more than SOLID. It's so much simpler and more elegant.
I would add one more "C" to it, though. 'Continuity". Functionality should never break after you make a change. You can overload functions and add optional parameters, but old method signatures should continue to work and work the same way.
5:07 Assume my UI has Name, Price and Quantity which an user can initially define when creating a new product. Is the UI required to send the Create request to each Service? My idea was to only provide a Create REST Endpoint within the Catalog module and internally using Domain and Integration Events like ProductCreated which then can be consumed by Warehouse for example. But this approach would require the Catalog Module to pass the quantity within the ProductCreated event. How could one avoid this?
I often hear people saying SRP means doing only one thing. You have clearly explained what that one thing should be. Great video! Thanks!
Thanks, actually coupling and cohesion are part of GRASP which in my opinion is more practical and applicable for modern architecture than SOLID.
7:12 why are "Models" not organized under "Features" with the features that they belong to? (is the model as a whole separate from features for design reasons? for example, I'm wondering if e.g. Checkout might also need access to the ShoppingCart and maybe that's why? do you generally keep the model separate from the features, even if the codebase is organized by feature?)
Often they are shared between various features, but a very limited subset that are related. Eg, Adding, Removing, Updating items, and Checking out a shopping cart all require the shopping cart.
I do believe most people build simple apps that do not require any coupling fighting. But then, once you start trying to write an app that implements business processes, you need to start thinking about behavior, events, and coupling. Even though I had my fair share of experience, I enjoyed this vid. Great work.
Glad you enjoyed it. Ya, I don't really know what "most" people are building. When building LOB type systems, in my experience they are fairly large and often end up in less than an ideal place, primarily because of lack of cohesion and almost no concern for coupling.
Thanks for your insights. You have bold statements but always reasonable. I really appreciate your labor for sharing your experience
Thanks, appreciate the comment. I don't think of them as bold or have any intent of being against the grain for views or whatever. Just speaking what I think.
Hi Derek! When you split your product entity to support different capability centric services, do you still keep one table on the database or you split it there too ? Can I have different aggregate roots or entities from the same table ? 🤔
Yes. So as long as your making that distinction and are aware that your logical separation is different than the physical storage. They don't need to be the same, so yes.
dudeeeee thanks for awesome video. It is so much clear now. I've been trying to get my head around this topic for the last 2 weeks.
Glad it helped.
Hello, thanks for the video, the content is great and super usefull!
Though, i still believe the solid Principles are quite usefull. I believe that, at a deeper level, they are all about coupling and coehision.
For example, you have already mentioned s.r.p. Then, o.c.p encourages polymorphism and dependency inversion, Therefore allowing various implementations to stay in different modules or services rather than putting them into the same place.
Also, i.s.p. can be understood as "you should only depend on what you need". Breaking the interfaces into smaller ones is also something that will lead to a higher coehision of the respective component.
I think they can be a guide, but unfortunately without understanding the root issue (coupling & cohesion), they turn into "rules" and people fail to be pragmatic and understand the tradeoffs.
very good, thx. But may be you can write with some code examples, start from functions, class, component, module, library, api service... Now i can understand, but for example then i look python functionc and php classes, then need think more about how to do that cohesion :) Video very good, best of all what i saw
this what i similarly do in the frontend. group to features, shared uis/utilities and data. Then inside a feature, will have all my codes, may also have shared folders within
very helpful, thank you! 👍👍
First, Thanks for yours video.
But I have question, the Product table is one-to-one relationship, my question is what about the performance? what about multi joins?
I started use yours way in my monolith project.
th-cam.com/video/DjZepWrAKzM/w-d-xo.html
and I saw this video from you, and you didn't put the part 2 😅😅, How can we compose and retrieve the data from it.
If you can help me. Thanks
The example is simplistic but to illustrate that different boundaries care about different data depending on the behaviors they provide. Each boundary would own the schema and data and provide a means through an API/contract. I wouldn't integrate via the database (eg, joins).
Really makes sense. There's only one thing that bothers me: sometimes you have to distribute code that could be part of one class to separate classes just to be able to unit test them (move them from the private methods of the original class to the public ones of a new class). In one sense it lowers cohesion and creates a new coupled class with the functionality that would benefit from being in one cohesive unit, on the other hand this makes functionality a lot more unit testable. Or is this more about micro service boundaries? What's your take on this?
I kind of know what you're referring to but I don't really do much of moving private to public etc. for testing purposes. Having multiple types isn't a problem as it's about grouping them together in the right place.
@@CodeOpinion Sometimes you'll have a lot of branching happening in those private. That makes testing particularly difficult for 2 reasons: 1) it might be a lot of work to setup inputs so a given branch is explored, and 2) the exponential explosion of branches. If you decouple by injecting dependencies then you can test the branches independently, avoiding the exponential explosion and simplifying test setup. The problem is now you have lots of mocks, so your tests are coupled to the implementation. So there is a balance there too. Branches often are a sign an endpoint tries to do too much, but eh sometimes you can't ask your client(s) to change their code just to simplify yours. You have to contend with the contracts as they are: full of bells and whistles, options, bools, nullables = branches galore.
is it same as DDD? also we seem to essentially end up in the microservices world right?
Not entirely. DDD has strategic and tactical patterns that ultimately are adressing coupling and cohesion. Almost everything resolves around them at the core.
Do you have a course on how to implement the feature base architecture u mentioned in the vid?
Not yet!
great content, i'll incorporate this approach into my designs
Is your capability approach in stark contrast to Data Oriented Programming?
Very good advice. Your video makes it obvious that focusing on entities so much is the wrong approach.
Focusing on 'entities' should not be thought of as 'wrong'. Derek is probably trying to direct people to focus on certain aspects of a solution at certain levels of exposure. For example, if defining a public/private API to the business, this is where consumers of this service will rather see endpoints that make sense to them, so more in tune with their 'business needs' or their 'business workflows'. So that's one level. That layer will obviously at some point need to interact with data, and maybe you have a company policy where abstracting access to the underlying data-source needs to be forbidden or tightly controlled, and therefore, engineers would need to build a mechanism to expose 'entities' that represent the underlying source, and this is the fine-grained/micro level. Generally public facing API's should be more 'capability' driven and not needlessly 'data/entity' driven.
Having said all this, when you look at Microsoft D365 OData API, they have ZERO capability level API's, they are all ENTITY based, at least from and endpoint pespective the terms are all 'entities'. So I gues it all depends on the type of thing you're building, and what type of consumer you are focusing on. :-)
@@joaodasilva2175 Good point Joao. My comment was overly simplistic in hindsight. Thanks for the comprehensive reply.
Design pattern is similar. Just couple and cohesive.
Thank you for the the video.
Great video as always
👍
I think the real value of SOLID and the like is simply to help talk around Coupling and Cohesion - especially with junior coders who seem to really struggle with this concept at an enterprise level.
Used as a guide they can be helpful. But if you don't understand the underlying reason they exist it turns into a pissing match. The number of times I get "but doesn't this violate X principle?" is pretty interesting.
@@CodeOpinion Totally. Context matters!
how about simple code example illustrating the point. There is too much spaghetti definitions of coupling and cohesion online, what we need it cohesive and decoupled explanation which we can transfer and apply elsewhere...
I'll give videos in the future with code examples.
my name is codeopinion and i love async messaging a lot
Accurate
I think that still part of SOLID principles only from business perspective.
One class/module responsible for 1 thing
Define one "thing". Everyone seemingly has a different definition. I'd guess most would use the "one reason to change" but think of it technically rather than business requirements, which is how I think of it.
@@CodeOpinion exactly. "Thing" here is could be business department. For example,
Product in marketing department, is different than product in warehouse department.
This is the kind of single responsibility where people often misunderstand.
They put all the product related behaviour in the same class
Long time no see. Nice video
I do proper solid with my C# and have done for many years. I get told …. ‘Nobody likes an uncle bob’ by those that wrote the most awful code I’ve seen in my 25yrs
Super useful. Great video.
Glad it was helpful!
Good stuff.
this is great thanks!
That’s make sense, except for the catalog service. Why would you replicate your catalog to each service using events? Each service would have the entire catalog data…
Why would or wouldn't you? I covered this in a video about event-carried state transfer (th-cam.com/video/IzBEbfSg0uY/w-d-xo.html). But generally yes if it's more reference data from a supporting boundary, then sure. However often times most folks are concerned about replicating data when it's really just for View/UI composition, which is another topic that I need to cover.
It feels like there is a small group of people that understand and practice this. I also wonder if this problem exists in most language ecosystems, traditionally OO languages, or if it is .NET specific.
My experience is it's industry wide on any platform/language/ecosystem
Outstanding
Is this basically microservices?
Microservices implies physical boundaries. Logical boundaries don't have to be physical boundaries
I feel like I completely don't get it after watching the video twice.
The explanation jumps from high level to very high level and doesn't stop on explaining why high cohesion any better than low cohesion and strong coupling any worse than week coupling and what are the traid-offs.
More abstract code often works out as a not needed and redundant layer which is easy to remove and get more imperative, simple code
Low cohesion will lead to high coupling. High coupling ultimately makes things more difficult to change. Check out this video, see if it helps: th-cam.com/video/wRVbHDkOMSM/w-d-xo.html
@@CodeOpinion
"Low cohesion will lead to high coupling. "
=
"If the degree of how well things belong together is low, it will lead to the degree of interdependence between modules being high"
If many modules are interdependent - it means that overall system is hard to change.
So, to reframe this -
if a thing doesn't belong somewhere firmly - it belongs to everywhere and a system becomes a ball of mud (difficult to change)
if a thing belongs to a certain part of the system firmly - you have a limited number of dependencies on it and it is easier to change.
I see that often the dependences are sort of bi-directional if a certain service doesn't bother to wrap the data in it's own abstraction.
e.g. a details of CRM system leak to billing through sales, where sales doesn't change things.
Then as long as billing gets some information, over time it starts to build dependencies on it, first accidentally and then as a lowest friction path.
- it is faster to put data through the whole stack in a single format and schema, rather then create representation on each.
Then it becomes that all parts of the system depend on CRM for example. So the "Ce" is hiddenly very high
Stellar!!!
I mean, you basically just paraphrased "Clean Code" and the core concepts of "Clean Architecture" using fewer words. SOLID itself is just a set of principles that effectively target coupling and cohesion. I don't think any seasoned developer "thinks" about the individual components of SOLID on a day-to-day basis, but instead has uses a mental model that they have built up over the years through both experience and studying/relating to principles and frameworks laid out by smart people before them.
My point is that if you started with coupling and cohesion, which I assume most don't, and you start with the ways to to deal with them, you don't really know why you're doing what you're doing. "I don't think any seasoned developer "thinks" about the individual components of SOLID on a day-to-day basis". I don't think anyone can agree on what "seasoned" is anymore. 😂
@@CodeOpinion I certainly agree with your point... I think that is sort of what I'm getting at. I don't think anybody can really agree with what the word "clean" means anymore. At least most people can have a relatively common understanding of what the words "coupling" and "cohesion" mean, so it makes for a good reference point
I work alone, so: 1) NO unit tests, 2) NO integration tests, 3) code fast, 4) when pain sets in, take a step back and spend some time refactoring