Not good enough

“I’m not good enough” says the graduate to herself, shuffling her feet.  “All those uni assignments made no difference; everyone knows more than me.  Why would anyone want to listen to what I have to say?”  Surrounded by self-assured, battle-hardened colleagues, there seems an insurmountable distance to cover—but one day, she’ll surely know enough.


“I’m not good enough” said the programmer with a grimace, starting a new job at a famous company. “Seven years of work and it’s like nothing! Everyone here knows so much; how long will it take for me to know enough?”

So when is enough? Is there a line we cross when we become experts? Does ticker-tape fall from the ceiling, and the mayor of Hackertown give us a medal?

“I’m not good enough” said the veteran of fifteen years. “The people writing these libraries, blogs and conference talks are so smart—am I ever going to know enough to have such an impact?”

Every point on this slope is fractally self-similar to every other, differing only in scale. We know only so much; the unfathomable expanse of the unknown is spread before us.  It was like this when you knew a tenth as much, and it will look the same when you know ten or hundred times more again.  From the horizon, we all look like ants.

Look at your heroes; the best in the world at what you do. In fact, what they see is roughly what you see: a body of accumulated knowledge, and the brutally vast frontier of their own ignorance ahead.

So when do we draw the line and call ourselves “expert”? Never! This is for fools who have already stopped pedalling. It takes humility to accept that a life’s work can barely hope to recover a drop from this ocean of ignorance, and a noble madness to cheerfully hurl oneself into the waves.  If there is a line to draw, it is between these folk and those who turn their backs, turtling in with trinkets and baubles already won.

This light harshly exposes those who can’t empathise with junior colleagues. So, they asked a stupid question. Why did you stop asking stupid questions? Nobody still open to improving themselves would fail to recognise one of their own.

So learn! Abandon yourself to permanent inadequacy. Your life may host any number of hardships, but you’ll never know boredom again. You’ll forget what it was like to endure barren, aimless hours. The waiting-room becomes a study, the bus-stop an opportunity, the laundry a goldmine.

No, you’re not good enough, because there’s no such thing and never was. But you can still head that way.

The worst thing in our Scala code: Futures

Author’s note: this isn’t an argument against Futures, there’s nothing wrong with them as such!  This article is about good abstraction and proper separation of concerns when using them.

The aims of functional programming are much the same as any other discipline of software engineering: modularity, abstraction, low coupling, high cohesion, and so on. While the techniques and terminology are often new to developers, the goals and benefits are expressible in very familiar language because it’s all software, and we’re trying to achieve the same thing! (Read SICP for more background on software engineering fundamentals expressed with functional ideas).

Continue reading

How we used Category Theory to solve a problem in Java

A few months ago, my colleague Chris Myers and I used some basic category theory concepts to guide us to a design that elegantly solved a problem in a Java codebase.

It isn’t the only way we could have arrived at the design; anyone could have done it, really! However, you might find it interesting to see what practical application of these ideas can look like. Importantly, category theory gives us a framework to shed light on what makes many good design concepts useful, and why. Continue reading

Getting Shit Done

This post was originally published internally, as an appeal to REA colleagues.

“Getting Shit Done” is the catchphrase on everybody’s lips, and deservedly so!  When we deliver new functionality, our users regroup and flock to us, our customers grudgingly respect us, and our shareholders rejoice.  When the novel concepts invented by our product managers take shape as they watch, their eyes light up with pride and enthusiasm.  Programmers are never happier than when fire and magic fly from their fingertips; products that change people’s lives materialise from thin air, and insurmountable problems melt like butter.  Beer flows freely, parmas are devoured and our managers circulate glowing praise within the company.

We have all felt the opposite too; long months gone by without new features, frustrated and bored developers; product managers forced to nervously adjust their collars and disappoint their superiors, with often dense technical reasons they can barely hope to convey.  New features pop up like mushrooms on our competitors’ sites, and we wonder: why didn’t we do this years ago?

Yet when I hear this phrase “Get Shit Done”, I grimace; my teeth clench and my back involuntarily stiffens.  Why?  There is truly nothing I want more, and it is clearly important; many of our most talented teammates live by it.

Continue reading

To Kill a Mockingtest

Please don’t use mocks or stubs in tests.  While they are seemingly ubiquitous in enterprise development, they have serious drawbacks, and typically mask easily fixable deficiencies in the underlying code.

Even their most ardent defenders concede that mocks and stubs have flaws. These include:

Dependence on fragile implementation details

Mocks and stubs require intimate knowledge of how code interacts with other modules.  Even if the implementation is correctly refactored without altering public contracts, these tests will tend to break, and draw your attention away from more productive tasks.

Testing incidental properties with no bearing on correctness

What is the point of this code?  This is an essential question to ask, in order to understand it.  Tests have a story to tell here, and mocks invariably tell the wrong one.  Is the point of makeCoffee() that we made a coffee, or that we opened the fridge to get the milk?  When we payShopkeeper(), do we care that we completed a transaction, or that we rummaged though our wallet for change?  When mocking tests fail, the poor maintainer is left to reconstruct the real intent from a trail of indirect clues and anecdotes.

Web of lies

It is good practice to write data structures that are correct-by-construction; any constructor or sequence of method calls is guaranteed to leave the data in a meaningful state.  Stubs introduce test-only fictions that are stripped of any of the safety latches and guarantees that may have been built in; they introduce fresh sources of error that are not present in the codebase.  There is no value in detecting any failure that arises in such a way.

As time goes on, lies beget more lies.  It is not unusual for a stubbed input in one place to result in another here, and another there; the fiction leaks and spreads into some kind of evil facsimile of the original code, but with more bulk, complexity and defects.

Continue reading

The abject failure of weak typing

More discussion on Hacker News, and the Clojure, Haskell, Rust and Programming subs on Reddit.

Over the last few years of maintaining code old and new at REA, it has become abundantly clear that the neglect and misuse of type-systems has had a sharply negative impact on our codebases. Here we address the concrete causes and consequences, and propose concrete and achievable solutions.

Types at REA

REA’s codebases vary between statically typed languages such as Java and Scala on one hand, and “dynamic” languages such as Ruby, Javascript, and Perl on the other. I’ll mostly leave the dynamic ones alone — while the same arguments obviously apply, they are what they are. However, if we are paying for the conceptual overhead of a static type system, we need to be sure we are using it effectively; otherwise we are simply writing the same old Ruby play-dough but with long build-times and cumbersome syntax. Used properly, the tradeoff of static types is overwhelmingly beneficial. Continue reading