Programming
EN
A Responsible Programmer
['Anders Janmyr', 'View My Complete Profile']
The Tapir's Tale
In the last few years I have been asked to help savor several web projects gone
bad. The quality of the projects, code, environment, documentation, and morale
has been low. To know what I think is right in situations like this, I started
asking myself the question, "What would a responsible programmer do?".
Clarity
Above anything else a responsible programmer values clarity. Not only does she
value clear code, but also clear documentation, clear communication and a
clear vision of where she and her project is going.
Coding
Write Consistent Code
The responsible programmer writes consistent code. Consistency helps other
programmers read and understand her code. It lets them know what to expect. If
she names constants with SCREAMING_SNAKE_CASE, they know that they wont
change. When naming attributes in CSS and HTML, she will make all of them
dash-er-ized, or none of them. This is easy stuff, but important. Consistency
breeds familiarity. Familiarity is good, it removes worry and increases
confidence.
When the responsible programmer contributes code to other projects, she will
make sure that she, consistently, follows the style of the project. Sometimes
it is not easy to tell what style a project uses, the responsible way is to ask
what style is preferred and then use that style. By just asking the question,
she will often trigger a review of the code which will help set a consistent
style in the future.
By writing consistent code, a responsible programmer will make the program
easier to understand and easier to maintain.
Don't Quick-Fix
A responsible programmer doesn't do quick fixes. When a bug needs to be fixed
she fixes the root problem instead of fixing the symptom. If an event-handler
suddenly starts receiving unnamed events the proper fix is not to ignore
unnamed events but, to figure out why unnamed events come at all when not
expected. She knows that fixing a symptom will only make the root cause much
harder to find.
Write Short Functions
Short functions are easier to understand, easier to reason about and easier to
test. It is the responsible thing to write. Enough said!
Separate Commands From Queries
CQS or Command Query Separation has become all the rave in the DDD world, but
it was coined by Bertrand Meyer in the book,
Object-Oriented Software Construction in 1988.
A good book, read it!
The responsible programmer separates her commands from her queries because she
knows that they are easier to test and that she can call the queries many times
without anything bad happening.
Separating your commands form your queries may be as easy as:
// Can be called whenever, no side-effects
function generateRoute(params) {
return [params.major, params.minor, params.patch].join('/');
}
// Updates the hash with the new route.
function updateRoute(params) {
location.hash = generateRoute(params);
}
Refactor Mercilessly
Since a responsible programmer values clarity, she refactors mercilessly when
her understanding of the system changes. She knows that the time invested in
making the code a little more clear will prevent bugs and frustration in the
future.
Prefer Explicit
A responsible programmer prefers explicit code over implicit code. Even though
her understanding of advanced concepts such as meta-programming, monads and
continuations is substantial, she prefers explicit code over beautiful
abstractions. New programmers (including her future self) have a lot easier to
understand code that is explicit than code that is not.
Don't Fear Advanced Techniques
Since advanced techniques can make the code a lot simpler in certain
situations she never shies away from advanced techniques when she realizes
that they are called for. At the end of the day meta-programming and "advanced"
functional programming techniques are just tools that should be used when
appropriate.
Check Boundaries
A responsible programmer always checks the boundaries of her system to make
sure that invalid data doesn't enter into the core of the application. This way
she can avoid defensive programming in the core domain where clarity is even
more essential than anywhere else.
Wrap External Services
External services is one of the main reasons that development takes time,
the responsible programmer makes sure to always wrap external services with a
local interface. This simplifies both testing and exchanging the services.
External Libraries
A responsible programmer will never use an external library she doesn't trust.
She will never add a library into her code base unless there is a significant
reason for adding it. When she adds an external library she will learn it. She
will learn how she configures it, how it is to be called, what are good
practices for using it, what bugs there are, etc.
Balance
A code base can be compared to a balanced tree. A balanced tree is
data-structure that will rebalance itself when new items are added to it. This
makes the cost of modifying the tree more expensive but has the benefit that
accessing items in the tree can be performed in an optimal way.
A responsible programmer treats her code base as a balanced tree. She will
never add code without thinking about balance. She knows that if the
project loses its balance it may have to be entirely rewritten to regain
balance again.
The balance of the code may shift as the code matures, when a major shift is
called for the responsible programmer will refactor mercilessly to obtain a new
optimal balance.
Documentation
A responsible programmer writes and maintains documentation as the needs come
up. The needs differ between projects, but most projects benefit from a system
overview, a domain overview, a style guide, and code comments.
A responsible programmer makes assumptions all the time when coding, she writes
the assumptions as comments in the code when she makes them. She tags them
to make it possible to generate a list of assumptions.
The System Overview
The system overview is a drawing and a description of all the servers that are
involved in the system. This includes databases, queues, web-servers, external
services, etc. The description describes how the pieces fit together.
The Domain Overview
This is a drawing and a high level description of how the core domain of the
system works. It includes the major concepts of the domain and what they mean.
The Style Guide
The style guide may be as easy as referring to Github's style guide or to write your own that alters someone else's. Anyway you do it, it is worth having it written down.
Code Comments
Comments in code should be very sparse and only added to point out
idiosyncrasies. When assumptions are made, they can be written as comments with
a tag to make it possible to generate a list. Example:
// ASSUMPTION: The list is expected to be small and will
// be entirely loaded from the server
function loadCities() {
}
Testing
The responsible programmer tests! She doesn't test for the sake of testing or
to increase code coverage, she tests to be sure that the code works as she
expects it to.
She knows that dynamic environments such as Javascript and web browsers are
fragile and that it is easy to break code without meaning to.
How to write good tests have been written about elsewhere and I wont spend any
time on it here. I can recommend the last chapter in Sandi Metz' book, Practical Object-Oriented Design in Ruby if you are interested in good techniques for testing in dynamic programming languages.
Environments
The responsible programmer owns her environments. In a project there are at
least three environments to care about, Production, Test, and Development.
There is also the development machine itself.
The responsible programmer can set up all project environments with a single
command that installs everything that is needed, including databases, seed
data, libraries, search engines, tools, environment variables, SSH-keys.
Everything!
This will allow a new programmer starting in the project to be setup within
minutes. It will also allow her to experiment with anything without having to
worry about destroying the setup and losing days debugging the environment.
Her personal development machine is also perfectly configured at all times. If
she learns a new trick, she will immediately incorporate it into her toolset
and into her configuration.
She is automatically prepared for catastrophes. If her hard disk crashes she
can just buy a new one at the local supermarket and install her configuration
files and be ready to go within hours.
To make this happen she always keeps backups of her configuration files. She
keeps the non-secret ones on Github and the secret ones, such as SSH keys and
passwords elsewhere.
Continuous Integration/Deployment
Another part of the environment is continuous integration. If a project doesn't
use continuous integration it is a clear sign that it is not healthy.
The continuous integration server is just another environment and setting up a
new is done with a single command just like the others.
The responsible programmer will set up and maintain continuous integration just
like she does every other environment.
Scripting
In order to achieve the environment goals, a responsible programmer knows how
to script. Scripting is not only essential for keeping your environments up to
date, they are essential for automating simple tasks. Scripts are useful for
generating code, testing, refactoring, renaming, installation, automating
checklists, etc.
A responsible programmer ask herself, "When did I do something once? Never!"
Writing a script that does what she wants frees her from having to remember the
sequence of instructions required to do a task and let's her focus on more
important stuff. It also serves as runnable documentation.
Tools
A responsible programmer knows her tools. She will always try to learn more
about them and she will replace them if other tools are invented that work
better. But she doesn't change her tools for the latest fashion.
The command line is a very powerful tool and so is scripting language and
a scriptable editor.
Version Control
The responsible programmer uses version control to communicate with her future
self and with other programmers. She knows that a clear commit message will
help her and others understand what has happened to the system.
She prunes her commits. When she has made several changes to a code base she
will make sure that she commits the different changes separately by using
something like git add --patch. She also knows that if she commits something
by mistake she can alter the commit message or add forgotten files with git
commit --amend and that she can change the contents of her history with git
rebase --interactive or with git reset
Projects
Own It
A responsible programmer owns her project, she will not allow anything bad to
happen to her code. This is a difficult goal to achieve when she comes into a
project that has already gone bad, but it is a worthy goal and not one that
should be taken lightly. All projects must have at least one person who owns
the code. When people start talking about the code as if it is someone else's,
it is time to shut the project down.
If a responsible programmer decides to take ownership of a project, she makes
sure that she has the authority to make the decisions that she deems necessary.
No authority, no responsibility, it's as simple as that.
Estimation
Sometimes projects require estimates, most of the time they don't but,
sometimes they actually do. A responsible programmer knows how to estimate. She
knows that an estimate is just a guess and the bounds of any task, however
trivial, always have a small probability of taking infinitely long to finish
(earth quake, meteor strike, blackout).
There is also a small probability that
the code is already being written at the time of estimation.
Being aware that the code may take infinitely long to finish she is very
careful not to make any promises and she is very clear about her estimates
being guesses.
Don't Do as They Are Told
Some people may not see this as a sign of a responsible programmer but I beg to
differ. When a programmer is told to do something, she will try to figure out
what the real problem is. She may do this in several different ways. She may
sit down and think through the "task" and come up with an alternate solution
that solves the problem simpler or, even better, makes the problem go a way
completely. She may ask questions to help clarify the problem for her. Why is
this a problem? Why do you do it like this? Why? Why? Why?
Some people may not like this and tell her to "Just fucking do it!". Her reply to
this is something along the lines of "Just fucking do it yourself!" but she is
usually a lot more polite so she may very well say "I don't understand what
your problem is and, therefore, I am not the best person to solve it, please ask
someone else."
She believes it is her job to understand what she is doing and why, and that
life is too short to be a drone!
If she feels that she is not able to be a responsible programmer on a project,
the responsible thing to do is to leave.
Summary
I have found that asking myself the question "What would a responsible
programmer do?" liberating. It clarifies what I should do in situations of
doubt.
At the end of the day, the responsible programmer can look through the commit
log and see a beautiful list of tasks that she has completed. She can look
through each commit and see that they are cohesive and well described by their
commit message. She can git blame the code and see that every line of code
that has her name on it reads well. She can look at her days work, and she can
feel proud!