This post is about a concept called Second System Syndrome, defined by Fred Brooks, in his book "The Mythical Man Month":
It refers to a condition that occurs after a first system has been implemented. When it seems to be working well, designers turn their attention to a more elaborate second system, which is often bloated and grandiose and fails due to its over-ambitious design. In the meantime, the first system may also fail because it was abandoned and not continually refined.
Maybe, you as a reader, could recognize the following expression coming from your team:
This system looks like crap and the code of the previous guy is understandable. We should implement it again avoiding mistakes made in the past with the best code practices and using the latest architectural designs.
As soon as this idea flourishes in the minds of team members, it’s difficult to take out.
Here are some reasons people try to salvage old code:
Commonly, managers, developers and architects gather to talk about it. They end up with great proposals in order to define how the new system should work:
Better architecture. Split the design into modules with specific functionality.
Generic design: We will easily make changes in the future and quickly.
Less code: We will avoid repeated code, which the old system has.
The latest technologies: Maybe they’ll also use the top notch frameworks that the community believes right now.
Knowledge: If it exists already an implemented system and we know how it works.
Fast delivery: Because we will have a better design, better technologies and a better approach, we will be able to finish it quickly.
All of those ideas are promising. Probably, in some cases, they are the solution to the current system. The idea of improving an existing system is something that we as developers need to embrace.
But the main idea and discussion I would like to cover in this entry comes which the following sentence:
It will be easier to redo it than to fix it. Let’s start over.
All promises are gathered and the new approach started. Everybody has input for the new project, team seems to be happy (check section "Team and Possible Conflicts"). The project starts, or the POC starts.
Some of the problems with the Second System Syndrome come with the knowledge of the functional requirements.
The previous system, usually, does not have enough test cases to prove that one specific functional requirement works correctly. This may slow down the progress of the second system because it could be difficult to prove the new implementation of a feature works exactly as before.
The first system may lack documentation. This issue could come from poor definition of use cases, documentation about the architecture and information about hotfixes patched in the previous system.
People are the most important part of the project. From professionals to beginners, everybody has a role in the team. Figure out what role can help to create products with better quality and in a sorted way. As an example, two extremely "professional” members working in a project that cannot work as a team will end up in an unfinished and poor product.
It’s also important to remember that team members could be affected from the Second System Syndrome. Professionally and personally.
Developers tend to embrace new technologies. When a second system needs to be implemented, it’s common to use new technologies or frameworks.
Team members may like to participate on the second system project, which could offer them more knowledge.
As the first system needs to be maintained, this could affect to some of the members that cannot participate full-time on the second system.
Team members may not be opened to express their disappointments, or they could express them in bad ways.
Features never end in a project. Features can be shaped as functional or nonfunctional requirements.
Normally, while the second system is being implemented, the first one is in production. Products change quickly and clients and salesmen agree to release features that are needed on the market.
Some important features can be planned to be implemented on the first system, that is currently in production, because they may start generating income to the company in short time.
The following diagrams explain the feature race between both systems:
In the first stage (stage A), the second system has been planned to have the same number of features that the first one. The architecture and design could cover those features and be slightly dynamic for changes.
When the first important feature is introduced on the first system, the second system needs to record it for future implementation (stage B).
Usually, the first system is able to implement and release the feature faster than the second system. Usually the second system is still implementing the missing features that the first system contains.
The following table describes the work needed on both systems:
|First system||Second System|
|Maintenance bugs/improvements||Maintenance bugs/improvements|
|Add new features||Add new features|
|Refactoring (make code better)||Refactoring (make code better)|
|Add test cases||Add test cases|
|–||Design new code/architecture|
|–||Implement missing features|
Note that refactoring the first system and add test cases could be slower than in the second system, which means that even the diagram shows the new feature with the same width (estimation), this could apply differently between systems.
The maintenance of the first system (refactoring and testing it) could end up in a feature race, where the first system may improve significantly before the second system is done. Adding new features in the second system may break the estimations done originally when the project started.
As said previously, the team members have good reasons to improve the product they are working on: Better architecture, better design, less code, new frameworks, faster delivery.
During this post, I tried to explain the consequences of a Second System Syndrome and explain some of the solutions if we are inside this stage. But before end up this post, we should consider the following approach:
Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its interanl structure […] In essence when you refactor you are improving the design of the code after it has been written – Martin Fowler in "Refactoring, Improving the design of existing code".
Refactoring gives us the possibility to modify an existing system and improve in such a way the system has the same features than before. Refactoring could cover from UX, Design, Architecture, APIs, Code, etc. For every of those areas, we may need to find an approach. The most common way is:
Some books about refactoring (in the code point of view):
As an extra, we can apply some of the following suggestions to the current system: