5

I'm reading the book "Clean Architecture" from Robert C. Martin and there is something that has been puzzling me in most parts of the book.

When the author introduces the term "component" he defines it as "the unit of deployment", they "always retain the ability to be independently deployable and, therefore, independently developable". As an example, they are Java .jar files, independent dlls, etc. They can be dynamically or statically linked or whatever makes sense in the programming language that we're using, but apparently what he is referring to what we could generally call libraries.

However, from my point of view, most of the techniques that are presented in the next chapters should not require that components are independent units of deployment. The explanations about decoupling, stability, dependencies, policies vs details, etc. can also be applied to components that are developed and deployed together.

For example, regarding the dependency rule: if I have a single repository project with a single versioning/release process, it still makes perfect sense to apply the rule and separate classes that access the database from use cases and domain entities.

I know that he also uses the term "modules" for the internal organization of components, but he only mention to apply SOLID principles to them. SOLID principles are more general and doesn't speak about domain, use cases, etc.

As I see it, having dozens of packages with their own versioning and release separate processes can easily become a nightmare with almost no benefits for a middle sized project (let's say some hundreds of files).

The possibility to keep components together in a single deployment unit is only very briefly mentioned in the chapter "partial boundaries", but it's presented almost as something unusual, rather than the default choice. Interestingly, in the chapter "the missing chapter", written by a different author, he also disagrees with Robert's definition of component.

I would like to know what the practical experience of people that have tried to implement clean architectures is with this "component == unit of deployment" idea. Also, I would like to know if there exist popular/well known more pragmatical proposals regarding this.

7
  • Martin's view on how you deploy the application (single executable, bunch of local components, distributed components/services) is that this is, in a way, an orthogonal concern with respect to design/architecture (though deployment considerations could constrain the design). The effort invested into decoupling and defining logical boundaries enables you to physically componentize, but how you actually go about it is up to you (or the dev team) to decide based on the needs of your application. The book doesn't say you have to do it. (1/2) Commented Apr 9 at 10:31
  • The principles he lists for the component design in the chapters you mentioned are component-oriented versions of some of the design principles from the earlier chapters, though those were cast mostly in terms of classes (modules, more generally). So you're right, there is a common, more general undercurrent of ideas that underlies both. It's just that these particular chapters are focused on componentization and deployment. (2/2) Commented Apr 9 at 10:32
  • I don't think "unit of deployment" sounds like a useful concept. The same code could potentially be deployed in a wide variety of ways, everything from source code fragments to a single monolithic exe-file. So does the "component" depend on the deployment method? This seem more prone to confuse than to clarify.
    – JonasH
    Commented Apr 9 at 13:50
  • @FilipMilovanović: sounds like a good answer
    – Doc Brown
    Commented Apr 9 at 14:44
  • Why bother decoupling things if you're going to then tightly couple them via the release process anyway? If you know you'll never be able to separate your DB layer from your domain layer, and even the tiniest hotfix in one requires redeploying both, you're losing a very significant advantage of maintaining a boundary between them in the first place. Commented Apr 9 at 18:16

4 Answers 4

5

etc. can also be applied to components that are developed and deployed together.

Sure. You can deploy the whole app together. But a component is the smallest thing you could deploy a new version of on it's own. You don't have to plan to do that to make it worth coding so it's possible to do that.

Components always make me think of old stereo equipment. You had things like an equalizer component that came in it's own box and was wired up to the rest of the system. You could unwire this thing from it's current system and hook it up to another system.

In programming terms that is what we mean by code reuse. Cohesion tells us the equalizers features should be about equalizing. Low coupling says to limit the wires that come out of the thing.

A deployment unit is only larger than that because you don't want to manage the deployment and versioning that closely. So maybe you want to deploy the equalizer and amplifier together. That's fine so long as the cost of redeploying the unchanged things is within what you're willing to pay. This is a balancing act.

The key lesson here is just because a chunk of code has been designed as a tiny component that could be deployed independently doesn't mean it's been versioned that way. The deployment plan could call for sending out many independent chunks of code together when one of them is updated.

Rather then telling you how large a module can be Martin is telling us how small they must be. Small enough that you can break off what needs deploying. They certainly can be smaller than that.

There's also the fact that when Martin talks about modules he's carefully avoiding calling them classes because some languages don't even have classes. He's trying to keep it generic.

But understand, modules were a thing long before Martin started talking about them.

6
  • This makes much sense to me. However, I still have the impression that Robert assumes that "component == unit of deployment" is the way to go. Actually, he calls "skipping the last step" to not separating the components in the release process, and he says that you are stablishing a "partial boundary", not a "full boundary".
    – naggety
    Commented Apr 10 at 6:10
  • I mean, it seems like many people has considered, as I do, that this definition of components doesn't make much sense, but the principles and ideas that he present for components are good even with a different definition of component.
    – naggety
    Commented Apr 10 at 6:15
  • @naggety do you have a particular definition in mind? What about this one? Commented Apr 10 at 12:51
  • Yes, I like that one and, in my opinion, the principles about dependencies between components can be applied with this definition as well.
    – naggety
    Commented Apr 11 at 6:13
  • @naggerty I don't find that Martins definition conflicts with this one. Rather, Martin leans heavily on what he must get out of a component, deliverability. Where as this definition tells you what's needed to do that. Again Martin focuses more on the abstract need rather than any particular how. It's annoying but it's why his stuff lasts. Commented Apr 11 at 13:28
0

When the author introduces the term "component" he defines it as "the unit of deployment"

Unfortunately "component" is one of those generic words in software that can mean a lot of different things to different speakers.

There are certainly many casual usages of the word "component" that don't imply independent deployment.

And in any given design, exactly what is or isn't a component is often a design decision in itself.

That is, how a software design is to be thought of as individual parts (so as to be convenient for humans, including the original designer, to understand), is one of the questions which are answered in the process of designing a particular piece of software.

The answer varies between one piece of software and another, and really it varies between designers too - since two different designers may have different opinions or habits, or even different cognitive facilities which make it genuinely easier or harder for them to think about the software design in certain ways.

I would like to know what the practical experience of people that have tried to implement clean architectures is with this "component == unit of deployment" idea.

I can't talk about following Martin's "clean" architecture idea, but when it comes to reporting, it's very common to deploy and alter reports individually (and therefore as "components" within a wider reporting suite) rather than always deploying everything as a set.

It's also quite common for a business to run multiple front-end applications, developed and overseen by different teams, but which share a server-side storage subsystem and maybe have some integration of data flow. Updates to the applications are therefore usually deployable independently, but because they have some common concerns they still form components of a wider system.

I don't really think Martin is the originator of these ideas, or that he is describing things that most experienced practitioners don't already do by default in many contexts.

Generally speaking, and although I'm no expert on his writings, my impression of Bob Martin is that he's a pundit who is good at trying to talk about what practitioners already do and know tacitly, but he often talks about things abstractly rather than in the context of many supporting case studies.

Expert practioners (i.e. people who have roughly the same skill and experience as Martin) can quickly relate his words to their own work, because as experts they've seen a lot of cases, so they can make sense of what he says and are content to nod along. Martin's writings might be useful to a community of experts in the sense that it provokes discussion amongst them, or strengthens and gives words to thoughts and practices that were otherwise weaker and less speakable.

But for junior and inexperienced practitioners, they can end up trying to make sense of his words alone, and there's just far too much ambiguity in them to be useful as a free-standing teaching aid or as guidance that can be applied to a concrete situation.

It's a bit like the Bible in that respect - you don't become a priest, and certainly not an archbishop or a pope (i.e. an expert in the political stewardship of a church), just because you have a copy of the book.

-1

If we look at the end of chapter 12, we see that Bob has a broad and maybe old fashioned definition of "deployable"

Today we routinely ship .jar files or DLLs or shared libraries as plugins to existing applications. If you want to create a mod to Minecraft, for example, you simply include your custom .jar files in a certain folder. If you want to plug Resharper into Visual Studio, you simply include the appropriate DLLs.

With most enterprise software "Independently deployable" might be a microservice api with hundreds of dlls. You would never think of replacing out one of them without redeploying the whole thing. Even though technically you could.

The "unit of composition" depends on the language you use, but it's never unclear. The key thing is not so much whether you actually independently deploy your units, but whether the language features support their use as components. ie referencing dependencies, hiding implementations etc.

Practical advice unfortunately is going to end up being a massive list and not make for good answers. You should ask again specifying the details of your actual code.

-2

However, from my point of view, most of the techniques that are presented in the next chapters should not require that components are independent units of deployment. The explanations about decoupling, stability, dependencies, policies vs details, etc. can also be applied to components that are developed and deployed together.

I don't think the book ever suggested that it would only provide guidance on things that only apply to separated components. "Next chapters" are not always built on top of the previous one, sometimes it's just a list of individually valuable pieces of advice.

For example, regarding the dependency rule: if I have a single repository project with a single versioning/release process, it still makes perfect sense to apply the rule and separate classes that access the database from use cases and domain entities.

When you get into the details of the clean coding guideline internal to a single application's codebase, and the way e.g. microservice ecosystems maintain their loose coupling; you're going to notice that these things are spritually similar if not identical. The differences between them are ones of language and format, but the goals are largely identical: keep things change-friendly, don't couple stuff tightly.

I know that he also uses the term "modules" for the internal organization of components, but he only mention to apply SOLID principles to them. SOLID principles are more general and doesn't speak about domain, use cases, etc.

"Clean architecture" is not an architecture in the sense that TDD and DDD are. To use an analogy, we can discuss how clean your house is regardless of whether you live in a flat or a bungalow. Clean coding guidelines apply to all manner of architectures and it would be a distraction for clean coding advice to tailor its advice to only apply to specific architectures.

As I see it, having dozens of packages with their own versioning and release separate processes can easily become a nightmare with almost no benefits for a middle sized project (let's say some hundreds of files).

Every approach has a bad use case. Every solution needs to be justified within the context you seek to use it. Because I like analogies, you don't need to sterilize your equipment in the same way that a surgeon's scalpel is sterilized, if all you're going to be doing is putting peanut butter on a sandwich. A McLaren F1 car is an amazing state-of-the-art vehicle but it's not going to be a great help if I'm going to do groceries with it.

I preach a lot of clean coding guidelines in the dev team I manage; but I don't follow these guidelines when I'm slapping together a quick console app that helps me generate a file and which I'm not going to use for more than a day or two, nor do I expect this of my developers. Cleanliness is relative to the lifetime (and importance) of the code in question.

The possibility to keep components together in a single deployment unit is only very briefly mentioned in the chapter "partial boundaries", but it's presented almost as something unusual, rather than the default choice. Interestingly, in the chapter "the missing chapter", written by a different author, he also disagrees with Robert's definition of component.

Definitions of abstract concepts are subjective to the author of that definition. For example, I use "strategy" in a slightly different manner than the strategy pattern describes. I stand by my own definition for my use cases, but that does not invalidate the definition of the strategy pattern. It just means that I think about it slightly differently than the author of the strategy pattern does.

I would like to know what the practical experience of people that have tried to implement clean architectures is with this "component == unit of deployment" idea.

You're just asking about "word == another word". If you ask 100 people what a component is, you're going to get 100 different answers.

I would suggest that you don't try to build your understanding off of specific terminology and the assumption that these definitions are deterministically applicable and universally agreed upon. Instead, I suggest you look beyond the semantics for the spirit of what is being (or trying to be) conveyed by these semantics.

The purpose of clean architecture is to keep your codebase change-friendly. That is the core of the Clean Architecture book you're reading. Everything else is either a concrete example or an elaboration to help clarify that core goal.

2
  • Next chapters talks all the time about "components" and their relationships. So yes, next chapters are built on top of the previous one.
    – naggety
    Commented Apr 10 at 6:12
  • @naggety "Next chapters are not always built on top of the previous one" is not synonymous with "Next chapters will never ever build on top of a previous one". What I'm pointing out is that some chapters build upwards, and some chapters build sideways.
    – Flater
    Commented Apr 10 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.