Short Commit Cycles

How often do you commit? Once a week? Once a day? Once an hour? Every few minutes? The more often you commit, the less likely you are to make a mistake.

I used to work with a guy who reckoned you should commit at least every 15 minutes. I thought he was mad. Maybe he is. But he’s also damned right. I didn’t believe it was possible: what can you actually get done in 15 minutes? At best, maybe you can write a test and make it pass. Well good! That’s enough. If you can write a test and make it pass in 15 minutes, check that sucker in! If you can’t: back it the hell out.

But I’ll never get anything done!

Sure you will, you just need to think more. Writing software isn’t about typing, it’s about thinking. If you can’t see a way to make a step in 15 minutes, think harder.

Chase the Red

One of my oft-used anti-patterns is to “chase the red”. You make one change, delete a method or class you don’t want – and then hack away, error by error, until the compiler is happy. It might take 5 minutes. It might take a week.

It’s very easy to get sucked into this pattern – you think you know where you want to get to: I have a method that takes a string – maybe it’s a product SKU from the warehouse; I want to replace it with a StockUnit which has useful functionality on it. Simples: change the signature of the method to accept StockUnit instead of string and follow the red, when the compiler’s happy: I’m done.

Trouble is – how do I know that every calling method can change? Maybe I think I know the code base and can make a reasonable guess. Maybe I’m even right. But it’s unbelievably easy to be wrong. I might even check all references methodically first, but until the code’s written – it’s just a theory. And you know what they say about the difference between theory and practice.

Is there a different way? What if I add a new method that accepts a StockUnit and delegates to the original method? I can test drive adding the new method, commit! I can go through each reference, one by one: write a failing test, make it pass by calling the new method, commit! Step-by-step, the code compiles and the tests pass every step of the way.

What happens if I hit something insurmountable half way? Where I am is a mess, but it’s a compiling, green mess. If I decide to back out I can revert those commits. Or refactoring tools can inline the method and automatically remove half the mess for me. But the critical thing is, every step of the way I can integrate with the rest of the team, and all the tests pass in case I hit something unexpected.

Merge Hell

The trouble with long running branches (and I include in that your local “branch” that you haven’t committed for two weeks!) is that the longer they run the harder they are to integrate. Now sure, git makes it easier to manage branching & merging – but you still have to do it. You still have to push & pull changes regularly – let others integrate with you and integrate with others as often as you can.

The likelihood of you having merge problems increases rapidly the longer your branch is open. If it’s 15 minutes and one test, you know what? If you have a merge problem, you can throw it away and redo the work – its only 15 minutes!

Just keep swimming!

But if you’ve been working for days and you hit merge hell, what do you do? You’re forced to wade through it. What you’re doing is chasing the red in your version control system. You’ve adopted an approach that gives you no choice but to keep on hacking until all the red merge conflict markers are gone from your workspace. If it takes 5 minutes or 5 days, you’ve got to keep going because you can’t afford to lose your work.

The kicker is by the time you’re done merging and everything compiles and works again, what’s the betting some other bugger has jumped in with another epic commit? Off we go again. You’re now in a race to try and merge your steaming pile before anyone else gets in. This is a ridiculous race – and who wins? Nobody, you’re still a loser.

Instead, if you adopt the 15 minute rule, you write a test, make it pass, check it in and push to share with everyone else. Little and often means you lose little time to merge conflicts and instead let your version control system do what it’s good at*: merging changes!

* doesn’t apply to those poor suckers using TFS, sorry

Brain Fade

An interesting side effect of a short cycle time is that you limit the damage periods of brain fade can do. I dunno about you, but there are times when I really shouldn’t be allowed near a keyboard. The hour after lunch can be pretty bad – a full belly is not good for my thinking. The morning after the night before: it’s best if you keep me away from anything mission critical.

The trouble is, if I have a multi-day branch open I’m almost guaranteed to hit a period of brain fade. Because I’m not committing, when my head clears and I realise I’ve screwed up I can’t just revert those commits or throw my branch away entirely – I have to try and unpick the mess I just made from the mess I already had. It’s incredibly hard to be disciplined and tidy when you’re wading in excrement.

