Evolutionary Architecture – Rebecca Parsons

What does good look like? What are characteristics are good, what characteristics are bad?

Design and Architecture – Big ‘A’ Architecture. How do different parts of the system communicate with each other. What is our security? What is our persistence strategy? Design are things that are closer to the code. How the system interacts with devices is Architecture.

What are the principles of Evolutionary Architecture?

  1. Last responsible Moment
    • Delay decisions as long as you can, but no longer
    • Maximizes the information you have
    • Minimizes technical debt from complexity
    • Decide early what your drivers are, and prioritize decisions accordingly
    • Evolutionary, neither emergent nor based on guesswork
  2. Architect and develop for evolvability
    • Sensible breakdown of functionality
    • Consider data lifecycle and ownership
      • Who has access to it
      • How long should we keep it.
    • Appropriate coupling
      • Coupling is inevitable
        • Two systems that must communicate, there has to be coupling.
    • Lightweight tooling and documentation
    • Develop for Evolvability
      • Software internal quality metrics focusing on each of change
        • You don’t want to optimize for understanding code, you want to optimize for understanding code
        • OnceI have these metrics, how to I focus my attention on making a piece of code more evolable.
        • Look for change hotspots
        • Measure continually, focus on trends.
          • Gives visibility into changes and software evolution
    • Reversibility
      • Change that decision later down the road.
  3. Postel’s Law
    • How systems communicate with each other.
    • Be conservative in what you send, if you put it out there people will use it, because you are now committed.
    • Be liberal in what you receive. If you only want a phone number, but receive the entire address. Only validate the phone number. You don’t want to be sensitive to changes that don’t impact you.
    • Use version numbering when you have to break a contract.
  4. Architect for testability
    • If you think about testability in your architecture, the side effect is a well architected system. Things that tend to make your system hard to tests also tend to make it hard to change and maintain.
    • Single Responsibility Principle – Example: Messaging infrastructure used for messaging, not business logic. Testing business logic embedded in Messaging is hard. Separate the two and test business logic outside the message infrastructure.
    • Map your business components to the business concepts. When the business requests changes, in a business concept if your components are similarly mapped the change will be less impactful.
    • Automated build and deployments is an essential underpinning
  5. Conway’s Law
    • Organizations design system reflecting their communication structures
    • Broken communications imply complex integration
    • Silos often result in broken communication
    • If you don’t want your product to look like your organization, change your organization (or your product)

Techniques for implementing evolutionary architecture

  • Database Refactoring
    • Decompose big change into series of small changes
    • Each change is a refactoring/migration pair(or triple of you include access code)
      • This should be easy, but data gets dirty overtime making it difficult.
    • Changes compose in the same way functions compose
    • And of course, version control the changes
    • And apply in the various environments during promotion
  • Continuous Delivery
    • Automate environments and configuration
      • Is the underpinning that makes everything works.
    • Automate builds and deployments and use continuous integration
    • Automate testing at all levels
    • Deployments should be boring!!
    • Just because you CAN release at any time, doesn’t mean you HAVE to
  • Choreography
    • How different parts of the system works together as opposed to orchestration
    • Scripted outcomes and vision
    • Individuals perform to the vision without a conductor
    • Distributes authority about interactions
    • Introduces new kinds of failure scenarios
  • Contract Testing
    • Acceptance tests at the systems interface
    • Documents assumptions made
    • Maximizes parallel independent work
    • Used in congestion with Postel’s Law
    • One traditional role of Enterprise Architect

Evolutionary Architecture

  • Define your architectural fitness function
    • Must think about this upfront
      • What is most important to you
        • What is your security threat landscape?
        • What are your scaling requirements?
        • What are your performance requirements?
        • What are the things you can’t compromise on?
  • Delay your decisions as long as you can
  • Understand various forms of technical debt
  • Implement evidence based re-use.
  • Create and maintain the testing safety net

Book Recommendations

  • Patterns of Enterprise Architecture
  • Enterprise integration PAtterns
  • Craft of being a Architecture
  • Data Architecture

Rebecca Parsons – Publishing a book on

Technical debt is some drag on your development process because of some technical issue.

Uncoupling – Micheal Nygard

Coupling is the difficulty when changing things.

Tensegrity – Holds it self together by the tension among parts and the resistant tension from the beams. It’s a nest of opposing forces.

Coupling is everywhere. We are coupled to the Earth. The Earth is coupled to the Sun. The solar system is coupled to the Milky Way. The same is true if we go to the atomic level.

Coupling defines the degrees of freedom. It constrains and enables some movement. It also connects effects.

Everything is coupled to everything

  • ambient temperature
  • ambient atmosphere
  • acoustic vibrations
  • Electromagnetic field
  • Gravity
  • Higgs field
Type Effect
Operational Consumer cannot run without the provider
Development Changes in producers and consumers must be coordinated
Semantic Change together because of shared concepts
Functional Change together because of shared responsibility
Incidental Change together for no good reason (e.g., breaking API changes.)

A shared concept is an idea that is exposed/implemented in one of area of the system. And then other consumers (external or internal) must embrace the concept to consume the resource. However, if the concept is flawed, that flaw proliferates throughout the system.

