Clean Architecture: A Craftsman's Guide to Software Structure and Design
Rate it:
Open Preview
53%
Flag icon
There is some truth to this belief—but only some. First, history has shown that large enterprise systems can be built from monoliths and component-based systems as well as service-based systems. Thus services are not the only option for building scalable systems.
53%
Flag icon
Second, the decoupling fallacy means that services cannot always be independently developed, deployed, and operated. To the extent that they are coupled by data or behavior, the development, deployment, and operation must be coordinated.
53%
Flag icon
This is the problem with cross-cutting concerns. Every software system must face this problem, whether service oriented or not. Functional decompositions, of the kind depicted in the service diagram in Figure 27.1, are very vulnerable to new features that cut across all those functional behaviors.
53%
Flag icon
These two components override the abstract base classes in the original components using a pattern such as Template Method or Strategy.
53%
Flag icon
Note again that the two new components, Rides and Kittens, follow the Dependency Rule.
54%
Flag icon
Thus the Kitty feature is decoupled, and independently developable and deployable.
54%
Flag icon
Each service has its own internal component design, enabling new features to be added as new derivative classes
54%
Flag icon
What we have learned is that architectural boundaries do not fall between services. Rather, those boundaries run through the services, dividing them into components.
54%
Flag icon
As useful as services are to the scalability and develop-ability of a system, they are not, in and of themselves, architecturally significant elements.
54%
Flag icon
The architecture of a system is defined by the boundaries drawn within that system, and by the dependencies that cross those boundaries. That architecture is not defined by the physical mechanisms by which elements communicate and execute.
55%
Flag icon
The goal is to decouple the structure of the tests from the structure of the application.
55%
Flag icon
Structural coupling is one of the strongest, and most insidious, forms of test coupling.
55%
Flag icon
Imagine a test suite that has a test class for every production class, and a set of test methods for every production method. Such a test suite is deeply coupled to the structure of the application.
55%
Flag icon
When one of those production methods or classes changes, a large number of tests must change as well. Consequently, the tests are fragile, a...
This highlight has been truncated due to consecutive passage length restrictions.
55%
Flag icon
The role of the testing API is to hide the structure of the application from the tests. This allows the production code to be refactored and evolved in ways that don’t affect the tests. It also allows the tests to be refactor...
This highlight has been truncated due to consecutive passage length restrictions.
55%
Flag icon
This separation of evolution is necessary because as time passes, the tests tend to become increasing...
This highlight has been truncated due to consecutive passage length restrictions.
55%
Flag icon
In contrast, the production code tends to become increasingly more abstract and general. Strong structural coupling prevents—or at least impedes—this necessary evolution, and prevents the production co...
This highlight has been truncated due to consecutive passage length restrictions.
55%
Flag icon
Tests are not outside the system; rather, they are parts of the system that must be well designed if they are to provide the desired benefits of stability and regression.
55%
Flag icon
Tests that are not designed as part of the system tend to be fragile and difficult to maintain. Such tests often wind up on the maintenance room floor—discarded because they are too difficult to maintain.
56%
Flag icon
Programmers, embedded or not, who just concern themselves with getting their app to work are doing their products and employers a disservice.
56%
Flag icon
There is much more to programming than just getting an app to work.
57%
Flag icon
Yes, embedded is special. Embedded engineers are special. But embedded development is not so special that the principles in this book are not applicable to embedded systems.
59%
Flag icon
Being able to test only in the target hardware is not good for your product’s long-term health. A clean embedded architecture is good for your product’s long-term health.
60%
Flag icon
From an architectural point of view, the database is a non-entity—it is a detail that does not rise to the level of an architectural element.
60%
Flag icon
Its relationship to the architecture of a software system is rather like the relationship of a doorknob to the architecture of your home.
60%
Flag icon
the database is not the data model.
60%
Flag icon
The database is piece of software. The database is a utility that provides access to the data.
60%
Flag icon
From the architecture’s point of view, that utility is irrelevant because it’s a low-level detail—a mechanism. And a good architect does not allow low-level me...
This highlight has been truncated due to consecutive passage length restrictions.
60%
Flag icon
The relational model is elegant, disciplined, and robust. It is an excellent data storage and access technology.
60%
Flag icon
But no matter how brilliant, useful, and mathematically sound a technology it is, it is still just a technology. And that means it’s a detail.
60%
Flag icon
While relational tables may be convenient for certain forms of data access, there is nothing architecturally significant about arrang...
This highlight has been truncated due to consecutive passage length restrictions.
61%
Flag icon
It originated from the highly effective marketing campaigns employed by the database vendors at the time. They had managed to convince high-level executives that their corporate “data assets” needed protection, and that the database systems they offered were the ideal means of providing that protection.
61%
Flag icon
We see the same kind of marketing campaigns today. The word “enterprise” and the notion of “Service-Oriented Architecture” have much more to do with marketing than with reality.
61%
Flag icon
The organizational structure of data, the data model, is architecturally significant.
61%
Flag icon
The technologies and systems that move data on and off a rotating magnetic surface are not. Relational database systems that force the data to be organized into tables and accessed with SQL have much more to do with the latter than with the former. The data is significant. The database is a detail.
61%
Flag icon
Actually the web didn’t change anything. Or, at least, it shouldn’t have. The web is just the latest in a series of oscillations that our industry has gone through since the 1960s. These oscillations move back and forth between putting all the computer power in central servers and putting all computer power out at the terminals.
61%
Flag icon
Of course, it would be incorrect to think that those oscillations started with the web. Before the web, there was client–server architecture. Before that, there were central minicomputers with arrays of dumb terminals. Before that, there were mainframes with smart green-screen terminals (that were very much analogous to modern-day browsers). Before that, there were computer rooms and punched cards …
62%
Flag icon
The upshot is simply this: The GUI is a detail. The web is a GUI. So the web is a detail.
62%
Flag icon
FRAMEWORKS ARE DETAILS
63%
Flag icon
Don’t marry the framework!
63%
Flag icon
If the framework wants you to derive your business objects from its base classes, say no! Derive proxies instead, and keep those proxies in components that are plugins to your business rules.
63%
Flag icon
Don’t let frameworks into your core code. Instead, integrate them into components that plug in to your core code, following the Dependency Rule.
63%
Flag icon
When faced with a framework, try not to marry it right away. See if there aren’t ways to date it for a while before you take the plunge.
64%
Flag icon
Now that we know the actors and use cases, we can create a preliminary component architecture
64%
Flag icon
views and presenters will be coded into abstract classes within those components, and that the inheriting components will contain view and presenter classes that will inherit from those abstract classes.
64%
Flag icon
Notice that the arrows do not all flow from the right to the left. In fact, most of them point from left to right. This is because the architecture is following the Dependency Rule.
64%
Flag icon
All dependencies cross the boundary lines in one direction, and they always point toward the components containing the higher-level policy.
64%
Flag icon
Also notice that the using relationships (open arrows) point with the flow of control, and that the inheritance relationships (closed arrows) point against the flow of control. This depicts our use of the Open–Closed Principle to make sure that the dependencies flow in the right direction, and that c...
This highlight has been truncated due to consecutive passage length restrictions.
64%
Flag icon
The architecture diagram in Figure 33.2 includes two dimensions of separation.
64%
Flag icon
The first is the separation of actors based on the Single Responsibility Principle; the second is the Dependency Rule.