yield thought

it's not as hard as you think

Posts Tagged ‘Programming

Criminal Overengineering

As programmers we’re continually accused of doing a sloppy job. There are countless programs in the wild, crashing, locking up and accidentally writing “I am a fish” a million times over someone’s mid-term essay. The effect? Something like this:

This damn computer and excel r fuckin my life up! Hatin life right now
MissAlauren (and everyone else at one time or another)

It’s experiences like this that cause people to rant about Microsoft and curse the anonymous programmers who suddenly (yet inevitably) betrayed them. We all know this; it’s burned into our very souls by countless hours of tech support provided to family and friends. Time after time we see that programmers who do quick, sloppy work make other people suffer. And so we try, we try so damn hard not to be like that. We try to be the good programmer who checks every return value and handles every exception.

If we stopped at competent error handling and sufficient testing, all would be well. In truth, we actually go too far and, it has to be said, largely in the wrong direction.

vast proportion of software at work today is horribly over-engineered for its task. And I’m not talking about the interfaces, about having too many controls or options for the users. These are, indeed, terrible sins but they are the visible ones. The worst of the overengineering goes on under the surface, in the code itself.

You’re Doing It Wrong

Have you ever seen someone using the strategy pattern when they should’ve used a 5 line switch statement? There are a million ways to turn something like this:

switch(operation)
{
case OP_ADD: return a + b;
case OP_SUBTRACT: return a - b;
case OP_MULTIPLY: return a * b;
default: throw new UnknownOperationException(operation, a, b);
}

… into a hideous, malformed mutant beast like this one, which I haven’t inlined because it’s far too long.

The most insidious cause of overengineering is over-generalizing. We will over-generalize anything given half a chance. Writing code to work with a list of students? Well, we might want to work with teachers and the general public someday, better add a base People class and subclass Student from that. Or Person and then EducationPerson and then Student. Yes, that’s better, right?

Only, now we have three classes to maintain each with their own virtual methods and interfaces and probably split across three different files plus the one we were working in when a one-line dictionary would have been fine.

Perhaps we do it because it’s relaxing to rattle off three classes worth of code without needing to pause and think. It feels productive. It looks solid, bulletproof, professional. We look back on it with a comforting little glow of self-satisfaction – we’re a good programmer, no messy hacks in our code.

Except, this doesn’t make us good programmers. Overengineering like this isn’t making anyone’s lives better; it’s just making our code longer, more difficult to read and work with and more likely to contain or develop bugs. We just made the world a slightly worse place. It lies somewhere between tossing an empty drinks bottle on the street and grand theft auto.

The extra effort caused by our overengineering carries a hefty opportunity cost:

  1. Less time spent refining the user experience
  2. Less time spent thinking about the meaningful implications of the feature we’re working on
  3. Less time available to look for bugs and – with harder-to-read code – more time spent debugging them

Yes, by overengineering the Student class you indirectly ruined MissAlauren’s day.

We have to stop championing each ridiculous feat of overengineering and call it what it is. It’s not ‘future-proof’, because we can’t see the future. It’s not robust, it’s hard to read. Applying a generic solution to a single case isn’t good programming, it’s criminal overengineering because like it or not somebody, somewhere will pay for it.

Don’t Worry, Be Happy

I suspect all the best programmers have already realized this, but they’re not shouting about it loudly enough for everyone else to hear. Paul Graham is completely right when he suggests that succinctness is valuable:

Use the length of the program as an approximation for how much work it is to write. Not the length in characters, of course, but the length in distinct syntactic elements– basically, the size of the parse tree. It may not be quite true that the shortest program is the least work to write, but it’s close enough… look at a program and ask, is there any way to write this that’s shorter?
— Paul Graham, The Hundred Year Language

He’s actually talking about language design here; indeed, in Succinctness is Power he’s careful to note that it’s clearly possible to write a program that’s too succinct. This is because, these days, Paul Graham is more a language designer than a working programmer. Otherwise he might have said:

If you’re about to take a hundred lines to write what you could in ten, stop and ask yourself this: what the fuck?
— Mark, Criminal Overengineering

When I feel tempted to over-generalize or over-engineer a bit of code, it’s often because of fear. Fear that someone will find a really good reason I shouldn’t have done it the easy way. Fear that I’ll have to rewrite the code again. Fear of finding myself on the wrong side of an argument about the merits of the visitor pattern. But fear does not naturally lead us to the most elegant solutions.

Next time you feel the compulsion to write a nice, general solution to a simple case, stop and ask yourself what’s stopping you just writing it the simple, specific, succinct way:

  1. Am I worried I’ll have to rewrite it?
  2. Am I worried someone will criticize it or that I’ll look bad?
  3. Am I worried that it’s not professional enough?

Are any of these true? Then relax. Don’t worry. You worry, you call me, I make you happy.

Just write the code the simple, specific way and then add a short comment, something like: Replace with the Strategy pattern if this gets any bigger.

This is the perfect solution. It’s a great reminder to you next time you come here about what you wanted to do. It shows other programmers on your team that you considered the ‘correct’ way to do it and have a good reason not to do it just yet. It’s very hard to argue with a comment like that, because you’re not arguing about the strategy pattern vs the switch statement, you’re arguing about whether to use the strategy pattern after 3 cases or after 4 cases – not a discussion that can reflect badly on you, in any case.

