5 Software Architecture

Learn how software architecture organizes systems, how architectural styles and component boundaries shape a design, and how to evaluate quality goals and trade-offs.

Architecture and stakeholder views

connects stakeholder needs to a design that can be built and operated. It defines the system’s major components, how they interact, constraints on those interactions, and the reasoning behind important decisions.

An architecture description can present different views for different stakeholder concerns. For example, developers may use a module view, while operators may use a deployment view.

Architectural styles

An is a recurring way of organizing components and their interactions. Styles provide useful starting points, but each has characteristic benefits and limitations; the appropriate choice depends on the system’s requirements. Styles can also be combined. For example, a system may be layered internally while its user interface communicates with a backend using a client–server arrangement.

  • Layered: Organizes responsibilities into levels, such as presentation, application logic, and data access. Layers can make responsibilities easier to understand and change independently. Restrictions on which layers may call others help preserve the structure; bypasses can weaken it.

  • Client–server: Clients request services from servers. This supports centralized service provision, but clients may depend on server availability and network performance.

  • Pipe-and-filter: Independent filters transform data and pass results through pipes. This suits sequences of data-processing steps. Filters are easier to reuse when they do not depend on shared state or on the identity of other filters.

  • Event-driven (publish–subscribe): Producers publish events that consumers handle. This can reduce direct dependencies between components, but makes event ordering, tracing, and failure handling more complex.

  • Service-oriented or microservices: Capabilities are provided by separately deployable services. Independent deployment and scaling may be useful, but network communication, distributed data, and operational complexity introduce additional costs.

Decomposing a system

divides a system into components or subsystems with defined responsibilities and interfaces. Decomposition is useful when each part has a clear purpose and interactions remain understandable. Two common design goals are , where related responsibilities belong together, and , where a change in one component requires few changes elsewhere.

A practical decomposition process is:

  1. Identify the system’s principal capabilities and important external interfaces.

  2. Group related responsibilities into candidate components.

  3. Define each component’s inputs, outputs, data ownership, and dependencies.

  4. Check whether the boundaries support important quality goals, including security, performance, and modifiability.

  5. Revise boundaries if a component accumulates unrelated responsibilities or many other components depend on its internals.

An online store might separate catalog, ordering, and payment responsibilities. If these are separated into independently communicating services, the design must also handle network failures and coordinate data changes across boundaries. A modular single application can avoid some distributed-system overhead, though separate parts may be harder to scale or deploy independently.

and scenarios

describe how well a system performs important behaviors or meets operational needs, rather than what features it provides. Common examples include:

  • Performance: Response time, throughput, and resource use.

  • Availability and reliability: Whether the system continues to provide correct service over time, including during failures.

  • Security: Protection of information and operations from unauthorized access or misuse.

  • Modifiability: The effort and risk involved in making a change.

  • Scalability: The ability to handle increased workload or users.

  • Usability: How effectively intended users can accomplish their tasks.

Make quality needs concrete with a . For example: “When traffic reaches 5,000 requests per second, 95% of catalog searches complete within 300 milliseconds.” This measurable scenario helps compare candidate designs and later test whether the system meets its goal. Quality requirements strongly influence architecture, so they should be considered before implementation rather than left to code-level optimization alone.

Evaluating architectural trade-offs

Quality goals can conflict, so an may be necessary. Adding replicas may improve availability and capacity while increasing infrastructure cost and the need to keep data consistent. Service boundaries may support independent deployment but add network latency and operational work. Tight access controls can strengthen security while complicating user flows or increasing processing overhead. There is rarely a design that maximizes every quality attribute at once.

Make trade-offs explicit by identifying the stakeholder goal, comparing options, noting benefits and costs, and recording important assumptions and risks. The provides a structured evaluation of how architectural decisions affect multiple quality goals. It helps identify risks, sensitive design choices, and trade-off points.