Clean Code

If we care about our craft, then we also care about cleanliness. We take care to keep our tools and environment clean – as well as the things we create. This holds true in software development. Clean code matters.

But what is clean code?

Every software engineer will have an opinion, a personal notion of clean code. Indeed it is hard to come by clear definitions in the literature. Papers refer to clean code, without defining it; the (excellent) book Clean Code does not define the expression, but instead opens by surveying the opinions of experienced software engineers. People generally have their own ideas and preferences. That’s fair.

Here is a definition that I like: Clean code is simple code that’s easy to understand and easy to test. I like that, because it is a simple sentence that is easy to remember. It evokes an image in my mind of something that is free of noise and that is easy to reason about. If we consider program code our attempt to teach another person what a computer should do (freely paraphrasing Knuth), then this definition summarizes great qualities to help achieve just that.

Your definition is probably different and that’s okay. If you’re working on a team, your team can benefit from agreeing on one definition and everyone will go with that definition for any work delivered in the context of that team.

This helps with communication. A reviewer’s handwaving at a piece of code and exclaiming “clean up that section!” will generally be met with understanding instead of confusion.

It also opens way for reasoning about cleanliness. Although we may talk in absolutes, cleanliness is of course relative – if examined over time, a code base’s cleanliness varies, hopefully generally for the better. How you think about it, determines how you can think about measuring it. This determines the kind of story you can tell.

Start by defining it.

Seattle Marathon 2016

Early in January of this year, clearly in a goal-setting mood, I realized I wanted to run my first marathon. During that time I also happened to be reading Tom Foreman’s My Year of Running Dangerously, which may have influenced my thinking; it is a good book! Either way, before I could change my mind, I went online and remarked on Facebook that I was committing to running the Seattle Marathon this year. Then, I more or less shut up about it for a while.

The Seattle Marathon is traditionally Thanksgiving weekend. It felt admittedly safe to set a goal for something in the relatively distant future. Even so, I meant it.

I had done a few half marathons, but of course I realized that this would be a lot harder and I would have to respect the preparation for it. I followed a fairly relaxed exercise regimen in the beginning of the year, but then became more serious. Along the way, I bought a copy of The Non-Runner’s Marathon Trainer. I knew, I probably was not going to join an actual running group, so wanted to pick up some motivation – as well as a researched schedule I could follow with discipline. This worked well, overall.

To train for a marathon means to run a lot. According to my notes, I logged 116 runs, totaling more than 764 miles, this year, prior to race day. It also means lots of stretching and icing of sore muscles, experimenting with different types of drink and food, before, during and after the runs. Managing exercise recovery. Self-talk, both good and bad. Exhaustion during long runs on hot summer days. Elation during the first signs of fall weather, with fresh breezes and rain. Dodging spider webs and low-hanging branches on the forest portions of the training routes.

The most disappointing run was probably the one that was cut short, when I stepped hard on a long, rusty nail — to first limp home and then rush to Urgent Care for an overdue Tetanus shot. The most exhilarating runs were those, where I pushed myself to accomplish a new distance or a faster time — or just felt stronger during it.

My wife is incredibly supportive. My dog joined many of the runs. Our four-year old daughter is excited about all types of physical activity – and the various types of drinks or energy chews. In the end though – you run by yourself. It is a solitary pursuit. Of course, you meet people along the way. Strangers turn into familiar faces. Many greet, some shrug. Occasionally a dog will bark or give chase for a bit. You encounter other runners, nod in passing, acknowledge an affinity. No one can do this for you. It is a simple thing. You just run.

Race day came, eventually and I made good on my promise to myself. I finished that marathon. It was hard, painful. I made mistakes, of course, went out too fast, paid the price for it later on. Nagging questions about my diet the days before (it was Thanksgiving week after all), training deviations due to scheduling conflicts, my internal dialog during the race, and so forth. This introspection is perhaps useful for future training, but now? Does any of that matter? I finished my first marathon. It was all worth it.

There is delight in the accomplishment, but also a sense of emptiness, a void to be filled: What’s next?

Debugging terminology

The term “bug” has long been part of computing jargon. We have, in fact, been referring to software or computer problems as bugs practically for the entire time that computers have been around. Nowadays, the term has found its way well into the mainstream and it is easy to find mention in regular news coverage.

