Posts

Velocity is not a Business Metric

Nowadays, every Agile™ organization is intently focused on increasing velocity. It's obvious: higher velocity means more productivity and efficiency, right? Because of this, managers and team leaders and product owners the world over are tracking team velocity. With it, they demand estimates, make projections, and kick off marketing campaigns. They are often led astray by velocity.

Because velocity is not a business metric.

Velocity is an imprecise metric in the best cases. We calculate it from an estimation metric over a defined period of time. Story points are the most commonly used metric. Story points are a team's best guess at how large a story will be relative to other stories. A story is assigned a number of points at some point before development starts on it. The points are credited to the team's velocity when the story is considered done. Ideally, velocity is fairly stable over time. Using velocity (say, 12 points/week), we can extrapolate an entire project (abou…

Respect Your Callers' Intentions

When we write code, we write it to be used. We call it from other places in our application. Others call it from places in their application. When we are writing code, we should show what we mean through our code, an idea known as intention-revealing interfaces. We reveal intentions through the external surface we expose. But what intentions are we exposing?

We write our code in a way that we think will be useful, but we are mostly writing implementation. We are writing what the code should do, and then from there how others would use it. The implementation drives the interface. The implementation does not always have the right intentions, though. Here's a simple class that stores historic temperature data for processing:

public class TemperatureHistory { private int[] temperatures; public TemperatureHistory(int[] temperatures) { this.temperatures = temperatures; } public int[] getTemperatures() { return temperatures; } }
This is a simple dat…

I'm Almost Always Wrong (The First Time)

When I write a chunk of code, it is wrong. I know it is wrong, even as I am writing it. But there's nothing I can do about it. I don't, and can't know how it is wrong when I am writing it. I can only know that I am writing wrong code. I am not phased in the least.

As professionals, we are expected to write code with a certain quality of maintainability so that our code can be easily changed in the future. This is expected because of how often code does need to change, often in unexpected ways. We cannot predict all the ways the code needs to change. The future is inherently unpredictable. We must write our code in a way that makes changes as straightforward as possible.

I don't worry about writing wrong code. I write it in a way that I can make right later. I design seams in places that seem most likely to change. I know them by the uncertainty that lives in them. I abstract and encapsulate that uncertainty behind methods and classes and interfaces so that later, when …

When Technical Debt Costs You MORE!

We've all heard of the metaphor of technical debt by now. Maintaining poorly written software costs more in the long term, even if it saves in the short term. Thinking of this as a form of debt helps explain this in terms business-oriented stakeholders can understand.

Metaphors are valuable because they can meaningfully convey a concept through a different context. They bridge the gap between two different ways of thinking. Sometimes we can take the metaphors a little too far, and they become disconnected from what they are actually trying to represent. This has happened with the metaphor of technical debt. Other times, we can explore the metaphor to find deeper relationships between the real concepts and the metaphorical ones.

Financial debt has the concept of interest in it. Interest is an extra charge on top of the original value lent. It covers risk and provides incentive to the lender. It is calculated as a percentage on top of the principle amount of the loan. So a loan of $…

Untangling Nested Code

Image
There is code out there that is ugly. I mean really ugly. I know, can you believe it? But it's true. One such example of really ugly code is code that has lots of deeply nested calls. The tests are trying to test a dozen different methods in every case. The methods look so simple with just a few lines and a few calls. And then those methods called have a few lines and a few calls. And then again, a dozen or more different calls deep.

We want to use private helper methods to make our code clearer and cleaner. Calling methods is also largely what programming is about. But sometimes we overdo it. Deep call hierarchies are difficult to follow and they can mask what the code is really doing. Each call means that we have to look all over a class to see what actually happens. This makes debugging hard. This makes testing even harder.

Say we have the following code:

class DataLoader { void loadNationalData(Nation nation, int year, DataReader reader) { for (State state : natio…

Break Down Code to Make It DRYer

Image
We are always looking to make our code DRYer. Code that is not repeated is easier to maintain. We can make a change in just one place rather than hunting for different incarnations in many different places. Making code DRYer is not always easy, and sometimes how to remove the duplication is not apparent.

Let's say we have the following two functions:

public List<Stats> processLines(File file) { List<Stats> stats = new ArrayList<>(); for (String line : lines(file)) { Data data = extractDataFrom(line); Stats dataStats = calculateStatsFor(data); stats.add(dataStats); } return stats; } public List<Stats> processLines(List<File> files) { List<Stats> stats = new ArrayList<>(); int fileNumber = 0; for (File file : files) { for (String line : lines(file)) { Data data = extractDataFrom(line, fileNumber); Stats dataStats = calculateStatsFor(data); st…

Every Case Is Special

Special cases are everywhere. This one little thing has to work this other way. Soon, there is an if/else chain twenty conditions long. Worse, that if/else chain is embedded in another chain of twelve conditions, all in one happy method. The next person making a kind of change has to tack on another condition and hope nothing blows up.

We know it's bad when we see a bird's nest like that. How can we deal with it? Why should we? The problem with code no one understands is that no one understands it. We will have a huge problem the day it stops working. We assume that, if it works now, it will work forever. That is a faulty assumption. The world changes around us. The solid rock beneath that code can erode away. And our hair will be on fire when that day comes.

Special cases are special. Normal cases are also special. Every case is special in some way. There are some classic special cases common to many code bases. There are quirky special cases unique to your own code. We need …