A few months later you can go back and look at how many of your comments eventually turn into more complicated, engineering code. I’ll bet you it’s not very many. That’s how much time and effort you’ve saved, right there. That’s setting yourself free to pursue the solution and that’s making the world a slightly better place.

Note: Yield Thought has moved to http://yieldthought.com – check there for the latest posts!

Written by coderoom

June 23, 2010 at 8:15 am

Posted in Programming

Tagged with , ,

Is That All?

with 50 comments

Note: This post isn’t about the iPad. It’s about me and you, our bosses and most of all it’s about normal people. It just starts with a story about the iPad, because that’s the way it happened.

What did Yahoo’s bosses say when they saw Google’s homepage for the first time? Why are 37signals so militant about saying ‘no’ to extra features? What did the Apple engineers think when Jobs told then to make a phone with one button?

Last weekend I spent twenty minutes playing with an iPad on a stand in an airport. I opened Safari and read xkcd, Penny Arcade and Hacker News. I flicked through the pictures of some sunkissed holiday by the sea. I played a couple of not very good games. I wrote a short document. I watched a video. At the end of twenty minutes I wandered away feeling slightly uneasy, thinking:

Is that all?
— Me

As a programmer, I’m comforted by screens full of settings. When playing a new game the first thing I do is find the options and tweak the hell out of it before I’ve even played a single level. The iPad left me feeling somehow uncomfortable, as if I was missing some core element. Had I really seen all it could do?

That was when I saw it: in a handful of minutes on completely unfamiliar hardware and software (no, I don’t have an iPhone), with an unusual multitouch interface I’d just ‘done’ things without having to think about them, without having to learn anything, without having to struggle. The gap between wanting to do something and doing it was so short that, for twenty minutes, it ceased to exist.

Don’t worry, we’re almost at the end of the iPad bit.

I was asking myself what the iPad could do. The iPad wasn’t doing anything – it was letting me do what I wanted. It had been designed by people who loved me more than their product (as Gandhi says you should). Was that all? Yes, because playing around for twenty minutes was all I wanted to do.

The user interface should be like a soundtrack barely noticed by the user
— Steve Capps

Everything we create should aspire to this, should leave us – as programmers – wondering if that’s all and if we shouldn’t perhaps add a bit more. Scott Berkun (a genius and a craftsman) said all of this more than ten years ago and I’ve known about it for at least half that time, but it hasn’t really changed the way I write software because it’s too hard to just know when something’s simple enough.

The feeling of ‘is that all?’, however, the uncomfortable suspicion that I can’t really ship a product with just one button, that all the important companies have login screens – this feeling proves we are on the right track. It is an excellent guide. Our world is full of self-indulgent interfaces clamoring for our attention. Why should we keep making this worse? We have to be brutal with our interfaces. Strip everything out. Consider every single piece of text as being a waste of the user’s time reading it, every control an unnecessary, unpleasant intrusion.

The user’s attention is a limited resource and we should heavily optimize to minimize our impact upon it. We must always, always remember that nobody wants to use our software – they want to finish their work and go play outside.

It’s hard. It’s risky. It’s easy to defend a new dialog as full of buttons as the old one. Our colleagues and managers live in bizarro world, believing our software has value independent of the things it helps people to achieve. They don’t want the new startup screen to have just 10% of the controls of the old one.

That’s not progress! Progress means more! Deleting things isn’t doing work! It’s anti-work!
— A stupid person near you (or, possibly, you yourself)

I’ve felt this, even if I haven’t said it. There’s this massive tension between writing something to humbly serve people you’ve never met and may never meet, and writing something your boss and colleagues will approve of. Yet we have to try, because the way software has been written for the last twenty years is making people unhappy.

Our calling, our duty, is to write software that will make our colleagues, bosses and competitors scoff and say “Is that all?” while making the lives and work of real people simpler, easier and less stressful. Our customers will love us for it – we just need the courage cut and hack and tear down everything that’s not necessary to get their work done and to put it out there for them to use.

Postscript: What am I doing about this? My startup, CodeChart, is making profiling very simple and very beautiful; the old generation of tools are so ridiculously overcomplicated that most people never use them. It’s in closed beta at the moment, but have a look at our getting started guide to see how it works and feel free to sign up for the beta if you’ve got some .NET code you want to look at. I know, I know, other languages – including my beloved python – are coming later!

Note: Yield Thought has moved to http://yieldthought.com – check there for the latest posts!

Written by coderoom

June 6, 2010 at 8:46 pm

Posted in Programming

Tagged with , , ,

A Song Is Worth 1093 Words

leave a comment »

Natural programmer. Ended up a rock star. Pity.

If someone had sent me this earlier in the week I could’ve saved us all 1093 words. Much love to Craig Lyons and some random youtuber for the developer anthem of the week.

Don’t stop listening until you’ve heard my personal message around 1:44 😉 In fact, it keeps on getting better!

If anyone makes a nice cut summarizing the software development sections (or just a loop ending at 1:16) send me a link!

Anyone know of any more songs secretly about programming and startups out there?

Written by coderoom

May 20, 2010 at 8:51 am

Start In The Middle

with 59 comments

I start in the middle of a sentence and move both directions at once.
— John Coltrane

Newspaper reporters are taught to write fractal articles: summarize the entire article in the title. Elaborate a little in the first sentence, then fill out the most important details in the first paragraph. A reader should be able to stop at any point without having missed any important details. We should approach programming projects in the same way.

As a child – after some experimentation and a lot of thought – I decided the best way to eat cornflakes was as follows:

