Huh, I always thought this was a quirk of old Java, that it created a seam for mocking or something. Sort of like how the C/C++ practice of only having a single return statement in a function existed to prevent various bugs around forgetting to free memory. That eventually floated free of the original purpose and was a general-purpose maxim I saw applied to memory-managed languages. This article feels like it still knows a bit about why the practice existed (“Surely there’s a better way to do the required testing”) and is looking for a new justification.
IIRC, older Java mocking libraries could only mock an interface. Nowadays, I think they generate a class at runtime if need be.
Great article! I love seeing actual software design articles instead of ads for frameworks/libraries.
I always fall back to using an interface for discrete effects (such as external services, hardware devices, etc) just so I can develop in a more natural way, whether that’s TDD or simply stepping through the code. Usually, this results in a single implementation for the interface, but that’s not a bad thing. The interface makes the protocol between the app and the externality obvious. I can answer allegations of overdesign by writing the interface in such a way that it protects the core domain from stupid details of externalities. Needing to think about a protocol that both the device and the domain agree on helps me arrive at a good interface much, much faster than simply extracting it out later.