Who the reader is
Code is read far more often than it is written. The most frequent reader of your hobby project is you, some months from now, with the context gone and a device that has stopped working. Readable code is a kindness to that person. It also makes it far easier to share a project, ask for help or accept a fix from someone else.
Readability is not about style for its own sake. It is about reducing the effort needed to understand what the program does, and so reducing the chance of misunderstanding it.
Choose names that carry meaning
Names are the most important part of readability, and the cheapest to improve. A good name says what a thing is or does:
- Prefer
battery_voltagetobvorval. - Include units where they matter:
delay_ms,distance_cm,timeout_seconds. Many hard-to-find faults come from mixing units. - Name functions after what they do, usually with a verb:
read_temperature,is_door_open,send_alert. - Name true-or-false values as questions or statements, such as
is_connectedorhas_new_data. - Be consistent. If one place says
sensorand another saysprobefor the same thing, readers will wonder if they differ.
Very short names are fine for tiny scopes, such as a loop counter, but a name used across many lines deserves more care. If you cannot think of a good name, that is sometimes a hint that the code is doing too many things at once.
Replace magic numbers
A bare number in the middle of code, like if (reading > 712), tells the reader nothing. Give it a name, such as DRY_SOIL_THRESHOLD, defined once near the top. Then the meaning is clear, and changing it means editing one line. This also applies to pin numbers, addresses and timing values. Where the number came from, for example a figure from a datasheet or a calibration measurement, a short note beside the definition is a good use of a comment.
Keep functions small and focused
A function should do one thing you can describe in a sentence. If the description needs “and” several times, consider splitting it. Smaller functions are easier to name, understand, reuse and check with automated testing. A common pattern in device code is one function to read inputs, one to decide, and one to act, so that the decision logic can be understood without thinking about hardware.
Limit nesting too. Deeply indented conditions are hard to follow. Returning early from a function when something is invalid, instead of wrapping everything in another level of if, often flattens the code. Long lists of unrelated statements in a single block are a signal to break the code into steps with their own names.
Structure the file for a reader
Group related things together. Put configuration and constants at the top, helper functions next, and the main flow where a reader can find it. Use blank lines to separate steps, the way paragraphs separate ideas. Consistent formatting, in particular indentation, matters more than which style you choose. Many languages have formatting tools that apply a consistent layout automatically, which saves effort and avoids arguments with yourself.
Avoid cleverness. A compact one-line trick may feel satisfying, but a plain three-line version that anyone can follow is usually better. Save optimisation for places where you have measured a real problem.
What comments are for
Comments should add information that the code cannot. Useful comments usually explain:
- Why, not what. “Wait 50 ms: the sensor needs time to settle after power-up” is helpful. “Wait 50 ms” beside a delay of 50 is not.
- Constraints and surprises. A workaround for odd hardware behaviour, a limit from a datasheet, an order of operations that must not change.
- Units and ranges for values whose meaning is not obvious.
- Intent at the top of a file or function: what it is for and how it fits in.
- Warnings about things that are easy to break.
When a comment explains what messy code does, consider rewriting the code with better names instead. A well-named function often removes the need for the comment.
What comments should not do
Several habits make comments harmful:
- Restating the code.
i = i + 1 # add one to iadds clutter and no information. - Going stale. A comment that no longer matches the code is worse than none, because readers trust it. When you change code, update the comments around it.
- Holding old code. Commented-out blocks make files confusing. If you use version control, the old version is in the history, so delete it.
- Hiding secrets. Do not leave passwords or keys in comments or code. They end up in shared files and history, which is a recurring problem addressed under API key secrecy.
- Venting or joking at the expense of clarity. Notes such as “this is a hack” are fine if they say what and why, and unhelpful if they do not.
Markers such as to-do notes are acceptable for genuine reminders, as long as you look for them occasionally.
Documentation beyond comments
A short README is often more valuable than any number of inline comments. It should say what the project does, what hardware it needs, how to set it up and how to run it, plus any known limitations. Wiring notes or a simple diagram belong there too, since code alone does not show how the parts are connected, and circuit schematics are the clearest way to record that.
A quick review habit
After finishing a feature, read the code as if you had never seen it. Where do you stumble? Rename what confused you, split what was long, and add a comment only where the reason is not obvious. A few minutes of this each time keeps a project from sliding into something nobody wants to touch.