Speed


One of the patterns I keep seeing over and over is that a lot of people are in a rush.

It seems that we’ve developed a culture of rushing through stuff. We learn new programming languages in a hurry, we skip through documentation and we rush to write code.

Whatever happened to understanding the problem, reading the documentation, thinking about what you’re going to do? Is that lame?

I think I’m turning into a grumpy old man.

The habit I encounter most is searching for functions in a file, or for a class in a codebase.

This feels wrong. Files should not be so big that they need search. The code should be well structured so that classes live in reasonable and memorable places.

I can understand a new team member using search, but as you get to know the codebase you should rely on search less and less.

Code Silos

Whenever you divide your developers into multiple teams, you will inevitably get code silos.

If multiple teams write code for the same product, you need to be scared. Seriously.

The Core Silo

The core silo is the most dangerous of all silos. This is the place where the code does not live on a hard-drive; it is carved in stone.

Each product has it’s own core and somebody will always come up with the (good) idea of moving some commonly needed bits of code into a shared library or module.

You need to tread carefully in this realm.

The moment you make a single person (or team) responsible for the core, you have a pretty high chance of freezing that code. It might never get improved or refactored again.

The politics might get so bad and the bureaucracy so soul crushing, that even thinking of changing something in there will send grown men running in despair and fear.

The core maintainers should be chosen carefully. They should be selfless and devoid of any political agendas—this is impossible in practice, but try to get as close as you can.

These people should feel that their job is to make the rest of the company’s work easier. They should be proud of this and should welcome any contributions; they should not be gatekeepers.

If you’re really unlucky, you’ll get a super-core. This will be a cross-product, company spanning silo. Watch out for words like infrastructure and pseudo-geeks trying to position themselves to be in the center of your development process.

The normal silos

You need to accept the rest of the silos as a fact of life and try to encourage collaboration by stripping away as much bureaucracy as possible. Have only a minimal set of rules for cross-silo interaction.

You might also choose to have all the code shared: multiple teams, single codebase. Teams don’t own any code, the developers do. No team is responsible for any chunk of code, everybody is responsible for all the code.

The latter approach may seem drastic, but I think that the problem with silos is their tendency to create political territories that inhibit collaboration.

I want to minimize the formation of silos as much as possible, even if I’m leaning a bit towards what some may call anarchy.

I’ll leave this post short, unfinished and ranty. So that’s it for now.

Minimal Change Development

Tunnel

There is a style of development out there that encourages making mostly minimal changes. Do the least amount of stuff to get your feature running.

I’ve heard this advice many times over the years.

This seems to be mostly used as a tactic when people are scared. Scared of changing the code.

It’s normal to be nervous when you work with crappy code, but keeping changes to a minimum will also keep the code crappy.

It’s a vicious cycle: you keep making small changes, the code doesn’t get properly refactored, it stays crappy, you stay scared, you keep making minimal changes.

The only time for minimal changes should be when backporting bug fixes, when you issue some emergency fix or when you write a dirty hack.

While I don’t think that minimal changes are intrinsically wrong, most people get the wrong idea and try to work like that all the time.

People think that the only way to add new features without introducing lots of bugs, is by making the smallest changes you can. This might be true, but at the same time you’re increasing entropy, and in the long run it will hurt you.

Think about it, you focus on a small bit of the system. It’s like you have tunnel vision, so you will implement a local solution instead of a global one.

You can think about it like when your searching for a function’s global minimum; you can get stuck in a local minimum far away from the real one.

If you do implement a feature with minimal changes in mind, you need to follow up with refactoring. Not code refactoring, but architecture refactoring.

Like with everything else, there is a time and a place for making minimal changes, but it has to be used with moderation.

Architecture Refactoring


Code refactoring is better than nothing at all, but I don’t think it helps too much.

After an opening line like that, I’d better explain what I mean.

In the context of refactoring, software teams can be split into two categories: teams that refactor code and teams that refactor architecture.

The difference might not be so clean in practice and you might have teams that are a blend of these two categories. But for the sake of being dramatic, lets just pretend that the split is clear.

Code refactoring teams