How did this happen?

The origin of the word in the context of computing is not that clear. No discussion is of course complete without mention of the oft-repeated story of Grace Hopper’s engineering team’s locating of an actual moth in the machine – with said bug still on display in a museum to this day. That was in 1947.

That is not the term’s origin story, though it may make a nice one, as emphatically explained in Etymology of the Computer Bug: History and Folklore. Apparently Thomas Edison was using the term bug to refer to technical difficulties and/or faults in the context of his inventions as early as 1878:

The first step is an intuition, and comes with a burst, then difficulties arise — this thing gives out and [it is] then that “Bugs” — as such little faults and difficulties are called — show themselves and months of intense watching, study and labor are requisite before commercial success — or failure — is certainly reached.

Stalking the Elusive Computer Bug, by Peggy Kidwell examines this in more historical detail. It makes for a fascinating read! More startlingly, Moth in the machine: Debugging the origins of ‘bug’ points out the relationship to old terms for monsters, gremlins. I cannot help but imagine (probably unfairly) people at the very dawn of the information age (superstitiously?) discussing “bugs” happening in (or to?) their programs or machines.

And now here we are. The most valuable and innovative companies in the world would not exist without modern computing technology — and we are without irony still talking about bugs in our machines.

Is that a problem?

When I think of bugs, I mostly think of, well, insects. On the spectrum of life’s problems, they would largely register as annoyances. Thus, this term seems to trivialize the issue — considering some of them (even if they started as mere typos) may well cause very costly damages. In Bugs or Defects?, Watts Humphrey made this argument:

By calling them “bugs,” you tend to minimize a potentially serious problem. When you have finished testing a program, for example, and say that it only has a few bugs left, people tend to think that is probably okay. Suppose, however, you used the term “land mines” to refer to these latent defects. Then, when you have finished testing the program, and say it only has a few land mines left, people might not be so relaxed. The point is that program defects are more like land mines than insects. While they may not all explode, and some of them might be duds, when you come across a few of them, they could be fatal, or at least very damaging.

In comparison to more abstract terms like errors, defects or faults, bugs seem more tangible. In fact, they seem rather like external entities. The inconvenient truth however is that those bugs are largely created by the same people who also create the product.  In On the cruelty of really teaching computing science, Edsger Dijkstra brought this to a point:

We could, for instance, begin with cleaning up our language by no longer calling a bug a bug but by calling it an error. It is much more honest because it squarely puts the blame where it belongs, viz. with the programmer who made the error. The animistic metaphor of the bug that maliciously sneaked in while the programmer was not looking is intellectually dishonest as it disguises that the error is the programmer’s own creation. The nice thing of this simple change of vocabulary is that it has such a profound effect: while, before, a program with only one bug used to be “almost correct”, afterwards a program with an error is just “wrong” (because in error).

Finally, usage of the term is burdened with ambiguity. Bugs can refer to bad code, incorrect execution or wrong results. In the excellent Why Programs Fail – A Guide to Systematic Debugging, Andreas Zeller elaborates:

This ambiguity of the term bug is unfortunate, as it confuses causes with symptoms: The bug in the code caused a bug in the state, which caused a bug in the execution— and when we saw the bug we tracked the bug, and finally found and fixed the bug.

The language we use is important to how we think about problems and go about solving them. There are at least a few issues with using the term “bug” and we would benefit from finally moving away from it.

Ada turned three

As she followed me down a slippery boulder field toward the shoreline of a small river, I could not help but marvel at how much Ada has grown up. She joined our family as a young puppy and has turned into a mature dog, roughly seventy pounds of happy, energetic German Shepherd.

I have known her most of her life and during this time she has become a loyal friend and companion to me. There is no equal to the exuberant joy she expresses when she first sees us in the morning. I wish I were able to show that much enthusiasm for the day, so shortly after waking up. During my childhood, we always had dogs in the family, but none of them were as affectionate as Ada is. Besides walks around the neighborhood and trips to the dog park, she enjoys resting in the office or downstairs around the entry way during the day. She responds to the door bell or seemingly suspicious noises and has made it her duty to caution strangers against unbidden entry.

