Software Architecture

Nick Gibbon
Pareture
18 min readAug 17, 2022

--

Software Architecture and Design Overview

Intro

Engineering is where we solve problems by designing and building solutions.

Architecture is part of the engineering process where we think about the composition of systems. Particularly how systems are internally and externally structured and how they relate to each other. What components are needed? How will these parts fit together to achieve the goals of the product?

Software Engineering is a young field that is establishing it’s own standards and definitions. Software Architecture is a part of that and so it is tricky to pin down exactly but common themes are becoming clearly established in the area.

Architecture and Design

Design is about planning and specifying to enable the generation of some desired tangible outcome (objects, processes, events etc.). All Architecture is Design but not all Design is Architecture.

Here are some of the most common views that come up from researching the definition[0]:

  • Architecture is What and Where. Design is How.
  • Architecture is Strategic. Design is Tactical.
  • Architecture is Logical. Design is Physical.
  • Architecture is Global. Design is Local.
  • Architecture is a Skeleton / Blueprint / Guardrails. Design is more Concrete and Detailed.

These sentiments do represent clear themes. But I also see conflicts and wooly-ness. Both Architecture and Design are logical / conceptual. I see Design as Physical as an anti-pattern. Many sources consider technology, language and framework choices as architectural decisions. I feel this is very much How something will be done. I like the consideration of locality. Can a change be made independently of everything else? But I also think that we can make strategic local decisions.

An important takeaway from these views is to see them, understand they are imperfect and not to be too zealous. This is good general advice for lots of topics.

The value to be derived is that is that it is very important to consider and present complex systems at different levels of abstraction.

For a hypothetical new feature that we know will require changes in multiple independent systems we can start very abstractly by just presenting the new requirement and capturing that as a result we need to get this specific new data from the user and that will need to be persisted and then used in some way.

We need to get a bit less abstract for real value. With the help of others these vague data requirements and flows need to become pathways between existing or yet-to-exist systems with clear external interfaces and data models.

Once this is accomplished component designs can be created or adjusted in isolation and these can be more detailed.

Anti-pattern #1: Too Low Level Designs

Design is here to guide decision-making and provide constraints. Think patterns, interfaces, organisation, algorithms, models and important notes.

When we go too low level in design then we are basically coding without testing or getting feedback (low quality) and creating a separate artefact that must be maintained and updated that is at very high risk of drift and causing confusion.

Designs are here to help not hinder. If a Design looks like a very detailed implementation plan then we need to step back and simplify things and focus on what is most important.

Remember that prototyping, spiking and iteration through actual coding can and should always be part of the design process. But in these cases write the actual code, run it, test it and provide fast-feedback of the outcomes. Don’t write the code inside a Design Document.

Layers and Models

A picture is worth a 1,000 words.

Architecture and Design are synonymous with visual representation. Across many disciplines we use models to make the problem domain more accessible. They improve comprehension and learning and lead to a better shared understanding and mental-model for the people involved. Models also make it easier to view clear issues or problems early where they are cheapest to resolve.

In Software we use 2D drawings to represent our systems in different ways. The Unified Modeling Language (UML) is the most well-known system that provides standards for several different diagrams with different semantics that can be used. I often see UML-adjacent representations used which are slightly less formal.

Anti-pattern #2: Too Many Models

Models are here for clarity and learning. There are many, many ways we can visualise a complex system and it is quite harmful to use too many. This creates more artefacts which need to be maintained and ultimately causes confusion. Models are very powerful and can be used to help with any design but they must be used wisely and with restraint. If a component design includes pseudo-code, a class diagram, a sequence diagram, a component diagram and an activity diagram then we need to step back and reconsider.

Anti-pattern #3: Too Busy Designs — The Right Level Of Abstraction — Don’t Repeat Yourself

As mentioned, finding the right level of abstraction to communicate is key. The basics of this is to have an overarching higher-level design along with slightly lower-level component designs. But often more higher-level designs will be needed. A very common case for this is where the middleware layer breaks down into many independent micro-services, brokers and a gateway service which needs it’s own high-level representation.

