I recently completed an extensive update/refactoring project at work, and the amount of organization required to do it with confidence was almost equal to the amount of code writing involved. It made me think there could be a consultant whose specialty was “professional organizer for websites” – and since professional organization was one of the options I considered seriously preparing to change careers six years ago there was a certain pleasant synchronicity to that.
This consultant would come to a company to work for a year or two with the sole goal of leaving them with an organized, unified, up to date codebase and associated tools. This post is how I would lay out such a project based on the refactoring project and the rest of my work experience.
If you want one takeaway, though, it’s this: the more deeply you understand the existing setup and code, the easier it will be to make changes.
Stage 1: Familiarizing and Quick Wins
- JavaScript error reporting: One of the first things I would do for any site that didn’t have it set up, whether I was looking to refactor or not, is start sending JS errors to Google Analytics. This is easy with Google Tag Manager, which has predefined variables for JS errors: filename, line number, and error message. It’s good not to send them to your main view, because they will overwhelm the Events report, and you may also find you need to filter by filenames including your site’s domain because of all the useless “Script error.” messages from outside scripts failing for reasons beyond your reach to diagnose or repair.
- Making acquaintance: There’s a long and repeating period of getting to know a new site: How is it set up? What pages call what files and how are those files put together? What about the templates/pages is essential for the CMS/JS to hook in and what can be changed without outside effects? What outside services are used and how are they integrated? If the site is not all on the same codebase, which is considered the up to date one and how does it differ from the older code? How many places might changes need to be made to take effect everywhere? (There may be templates for your CMS and separate templates for a vendor integration, for instance.)
- Test page list: During the get-to-know process – and beyond – collect a list of URLs. Include a representative set of “regular pages,” such as one instantiation of every template used by a CMS, plus “strange” pages. The strange pages are those that call files other pages don’t, have fancier functionality, have custom styling, have iframes or API integrations, or are in some other way different from the typical page. Use this list of pages for checking over changes to the site (code or otherwise – such a list is valuable when going https-everywhere, for instance); the idea is it allows you to be thorough without having to check every page.
- Make easy improvements: Are any unnecessary files called in the CSS or JS build? Are there files that aren’t called at all because they’re deprecated, but still in their original location? Do all the GA events that are set up record properly? Is there streamlining or improvement you can make to the task runner’s setup? Although it was not necessary to update the site, I made significant edits to our Gruntfile to eliminate redundancy and improve our local server setup.
Stage 2: Scoping Specific Updates (i.e. familiarity deeper dive)
- Learn to love spreadsheets: If you’re reorganizing the codebase, knowing what is already where and what needs to be available to which parts of the site is key. I used spreadsheets to keep track of the association between templates and back-end files, templates and CSS/JS files, and even templates and individual JS functions.
- Also learn to love “find in project”: I have local copies of repositories I never intend to work in, simply for the ease of finding references to functions. Even if you are updating front-end code only, sussing out the precise nature of ajax calls can take you deep into the server side.
- Get to know how people work with the site: In particular, if you want to rearrange the filesystem, make sure everyone who needs to work with those files is on board with your plans. Refactoring should be something that benefits everyone, not something imposed with outside standards of “good” regardless of how they fit with continuing work.
- Get into the details: Comb the code; ask others for explanations; double-check everyone’s understanding including your own.
- Try everything: There is no substitute for seeing what things do in practice. Load the pages, do everything one could do on them. Your understanding from reading the code may not be how it actually works.
- The key: Don’t expect to get everything the first time through. You will find things you missed or misunderstood both as you get to know the setup better, and as you actually start making changes.
Stage 3: Making Updates
- Make changes iteratively, at two levels:
- Level 1 (Macro): If your codebase is structured to support it, section-by-section updates let you begin with the easier pages and complete them as you go along, which is encouraging. Later pages can build on the updates to earlier pages, via shared functionality and styling, which can balance out the difficulty of the rounds of updates.
- Level 2 (Micro): Make changes in waves, testing at each stage that everything still works. Unless you’re throwing things out and starting over, first reorganize the files and eliminate unneeded code, then update and refactor, and finally make changes to the original functionality.
- Level 1 (Macro): If your codebase is structured to support it, section-by-section updates let you begin with the easier pages and complete them as you go along, which is encouraging. Later pages can build on the updates to earlier pages, via shared functionality and styling, which can balance out the difficulty of the rounds of updates.
- Comment comment comment: TODO comments may not be a practical way to record your remaining tasks near the beginning, but they will be when you are partway through. End with comments that let later developers know how things work: did you rethread function calls? Does it take a little parsing to understand a series of conditionals? Brief explanatory comments can save a later reader (including you) a lot of time.
- Use “real” pages: With our setup, it was not practical for me to work directly with the CMS while I was in the “new edits to check every 5 minutes” phase. I could work with the template files as static HTML as well, but I found working with templates directly gave me too much and not enough simultaneously – all the possible elements that could ever appear, but not as many entries in a list, say, as there would be live. Instead I made static copies of specific instantiations and found it a huge help to both styling and JavaScript updates. Just be careful when you transfer your updates to the actual templates that you don’t miss anything, and that you use a good variety of instantiations (if there are such) so that you don’t accidentally make global assumptions based on the way the template is filled out only some of the time.
- Avoid unnecessary work: Before spending any significant time fixing a broken feature, confirm it’s still wanted.
- Test extravagantly: Standard use, edge cases, different orders of actions and errors. I learned the basics of automated testing for my refactoring project and it was a huge help for catching issues and launching changes with confidence – and even just for getting screenshots on different browsers.
Of course the stages aren’t completely linear; 2 and 3 in particular will repeat for various projects, and what “quick win” means for 1 can evolve with your understanding of the site.
While I was drafting this post, CSS Tricks posted 5 Tips for Starting a Front End Refactor. That one is specifically about the CSS codebase but the principles are very much the same: investigate, document, test. I feel that with this approach and enough time and spreadsheets – and willing coworkers who know the languages I don’t – I could refactor the codebase for any website out there.
Jenga photo from Zaimful on Pixabay.