Scenario
This was a project that I once had to maintain. After reading Working Effectively with Legacy Code, I started to think how I would refactor this system in a live environment, if I had to (thankfully, I didn't).
The system was a legacy system without documentation and extremely tightly coupled. Database relationships were incorrectly modelled - i.e. objects that were meant to be many-to-one were mapped as one-to-one. Using "duplication" allowed for "pseudo-many-to-one" relationships. Business logic was stored as JavaScript solely on the front-end. Data was tightly coupled to Presentation data.
As an example, a Question object could not exist without a Table Cell object. The database had a table call "TableCell" to store inline CSS for each cell which was mapped one-to-one with a "Question" object.
The system was a horrendous mess and eventually lead to loss of data and a complete re-write in the end. In total the project was about 350K LOC.
As a side note, the reason why the system was re-written (or needed refactoring) was that it was to be exposed to the Internet, but we were able to modify the business logic using the Chrome Debugger to elevate roles, inject code, and execute all sorts of undesired functions.
Question
The book used examples where the logic was placed in the middle tier. However, what happens when the business logic is placed in the front-end? From my point of view the refactor process would have to go this way:
- Refactor the front-end JavaScript to understand the business logic
- Refactor the middle-tier to include validation
- Refactor the database to decouple the data models
- Migrate the data
- Refactor the middle-tier to decouple the data models
- Refactor the front-end to reflect the changes in the data models.
I have read Techniques to re-factor garbage and maintain sanity? and it is helpful, but it doesn't address the order in which refactoring should occur for this specific scenario. This process seems to add a lot of redundancy as the front-end and middle-tier are refactored twice in the live system.
- What is a more efficient way to refactor such a system while keeping the system live?