Chapter 5: Architecture in the Life Cycle
Software architecture is integral to every phase of the software development life cycle (SDLC),
influencing decisions from the initial requirements gathering to design, implementation, and
testing, as well as post-deployment maintenance. This chapter focuses on how architecture
interacts with different stages of the life cycle, including agile projects, requirements, design,
documentation, implementation, testing, and architectural reconstruction.
1. Architecture in Agile Projects
Agile methodologies, such as Scrum or Kanban, emphasize iterative development and flexibility,
which may seem at odds with the structured nature of software architecture. However,
architecture in agile projects plays a crucial role in ensuring that software can evolve while
maintaining a robust design.
Key Considerations for Architecture in Agile:
Evolving Architecture: In agile projects, the architecture evolves incrementally
alongside the development process. Early in the project, the architecture is typically
simple, focusing on just enough design to get started. As the project progresses, the
architecture is refined based on feedback and new requirements.
Emergent Design: Agile encourages emergent design, where the architecture adapts
and evolves over time. Rather than committing to a detailed architecture upfront, agile
teams prefer to make architectural decisions just-in-time, allowing for flexibility.
Continuous Refactoring: Agile projects often require continuous refactoring of the
codebase, which in turn affects the architecture. Teams should make sure that the
architecture allows easy refactoring without breaking critical functionalities.
Collaborative Design: Agile emphasizes close collaboration among team members,
stakeholders, and customers. This interaction is vital in ensuring that architectural
decisions meet the system’s evolving needs.
Minimal Documentation: In agile projects, documentation is kept to a minimum. The
focus is on working software, but important architectural decisions should be documented
in an easily understandable format to help guide future development.
Challenges:
Maintaining technical debt is a concern in agile projects where architecture is
continuously changing. Teams need to ensure that the architecture is not constantly
patched with temporary solutions, leading to instability over time.
2. Architecture and Requirements
Architecture and requirements are closely linked in the software development life cycle. The
architecture is often influenced by both functional and non-functional requirements, which drive
design decisions and help ensure that the system will meet stakeholder expectations.
Key Aspects:
Functional Requirements: These describe what the system must do, i.e., the specific
functions or behaviors the system must provide. The architecture must ensure that the
components of the system can deliver these functionalities effectively.
Non-Functional Requirements (Quality Attributes): These include performance,
scalability, security, and maintainability, which influence how the system is structured.
Non-functional requirements can often drive architectural decisions more significantly
than functional requirements, as they can impact the overall system design, including its
scalability and performance.
Architectural Decisions Based on Requirements: Architectural decisions should be
made early, especially for requirements that significantly influence system behavior, such
as:
o Scalability: How will the system handle increased load?
o Availability: How will the system ensure high uptime and fault tolerance?
o Security: How will data and access be secured?
Changing Requirements: The architecture must be flexible enough to accommodate
changes in requirements, which is especially important in agile projects. The ability to
easily adjust the architecture as requirements evolve is a key factor in maintaining a
successful project.
Balancing Requirements and Architecture:
Trade-offs: Sometimes, non-functional requirements may conflict with one another. For
example, security might reduce performance, or modifiability might increase
complexity. Architects must balance these trade-offs carefully, aligning with project
goals.
3. Designing and Documentation
Designing and documenting software architecture are essential parts of the SDLC, ensuring that
the system’s high-level structure is well understood and can be effectively communicated to all
stakeholders, including developers, testers, and non-technical stakeholders.
Designing Architecture:
High-Level Design: The architecture typically starts with a high-level design, outlining
the system’s major components, their responsibilities, and the relationships between
them.
Modularity and Layers: A good design breaks the system down into modules or layers,
allowing for easier management, development, and testing. Common architectural
patterns include layered architecture, client-server, and microservices.
Component Interaction: The design should also specify how components interact. This
includes the communication protocols, data formats, and dependencies between
components.
Documentation Practices: While agile projects limit extensive documentation, there
should still be sufficient architectural documentation to:
o Help onboard new team members
o Provide a reference for design decisions
o Ensure the architecture aligns with requirements and quality attributes
Types of Documentation:
Architecture Decision Records (ADR): These records document important architectural
decisions, the reasoning behind them, and the potential alternatives considered. ADRs
help maintain consistency and provide a historical record of architectural choices.
Diagrams: Various diagrams (e.g., component diagrams, class diagrams, sequence
diagrams) should illustrate the system’s structure, data flow, and interactions between
components.
Code and Documentation: The architecture should be accompanied by code examples,
if possible, or pseudo-code to show how the architecture translates to the implementation.
4. Implementation and Testing
Once the architecture is designed and documented, it is time to implement the system. The
implementation phase brings the architecture into reality, translating it into working code.
Testing is equally important to ensure that the system aligns with the architectural decisions and
performs as expected.
Implementation:
Component Development: In the implementation phase, developers build individual
components according to the architectural design. These components should conform to
the defined interfaces and behaviors as laid out in the architecture.
Agile Practices and Implementation: In agile projects, development is done iteratively,
and the architecture evolves along with the code. Architects and developers must
collaborate frequently to ensure that any changes in the code do not adversely impact the
architecture.
Testing:
Unit Testing: Each component should undergo unit testing to ensure it works as
expected in isolation. These tests also verify that the individual components conform to
their specified behavior within the architecture.
Integration Testing: Once components are implemented, they must be tested together in
integration testing to ensure the overall system functions as expected. Integration testing
also verifies that the components interact correctly with one another.
Architecture Validation: The architecture should be tested against the initial
requirements and quality attributes. Performance, scalability, and security tests should
ensure the system behaves as expected under real-world conditions.
Regression Testing: As changes are made to the system (e.g., refactoring, feature
additions), regression testing ensures that no existing functionality is broken.
5. Architecture Reconstruction and Conformance
Over time, software systems may evolve, and the architecture may need to be adjusted or even
reconstructed to better support the system's growth and changing requirements. This phase
ensures that the architecture remains aligned with both technical and business goals.
Architecture Reconstruction:
Refactoring the Architecture: The architecture might need to be refactored to improve
maintainability, scalability, or performance. This may involve modifying existing
components or introducing new components to meet evolving requirements.
Handling Technical Debt: Over time, a system may accumulate technical debt, where
shortcuts were taken in design or implementation to meet deadlines. Architecture
reconstruction often involves addressing this debt by refactoring inefficient or poorly
designed parts of the system.
Revisiting Architectural Decisions: As the system matures, the architecture should be
revisited to assess whether initial decisions still hold. New patterns, technologies, or tools
may emerge that offer better solutions.
Architecture Conformance:
Ensuring Consistency: Throughout the life cycle, it’s important to ensure that the
architecture is consistently followed. This involves checking whether the implemented
components match the original architectural designs and whether any deviations are
justifiable.
Conformance Testing: This type of testing ensures that the implemented system adheres
to the architectural constraints and design decisions. Deviations from the architecture can
lead to unforeseen issues, such as poor performance, maintainability, or scalability
problems.
Continuous Monitoring: Implementing continuous monitoring tools can help detect
deviations early in the development process, allowing teams to correct course before
significant issues arise.