We all make mistakes – but version control gives me an overview of what I did, without relying on my flaky memory. Maybe I’ve gone completely the wrong way and can unpick parts of what I’ve done, maybe I got lucky and some commits were half-way decent – I can cherry pick those and start a new branch. Without version control I’d be flapping around in an ungodly mess trying to figure out how to keep the good bits without just binning everything. All the time trying to explain to the project manager how I’m 90% done! No, really! Nearly there now!

Practice!

Version control is an invaluable tool that we must learn to use properly. It takes discipline. It doesn’t come naturally. If you’ve never worked in such short cycles, work through a kata committing regularly. Our natural instinct is to type first and think later. Stop! Think about how you can make an increment in 15 minutes and do that. If you can’t: revert!

Measuring Software

A while back I read Making Software – it made me disappointed at the state of academic research into the practice of developing software. I just read Leprechauns of Software Engineering which made me angry about the state of academic research.

Laurent provides a great critique of some of the leprechauns of our industry and why we believe in them. But it just highlighted to me how little we really know about what works in software development. Our industry is driven by fashion because nobody has any objective measure on what works and what doesn’t. Some people love comparing software to the medical profession, to torture the analogy a bit – I think today we’re in the blood letting and leeches phase of medical science. We don’t really know what works, but we have all sorts of strange rituals to do it better.

Rituals

Rituals? What rituals? We’re professional software developers!

But of course, we all get together every morning for a quick status update. Naturally we answer the three questions strictly, any deviations are off-topic. We stand up to keep the meeting short, obviously. And we all stand round the hallowed scrum kanban board.

But rituals? What rituals?

Do we know if stand ups are effective? Do we know if scrum is effective? Do we even know if TDD works?

Measuring is Hard

Not everything that can be measured matters; not everything that matters can be measured

I think we have a fundamental problem when it comes to analysing what works and what doesn’t. As a developer there are two things I ultimately need to know about any practice/tool/methodology:

  1. Does it get the job done faster?
  2. Does it result in less bugs / lower maintenance cost?

This boils down to measuring productivity and defects.

Productivity

Does TDD make developers more productive? Are developers more productive in Ruby or Java? Is pairing productive?

These are some fascinating questions that, if we had objective, repeatable answers to would have a massive impact on our industry. Imagine being able to dismiss all the non-TDD doing, non-pairing Java developers as being an unproductive waste of space! Imagine if there was scientific proof! We could finally end the language wars once and for all.

But how can you measure productivity? By lines of code? Don’t make me laugh. By story points? Not likely. Function points? Now I know you’re smoking crack. As Ben argues, there’s no such thing as productivity.

The trouble is, if we can’t measure productivity – it’s impossible to compare whether doing something has an impact on whether you get the job done faster or not. This isn’t just an idle problem – I think it fundamentally makes research into software engineering practices impossible.

It makes it impossible to answer these basic questions. It leaves us open to fashion, to whimsy and to consultants.

Quality

Does TDD help increase quality? What about code reviews? Just how much should you invest in quality?

Again, there are some fundamental questions that we cannot answer without measuring quality. But how can you measure quality? Is it a bug or a feature? Is it a user error or a requirements error? How many bugs? Is an error in a third party library that breaks several pages of your website one bug or dozens? If we can’t agree what a defect is or even how to count them how can we ever measure quality?

Subjective Measures

Maybe there are some subjective measures we could adopt. For example, perhaps I could monitor the number of emails to support. That’s a measure of software quality. It’s rather broad, but if software quality increases, the number of emails should decrease. However, social factors could so easily dwarf any actual improvement. For example, if users keep reporting software crashes and are told by the developers “yeah, we know”. Do you keep reporting it? Or just accept it and get on with your life? The trouble is, the lack of customer complaints doesn’t indicate the presence of quality.

What To Do?

What do we do? Do we just give up and adopt the latest fashion hoping that this time it will solve all our problems?

I think we need to gather data. We need to gather lots of data. I’d like to see thousands of dev teams across the world gathering statistics on their development process. Maybe out of a mass of data we can start to see some general patterns and begin to have some scientific basis for what we do.

What to measure? Everything! Anything and everything. The only constraint is we have to agree on how to measure it. Since everything in life is fundamentally a problem of lack of code, maybe we need a tool to help measure our development process? E.g. a tool to measure how long I spend in my IDE, how long I spend testing. How many tests I write; how often I run them; how often I commit to version control etc etc. These all provide detailed telemetry on our development process – perhaps out of this mass of data we can find some interesting patterns to help guide us all towards building software better.

