Author: Robert C. Martin (Uncle Bob)
Contents
- 1 PART 1. Introduction
- 2 PART 2. Starting with the Bricks: Programming Paradigms
- 3 PART 3. Design Principles
- 4 PART 4. Component Principles
- 5 PART 5. Architecture
- 5.1 Ch15. What Is Architecture?
- 5.2 Ch16. Independence
- 5.3 Ch17. Boundaries: Drawing Lines
- 5.4 Ch18. Boundary Anatomy
- 5.5 Ch19. Policy and Level
- 5.6 Ch20. Business Rules
- 5.7 Ch21. Screaming Architecture
- 5.8 Ch22. The Clean Architecture
- 5.9 Ch23. Presenters and Humble Objects
- 5.10 Ch24. Partial Boundaries
- 5.11 Ch25. Layers and Boundaries
- 5.12 Ch26. The Main Component
- 5.13 Ch27. Service: Great and Smal
- 5.14 Ch28. The Test Boundary
- 5.15 Ch29. Clean Embedded Architecture
- 6 PART 6. Details
1.1 Ch1. What is Design and Architecture? #
- The Goal?
- The Signature of a Mess
- Conclusion:
To take software architecture seriously, you need to know what good software architecture is.
To build a system with a design and an architecture that minimize effort and maximize productivity, you need to know which attributes of system architecture lead to that end.
clean architectures and designs that software developers can build systems that will have long profitable lifetimes.
1.2 Ch2. A Tale of Two Values #
Every software system provides two different values to the stakeholders: behavior and structure
- Behavior
- Architecture
- The Greater Value
- Eisenhower's Matrix
The mistake that business managers and developers often make is to elevate items in position 3 to position 1.
In other words, they fail to separate those features that are urgent but not important from those features that truly are urgent and important.
This failure then leads to ignoring the important architecture of the system in favor of the unimportant features of the system.
It is the responsibility of the software development team (not business managers) to assert the importance of architecure over the urgency of features.
- Fight For the Architecture
2.1 Ch3. Paradigm Overview #
The three paradigms: structured programming, oop, functional programming
- Structured Programming
- Object-Oriented Programming
- Functional Programming
- Food for Thought
- Conclusion
2.2 Ch4. Structured Programming #
Edsger Wybe Dijkstra
- Proof
- A Harmful Proclamation
- Functional Decomposition
- No Formal Proofs
- Science to the Rescue
- Tests
- Conclusion
2.3 Ch5. Object-Oriented Programming #
- Encapsulation?
- Inheritance?
- Polymorphism?
- The Power of Polymorphism
- Dependency Inversion
[HL1] --> <I.f()> <== [ML1.f()] --> : control ==> : inheritence
Module HL1 calls f() function in module ML1.
It calls this function through an interface I.f().
Note that the source code dependency between ML1 and the interface I points in the opposite direction compared to the flow of control.
This is called 'dependency inversion'
The fact that OO languages provide safe and convenient polymorphism means that any source code dependency, no matter where it is, can be inverted.
That si the power that OO provides. That's what OO is really all about.
- Conclusion
2.4 Ch6. Functional Programming #
This paradigm is strongly based on the lambda-calculus by Alonzo Church in the 1930s.
- Squares of Integers
- Immutability and Architecture
- Segregation of Mutability
Architects would be wise to push as much processing as possible into the immutable components, and to drive as much code as possible out of those components that must allow mutation.
- Event Sourcing
- Conclusion
3 PART 3. Design Principles #
- SRP: The Single Responsibililty Principle
- OCP: The Open-Closed Principle
- LSP: The Liskov Substitution Principle
- ISP: The Inteface Segregation Principle
- DIP: The Dependency Inversion Principle
3.1 Ch7. SRP: The Single Responsibility Principle #
Historically, the SRP has been described this way:
A module should have one, and only one, reason to change.This can be rephrased:
A module should be responsible to one, and only one, actor.
The symptoms of violating this:
- Symptom 1: Accidental Duplication
separate the code that different actors depend on.
- Symptom 2: Merges
- Solutions
- Conclution
3.2 Ch8. OCP: The Open-Closed Principle #
A software artifact should be open for extension but closed for modification.
The goal of OCP is to make the system easy to extend without incurring a high impact of change.
This goal is accomplished by partitioning the system into components and arranging those components into a dependency hierarchy that protects higher-level components from changes in lower-level components.
3.3 Ch9. LSP: The Liskov Substitution Princicple #
The LSP can, and should, be extended to the level of architecture.
A simple violation of substitutablity, can cause a system's architecture to be polluted with a significant amount of extra mechanisms.
3.4 Ch10. ISP: The Interface Segregation Principle #
User1 --> +-------------------- User2 --> | OPS +op1 +op2 +op3 User3 --> +--------------------
A change to the source code of op2 in OPS will force User1 to be recompiled and redeployed, even though nothing that it cared about has actually changed.
- segregated operations
User1 --> <I>U1Ops+op1 <==+ +-------------------- User2 --> <I>U2Ops+op2 <==+== | OPS +op1 +op2 +op3 User3 --> <I>U3Ops+op3 <==+ +--------------------
Depending on something that carries baggage that you don't need can cause you troubles that you didn't expect.
3.5 Ch11. DIP: The Dependency Inversion Principle #
- Stable Abstractions
Don't refer to volatile concrete classes.
Don't derive fro volatile concrete classes.
Don't override concrete functions.
Never mention the name of anything concrete and volatile.
All source code dependencies cross the curved line pointing in the same direction, toward the abstract side.
Note that the flow of control crosses the curved line in the opposite direction of the source code dependencies. The source code dependencies are inverted against the flow of control.
4.2 Ch13. Component Cohension #
- REP: The Reuse/Release Equivalence Principle
- CCP: The Common Closure Principle
- CRP: The Common Reuse Principle
4.3 Ch14. Component Coupling #
Allow no cycles in the component dependency graph.
- Breaking the Cycle
- The Stable Dependencies Principle
X is a stable component
ComponentA ---> +------------+ ComponentB ---> | ComponentX | ComponentC ---> +------------+
Y is a very unstable component
+------------+ ---> ComponentA | ComponentY | ---> ComponentB +------------+ ---> ComponentC
Stability Metrics
Fan-in: Incoming dependencies. Fan-out: Outgoing dependencies. I: Instability = FanOut / (FanIn + FanOut)
- The Stable Abstractions Principle
A:Abstractness = Na / Nc Nc: The number of classes in the component. Na: The number of abstract classes and interfaces in the component
5.1 Ch15. What Is Architecture? #
The architecture of a software system is the shape given to that system by those who build it.
The form of that shape is in the division of that system into components, the arrangement of those components, and the ways in which those components communicate with each other.
The Purpose of that shape is to facilitate the development, deployment, operation, and maintenance of the software system contained within it.
The strategy behind that facilitation is to leave as many options open as possible, for as long as possible.
Good architects carefully separate details from policy, and then decouple the policy from the details so thoroughly that the policy has no knowledge of the details and does not depend on the details in any way.
Good architects design the policy so that decisions about the details can be delayed and deferred for as long as possible.
5.2 Ch16. Independence #
a good architecture must support:
* The use cases and operation of the system. * The maintenance of the system. * The development of the system. * The deployment of the system.
- Use Cases
- Operation
- Development
- Depolyment
- Leaving Options Open
- Decoupling Layers
- Decoupling Use Cases
- Decoupling Mode
- Independent Develop-Ability
- Independent Deployability
- Duplication
- Decoupling Modes (Again)
My preference is to push the decoupling to the point where a service could be formed.
Initially the components are separated at the source code level.
If deployment or development issues arise, driving some of the decoupling to a deploymen t level may be sufficient.
As the development, deployment, and operational issues increase, I carefully choose shich deployable units to turn into services, and gradually shift the system in that direction.
A good architecture will allow a system to be born as a monolith, deployed in a single file, but then to grow into a set of independently deployable units, and then all the way to independent service and /or micro-services.
Later, as things change, ti should allow for reversing that progression and sliding all the way back down into a monolith.
A good architecture protects the majority of the source code from those changes.
5.6 Ch20. Business Rules #
Business rules are rules or procedures that make or save the business money.
Critical Business Rules
Critical Business Data
- Entities
- Use Cases
The business rules should be the most independent and reusable code in the system.
5.7 Ch21. Screaming Architecture #
- The theme of an architecture
5.8 Ch22. The Clean Architecture #
Each of these architectures produces systems that have the following chracteristics:
- Independent of frameworkds - Testable - Independent of the UI - Independent of the database - Independent of any external agency
Source code dependencies must point only inward, toward higher-level policies.
5.9 Ch23. Presenters and Humble Objects #
- The Humble Object Pattern
- Presenters and Views
The Presenter is the testable object. Its job is to accept data from the application and format it for presentation so that the View can simply move it to the screen.
- Database Gateways
- Data Mappers
- Service Listeners
5.10 Ch24. Partial Boundaries #
Full-fledged architectural boundaries are expensive.
- Skip the Last Step
- One-dimensional Boundaries
- Facades
6 PART 6. Details #
Ch30. The Database Is a Detail
-
-
-
-
-
Ch31. The Web Is a Detail
-
-
-
Ch32. Frameworks Are Details
-
-
-
Ch33. Case Study: Video Sales
-
-
-
Ch34. The Missing Chapter
- Package By Layer
- Package By Feature
- Ports and Adapters
- Package By Component