System Diagrams – Long Arrows

  • Arrows connecting two systems is actually hiding a number of moving parts
    • Extract tables to files
    • Push files across network
    • Load data into database
    • etc…
  • Architecture Qualities in Long Chains
    • Latency strictly warse than the slowest link in the chain
    • Availability strictly worse than the least available link
    • Throughput strictly worse than the throughput of the worst bottleneck
    • Security strictly worse than the security of the weakest link
  • Digging Out – Information Hiding (Decision Hiding)
    • On the Criteria to be used in Composing Systems into Modules – David Parness

Composing Interfaces

A smaller number of well defined interfaces is preferable over more interfaces and small number of concise datatypes is preferable over more datatypes.

Composiblity

  • Inversely proportional to the # of interfaces
  • Inversely proportional to the # of data types

Uncoupling

Orthogonality in Software

  • separation of concerns
  • High cohesion within a module or component
  • low coupling between modules or components
  • little overlap in functionality between modules
  • information hiding / decision hiding

Rotate your perspective 90%

  • When looking at components, think about modules
  • When looking at modules, think about components
  • When looking at data, think about code
  • When looking at code, think about data

Use all your tools

  1. Module structure – layout of your code and libraries
  2. Component structure – interactions between runtime components
  3. Abstraction – Emphasize similar interfaces & data formats

O’Reilly’s Software Architecture – Domain-Driven Design

O’Reilly Learning Course:

Domain Driven Design – Software Architecture

Andrew Harmel-Law

The Heart of Domain-Driven Design

Complexity in Software Tackling complexity is the heart of software. Complexity is in the problem domain, not in our software. We add our own complexity in solving the problem that may or may not be needed. This additional complexity is on us.

Concepts of that are Core to Successful Domain Driven Design

Ubiquitous Language

Domain Experts are developers who can’t code and we are developers who don’t know the domain.

Translation fractures the language between the developer and the business. It’s a mental overhead and things are always lost in translation. If we (the engineering team) and the business have the same understanding and use the same terminology there is no overhead to communication concepts. There is no opportunity to lose meaning in translation. What the point of using two different terms to mean the same thing? Isn’t this idea much like copy and pasting code? They might be the same to start with, but they always diverge over time?

Why are accounts in the banking domain opened and not created?

Respect the domain experts, the domain might seem simple, but once you start talking to the domain experts, it’s not. Domain experts have the solution to one of the hardest problems in Software Development and that’s they names for all the concepts.

Domain experts have a term that succinctly communicates a complex idea?

Are they correcting your word usage?

If so, these are the hints of a complex ideas and the naming to got along with it.

Hands-On Modelers

Developer assumptions get shipped to production and sometimes these assumptions are wrong.

In a typical organization the business domain is documented by a Business Analysis, which records what they think the developers will need. This document is then handed to the Developers. The Developers are reading the Cliff Notes version of the domain problem. This may or may not be the details the developers need to complete their work. Getting the Developers as close to the source of information gives the highest chance of getting the software right.

Engineers working on the model must understand the change they are making and how they are improving the model. If they don’t understand this then they are weakening the model.

Tests verify the facts of your Ubiquitous Language are still true.

Procedural and Data-Centric don’t work for DDD.

Breakthroughs (fine tuning the Ubiquitous Language)

Focus on breakpoints on the Ubiquitous Language. ARea’s of the domain/model that break down and don’t meet the needs of the problem domain.

Tests don’t do this because most of the time you are testing the positive of the assumptions.

Multiple Models

"Bounded Contexts"

A bounded context is an area of the problem domain that had natural or logic borders from other idea’s in a system.

DRY (Don’t Repeat Yourself) doesn’t apply across Bounded Context boundaries. If you do, you are coupling these two Bounded Contexts. The fact that they are two bounded context means they are two different spaces and shouldn’t have overlap. Sharing algothrims is coupling.

If there are truly algorithms that span Bounded Contexts, they should be cross-cutting concerns. For example, working in the financial industry and using financial calculations in multiple Bounded Context is an example of Cross-Cutting concerns.

DRY isn’t about code, it’s not about removing code duplication, but removing duplication of knowledge.

Nested Bounded Contexts aren’t a thing.

Do’s and Don’ts of Error Handling – Joe Armstrong

Systems will fail. You can’t have a resilient single system. Even if internally, the system is rock solid, it can’t contend with all outside variables and will at some point succumb to outside forces.

The basis of object-oriented programming is message passing. If you have two systems that work together, they must pass message between each other. There must be a mechanism to share data. In some systems this is a Database, a Queue, or an API.

  • Some small things can be proven to be self-consistent
  • Large assemblies of small things are impossible of prove correct.
  • Scalability is impossible on one computer
  • Security is very difficult with one computer.

Arithmetic Errors

  • silent and deadly errors – errors where the program doesn’t crash but delivers incorrect results
  • noisy errors
  • errors that cause the program to crash

Silent Programming Errors

  • Why is it silent, because the programmer doesn’t know there is an error.

Rump’s Royal Pain

Rump’s Royal Pain

[Fact]
public void RumpTest()
{
    int x = 77617;
    int y = 33096;

    var value = 333.75 * Math.Pow(y, 6) + Math.Pow(x, 2)*(11 * Math.Pow(x, 2) * Math.Pow(y, 2) - Math.Pow(y, 6) - 121 * Math.Pow(y, 4) - 2) + 5.5 * Math.Pow(y, 8) + x / (2 * y);
}