Scott Boring

The problem with story points

Although scrum dominates the management and process philosophy for software development; I don't believe it will last as it currently stands. Some aspects of scrum are good or even great, some aspects are terrible. Story sizing is one of those aspects that I believe is terrible and eventually will go away.

Over estimating

It's a natural and smart human characteristic to over estimate. This is especially true when a team is also asked to commit to the estimate.

A story that could likely be completed in 3 days will likely be estimated to take 5 days.

Expanding into the estimate

Once an estimate is made, it's natural and even beneficial to expand into the estimate. Why use less time than available? Using less time is indication that the estimate was wrong and who wants to be wrong.

A story that likely would take 3 days but estimated to take 5 days, will likely take all 5 days.

Story points aren't useful

Story points are a data point that can be used to measure productivity and make improvements. I have never seen this happen. Not at my current company, not at previous companies, and worst of all, I have never read or heard about case where this has happened.

Story points are too abstract to be a useful data point.

I'm a big fan of data driven decisions but I have never been successful at using story points to this end.

Too many layers of abstraction

Story points are a complexity estimate, not a time based estimate; but ultimately time based estimates are what's useful. Supposedly, overtime, story points can be used to estimate time but why? Why not just estimate time to begin with.

Estimate time needed, not story points.

Most teams struggle with a complexity estimate; time based estimates tend to be wildly inaccurate but I've never seen a complexity score result in better time based estimates.

An alternate approach

I believe that story points and in general sizing should go away. A Kanban backlog is a better approach that allows product owners to prioritize work and does not require developers to estimate.

Not all work needs a time based estimate.

Some work will need a time based estimate for downstream dependencies but some work won't need time based estimates. For cases where an estimate is needed, ask the team to estimate the time.

This approach is not perfect, but it eliminates story sizing which is takes significant time and encourages work to take longer than needed.

Inverse Monolith

With Micro services being all the rage, there is a trend to make smaller independent modules of code. But, smaller modules does not guarantee independence!

Monoliths

Monoliths form naturally for two good reasons.

  1. It's a simple way to start and arguably the best way to start a project
  2. It's easy to reuse code that exists in a common code base

Monoliths tend to have the following problems.

  1. Large code bases are difficult to maintain
  2. It's Difficult to ramp up a development team with one code base

Micro services

Micro services are largely an over hyped approach to modularization which can address the challenges with a Monolithic code base.

BUT, this effort to modularize can be thwarted by excessive use of shared libraries resulting in an inverse Monolith.

Inverse Monolith

With small modules of code, less code is reused. This in most cases is actually a good thing because it ensures modules are independent. Most development teams create shared libraries so that this code can be reused across micro services.

UNFORTUNATELY, this results in micro services being tightly coupled through a shared library. And now your back to a monolith in disguise or as I like to call, an inverse Monolith.

Optional

Java 8 includes the Optional class which can be used in place of null. Optional provides several features over null that make it worthwhile.

is present

The isPresent() replaces the check for null.

Optional <String> value = Optional.of("value");

if(value.isPresent()) {
    // do something with value
}
else {
    // no value present
}

The isPresent(consumer) conditionally executes a lambda if not null.

Optional<String> value = Optional.of("value");

value.isPresent(() -> {
// handle value
});

or else

The orElse(T other) allows you to provide a default value if null.

Optional<String> value = Optional.of("value");

String setting = value.orElse("default");

The orElse(supplier) allows you to get a default value if null.

Optional<String> value = Optional.of("value");

String setting = value.orElse(() -> {
    return "default"; // could get this from somewhere else
});

The orElseThrow(supplier) allows you to throw an exception if null.

Optional<String> value = Optional.of("value");

String setting = value.orElseThrow(() -> {
    return new IllegalArgument("value is missing");
});

Don't have Java 8?

The Optional class was created as part of the Guava library and can be used on older versions of Java. There are a couple differences between the two.