The Economics of Programming: Externalized vs. Internalized Costs

external_costs
Diagram: Econation NZ

Many days I feel like my work as an agile consultant is simply internalizing (externalized) costs.

First example that comes to mind: software development done too quickly which creates technical debt as it goes. In the short term, a project like that can seem very successful, exceeding expectations for delivery time and customer satisfaction. And then the devs rotate on to another green field.

I once argued to a manager that a certain project was producing “negative value”, but I didn’t get far with that argument 😉

Contrast this to programming under a method like Test Driven Development, where, many times per day, a small coding effort is followed up by a small “refactoring” (cleanup) effort.

Python vs. Haskell round 2: Making Me a Better Programmer

Another point for Haskell

In Round 1 I described the task: find the number of “Titles” in an HTML file. I started with the Python implementation, and wrote this test:

def test_finds_the_correct_number_of_titles():
    assert title_count() == 59

Very simple: I had already downloaded the  web page  and so this function had to do just two things: (1) read in the file, and then (2) parse the html & count the Title sections.

Not so simple in Haskell

Anyone who’s done Haskell might be able to guess at the problem I was about to have: The very same test, written in Haskell, wouldn’t compile!

it "finds the correct number of titles" $
    titleCount `shouldBe` 59

There was no simple way to write that function to do both, read the file and parse it, finally returning a simple integer. I realized that the blocker was Haskell’s famous separation between pure and impure code. Using I/O (reading a file) is an impure task, and so anything combined with it becomes impure. My function’s return value would be locked in an I/O wrapper of sorts.

I got frustrated and thought about dumping Haskell. “Just another example of how it’s too difficult for practical work,” I thought. But then I wondered how hard it would be to read in the file as a fixture in the test, and then call the function? I’d just need to pass the html as a parameter. And yep, this worked:

it "finds the correct number of titles" $ do
    html <- readFile "nrs.html"
    titleCount html `shouldBe` 59

As I refactored the code to pass this test, I realized that this is much better: Doing I/O and algorithmic work should always be separate. I had been a little sloppy or lazy in setting up my first task. The app with the Haskell-inspired change will be more reliable and easier to test, regardless which language it ends up being written in.

See also:

Engineering with Empathy: how do we decide when to fix?

populations

It’s a sappy title, but bear with me. I’m wondering if the best lessons of diversity and inclusion can be applied to software development? For example, if something is offensive to others, then it’s worth looking for an alternative — even if I’m not personally offended.

I witnessed an interesting disagreement on a software project: Some developers joined a project with a large codebase which had been up and running for a while. They stumbled upon an aspect that made it harder for them to understand. These new-to-the-project devs proposed a small change:

Why is this named Dwankie? It keeps tripping us up. Can we rename it to ApplicationConfig? It’d be a lot clearer.

The group’s current decision-making process: Is no clear majority dissatisfied? Then keep the status quo.

The long-time devs disagreed with the change. They acknowledged that it would do no harm. But in their view, the code was understandable enough as is. Interestingly, every dev who was unbothered by the odd naming advocated keeping it. They also argued that this wasn’t an important issue. I saw this argument boiling down to, “we don’t think it’s a problem”. This struck me as analogous to “I don’t find it offensive” in the context of inclusion. And so I’m thinking it’d be similarly invalid. The change was disallowed.

A better way to decide: Is a significant group dissatisfied? Then we allow change.

Thinking about it, “But is a different group of people ok with things as they are?” is not a good guideline. Instead, we should use a rule of thumb based on empathy when deciding whether to act: A sizeable group of people who are dissatisfied with the status quo is enough reason to support change. We shouldn’t require a unanimous or even a majority vote. rabbit

Meteor Won’t Kill Rails Anytime Soon

This is in response to Why Meteor will kill Ruby on Rails. A pretty big claim, for sure. Now, Meteor is worth checking out, but Josh didn’t name any of the reasons why I and a whole lot of others choose Rails. So here we go.

It was its built-in support for these got me interested:

…and then its convention-over-configuration kept me hooked.

It’s like Rails has taken the best practices we’ve learned about building good software, and made them the default. And Django is on the same path. Josh credits Rails’ popularity on convention-over-configuration. That’s definitely helped. Meteor looks very interesting, but until it supports more of the above, we’re talking apples and oranges.