Introduction
I have previously blogged about the book Software Architecture for Developers by Simon Brown, where he breaks Software architecture into structure and vision. I want to extend the definition of software architecture with the 4 pillars introduced in the book Fundamentals of Software Architecture: An Engineering Approach by Neil Ford and Mark Richards. The pillars are:
- Structure
- Architecture decisions
- Architecture Characteristics
- Design principles
Structure
Neil and Mark define structure much the same way as Simon Brown does, but with adding a reference to the type of architecture style used as well, e.g., microservices, layered, or microkernel. Overall, the structure of software architecture refers to the way in which the system is organized or partitioned. It's about dividing the software into different components or bigger modules and defining how these parts interact with each other. This structure helps to manage complexity, as each component can be understood in isolation, and changes can be made to one part without affecting others. It provides a roadmap for developers, making it easier to understand where certain functionalities should be implemented. Furthermore, a well-defined structure can enhance the maintainability of the system. The structure is typically what most people think about when discussing software architecture, with drawings of boxes and arrows. Hopefully, I will use some kind of well-known notation, e.g., C4 from Simon Brown.
Architecture Decisions
Neil and Mark define Architecture decisions as rules for how a system should be constructed. Examples are:
- We want to utilize private endpoints and avoid public exposure as much as possible
- Complex subsystems should have a core without dependencies on external libraries
One way to document and bring clarity to architectural decisions is to use architecture decision records (ADRs). I am, currently leaning more towards and following Google's definition, where ADRs are more specific:
- Specific product choices, such as the choice between Pub/Sub and Pub/Sub Lite.
- Specific product options and configurations, such as the use of regional GKE clusters with Multi Cluster Ingress for highly available applications.
- General architectural guidance, such as best practices for Dockerfile manifests.
- The use of Azure Container Registry Cache to reduce dependencies
The ADRs bring clarity to the most important questions when introducing a new component, technique, pattern or technology, i.e., what and why were they introduced.
Architecture Characteristics
Architecture characteristics refer to the -ilities that the systems must support, e.g.:
- Availability
- Reliability
- Security
These are typically the non-functional requirements. The architect and team need to be specific about what kind of tradeoffs and parts of the architecture to prioritise. I have been on a project with a clear emphasis on reliability from the end customers’ point of view. Under no circumstances should the end customer see or find out about a bug. That obviously added a great toll on the development, testing, and speed at which we could develop software and how the architecture is in terms of High Availability and failover. We informed the customer about the consequences and tradeoffs.
Neil and Mark define architecture characteristics more specifically as the success criteria of a system, which is generally orthogonal to the functionality of the system.
Design Principles
Design principles define the guidelines. What guides the developers when choosing technology/pattern/structure A over option B. Architectural decisions are hard rules, and design principles are guidelines. ADRs will never be able to cover all technologies and decisions that need to be made. Examples of design principles are:
- We emphasize continuous integration and continuous delivery on all deliverables
- Readability over automation, although we like automation
- Day 2 operations, over how easy it is to get started
- Asynchronous messages between systems over temporal coupling
Tips
- When making these architectural decisions or principles, make it very clear to the development team that these are decisions that are made in a joint venture. However, ultimately, the responsibility lies on the architect and, as a consequence, the final decision when there are disagreements.
- Be aware of the ivory tower architect antipattern
- Create the ADRs and design principles in markdown and use PRs as one of the feedback points.
Conclusion
In conclusion, software architecture is a multifaceted domain that extends far beyond just the structure of a system. It encompasses hard rules in the form of architectural decisions, the non-functional requirements expressed as architectural characteristics, and the guidelines outlined by design principles. Understanding these four dimensions of software architecture allows for the creation of more robust, efficient, and maintainable systems. It also ensures that the team aligns on the priorities and trade-offs necessary to meet the specific requirements of a project. Ultimately, a well-architected system can greatly enhance the overall software development process, from initial development to maintenance and future enhancements.