3 ways your team can improve code quality

Pair programming with new hires

Even if the new hire is a great developer, they will inevitably have their own way of doing things that may not marry up perfectly to the way your agency does things. Taking the time to do some pair programming and code reviews can go a long way in getting them onto the same page.

There are also production benefits to this practise: Williams et al (2000), The Costs and Benefits of Pair Programming, indicates that for a slightly increased development time of around 15%, projects which utilise pair programming show a reduction in bugs and risk, as well as improving team skills and communication.

While some managers may wince at the idea of increasing development time, take this into consideration: between bugfixing, repeated deployments, QA testing and back-and-forth with clients, program defects can take up as much development time as building the thing in the first place. Even worse, if hard limits on time allocated to bugfixing is not discussed with the client, agencies can easily overspend on time spent simply getting a website up to standard. Without a doubt, it is more cost effective to do things right the first time around. In the long run pair programming could greatly decrease the cost and development time of projects.

Pair programming has also been shown to improve developer engagement and satisfaction, as well as making devs more confident in their solutions. There’s also evidence that pair programming may help with inclusivity, particularly improving female representation in programming. It might be that it’s a break from the monotony of independent work,  the learning experience or just the chance to improve work relationships, but it’s clear that developers who code in pairs are happier and have more pride in their work.

There are even Git workflows, such as Trunk-based development, which embrace the idea of pair programming whole-heartedly. This style of development is not only great for improving development quality in small teams, but also improves each team member by forcing them to explain and justify their code while taking in contributions from their peers.

Have everyone use the same auto-formatter

Formatting code is one of the longest running arguments in programming. Line length, tabs vs spaces, padding parenthesis with whitespace – all these issues can be made consistent by using a formatter. Even better, you can enable format-on-save in most IDE settings, meaning you can forget about formatting entirely. Just press save, et voila! Beautiful code.

However, this becomes an issue when working on a team of developers. Why? Well, if only one person is using a formatter, every time they save a file the whole structure will change. This will show up in git, so it becomes impossible to see what has changed with each commit, because when a formatter does its job it can change every single line of code. If you can’t see what’s changed, it becomes hard to figure out how something went wrong when it inevitably does. It also really messes up any merges you try. The same goes for if multiple people are using formatters with different settings. Each will end up overwriting the previous developer’s code every time they work on a file.

The solution is for everyone on the team to use the same settings. We can then have beautiful, readable code, with no effort and no problems with source control. This takes a bit of time to setup, but for the time saved later on it’s worth it.

Formatters

There are a few known formatters for most editors – I’ll be focusing on VSCode, since it’s what I used. If you use a different editor, google is your friend: experience will vary based on what you use.

Personally, I have been using the Prettier extension to do my formatting as it supports all the languages I use on a regular basis. If you’re a frontend developer, chances are this will cover the majority of languages you need to use.

For other languages, there are plenty of other extensions that will handle formatting of these languages. You may need to configure your VSCode settings to get them working for specific languages.

If you’re a backend developer and use Visual Studio, there are similar extensions which can handle formatting of any language you require.

Linters

Formatters tend to take their rules from linters – scripts that raise issues if your code doesn’t follow a particular standard. It’s a good idea to run linters alongside your formatter, so they can highlight any issues you missed or if you forgot to format a particular file. This might be redundant, however, if you opt to enable format-on-save in VSCode. This way, you won’t even need to think about formatting – every time you save a file, everything is automatically taken care of.

Setting up format-on-save in VSCode

VSCode official supports format-on-save, so this can be enabled by changing a property in your settings.json file. To access this file, press Ctrl + Shift + P and type in ‘settings’ – then select ‘Preferences: Open settings (JSON)’.

Add the following line:

"editor.formatOnSave": true
 
If not already set, you will also want to set your default formatter here:
 
"editor.defaultFormatter": "esbenp.prettier-vscode"
 

Once you’ve done this, save the file and reload your VSCode. Your files will now be formatted automatically, with zero time and effort!

Write up a methodology guidebook

We all know (roughly) how to use BEM, sure. We all know how to name variables, how to use the block-element-modifier pattern, and how to structure our CSS for performance and readability.

The problem is that even within those rules, everyone has idiosyncrasies in the way they use them. Some people who use BEM will insist on heavy nesting. Some people will style elements directly, even though it encourages the unholy !important rule.

Drilling down into exactly what the guidelines for code quality are helps new developers understand what is expected of them, encourages learning and higher code quality, and overall reduces potential problems caused by different approaches. It also helps bridge the gap between senior and junior/mid developers – by having the important information in writing, it’s not locked away in the minds of only a few developers.