But it is outside, in the mountains, lakes and streams of the beautiful pacific northwest that Ada comes alive like nowhere else. As soon as we begin getting our gear ready, she senses that a new adventure awaits. Her excitement grows, when we load up the car and once we are on the road, she will remain sitting (usually next to a pile of boots and a pack), staring intently out the back window. Once out on the trails, Ada truly is in her element.

Always eager to chase a stick or a ball or to just run and frolic about, she has learned that these outings can take all day and she can pace herself. Given the chance, she will happily go drinking from a mountain stream or swimming in a lake in the summer. During the winter months, she is overjoyed to discover (seemingly anew every time) the magic of snow and ice. Sometimes bounding ahead, exploring as we go, or following in our footsteps with tired determination, if we break trail in deep snow. No matter what, she brings endurance, strength and eagerness.

We share the struggle, joy and appreciation of the Cascades like we share water and food breaks. I would not ask for a better companion out there.

Happy Birthday Ada, my beautiful, furry friend! I hope you will have many, many chances to get dirty, soaked and tired all over those mountains in the coming year.

Under Pressure

On days off, my wife and I like to leave the office and the city behind and venture into the mountains, seeking nature, relative solitude, fresh air and a good workout. A typical trip will cover a distance of at least eight miles and a few thousand feet of elevation change. Especially during the winter months, conditions can be tough. In snow, ice and pouring rain, the miles seem longer and the packs ever heavier.

Now, imagine bringing a small child and carrying her on your back with you.

Our little daughter is at an age (just under 18 months), where she understands to use primarily one method to communicate discomfort: Crying – or worse yet, screaming.

There is something about a young child’s crying that will grate on you and spur you on to take action. Perhaps it is the tone of it, but it seems even worse, if you are hearing your own child’s crying. Of course, if said child is riding along in your carrier backpack, then the crying will be just inches from your ears: It hurts. You might be tired and hungry, miles away from your car. You have brought only the gear necessary for the trip, no additional items of comfort. She may be unhappy, because she is actually tired and trying to nap. In this case, you could just keep going and she may well calm down within a few minutes and simply go to sleep.

Then again, it might be different and if you don’t address her problem quickly enough, she will continue crying and before too long escalate in tone and urgency. It is possible that she is in real distress and any further delay is just worsening things for her – and you. In fact, given enough agitation, she may begin screaming at you and continue – even as you’re taking the right steps to address her problem – until the situation is entirely resolved. Her urgency, perhaps amplified by harsh weather and (your own) tiredness instills a sense of crisis.

This can get very stressful. You may notice the signs: You rush through movements. Conversations quicken, responses shorten, turn impatient. Communication (among the adults) deteriorates, arguments ensue.

So, what do you do?

Certain experiences can be useful to anchor our intended actions to certain conditions: If I am in this position, then I will generally respond that way. In this case, it is important to keep your cool and understand that there is a problem to be solved. The crying (or screaming even, as it may be) is a symptom, but it can also be very distracting and very well make the situation seem a lot worse than it is. How well do you do at performing a task, if someone is screaming at you during it? In this scenario, we can find out and learn from it to improve during future outings. That is part of our experience of these trips.

It never plays out the same way, but there are some general patterns that can be observed. The problem to be solved here is usually one out of a relatively small list of possibilities. She might be hungry, thirsty, too warm or too cold, bored, uncomfortable, and so on. She might need a diaper change. Resolving the situation is usually straightforward. To get it right though, it is very important to stay cool and get the setup right.

Unless there is a very obvious cause of the distress, we make a decision after a few minutes. We start looking for a good stopping point, factoring in the  weather and environment. If we make a stop and stay for a bit, then this should obviously happen in a way that is safe and protected from the elements. This might involve building an ad hoc rain shelter, flattening down snow and providing some ground insulation, and so forth. Once we are ready, we remove her from the pack. Unless we already know what is wrong, we now go down the list of possibilities and address what is necessary. She will let us know, when we got it right. Again, this is all about remaining calm and being deliberate about our course of action.

You learn so much, when the pressure is on.

As we returned to our car after a long day out on the trails a few weeks ago, boots covered in mud and rain gear glistening from the constant downpour that had accompanied us, I could not help contemplating just how much these outings have taught me about working under pressure.