Cornflakes, by Mike Haufe

  1. Pour the cool milk over the golden roasted flakes
  2. Sprinkle the one allowed teaspoon of sugar over the top
  3. Start eating around the edges, saving the sugary middle section for one last big spoonful of joy at the end

I stand by that decision. In fact, I’ve noticed I do similar things in other areas of my life. I’m sure a psychologist would talk for hours on the subject. Luckily for you I’m not a psychologist, I’m a programmer. And it turns out that this is an awful way to work on software projects.

Has this ever happened to you? You wake up one day with a great new idea for applying bayesian filtering to twitter streams to filter out the pictures of Joel’s new puppy spam. You’re totally convinced it’s what the world needs. It’s the startup that’s finally going to help you to break out of your day job maintaining PHP payroll software stock supermarket shelf stockers. So what do you do? You do this:

  1. Fire up your IDE and start a new website project
  2. Whip up a login page and get the user account basics set up
  3. Decide OpenID’s really where it’s at these days and hit stackoverflow for a good OpenID provider plugin
  4. Run into problems getting it to accept Google accounts and spend half the night debugging it

Wait, what? How did this happen? Getting OpenID working isn’t fun. It’s almost the definition of not fun.

I didn’t want to do all this, I just wanted to make an awesome bayesian twitter filter, but somehow there’s all this stuff I have to get through first.
— Me (swear words redacted)

My hard disk is littered with projects that I started, got half way through setting up without ever really getting to the good bit, then abandoned. I suspect yours is, too.

The right way to start a bayesian twitter filter is to apply a bayesian filter to content from a twitter stream. I know. It looks like this:

  1. Google for some bayesian filter code
  2. Dump whatever’s in your twitter client logs to a file and write three lines of python to parse it into a form the bayesian filter can work with
  3. Train the filter and see what happens

Compared to the original approach it looks awesome, right? So what stops us approaching all projects like this? Well, there’s something beguiling about wanting to get the framework right from the start this time. It’s more comfortable starting with something we already know how to solve. Sometimes we have a clear vision of how it should end up in our heads and simply start to create that vision from the beginning through to the end.

Start in the middle
— Paul Graham (lightly paraphrased)

Lean startups and the Minimum Viable Product are all about starting in the middle. Paul Graham’s advice for startups can be summed up as ‘first solve the interesting part of the problem, then build the business around it’, but the process is also fractal – starting in the middle applies right down to the level of writing a new class, or a single function. First write some code that solves the problem even if it’s imperfect or partial, then expand it out with your favourite blend of accessors, inheritance and polymorphism (Note: don’t even bother with that bit unless you hate yourself).

I’ve seen four key benefits to starting in the middle:

Benefit 1: Ideas that turn out to be impossible or just plain bad are discovered early. This is classic lean startup advice: fail early.
Benefit 2: Spend most of your the time solving interesting problems and not fine-tuning framework skills. Which would you rather get better at?
Benefit 3: Discover interesting things while your project is still young and flexible enough to adapt to them.
Benefit 4: Once you’ve solved a problem, you’re so motivated to use it that you finish up the surrounding areas in no time. You add extra users because you want to show it to your friends; you add keyboard shortcuts because you’re getting tired of using the mouse all the time. This is programming the right way around – first the need, the desire, and then the solution.

I’ve recently seen all of these benefits while working on my own side-project-turned-startup. Ages ago I had this great little idea for making profiling so simple that it just told you which line of code was slowest in a nice little report and I whipped up some C# code to do just that. The results weren’t making much sense, so I tried plotting the data to a canvas to see what was going on. Pretty soon I was looking at a poor man’s sketch of this:

Visualizing a program's execution

Instantly I knew I’d been working on the wrong thing; seeing the execution of a program laid out before me in all its glory was so rich and so interesting; something I had no hope of summarizing in a small table of figures. I just had to explore it – I added function names, colour, a breakdown of time spent in each and over time it grew into such a valuable part of my toolkit that I’ve started sharing it with the rest of the world.

Would I have changed direction if I had already created a website, a login system, a messaging layer, a database schema all geared around the original idea? No. I’d have reached the interesting part of the problem with a half-finished framework and close to zero energy and enthusiasm. The discouragement at seeing the futility of my cherished profiling-via-pdf idea would’ve seen me put the whole thing back on the shelf and go play Altitude to forget about it.

So start in the middle, start with the interesting, challenging, core of the problem you’re trying to solve. Cut down everything else to ridiculous minima and see what happens; you may create something fascinating.

Note: Yield Thought has moved to http://yieldthought.com – check there for the latest posts!

Written by coderoom

May 18, 2010 at 9:26 am

TDD without the T

with 40 comments

While discussing our natural tendency to spend too much time and effort refactoring code, Jul (aka -jul-) raised an interesting point:

This is why I think TDD is good. According to the rules, you should not write a single line of code before having a failing test, but you should not write more than one failing test. Then write some code which makes the test pass, but then, start over (eg. don’t write code).

If you follow this cycle, you won’t code l’art pour l’art.

Haha.

Odds are you’ll end up writing tests l’art pour l’art.
— Jul, commenting on 7 Reasons To Hate Your Code

Note for those coming from digg: “l’art pour l’art” can be translated as “just for the sake of it”. Much love, my friends.

When I discovered TDD back in 2003 it came like a breath of fresh mountain air sweeping through the midst of my abstraction-freak analysis paralysis. At last I could code relaxed again, without trying to over-engineer every single feature. It set me free.