Take CSS, for example. It’s a great language – very powerful. The problem is that, by using its multitude of features without any rules, we end up writing difficult to understand code. This is circumvented by methodologies, yes, but methodologies don’t always go into the detail they should. Over time, agencies and individuals accumulate a set of rules which guide them to a cleaner codebase.

Keeping and maintaining a document or web page that explains these rules, including the minute details and unique features of an agencies own approach, is a fantastic tool for both new hires and old heads. Including this document in the required reading for new hires gives them a head-start, and being strict about these rules when reviewing pull requests can help to solidify the best approach in the workflow of developers.

There are a few principles which make up a solid coding style guide:

1. Comprehensive & accessible

Your style guide should be well documented: Lack of documentation will lead to confusion, and allows developers to fill in the blanks themselves. On the flipside, this document should be no longer than it needs to be. Nobody will be able to remember a hundred different rules, and so code standards will be fragmented and inconsistent.

2. Logical & justified

This material should not boil down to someone’s opinion, and if it is it must be well thought out and justified. If not, it’s likely that developers will disagree with the style guide and may push to change the guide. It’s a good idea to get everyone’s own opinion from your team and then debate pros and cons of each. The standards should work for everyone, not just one or two developers.

3. Purpose-built

While online guides are a fantastic starting point, they may not consider all the nuances and workflows of your team. Whether you need commits written a certain way for Git flow, or you’re using a CSS framework such as Tailwind, there will be unique requirements for every team.

4. Enforced

It’s no use having a style guide if it’s just going to be ignored! The two most obvious ways to enforce standards are with pull requests, and pair programming. I would personally advocate for pair programming, since it’s a much more focused format and because it’s easy to skim over a pull request on a really busy day, but as with the previous point: Whatever works best for your team.

Coding Standards Resources & Examples

GeeksforGeeks – Code Standards and Guidelines

CXPartners front-end coding standards

O3 World Front-End Coding Standards (HTML & CSS)

imarc Frontend Handbook

 

6 tips to avoid headaches in SCSS

1. Never style elements

This is probably the biggest cause of headaches, at least in my experience. It seems innocent enough to style a button or a heading – they’re buttons and headings, of course they should look like buttons and headings.

// don't do this!
button {
  background-color: $color-btn;
  border-radius: 4px;
}

// nooooo!
h2 {
  font-size: 40px;
  font-weight: bold;
}

But!

What if you have an element that should look like a link, but is really a button? Or if you have a button which needs to look different from all the others, such as with hamburger/pancake menus (there’s a lot of debate on exactly which food item these look like, I think it’s a pancake).

What if your headings need a different size or style in a particular context?

In all these cases, you would have to manually un-style these elements in their own class. And because element styling wins specificity wars over classes, you would often need to use the !important rule – a huge no-no.

Instead, assign classes to your elements. This is much more expressive than styling raw elements as you can state the intention of the element through it’s class. You can also reuse the class on different elements, such as with buttons and links.

// better
.button {}
.heading-2 {}
// now you can reuse the classes!
<button class="button">I am a button</>
<a class="button">I am link, but I look like a button</>

If you need to style elements for a Rich Text Editor or WYSIWYG section, or anywhere else you might not be able to add classes directly, you can do so by nesting. By putting a .rte class on the container for these sections, you can scope your element styles to only target what you need to.

// _rte.scss

.rte {
  & h2 {
    font-size: 28px;
    font-family: $font-headings;
    font-weight: bold;
    line-height: 1.3;
  }

  & p {
    font-size: 16px;
    margin-bottom: 16px;
  }

  & ul {
    // etc...
  }
}
// article template

<article class="rte">
  <!-- content added by cms -->
</article>

2. Strive to never use !important

Your CSS should follow rules, and your classes shouldn’t overstep each other. The more tangled up in the web of specificity and nested selectors your code becomes, the harder your codebase will be to work with. You’ll end up adding !important to properties that really have no need to be, and the more of these rules you have in the first place the more you’ll have to use it again to override these rules. It’s a downward spiral of manually forcing specificity, and it has rippling consequences for your CSS.

There are a few ways to avoid using !important[]: For one, keeping your CSS structure as flat as possible can avoid any specificity wars that could crop up. Nesting CSS, and using complex selectors to target classes in specific situations, are things many developers do without realising they are lining up headaches and delays for themselves in future.

3. Use reset.css

Cross-browser consistency is one of the major problems surrounding not only CSS, but also JS and even accessibility with ARIA. In CSS, we can lay out a level playing field using a reset.css file. This will remove any browser-specified styles, such as margins, font sizes, button styles etc. so every browser will show the same thing.

