Let me begin by stating I have already reviewed the following related questions, and just wanted to showcase the software architecture which I have inherited to see how opinions may vary.
- When is a BIG Rewrite the answer?
- Would you re-design completely under .Net?
- To rewrite or slowly refactor old C++ project
So, I have inherited a highly interdependent C++ object oriented application. The original software was written by a single developer (contractor) with no oversight, and is roughly 10 years old. The company has traditionally been more hardware oriented, and the software product was designed to replace purchased third-party controllers, and give us a leg up.
I have been with the company roughly 2 years, and was originally brought on to assess the existing software, and potentially re-design. My first approach was to suggest a potential incremental refactoring. Now working with the company and understanding the products better I have come to appreciate the need of a good modular software and hardware design to support a myriad of hardware combinations utilized.
From a product perspective the company attempts to operate in a very agile environment (need to make changes quickly and gracefully to support specialized customer needs). The current software attempts to accomplish this through the use of configuration value controlled logic which significantly muddies the software, makes it bug-prone, and highly interdependent. There were never any unit tests written for the software, so the validation process consists of testing any new software on as many representative hardware variations that the group can get their hands on.
The test group is fairly rigid, given the interdependent nature of the software, that for any single change they need to re-test everything. To give you an idea of the interdependence I have attached a class inheritance diagram below.
As you can assume, this structure is a nightmare to maintain. I suppose I'd like to hear from you if you have ever encountered an architecture such as this as I tend to prefer single, linear inheritance models. It appears that the original developer utilized inheritance for functional augmentation, rather than creating members, or allowing access to other class pointers to provide the additional functionality, it was done through multiple inheritance, sometimes inheriting from up to five parent classes.
The current software is deficient in many ways. It cannot support the functional growth that the company requires. In one part this is due to current developers knowledge of the existing software, and is otherwise due to the fundamental architecture (data and execution flow). It also has areas where it is highly inefficient. Over the past two years it hasn't been uncommon for me to find busy loops, nested (5 times) for-loop structures, and poor timing functions. I have worked to improve these as I have identified them, but this type of design error is consistent in the software. It is also not only multi-threaded, but many-threaded with poor data synchronization where it even exists.
So what are your thoughts?, have you ever had to work through a similar problem?
To give you a little insight; I have been working in the specific industry in which I have encountered this problem for nine years, so I have a reasonable understanding for the requirements of the software product, and could manage a re-design as I believe is required. I have grown into a software architect through professional experience primarily over the past 5 years, so this is my first experience with a major re-work problem.
TL;DR Have you every seen an inheritance diagram like this?
@gnat, Thanks for the duplicate suggestion, great description provided by @haylem and others there in the popular answer. Another unfortunate aspect of the existing software is that when I came onboard there was very poor revision control over the software, and inconsistencies in the build system. There was definitely no continuous build system in place. I have at least transitioned the scm to Git (GitLab) rather than SVN (mainly just a personal preference, easier to visualize the software), implemented a CI system with Jenkins, and helped establish development, and specifically commit rules.
One other aspect of the program that I had not previously mentioned is that the inheritance diagram you see is for the "core" software element. The software suite consists of this as its foundation, and 40-50 dynamically loaded libraries to augment the system.
In a plan to re-architect there will be hard rules for software unit testing which will be integrated into the CI system. I have not yet gotten a continuous inspection running, but that is on my list of improvements to investigate as well.