Tuesday, April 30, 2013

A Responsible Programmer

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!

Sunday, April 07, 2013

Javascript Conditionals

As we all know, Javascript is a very flexible language. In the article I will show different ways to execute conditional code by using some common idioms from Javascript and general object-oriented techniques.

Default values

Javascript does not support default values for arguments and it is common to use an if statement or a conditional expression to set default values.

function swim(direction, speed, technique) {
  // Default value with if statement
  if (!direction) direction = 'downstream';

  // Default value with conditional operator
  var speedInMph = speed ? speed : 2;
}

I usually prefer to use an or-expression instead. The short-circuiting or, ||, avoids the repetition of the conditional operator and is, in my opinion, more readable. Another advantage of avoiding repetition is that a slow executing function condition such as fastestSwimmer() will avoid the performance penalty of calling the function twice.

  // Default value with or.
  var swimTechnique = technique || 'crawl';

  // Function is only invoked once
  var siwmmer = fastestSwimmer() || 'Michael Phelps';
}

Naturally, this technique is not limited to default arguments, it can be used to set default values from object literals too.

options = { kind: 'Mountain Tapir', }
var kind = options['kind'] || 'Baird Tapir';

A simple, yet useful, technique.

Update 2013-04-13, as Jeffery mentions in a comment, the technique only works for values that are not falsy. If values such as 0 or false are acceptable values, you will have to explicitly test for undefined instead.

Call callback if present

Another idiom in Javascript, especially in Node, is passing callbacks to other functions. But, sometimes the callbacks past in are optional. In this case we can use short-circuiting and, &&, instead.

function updateStatistics(data, callback) {
  var result = doSomethingWithData(data);
  // Call the callback if it is defined
  if (callback) return callback(result);
}

function (data, callback) {
  var result = doSomethingWithData(data);
  // The last evaluated value of the `&&` is returned
  return callback && callback(result);
}

I, personally, prefer the first form with the explicit if because I think it communicates my intent better but, it is good to know about the technique anyway.

Update 2013-04-13, A better use for the technique is for testing for the presence of objects before getting their properties.

function callService(url, options) {
  ajaxCall(url, options && options.callback);
}

Lookup Tables

If you have code that behaves differently based on the value of a property, it can often result in conditional statements with multiple else ifs or a switch cases.

if (kind === 'baird')
  bairdBehavior();
else if (kind === 'malayan')
  malayanBehavior();
else if (kind === 'mountain')
  mountainBehavior();
else if (kind === 'lowland')
  lowlandBehavior();
else
  throw new Error('Invalid kind ' + kind);

I find this kind of code ugly and I don't think it looks any better with a switch statement. I prefer to use a lookup table if there is more than two options.

var kinds = {
  baird: bairdBehavior,
  malayan: malayanBehavior,
  mountain: mountainBehavior,
  lowland: lowlandBehavior
};

var func = kinds[kind];
if (!func)
  throw new Error('Invalid kind ' + kind);
func();

I find this code a lot clearer since makes it clear that the else clause handles an exceptional case and that the normal cases works similarly.

Missing Objects

If similar conditionals appear in multiple places in my code, it is a sign that I am missing an object somewhere. Since Javascript is duck typed I can use the same technique as above to create objects instead of just functions.

var kinds = {
  baird: { act: bairdBehavior, info: bairdInfo },
  malayan: { act: malayanBehavior, info: malayanInfo },
  mountain: { act: mountainBehavior, info: mountainInfo },
  lowland: { act: lowlandBehavior, info: lowlandInfo },
};

var tapir = kinds[kind];
if (!tapir)
  throw new Error('Invalid kind of tapir ' + kind);

I prefer to have this kind of code on the borders of my application. That way the code inside my core domain doesn't have to deal with complicated conditional logic. Polymorphism for the win!

Null Objects

If I notice that in many places I have to check fornulls, it is usually a sign that I haven't handled the special null case properly. In the example above I have handled it properly since I throw an Error if the kind of tapir does not exist. But sometimes it is not an error when the value is missing.

// If a non existant kind is used, tapir will become null
var tapir = kinds[kind];

// In other places of the code
if (tapir)
  tapir.act();

// Somewhere else
if (tapir)
  return tapir.info();

This type of code is rather unpleasant and it is time to break out the Null Object.

var tapir = kinds[kind];
// If a non existant kind is used I use a Null Object
if (!tapir)
  tapir = { act: doNothing, info: unknownTapirInfo }

// In other places of the code the conditionals are gone.
tapir.act();

// Somewhere else, no special case here.
return tapir.info();

Null Objects are not appropriate everywhere but, I often find it very enlightening to have them in mind when I write code.

Summary

There are a lot of elegant ways to deal with conditional code in Javascript. I didn't even mention inheritance since it works similarly to the object approach I showed above. But if I need multiple instances of something I would of course use polymorphism through inheritance instead.