DEV Community

Derek L. Seitz
Derek L. Seitz

Posted on • Originally published at campfire.dlseitz.dev on

#4 - Refactoring A False Sense of Simplicity

Hey everyone! Welcome back to Campfire Logs: The Art of Trial & Error. In my last log, #3 - Data Privacy: Things to Consider, I walked you through how I developed the privacy policy for my website and discussed some of the considerations that developers should make when handling client data. Today, I want to get back to the technical side of things by discussing the refactor, or restructuring of existing code, I recently did on a demo website, including the things I learned along the way.

The Original Demo

About a year ago, I designed and built a demo static eCommerce website for a web development course in college. The requirements weren’t anything crazy:

  • choose a scenario from the provided list

  • create four distinct HTML pages

  • use a single, external CSS stylesheet

  • use JavaScript to create a couple of modals, a shopping cart, and a contact form

Easy enough.

But with this having been my first web site, and not really having anybody to tell me when to put on the brakes with the creativity (it was an online course), it was the perfect way to trigger a bipolar manic episode. Some may say I went a tad overboard on the project (hence the little “menty b” or two that came along with it), and I wouldn’t disagree with them.

While this project, in part, acted as a catalyst for me to resume seeing my therapist, I have to give it props for firing up my interest in web development (sounds contradictory, but it’s true). When I came out on the other side of it, I finally realized “Hey! I can actually do this!”

So what exactly was the problem with the demo?

The Problem

The problem with the demo was this: due to the curriculum requirements for the project, along with the fact that it was meant to be an intro-level website, the focus on “best practices” was more about basic fundamentals than that of the full development lifecycle. Maintainability, scalability, and the potential for future enhancements weren’t considerations during the build. In other words, my codebase became a tightly-coupled, monolithic behemoth that wasn’t easy to read or work with, no matter how well-commented it was. I didn’t understand it enough at the time, but just like with backend development, having a loosely-coupled, modular front end should always be the goal.

On top of that, I tried my best to take an accessibility-first approach. At the time, I understood the importance of semantic HTML, but I didn’t quite grasp that ARIA attributes were meant for filling in gaps for assistive technology (AT) like screen-readers when using HTML tags without inherent semantic meaning. This led me to over-apply attributes such as ARIA-label and ARIA-labelledby, which really cluttered up my code. But hey, ‘A’ for effort, right? I’ll talk about this more a little later.

Now, it really isn’t uncommon for either of these to be overlooked in foundational academic settings. After all, the focus is often on making the code work more so than perfect execution. But that isn’t quite the case for professional-grade work (what I’m aiming for). So a few weeks ago, I decided what better way to continue practicing professional development standards than to refactor this demo. I may have slightly underestimated what I had coming…

Challenging the Notion of Simplicity

I used to associate “simple programs” or “simple design” with having as few files or components as possible. In my early days of coding (not quite the same thing as developing), I thought that meant if an application was contained to a single file, it meant that it was a single object. While in some ways, this isn’t necessarily incorrect, I didn’t yet understand how I was looking at it from a very abstracted or zoomed-out point of view.

I learned, however, to think about the design and architecture of software as a system of interconnected parts. It’s much like the human body with its many systems (immune, digestive, etc.) all working together to function as a whole. This helped me to better understand development practices like the separation of concerns (SoC) and writing DRY (Don’t Repeat Yourself) code.

With these things in mind, I came up with the idea to refactor the demo, because how hard could it possibly be?

The Monolith-to-Module Challenge

One of the hardest parts about revisiting old code is trying to make sense of what it’s actually doing. You can do an excellent job of commenting each section of code and still end up spending a good amount of time scratching your head while trying to figure out what it all means—and that isn’t necessarily a bad thing.

As I got started on this refactor, I really thought the head-scratching meant that I didn’t know as much about web development as I believed I did. However, after finding several snippets of code that could have been better written another way, it didn’t take very long for me to realize this wasn’t the case. The initial confusion actually signaled I had a deeper understanding and that my approach to development had evolved—very much a good thing, right? I had to think back to that first-time mentality from a year ago so that I could decipher what I had intended the code to do, then translate that functionality into a cleaner implementation.

Modularizing the HTML files was the easiest part of this whole process, at least for me. As I’ve mentioned before in some of the other Campfire Logs, I use 11ty (Eleventy), a static site generator (SSG), along with the templating language Nunjucks, to write modular, easier to maintain static websites. It was a breeze breaking the HTML into smaller, reusable components to be injected into a base template of boilerplate HTML using Nunjucks conditional logic (“for-loops” and “if-statements” written in Nunjucks syntax). Sure, this broke up four HTML files into several other files, but this didn’t make the project more complex, just more organized and DRY.

The Cascading Nature of CSS

As I moved on from the HTML-turned-template files, the next logical step was to break up the incredibly long CSS stylesheet. Now remember, per the course project’s requirements, I had to use a single stylesheet for all CSS rules. Because of this, the original styles.css file ended up being 1158 lines long. Fortunately, I had grouped rules by the page to which they applied using comments (/* <comment> */), and those comments created natural breakpoints when separating the rules into separate stylesheets.

That sounds like it made this part incredibly easy as well, but it wasn’t nearly as easy as you’d imagine. I didn’t do the best job at keeping all style rules within their corresponding sections, so once I linked the page-specific stylesheets into the front matter of the corresponding page template and the global stylesheets (for components like the header and footer) into the base layout template, the styling across several pages broke completely.