We want each part of the design to be focused and clear and this can only be achieved by breaking it up in the right way and having the Designs link and reference each other. Embedding models from a higher level into the lower level can work well if possible. This linking does create some overhead and complexity in it’s self but it is better than the alternative where we try to stack every aspect of the system into a single ultra-packed space.

If we are focusing on a core functional flow between systems then that needs to take centre stage. Often systems will be supported by infrastructure, platforms and tools but this needs to be referenced not repeated. We can not and should not squeeze the networking information into every model. Keep Designs DRY!

Cross-cutting concerns such as observability and tracing requirements or security flows between systems can be represented in isolated supporting Designs.

Finally we must consider scope. Is an architectural project trying to do too much at once? Are there elements which feel odd to the teams working on it? Should it be split up? It is better to do three things well and obtain incremental value and learn along the way than treat those three things as one thing and fail. It would be nice to just have the organisational objective be; “Make technology better and make more profit!”; but alas we need to refine these things further.

For these cases we can go a level higher and create an Architecture Case which is a program of work to achieve a loftier goal. It’s Architecture and Design all the way (up and) down.

Fundamental Architecture and Design Process

The fundamental architecture and design process is deliberate architecture. All systems, processes and organisations have an architecture whether they like it or not — just some were accidental. The architecture and design process is the basic framework for making technical decisions and seeing them through.

  1. Problem: Have a clear problem that needs solving.
  2. Design: Create a proposal for a solution considering many aspects of the problem.
  3. Discuss: Democratise, make the design visible, share, get feedback and work on changing the design to be more suitable and answering outstanding questions.
  4. Create: Coordinate execution and implementation.
  5. Iterate: Continually evaluate and discuss with stakeholders, solve problems and maintain the designs as problems arise and adjustments are needed.

The process is fundamentally very simple. The complexity comes from the problems themselves and the continuous collaboration required to keep things moving in the right direction.

Why Do Architecture And Design At All?

The vehicle of architecture and design is the Design Document. Thinking about what goes into this and how it’s composed is very important. But before we go on to that we need to consider why we would follow the architecture process or create design documents at all. What is the value?

Assuming we have sensible organisational design, teams with good engineers and capacity for work why can’t we just leave engineers to get on with it and solve problems. After all there is some significant overhead to the design process.

In the case of decisions that span multiple teams then it is obvious that additional overhead is absolutely needed for effective coordination. The case for deliberate architecture and design is strong enough in the single team case that explaining that should be sufficient.

For a significant technical project there are too many aspects and concerns to be maintained in one head on the fly. Concerns need to be inventoried and addressed. If they are not then there is a high risk of some quality issue. If they are then why not make it visible for others.

Individual engineers often don’t have all of the context needed which can lead to poor decisions. If they are very diligent in obtaining information from all of the places and people they ought to then it would always be better for this information to be shared with the team and not private.

Of course we will always miss things and mistakes will be made with hindsight but it is better to make these mistakes together. When we are making decisions unilaterally and something undesired moves forward it is more awkward and uncomfortable to stop it. If it gets implemented then it can be difficult to work with and it may eventually be redone. This is inefficient. We want to discount negative options early if at all possible. The designer still has significant ownership of the solution. They just need to address concerns more strongly or adjust designs according to feedback.

Ultimately individual engineers don’t support, maintain and evolve systems. Teams do. Teams therefor need visibility and the option of input into significant decisions. Even in the case that the team are happy with everything about the approach then the Design Document its self is important. It is a reference point to guide future decisions by understanding the past and it is a learning opportunity for everyone in the team. Central Designs which are updated based on feedback enable alignment between many parties that doesn’t depend on being in a specific meeting or part of a specific conversation or reverse-engineering what is going on from code.

Finally if there is significant disagreement on what should be done then design documents provide the opportunity to disagree and commit. Things need to progress so a decision gets made and we roll with it.

