Evolutionary Design: Normalize Growth
Evolutionary Design is the practice of creating the components and interactions of a system while it is evolving, on the basis of the client requirements and user needs.
Normalization refers to a process that makes something more normal or regular
I am a big fan of gardening. Whenever I can, I take care of my plants and think about subjects like Evolutionary Design. One moment I was taking care of my young tomato plants: I needed to rip the small leaves that grow and just take the food away from the flowers and fruits. And it struck me: any gardener is doing Evolutionary Design.
Evolutionary Design is the concept of developing a system without a big plan ahead, but rather letting it evolve naturally, like a plant would grow. A designer would look at certain structures that do not fit well together, and restructure just in time the system so that it respects certain quality constraints like changeability, testability, low coupling, high cohesion, separation of concerns, etc. An experienced designer would just feel that something is wrong. A very experienced designer would also be able to explain why that something is wrong and the reasons behind the needed change.
As gardener I would let the plant grow, and when I see certain patterns, I need to take specific measures. But these patterns are well known among gardeners, you can read about them in any book, article on blog post. So they became best practices. We could call them Evolutionary Gardening Design Patterns. But we won’t.
I would call the action of a gardener to take decisions like trimming, pruning, feeding, etc the plant at certain moments growing the plant. Because gardeners can plant a new system every year, they found the best practices faster. Doing something more often would make you create and solidify knowledge.
I would like to evolve the patterns of evolving a software system in an evolutionary way, like letting a plant grow, in such a way that they are well. I would like to see all the (good) programmers using them like any (good) gardener knows how to trim a tree or a plant in certain situations.
The more often I plant a new software system, the more often is possible that I learn something new. So instead of learning just after 12 months, I can minimize the duration and use Deliberate Practice in my advantage.
Four Elements of Simple Design
The Evolutionary Design Growth Patterns are clearly related with the Four Elements of Simple Design, mainly about Minimizing Duplication and Maximizing Clarity. Another connection is with our habits of programming as like any great gardener a programmer needs to use the appropriate tools for the job. But something is missing, and I plan to look for it, or at least I will try to unite the things I know into the Design Growth Patterns book, or a similar name.
is the name I used to sum-up certain practices and you can find some of them explained in these slides. Find below some examples. I plan to evolve them into separate blog posts and I have ore ideas like them.
Focus on problem, not on solution
While focusing on the problem we iteratively deploy a new improved version of the system and we constantly look at ways to normalize the system growth by refactoring, re-architecting, re-designing, etc with the purpose of having a balanced system.
Always refactor in small and safe steps. Use tests and frequent versions to insure safety.
The Rule of Three
Always create duplication in order to remove it. But remove duplication only when it appears at least three times.
Keep Small Visual Distance
Whenever refactoring make sure you have the duplication close, so you can make it identical and remove it with little risk.
Unnatural Third Party
When a design structure does not respect the natural level of abstraction or crosses many architectural boundaries, make sure you extract it into a third party.
1) Software system
a)Upfront Software System Design
The architecture is already in place, created by the architecture specialists. Design specialists gather and discuss about the system requirements. They estimate the time it takes to create the full design of the system. After a while, usually more than estimated, the design is finished.
The implementation team gets the design and needs to use it in order to create a system exactly how the design describes it. Usually there are flaws in the design, caused by small details that create mismatches inside the system. Typical flaws are abut system communication, APIs, performance, changeability, testability, etc.
Using this way of working the design is rigid and very difficult to change. Often the development, testing, deployment and maintenance are sub-optimal.
b) Evolutionary Software System Design
The team is cross-functional: they have skills of design, programming, testing, deployment, requirements analysis, etc. The analyze the requirements and understand together with the customer what is more important to develop. They find the first feature to develop and they create the minimal architecture for the first feature. Together as a team they build, check, test and deploy the feature. Then they receive feedback from the customer, and they improve whatever is needed.
The next feature might need introducing new concepts into the emerging system. Maybe new modules are needed, maybe new technologies. The team focuses on having an easy to change design, good feedback from the automated tests, and a fast deployment pipeline.
After a while the team has implemented a few features, they start observing duplication between certain areas of the system. That is a sign that tells them they should extract those parts into separate module(s). Basically the team wants to create duplication in order to remove it when they have enough proof.
Using this way of working the design is flexible and easy to change. But the team needs to take the refactoring and re-architecting decisions just in time. If they would generalize too fast, the system might become an unusable framework. If they would generalize too late, the process will take a long time and it will be time-consuming.
a) Upfront Team Design
The manager walks into a meeting, discusses with the team leaders and they create the teams for this project. They are convinced they are taking the best decision, who in which team should be, they nominate the team leaders and they think it will work well.
b) Evolutionary Team Design
A new project arises. The manager explains all the constraints of the project to all the potential team members. The team members are given a task: create the teams in one day and tell me how they will be. The manager says that mistakes are possible, and we will need some time to adjust, until we get to having performing teams.
This concept might be old or new to you. In any case I ask for your help:
- Does this make any sense at all?
- What do you think is missing?
- How can I improve the names I used?