Magic Numbers, Semantics, and Compiler Errors

Magic numbers are considered such a scourge upon code bases that there tools out there to automatically find them and root them out. After all, who knows what setValue(6); really means? There are also many approaches to giving better names to magic numbers. Not all of them are good, though. For example, we have a callback that sets a completion percentage on a status:

void callback(Status status) { status.updateProgress(0, "Starting"); // Do some stuff... status.updateProgress(25, "Some stuff done"); // Do some more stuff status.updateProgress(50, "More stuff done"); // Reticulating splines status.updateProgress(75, "Splines reticulated"); // Validate everything status.updateProgress(100, "Complete"); }
Those percentages would get flagged as magic numbers by the automatic tools. The developer would need to extract those out to constants to make that tool happy. A thoughtful developer would create well…

Typing != Complexity

Developers of all experience levels commonly share a false belief: more typing means more complexity. The most powerful idioms and tools often require a few extra keystrokes, but dramatically reduce complexity.

The final keyword in Java is a bit of extra typing. The final keyword can be applied to variables, method parameters, instance members, static members, methods, and classes. By making these final, their values will not depend on their context. They will be known constants through their lifetime. Their constancy removes a large cognitive load. The developer no longer needs to worry if the value was not set or if it was set multiple times. Many developers forgo this benefits to avoid typing the extra keyword, to their own detriment. Later, they spend too much time chasing down defects caused by mutable state.

Developers will often shun creating small types and interfaces because of the extra typing involved. Interfaces can abstract away many different implementations behind a sim…

The Cohort of Responsibility

Sometimes the team just isn't enough.

Delivering business value from idea to production is a complex endeavor. Development teams sit squarely in the middle of that process. Ideally, they are talking directly to the customer. Often in real life, business analysts collect requirements from customers and pass them to the development team. On the other side, development interacts with operations to deploy and run the software.

All of these groups, and more, have the responsibility to deliver the business value. But too often, there is friction between these groups on the path. Not everyone wants to move in the same direction. Some individuals or groups can slow down or altogether stop value from being delivered. They are responsible, but not always accountable.

Everyone who bears direct responsibility toward delivering business value is part of the Cohort of Responsibility in the organization. To most easily identify everyone in the cohort, we can pick out everyone who must touch a re…

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 $…