This post talks about the design approaches in Agile, the principle for Agile projects in details and step by step manner.
Introduction to design approaches in Agile
System Architecture provides high-level structure to serve as a starting point for design and development activities for a project Architecture and Infrastructure Planning(AIP), and high-level organization of components at the start of the project can help discover and prioritize major Architecture and deployment issues that require further investigation.
In Agile, designs need not consider all known system features. The immediate focus is on implementing a subset of features at any given time, evolving the software and its design with additional features.
Core System architecture, product and platforms are typically decided initially to ensure that the system is being developed using a stable platform. There is no dedicated design phase in Agile projects. The design documents are typically not prepared or maintained in Agile projects.
However, the organization can customize Agile projects to prepare just enough documentation for complex modules. The code is self-explanatory and forms at the basis of design in Agile projects. The detailed design evolves iteratively with the addition of new features. The System design is kept open and simple to add new features.
Major Challenges in Agile projects Design
- Design in Agile is iterative nature and evolves over a period of times as the projects are executed. Not knowing the complete. The landscape of the project may, at times, lead to certain issues such as incompatible design to interact with external interfaces, system security and other non-functional requirements.
- Detailed design is not done in Agile projects at the beginning. The emerging design the sprint execution may lead to technical debt with a huge codebase, having duplicate code, monolithic routines and flexible routines. It becomes difficult to maintain the code base, find and fix bugs and extend new features.
- Since there are limited detailed documents present in Agile projects, quite a few times developers accustomed to working in traditional methodology find it difficult to function in an Agile way of development.
Concepts of Agile Design
Agile believes in “welcome changing requirements, even late in development” and Simplicity- the art of maximizing the amount of work not done- is essential”.
As s result of above doctrines from Agile manifesto, Agile projects believe in No Big Design Upfront (NBDUF) and you aren’t Goanna need it (YAGNI) principles.
Relationship between YAGNI and NBDUF approach–
- Any code or design which is not required for the current set of features might not be required in the future.
- More time is spent in designing/developing feature which does not add any value to the current set of features required by the customer.
- The additional unrequired feature can lead to software becoming larger and complicated which in turn can impose constraints on adding new features.
Projects executed in traditional methodology have requirement phase where the entire system requirements are gathered up front.
This is followed by the design phase where system design is detailed out and designed. Typically, System Architecture, interaction diagram, component model, class diagram, sequence diagram, system context diagram, use case diagram are done during the design phase (High level/Low-level design phases).
This detailing is done before the start of the coding phase and is called Big Design up Front as all the design is complete before the start of the coding phase.
Design Guidelines for Agile projects
In a traditional development project, requirements and plans are set before development begins, which enables the team to know the road ahead with reasonable confidence that requirements or design will not change drastically in the middle whereas Agile method is to enable and embraces change.
On an Agile project, requirements can change at any point in the project cycle. Therefore it is imperative for the Agile team to have a code in a position where they can conveniently accept a new requirement or change.
One of the important Agile manifests principles stresses on good design in Agile projects “Continiousaltention to technical excellence and good design enhances agility”.
Following guidelines can be used to design in Agile projects-
- Keep it simple
- Apply SOLID principles
- Continuous code refactoring
- Rest driven development (TDD)
- Implements Designs Patterns.
Keep it simple–
One of the key concepts in Agile development is to keep the system design as simple as possible. The simple design is adaptive in nature and easily responds to frequent changes due to changing the requirements in Agile projects. Following four criteria can be applied to keep the system design simple-
Code should be self-documenting. The code should have unabbreviated words i.e full names standard naming convention should be followed. Use comments or assertions for a better understanding of code.
Each and every declaration of the behaviour should appear once and only once. Developers should not implement unrelated ideas in the same method. Code without duplication is easier to maintain and change.
Remove Super flows Content–
Code should not have any unnecessary Content. It should only have the code to support the required functionality. Any functionality which is not required should not be called the YAGNI principle.
Cover all test scenarios–
Write code that satisfies unit tests covering all functional areas. TDO helps the developer with the same. With code, only for the required features, minimal coding is done to keep it simple and flexible to maintain.
Read more about SOLID principle.
Continuous Code refactoring-
Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour. Its heart is a series of small behaviour preserving transformations. Each transformation (called refactoring) does little, but a sequence of transformation can produce a significant restructuring.
Since each refactoring is small, it is less likely to go wrong. The system is also kept fully working after each small refactoring, reduces the chances that a system can get seriously broken during the restructuring. ( source – www.refactoring.com ).
Refactoring can be done for a variety of reasons to make the code extensible and maintainable which in fact leads to the adaptive and simple design.
Code refactoring is done to-
- Remove duplication and unused code.
- Increase abstraction.
- Change to code structure to make it modular and simpler.
- Increase reuse or implementing design patterns.
- Increase cohesion, reduce coupling.
- Change poor design or code.
- Implement coding standards.
Code refactoring gives us the following advantages-
- Simplified Design– Refactoring should be done to clean up unwanted code and provide structure to the code so that it is easier to understand.
- Maintainability- Refactoring reduces long monolithic routines into a set of single-purpose methods, removes code duplications and provides more readable and standardized Code which in turn helps in easier maintenance of the application.
- Develop Frameworks- Refactoring helps in extracting reusable components which can be used to develop frameworks. E,g- If we are using xx at multiple places, instead we can refactor the code to use design patterns.
- Adaptability- Refactoring helps in making the software design simple and open. This makes easier to extend application capabilities.
- Faster development- Simple structure and open and adaptive design are easier to understand and add new system requirements. Impact due to adding a new feature is localized is easier to implement.
Though Code refactoring has multiple benefits there is cost associated with the development and testing effort. Also, there is a possibility of new bugs getting introduced in the code.
The cost and possibility of introducing new bugs can be reduced by having good regression or unit test suites which can be run to ensure existing functionality is not broken. Test-Driven Development helps in putting across good unit test suites.
Test-driven development is a design enabler. It helps the developer to analyze the requirements, think about code structure(APIs, interfaces, classes, their methods, interactions and dependencies). It also helps in finding reusability, reusable components, code behaviours for boundary conditions. Read more about TDD.
Implement Design Patterns:-
As per the YAGNI principle, design patterns evolve with features being developed and code refactoring and should not be implemented up-front. This requires developers to have good understanding of design patterns and their implementations.
But the team can do a trade-off with YAGNI principles on implementing design patterns upfront if they are clear about the need for design pattern or can defer for later implementation. In this case, design patterns can be put across in Simplest form based on their applications and the complexities can then be added at later point of time.
Design in traditional methodology-
In traditional software development, there is a dedicated design phase (high-level and low-level/ detail design phases) before the start of the coding phase. High-level architecture generally involves depicting the system into modules, representing the interfaces and interactions between these interfaces.
Detail design outlines the design internals for each of the modules. Typically for OOAD (Object-Oriented Analysis and Design) project, the high-level design includes system architecture with details about interfaces, Components and networks that need to be developed along the data flows and interactions between component systems.
Detail design further divides the high-level design into the class diagram with all the methods and relation between the classes. Design documents in traditional software development are very elaborate and detailed and run into several pages since the entire system design documents to the development team.
You Aren’t Gonna Need It (YAGNI) is one of the engineering principle of Extreme programming (XP) which focuses on working on the features which are deemed necessary. It is usually used in combination with other Extreme Programming practices of refactoring and Test-driven Development(TDD).
Define System Architecture:-
Product and platform should be decided at the start of the project. Create visual architecture and infrastructure (AIP) planning diagram defining the components, interfaces and other characteristics of system or components as required.
Any specific security or other NFRs can be outlined in the visual A1 Palong with product and platform being used. The system architecture is typically decided during project workshop or project initiation (sprint 0) phase.
The architecture defined takes care of the organizational IT roadmap and the application/product being developed. The following guidelines can be followed to create a stable Software architecture-
- Create System architecture diagram to show how the system will be implemented in different layers and the main components being used.
- Decide on platform level details (programming language, database etc)
- Identify risk areas that new POC (proof of concept)
Techniques used for defining System architecture are-
- Expert judgment
- Whiteboard, AIP diagram
- Existing enterprise guidelines and constraints.
Define Architecture stories
This is an optional phase typically applicable for projects with the technical complexities or known technologies and tools. Depending on the technical competency in the project the team may want to skip this phase.
The system architecture is defined at the project, Risk area identified as part of the ‘Define System Architecture’ phase should be defined as architecture stories and taken up as POC during this phase, which is in line with the idea of a fail test of Agile principle.
Any other POC as required for the identified risk areas or new technology implementation should be covered during this phase. Some of the high priority stories can be identified for implementation, during first 2-3 sprints (assuming 2 weeks iteration for a project duration of more than 6 months) which can be set up the technical foundation (e.g- Data access framework, Error logging framework, Common utility etc) for the system being developed.
It is implemented to note that the team should have good visibility of the system requirements to implement these technical stories.
High-level objectives of this phase are-
- Reduce project risk due to technology by validating assumption (eg- POC for identified risk areas).
- Provide a foundation for future sprints like define error handling framework, define data services and design patterns ( can be implemented at later sprints if the customer priority is different).
Techniques used are-
- Expert judgment
- Team discussions
Just in Time Design:-
Minimal design discussion can happen at the start of the sprint stories for the current sprint to ensure consistent implementation. Further focus on feature implementation and design should be given at the start of the story.
The design typically evolves iteratively along with the sprints. The design focus during the sprint shifts to just in time designs. Designs at the start of the sprint sat the directions for the team for implementing the stories in conjunction with the defined architecture. Whiteboard with expert judgment is the most used tool and technique for just in time (JIT design).
Typically the team during this phase has design discussion for implementation of the features. As new features are implemented, design needs to be constantly kept simple to ensure that it is both maintainable and extensible.
Design guidelines, as described in the concepts section, should be applied while developing the system to ensure the same. TDD can be followed to ensure easier code refactoring during subsequent sprints. Pair programming can be followed in the project to ensure code is simple and self-explanatory.
During JIT design phase, certain visual artefacts as mentioned below can be created for implementing the current story in hand-
- Interaction Diagram
- ER (Entity Relationship) diagram
- Sequence diagram
The design techniques used for JIT are-
- Expert judgment
During sprint phase architecture, design and code quality should be frequently monitored. It is recommended to have a code quality tool integrated into the developer’s IDE to ensure code quality compliance. Practices like continuous integration should be followed and any technical debt accrued should be addressed in a timely and effective manner.
System Architecture Diagram:-
System Architecture diagram shows how the system is implemented in different layers and what are the components belong to the system. It illustrates the main system components, layers and interaction between them. It is used by the architect and technical design team to understand the system from a technical perspective.
Infrastructure/ Deployment Diagram:-
The infrastructure/ deployment diagram contains package level details of the system to be deployed. This diagram is used by the architect and technical design team to understand a system from a deployment/ infrastructure perspective and provide input on the infrastructure requirements.
Design principles used across key Agile methods:
Even though there are various Agile development methods, almost every method emphasizes or working code rather than a big design up front approach. Two of the most commonly followed Agile design principles are from Agile modelling and extreme programming (XP) methods.
Agile modelling prescribes following design principles with focus barely good artefacts.
- Architecture Envisioning- Focus on high-level architectural modelling to identify a viable technical strategy for the project at the start of the project.
- Iteration modelling- Minimal design for the current sprint to define teams strategy.
- Model Storming- Focus on requirements and think through the design on a just-in-time (JIT) basis.
- Test Design Development (TDD)- TDD helps in designing for the requirement write test case and then prepare just enough code to fulfil the test.
Design in Extreme Programming (XP) is based on the concept of no fig Design Up Front and YAGNI principle. The key design concept of XP are –
- Simple Design – Focus is on “simple is best” approach to software design. Big Design Up Front is avoided as most design occurs during development.
- System metaphor – It is a naming Concept for classes and methods that should make it easy for a team member to guess the functionality of a particular class/method based on its name.
- Code refactoring – XP advocates programming only what is needed and implementing it as simply as possible. In case there is a functional change requiring changes to existing code, code needs to be refactored for making it simpler and more generic.
- Test-driven development (TDD) – Write test cases and then just enough code to fulfil the test.
- Collective code ownership – Everyone is responsible for all the code. Pair programming is a very appropriate contributor to this practice. Pair programming helps developers to see and understand all parts of the code.