Great! We’re having so much fun here! But in all actuality, I needed this. Why, you ask? Well let’s look at an example of the <head> section of an HTML document, and I’ll explain:

In the example here, let’s say it is of contact-page.html. We can see that the browser will first load styles.css, which holds the style rules that are common to every webpage on the site. Then, the browser will load contact-page.css, which holds the style rules that are specific only to contact-page.html.

The way a browser applies these stylesheets is in the order they are listed, from top to bottom. If both stylesheets contain a style rule for the same element, the rule that is listed last in the document will override the previous one. This is because the latter styles are applied after the former. The browser prioritizes the last rule it reads.

So with the layouts for most pages across the demo breaking, I realized a few things in rapid succession:

  1. I did not, in fact, have my style rules as organized as I previously thought

  2. Several important base rules must have been overridden somewhere in a later part of the original stylesheet because now they weren’t being applied as I expected them to be

  3. This would require a methodical, page-by-page approach to untangling the mess I had unknowingly created

While this seems like it would be incredibly frustrating, especially after having just broken up my original styles.css file into several purpose-specific stylesheets, it gave me the opportunity (yes, opportunity) to systematically improve my usage of semantic HTML, reduce my overuse of accessibility-focused HTML attributes, and leverage the cascading nature of CSS to improve my design rather than trying to work around it.

Accessibility & Semantic HTML

I think for many, the term “accessibility” in the context of web design and development is believed to mostly mean contrast ratios and font sizes. That’s how I thought about it, at least, until I was taught about assistive technologies like keyboard navigation, screen-readers, and speech recognition tools (among others). I knew what screen-readers were, having messed around with them on Windows, Apple, and Android devices, and I knew I could tab through objects on a web page or desktop, but I didn’t understand how they worked.

Many (but not all) HTML element tags have an inherent meaning recognized by assistive technologies. This is what creates structure and logical groupings that enable these technologies to present information in a useful way to individuals using said tech. For example, screen-readers use semantic HTML tags, like <section>, <form>, hierarchal headings (<h1>, <h2>,…), and others, to navigate documents and read aloud related content in a way that’s more easily understandable for individuals with visual impairments.

For tags such as <div> and <span>, which have no inherent meaning, that’s where you would use ARIA attributes to give them meaning and a role. But as a rule of thumb, it’s best to always try and use a semantic HTML tag first and foremost, and only use ARIA as a last resort. This is often referred to as the First Rule of ARIA.

When I built the demo for class, I didn’t understand accessibility and semantic HTML enough. This led me to incorrectly use semantic tags and add ARIA attributes to tags that simply didn’t need them. For assistive technologies, this can cause a lot of confusion in an HTML document’s structure, which can lead to bad UX for those reliant on accessibility features. Having to go over the entire HTML and CSS during the refactor meant a chance to truly make the demo accessibility-focused beyond just contrast ratios and font sizes, which was important to me.

Looking Back

Modularizing and refactoring the demo website also introduced a few minor bugs in the JavaScript that controlled the interactive components on some of the pages, but that meant I had to make sure event listeners grabbed the corrected HTML elements from the DOM. Because I thought of JS like I did Java (because it’s a programming language, not the similarity in their names), separating concerns into different scripts was a little more instinctual for me and was done in the original project, saving me a bit of work.

While I thought going into the refactor it would be as simple as copying/pasting code into a more modular file structure, I’m really glad that I was wrong. Not only did the refactor give me the chance to go back and visit an old project (the nostalgia was real), it really boosted my self-confidence to see where I was a year ago in my development journey versus where I am now. We often don’t realize just how much we grow and evolve over a period of time because we get trapped thinking about what’s in front of us. As somebody that often questions his own levels of understanding, a project like refactoring an old codebase is a great way to squash feelings of inadequacy and self-doubt. I’m really glad I did it.

TL;DR

I built an intro-level website for a college course a year ago that became a tightly-coupled, monolithic behemoth. Deciding to refactor it to a more professional standard, I learned that while modularizing the HTML was a breeze, breaking up the single, 1,158-line CSS file was much harder. This "mess" provided an opportunity to go back and fix my overuse of ARIA attributes and improve the site's overall accessibility and semantics. Ultimately, the refactor was a major confidence-booster, reminding me of the growth I've made as a developer over the past year.

Before You Go

As always, thank you so much for checking out this Campfire Log! Be sure to comment with your own experiences. Maybe you had a similar one to mine, or maybe yours was way different. I’d love to hear about the challenges you ran into and how you got around them.

The refactored demo is now live. You can check it and its source code out by visiting https://dlseitz.dev/demos/ and clicking the corresponding button. I recommend doing so using a desktop browser simply because the demo isn’t currently mobile-friendly. Making it responsive for smaller screens, as well as improving the custom alerts and shopping cart feature, is next on my list of things, however. Additional dynamic features have also been added, such as an interactive events page and a dedicated page to attributions for the royalty-free media I used, so you may be interested in seeing how some of those work.

Looking ahead to #5, I’ll be talking more about those expanded features. I’ll also explore what it meant to separate the presentation, data, and logic layers of the demo and how that enhanced its modularity, dynamism, and interactivity. Be sure to check back soon!

Top comments (0)