Years later I couldn’t help noticing I was writing more test code than program code and that I’d stopped working on side projects, because every time I started I thought:

Ok, I’ll hack out a prototype for this cool little game in no time. So, well, I guess I’d best start by writing a few tests for the core mechanics. Right, time to get my framework out. And… uh… ugh, maybe I’ll go watch some Buffy instead.

Writing tests turned me off the whole enterprise so much that eventually I decided I’d just write without them. And nothing awful happened! In fact, it was as much a breath of fresh air as I’d first felt when I started. What gives?

It wasn’t until reading Jul’s comment yesterday that I realized why this was: I hadn’t stopped doing TDD, I’d just stopped doing the T part.

Essentially, the core of many test-driven development processes looks something like this:

  1. Make a list of features and prioritize them
  2. Pick the most important or fundamental feature
  3. Write test cases for it and implement just enough code to make them pass
  4. Repeat form step 2 until you’ve got something useful

I hadn’t stopped doing this, I’d just skipped the “write test cases” part. Writing just enough code to implement the tests you would have written turns out to work just as well!

Let me be clear – I both like and appreciate unit tests. There are many places in which I still use and rely on them. You’d be crazy to skip the unit tests when you’re writing a complicated translation function, or implementing a novel data-analysis algorithm. However, it was still an eye-opener for me to realize that there are places in which they’re a waste of time. Shock! Call Kent Beck! No, it’s true. Albert Einstein backs me up:

Make things as simple as possible, but not simpler
— Albert Einstein (somewhat paraphrased)

Thanks, Al. In this case, testing your accessors and adding half a dozen interface patterns just to support a burgeoning test suite isn’t as simple as possible. Writing no tests at all for your parsing code is too simple. Finding the perfect level of minimalism between code, tests and bugs is difficult, but liberating.

The truth is, doing TDD for all those years changed my programming style, moulded it into a new, more efficient form that stays efficient even when I stop writing tests for everything. I guess this is common; maybe you should try abandoning your test-first framework for your next side-project and see how it works out for you.

TDD without the T: you may find it surprisingly refreshing.

Note: Yield Thought has moved to http://yieldthought.com – check there for the latest posts!

Written by coderoom

April 27, 2010 at 7:15 am

Posted in Programming

Tagged with , ,

7 Reasons To Hate Your Code

with 85 comments

Incompetence is the cause of many ills in the software world, but increasingly I’m seeing a certain kind of competence as being just as destructive. You see, there are a lot of programmers who care deeply about their code. I did, but it turns out there are good reasons we shouldn’t do that; reasons why we should hate our code…

Reason 1: It keeps you open to change

The most productive way to write software is to release early and iterate quickly with feedback from real users, right? It saves us from implementing the wrong features, that it helps build a community and so on. What’s people don’t talk about as often is the impact it has on our relationship with the code. Putting a program in front of users is terrifying because they might not like it. The more lovingly we craft and polish every class before release, the more carefully we plan our abstractions and structures, the more emotionally attached we are to the way we have made it.

The result is that we instinctively resist making significant changes to the code based on early feedback, even though this was the whole point. It’s an unconscious, emotional reaction that we rationalize away to ourselves by claiming the users just don’t understand the feature, or that it just needs a bit more polish when, seen objectively, the best thing to do might be to restructure it completely do do something rather different.

In fact, the best way to remain responsive to your users is to hate your code.

Reason 2: Jeff Atwood says that you should

You can tell a competent software developer from an incompetent one with a single interview question: “What’s the worst code you’ve seen recently?”
If their answer isn’t immediately and without any hesitation these two words: “My own,” then you should end the interview.
Jeff Atwood

Every now and again people attack Jeff for his assertion that we write bad code, for his arms-wide-open group humility. I think people misunderstand him. The message is not you are a bad programmer, it’s that part of being – of becoming – a great programmer is writing code that you’re ashamed of. If you think all the code you write is wonderful, you’re probably not learning anything.

Reason 3: If you don’t hate your code, you’re wasting too much time on it

Andy Brice famously wrote that if you aren’t embarrassed by v1.0 you didn’t release it early enough – you spent too much time polishing it to meet your expectations instead of giving it to the user and finding out what they think of it. A corollary of this is that if you aren’t embarrassed by your own code then you spent time crafting and reworking it until you loved it. This is time that you should have spent trying to make a product the user will love.

Nobody cares if you refactor to use the Chain of Responsibility pattern or not; they want simple, elegant features that work first time. We should spend our time delivering that, instead.

Reason 4: It’s what Jesus would do

No one can serve two masters. For you will hate one and love the other; you will be devoted to one and despise the other. You cannot love both your code and your users.
— Matthew 6:24 (lightly paraphrased)

Reason 5: Loving your code for its own sake will make your product suck

Loving your own code is a kind of hubris. It presumes that you’re writing the code so that you can work on it in the future, or can show off a neat trick to your colleagues.

This love is misplaced; your code isn’t going to be judged on its internal beauty and consistency. It’s going to be judged by people who just want to get their work done. They’ll love it if it makes that easier and they’ll hate it if it distracts them from that task, if it makes their lives harder.

Creator: I love the power of Unix/AJAX/C#/whatever.
Customer: I want to finish my work and go play outside.
Scott Belkun

I once spent six months crafting a beautifully-constructed version 2.0 of our company’s product. We’d started again so we could use unit tests throughout, the code was completely modular and pleasant to work on. There was none of the spaghetti-code complexity that dogged the first version.

