Chapter 1 Introduction
Programmers know the benefits of everything and the tradeoffs of nothing. Architects have to understand both! - Rich Hickey1
System architecture defines how a system is composed of individual components. It describes the interfaces of how the components are connected with each other and the process of their interactions and collaborations. Therefore, the central concern of system architecture are the issues of structuring and modularisation. The basic unit is the one of a component which is a clearly delimited part of the system. Such a component is described through externally observable properties, for example input/output interfaces. In theory, such a component should be replacable through another component, which also implements the given contract, specified through the interfaces, see Figure 1.1 for a simple UML component diagram.
In Figure 1.2 we see a simple case of a system structure. This nesting of components is the essence of system architecture and the larger a system, the more layers of abstraction are introduced to deal with complexity2
In general, there is the distinction between lower levels of the architecture and higher levels of abstraction. The lower level (Components A,B,C in Figure 1.2) are commonly known as Software Design or Micro Architecture. The upper level (Component 1 and 2 in Figure 1.1) are simply known as Architecture or more explicitly as Macro Architecture. The structures built on these principles should support:
- Development and maintenance of single components without side effects and coordinating effort.
- Document and understand single components independent from the rest of the system.
- Test single components isolated through ther input/output interfaces.
- Replace a component with another component.
This leads to the effect that if a software runs into problems for example with stability and maintainability, this will affect always only a certain part of the system and not the whole, given careful modularisation. Software of a certain size runs into existential problems if it does not exhibit certain structuring, modularisation and architecture.
In general, a system architecture has direct consequences for non-functional requirements in a software project: only with a certain software architecture can certain non-functional requirements be achieved. Non-functional requirements directly affected by software architectures are generally:
- Maintainability (changeability, extensibility, replaceability)
- Relibability (stability, recovery)
- Performance (speed, efficiency, response time)
Maintainability can be assumed to be the most important one as it allows for future changes, which is especially important in an agile setting. The key to maintainability is low coupling and high cohesion, which is generally achieved by splitting up the software into components.
- It’s gonna work! Weaknesses and critiques of an architecture are ignored and dismissed with it will work. This attitude enforces a culture where functional requirements dominate and non-functional requirements are neglected and ignored.
- Enterprise vs. Macro Architecture These two terms are often used interchangeably, however they are not. Enterprise Architecture applies architecture principles and practices to guide organisations through their process. Macro Architecture on the other hand is on a higher abstraction level and deals with general architectural decisions, independent from the context, be it business, information, finance or real time domains.
- Scrum Scrum or other agile methods are often used as excuse to avoid doing any architectural work, neglecting non-functional requirements, modularisation and just code. However, this is not true, these activities are now just distributed onto multiple iterations. The good thing of agile methods is that problems with architecture are identified much earlier than in other processes.
- Unification If there are problems in a large architectural landscape, often the attempt is for more unification. However, this will lead to more dependencies, requiring more coordination, leading to reduced productivity. Therefore the architecture should be split into functional parts, to reduce the dependencies and coordination between teams.
- Big-Bang Migration Tries to solve all architectural problems by a new big-bang migration project. Given a sufficient large system this is deemed to fail and the only alternative is to refactor and adapt structures over time.
- Architecture vs. Technology Architecture is not about using, mastering and integrating a myriad of technologies (Hibernate, JavaRX, Akka, and other libraries and frameworks) but in its heart it is about building of structures and managing their dependencies. Yes, technologies are an important way to achieve this but deal only with the how, not with the what which is what architecture should answer.
- Ivory Tower In this pitfall, guidelines are created which go too far and limit teams, leading to excessive unification. In this case architecture becomes and end in itself (Selbstzweck). In this situation technical elegance and cleanliness has become the main goal and does not serve any user, stakeholder or business value.
- Perfectionism Software architecture cannot be perfect and is always about making reasonable compromises between technical debt and time.
Software Architecture is not about selecting technologies (Frameworks, Code Libraries, …) and development. An architect is not a senior or lead developer: although most architectures are good developers, a good developer is not necessarily a good architect. Developers should excell in micro architectures (Design) with detailed knowledge about individual technologies. An architect should have a broad overview.
As software architecture is a highly complex issue, with a broad range of patterns, best practices and concepts, it is very difficult or impossible in general to make statements which have general validity. In software architecture a lot depends on the domain and the problem and there is no silver bullet. Things might not be clear in the beginning, situations are different, teams have different qualification, leading to a lot of complexity which makes it impossible to have exact measures of efficiency.
Therefore the most general advice can only be to avoid dogmatism, adapt constantly, question established patterns and experiment. The only constant is change - architectural patterns of today can become anti patterns of tomorrow in an instant.
This chapter is based on material from .
 Herbert Dowalil. 2018. Grundlagen des modularen softwareentwurfs: Der bau langlebiger mikro- und makro-architekturen wie microservices und soa 2.0. Hanser Verlag, München.