Code etiquette
Almost all children learn about ‘good behavior’ from an early age. Children learn about what to say (and what not), how to be polite, how to eat, and so on. Those are complex rules, and parents find it important that their children know how to behave. This is certainly advantageous for people to know the rules of etiquette: if you know the rules, you can feel more confident that you don’t annoy others. Social interactions will get much better when people know how to behave.
Read more: Code etiquetteInteractions between people
In all situations where people interact, rules are needed to make interactions smooth. Rules determine boundaries for desired behavior.
For example, there are traffic rules that tell to stop at a red light, when to give way, to keep right (or left if you live in Great Britain). Sometimes, not obeying the rules is dangerous, but sometimes it annoys other road users Like staying in the left lane unnecessary. Driving lessons pay attention to teach students to be considerate of others.
Another example is when making a phone call. You say “Hello” or something when you pick up the phone, so that the other person knows you’re there. Likewise, when ending the call, you say something like “Goodbye”. You try to find a quiet place so the other person can hear you well (and vice versa).
The purpose of these rules is that, by being considerate and respectful, people get along much better. So it might seem that etiquette has nothing to do with technology. Not so fast! What to think of the netiquette rules for example? After all, technology always has a human component.
Source code etiquette
So interaction between people requires rules. It occurred to me that developing software is also a form of interaction between people. Maybe you say: “But we program computers, not humans!” As true as that is, there is still interaction involved. Interaction is just more stretched in time: it happens when you need to change the code after it was written. Maybe you need to fix a bug, or perhaps add some functionality. In that case, you start with the source code that the developers before you had written down. And you cringe when they did a poor job, don’t you?
It is safe to say that the very purpose of programming languages is to make software readable for humans. Otherwise, any assembly language would do. But those are rarely being used in practice, precisely because assembler is so difficult to read. So it is important that source code is easy to read. It helps developers when they do not have to spend a lot of time figuring out what the intention was. It prevents them from making the wrong changes.
Etiquette rules
As one of the goals of good etiquette is to make it easy for others, there should also be some form of etiquette for source code. What should it look like? Below is a list of things that I consider important. The list is not exhaustive, and you may disagree with items on it.. That is okay, as long as it suffices as a starting point to convey my intention. It is also not my intention to start a tabs vs spaces war as that would defy the purpose. Remember, the goal is to help the next guy, not to express personal preferences.
- Limit the line length. Maybe you’re the developer with a huge screen and ultra high resolution so you can write very long lines and read them all at once. Not your colleagues. They may have standard resolution screens, or perhaps must resort to a huge font because of limited eyesight, or want to view a diff side-by-side. They won’t like it when they have to scroll sideways. Therefore, I think it is better to limit the line length, so that two documents will fit side by side on most screens. It does not limit the usefulness of large resolution screens: each IDE can show multiple documents side by side to ease jumping back and forth. There is also another consideration: breaking long lines into logical segments makes them better readable.
- For the same reasons, it is better to have functions that fit on a single screen. Shorter functions are just better readable. And yes, there are exceptions like hard-coded arrays.
- When joining an existing code base, it is more important to be consistent than to follow your own preferences. It is just much easier to reason when similar problems are solved in a similar way. Of course, that is not to say that no improvements can be made. Just works towards a coherent code base, not one that has the same problem solved in multiple ways. Nobody is happy with lava layers.
- Do not mix high and low abstractions within a single function. All statements in the function should be on a similar abstraction level. It is very difficult to reason if a single function contains bit level control logic mixed with high level automation behavior, even more difficult to change it.
- Choose good names. This is really a difficult one, and it really requires practice to become better at it. One simple guideline is to reflect a variable’s intention in its name, without redundancies, but as specific as a short name can be. For example, a
Car
may have afloat Velocity
member, but that does not say much. Is it the target velocity, or the current velocity, or even something else? And what is the unit, m/s, or mph? When the context does not tell the meaning and unit, I’d rather name it something likeCurrentVelocityKmPerHour
even though it is more cumbersome to use. - Fix your typos. They are annoying to others, and distracting. Often enough I have seen code with lots of typos even to the point that names are downright ambiguous. Do not do that to others, it makes it mentally very hard to understand what is going on.
- Be terse, yet descriptive. You cannot be completely specific in all corner cases, but good code clearly shows the general approach and does not bury it in lots of details.
- When designing an API of any kind, be especially considerate to the client side. I’ve seen enough difficult to use libraries because their developers did not think about their usage, or just had a single specific use case in mind. Especially avoid methods that can only be called in certain circumstances that are specific to the internals of the library. Remember that the clients have no access to the library’s internals, so they have to find out using trial and error. In my experience, TDD will help to design such APIs because the tests are the first clients, and they are demanding clients too.
- Clean up after yourselves. The code needs some cleanup just as your workplace needs when you’re done. Also here the goal is not gold plating but to make it easier for the next developers.
- You can make up many more rules by reading the famous essay “how to write unmaintainable code” and inverting all practices listed there.
In general, keep in mind that the goal is more important than the examples: to care for the people that come after you and make their work easier. Making them feel at home will help everybody involved.