At some point, many applications get to a state in which a large refactoring or, in some cases, a complete rewrite needs to happen. The decision to do so can be driven by many factors. For example, the code base is growing rapidly and the current architecture cannot support the growth, components are becoming too tightly coupled and need to be split, new and better technology becomes available which offers significant improvements, or due to other factors the current code base is just not maintainable. In part 1 of this blog post, I will describe why we here at Logentries decided to perform a rewrite of a major component of our front-end and reveal the thought process into planning such a migration.
In our case the reason for a migration from legacy was very simple—it was legacy code that was written a while ago to ‘just work.’ When Logentries started, it was a small start-up and the front-end web application was not the core aspect of our technology. As the company started to rapidly grow, more features were pumped into the application, and we started to consider the growing complexity and maintainability of our web application. What was needed was a solid framework that would help us in creating and managing large front end components, make development easier, provide a more structured architecture, and enable us to far more easily test these components. The code base at that time didn’t have a concrete framework, it was a mix of a few technologies like jQuery and many other libraries which didn’t necessarily play well with each other. Over time, some developers on the team had refactored various aspects of the codebase and added some more structure, however, it became clear that they were effectively building parts of an ‘in-house’ framework. I believe that if you do not choose a framework, eventually you will probably end up writing your own. Why re-invent the wheel? It was inevitable that a codebase like this will at some point become bloated and extremely difficult to develop, manage, and maintain. We decided that the best approach going forward was to introduce a framework into the web app that would help us create a better, more maintainable, more readable and testable application.
AngularJS was selected as our framework of choice. For us, it was a simple decision. Most of us were familiar with it and, by design, it would solve our structural problems. One of the bigger wins from picking Angular was how easy it made testing. There are a ton of blog posts on the web explaining in detail why you should choose AngularJS, and there are a ton of blog posts explaining why you should choose a different framework, as well as comparisons between different frameworks. At the end of the day, it is a team decision that comes down to many factors such as the suitability of the framework to your application and developer familiarity. Our team decided on AngularJS…
It is never easy. We were not re-writing the application from scratch, we were dropping in a full framework into the current code base, which as I am sure you can imagine is not trivial and can cause some pains. The main issues for us were mostly related to routing. The router that comes with Angular was not compatible with our existing application routing managed by jQuery BBQ. I will talk more about that at a later point. The initial plan of action was as follows:
- Introduce AngularJS into the current application
- Make sure that there is no regression and all application functionality remains
- Create a first Angular component in the application and incorporate it
- Any new features to be developed in Angular
- Over time refactor existing components and migrate them to Angular
The issue with routing appeared when we came to the third point above. The first component we chose to write in Angular was the log selector. The log selector enables you to select what log/logs you would like to view. Behind the scenes, the log selector is responsible for routing between log view and other parts of the application. On its own, the log selector is just a simple checkbox tree— for that purpose, we created a directive which encapsulates the creation of the tree and a controller which reacts to state changes in the tree. Based on those state changes, routing in the application changes. The decision to develop this component in Angular came from the fact that most of problems with bringing Angular would appear then. As mentioned above, the biggest problem we had was handling routing. BBQ was interrupting Angular routing which caused unwanted states in the current route. To solve that issue we had to override some of the angular-routing code to handle state changes that would conflict with BBQ. That was a temporary fix that enabled us to successfully incorporate Angular. At that point, it became clear that BBQ would have to be removed sooner rather than later, and that Angular would have to handle all routing requests. That was easier said than done.
The application was mostly just legacy JS code, only new pages were to be fully written in Angular. We needed a quick solution for this in order to have BBQ gone for good from the application.
The plan was to create routes in Angular for all of the pages in the application. Then we created a generic routing controller which takes the current route and delegates the work to correct legacy code component. At that point, all of the routes were handled by Angular, and we had removed BBQ from the application, as well as removing any code changes made to the angular-routing service . To celebrate this, of course, we had a real BBQ.
After the above work, we had Angular fully working in the application, removed one legacy library, and started to create all new components in Angular. The future started to look bright for us. The code base started to take some shape. We agreed on a Style Guide for file structure and naming conventions for files. We were a step closer on a long road to an improved and easier-to-manage application. In the next blog post, I will talk about other core components which were migrated to Angular and the initial plan to move the core part of the application ‘Log View.’ Stay tuned!