I am currently working on an application with legacy code that was built using proof of concepts (POCs). These POCs became the finished production-ready code, there were no tests, and the classes have become quite large over time (pretty much god objects and there are multiple objects that follow this structure). These questions are related to these god objects as legacy code.
For the application itself, it works well enough, but there are bugs that do hinder the users. There are some workarounds in place, but there is a vibe of unreliability in the overall product (bugs creep back into the application due to coupling). For the development team, there is a fear of adding/modifying functionality due to large classes, tight coupling, and typical problems with inheriting legacy code that implements certain business rules and one-offs.
I do understand that with legacy code there is a need to review the costs of maintaining or refactoring code. Most attempts at refactoring would not be worth it, since the usage and coupling of POCs as production-ready code would make the refactor a fairly large undertaking. I have been through part of the Working Effective with Legacy Code book, but I do not know if this scenario specifically comes up. Also, I feel that developing valid tests for these kind of classes, or even some specified functionality, could fall under the same cost review as a refactor. (correct me if I am wrong on the assumption)
As for new functionality, I do not have a grasp on what should happen. There is the idea that new functionality could be separated into the preferred structure determined by the team, but there is the argument for consistency by putting the functionality in with the rest of the methods of some large class. Consistency being that some class which contains many uses/CRUD for many entities should receive the new functionality. For the consistency argument, it could have an advantage for the "possible" payoff on technical debt by having all of the functionality in the same place.
These questions lean more towards preference, and management normally has more weight in determining the direction taken. The main takeaway for me would be the outside perspectives. There could be discussions and other approaches that are being missed by the team (myself included) but could help in the long run. We could be doing everything that we can do, and that leaves us at the point of pushing through these growing pains.
Questions
For Maintenance, is there ever an instance where you cannot avoid a refactor that involves pulling out a piece of functionality from the large class, even if consistency is preferred? If so, then what would be a good example? (I do not know if there is a "problem" that fits this scenario, like what is seen with the square rectangle problem)
(my possible example; some functionality breaks because the large class was meant to deal with some in focus entity, but it is being used for multiple entities that are not always in focus. I cannot change the idea of the entity being in focus otherwise other pieces of functionality will break.)
For Moving Forward: Should the preferred method of adding functionality be up to the team/management? (it could be decided to separate or keep with consistency based on the situation)
Should new functionality always be one or the other (always consistent or always separate), with or without some expected large scale refactor?