We demoed an early prototype to management and marketing who said:

Great, so it’ll be ready next month?

Aghast I pointed out we still had to add a whole bunch of features and do a ton of testing. Their faces fell, and at that point I realized that it didn’t matter how beautiful the new codebase was. It would cost too much to bring it up to the feature level of the old one.

Its intrinsic beauty wasn’t worth anything; only user-visible features weighed in the balance. The project was cancelled, and rightly so.

To worry about code aesthetics more than the aesthetics of the product itself… is akin to a song writer worrying about the aesthetics of the sheet music instead of the quality of sounds people hear when the band actually plays
Scott Belkun

Reason 6: Gandhi would want you to

Hate the User class, love the user.
— Mahatma Gandhi (lightly paraphrased)

Reason 7: It will make you a better developer

Like most people, I got into programming because I wanted to write things for myself and for my friends. During this enthusiastic newbie phase I was a happy user and a happy developer. My code sucked but I didn’t know that yet.

Later on I got into programming for its own sake, I ended up caring deeply about the kind of design patterns I was applying and whether this for loop could be refactored a third time. Eventually this abstraction freak phase left me almost incapable of creating any real value because I invariably got lost in the upper echelons of the software design and never finished any useful features.

Of course, when I started writing professionally I had to care about the features, and had to see my beautiful code mutilated again and again in the name of profit, of getting this feature out in time for the next release. This is enough to make anyone into a bitter veteran.

Eventually I started discovering the joy of programming again, via dynamic languages and web frameworks that made it possible to get useful programs out of the door on day one. I started writing side projects I actually wanted to use. I became free to write the minimum necessary to make something useful. I’d become the ‘guru’, who mistakenly believes he’s better than everyone else because he’s finally become productive again.

But I haven’t become great yet. What might the next step be? I don’t know. Reading more code? Writing less code? Perhaps. But at the moment I have a feeling that to grow in another dimension – creating awesome software – I need to sacrifice the pride I’ve built up in my art:

The seventh step of humility is that a monk not only admits with his tongue but is also convinced in his heart that he is inferior to all and of less value, humbling himself and saying with the Prophet: I was exalted, then I was humbled and overwhelmed with confusion and again, It is a blessing that you have humbled me so that I can learn your commandments.
— The Rule of St Benedict 7.51-54

Until today I found this quote somehow ridiculous or inhuman, yet now I’m beginning to believe that overcoming our egos and admitting that we are writing unworthy code but writing it anyway is a vital step in becoming truly great programmers. Perhaps we can let go and accept that, ultimately, the code never really mattered at all.

Postscript: I’m not saying we should set out to write bad code. It’s vitally important to have an idea of how the code should end up, but instead of working and working until we achieve that and then shipping the product we must write the least we can get away with while gradually approaching the ideal. Understanding this distinction is crucial.

Note: Yield Thought has moved to http://yieldthought.com – check there for the latest posts!

Written by coderoom

April 22, 2010 at 3:45 pm

Code for Flexibility: A Manifesto

with 12 comments

Different environments give rise to different programming styles. Over the last few years there’s been a massive trend for software to move from:

Work for a whole year then release a fixed binary, then write for another year.

to the more dynamic, web 2.0 ideal of:

Whip up a web application and upload each feature as soon as it’s done.

This is a much more efficient way to do business, but it’s a very different kind of programming environment and benefits from a very different programming style – not the one we’ve all picked up by copying API conventions and old-fashioned corporate practices.

If you’re able to make your software available to customers instantly, there is one optimal strategy: code for flexibility.

The flexibility of your code is defined by the ease with which you can modify it to fulfill some purpose you hadn’t envisaged at the time you wrote it.

This is important, because when you give your customers a rapidly-iterating product you’re going to find your initial guess at what they wanted was completely wrong. In fact, all your guesses are probably wrong. You’re going to spend years learning from your customers and adapting your software in all sorts of unexpected ways to fit their needs as precisely as possible.

For a long time I confused generality with flexibility; I was always worrying about how I might want to use a class in the future and trying to abstract out all the common use cases right form the start. As it turns out, this is the opposite of flexibility; this builds rigidity into the project. The moment you realise that actually it makes much more sense to have flip your design so that users vote for *each other’s* questions a little part of you dies inside, because you now have five levels of abstraction and four different database tables to rewrite.

In fact, flexible code is specific code. We want to write code that expresses, as succinctly as possible, a solution to a problem. It’s quicker to read and understand code with fewer syntactic elements, such as variables, functions and classes. It’s also quicker to repurpose.

We also build flexibility – or rigidity – into the large-scale structure of our programs. I’ve often fallen in love with the idea of encapsulation for its own sake; I thought that each part of my program should be as well-hidden from the rest as possible, with only one or two well-specified interfaces connecting things. This is a very tempting dream that results in a kind of tree-like structure of classes. This is extremely rigid, because by design it’s difficult to get access to classes in another branch of the tree.

The best way to build for flexibility is drawn from the Lisp world and championed by Paul Graham: when working on a problem, write code that builds up into a language for describing and reasoning about the problem succinctly.

You can magnify the effect of a powerful language by using a style called bottom-up programming, where you write programs in multiple layers, the lower ones acting as programming languages for those above.

