by Leon Rosenshein

When You Have A Hammer

You haven’t mastered a tool until you understand when it should not be used.

Kelsey Hightower

I’ve talked about patterns and best practices before. They’re great. They give you a starting point. But they’re no substitute for thinking about your situation.

Consider the hammer, screwdriver, and pliers. In theory, there’s very little you can’t do with that set of tools. You use the hammer to put screws in. You use the pliers to take screws out. And you use the screwdriver to open paint cans, pry valve covers off, and, with the hammer, chisel out notches in wood. That’s mastery of your tools, right?

Not exactly. Sure it works, but screwdrivers are much better at putting in and taking out screws. using screwdrivers as prybars or chisels can work, but you end up with

screwdriver

And the less said about using pliers for every nut, bolt, and pipe you need to turn, the better.

The same can be said of software. Consider DRY. Don’t repeat yourself. Short functions. Generally good ideas. But even that can be taken to extremes. Consider this silliness

package main
import (
    "fmt"
)

func increment(x int) int {
    return x + 1
}

func is_less_than(x int, threshold int) bool {
    return x < threshold
}

func print_i_and_j(i int, j int) {
    fmt.Printf("I: %d, J: %d\n", i, j)
}

func main() {
    for i := 0; is_less_than(i, 10); i = increment(i) {
        for j := 0; is_less_than(j, 15); j = increment(j) {
            print_i_and_j(i, j)
        }
    }
}

It works, but it’s actually less clear. Sure, we can guess what those functions do, we can’t be sure. Especially if they’re in another package/library.

Or, a different example would be microservices. Sure, at planet scale lots of things need to scale at different rates/shapes, so when you get to that scale you need it. But using a microservice architecture for a simple static website doesn’t make a lot of sense.

So when you reach into your toolbox, make sure you grab the right tool, not the one on top :)