Knowledge vs Superstition

How much of what we do is based on sound understanding? And how often do we do things without really understanding why? Everything we do: from walking down the street to writing software – sometimes we understand why we do things, other times we follow superstition.

We’re trained to associate cause with effect, even if we don’t understand the connection:

Press button: get food. Hungry. Press button. Food.

At an animal level, the reason is irrelevant. But as rational human beings, we’re able to understand the relationship between cause and effect; but that doesn’t mean we always behave rationally. Ever walked around a set of ladders rather than under them? My wife makes me laugh by saluting magpies. These superstitions are entirely irrational behaviours, but are mostly just amusing and harmless.

But when it comes to computers, this ability for us to not worry about why things work is pervasive. For example, ever had a conversation like the following:

Wife: I need to email someone this word document I just wrote

Me: ok, where did you save it?

Wife: in word

Me: ok, but is it in your documents folder or on your desktop?

Wife: I clicked File then Save.

Me: ooookaaaay, but what folder did you save it in?

Wife:

Me:

Wife:

Me: *sigh*

Now, this isn’t an uncommon problem – people use computers all the time without really understanding what’s happening underneath. We learn a set of behaviours that do what we want. Why that set of behaviours work is irrelevant. We have a mental model that describes the world as we see it, our model is only called into question when we need to do something new or different.

Mental Models

The trouble is, from the outside, it can be very difficult to tell the difference between superstition and understanding. For example, how many Windows users actually understand shortcuts? Ever tried explaining the idea to your Dad? But yet, I bet he can click links on his desktop or in his start menu without any problem. His mental model of the world is sufficient to let him work, but insufficient to let him understand why it works. As soon as you step outside the normal behaviour – for example, trying to explain the difference between deleting the desktop icon and deleting the application – your mental model is challenged and superstitions exposed.

For users to not question things and adopt computer superstitions is understandable. But for software developers, it’s frightening. If you don’t understand something someone is explaining, you have to challenge it – either their model of the world is wrong or yours is. Either way, you’re not going to understand and agree until you can agree a consistent model.

Voodoo Programmers

But I’ve worked with developers who effectively become superstitious programmers. They don’t really know why something works, they just know that clicking these buttons does the right thing. Who needs to know how Hibernate works, as long as I know the magic incantations (or can copy&paste from somewhere else) – I can get the job done! But as another developer on the team, without looking closely – can I tell whether you’ve setup the Hibernate mappings because you know how they work, or just copy&pasted it from somewhere else without understanding?

The trouble is, almost all programmers resort to copy&paste&change from time-to-time. There are some incantations that are just too complex and too rarely used to memorise, so we quite reasonably borrow from somewhere else. But the difference between a developer that uses the incantations to aide his memory and the developer who just blindly copies without thinking is incredibly subtle. It’s easy to be one while thinking you’re the other – especially if it’s something you don’t do all the time.

Understanding

How many times have you found a fix for something but not understood why? Do you keep investigating or move on? For example, I was investigating a race condition recently and I’d spotted an incorrect implementation of double-checked locking – but I found that fixing it didn’t actually fix the bug. I wasn’t convinced I’d implemented the double-checked lock correctly either, so I replaced it with a method that always locked. What do you know: problem fixed!

Now, given what I know of the bug – that’s not right. Double-checked locking is a performance tweak, it shouldn’t impact the thread-safety of the solution. The fact that locking in all cases has fixed the bug gives me a hint that there must be something else that isn’t thread safe. By introducing the lock, the code that runs just after ends up effectively locked – it’s unlikely to get interrupted by the scheduler with another thread in the same critical section.

After another couple of hours investigation, I found the code in question – there was a singleton that was being given a reference to a non-thread safe object. I could have left my lock in place, since it “fixed” the bug – but by following my intuition that I didn’t understand the reason I found a much more damaging bug.

Understanding is key, be wary of superstitions. If you don’t understand why something works, keep digging. If this means you slow down: good! Going fast when you don’t understand what you’re doing is a recipe for disaster.

Fast Feedback

Writing good software is all about getting feedback, quickly. Does it compile? Does it function? Does it build? Does it deploy? Does it do what the customer wanted? Does it actually work? Every step of the way we have feedback loops, to improve the software. The faster these feedback loops are, the faster the software improves.

Builds