This way the solution ends up being a clear, readable algorithm written in this language – the language of the problem domain. In non-lisp languages you end up with a set of functions and classes that make it easy to reason about the problem, a little like the standard string and mail classes make it easy to work with strings and email.

Building up code for reasoning about the problem domain is vital for flexibility, because although our solution to the problem might change drastically as we get extra insights from our customers, the domain of the problem will probably only change incrementally as we expand into new areas. Adopting this flatter, domain-language appropach to program design almost always increases flexibility.

Another aspect of flexibility is robustness. A function or class that makes assumptions about the circumstances it is called in is going to break as soon as we repurpose it in some other part of the code; sooner or later I always forget that the caller needs to check the file exists, or that the user isn’t null and already has a validated address. There are two schools of thought on how to deal with this – contract programming (essentially visible, machine-verified preconditions) and defensive programming (make no assumptions, handle all the exceptions you can locally and try hard not to destroy any persistent state if things go wrong). It doesn’t really matter which you use, but use one of them.

Many of the extreme programming principles help us write flexible code – the c2 team recognized that:

Change is the only constant, so optimize for change.

They looked at this from a project management perspective, but code guidelines like Don’t Repeat Yourself and You Ain’t Gonna Need It are well-recognized as being fundamental to producing flexible code. In fact, these two oft-quoted principles are worth looking at more closely in terms of how they create flexibility.

Don’t Repeat Yourself: When modifying a bit of code it doesn’t help if there are three or four undocumented places it also needs to be changed; I never remember them all. A perfectly good way to deal with this is to add a comment in each block mentioning the link rather than to refactor right away. Over-zealous refactoring tends to merge lots of bits of code together that look kind of similar but ultimately end up going in different directions. At this point very few people take the logical step of splitting a class or subsystem back into two more specialized units; instead it’s over-generalized again and again until it’s completely unmaintainable

Refactoring should always be Just In Time, because the later you leave it the better you understand the problem; refactor too soon and you’ll combine things in a way that restricts you later, building rigidity into the system.

You Ain’t Gonna Need It: This doesn’t just apply to extra functionality. It applies to all elements of your code, from accessors (a waste of time in most cases) to overall class structure. You’re not going to need to handle N kinds of book loan, you’re going to handle at most two, so don’t write some complicated code to handle the general case. You’re not going to need three classes, one interface and two event types for your “please wait” animation because there’s only ever going to be one and it’s always going to be while printing. Just write a function with a callback and release – the simpler it is, the quicker we can write it today and the more easily we can modify it tomorrow.

There is a tension here. On the one hand, we want to write our software by constructing recombinable blocks that represent the problem domain, yet on the other we want to write the simplest thing possible – and writing reusable blocks of code isn’t usually the simplest thing possible.

This tension is resolved when we stop looking at a program as a snapshot of its state at any one time and instead look at it as an evolving codebase with many possible futures. So we write the simplest thing possible, yet while doing so we keep an eye on its potential for being refactored into nice, reusable blocks and avoid doing making poor choices that will make that process difficult. The potential for refactoring is just as valuable as the refactoring itself, but by deferring the refactoring we keep our options open.

The ability to see the code you’re writing today and its possible evolution through time is something you can focus on learning, but it also grows with experience. It’s one of the things that makes a great hacker’s code subtly better than a newbie’s code – both start writing simple code that addresses the problem directly, but the newbie makes all sorts of small structural mistakes that get in the way of the code’s growth, whereas the hacker knows when it’s time to turn this set of functions into a class, or to abstract out this behaviour, and has already prepared the way for doing so. The effect is to make programming look effortless again, naturally flowing from the simple into the complex.

I’m not a great hacker who does this as naturally as breathing. I have tasted it, have seen glimpses of it in my own work and in other people’s, but I still make mistakes; I mistime my refactoring – sometimes too early, sometimes too late. I still bind objects to each other too tightly here, or too loosely there. Despite my failings, just aiming at this goal makes me far more productive than I’ve ever been before. It’s not an all-or-nothing premise. The closer you come, the smoother and lower-friction your development will be.

We can gather all these heuristics together into a concise manifesto:

A Manifesto for Flexibility

  1. Write new code quickly, as if you’re holding your breath. Cut corners and get it in front of users as quickly as possible.
  2. Keep your code specific, with a clear purpose. Don’t over-generalize and don’t refactor too early – it should be as simple as possible, but not simpler.
  3. Stay aware that all code is thrown away or changed dramatically. Hold the image of the refactoring you’d like to do in your mind and avoid doing things that will make it more difficult – this is slightly better than doing the refactoring now.
  4. Recognize the point at which simple code becomes messy code and refactor just enough to keep the message clear. Just In Time refactoring is not the same as no refactoring.
  5. Build up a language for reasoning about your domain and express your application in that language. Avoid building up a large, rigid hierarchy of over-encapsulated classes that embody your particular solution to the problem.

Postscript: You should do this in a startup and you should do it in personal project, but you shouldn’t do it everywhere. If, say, you’re writing the Java or .NET API then none this applies to you because:

  1. Millions of people will abuse your API in every way possible the very second it’s released.
  2. Every time you change something a howling mob will descend upon your office, making it difficult to get a good parking spot.

Written by coderoom

April 16, 2010 at 12:37 pm

On The Fear of Reading Code

with 25 comments

As programmers, we love writing code. Opening a fresh, clean editor, bringing up a blank form in Visual Studio, the world crisp and uncluttered and ready to receive your vision. It’s easy to understand why starting a new project is fun.

