Recently I mentioned 6 steps of an evolutionary design in software development. These steps describe iterative process aiming at continuous improvement. Such an improvement process can happen at two distinct levels:
- High-level view of the entire system involving components and their interactions;
- implementation details of a component.
While high-level system evolution is covered pretty well in methodologies like domain-driven modelling (strategic design), implementation level can be more project-specific and hard to explain in uniform fashion. May be that's because there is no generic approach to describe evolution of components or services in a real-world system. Each element might need to evolve in a unique way to order to reach the best balance between complexity, performance and capabilities.
For example, let's consider an evolution path that a single component can go through in a startup team focused on emergent design, rapid iterations and .NET stack:
Team dynamics, past experience and current political situation might lead to a design approach, where each component starts as a simple console app and then evolves towards more complicated design in order to fulfil specific requirements. We try to keep things as simple as possible, but no simpler. If a component is kept simple and focused (which is a task of a strategic design), then at any point in time it could be rewritten from scratch.
Evolution tree below is merely a visualisation of existing design approach inside a given team, serving as a way to make design options more explicit and allow better communication. Any change in team, business priorities or design methodologies could affect this evolution tree.
Here is a bigger version of this image.
Please note, that at any evolution along such design tree is a specific optimisation that comes at the cost of complexity. Sometimes it is better to delay paying that complexity cost and keep your options open.