CodingBlocks
72. Clean Architecture – How to Quantify Component Coupling
Joe baits Michael, Michael takes the bait, and Allen lets it happen, as Uncle Bob explains how we can quantify the coupling between our components from his latest book, Clean Architecture.
Tired of reading these show notes on the small screen of your favorite podcast player? Find this episode’s full show notes at https://www.codingblocks.net/episode72.
Sponsors
- FreshBooks.com/Coding – Use code “CODING BLOCKS” in the “How Did You Hear About Us?” section
Survey Says …
During this episode we ask: How often do you shutdown your computer?
#yop-poll-container-49_yp5a52cbbb12a60 { width: 1000; background:#fff; padding:10px; color:#555; overflow:hidden; font-size:12px; } #yop-poll-container-49_yp5a52cbbb12a60 input[type='text'] { margin:0px 0px 5px 0px; padding:2%; width:96%; text-indent:2%; font-size:12px; } .yop-poll-name-49_yp5a52cbbb12a60 { font-weight:bold; background:#327BD6; color:#fff; padding:5px; text-align:center; font-size:12px; } #yop-poll-questions-container-49_yp5a52cbbb12a60 { font-size:14px; margin:5px 0px; } .yop-poll-question-container-49_yp5a52cbbb12a60 { padding: 2px; } .yop-poll-question-49_yp5a52cbbb12a60 { background:#327BD6; color:#fff; margin-bottom: 21px; margin-top: -10px; font-style: italic; text-align: center; width: 100%; padding:5px; } .yop-poll-answers-49_yp5a52cbbb12a60 { } .yop-poll-answers-49_yp5a52cbbb12a60 ul { list-style: none outside none; margin: 0; padding: 0; } .yop-poll-li-answer-49_yp5a52cbbb12a60 { font-style:normal; margin:0px 0px 10px 0px; padding:0px; font-size:12px; margin-bottom:20px; } .yop-poll-li-answer-49_yp5a52cbbb12a60 input { margin:0px; float:none; } .yop-poll-li-answer-49_yp5a52cbbb12a60 label { margin:0px; font-style:normal; font-weight:normal; font-size:12px; float:none; } .yop-poll-results-49_yp5a52cbbb12a60 { font-size: 12px; font-style: italic; font-weight: normal; margin-left: 15px; } .yop-poll-customs-49_yp5a52cbbb12a60 { } .yop-poll-customs-49_yp5a52cbbb12a60 ul { list-style: none outside none; margin: 0; padding: 0; } .yop-poll-li-custom-49_yp5a52cbbb12a60 { padding:0px; margin:0px; font-size:14px; } /* Start CAPTCHA div style*/ #yop-poll-captcha-input-div-49_yp5a52cbbb12a60 { margin-top:5px; } #yop-poll-captcha-helpers-div-49_yp5a52cbbb12a60 { width:30px; float:left; margin-left:5px; height:0px; } #yop-poll-captcha-helpers-div-49_yp5a52cbbb12a60 img { margin-bottom:2px; } #yop-poll-captcha-image-div-49_yp5a52cbbb12a60 { margin-bottom:5px; } #yop_poll_captcha_image_49_yp5a52cbbb12a60 { float:left; } /* End CAPTCHA div style*/ .yop-poll-clear-49_yp5a52cbbb12a60 { clear:both; } #yop-poll-vote-49_yp5a52cbbb12a60 { } /* Start Result bar*/ .yop-poll-results-bar-49_yp5a52cbbb12a60 { background:#f5f5f5; height:10px; } .yop-poll-results-bar-49_yp5a52cbbb12a60 div { background:#555; height:10px; } /* End Result bar*/ /* Start Vote Button*/ #yop-poll-vote-49_yp5a52cbbb12a60 div#yop-poll-vote-49_yp5a52cbbb12a60 button { float:left; } #yop-poll-vote-49_yp5a52cbbb12a60 div#yop-poll-results-49_yp5a52cbbb12a60 { float: right; margin-bottom: 20px; margin-top: -20px; width: auto; } #yop-poll-vote-49_yp5a52cbbb12a60 div#yop-poll-results-49_yp5a52cbbb12a60 a { color:#fff; text-decoration:underline; font-size:12px; } #yop-poll-vote-49_yp5a52cbbb12a60 div#yop-poll-back-49_yp5a52cbbb12a60 a { color:#555; text-decoration:underline; font-size:12px; } #yop-poll-vote-49_yp5a52cbbb12a60 div#yop-poll-archive-49_yp5a52cbbb12a60 a { color:#555; text-decoration:underline; font-size:12px; } #yop-poll-vote-49_yp5a52cbbb12a60 div { float:left; width:100%; } /* End Vote Button*/ /* Start Messages*/ #yop-poll-container-error-49_yp5a52cbbb12a60 { font-size:12px; font-style:italic; color:red; text-transform:lowercase; margin-bottom:20px; text-align:center; } #yop-poll-container-success-49_yp5a52cbbb12a60 { font-size:12px; font-style:italic; color:green; margin-bottom:20px; text-align:center; } /* End Messages*/#yop-poll-container-49_yp5a52cbbb12a60 img { max-width: 1000; } .yop-poll-forms-display{}How often do you shutdown your computer?
- Shutdown daily.
- Every week.
- Every month.
- Only when the updates force me.
- Who shutdowns their computer?
- I don't shutdown often. But when I do, it's because of a BSOD or kernel panic.
- Only right before taking some much needed time off.
News
- Thanks and appreciation to everyone that left us a review:
- iTunes: DevMaterial, BTNDs, Broahm, CSOleson, 保罗.熊 (any guesses), The Real MrNice, bferman, jaramillodeveloper
- Stitcher: Georgio33, Jenna Tulls, Blue Wilson, Daniel Holter, Jimmy Clif
- Podchaser: rmquist
- Allen manages to escape the room – https://www.mindscaperooms.com/
- Get 3 free months of Pluralsight with your Microsoft Dev Essentials account (act quickly, we assume this is a limited time offer).
- Want to help us? Be sure to check out our sponsors as well as our affiliate resources.
Component Coupling
Acyclic Dependencies Principle
- Allow no cycles in the component dependency graph
- “The morning after syndrome” – what you did last night worked when you left but you got back the next day and something broke because code you depended on changed in a breaking way
- This happens when too many developers are working in the same files / project
- Can make it difficult to get a stable build out
- There are two types of solutions that have evolved: The weekly build, and eliminating cycles
Weekly Build
- Developers would work locally for four days, and then on the fifth they integration with everyone else’s code and figure out the problems
- Doesn’t scale – as complexity / size of project grows, this integration takes more time…
- Starts eating into Saturdays until people start saying you should integrate earlier in the week
- Lengthening the build schedule typically ensues
- Integration and testing become more difficult
- Quick feedback cycles becomes increasingly difficult
Remove Dependency Cycles
- Developer / developers begin working on independent releasable components
- When completed, the component gets a release number and other teams work off the released component
- Teams that use the component can decide whether to use a newly released version of the component
- Integrations happen in smaller more manageable increments
- When completed, the component gets a release number and other teams work off the released component
- Removes the need for everyone to come together for a “weekly build”
- For this to work there can be “no cycles”
- Directed Acyclic Graph
- Is this advocating for breaking teams up by the source code, over (for example) feature related teams?
- Cycles make code and releases more fragile, lead to the “morning after syndrome”
- How do we break the cycles?
- Dependency Inversion Principle – Insert strong interfaces for the different components that act as a buffer between compoents and severs those lines
- It goes from “I require the Database Project” from “I define an interface that I require, and it just so happens that the Database Project impliments that interface”
- Enables us to know how to build the application because we understand the dependencies and the order in which they are required to be built.
Top Down Design
- Component structure “jitters” and grows, so it cannot be designed top down
- Component diagrams don’t describe functionality, they are a map to buildability and maintainability of the application
- These diagrams are an important tool for isolating our volatility – push the things that change out to the edges of our application
- What parts of the application are the most volatile? UI? Business rules? Schema?
- So, if the component diagram is fluid, and important – who is responsible for maintaining the diagram?
The Stable Dependencies Principle
- Volatility is necessary and expected
- Components that we expect to change should not be depended on by a component that is difficult to change
- Components that are depended upon, are harder to change…what tools do we have to prevent dependencies? And should we?
- Lets define stability as the amount of work to make a change
- Components that are heavily depended on (say, a logging framework) are very stable, because it’s difficult to change
- Components that rely on many other components are highly volatile (for example, a UI or service layer)
- Hey…we can measure a components stability by counting the number of dependencies in and out!
- Instability = Fan out / (Fan in + Fan out) … Fan Out = Outgoing Dependencies, Fan In = Incoming Dependencies
- The formula gives you a ratio between 0 and 1: 0 is stable, 1 is unstable
- High instability means the component depends on lots of things, but has nothing depending on it
- Low instability means lots depend on it, but it doesn’t depending on much
- So…it’s like golf, lower score is better?
- No, but our component structure should sort unstable components at the top, and filter down to stable components
- But…what do we do about incongruences? (highly stable or unstable components at the middle)
- Dependency Inversion Principle – create an abstract component
The Stable Abstractions Principle
- A component should be as abstract as it is stable
- Code in stable components is the hardest to change, so we shouldn’t put logic that is likely to change in there
- Stable Abstractions Principle states that a stable component should also be abstract so the stability does not prevent it from being extended – unstable components should be concrete since it’s instability allows the concrete code within it to be easily changed
- Stable == interfaces and abstract classes, Instable == concrete
- Dependencies run in the direction of abstraction
Measuring Abstraction
- Abstractness = (Number of classes) / (Number of Abstract Classes or Interfaces)
- Result is a ratio, between 0 and 1
- Now that we have defined ratios for instability and abstractness, we can chart them!
- Ideally our components will be stable and abstract, or volatile and concreate
- Another way of saying this, is that we want instability XOR abtract
- The line between these two conditions is called the “Main Sequence” – and it’s basically the “good” line
- The lower left corner (0 instability, 0 abstract) is the “Zone of Pain”
- The upper right corner (1 instability, 1 abstractness) is the “Zone of Uselessness”
Zone of Pain
- When code is volatile and stable, it’s difficult to change because of downstream dependencies
- Example would be a database schema, often highly volatile, concrete, AND depended on (which defines stability)
- Greater volatility + Concrete classes == Greater Pain
Zone of Uselessness
- When code is highly abstract, but doesn’t have any dependents
- It’s meaningless code, abstract classes with few subclasses, interfaces with few implimentors
- The software that inhabit this region are “detritus”
Distance from the main sequence
- What’s the main sequence?
- The line from 1,0 to 0,1
(D)istance = | (A)bstractness + (I)nstability – 1 |
- The line from 1,0 to 0,1
- Values between 0 and 1…0 is on the main sequence and 1 is as far away as possible
- So, how good is our code? What’s your distance from the main sequence?
- It’s like golf, the lower the better
- We can look at the standard deviation to compare the quality of components – what are the outliers?
- Setting a threshold for identifying components to look further into is a way of keeping things in line
- Can plot these changes over time for components
In closing …
_”These metrics are imperfect, at best, …”_ – Robert C. Martin
Resources We Like
- Clean Architecture by Robert C. Martin (Amazon)
- NDepend – https://www.ndepend.com
- SonarQube – https://www.sonarqube.org
Tip of the Week
- Learn how to build intelligence into your next application using Microsoft’s AI platform. – https://aischool.microsoft.com/
- Create types from your data using quicktype. – https://app.quicktype.io/
- Gamify your life and make those good habits the norm. – https://habitica.com/