reset.css is also great because we don’t need to waste time overwriting default styles: If your <button /> needs to have a transparent background and no borders, we would normally need to specify these in our own CSS. This way, we know any CSS we are writing is additive instead of being subtractive.

.button {
  // these properties wouldn't be necessary with reset.css
  background-color: transparent;
  border: none;
}

Subtractive CSS, where we write styles to overwrite other styles, is generally a big no-no as it adds a level of confusion to what a class is doing. CSS classes, as with anything in programming, should be concise and to the point. If you find yourself writing subtractive or overwriting CSS, it may be worth tracing back to find what it’s overwriting, and breaking down the original styles further using placeholders[link] or mixins[link].

You could also use normalize.css. This will maintain a set of default page margins and other element-level styles across browsers. Personally, I prefer reset.css due to the fact that I want to control everything on a page without being interrupted by default styles – I don’t want any page to have a margin on the body, for example, and writing code to undo these margins makes my code confusing. However, this might work better for you if you want some defaults.

4. Use variables to stay DRY

DRY, meaning Don’t Repeat Yourself, is a key concept to understand for any kind of programming. In SCSS, the best place to start with this is in using variables, placeholders and mixins. The most common of these you’ll be using is variables.

Let’s say you’re looking at a design you need to create, and it has many colours across it. You can make your life much easier by assigning these colours to variables, perhaps with a kind of hierarchy which relates to the brand you’re working with. There are lots of different ways to name variables, as outlined in this CSS Tricks article.

Another great use of SCSS variables is naming the top level of components. Here, I use $module to store the name of the component and am then free to reuse it in other places, without needing to worry if I want to change the name of that component for some reason.

// we can change $module at any time in one place
$module: 'nav';

.#{$module} {
  &__dropdown-link {
    position: relative;
  }

  &__dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    display: hidden;
    
    .#{$module}__dropdown-link:hover & {
      display: block;
    }
  }
// above css applied to html, for reference

<li class="nav__dropdown-link>
  <a>Link title</a>
  <ul class="nav__dropdown">
    ...
  </ul>
</li>

5. Use placeholders

Placeholders are a great way to save time and file size with SCSS. They are essentially groups of properties which you can apply in a similar way to variables, and further build on top of them.

I’ve used placeholders on my own site to help generate a set of paragraph styles using the Golden Ratio Typography Calculator (check it out!) which downsize appropriately at different resolutions:

// these styles...

%t-1\/2 {
  font-size: 14px;
  line-height: 1.786;
}

%t-1 {
  font-size: 18px;
  line-height: 1.722;
}

%t-2 {
  font-size: 23px;
  line-height: 1.652;
}
// ...can be easily reused for different breakpoints
.t {
  &-1 {
    @extend %t-1\/2;
    @screen lg { // @screen is a tailwind directive - these are just desktop-first breakpoints!
      @extend %t-1;
    }
  }
  &-2 {
    @extend %t-1;
    @screen lg {
      @extend %t-2;
    }
  }
}

As well as needing to write less code, we are also building a sensible design system with our CSS to ensure consistency between elements and enforce a single source of truth.

6. Don’t set a max-width on <main>

More often than not, any content on a webpage has a certain max-width which it cannot exceed. This helps with readability and keeps the page content flush all the way down.

If you’re a beginner, it may be instinctive to set this max-width on an element that’s quite high up in the hierarchy – the <main> element for instance, or even the <body>. On a page that has the same background color all the way down, this might be perfectly fine. Most webpages, however, are broken up by different sections that have a background color spanning the entire width of the page.

The issue you will run into by setting a max-width on the <main>, is that this background color will be limited by the max-width. Beyond this max-width, the background color will be white (or whatever color the <body> is set to).

// index.html

<main>
  <section class="section section--bg-primary">
    <div class="section__inner">
      <h2>Hello world!</h2>
      <p class="paragraph">
        Lorem ipsum dolor sit amet...
      </p>
    </div>
  </section>
  <section class="section section--bg-secondary">
    <div class="section__inner">
      <h2>Hello again world!</h2>
      <p class="paragraph">
        Lorem ipsum dolor sit amet...
      </p>
    </div>
  </section>
</main>
// layout/_section.scss

.section {
  // use the parent element to add padding
  padding: 48px 16px;

  &--bg-primary {
    background-color: $color-primary;
    color: white;
  }
  
  &--bg-secondary {
    background-color: $color-secondary;
    color: black;
  }

  &__inner {
    // set the max-width on the inner element
    max-width: $max-w-page;
    margin: 0 auto;
  }
}