Don’t you hate waiting for your code to compile? Or, if you use a language from this century: do you remember back in the olden days when you had to wait for the compiler? Until recently, I’d actually forgotten that incremental compilers are a relatively new invention. I remember when JBuilder (my IDE of choice back in those distant times) first introduced me to incremental compilation – it was something of a revelation! You mean, I don’t have to hit compile? It just does it? In the background? Like magic?!

A few years ago I joined a company who had something of a byzantine build process. As was the fashion at the time, they used ant for their build. Unfortunately, nobody had told them that Eclipse could also compile code. So all code was built with ant. Made a change? Run the ant build to build the relevant library (may require guesswork). Copy it (by hand) to the app server. Quickly restart WebSphere (note: not quick). Test. Lather. Rinse. Repeat. Die of boredom.

Eventually, I replaced this with an Eclipse workspace that could run the application. No more build step. No more copying things by hand. No more mistakes. No more long delays in getting feedback.

Just recently I started working with C++ again after nearly a decade in byte code / interpreted languages. I’d actually forgotten what it was like to wait for code to compile. I’d got so used to working in Eclipse where you press Go and Things Happen(tm). Now instead I have to wait for a build before I can do anything. Every little change involves minutes of my life waiting for Visual Studio.

Then, if I’m really lucky – it will even compile! Remember when your IDE didn’t give you little red squiggles or highlight broken code? How fast is that feedback loop now? Before I’ve even finished typing the IDE is telling me I’m a moron and suggesting how to fix it. Assuming my code compiles, next I run the gauntlet of linking. Normally that means some godawful error message that googling just gives decade old answers and stack overflow posts that might as well be discussing religion.

TDD

I suspect this is why TDD is less common in the C++ world. Not only does the language feel ill-suited to doing TDD (to be honest, it feels ill-suited to writing software at all), but if you have to wait minutes after each change – TDD just doesn’t work.

  • Write a failing test
  • Wait minutes for the compiler to check your work, maybe go for a cuppa
  • Write code to make the test pass
  • Wait minutes for the compiler to check your work, perhaps its lunchtime?
  • Refactor

Actually, scrap the last step – since C++ is basically entirely devoid of automated refactoring tools – just leave whatever mess you’ve created because it’s about as good as it will get.

But with a red, green, refactor cycle that takes approximately 2.6 hours – it would be impossibly slow. No wonder TDD happens less.

Pairing

I’ve been arguing recently about whether pairing or code review is the best way to improve code quality. I always used to be a huge believer in code review – I’d seen it have a massive impact on code quality and really help the team learn both the code and how to code better.

But now, after spending months pairing day in day out – I think pairing is better in every conceivable way than code review. Why? Because it’s so much more immediate. How many times have you heard feedback from code review getting left because “we don’t have time right now” or “we’ll come back to that just as soon as we’ve got this release out”.

But with pairing, you have your reviewer right there offering feedback, before you’ve even finished writing the line of code. Just like your modern IDE – giving you feedback before you’ve even had chance to get it wrong. And, just like the IDE, if the smart ass sitting next to you thinks he knows better, pass over the keyboard and let him show you.

This is just impossible with code review. The feedback cycle is necessarily much slower and, worse, it’s too easy to ignore. You can add a story to the backlog to fix code review comments. You can’t so easily add a story to the backlog to make the argumentative bloke next to you shut up! (More’s the pity, sometimes)

But either way – whether you get feedback from code review or pairing, the important thing is to get feedback. If you’re not getting feedback: you’re not learning and neither you nor your code are improving.

Pattern oriented programming

Ever since the “Gang of Four” book, everyone and their uncle is an expert in patterns. Software is all about patterns – the trouble is, it seems very little of note has happened in the intervening 20 years.

Why patterns are good

Patterns help because they let us talk about code using a consistent language. Patterns make it easier to read code. Ultimately, reading code is all about being able to reason about it.

If I change this, what’s going to break?

This bug got reported in production, how the hell did it happen?

If I can see the patterns the code implements, it lets me reason about the code more easily, without having to carefully analyse exactly what it does. Without them, I have to carefully understand every single line of code and try and reverse engineer the patterns.

The trouble is, the patterns often get mixed up with the implementation. This makes it hard to discern what the pattern is, and whether it’s actually being followed. Just because a class is called TradeManagerVisitorFactory doesn’t mean I actually know what it does. And when you open up the rats nest, you realise it’s going to take a long time to know what on earth it’s doing.