However, mostly we don’t like reading code. Dropped into the middle of some densely-packed jungle of a project, filled with obfuscated filenames and cryptic little comments like:

if (section == 0) /* can’t validate section this way */

and having to fight your way through to fix a bug or add a featurette without breaking anything else. It’s a lot like going to certain modern art exhibitions; you end up feeling as if those responsible are deliberately obscuring things just to piss you off. Actually, in the programming world this is sometimes the case. It’s easy to understand why people will go to extraordinary lengths to avoid reading and understanding complicated, real-world code.

This is unfortunate, because reading code – even bad code – is the key to writing good code.

When I was learning to program someone told me that I should try to read as much code as possible. Budding genius that I was, I thought this was advice for stupid people who needed to learn from their betters. I thought the only reason to read code was to pick up tricks from it.

How wrong I was. The real reason to read code has nothing to do with learning from the programmer who wrote it.

Recently I discovered that learning a foreign language teaches you two things: how to communicate in that language and how to communicate in your own language to non-native speakers. You learn that simple grammatical structures and shorter sentences are easier to understand. You get a feeling for when someone’s following you and which words in the sentence are most important to pronounce clearly.

It’s the same with reading and writing code. Reading code teaches you how to read code and it teaches you how to write code that’s easy to read. Both of these are desperately important.

Actually reading code is something most of us subconsciously avoid. I’ve lost track of the number of times I’ve been through this little dance:

  1. Decide to fix a bug or add a feature to a piece of code someone else has written
  2. Take a brief look at said code
  3. Frown in distaste because the original programmer – curse his blackened soul – put the opening brace on the end of the if statement instead of on a new line, as God intended*
  4. Spend the next 90 seconds not being able to work out why it was put together the way it was, or what’s calling what and why
  5. Tell myself: “Boy, this code is a real mess! Even I can’t understand it! The best thing to do is clearly to make a clean start and write it myself – it can’t be that hard and I can always refer back if I run into problems!”
  6. Spend the next few hours, days or (on one memorable occasion) weeks reimplementing a slightly buggier, less complete version of the original code. I now have something that isn’t noticably better by any metric, but I feel I understand it and that lifts a weight from my heart
  7. “Phew”, I say, wiping my brow with the back of my hand, “it’s a good job I rewrote that!”

* 😉

It’s only after years and years of repeating this pattern that it has begun to dawn on me that each time I do this I’m really just wasting precious, precious time on something that doesn’t improve the product at all. What’s worse, I’m only doing it because I can’t face the thought of reading somebody else’s code. If I spent one fraction of the time reading and understanding it then I’d learn a lot more about the problem it’s trying to solve and would be in a great place to tweak or refactor it to suit my needs.

The desire to start afresh comes from the fear of reading code, and it’s always, always a waste of time because – guess what? When you’re done, there’s just as much code to be read next time you come back to it. The right thing to do is to read it, grok it and gently massage it into a more suitable shape. Or hack it apart brutally and repurpose it. It doesn’t matter! Once you understand it, you can do what you want with it. Code doesn’t rust and it doesn’t go off. Just read it, change it and use it. Every time I do this now, it makes me happy.

Just being able to read complex code quickly and effortlessly is a wonderful aim in itself, but the real benefits come from the effect it has on your own code. When you first learn to program, you’re really learning to write code that communicates your intentions to the compiler. Initially this seems like hard work, but actually a compiler jumps through a lot of hoops to work out what your convoluted code is supposed to mean.

To become a better developer, however, you need to learn to write code that simultaneously communicates your intentions to the compiler and to other programmers, who would rather do anything than work out what you were trying to achieve.

Even when working on your own you benefit hugely by writing code that clearly communicates its intentions, because most interesting programs end up being larger than you can hold in your head at any one time and end up being worked on for more than one session.

If you think your intentions are clear, but you’re not in the habit of reading code, you’re probably wrong and they’re only clear to you (and only today). It’s when you summon up your courage and dive into the deep end of someone else’s code and try to work out what’s going on without any reference points that you start to notice what makes this easy and what makes it hard. Would a brief comment here have saved you looking things up in that other set of nested classes?

When you come back to write more code yourself, you recognise which parts might be confusing, where a helpful comment or carefully-chosen function name would clear up any potential ambiguities. You recognise that a future maintainer who comes in to change this function will need to know that it’s affected by this other class over here.

In short, you learn to see your code with the eyes of a reader, and in doing so you become better at writing it. You can work on it faster and your team can work on it faster. Everybody wins. I worked professionally for years – years – without ever really reading anyone else’s code. Once I started, I began to see the whole field in a new light. I wish I’d started reading code years ago, I really do.

Written by coderoom

March 26, 2010 at 3:02 pm

Posted in Programming

Tagged with

An Honest Superstar: Always One Level Deeper

with 7 comments

So the other day, coffee in hand, I opened up one of our bug tickets about some unusual error messages in our C++, GUI-based desktop application and was confronted with this little gem from another dev:

Compiler bug.

The code does this:

00000000000002f0 <petscinitialize_>:
2f0: 48 81 ec e8 01 00 00 sub $0x1e8,%rsp
2f7: 48 89 5c 24 18 mov %rbx,0x18(%rsp)
2fc: 48 89 f3 mov %rsi,%rbx
2ff: 48 89 6c 24 10 mov %rbp,0x10(%rsp)

but the compiler doesn’t emit the correct FDE. It claims %rbp is not
stored on the stack frame, even though it’s stored at 0x10(%sp) by the code.

