Rewrite, refactor, knee-deep in legacy - part two

I really don’t take on extra work apart of my full time job. At work I do get to try many different things. We get chance to work on both legacy and greenfield projects. So really don’t feel that I would need extra projects on the side.. :D

This project that I’m gonna write about is a webshop, that sort of fallen into my lap. Back in 2010, when I started out with programming I’ve been doing webhops and inventory sites, using PHP, MySQL. So it didn’t feel too alien to me to help out every now and then, when the person running it needed help. Even though I really don’t like webhops and always turned them away, this was the first and last exception.

I got to be a second dev on this project as the original author had less and less time to deal with it. Eventually the situation got to the point that I had to take over the maintenance fully (to much of my dislike).

State

The site was written in PHP using MySQL and NextJS for the front-end. The backend was producing normal JSONs, so nothing too exotic there. The issues started when one started to look under the hood. The original author also didn’t have much time to actually do the site and this was reflected in the code as well.

It was really chaotic and as I didn’t do programming in PHP for long it was hard for me to change it in a good way. Since the site was simple there was no framework used and as it was a rushed job the most common mistake was also made: no tests were written.

Front-end was also similar, with the exception that there NextJS gave a nice frame to it, but also zero tests to see if everything is working.

Kickoff

When I had to take over the maintenance including running the server, it was clear that I won’t be able to support the PHP backend specially in its current form. Wanted to fix that up and stick with it, but really couldn’t get a handle on it.

At that time I started to get to know NestJS as at my company we started to migrate services to this framework. So for me it was an easy choice to go with NestJS. The plan was to rewrite the backend using NestJS while keeping the database schema and HTTP API the same.

This time I’ve made sure to do it in TDD, so that every new route and service was fully tested. Some logic issues came out that were also present in the PHP version. It was an interesting journey, but at times it did feel monotone, doing the same over and over. But on the end all worked out and managed to deploy the backend with nearly zero change to the front-end.

With NestJS the default database ORM is TypeORM, it supports many different databases. In general I don’t trust libraries that can do anything while providing the same interface. But here it actually worked out nicely, as when I was looking for database providers I couldn’t find cheap MySQL provider while I managed to find a really cheap (actually free plan) for PostgreSQL. This was the first time where I actually migrated from one database to a different one with about 10 minutes job thanks to the ORM. I did concentrate on using the ORM’s methods for building queries and had zero raw SQL statements in the code.

Frontend

The frontend wasn’t in the best of shape either, but hey it is React thanks to NextJS, so that help a bit. It wasn’t in such a bad shape that I would want to rewrite from scratch, but I needed some proof after each and every change that all is working.

Tried to write tests using Jest, but the react part wasn’t written with the best practices, so it brought out all timing issues. This way proved to be really slow going. Here I decided to do an end-to-end testing using Cypress instead unit and functional tests with Jest.

Had zero experience with Cypress, just seen some PRs and nice comments at work from colleges. Before jumping into Cypress tests I crunched through a course from udemy, with double playback speed, think it took me day and a half. Sorry, don’t want to brag here but still makes me smile thinking about the instructor’s voice in double speed :D

After this I covered all the pages and all the features that I came across. With cypress it was truly a breeze, timing issues were still present, but manage do put some cy.wait commands and TODO comments for a later time.

Once cypress covered everything, refactoring the front-end and getting rid of all the timing issues was a dream. Okay maybe not a dream, but went with good speed and managed to do frequent deploys, knowing all is working.

Outro

Overall I’m happy that I chose rewrite, with the old code without tests I would still be having nightmares. Since then I managed to extend on the features of the site and also automated a lot of tasks on it. All these new features were done with tests, so at all time I know that the site is working and that the person relying on it won’t lose sales due to bugs.

Also this project gave me a good chance to deepen my knowledge with NestJS, Cypress, React and NextJS. Did make me a fan of NestJS and NextJS!

However I did put a lot of work into it. Looking back on it, eventually I rewrote the front-end as well. Via refactors think there is no line that I didn’t touch there. So in hind site for a webshop I would pick a provider rather than hand rolling it.