The fundamental architecture and design process helps to foster a culture of deliberation, care, quality, rigour, transparency, visibility, collaboration, ownership, learning and efficiency.

Design Documents

Design Docs (DD), Technical Decision Documents (TDD), Key Decision Documents (KDD), Request For Comments (RFC).

Adhering to a design process is a practise used by many successful technology organisations. Google is well known for using Design Docs. This section is informed by my own experience and by the the post Design Docs At Google by Malte Ubl in his blog Industrial Empathy[1]. If you read this post and Malte’s writing you should get a good gist of what you might want to include in your own Design Documents.

Purpose of a Design Document

The purpose is to share intentions and reasoning, get feedback and make good decisions in a highly visible way. The purpose is not to simply have another document to maintain. It is not an admin tick box. It does not have to be super formal and Design Documents are not at all always necessary.

A Design Document is a living document that needs to be maintained and updated as decisions are made.

When To Create A Design Document

  • When work will affect, span or impact multiple teams.
  • When work will affect a high proportion of users.
  • When you want feedback from some specific stakeholder groups.
  • When you know that the outcome will be difficult to change.
  • When work will take longer than a month to complete.
  • When work will take 2+ people to complete.
  • When something feels novel.
  • When there is uncertainty. Going through the design process can highlight this and be used as a vehicle to obtain clarity.
  • If it simply feels big or important.

Where To Store Them

Designs need to be highly visible and easily accessible. They need to be stored in some orderly manner. Every team and every department needs a place where anyone in that organisation can contribute a Design and everyone in the team or organisation knows where it is.

Goals

The goals of the project. The Why. There needs to be a clear problem or requirement and evidence for this. What does the solution need to solve. A feature we want to give to a user, a gap in technical capability, an inefficiency that is harming us. It should be clear why we are undertaking this effort and who it will be benefiting in a positive way. If this is not clear then the project needs to stop here until it can be articulated clearly.

Background

By background you can provide useful context for the problem. This might include a history of decisions that have got to this point or anything else that might be relevant.

As-Is

It is important to understand and record the current process or state of the system as it is now. This make it more clear exactly what might need to change.

Scope

What is in scope of the project what is not in scope of the project. It is important to mention things which are related but are intentionally being left out of the project. We need bounds.

Principles

Are there any principles particularly important to this project? Perhaps link to a central principles document. For example prefer familiar technology can be a god heuristic to technical decisions. Breaking this would require that the new technology provides something special or unique.

Constraints

What requirements of this project are hard barriers which must be considered. For example can not use any third-party PaaS or SaaS due to specific regulation.

Timeline

Are there any deadlines or contingent events that the project needs to be oriented around?

Success Measurement

What does success mean to this project. Can we define metrics that can be tracked in advance to focus our efforts.

NFRs

Add information about Non-Functional Requirements which support the primary project objectives and may impact the design. Capacity, reliability, security etc[2].

Options

This section will always look different. It is where you put alternative strategies or options that can solve the problem. You will include various important details and models to try to make the solution clear. Each option should have trade-offs. What are the positives? What are the negatives? What does it not give you that another option could?

In the end these technical decisions come down to a cost benefit analysis between options.

Outstanding Information

This is where you note gaps in knowledge and information that you or others have. This section results in actions that need to be performed and then the outcome is updated here. It could be research, discovery or proof-of-concepts for example. It could just be asking someone a question.

Related Designs

Links to other related designs. This allows the right level of abstraction to be used in individual designs and holds focus. This could be supporting designs or parent designs.

Resources

Links to references and resources used in the design in some way.

Architecture Patterns

Jim Keller is a legendary Microprocessor Engineer who has worked over the past 40 years at organisations including DEC, AMD, Apple, Tesla and Intel. He is currently the CTO of Tenstorrent. One way he defines engineering is as the “Reduction to practise of known Methods”[3].

Architecture patterns are a good example of Keller’s Engineering. Architecture patterns are known technical strategies that can be used to solve common technical problems. They are established through research and hard-won industry knowledge.

