Writing Clean Code and the Practice of Programming

Photo by Toa Heftiba on Unsplash
“The purpose of style is to make the code easy to read for yourself and others, and good style is crucial to good programming.”
— Brian W. Kerninghan, “The Practice of Programming”

When you’re teaching yourself, it’s easy to pick up bad habits or styles because you don’t have someone checking your work. You don’t have many reference points for clean code because not many books/courses directly address these.

In this article, I want to give you some actionable advice on writing clean, beautiful code.

Five Simple, Actionable Good-Programming Practices:

1. Put some thought into choosing your variables’ names

“Should I be descriptive, or can I be lazy?”

That’s the conundrum we all face when creating a new variable.

I find Brian W. Kernighan’s advice (in the above mentioned book) really helpful here:

  • Global functions, classes, and structures should have descriptive names that suggest their role in a program
  • By contrast, shorter names suffice for local variables; within a function, n may be sufficient, npoints is fine, and numberofPoints is overkill
  • Local variables used in conventional ways can have very short names. The use of i and j for loop indices, p and q for pointers, and s and t for strings is so frequent that there is little profit and perhaps some loss in longer names.

Anyway, we have it a lot better than Brian did in the ‘90s when he wrote this book —like IDEs that can autocomplete our variable names.

So can you even justify being lazy now?

2. Create new functions wherever necessary

It’s easy to understand the syntax of writing functions in your favorite language. But it takes practice and some sense of design to learn when to break the code into functions.

One goal is to design functions such that they can be reused when extending your program to new cases.

What more? Making such design choices is what makes programming fun.

Here are three heuristics from Bob Martin’s book “Clean Code” that’ll guide you while making such choices:

  • Functions should be small. How small? No more than a screenful or 20 lines.
  • Functions should have descriptive names. The smaller and more focused a function is, the easier it is to choose a descriptive name. Don’t be afraid to make a name long. A long descriptive name is better than a short enigmatic name. A long descriptive name is better than a long descriptive comment.
  • Functions should do only one thing and have no side effect” — its intent should be clear from its name.

When you first write a function it’ll probably come out long and complicated and not follow any of the above rules. And that’s OK. You can refine and reformat your code later. I don’t think anyone could start with writing functions that follow all the rules mentioned above.

Remember they’re function-building goals that you need to strive towards. Don’t let them paralyse you.

3. Document your code, and write helpful comments

Your code should always include comments that serve as documentation for the functions and modules.

Every function definition should be proceeded by a comment that includes:

  1. A short, one/two sentence description of what the function does.
  2. Followed by a one line description of every argument that the function accepts (if they exist).
  3. Which is followed by a one-line description of the return variable of the function (if it exists).
Apart from that, you should include comments to describe less-comprehensible parts of your code.

Just keep in mind that:

  • Comments are meant to help the reader of a program. They don’t help by saying things the code already plainly says or by contradicting the code or by distracting the reader with elaborate typographical displays.
  • As much as possible, write code that’s easy to understand; the better you do this, the fewer comments you need. Good code needs fewer comments than bad code. Comments are, at best, a necessary evil.
  • Don’t contradict the code. Most comments agree with the code when they’re written, but as bugs are fixed and the program evolves, the comments are often left in their original form, resulting in disagreement with the code.

4. Be consistent

Why?

Because a consistent coding style is a good coding style.

It makes it easy for someone (including you, yourself) to dive into your code and read it in the future.

Remember:

  • Follow standard practices whenever you can. Search for “< insert programming language> style guide” and follow a credible source throughout your code. Here’s the Python PEP8 style guide recommended by Python itself.
  • If you aren’t sure of what the standard is or need to break away from it, make sure you have a reason and that you do it consistently throughout your code.
  • Be consistent in the way you name your variables, the way you indent your code, the way you document your functions, and all the way to whether you use ++i or i++.

5. If it breaks, assume that it’s (probably) your fault

And learn to own it.

You’re likely to spend a majority of your coding time banging your head over broken code.

In those moments, you’ll inevitably try to shift the blame to your IDE, compiler, environment, or your machine — especially in the beginning of your journey as a programmer.

You must learn to control that frustration and remember: It’s not the computer, it’s you.

Only when you do that will you be able to diagnose and get to the heart of the problem (even if it’s some problem with the machine).

How to debug your code:

  1. Explain the code to a friend or use the rubber-duck technique
  • Pick a friend (or a rubber duck)
  • Open the problematic code, and explain it to him (/her/it) line by line, slowly and patiently
  • Find the problem staring at you in the face without any help from your friend (or the duck) — as if by magic!

2. Add print statements

You know ... these print statements.

Although adding such print statements isn’t the correct way to debug, I find them incredibly effective at times. Especially, when I’m working with a text editor like VIM and not on a full-fledged IDE that has a debugger (or when you’re too lazy to learn how to use a debugger).

But I have to say, once you learn how to use an IDE debugger, there’s no going back.

3. Use an IDE debugger

A debugger can be so incredibly helpful. Yet, I neglected learning that part of my IDE for a stupidly long time. I’ll suggest you learn how to use the debugger in your favourite IDE, ASAP. Trust me, it’s totally worth the pain.

Personal advice: I’m using IDE debugger because Python provides a debugger in the standard library module — pdb — and I won't recommend using it.


Guiding Principles

In the end, remember that the principles of a programming style are based on common sense guided by experience, not on arbitrary rules and prescriptions.

Here are 4 guiding principles that I follow to keep my code clean:

  1. Don’t settle for “well, it runs.
  2. Write for readability — code is read more often than it’s written.
  3. Explicit is better than implicit.
  4. Duplication may be the root of all evil in software.
And professionals agree

These should help you when you forget any rules or run into new situations in the real world that aren’t covered by these concise rules.


So How Can You Adopt These and Improve Your Own Coding Style?

Here are the 2 books that I use to inform my own intuitions about good coding style:

  1. Bob Martin’s book Clean Code
  2. Brian W. Kerninghan’s book — The Practice of Programming

But mind you, only reading about such practices is not enough.

These are difficult-to-grab intuitions, and the best way to develop your own intuitions is through practice.

I have written before that the problem with the teaching-through-small-programs approach is that it doesn’t

  • Develop your intuition — like how to go about modularizing your code
  • Address how to write functions so they can be reused when extending your program to new use cases
  • Talk about the trade-off between writing readable code and compact code and provide focus on the need for a good and consistent programming style

In summary, small programs fail to teach the core design choices that one learns to make when creating larger programs working on your side-projects.

So the way you develop these intuitions is by working on projects.

If you’re stuck at the stage of finding ideas for an interesting project, I’ve written an article to help you out:

Fantastic Programming Project Ideas and Where To Find Them (a beginner-friendly version)
20 cool project ideas for data science, machine-learning app development, and web development

And if the idea of building your own project still seems too daunting, I wrote a guide to walk you through one of the projects in the above article:

Advance Your Python Skills by Building a Whatsapp Chat Analyser
A guided project that helps you dive into creating something cool and learn useful programming concepts by yourself!

I am passionate about teaching. I will try to keep producing such articles that address the problems that I face myself, with empathy. Subscribe to the Build To Learn newsletter to get updates when I do such guides and articles.

You can reach out to me via Twitter or LinkedIn or the plain old email — nityeshagarwal[at]gmail[dot]com .


Originally published on the Build To Learn blog.