What is (Software) Architecture?
Grady Booch puts it succinctly: “All architecture is design but not all design is architecture. Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.”
Clearly, it follows that the architecture decisions need to be made with care and foresight.
Agile and Architecture
How do we establish the architecture for a software project in an agile manner? In agile methodologies, we build a system in short iterations, with focus on delivering working software to the customers in an incremental manner. Does that leave us with any time for architecture in a software project? Or do we reserve the first few iterations to creating the architecture?
Dedicating the first few iterations for architecture would be so waterfall-ish. Besides, committing to architecture decisions too early without validation can be very costly for a system.
But that does not mean that there is no architecture in an agile project. We do need to take architecture seriously even in agile projects. Neglecting the architecture, or crafting an inappropriate architecture is also very risky, and can lead to a system turning out to be too brittle.
Overview of Agile Architecture
The agile way to architecting a system is to evolve it iteratively, through initial envisioning, implementation of stories, refactoring and restructuring.
And a good way to accomplish this would be to:
Let us now look at each of the above points in some detail.
Involve the Entire Team
Agile teams are expected to be cross-functional. We strive to help each team member acquire and demonstrate skills in as many different roles (developer, tester, business analyst, database designer, UI designer, etc) as possible. So why not the role of architect also?
Involve the entire team in things like:
- architecture discussion, evaluation, implementation
- architecture reviews
- technical debt sessions
- refactoring and restructuring.
Encouraging every team member to participate in such activities leads to a shared understanding of the architecture, among all the team members.
Have an “Architecture Owner” Role
Identify one of the competent and experienced developers to play the role of “architecture owner”. This person should:
- be a master builder
- have the depth and breadth of knowledge and skills needed for architecture decisions
- provide architectural leadership to the team in a collaborative manner.
The architecture owner:
- brings the team together for all discussions regarding architecture envisioning and modeling
- facilitates architecture modeling and evolution
- helps in building a shared understanding of the architecture among the team members
- helps the team members enhance their capabilities in understanding architecture principles and tradeoffs involved.
Understand Your Product
Diving in to build a product without having a broad understanding of the system (tunnel vision) is likely to result in an incomplete and inappropriate architecture.
Everyone in the team should have a good understanding of the product (the system) they are going to build. This understanding should include:
- vision and broad scope of the product
- key features and their purpose
- the context in which the system will be used and
- the constraints and expectations imposed by the context
Create an Architecture Vision
Establish a shared vision of the architecture for a system without committing to any specific architecture decisions.
When should one do this? Sprint Zero is the right time for this. And how? Through an architecture workshop. Organize the architecture workshop right after the team has understood the product vision and gone through the Product Backlog in as much detail as necessary.
Who participates in this workshop? As you can perhaps deduce from the earlier discussion, we involve all the team members in this workshop. And the Product Owner also. After all, architecture needs to be based on the requirements from a system (even if the Product Owner is unable to articulate the architectural requirements clearly).
Let us understand the activities in the architecture workshop now.
Identify the Desired Architecture Qualities
In consultation with the Product Owner, identify the important quality attributes for the architecture of the system. Examples of quality attributes (borrowed from “Software Architecture in Practice”, by Len Bass and others):
- Conceptual integrity
- Customization points
- Environmental impact
- Regulatory compliance
- Dependencies on external systems
Let’s consider a few examples. If we are building a search engine, we are likely to consider the following as important quality attributes for the architecture:
For a stock trading system, perhaps the following represent some of the important quality attributes:
- Dependency on external systems
Specify the Architectural Qualities
Be specific about what exactly is required for a given quality attribute for the system. For example, the specific security requirements for a system may include:
- Preventing unauthorized access to data or services
- Dealing with Denial of Service attacks
- Non-repudiation (a transaction cannot be denied by any party)
- Secure transmission of sensitive data
Similarly, the specifics of usability requirements may be:
- Ability to save incomplete data as draft and resume later
- The system should provide appropriate feedback about the state of completeness of a business process / long-running transaction / multiple-step data entry, etc
- Ability to bookmark things / roll back actions in the system
Identify Strategies for Achieving the Desired Architecture Qualities
Next, the team should discuss the various strategies for achieving the desired qualities, including tradeoffs involved, without committing to any architecture at this stage. For example, some of the strategies for implementing security could be:
- Authentication of users
- Single sign-on
- Authorization of users, limiting access
- Audit trail
- Intrusion detection system
Likewise, some of the strategies for meeting the usability requirements could be:
- Separation of UI from the rest of the application
- Providing feedback in the UI about what the system is doing
- Letting the user issue commands such as Save as Draft, Cancel, Undo, Redo, etc
- Using design patterns, such as Command and Memento
- Maintaining a model of the task, or the system, or the user
Consider the Cross-Cutting Requirements
Identify the functional requirements that are common to many stories (cross-cutting), and consider their impact on the architecture, such as:
- Audit trail of changes to the system
- Notifications for important situations that need attention
- Centralized error logging
- Exporting data from any list views to spreadsheet files
Take Stock of Reusable Architectural Assets
Over a period of time, your organization may have built some reusable architectural assets, such as application frameworks, logging or error handling mechanisms, which may meet specific requirements of a project portfolio, or applications in specific domains, etc.
In addition, there are many general-purpose, third-party frameworks and toolsets available that address many of the architectural needs mentioned above.
Take stock of the internal as well as external, reusable architectural assets that may potentially meet some of the architectural needs for the system that you are going to build.
Prioritize the Architecture Features (Qualities)
You have a list of architectural qualities required from the system. We can also call them the architectural features of the system. Prioritize these, just as you would the functional stories of the system.
Prioritization would be based on the combination of:
- Business value of an architecture quality for the customer
- Cost of implementing early vs cost of implementing late
Add to the Prioritized Product Backlog
Turn the architectural requirement into stories. Add these to the Product Backlog, appropriately ordered by priority. The idea is that the architectural stories will be implemented like functional stories, so that we can test, evaluate and validate these and their appropriateness. Here is an example of a prioritized Product Backlog, with an intermingling of functional and architectural stories.
Establish Architecture through Stories
Pick the first story from the Product Backlog: maintaining the list of “Items” for stock and sale. Implement it the way you would. Identify the acceptance tests. Design the UI. Implement the UI, the business logic, the database operations, and whatever else is required. Run the acceptance tests. Ensure that the story is potentially shippable.
Next, pick the second story: implementing Layering and Partitioning in the “Items” story. Refactor the code from the first implementation to move UI, business logic and database logic in separate layers. Distribute these layers to run in different address spaces. Establish the connections between the layers. And run the acceptance tests again. Ensure that the story is potentially shippable.
At this stage, we have evolved a miniscule architecture, with just one architectural quality taken care of, but it is proven with the working code. Architectural stability and state of completeness, at this stage, is low. But we have taken our first baby step. And we are confident of what we have done. And ready to take the next steps.
We now take up the third story: creating the list of “Account Heads”. And then the fourth one: refactoring the “Items” and “Account Heads” stories to extract the common behavior into a “framework” for the application.
Again, we run all the acceptance tests. And ensure that the stories are all potentially shippable.
Model and Implement Incrementally
As illustrated in the previous section, architecture and design continue to evolve as the system is built. Keep in mind:
- Model throughout the development lifecycle, in small increments.
- Split large, complex stories into smaller, more manageable ones.
- At the start of each iteration, during the Planning Meeting, have discussions on incremental modeling, design changes
- Apply architecture and design patterns as required, gently
- Keep investing in architecture across sprints