Patterns Exist

Patterns exist in our code, whether we explicitly call them out or not – there are hundreds, probably thousands of patterns that we’re all familiar with. Wouldn’t it be great if these patterns, at least within a single code base, were consistent? Wouldn’t it be great if we could help keep developers on the straight and narrow so that when they instantiate a second instance of my “singleton” we can break the build because it’s obviously changed something that might break all sorts of assumptions.

If we could start identifying the patterns in our code, and (somehow) separate that from how they’re implemented, we might actually be able to change how certain things are implemented, consistently, mechanically, across an entire enterprise-scale code base. Let me guess, an example would help?

The Builder Pattern

Ok, it’s a really simple pattern – but it makes a nice example. I have a class, that I need to be able to create, so I use the builder pattern. However, really, a builder is a type of object construction pattern. If I start thinking about different ways objects can be instantiated I can quickly come up with a handful of alternatives:

  • A constructor, with a long parameter list
  • A builder, with a lot of setXxx methods
  • A builder, with a lot of withXxx methods, that each return the builder for method chaining
  • A builder with a list of properties for object initialisation (C#)

Now, this means I have four ways of implementing “the builder pattern”. And you know, it makes precisely zero difference, functionality-wise, which I choose. It’s an entirely stylistic choice. However, I probably want it to be consistent across my codebase.

When it boils down to it, my pattern has three elements:

  • The actual pattern – e.g. a builder with method chaining
  • The logic & configuration for the pattern – the list of fields, the types, any type conversions or parsing etc
  • The actual rendering of the first two – this is all we have today: source code

I don’t want to get rid of the last (code generation is great, until you have to, you know, actually use the generated code). This should all work from existing, real code. But maybe we could mark up the code with annotations or attributes to describe what pattern we’re following and how it’s configured. Some of the logic and configuration would have to be inferred – but that’s ok, once we know it’s a builder pattern we can take entire method bodies as “logic”.

Pattern Migration

But you know what would be really awesome? If I could change how the pattern is implemented. Maybe today I’m happy with all my objects being constructed from a long parameter list. But maybe tomorrow I decide to change my mind and use builders and withXxx method names. Wouldn’t it be awesome if I could simply change the global config and have all my code automagically refactored to match? If all my builders are annotated and identified, and all enforced to be written the same way – I can extract the configuration & logic from the implementation and re-render the pattern differently. I could programmatically replace a constructor call with a builder or vice versa.

Ok, the builder is a trivial example that probably isn’t of much use. But how many more patterns are there? Say today I have classes with lots of static methods. Well, really, they’re singletons in disguise. But none of the cool kids create singletons nowadays, they use IoC frameworks like spring to create singleton beans. Wouldn’t it be nice if I could mass-migrate a legacy codebase from static methods, to singletons, to spring beans (and back again when I realise that’s made things worse!)

Controllers

What about a more complex example – let’s compare spring-mvc and struts. Two frameworks to accomplish basically the same thing – but both with a very different philosophy. The answer isn’t to build a framework to capture the common parts of both – trust me, been there, done that: you get the worst of both worlds.

But, could you describe a pattern (probably several) that struts actions and spring-mvc controllers follow? Ultimately, both spring-mvc and struts let you respond to web requests with some code. Both give you access to the HTTP request and the session. Both give you a way of rendering a view. I wonder if you could describe how to extract the pattern-specific parts of a struts action and a spring-mvc controller? The config comes from different places, how to render views is different, how the view is selected is different, even the number of actions-per-class can be different. But, could you extract all that functionally irrelevant detail and separate the pattern configuration from the underlying source code.

If you could, maybe then you could describe a transformation between the two (sets of) patterns. This would give you a purely mechanical way of migrating a struts application to spring-mvc or vice versa.

Pattern Database

Now, the cost for me to describe, in great detail, all of the patterns for spring-mvc and struts in order to automatically migrate from one to the other is probably more than the effort to just get on and do it by hand. I could probably tackle a bunch with regexes and shell scripts, then hand finish the rest. However, what if we could define these patterns and share them? If there was some kind of open source pattern database? Then, the cost for the community is spread out – the cost for me is minimal.

Could we get to a point where our patterns are documented and codified? Where we can migrate between frameworks and even architectures with a manageable cost? An impossible dream? Or a better way of crafting software?