Book notes: Fundamentals of Software Architecture
Tags: books, architecture
Published: 2022-03-26 10:34:13

---
title: Book notes: Fundamentals of Software Architecture
published: true
date: 2021-11-16 23:00:00 UTC
tags: books, architecture
series: Book notes
canonical_url: https://danlebrero.com/2021/11/17/fundamentals-of-software-architecture-summary/
description: Book notes on "Fundamentals of Software Architecture" by Mark Richards and Neal Ford
cover_image: https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/fundamentals-of-software-architecture.jpg
---

These are my notes on [Fundamentals of Software Architecture](https://amzn.to/38G1nh3) by [Mark Richards](https://twitter.com/markrichardssa) and [Neal Ford](https://twitter.com/neal4d)

A solid introduction to software architecture. 

Key learning: "it is really easy to fake it as an architect" :P.

A good companion to the book is Mark Richards' [Software Architecture Mondays](https://www.developertoarchitect.com/lessons/).

# Key Insights

* Architecture of the system is the sum of:
    1. Structure.
    1. Architecture characteristics (- ilities):
        * Define the success criteria of a system.
    1. Architecture decisions.
    1. Design principles:
        * Guidelines, not rules.
* Architect: Breath instead of depth.
* Almost every decision an architect makes will be challenged.

> Everything is a trade-off.
<cite>First law of software architecture.</cite>

> Why is more important than how.
<cite>Second law of software architecture.</cite>

* Architecture Thinking:
    1. Collaboration with teams to do architectural work.
    1. Technical breadth.
    1. Analysis trade-off.
    1. Understanding business drivers.
* Architecture is the stuff you can't Google.
* Never shoot for the best architecture, but rather for the least worst one.
* [Architecture Katas](http://fundamentalsofsoftwarearchitecture.com/katas/list.html).
* Once you have identified the architectural characteristics try to drop one (or two).
* Layered Architecture Style:
    * Sinkhole anti-pattern:
        * If most (> 50%) of the layers is a simple pass-through without logic.
* Service-based Architecture Style:
    * Typically, shared DB and UI.
    * One of the most pragmatic architecture styles.
* Event-Driven Architecture Style:
    * Two topologies:
        1. Broker topology:
            * No central event mediator, but a chain of events.
        1. Mediator topology:
            * Mediator manages and controls workflow.
        * [Trade-off table](#topoly-table).
        * Choice between topologies comes down to workflow control/error handling vs performance/scalability.
* Orchestration-Driven Service-Oriented Architecture Style:
    * Doomed to irrelevance.
* Making an architecture decision involves:
    1. Gather enough relevant information.
    2. Justify the decision.
    3. Documenting the decision.
    4. Communicating if effectively to the right stakeholders.
    * [Anti-patterns](#antipatterns):
        1. Covering your assets.
        1. Groundhog day.
        1. Email-Driven architecture.
* Asses risk per architecture characteristic per quanta.
* Unknown or unproven technologies are always high risk.
* Presentations: Insert blank slide to focus attention on speaker.
* Signs dev team is too big:
    * High process loss.
    * Pluralistic ignorance.
    * Diffusion of responsibility.
* Leverage on checklists.
* Demonstration defeats discussion.
* Negotiating with developers:
    * Always provide a justification, state it first.
    * Once a person hears something they disagree with, they stop listening.
    * If a dev disagrees with a decision, have them arrive at the solution on their own.
* Spend 20 mins first things in the morning (before reading work email) on learning.

# TOC 

* [Chapter 1: Introduction](#ch-1)
* [Part I - Foundations](#part-1)
    * [Chapter 2: Architectural Thinking](#ch-2)
    * [Chapter 3: Modularity](#ch-3)
    * [Chapter 4: Architecture Characteristics Defined](#ch-4)
    * [Chapter 5: Identifying Architectural Characteristics.](#ch-5)
    * [Chapter 6: Measuring and Governing Architecture Characteristics](#ch-6)
    * [Chapter 7: Scope of Architecture Characteristics](#ch-7)
    * [Chapter 8: Component Based Thinking](#ch-8)
* [Part II - Architecture Styles](#part-2)
    * [Chapter 9: Foundations](#ch-9)
    * [Chapter 10 - Layered Architecture Style](#ch-10)
    * [Chapter 11 - Pipeline Architecture Style](#ch-11)
    * [Chapter 12 - Microkernel Architecture Style](#ch-12)
    * [Chapter 13 - Service-based Architecture Style](#ch-13)
    * [Chapter 14 - Event-Driven Architecture Style](#ch-14)
    * [Chapter 15 - Space-Based Architecture Style](#ch-15)
    * [Chapter 16 - Orchestration-Driven Service-Oriented Architecture Style](#ch-16)
    * [Chapter 17 - Microservices Architecture](#ch-17)
    * [Chapter 18 - Choosing the Appropriate Architecture Style](#ch-18)
* [Part III - Techniques and Soft Skills](#part-3)
    * [Chapter 19 - Architecture Decisions](#ch-19)
    * [Chapter 20 - Analyzing Architecture Risk](#ch-20)
    * [Chapter 21 - Diagramming and Presenting Architecture](#ch-21)
    * [Chapter 22 - Making Teams Effective](#ch-22)
    * [Chapter 23 - Negotiation and Leadership Skills](#ch-23)
    * [Chapter 24 - Developing a Career Path](#ch-24)

# <a name="ch-1"></a>Chapter 1: Introduction

* Architecture of the system is the sum of:
    1. Structure:
        * Refers to the type of architecture style.
    1. Architecture characteristics (- ilities):
        * Define the success criteria of a system.
    1. Architecture decisions:
        * Rules of how the system should be constructed.
        * Variance == break rule. Reviewed/approved by architecture review board or chief architect.
    1. Design principles:
        * Guidelines, not rules.
* Core responsibilities of an architect:
    1. Make architecture decisions:
        * To guide, rather than specific technology choices.
    1. Continually analyze the architecture:
        * Viability of current architecture, specially if older than 3 years.
    1. Keep current with the latest trends.
    1. Ensure compliance with decisions.
    1. Diverse exposure and experience.
        * Breath instead of depth.
    1. Have business domain knowledge.
    1. Possess interpersonal skills.
    1. Understand and navigate politics.
        * Almost every decision an architect makes will be challenged.

> Everything is a trade-off.
<cite>First law of software architecture.</cite>    


> Why is more important than how.
<cite>Second law of software architecture.</cite>    

# <a name="part-1"></a>Part I - Foundations

## <a name="ch-2"></a>Chapter 2: Architectural Thinking

* Seeing from an architectural point of view. 
* 4 aspects:
    1. Collaboration with teams to do architectural work.
    1. Technical breadth.
    1. Analysis trade-off.
    1. Understanding business drivers.
* Architect must be part of the dev team to:
    1. Mentor/coach.
    1. Keep architecture and design in sync.
* Architecture is the stuff you can't Google.
* The answer to every architecture question is "it depends".
* Every architect should code:
    * Not in the critical path.
    * Proof of concepts.
    * Tooling.
        
# <a name="ch-3"></a>Chapter 3: Modularity

* Module:
    * Standardized or independent units that can be used to construct a more complex structure.
* Measuring modularity:
    * Cohesion:
        * Attempting to divide a cohesive module would only result in increased coupling and decreased readability.
        * LCOM: Lack of Cohesion in Methods:
            * Methods not using the same fields.
            * The sum of sets of methods not shared via sharing fields.
    * Coupling:
        * Afferent or efferent.
    * <a name="mainsequence"></a>Distance from the main sequence:
        * D = | A + I - 1 |
        * A = abstractness = sum(abstract elements) / sum(concrete elements)
        * I = instability = efferent coupling / (efferent + afferent)<br/>
![main sequence](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/main-sequence.jpg)    
    * Connascence:
        * Two components are connascent if a change in one requires a change in the other.
        * From more desirable (weaker connascense) to less desirable (stronger connascense):
            1. Name: agree on name.
            1. Type.
            1. Meaning or Convention: meaning of particular values.
            1. Position: order of values.
            1. Execution: order of execution.
            1. Timing: timing of threads.
            1. Values: several values must change together.
                * Distributed transaction.
            1. Identity: reference same entity.
        * [Jim Weirich](https://twitter.com/jimweirich):
            * Rule of Degree: convert strong forms into weaker forms of connascense.
            * Rule of Locality: as the distance between software elements increase, use weaker forms of connascense.
     
## <a name="ch-4"></a>Chapter 4: Architecture Characteristics Defined

* Architecture characteristic == non functional requirements:
    * Implicit or explicit.
    * Architect should choose the fewest architecture requirements.
    * Criteria:
        * Influences design.
        * Is critical for success.
    * List in page 58.
* Never shoot for the best architecture, but rather for the least worst one.

## <a name="ch-5"></a>Chapter 5: Identifying Architectural Characteristics.

* Translate domain stakeholders concerns:
    * Examples:
        * Time and budget -> Simplicity, feasibility.
        * User satisfaction -> Performance, availability, fault tolerance, testability.
        * Time to market -> Agility, testability, deployability.
        * Merger and acquisitions -> Interoperability, scalability, adaptability, extensibility.
* From requirements and inherent domain knowledge.
* [Architecture Katas](http://fundamentalsofsoftwarearchitecture.com/katas/list.html).
* Once you have identified the architectural characteristics try to drop one (or two).
    
## <a name="ch-6"></a>Chapter 6: Measuring and Governing Architecture Characteristics

* Governance:
    * Evolutionary architectures and fitness functions.
    * Conformity, Janitor and Security monkeys. 

## <a name="ch-7"></a>Chapter 7: Scope of Architecture Characteristics

* Scope is per architecture quantum, not the whole system.
    * Architecture quantum:
        * An independently deployable artifact with high functional cohesion and synchronous connascense.
        * DB is part of the quantum.
    
## <a name="ch-8"></a>Chapter 8: Component Based Thinking

* Component:
    * Physical manifestation of a module.
    * Lowest level than an architect interacts directly with.
* Top level partitioning; either
    * Technical partitioning: layered architecture.
    * Domain partitioning: modular monolith, microservices.
        * By workflow or domain.
* Component identification flow:<br/>
![Component identification flow](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/component-identification-flow.png)
* Entity trap anti-pattern:
    * Entity manager == components.
* Discovering components:
    1. Actor/Actions: use case diagrams.
    1. Event storming.
    1. Workflow approach.

# <a name="part-2"></a>Part II - Architecture Styles

* Architecture style: overall structure of how the code is organized.
* Architecture pattern: specific solutions within an architecture style.
    
## <a name="ch-9"></a>Chapter 9: Foundations

* Fallacies of distributed programming:
    1. The network is reliable.
    1. Latency is zero.
    1. Bandwidth is infinite:
        * Stamp coupling: 
            * Returning more data than required in a REST endpoint.
            * Fixes:
                * More specific endpoints.
                * Field selectors in contract.
                * GraphQL.
    1. Network is secure.
    1. Network topology never changes.
    1. There is only one administrator.
    1. Transport cost is zero.
    1. The network is homogeneous.
        
## <a name="ch-10"></a>Chapter 10 - Layered Architecture Style

* Typical layers:
    * Presentation, business, persistence, database.
* Leverage technical expertise.
* Lack of overall agility.
* Business domain is spread through all layers.
* Does not work well with DDD.
* Architecture sinkhole anti-pattern: 
    * If most (> 50%) of the layers is a simple pass-through without logic.
    * Move to another architecture style.
* Good for small apps.
* Layered are == monolith.
* Cost and simplicity degrade quickly when app gets bigger/more complex.

## <a name="ch-11"></a>Chapter 11 - Pipeline Architecture Style

* Encourages compositional reuse.
* Usually deployed as a monolith.

## <a name="ch-12"></a>Chapter 12 - Microkernel Architecture Style

* Aka plug-in architecture.
* Core can be layered or modular monolith or another process.
* Typically, point-to-point communication between core and plugins.
* Compile time or runtime (OSGi) plugins.
* Eclipse, Jenkins, Jira, Chrome/Firefox.

## <a name="ch-13"></a>Chapter 13 - Service-based Architecture Style

* Coarse-grained services with typically a shared DB and UI:
    * Split by domain.
    * Services do not talk to each other.
    * Maybe an API gateway.<br/>
![Service-based Architecture Style](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/service-based-architecture-style.jpg)
* DB can be split logically by providing domain specific libraries, so it is easier to find out which service is going to be impacted by a DB schema change.
* One of the most pragmatic architecture styles:
    * Good modularity.
    * No distributed orchestration/choreography.

## <a name="ch-14"></a>Chapter 14 - Event-Driven Architecture Style
   
* Two topologies:
    1. Broker topology:
        * No central event mediator, but a chain of events.
        * Usually broadcast of events.
        * Good practice: event processors to advertise what they did, even if no other event processor cares right now. (Really?)
    1. Mediator topology:
        * Mediator manages and controls workflow.<br/>
![Mediator topology](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/mediator-topology.jpg)
        * Communication between Event Mediator and processors is sending commands point-to-pint with queues.
        * Processors do not broadcast their actions.        
* For simple processing: Apache Camel, Spring Integration.
* For hard: BPEL product (Apache ODE).
* For complex, long running transactions that require manual intervention: BPM.
* Recommendation: initial processing by simple mediator that can forward the event to complex/hard depending on event complexity classification.
* <a name="topoly-table"></a>Trade-off table:
<table>
    <thead>
        <tr>
            <th></th>
            <th>Advantages</th>
            <th>Disadvantages</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan=5>Broker</td>
            <td>Highly decoupled event processor</td>
            <td>Workflow control</td>
        </tr>
        <tr>
            <td>Highly scalability</td>
            <td>Error handling</td>
        </tr>
        <tr>
            <td>High responsiveness</td>
            <td>Recoverability</td>
        </tr>
        <tr>
            <td>High performance</td>
            <td>Restart capabilities</td>
        </tr>
        <tr>
            <td>High fault tolerance</td>
            <td>Data inconsistency</td>
        </tr>         <tr>
            <td rowspan=5>Mediator</td>
            <td>Workflow control</td>
            <td>More coupling</td>
        </tr>
        <tr>
            <td>Error handling</td>
            <td>Lower scalability</td>
        </tr>
        <tr>
            <td>Recoverability</td>
            <td>Lower performance</td>
        </tr>
        <tr>
            <td>Restart capabilities</td>
            <td>Lower fault tolerance</td>
        </tr>
        <tr>
            <td>Better data consistency</td>
            <td>Modeling complex workflows</td>
        </tr>        
</tbody>
</table>

* Choice between topologies comes down to workflow control/error handling vs performance/scalability.
* Workflow event pattern for error handling:
    1. Event consumer forwards bogus event to the workflow processor and continues with next event.
    1. Workflow processor tries to repair event and forwards it to the event consumer's original queue.
    1. From event consumer point of view is a new event.
    1. If event cannot be repaired, workflow processor forwards it to some dashboard for manual intervention.
* Preventing data loss:
    1. Producer: synchronous sent + persistent queue.
    1. Consumer: client acknowledge mode.
* Request-reply implementations:
    1. Correlation ID.
    1. Temporary queue for the response.

| Request-based model | Event-Based model |
| ---- | ---- |
| Certainty and control over workflow is needed | Flexibility |    
| | Responsiveness, scalability|    
| | Complex and dynamic processing |   

## <a name="ch-15"></a>Chapter 15 - Space-Based Architecture Style

* Usage of data grids to avoid DB bottlenecks.
* Highly scalable, elastic, performant.
* Async writes to DB through persistent queues.
* Hazelcast, Apache Ignite, Oracle Coherence.<br/>
![Space-Based Architecture Style](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/space-based-architecture-style.jpg)
* Message grid:
    * Nginx or HA proxy.
    * Routing of request.
* Data Grid:
    * Nowadays implemented within the processing unit.
    * It is essential that each processing unit contains exactly the same data.
* Processing grid:
    * If orchestration is needed between different processing unit types.
* Deployment manager:
    * Manages number of processing units depending on load.
* Data collision due to replication lag:
    * Collision rate formula: N * (UR<sup>2</sup> / S) * RL
        * N = number of instance.
        * UR = update rate in milliseconds.
        * S = cache size.
        * RL = replication latency.
* Can deploy processing units, virtualized middleware and data pumps to cloud, and reader/write and DB on-premise.
* Distributed cache:
    * When: 
        1. Data to be cached is big (> 100 Mb).
        1. High write rates.
        1. Collisions are not acceptable.
* Recommended with very spiky apps and high number of concurrent users (> 10k).

## <a name="ch-16"></a>Chapter 16 - Orchestration-Driven Service-Oriented Architecture Style

* Doomed to irrelevance.
* Aim is reuse by technical partitioning:<br/>
![Orchestration-Driven Service-Oriented Architecture Style](https://danlebrero.com/images/blog/books/fundamentals-of-software-architecture/esb-architecture-style.jpg)
* Enterprise Service Bus (ESB).
* Business services:
    * No code.
    * Defined by business users.
* Enterprise services: Reusable.
* App Services: 
    * App specific logic. 
    * Not reusable.
* Infrastructure Services: Monitoring, logging, ...
* ESB: 
    * Bureaucratic bottleneck.
* Distributed monolith.

## <a name="ch-17"></a>Chapter 17 - Microservices Architecture

* Primary goal is high decoupling.
    * At the cost of duplication and distributed architecture.
* Size, consider:
    * Purpose.
    * Transaction boundaries.
    * Choreography.
    * Data isolation.
* Sidecar pattern.
* Service mesh.
* Microfrontends, either:
    * Choreography: service call other services as needed.
    * Mediator: new service that pulls data from several other services.
* Don't do distributed transactions, fix granularity instead.
    * Saga pattern:
        * Mediator to coordinate.
        * Compensating transactions to rollback.
        * More than double the complexity.

## <a name="ch-18"></a>Chapter 18 - Choosing the Appropriate Architecture Style

* Design criteria:
    * Domain.
    * Architecture characteristics that impact structure.
    * Data architecture.
    * Organizational factors.
    * Processes, teams, and operational concerns.
    * Domain/architecture isomorphism: 
        * Some domains match the topology of the architecture.
* Decide on:
    1. Monolith vs distributed.
    1. Where should data live?
    1. Async vs sync communication:
        * Use sync by default, async when necessary.
        
# <a name="part-3"></a>Part III - Techniques and Soft Skills

## <a name="ch-19"></a>Chapter 19 - Architecture Decisions

* Making an architecture decision involves:
    1. Gather enough relevant information.
    1. Justify the decision.
    1. Documenting the decision.
    1. Communicating if effectively to the right stakeholders.
* <a name="antipatterns"></a>Anti-patterns:
    1. Covering your assets:
        * Avoid or delay making a decision out of fear of making the wrong one.
        * Overcome by:
            1. Waiting until the last responsible moment.
            1. Continually collaborate with dev teams to avoid blind spots and ensure feasibility of implementation.
    1. Groundhog day:
        * Decision is discussed over and over because people do not know why of the decision.
        * Both technical and business justification is required.
    1. Email-Driven architecture:
        * People lose, forget, or don't even know an architecture decision due to poor communication.
        * Improve effectiveness of comms:
            1. Email should not contain any details of decision, only a link to the system of record.
            1. Only email people that care about the decision.
* Architecture Decision Records ([ADRs](adr.github.io)):
    * Allows to place more emphasis on the why rather than the how.
    * Consequences section: add trade-off analysis.
    * Authors suggest two more sections:
        1. Compliance:
            * How the decision will be checked.
        1. Notes:
            * Metadata: author, approval date, ...
            
## <a name="ch-20"></a>Chapter 20 - Analyzing Architecture Risk

* Risk = impact (1 to 3) * likelihood (1 to 3):
    * High risk >= 6, medium >= 3.
* Asses risk per architecture characteristic per quanta.
* Risk storming:
    * Architects + some devs.
    * Ideally one storming session per architecture characteristic.
    1. Identification:
        * Individual activity.
    1. Consensus.
    1. Mitigation.
* Unknown or unproven technologies are always high risk.

## <a name="ch-21"></a>Chapter 21 - Diagramming and Presenting Architecture

* Representational consistency: always show relationship between parts of an architecture before changing views/drilling down.
* Solid lines indicate synchronous communication, dotted lines async.
* Insert blank slide to focus attention on speaker.

## <a name="ch-22"></a>Chapter 22 - Making Teams Effective

* It is really easy to fake it as an architect.
* Architect personalities:
    1. Control freak:
        * Tight boundaries that causes frustration in the dev teams.
    1. Armchair architect:
        * Loose boundaries that cause confusion in the dev team.
    1. Effective architect: not too hot, not too cold, but just right.
* [Elastic leadership](ElasticLeadership.com).
* How much control depends on:
    * How long/well the team members know each other.
    * Team size.
    * Overall experience.
    * Project complexity.
    * Project duration.
* Signs dev team is too big:
    * High process loss:
        * Potential productivity - process loss == actual productivity.
        * Example: merge conflicts.
    * Pluralistic ignorance:
        * When everybody agrees to a norm, but privately rejects it because they think they are missing something obvious.
        * Fear to speak up.
    * Diffusion of responsibility:
        * As team increases, communication gets harder.
        * Example:
            * Confusion about responsibilities.
            * Things getting dropped.
* Leverage on checklists:
    * [The Checklist Manifesto](https://amzn.to/3h9xNoZ).
    * Don't worry about stating the obvious in a checklist. It is the obvious stuff that is usually skipped or missed.
    * 3 typical checklists:
        1. Developer code completion list:
            * "Definition of done".
        1. Unit and functional testing checklist:
            * More unusual and edge cases.
            * Not automated stuff.
        1. SW release checklist.
    * To make devs use checklists:
        1. Explain importance, show effectiveness, ask devs to read The Checklist Manifesto.
        1. Hawthorne effect:
            * If people believe they are observed or monitored, they will change their behaviour.
            * Tell devs that checklist compliance will be monitored.
            
## <a name="ch-23"></a>Chapter 23 - Negotiation and Leadership Skills

* Negotiation with business stakeholders:
    * When all else fails, state things in terms of cost and time.
    * Leverage the "divide and conquer" rule to qualify demands or requirements.
* Negotiation with other architects:
    * Demonstration defeats discussion.
    * Avoid being too argumentative.
    * Calm leadership.
* Negotiating with developers:
    * Always provide a justification, state it first.
    * Once a person hears something they disagree with, they stop listening.
    * If a dev disagrees with a decision, have them arrive at the solution on their own.
    
## <a name="ch-24"></a>Chapter 24 - Developing a Career Path

* Spend 20 mins first things in the morning (before reading work email) on learning.
* Personal Technology radar.