This past week has been absolutely packed with new knowledge. I’ve distilled it as best I can for now. I hope future travellers will benefit from this as much as I have.
This past week I read the first four chapters of Clean Code and several relevant blog articles:
- The Case Against Singletons in WordPress – Michael Toppa
- The Case for Singletons in WordPress – Eric Mann
- Dependency Injection for WordPress Plugins – Michael Toppa
- SOLID: Part 1 – The Single Responsibility Principle – Patkos Csaba, Tuts+
- SOLID: Part 2 – The Open/Closed Principle – Patkos Csaba, Tuts+
I’ll talk about each of these in turn below.
Clean Code, Chapter 1 – Clean Code
Honesty in small things is not a small thing.
This is the omen that kicks off the book, actually belonging to the foreword rather than the first chapter. I really appreciate this quote, much as the author does, because I value the small, the finite, the detailed. Small things matter, and they make all the difference. It reminds me of another quote I greatly enjoy…
It’s always the difference that makes the difference.
Ponder, for a moment, your favorite brands and your favorite experiences. What makes them special? What makes them memorable? I guarantee it’s not their broad generalities. Indeed, it’s their details – their uniqueness from other similar, but different things – that make them special and memorable to you. And, I argue, it is for these very same reasons that the details in your code matter.
It is through practice in the small that professionals gain proficiency and trust for practice in the large.
Attentiveness to detail matters when programming. It means the difference between code that functions properly, and code that brings an entire production site to a halt due to a misspelled variable or missing semi-colon.
A fascinating statistic that the author presents very early in the book is that studies have found “consistent indentation style was one of the most statistically significant indicators of low bug density.” If you’re lackadaisical about how you’re indenting your code, you’re probably less specific about a lot of other things, too.
Making your code readable is as important as making it executable.
This point, I feel, is paramount to everything else that this book covers. Humans will read your code often – maybe not that one small module tucked away in the recesses of the codebase, or that one-off function you had to hammer out at the end of the day specifically, but by-and-large code that you write will be read again by humans. It will either be read by someone else, or by future-you (which, if time has elapsed more than two weeks, makes future-you as good as a total stranger). What will they think when they read this code? Can they read this code? How frustrated do you feel when you cannot read or understand code that someone else has written?
Have you ever been significantly impeded by bad code?
Where does bad code come from? We run into it often, but why is that? I wager that improper planning, poor time management, and unrealistic expectations are the three most common factors of bad code.
Perhaps you felt that you didn’t have time to do a good job; that your boss would be angry with you if you took the time to clean up your code. Perhaps you were just tired of working on this program and wanted it to be over.
The best way to combat writing bad code is to remember that small things matter and that, ultimately, going slow will lead to working fast.
Working Fast = Working Clean
The only way to make the deadline— the only way to go fast— is to keep the code as clean as possible at all times.
This is a phrase I want to have enlarged, bolded, italicised, highlighted, underlined, and framed. It should be a permanent fixture at the top of every code editor, before the signature line on every contract, and in the footnotes of every email and project communication.
Sloppy code slows everyone down. If may feel faster as you’re writing it, because you’re just flying through line after line as you scramble to complete each function. But think about the gravity of what you’re doing – you’re writing the very lining of your own tomb!
How will you extend that code going forward? How will your code interact with the code of your teammates? How will it respond to the third-party integration you now need to include as part of phase 2? What happens when you or the client uncover a bug – will you even be able to trace it and correct it?
If you want to go fast, if you want to get done quickly, if you want your code to be easy to write, make it easy to read.
An inordinate amount of time is dumped into maintaining bad code. It’s an alarmingly and depressingly large statistic. Don’t burn away hours of your future because you couldn’t spare a few moments in the present.
Incremental Improvements beat No improvements
Try and leave this world a little better than you found it… — Robert Stephenson Smyth Baden-Powell
The next time you sift through a project, take some time to change code for the better. To quote the author once more, “Improve a variable name, break apart a function that is doing too much, see if you can’t eliminate one small bit of duplication…”
Clean Code, Chapter 2 – Meaningful Names
One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand.
If you want your code to be understandable to strangers (and I’m including future-you, here), long after you’ve written it, you would do well to choose meaningful names for the things you write. Files, classes, functions, and variables should all be named in such a way that they are completely obvious and even pronounceable.
That last word there, pronounceable, isn’t a prerequisite for names that I had fully considered before reading this book. Now it’s a concept I haven’t been able to shake loose from my head. A function or variable that is pronounceable, say, convert_usd_to_eur(), is far, far easier to verbally reference to your coworkers than one named, say, UsdToEurCnv().
A consistent lexicon is a great boon to the programmers who must use your code.
This is a principle I’ve tried to maintain for almost my entire career as a developer. Not strictly for the sake of other developers, but for myself, too. Using a consistent, predictable naming pattern makes it very easy to correctly guess what something is likely named within a project. If you take no other tips away from this chapter, let it be this one: name things consistently!
Shorter names are generally better than longer ones, so long as they are clear. Add no more context to a name than is necessary.
A long descriptive name is better than a long descriptive comment.
Be concise, but be clear. “Post ID” is better than “The ID of the post”. However, “ID” is not better than “Post ID”. However, while striving for brevity, remember that it’s better for your function or variable name to be descriptive than it is to provide a descriptive comment.
People are afraid of renaming things for fear that some other developers will object.
Don’t be afraid to rename something in this age of “Global Find and Replace”. As the author suggests, you’ll likely surprise someone, but that is far better than the alternative of further cementing a poorly named item in your project.
Clean Code, Chapter 3 – Functions
The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.
I love this excerpt, and the paragraph that surrounds it. The author cannot justify his assertion that smaller functions are better, except his four decades of experience in writing functions of all shapes and sizes. The shorter a function is, the easier it is to read, and the smaller the space for bugs to hide.
Your functions should tell a story.
Every function in this program was just two, or three, or four lines long. Each was transparently obvious. Each told a story. And each led you to the next in a compelling order. That’s how short your functions should be!
The program referenced in the quote above did some pretty neat and seemingly advanced stuff, and even still it could be broken down to functions that were an average of four lines long. That’s a pretty lofty goal to aspire towards, but a goal worth achieving nevertheless.
The implications here are that any nested structures currently found in your functions (
switch statements, iteration loops, etc) are better suited in their own separate functions.
Functions should do one thing. They should do it well. They should do it only.
Functions that do one thing cannot be reasonably divided into sections.
Break apart those large functions! Make sure every function has a single purpose, and remove everything else it’s doing until that purpose is met. It is OK if a function’s sole purpose is to call three other functions, but make sure its name clearly reflects that purpose (e.g. find_and_delete_invalid_subscriptions() – This function is clearly doing two different things because the word “and” appears in its name. If those two things are two different function calls – find_invalid_subscriptions() and delete_invalid_subscriptions() – that’s a-o-fine).
Your function promises to do one thing, but it also does other hidden things. Sometimes it will make unexpected changes to the variables of its own class.
If a function conditionally behaves in multiple different ways, or it modifies something outside of the scope of its single, solitary purpose, its doing too much. Refactor that function in such a way that it does its one obvious purpose, and put the other bits into a separate function.
Functions should either do something or answer something, but not both. Either your function should change the state of an object, or it should return some information about that object.
On Function Parameters…
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification— and then shouldn’t be used anyway.
This is something I want to explore more in-depth, and I’d wager its worthy of a blog post all its own. I agree that fewer parameters is preferred to many (e.g.
$args = array() vs
$param1, $param2, $param3, ...), but I’m not so sure how I feel about “zero arguments”. That is something I’ll need more time to explore.
Clean Code, Chapter 4 – Comments
Nothing can be quite so helpful as a well-placed comment. Nothing can clutter up a module more than frivolous dogmatic comments. Nothing can be quite so damaging as an old crufty comment that propagates lies and misinformation.
While reading this chapter I found myself disagreeing with the author quite often. You see, I’ve always found code comments and inline documentation to be tremendously helpful – both while reading and writing code – and he maintains the position that comments are a crutch and too-often clutter up the codebase.
Comments are a great way to get your thoughts down on how you think a function should be written, and what generally needs to happen, in plain English. They’re also a great way to see a quick summary of what a conditional statement may be testing, or a helpful note about why a particular section is written in such an obviously non-optimal way (e.g. “This function checks for [something] in this way because [some other method] isn’t available at runtime”).
After wrestling with many of his points over the weekend, I’m starting to shift my position.
Don’t comment bad code — rewrite it. — Brian W. Kernighan and P. J. Plaugher
[W]hen you find yourself in a position where you need to write a comment, think it through and see whether there isn’t some way to turn the tables and express yourself in code.
Replace the temptation to create noise with the determination to clean your code. You’ll find it makes you a better and happier programmer.
[Good] comments do not make up for bad code.
Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments.
Most of my struggles throughout this chapter came to an abrupt end when I encountered the above quotes. Prior to this I saw our author as a simple comment hater. When I read, and then re-read these lines, though, I started to evaluate the many ways in which I misused comments in my code.
Don’t waste precious minutes of your limited time on this earth adding comments to poorly-written code. Put those minutes to better use and improve the code. You won’t only be improving your own life, you’ll also be improving the lives of everyone else who will have to interact with that code in the future. You’ll be doing everyone a better favor, too, by improving the code than you will by merely describing it.
Blog Posts – Objects, Singletons, and Dependency Injection, oh my!
I don’t have much commentary to add to the blog articles I read, but I do highly recommend reading them. I’m of the mind that singletons (classes that are designed to be instantiated exactly once) are generally bad and to be avoided, for all the reasons Michael Toppa raises in his article.
I’ve personally been drawn towards using singletons across a number of projects. I liked working within a class structure because of the clean namespace it afforded me. Even as recently as this week I’ve placed code inside of a class that I only intend to instantiate once, globally. I know it’s bad – my awareness of my habitual problems is the entire reason I’ve committed to this 16-week series!
Bonus reading! This weeks serendipitous look at Object-Oriented Programming reminded me of an article I read back in August titled OOP is Not Your Hammer by John Hann.
WordPress and Backbone.js
I don’t think I can say enough good things to fully do this session justice. The three presenters, K.Adam White, Carl Danley, and Zack Tollman each did a phenomenal job in breaking down Backbone and making it approachable, even to a beginner. I’ve had a keen interest in Backbone.js for over a year now, but I just didn’t have the ambition or fortitude to take it on until after watching this session. Now I can’t wait to put it to use. I’ll probably start using it this week, in fact.
To conclude this past week’s study, I leave you with a quote from the end of the Foreword to Clean Code:
Learning to write clean code is hard work. It requires more than just the knowledge of principles and patterns. You must sweat over it. You must practice it yourself, and watch yourself fail. You must watch others practice it and fail.
But never forget that your real goal is to tell the story of the system, and that the functions you write need to fit cleanly together into a clear and precise language to help you with that telling.
We are in for a long haul. This work will not be easy, but it will be worth it. Everything else builds from this foundation, so it is important that we get it right.
Over the next week, starting today, I’ll be reading chapters 5-8 of Clean Code.
Are you keeping up? I’d love to hear your thoughts on any insight you’ve gained or any of the commentary I’ve added above. Leave some feedback in the comments!