This week, Chris Ferdinandi examined a clever JavaScript snippet, one that’s written creatively with new syntax features, but is perhaps less readable and performant. It’s a quick read, but his callout of our industry’s fixation on cleverness is worth… calling out:
…we’ve become obsessed as an industry with brevity and clever code, and it results in code that’s sometimes less performant, and typically harder to read and make sense of for most people.
He made a similar argument late last month when he wrote about code readability, noting that brevity might look cool but ultimately leads to all sorts of issues in a codebase:
Often, web developers are obsessed with brevity. There’s this thing were developers will try to write the same function in the fewest number of characters possible.
Personally, I think brevity is pointless. Readability is a lot more important.
I entirely agree with Chris on this point, however, I think there is one important distinction to make and that’s the difference between code that’s intended as a prototype and code that’s intended for production. As Jeremy Keith argued a short while ago:
What’s interesting is that—when it comes to prototyping—our usual front-end priorities can and should go out the window. The priority now is speed. If that means sacrificing semantics or performance, then so be it. If I’m building a prototype and I find myself thinking “now, what’s the right class name for this component?”, then I know I’m in the wrong mindset. That question might be valid for production code, but it’s a waste of time for prototypes.
I agree with Chris that we should be writing code that is easy to read when we’re in production. I also think experimenting with code in this way is a good thing when it comes to prototypes. We shouldn’t ever shy away from playing with code and pushing things a little bit – so long as we’re not doing that in a giant web app with a a team of other developers working alongside us.
I’ve noticed that there are some folks that are doing genuinely ingenious things with Sass. I consistently sit back and think, “Wow, I’ve never seen anything like this before.” But when it comes to a production web app that has to be understood by hundreds of people at the same time, I don’t believe that this is the reaction we want when someone looks at the code.
As a result, I’ve been trying to write Sass code that is actually so simple that it almost looks dumb. One easy way to make code a lot simpler is to reduce the amount of nesting:
.element {
.heading { ... }
}
This looks fine when there’s code inside — and it’s pretty easy to understand — but add a complex bit of design in the mix (say, using pseudo elements and media queries) and you suddenly have a rather complex set of rules in front of you. Creativity and cleverness can be harder to scan and identify one small part of the code that you’re looking for. Plus, in this example, we’ve unnecessarily made our .heading
class a little bit more specific which might encourage us to override things in a hacky way elsewhere in the codebase.
We could write the following:
.element { ... }
.element-heading { ... }
I know this looks foolishly simple but the relationship between these two classes is easier to see and easier to extend in the future. Bundling all that code into a single nested class can get out of hand real fast. Even if it happens to look a lot cooler.
(As an aside, Andy Bell’s post on using the ampersand in Sass — and the resulting comments — is a great example of the clash between creativity and practicality.)
Anyway, the point I’m trying to make here is that CSS (and JavaScript for that matter) is a strange language because there are no definite rules you can make about it. It all really depends on the codebase and the project. But I think we can safely say that our code ought to be a lot more boring than our prototypes when it moves to production.
Continue to make prototypes that are wild and experimental or impossibly weird! Code quality be damned.
The problem with playing fast-n-loose with prototype code is that, all too often, prototype code becomes production code. And the time to sanitize it may not always be available.
Agreed. This is my life.
“nothing is as permanent as a temporary solution.”
So yeah i agree with you. The amount of times i have seen my prototypes go to production is staggering.
I deal with the pain of “not entirely sanitized prototype code” in production a lot. My view is that it’s fine so long as your team is good about constantly refactoring code in general (which mine is). This wastes some time but not nearly enough time as is wasted when engineers (especially Junior) try to write production ready code when the core problem hasn’t even been solved.
Why not write
.element {
…
&-heading { … }
}
@Bytebrand
I used this approach while using SMACSS naming convention then dropped it quickly, because I made a partial file for every module ( .element in this case ), writing everything inside one brackets make no sense for me as it reduces my overall visibility for the module. So I prefer writing my SASS as described in this article. Though, I nest the modifiers inside the relevant class, for example :
.element {
&#{–bigger} {
font-size: 20px;
}
}
This gives me a lot of comfort and saves my time when I scan the file.
To give you the widest possible space for adding any stuff to the working code without the need to think about structure and coding standards. You can arrange and fix it later after being solid with the results.
I agree, if you are trying to come up with a logic flow you can do simple. But when prototyping, I have always needed to use production names, comments and code. It’s great if you setup a culture where this is possible.
I wonder if that is what the author was really trying to say. Change the culture.
Me:I’m not fully sold in the idea.
It’s about clarity and moving away from nesting because it naturally leads to more complexity.
Thanks for the mention. One thing to clarify (that I do mention in the second article you linked to) is that a big reason why readibility is more important is because you can let tools condensed and optimize your code for you.
Writing short code is pointless when Uglify can take whatever you feed it an spit out something that’s a fraction of the size and completely unreadable to humans.
I like to ensure there is always one root selector in our SCSS partials:
Rather than having an entirely flat SCSS file (like the example)
The reason being, it ensures that the styles added to the partial are relevant to that partial. With a flat SCSS file, it’s easy to add in a selector that isn’t at all related to the partial as a whole. When developers are in a rush, rather than finding the right place to put code, they’ll put it in the first place that works, which is any file when all SCSS partials are flat. Using a single root selector scopes all of the styles to the component that the partial is responsible for, which prevents unrelated styles being added.
Obviously someone could add a style outside of that root selector, but then it stands out a lot more in code review.
I love sass nesting because for me it is perfectly readable. I make heavy use of nesting and I don’t like too many class names. Quite often it only needs a module class and all tags inside can be addressed by being nested in this class name.
I also don’t write one attribute per line – I have the class and all its attributes in a single line. I got used to it. It is compact and beautiful to my eyes and for production it is minified. Your example would hurt my eyes so bad
A lot can be said about why clever code is bad, but the SCSS example fails to highlight this, and it’s very misleading:
It claims that the second code example is simpler, because there is no creativity or cleverness, and the second one is foolishly simple, but they are both foolishly simple. It also claims that the first one looks cooler, which is entirely subjective, and irrelevant.
The two code examples are not the same. The first one will produce “.element .heading {}”, which is very different from “.element-heading {}”. It can be reasoned that the point is that you should not nest selectors, but that point is touched upon way too lightly by saying we have made the selector a bit more specific. It also opens new problems: Renaming the class is harder because now you have to do multiple replacements, you cannot lift an element out of the container without also making changes to the CSS code, and probably others. These might sound like nitpicking, but the important point is that you are making tradeoffs, one is not objectively better than the other.
The point the article makes about “I know this looks foolishly simple but the relationship between these two classes is easier to see and easier to extend in the future” is entirely wrong in my opinion, and the reverse is true. If you use the second style, there is no guarantuee where the declarations start or end. You, or other people might make a mistake, and put in other declarations, for other comonents, inbetween. The first example gives you a guarantuee by its syntax and removes the possibility of human error: all the styles that belong to this component and its children, are here, between the {} blocks. You cannot put it any styles that belong to another component not under this tree, because you would have to close the {} block, and reopen it later. This increases clarity, rather than decrease it.
It is also much easier to refactor: Renaming the class, or moving the declarations when they become too much to a different file are all easier, and because of the guarantuee you can be sure that you are moving everything, and not leaving anything behind, or moving something that you are not supposed to.
The point about “add a complex bit of design in the mix (say, using pseudo elements and media queries) and you suddenly have a rather complex set of rules in front of you”, is true, but that is caused by your application/requirements are growing bigger, the complexity will be there either way, nesting/unnesting declarations is not going to affect it that much.
Honestly? Bad code is bad. If we always chase the high end of performance curve we’d be forced to flatly disregard functional programming and in many cases OO due to their performance hit over optimized procedural logic.
However, I tend to think “readability” arguments favor the low end of the talent pool. People quote uncle Bob with religious fervor, then put words in his mouth going so far as to say even language features are bad because “readability.” SOLID has also been broadly misunderstood in the same fashion.
Statements like “reduce nesting” are all well and good, but where is the argument to cyclomatic complexity concerns? Personally, if I read code exposing higher order functions or nested invocations where I’m forced to continuously symbolically trace the flow of the application I tend to find that unreadable due to conceptual discontinuity, even though it is the height of fashion.
An issue that comes up, though, is that the insistence by everyone to go fast often means that a prototype, written cleverly, is demoed to leadership who dont see a demo, or a prototype, they see a finished product that they think should be launched tommorrow. And all thay clever unreadable unmaintainable production code goes into production, or at best, you get a few weeks time to try to clean it up.
When developers are in a rush, rather than finding the right place to put code, they’ll put it in the first place that works, which is any file when all SCSS partials are flat. Using a single root selector scopes all of the styles to the component that the partial is responsible for, which prevents unrelated styles being added.