Podcast: Play in new window | Download
Subscribe: Apple Podcasts | Spotify | TuneIn | RSS
Joe drinks too much coffee, Allen spits his coffee out, and Michael feels vindicated as the discussions about Robert C. Martin’s latest book, Clean Architecture, continues.
Reading these show notes via your podcast player? Want to read them on a bigger screen? You can find this episode’s full show notes in all their glory at https://www.codingblocks.net/episode73.
Sponsors
- FreshBooks.com/Coding – Use code “CODING BLOCKS” in the “How Did You Hear About Us?” section
Survey Says …
This episode we ask: Is it OK for a site to open links in a new tab/window for you?
News
- We take a moment to say thanks to those that left us a review:
- iTunes: mbaumbach, Rawldo, JeremyRose22, Cplyoung, Arbinger, DanMarshall909, AndrewScottVT, __gopher__, feargalwalsh
- Stitcher: mbaumbach, Madjac, GotSkillsNowGimmieJob
- TeamCity now comes with 100 configurations instead of just 20. For FREE! (JetBrains Blog)
- Make your travel plans now to catch Joe presenting at the next Orlando .NET meetup!
- Help us out by checking out our sponsors and affiliate resources.
What is Architecture?
- Makes us think of weighty decisions and deep technical prowess
- Even though it sounds like an architect is Gandalf the Gray, it’s really still a programmer
- They still program but also focus on guiding the rest of the team towards better productivity
- They must continue to program so they can experience the problems / pains the rest of the developers feel
- Purpose of the shape of software is to facilitate the development, deployment, operation and maintenance of the software itself
- The strategy should be to leave as many options open as possible, for as long as possible
- Software architecture is NOT about whether the software works – seems counter intuitive…but….even bad architecture can work
- There are few, if any behavioral options that architecture can leave open
- Architecture’s main goal is to support the life cycle of the system
Development
- Hard to develop software = unhealthy lifetime
- Typically small teams don’t need to think about architecture because they can work well without drawing lines
- This is probably why most software systems aren’t architected well – they start out small and then teams / software grow
- Systems developed by multiple decently sized teams will need some sort of dividing lines / splitting up components
- Typically this would end up with the same number of teams = same number of components
- Probably not best for the long term deployment / architecture
- Typically this would end up with the same number of teams = same number of components
Deployment
- Software systems should be deployable
- Software that is more difficult/expensive to deploy is less useful
- Good architecture means that software can EASILY be deployed with ONE action
- This is seldom a consideration during the initial phases of a new project
- Microservices were called to the floor here – typically when microservices are decided upon, folks aren’t thinking about the pain points with deployments, failures, etc
Operation
- When talking about operation, he’s talking about how efficiently the software runs
- Typically this isn’t taken into too much consideration because it’s cheaper to throw hardware at a problem than throw more resources at development, deployment and maintenance
- However, a good architecture communicates the operational needs of the system
- The operational needs will be apparent to the developer
Maintenance
- Maintenance is the most costly aspect of software
- Primary reasons: spelunking and risk
- Exploring to find the best place and best strategy to introduce a change
- A well thought out architecture greatly reduces these costs / risks
Keeping Options Open
- Software has two types of value: behavior and structure
- The structure is what makes it _soft_
- The key to keeping software _soft_ is by leaving as many options open for as long possible.
- Options that can be left open are those details that don’t matter. Until they do.
- All software can be broken down into two themes: policy and details.
- Its the policy that is the true value of the system.
- The goal of the architect is to shape the system so that the policy is the most important aspect while making the details irrelevant to the policy
- The longer you wait to make these decisions, the more informed you’ll be by the time you _need_ to make that decision
- _A good architect maximizes the number of decisions not made._
- The last responsible moment: https://blog.codinghorror.com/the-last-responsible-moment/
Wrapping it up
- Good architects separate the policy from the details so throughly that the policy has no knowledge nor dependency on the details
Independence
- Recap, architect must support use cases/operation, maintenance, development, deployment of the system
Use cases
- Architecture must support the _intent_ of the system
- The most important thing architecture can do is to expose that behavior so the INTENT of the system is visible at the architectural level
- A shopping cart app with good architecture will look like a shopping cart app
- Use cases should be plainly visible
- “Screaming Architecture” – The architecture should emphasize it’s purpose, not the framework
- Frameworks are an implementation detail!
Operation
- Sometimes it can be tempting to rearrange the architecture of a system around processing requriements
- For example: A high throughput system may need to take great advantage of independent scaling and parralelism
- Ideally your system will be agnostic to it’s implementation details though, as these requirements could change over time
* It’s better that your architecture primarily reflect it’s purpose
* An architecture that properly isolates its components will be easier to change over time as the operational needs change
Development
- Conway’s law (Wikipedia)
- “Any organization that designs a system will inevitably produce a design whose structure is a copy of the organization’s communication structure.”
- Goal is to partition the system into isolated, components…so should we arrange our teams that way?
- A system developed by many teams and concerns must facilitate independent actions
Deployment
- The goal is immediate deployment
- Not a hodgepodge of scripts and ftp – this is achieved by proper partitioning and isolation
- Was there life before Docker?
Leaving Options Open
- Good architecture balances these concerns
- Sounds easy. But the reality is that is hard.
- Why? Here are the things we don’t know up front:
- All of the use cases
- The operational constraints
- The team structure
- Deployment requirements
- Why? Here are the things we don’t know up front:
- Worse, those things _will_ change
- We’re trying to hit a moving target
Decoupling Layers
- The goal is to support all necessary use cases…even the ones we don’t know about yet
- The architect DOES know about the basic intent of the system – apply the Single Responsibility Principle and the Common Closure Principle to isolate functionality, and promote composability
- The database, query, and schema are technical details that have nothing to do with the business rules or UI – they change at different rates so keep them in separate layers
- Good starting point: UI, App / Biz Rules, Core Biz Rules, Database
Decoupling Use Cases
- Use cases are narrow vertical slices that cut through horizontal layers of the system
- For example: The uses cases for adding an order and deleting an order will likely change for different reasons, at different rates – so why tie them together?
- Try to keep use cases separated, for example – having a separate UI to delete orders and a separate one to add orders
- But…what about UX? If it’s common for the user to delete orders and add orders at the same time – why punish them?
- Great podcast from Eat Sleep Code (Pocket Casts), with Sara Ford (Twitter) talking about how software developers tend to design systems in such a way that it’s easier to work on…but not necessarily easier to use!
- The benefit is that decoupling the features makes them easier to add and change
Decoupling Mode
- Having your components divided up into layers makes it easier to scale those layers separately
- You can add more back-end servers, or more front-end servers as necessary
- Decoupling what we did for use cases is now aiding our operations!
- Good architecture is about leaving your options open
Independent Developability and Deployability
- Horizontal layers make it easier for teams to be organized based on what makes sense for the biz (a la feature, layer, etc)
- Horizontal layers buy you some deployment flexibilty
Duplication
- Architects often fall into the trap of the “fear of duplication”
- Duplication is generally a bad thing
- And when there is duplication, we are honor-bound to reduce it
- But there are different kinds of duplication
- True duplication – every change to one instance requires the same change to the other instances
- False or accidental duplication – seems to be duplicated, but changes at different rates and/or for different reasons
- When separating use cases, there’s a temptation to couple use cases that have similar screens, algorithms, or database queries/schemas
- Resist the urge to eliminate this duplication until you know that it is true.
- But don’t get lazy either and simply pass a entire row from the DB straight to the UI. View models are cheap/easy and decouple these layers.
Decoupling Mode (revisited)
- We can decouple at the many levels: source code, deployment, and execution level.
- Source control: Packages (changes in one, don’t force a recompile)
- Deployment level: Similar, but independently deployed
- Service level: Separated by network, completely independent deployment
- Which is best? Difficult to know during the early phases of a project.
- Microservices are (were?) all the rave but service level decoupling is expensive both in terms of dev time and system resources.
- Uncle Bob’s preference? Push the decoupling to the point where a service _could_ be formed. _Should_ it become necessary. In the meantime, leave it in the same address same for as long as possible.
- Start at the source code level, but keep things nice and isolated so you could easily split it off
- Good architecture will allow a system to start as a monolith, and then grow to independently deployable units, and all the way back to monolith if need be down the line.
- Good architecture protects the majority of the source code from these changes – the decoupling is left open
Resources We Like
- Clean Architecture by Robert C. Martin (Amazon)
- Feature Toggles, Package Management and Versioning in Microsoft TFS and VSTS 2017 by Marcel de Vries (Pluralsight)
Tip of the Week
- Selectively stage chunks of a file using git add -p [<pathspec>] – https://git-scm.com/docs/git-add
- Sql Operations Studio is now available
- Use Flow for static type checking your next JavaScript project – https://flow.org/
- Application Security Weekly, listen and learn how to do security right.