Quick fix

by Michael Scharnagl

When viewing code you will most likely come around a note along the lines of // Quick fix. Todo: Cleanup later at some point. There are many reasons developers went for a quick fix instead of a proper fix.

A critical bug was detected after a new release which needs to be fixed immediately, and there is no option to revert to an older version. Or a feature needs to be released tomorrow and you found a bug last minute and there is simple no way to postpone the feature and not enough time to do a proper fix.

A comic showing two persons talking about quick fix. First image: First person says "Can you just do a quick fix? It's really urgent...", second person responds with "Yeah... well... there are two options...". Next image: Person two continues saying "I can do a quick fix right now, but it won't handle all cases and someone will have to redo it and fix it properly at some point. It'll be difficult to debug and in the end it'll take twice as long. Next image: person two continues saying "Or we can do things by the book, and write a real fix. But it won't be ready before tomorrow because there are a few dependencies to handle. But when it's done it'll be clean, good code. Fourth image: person one says "Let's go for the quick fix option. Quick fixes are good". Second person says "Of course, what was I thinking..."
Web comic by CommitStrip. Original comic can be found here

Avoiding quick fixes

There are many ways to avoid quick fixes at the first place. As I mostly do Front-end development I will focus on CSS, HTML and JavaScript here.

HTML

Browsers try everything to fix HTML errors, but it is of course still possible to mess it up. You could forget to close an HTML element, or you could use wrong attributes or you could use a different closing tag as intended. The first thing you can do is validating your HTML. While the validator does give you good idea what is wrong and should be fixed it can’t handle everything.

Some HTML problems may only appear after interacting with the site, so manual testing is still required for checking HTML errors.

CSS

All CSS features have different browser support, there are still features which require a Prefix in certain browsers and there are also features which need a different syntax in different browsers. On top of that browsers will handle certain CSS differently. There are different ways to handle this:

First, we can make use of the fact that browsers will ignore CSS properties and values they are not aware of.

.element {
   color: red;
   color: hsl(0, 100%, 50%);
}

All browsers not aware of hsl() will use the value red here for color, while all other will use the hsl() value.

To handle Prefixes we can use autoprefixer in our build process so we don’t have to write all the Prefixes by ourselves.

Next, we can use feature queries.

.element {
   // code that will run in every browsers, define the fallback for CSS Grid here
}

@supports (display: grid) {
   // code that will only run if CSS Grid is supported by the browser 
}

This way we can use new CSS features for supported browsers and still ensure that older browsers look okay, by providing the fallback before defining the new CSS inside @supports.

Finally, we should use min-width/max-width instead of an explicit width to ensure it doesn’t break for long words or content. We should also build mobile first so in the worst case a user will see the mobile styling.

Automatic testing of CSS is possible, but in my opinion not practical. There are some tools to compare screenshots before/after a deploy, but there are hundreds of browsers out there used on thousands of different devices with lots of different screen sizes. The web is not print, we cannot exactly say how a website will look in any browser, but we can use feature detection and robust CSS to ensure that the site doesn’t look broken in a browser.

So, for CSS, manual testing is still the way to go. You should test early and in various browsers on various screen sizes. If you already have statistics you could check there the top 10 browsers and screen sizes and ensure that your tests at least cover these.

JavaScript

Same time ago a client reported a bug, which made some parts of the site unusable for them. They were using Safari on an iPhone 6 in this case. I first tried to reproduce the error in an emulator, next on an iPhone 5 with the same Safari version, but it worked fine for me in both cases. Eventually I met the client and tested directly on their device. There I could finally reproduce it, but still had no idea why this would only fail on this device on not on another one using the same browser. To make a long story short, they were using Safari in incognito mode and our localStorage detection failed in this case.

So before using localStorage, we used this check:

if ('localStorage' in window) {
    // localStorage is supported, run the code
}

At first this looks like it will work. The problem is that by using the incognito mode in Safari, ‘localStorage’ was available, but once you use localStorage.setItem() it will throw an ecxeption because of security reasons.

After changing our feature detection to:

var isLocalStorageSupported = function () {
var mod = 'test';
    try {
        localStorage.setItem(mod, mod);
        localStorage.removeItem(mod);
        return true;
    } catch(e) {
        return false;
    }
}

it worked fine again. You can find more details about this in the Modernizr feature detection script.

So, before using a JavaScript feature you should always add a check to ensure the browser actually knows how to handle it. I don’t use Modernizr, but I often check the code for feature detects there. Often there are browser bugs or other issues and the Modernizr detect mostly handles these correctly to ensure the check will only be successful if the browser really supports the feature.

Furthermore, you should write robust JavaScript. Mat​hia⁠s S​chäf⁠er wrote a fantastic developer guide about robust Client-Side JavaScript, where he writes about Progressive enhancement, How JavaScript might fail and How to prevent failure. You should read it and came back later to continue reading here.

Automatic testing

There are various solutions available to automatically test code. There are test libraries for Accessibility , JavaScript and many more.

I won’t go in to details here, but you should always add tests to find errors before a user will find them. Personally, I don’t do enough testing at the moment, but it is on top of my priority list to change it this year and get better at it.

It should be noted that even the best automatic testing solution will not catch all errors, so be sure to always test manually in as many browsers and on as many devices as possible.

Refactoring quick fixes

Tests help to prevent a lot of potential bugs, but even with the best test setup and lots of manual testing it is still possible that bugs make it into production. Bugs occurring in production happens to everyone.

I remember some years ago, Google shipped the landing page for the Chrome browser with a JavaScript error, which made the download button unusable for all users. When something like this happens you don’t want to waste time and get a fix out as soon as possible.

Once the fix is done, the first thing you should do is open a new issue/ticket to refactor it and find the real issue behind it. This ticket has to get the highest priority and you should start working on it immediately the next day even if you have other things planned.
Some project manager might not see the value of doing a proper fix at first – “It works now, why should we invest more time in it…”. After explaing to them that a quick fix will sooner or later result in more bugs, which will cost a lot of time and money, they mostly understand and will give you time to do the proper fix now.

Writing a comment that it should be properly refactored is not enough. Go search your current project for »Quick fix« or »Fix later« and you will probably find some and will also notice that some of these comments were added a long time ago and that there is no open issue about it.

A quick fix has to be done sometimes, but you should always react immediately after the fix is out and do a proper rewrite. You should also find the real issue why the problem occured and add a new test so this won’t happen again. And you should always use future-friendly and robust HTML, CSS and JavaScript.

Michael Scharnagl

Portrait Michael Scharnagl

Follow me: @justmarkup

Subscribe to RSS: /feed

A freelance front-end developer focusing on HTML5, CSS, progressive enhancement and web performance.