If your team is refactoring code all the time and things seem to stay the same, you may be in a team that practices code refactoring.

Imagine that you have a big system with lots of legacy code. You all know that it sucks and you all want to make it better.

You start improving small, isolated pieces of that system. You make small changes – a class here, an interface there, remove a method, clean up some function. You get the idea, you are changing the code, not the architecture.

This may feel good, but I don’t think it helps all that much. You’re missing the big picture.

A system most likely sucks because it’s missing good abstractions and easy to understand concepts. To create good abstractions you need to make sweeping changes across your codebase.

Architecture refactoring teams

With this kind of refactoring, instead of making localized changes, you add some abstractions and make all the code work with the new stuff while at the same time you remove the code that’s now made obsolete.

You refactor a bit of the system’s architecture. The goal is to improve the system not the code.

With this style of refactoring, making code changes is just a means to an end.

Let me give you an example.

Say you have some web service that receives requests and has to do a bit of processing. The current code goes straight into the processing and returns the result in the response body.

Code refactoring would keep this architecture but make the code pretty, more efficient or whatever is currently bothering you over there.

With architecture refactoring you would need to take a step back. Maybe you would replace the whole thing with a nice message queue and some worker processes that you can scale horizontally across machines.

Conclusions

I think that while the kind of code refactoring I’m talking about helps locally, it can’t really keep up with the global increase in the code’s entropy.

The architecture refactoring style takes courage. It may not be for everyone. It’s riskier than making local changes but it also brings the biggest rewards if done properly.

Also, you can easily cover your ass when you make small changes that don’t touch the system’s design. But we’re not here to cover our asses, we’re here to create great systems that work well.

Code Entropy

Code entropy

I believe that a codebase has entropy. I am alone in my beliefs.

A codebase with high entropy will most likely manifest code rot and brittleness.

Other people like to think in terms of technical debt.

For me, the concept of technical debt is a nice way of explaining to management that while we increase the entropy for the sake of a timely release, we will have to take steps towards decreasing it in the future.

Entropy (and technical debt) is decreased by refactoring.

Don’t confuse entropy with complexity, they are different. Entropy is just the amount of chaos in your codebase. You can have nice, clean and complex code with low entropy.

For example: Increasing entropy to fit in a last minute feature that some important client wants, will take some amount of effort. The effort to decrease the entropy, back to previous levels, will be dependent on the total amount of entropy in the system, the people that take part in the refactoring and the amount of time since the entropy was increased.

Let me explain.

Total entropy

Every codebase contains some entropy.

The higher the entropy the weirder, and harder to refactor your code gets.

I think you can actually measure the total entropy in a codebase. Do it like this:

  1. Listen to your developers while they code.
  2. Count the number of swear words they use.
  3. Weigh the counts according to the developer’s age in the company†.
  4. Sum all the counts and divide by time.

I like to think of this measure as WTFs / hour.

Yeah, this is not an objective measurement and you can’t put it in your PowerPoint or talk to your manager about it. But it’s fun!

† Older developers are more important because they are used to the code. If they are surprised by something, you can bet that it’s really ugly.

People dependency

Some people are better at adding entropy than they are at removing it.

Did you ever write some sloppy code while thinking that you’ll refactor it later? Did you ever forget to refactor it and some co worker comes in and refractors it for you? Is that code now worse instead of better? That’s the guy I’m talking about.

Some developers don’t take the time to understand the code that they are working with. They don’t think about the bigger picture and what the code is trying to do. All they care about is getting it to do what they want.

Private method that looks like what I need? No problem! I’ll make it public without understanding the rest of the class or how it’s used.

Time dependency

This one is pretty straightforward.

The longer you wait to fix some bit of code, the longer it will take you to relearn what it does, what are the dependencies, and how to fix it.

The solution

Keep your code entropy as low as possible from the start. This way you will have more stable releases, fewer bugs and you can add new features faster and cheaper.

Did you ever look at some software and learn that it has an unexpectedly large number of people maintaining it? Yup, entropy is to blame.

There is no silver bullet. Just use common sense and refactor regularly.

Oh and test your code too. Refactoring is scary without tests.