Patterns enable teams and organisations to utilise the principle of not reinventing the wheel by resolving or consciously avoiding identifiable classes of issues. Typically we mean known industrial technology patterns but we could also be referring to the reuse of patterns which have been successful with other projects inside the organisation.

Patterns also help with alignment and communication as the concepts are often well-articulated externally or internally. People can learn about the pattern and then use the pattern name as short-hand for the more complex underlying strategy.

Here is an absolutely non-exhaustive list of some common architecture patterns[4,5,6]:

  • Model View Controller (MVC)
  • Microservices
  • The Strangler
  • Event-driven
  • Blackboard
  • Pub-sub
  • API Gateway
  • Circuit Breaker

The Architect

Architecture is always relevant all over the stack. If you have significant ownership, input into system structure and utilise the fundamental architecture and design process described then you can happily consider yourself an architect in your domain.

Specialist Architects are particularly important when work spans or impacts several different teams and when ensuring successful (clean / nice) integrations between components.

Skills

When specialising as an Architect you must already be a Senior Engineer where you can independently technically handle vague and complex situations. It may be appropriate for you to help out with Spikes or POCs.

You will certainly want to focus on technical width across several domains so that you can be effective working with multiple teams and technologies. You will be constantly learning and need to be excited by this prospect. You must remain curious and be versatile.

Leading big architecture projects fundamentally means that you will be working with lots of stakeholders. Various people, teams, managers and leaders. You will need to develop great communication skills and collaboration techniques to enable that all-important alignment between parties. Variety of past experience and wisdom can help you steer the ship in strange or complex situations (this is never a junior role). As will elements of your attitude such as positivity and patience. You will be herding cats at times and need to avoid frustration.

You must be humble as you will consistently be working with people who have much better knowledge than yourself of various systems and domains and you need to work with them to get the right information to iterate, improve designs and move projects in the right direction.

If the organisational objectives give us Why. And following the fundamental architecture and design process will give us What, Where and How. Then we are still missing Who and When! Right? As the owner of the overall solution it falls to the Architect to help ensure the parties schedule required work at the right times and the project proceeds with the right priority level. For this you need more patience and empathy for the pressures involved. But you also need to be savvy and persistent and use your relationships to keep things going.

As an Architect you will need to continually step-back and consider the System as a whole. Are we still hyper-focused on the organisational objectives and NFRs. Is the whole system still efficient? Are any interventions needed You need to be diligent and quality-oriented to ensure that no issues slip through the cracks between teams. This blend of System and Product Thinking is very important for an Architect.

Finally you need to enjoy this whole process so that you can perform well and grow in the Architect Role.

Anti-pattern #4: Ivory Tower Architecture

In any situation the work of an Architect is inherently complex because if it were not then there would be no need for the specialised role in the first place. If we consider the skills and areas needed for good architecture examined so far then the potential pitfalls crystallise.

The Ivory Tower Architect is the most common negative Architect stereotype. Where an individual designs a solution and gives it to teams to implement. The solution is detached from reality or over-prescribed or too many assumptions or decisions are made in the early phases of high-level Architecture and Design without consultation. Teams will struggle with it before making independent and uncoordinated changes. Chaos and negative outcomes ensue.

We mitigate this by:

  • Centralising important information and making it visible via the fundamental architecture and design process.
  • Being humble and understanding the role of the Architect is not to know everything but to learn with the team, iterate and progress.
  • Shifting collaboration with experts and domain leaders left so they can input and feedback on proposals and we can work out what we don’t know yet and need to find out. This also makes important stakeholders feel included and enthusiastic about a project.
  • Ensuring the Architect is constantly involved throughout execution.

Architecture is not a detached discipline. Quite the opposite. Each part of the System needs to be continually considered and cared for to provide the best chances of success and avoid entropy in that area.

TOGAF

