Notes for the book Fundamentals of Software Architecture - An Engineering Approach by Mark Richards and Neal Ford.
Brief Summary & thoughts
The book had a certain vision of a software architect role, but I missed some discussion on roles on different levels of architecture, e.g. system design, solution, enterprise, etc. (See e.g. SFIA skills framework for Systems Design vs Enterprise architecture.
Some high-level take-aways
- Importance of context - Past decisions were based on realities of the environment from that time
- Why is more important than how. (Second law)
Intros
- Preface: Invalidating axioms
- Mathematics build theories based on axioms
- Software architects also build theories atop axioms, but the software world is softer than mathematics.
- It is important to question assumptions and axioms left over from previous eras.
- Subtitle "Engineering approach" - Engineering discipline, implying repeatability, rigor and effective analysis.
- Trade-off analysis is important!
Why no clear career path for software architects?
Definition of software architecture or architect is difficult
- Definition of a software architect from Martin Fowler's Who Needs an Architect
- Architecture is about the important stuff... whatever it is (Ralph Johnson)
- Definition of a software architect from Martin Fowler's Who Needs an Architect
Massive amount and scope of responsibility
Constantly moving target
Much of the material about software architecture has mostly historical relevance.
NOTE: When studying architecture, keep in mind that it can only be understood in context
- Past decisions were based on realities of the environment from that time
One way to think about software architecture:
- Structure of the system
- Architecture characteristics ("-ilities")
- Architecture decisions
- Design principles
- Principle is a guideline rather than a hard rule.
Expectations of an architect (instead of defining the role)
- Define the architecture decisions and design principles
- Continually analyze the architecture
- Keep current with latest trends
- Ensure compliance with decisions
- Diverse exposure and experience
- Have business domain knowledge
- Possess interpersonal skills
- Gerald Weinberg: "no matter what they tell you, it's always a people problem."
- Understand and navigate politics
- Almost every decision an architect makes will be challenged -> negotiation skills
Engineering practices
- All architectures become iterative because of unknown unknowns, Agile just recognizes this and does it sooner. (Mark Richards)
- See also Building
Evolutionary Architectures
- Architectural fitness functions
Laws of Software Architecture
- Everything in software architecture is a trade-off (First law)
- If an architect thinks they have discovered something that isn't a trade-off, more likely they just haven't identified the trade-off yet. (Corollary 1)
- Why is more important than how. (Second law)
Part I - Foundations
Chapter 2: Architectural Thinking
Four aspects
- Understanding the difference between architecture and design
- In traditional view, unidirectional flow from the architect to the developer
- To make architecture work, both the physical and virtual barriers between architects and developers must be broken down.
- Having a wide breath of technical knowledge
- Three sections
- Stuff you know (and need to maintain)
- Stuff you know you don't know
- Stuff you don't know you don't know
- Architects should focus on technical breadth more than depth.
- Three sections
- Understanding and analyzing trade-offs
- Architecture is the stuff you can't Google (Mark Richards)
- There are no right or answers in architecture - only trade-offs (Neal Ford)
- Programmers know the benefits of everything and the trade-offs of nothing. Architects need to understand both (Rich Hickey)
- Understanding the business drivers and their importance
Chapter 3: Modularity
- Physics analogy Energy must be added to a physical system to preserve order. The same is true for software systems - Good structural soundness won't happen by accident/itself.
- Modularity definition of book: Logical grouping of related code
(actual term varies by programming language etc.)
- For discussions about architecture, a logical separation, not necessarily "physical"
Three metrics/concepts for modularity:
- Cohesion - To what extent the parts of a module should be contained
within the same module
- Attempting to divide a cohesive module would only result in increased coupling and decreased readability. (Larry Constantine)
- Lack of Cohesion (of Methods (LCOM) metric
- Coupling
- Afferent & efferent couplings and other metrics in Software package metrics
- NOTE: Coming from the age of structure programming, before e.g. object-oriented languages
- Connascense
- Two components are connascent if a change in one would require the other to be modified in order to maintain the overall correctness of the system (Meilir Page-Jones)
- Static connascense (source-code-level coupling) vs dynamic (execution-time) connascense
- Strength of connascense (see e.g. blog post About connascence
- Three guidelines from Page-Jones for using connascense to improve
system modularity:
- Minimize overall connascence by breaking the system into encapsulated elements.
- Minimize any remaining connascence that crosses encapsulation boundaries.
- Maximize the connascence within encapsulation boundaries.
- Jim Weirich's two principles
- Rule of Degree: Convert strong forms of connascence into weaker forms of connascence.
- Rule of Locality: As the distance between software elements increases, use weaker forms of connascence.
- Problems with 1990s connascence
- Low-level, focusing on code quality and hygiene more than architectural structure
- Doesn't really address a fundamental decision - synchronous or asynchronous communication in distributed architectures
Own book recommendation related to modularity: A Philosophy of Software Design
Chapter 4: Architecture Characteristics Defined
- Architectural characteristics: "All the things the software must do
that isn't directly related to the domain functionality"
- Traditional "Non-functional requirement" not preferred as "non-functional" doesn't sound something worth paying attention to.
- Three criteria for architectural characteristics
- Specifies a non-domain design consideration
- Influences some structural aspect of the design
- Is critical or important to application success
- NOTE: A critical job for architects lies in choosing the fewest architecture characteristics rather than the most possible.
- Lists
- For a partial list, see blog post [Summary — Chap 4] Fundamentals of Software Architecture
- ISO/IEC 25010 list
- Quote: Never shoot for the best architecture, but rather the least worst architecture.
- See also the book Building Evolutionary Architectures
Chapter 5: Identifying Architectural Characteristics.
At least three ways to extract architecture characteristics:
- from domain concerns
- For prioritization, a good approach is to have the domain stakeholders select the top three most important characteristics from the final list.
- Note: Often domain concern consists of multiple architecture characteristics. E.g. "time to market" comes from agility + testability + deployability
- from requirements
- from implicit domain knowledge
For practising, see Architectural Katas
Quote: There are no wrong answers in architecture, only expensive ones.
Chapter 6: Measuring and Governing Architecture Characteristics
- Challenges around the definition of architecture characteristics
- They aren't physics
- Wildly varying definitions
- Too composite
- Objective definitions solve all three problems.
- Architecture fitness functions
- See the book Building Evolutionary Architectures
- Compare to checklists (see The Checklist Manifesto
Chapter 7: Scope of Architecture Characteristics
- Earlier discussed metrics, e.g. afferent/efferent coupling are at a too fine-grained level for architectural analysis.
- Connascense at service level with (micro-)service architecture
- static connascense: two services share the same class definition of some class
- dynamic connascense:
- synchronous: Synchronous call between two distributed services
- asynchronous: Asynchronous calls allowing fire-and-forget semantics
- Defining Architecture quantum: An independently deployable
artifact with high functional cohesion and synchronous connascense
- Architecture quantum provides a new scope for architecture characteristics
- In modern systems, architects define architecture characteristics at the quantum level rather than system level.
Chapter 8: Component Based Thinking
- Component (here): Physical packaging of modules
- library: A component wrapping code at a higher modularity than classes/functions
- layers/subsystems
- services
- Architect role (book's view)
- Typically architect defines, refines, manages and governs components within an architecture
- Generally, a component is the lowest level of the software system an architect interacts directly with.
- Two types of top-level architecture partitioning - One of the first
decisions an architect must make.
- Layered (often "technical partitioning")
- Modular (often "domain partitioning")
- Conway's Law: Organizations,
who design systems, are constrained to produce designs which are copies
of the communication structures of these organizations.
- See also Inverse Conway Maneuver
Part II - Architecture Styles
- Architecture style/pattern? (Book's definition)
- Architecture style: The overarching structure of how the user interface and backend source code are organized and how the source code interacts with a datastore
- Architecture patterns: Lower-level design structures that help form solutions within an architecture style
Chapter 9: Foundations
- Architecture style name creates a single name that acts as shorthand between experienced architects
Fundamental Patterns
- Big Ball of Mud
- Unitary Architecture - Everything running on one computer
- Client/Server
Two main types
- Monolithic
- Distributed Architectures
For distributed architectures, it's important to be aware of Fallacies of distributed computing
- The network is reliable
- Latency is zero
- Be aware of "long tail" latency - It's important to know the 95th to 99th percentile
- Bandwidth is infinite
- Regardless of the technique, ensure that minimal amount of data is passed between services in distributed architecture to avoid bandwidth problems.
- The network is secure
- Topology doesn't change
- There is one administrator
- Transport cost is zero
- The network is homogeneous
Other distributed considerations
- Distributed logging
- Distributed transactions
- Eventual consistency
- Transactional sagas
- BASE
transactions
- Basically available
- Soft state
- Eventually consistent
Chapter 10 - Layered Architecture Style
- Often implemented if developer/architect is unsure about which architecture style is used or team "just starts coding"
- Typically four layers: Presentation, business, persistence and database
- Technically partitioned (opposed to domain-partitioned)
- Any particular business domain is spread throughout all of the layers of the architecture
- Can be either
- closed - request must go through the layer immediately below it to get to the next layer
- open - allowing requests to pass layers
- Layer of isolation concept - Changes made in one layers generally don't affect components in other layers, providing the contracts between layers stay unchanged
- Be aware of architecture sinkhole anti-pattern
- Why to use?
- Good choice for small, simple applications or websites.
- Good choice as a starting point with very tight budget and time constraints
Chapter 11 - Pipeline Architecture Style
- Also known as pipes and filters
- Four types of filters
- Producer - The starting point
- Transformer - FP
map - Tester - FP
reduce - Consumer - The termination point
- Blog post More shell, less egg illustrates power of these abstractions
Chapter 12 - Microkernel Architecture Style
- Also known as plug-in architecture
- Natural fit for product-based applications, e.g. IDEs
- Basic components
- Core System (can be implemented as a layered architecture or a modular monolith)
- Plug-In Components
- (Additionally) Registry: A common way to manage which plug-in modules are available and how to get them
Chapter 13 - Service-based Architecture Style
- Hybrid of the microservices style
- Topology
- Separately deployed user interface
- Separately deployed remote coarse-grained services
- A monolithic database (usually)
- Service design and granularity
- Regular ACID database transactions are used to ensure database integrity within a single domain service.
- Whereas microservice setups typically use BASE transactions
- When to use?
- Flexibility
- One of the most pragmatic architecture styles
- Natural fit when doing DDD
- When ACID transactions are needed
- A good choice for achieving a good level of architectural modularity without complexities and pitfalls of granularity
- Not so much need for coordination as with other distributed architectures
Chapter 14 - Event-Driven Architecture Style
- Made up of decoupled event processing components that asynchronously receive and process events
- Can be used as a standalone style or embedded with other styles
- How to implement a request-based model with an event-driven style?
- Request orchestrator - Typically UI but can also be implemented through an API layer or ESB
Two main topology variants
- Variant: Broker topology
- no central event mediator
- Message flow is distributed through a lightweight message broker (e.g. RabbitMQ, ActiveMQ etc)
- Four primary architecture components
- Initiating event
- Event broker
- Event processor
- Processing event
- It is a good practice for each event processor to advertise what it did to the rest of the system (-> provides easy extensibility)
- Trade-offs of the broker topology
- (+) Highly decoupled event processors vs (-) Workflow control
- (+) High scalability vs (-) Error handling
- (+) High responsiveness vs (-) Recoverability
- (+) High performance vs (-) Restart capabilities
- (+) High fault tolerance vs (-) Data inconsistency
- Variant: Mediator topology
- Addresses some of the short-comings of the broker topology
- Event mediator manages and controls the workflow for initiating events
- Primary architecture components
- Initiating event
- Event queue
- Event mediator
- Event channels
- Event processors
- Various approaches
- The book recommends classifying events as simple, hard or complex
- Simple events with a simple mediator (e.g. Apache Camel or Mule)
- If event workflow requires lots of conditional processing / dynamic paths, a mediator such as Apache ODE or Oracle BPEL Process Manager are recommended
- Main differences to broker topology
- Central mediator that can maintain event state and manage error handling, recoverability and restart capabilities
- Typically, in broker topology the messages are events (things that have happened), whereas in mediator topology they are commands (things that need to happen)
Various topics on Event-driven Architecture Style
Asynchronous capabilities
- Can be a powerful technique for increasing the overall responsiveness of a system
- Responsiveness vs Performance
- Responsiveness - Notifying the user that the action has been accepted and will be processed momentarily
- Performance - Making the end-to-end process faster
- Main issue with asynchronous communication is error handling
Preventing Data Loss
- Typical setup - Processor A sends message to a queue and Processor B accepts the message and inserts the message into a database
- Three areas of data loss
- Message does not make it to the queue from Processor A - Can be solved with synchronous send with persistent message queue
- Processor B de-queues the message and crashes before it is processed - Can be solved with client acknowledgement mode
- Processor B is unable to persist the message - Can be solved with an ACID transaction via database commit and acknowledging the message only after it
Request-reply messaging (pseudosynchronous communication)
- Two primary techniques
- Correlation ID in the request message header and using the same ID in the reply message
- Temporary queue for the reply
Trade-offs of event-driven model vs request-based
- (+) Better response to dynamic user content
- (+) Better scalability and elasticity, responsiveness and performance
- (+) Better adaptability and extensibility
- (-) Only supports eventual consistency
- (-) Less control over processing flow
- (-) Less certainty over outcome of event flow
- (-) Difficult to test and debug
Architectural quantum: Even though all communication in event-driven architecture is asynchronous, if multiple event processors share a single database instance, they are all contained within the same architectural quantum.
Chapter 15 - Space-Based Architecture Style
- Space-based architecture style is specifically designed to address problems involving high scalability, elasticity and high concurrency issues.
- The style gets its name from the concept of tuple space, the technique of using multiple parallel processors communicating through shared memory.
- Architecture components:
- Processing unit containing the application code
- Virtualized middleware used to manage and coordinate the processing units
- Data pumps to asynchronously send updated data to the database
- Data writers that perform the updates from the data pumps
- Data readers that read DB data and deliver it to processing units upon startup.
- One decision to be aware of : Replicated cache vs distributed cache
Chapter 16 - Orchestration-Driven Service-Oriented Architecture Style
- Architecture styles must be understood in the context of the era in which they evolved.
- Late 1990s
- Operating systems were expensive and licensed per machine. Commercial database servers with Byzantine licensing schemes...
- -> Architects were expected reuse as much as possible
- -> Driving philosophy in this architecture centered around enterprise-level reuse.
- Topology
- Business Services - "Entry points"
- Enterprise Services - Meant as reusable building blocks. (Did not work se well often)
- Application Services - one-off single-implementation services
- Infrastructure Services (e.g. monitoring, logging, ...)
- Orchestration Engine (ESB?)
- Typically one or a few relational databases - Transactional behaviour handled in the orchestration engine
- Because of Conway's Law, the team of integration architects responsible for this engine become a political force within an organization, eventually a bureaucratic bottleneck
- Finding the correct level of granularity of transactions became difficult
- Reuse ... and coupling
- Aggressive reuse
- High amount of coupling between components
- E.g. Customer service ending up including all the details the organization knows about customers
- Combining the disadvantages of both monolithic and distributed architectures
Chapter 17 - Microservices Architecture
- The driving philosophy of microservices is the DDD concept bounded context - Each service models a domain or workflow.
- Primary goal of microservices: High decoupling, physically modeling the logical notion of bounded context.
- Each service owning its own process
- Note: This is nowadays practical because of virtual machines & containers, open source operating systems etc.
- Granularity
- Difficult - Often the mistake of making services too small
- Purpose is to capture a domain or workflow
- Some guidelines
- Purpose - Functionally cohesive services
- Transactions - Entities that need to cooperate in a transaction show a good service boundary
- Choreography - Sometimes it might make sense to bundle services together to avoid the communication overhead.
- Data isolation - Avoiding shared schemas and databases used as integration points
- API Layer
- Sitting between the consumers of system (UIs or calls from external systems)
- Optional
- Operational reuse
- Microservices prefer duplication to coupling
- Certain parts of architecture that benefit from coupling - such as operational concerns like monitoring, logging and circuit breakers?
- Sidecar pattern, even a service mesh
- Two styles of user interfaces commonly appear with microservices
architecture
- Monolithic frontend - A single UI that calls through the API layer
- Microfrontends
- Communication
- Big decision - Synchronous or asynchronous communication
- Microservices often utilize protocol-aware heterogeneous
interoperability
- Standardize how services communicate with each other
- Choreography and orchestration
- Choreography
- Same communication style as a broker event-driven architecture
- No central coordinator/mediator
- Orchestration - localized mediator
- Each option has trade-offs
- Choreography
- Transactions and sagas
- The best advice for architects that want to do transactions across services is: Don't!
- Saga pattern is a popular distributed transactional pattern in microservices.
Chapter 18 - Choosing the Appropriate Architecture Styled
- Very contextual to a number of factors within an organization and what software it builds.
- Good to be aware of industry trends, when to follow and when not to.
- Many factors to take into account, e.g.
- The domain
- Architecture characteristics that impact structure
- Data architecture
- Organizational factors
- ...
- Taking these into account, the architect must make several
determinations
- Monolithic versus distributed?
- Where should data live?
- Communication style between services - synchronous or asynchronous?
- Rule of thumb: Use synchronous by default, asynchronous when necessary.
- Output of this process is architecture topology.
Part III - Techniques and Soft Skills
Chapter 19 - Architecture Decisions
- Architecture decisions
- Usually involve the structure of the application or system
- May involve technology decisions as well, especially when those impact architecture characteristics.
- A good architecture decision is one that helps guide development teams in making the right technical choices
- Three major anti-patterns
- Usually progressive flow: Overcoming the first leads to the second etc.
- Anti-pattern 1: Covering Your Assets
- Avoiding or deferring decisions out of fear of making the wrong choice.
- 2 ways to overcome:
- Wait until the last responsible moment
- Continuously collaborate with the development teams to ensure that the decision you made can be implemented as expected
- Anti-pattern 2: Groundhog Day
- People don't know why a decision was made -> It keeps getting discussed over and over again
- Background: Missing of incomplete justification
- To overcome: Provide both technical and business justifications
- Anti-pattern 3: Email-Driven Architecture
- People lose, forget or don't even know an architecture decision has been made
- Ways to overcome:
- Do not include the architecture decision in body of an email
- Instead, mention only nature and context of the decision and provide a link to the single system of record for the architecture decision
- Only notify those people who really care about the architecture decision.
- Architecturally significant decisions
- Those that affect the structure, non-functional characteristics, dependencies, interfaces of construction techniques.
- Architecture Decision Records
- ADRs, see https://adr.github.io/
- Basic structure: Title, Status, Context, Decision and Consequences
- Important to mark Superseded and link back and forth
- More emphasis on the why rather than how.
Chapter 20 - Analyzing Architecture Risk
- One of the key activities of architecture
- Risk matrix: Likelihood of risk occurring X Overall impact of risk
- Risk storming exercise, see https://riskstorming.com/
- Identification, consensus, mitigation
- Recommendation: Whenever possible, restrict risk storming efforts to a single dimension.
- Not a one-time process but continuous process
Chapter 21 - Diagramming and Presenting Architecture
- No matter how great an architect's technical ideas are, if they can't convince managers to fund them and developers to build them, their brilliance will never manifest.
- Representational consistency - Always showing the relationships between parts of an architecture
- Avoid "Irrational artifact attachment"
- Many tools, the authors happily used OmniGraffle for the diagrams of
the book
- Good to have: Layers, Stencils/templates, Magnets
- Standards: UML, C4 and ArchiMate
- Various tips & links
- Check out Presentational Patterns
- Avoid Bullet-Riddled Corpse
- Distinctiate between infodecks vs presentations
- Invisibility - Inserting a blank slide within a presentation - Refocusing attention solely on the speaker
Chapter 22 - Making Teams Effective
- (Own comment) Here the role of an architect was left somewhat open to me.
- Promoting close cooperation between an architect and development teams.
- Important: Create and communicate the constraints, in which developers can implement the architecture. Avoid being too tight or loose.
- Architect personalities:
- Architect personality: Control Freak
- (Own comment) In the book, architect is seen as a role that does not code
- Tries to control every detailed aspect of the software development process.
- Architect personality: Armchair Architect
- Quote: Here's a dirty little secret about architecture - it's really easy to fake it as an architect
- It might not be the intention of an architect to become an armchair architect, but rather it just happens by being spread too thin between projects or development teams and losing touch with technology or the business domain.
- To avoid, get more involved in the technology being used in the project and understanding the business problem and domain.
- Architect personality: Effective architect
- Produces the appropriate constraints and boundaries on the team.
- Ensures the team members are working well together.
- Have the right level of guidance on the team.
- Architect personality: Control Freak
- How much control?
- Elastic Leadership
- Finding the right level of control (balancing between control freak
and armchair architect) depends on 5 factors
- Team familiarity (with each other)
- Team size
- Overall experience
- Project complexity
- Project duration
- Note: This changes as the system continues to evolve and the projects goes on
- Model in the team: Assign a value between -20 and 20 for each factor and sum
- Three factors when considering a proper team size
- Process loss ("Brook's Law" from Mythical Man-Month)
- Pluralistic ignorance - Occurs as the team size gets too big (compare with "The Emperor's New Clothes")
- Diffusion of Responsibility
- Leveraging Checklists
- See The Checklist Manifesto
- Good candidates for checklists: Processes that don't have any procedural order or dependent tasks.
- Three key checklists
- Developer code completion checklist (~DoD)
- A unit and functional testing checklist
- Software release checklist
- On Providing Guidance
- (Discussion on code-level 3rd party libraries, frameworks etc)
- When somebody is proposing a library/framework, first ask the
following questions
- Are there any overlaps between the proposed library and existing functionality in the system?
- What is the justification for the proposed library
- (Own comment) Here the architect role is already quite much into the details also.
Chapter 23 - Negotiation and Leadership Skills
- A software architect must understand the political climate of the
enterprise and be able to navigate the politics.
- Reason: Almost every decision an architect makes will be challenged
- Negotiating with Business Stakeholders (Various tips)
- Leverage the use of grammar and buzzwords to better understand the situation
- Gather as much information as possible before entering the negotiation
- Validate concerns, then bring the negotiation
- When all else fails, state things in terms of cost and time
- Leverage the "divide and conquer" rule to qualify demands or
requirements
- E.g. does some requirement apply to the entire system or some specific part/functionality?
- Negotiating with Developers
- Work with the development team to gain respect
- When convincing developers to e.g. adopt an architecture decision, provide a justification rather than "dictating from on high"
- Provide justification/reason first to make sure it will be heard.
- Guide the developer to arrive at the solution on their own.
- The Software Architect as a Leader
- 50% of being an effective software architect is having good people skills, facilitation skills and leadership skills.
- Essential complexity vs accidental complexity
- 4 C's of architecture: Communication, Collaboration, Clarity and Conciseness
- Be Pragmatic, Yet Visionary
- Visionary - Thinking about or planning the future with imagination or wisdom
- Pragmatic - Dealing with things sensibly and realistically in a way that is based on practical than theoretical considerations
- Strive to find an appropriate balance between these
- Leading Teams with Example
- "No matter what the problem is, it's a people problem" [https://en.wikipedia.org/wiki/Gerald_Weinberg](Gerald Weinberg)
- (Basic tips)
- Instead of "What you need" or "You must", try "Have you considered", "What about"
- Try to use a person's name during conversation or negotiation.
- When meeting someone for the first time or only occasionally, shake the person's hand and make eye contact.
- Being effective architect -> Make more time for the development team -> Control meetings
- "The most important single ingredient in the formula of success is knowing how to get along with people." (Theodore Roosevelt)
Chapter 24 - Developing a Career Path
- An architect must continue to learn throughout their career as the technology changes at a fast pace.
- Keep an eye out for relevant resources, both technology and business.
- 20-minute rule
- Devote at least 20 minutes a day to your career by learning something new or diving deeper into a specific topic.
- Some example resources: InfoQ, DZone Refcardz, ThoughtWorks Technology Radar
- Recommended to leverage the 20-minute rule first thing in the morning.
- Assess a personal radar
- Suggested quadrants for personal use:
- Hold: Not only technologies and techniques to avoid, but also habits you're trying to break.
- Assess: Promising technologies that you have heard good things about but haven't time to assess for yourself
- Trial: Active research and development
- Adopt: The new things you're most excited about
- Suggested quadrants for personal use:
Links
- Architecture Katas
- Software Architecture Monday by Mark Richards
Other potential resources for system design and architecture
No comments:
Post a Comment