00000038 0000001c 00000000 FDE cie=00000000 pc=000002f0..00000add
DW_CFA_undefined: r6
DW_CFA_advance_loc: 7 to 000002f7
DW_CFA_def_cfa_offset: 496
DW_CFA_nop
DW_CFA_nop
(r6 = %rbp)

I responded instinctively by spraying my keyboard with droplets of delicious dark caffeine. “Kr-ala-fskwag-yak,” I spluttered, “Uh wha?”

I shouldn’t have been surprised – this kind of bug resolution isn’t all that uncommon from the developer in question, although this was a particularly fine example at a sensitive time of the morning. The developer is, I somewhat grudgingly admit, the best I’ve ever worked with. She* is also prone to patch the windowing system we work with, or indeed any other open source API we have to use.

(* The sex of the developer in question has been changed to protect the innocent)

You might argue that tracking a bug all the way from the GUI symptoms down through assembler and DWARF output is overkill, a waste of time that could better have been spent elsewhere, but you’d be wrong, wrong, wrong. The amount of time it took Janine* to do this? 54 minutes.

(* Yes, the name has been changed as well – there’s no such thing as overkill, after all)

Fifty. Four. Minutes. From start to end. I couldn’t have done that. More to the point, I wouldn’t have. I cut my coding teeth on the Windows API and I’m used to finding what appears to be a bug^H^H^Hundocumented API behaviour and thinking “fine, let’s not waste any more time there, I’ll find another way around.”

Everyone does that, right? Sometimes things just don’t work. The universe just says ‘no’. But the other way of looking at it – Janine’s way – is that computers are logical systems that follow simple instructions. There’s *always* a reason they’re doing what they’re doing. If you keep looking, you can find it.

Having watched Janine at work for a while now, I can see three sweet bonuses for doing this regularly.

Bonus 1: You actually fix the bug, resulting in more elegant application code, free of awkward workarounds.

Bonus 2: You build up a set of tools and techniques for following bugs right down to the assembly level, which makes tracking down problems in the future easier and faster every time. Eventually it takes even less time than getting a cup of coffee and complaining about the API to anyone who can’t get away fast enough.

Bonus 3: You look like a superstar without turning to the dark side.

But these are all just bonuses compared to the best reason to hunt bugs relentlessly through the layers of API right down to their source:

Superstar bonus: You understand your software stack at many levels of abstraction.

Let me explain why this is awesome, because I know it sounds, well, dull. Abstraction is such a Java word. I know.

It’s like this: when you learn to drive a car, you’re told that one pedal makes it go faster, one slower and the wheel turns. Maybe you learn to change gears. That’s pretty much enough to be able to drive a car from A to B.

A racing driver, on the other hand, knows – even groks – that pushing the accelerator increases the flow of fuel through the injectors. He knows that the exhaust gases produce back-pressure on the engine while the turbo is still spinning up, before the boost effect starts to kick in. He knows that his suspension setup distributes this amount of pressure on the tyres during a tight corner, which is just below the coefficient of friction with this road surface.

To put it another way, he understands driving a car at a deeper level; he sees behind the first layer of abstraction and this makes him a much better driver.

In the same way, Guido van Rossum is a much better Python programmer than I’ll ever be, because he knows the system literally inside out. Sure, I have this idea that the garbage collection system uses reference counting rather than the more modern generational systems, but I don’t know that it’ll need to do some cleaning up exactly here, or that using tuples instead of lists just there will result in two fewer indirections per loop in the bytecode.

Although I don’t believe in Joel and friends’ concept of ‘superstar’ programmers (a subject for a whole post on its own), it seems clear to me that you can be 10x as productive in a particular domain that you understand deeply, thoroughly.

That’s why I’m convinced that anyone who wants to become great should take the extra time to peel back that comfortable layer of abstraction and learn about the unseen world beneath.

It’s the only honest way I know to become a superstar.

Written by coderoom

February 1, 2010 at 8:24 pm

Posted in Programming

Tagged with ,

The Best Comment Ever (No, I Didn’t Write It)

with one comment

Disclaimer: I didn’t write this and take no credit for it whatsoever. edw519 wrote it as a comment on Hacker News, which you can see here: 3 Simple Rules That Will Make You a ‘Superstar’ Developer – or at the time of writing on the wonderful HN Best Comments page. However, I’m terrified that this zen-like jewel will become lost in comment-page obscurity. Also I want an easy way to link to it, so here it is without further commentary:

A smart accountant once told me that the answer to “How much money did you make?” is always, “Who wants to know?” If it’s an investor, the answer is “A lot.” If it’s a customer, the answer is “A little.” If it’s the IRS, the answer is “None.”

Same thing here. The answer to “Who is a superstar developer?” is always, “Who wants to know?”

To a project manager, the programmer who hits every deadline (regardless of quality) is a superstar.

To a customer, the programmer who solves their problem quickest is a superstar.

To a business owner, the programmer who makes them the most money is a superstar.

To a PHB, the programmer who makes them look the best is the superstar.

To a journalist, the programmer who tells the best stories is the superstar.

To a junior programmer, the best mentor is the superstar.

To another programmer, the programmer they are most likely to want to go into battle with is the superstar.

— edw519, writing an incredible comment on an otherwise unworthy Hacker News story.

Written by coderoom

February 1, 2010 at 7:58 pm

Posted in Programming

Tagged with , , ,