TOGAF stands for The Open Group Architecture Framework. It is an Industry Standard Enterprise Architecture Framework[7,8]. I believe this is the most well-known central set of structured architecture information and would be worth the investment of some further enquiry and learning.

They provide a knowledge-based and experience-based certification program and recognise 4 different types of Architect:

  • Business Architect
  • Digital Architect
  • Enterprise Architect
  • Solution Architect

Cloud Architecture Certification

The best way to improve in this area is to seek opportunities to play a role in the fundamental architecture and design process that has been described. It’s also important to actively seek architecture knowledge outside of our organisations to give us a wider toolset.

If we are interested in formal learning and certification I believe that (along with TOGAF) the architecture programs by the big cloud providers are effective. They teach people about the cloud and architecture in general as well as applied to their specific platforms and products.

AWS[9]

  1. Cloud Practitioner — Foundational
  2. Solutions Architect — Associate
  3. Solutions Architect — Professional

Azure[10]

  1. Azure Fundamentals — Fundamentals
  2. Administrator — Associate
  3. Solutions Architect — Expert

GCP[11]

  1. Cloud Digital Leader — Foundational
  2. Cloud Engineer — Associate
  3. Cloud Architect — Professional

AWS focuses on it’s Well-Architected Framework for Infrastructure Architecture oriented around 6 pillars[12]:

  1. Operational Excellence
  2. Security
  3. Reliability
  4. Performance Efficiency
  5. Cost Optimisation
  6. Sustainability

Help with these journeys is widely available online as all of the cloud providers have healthy community support along with official resources.

Perspectives

Fred Brooks (1975)[13]:

“I will contend that conceptual integrity is the most important consideration in system design. It is better to have a system omit certain anomalous features and improvements, but to reflect one set of design ideas, than to have one that contains many good but independent and uncoordinated ideas.”

“Today I Am More Convinced Than Ever. Conceptual Integrity Is Central To Product Quality. Having A System Architect Is The Most Important Single Step Toward Conceptual Integrity.”

Allan Kelly[14]:

“More than ever I believe that someone who claims to be an Architect needs both technical and social skills, they need to understand people and work within the social framework. They also need a remit that is broader than pure technology — they need to have a say in organizational structures and personnel issues, i.e. they need to be a manager too.”

Martin fowler and Ralph Johnson[15]:

“Architecture is about the important stuff. Whatever that is.”

Dave Farley[16]:

“Architecture has to be an evolutionary process.”

“Good architecture allows us to isolate one part of the problem from another.”

Stefan Tilkov thinks that architecture needs to be “good enough”[17]. Over-engineering and under-engineering are both anti-patterns and there is an art in finding the sweet spot.

Grady Booch[18]:

“Architecture represents the significant design decisions that shape the form and function of a system, where significant is measured by the cost of change. Every software-intensive system has an architecture: some are intentional; a few are accidental; most are emergent. All meaningful architecture springs from a living, vibrant process of deliberation, design, and decision.”

Will Larson identities The Architect as a Staff Engineering Archetype[19].

“The Architect is responsible for the direction, quality, and approach within a critical area. They combine in-depth knowledge of technical constraints, user needs, and organization level leadership.”

Kevlin Henney thinks that good architecture is about details[20]. Details are crucially important. What if an assumption was incorrect? What if it turns out we can not execute on a planned architecture due to the current underlying networking? Can we change the networking? Do we need to adjust the architecture? What are the trade-offs and implications? Details matter. We all have some experience of where something has been left as an implementation detail and it comes back to cause great pain in the future. Architecture is about trying to identify the details that will matter as early as possible and effectively handling situations where details have slipped through the net.

Outro

This post blends my own experience and thinking with various industry experts but is absolutely non-exhaustive in views on the subject. I hope it can stand as a useful summary for others who are interested.

Please go on and read the resources that I have used throughout this post for great insights into the topic of Software Architecture and Design!

Resources

--

--

Nick Gibbon
Pareture

Software reliability engineer & manager in cloud infrastructure, platforms & tools.