Warning: academic theorizing and hypothesizing follow. Oh, and half-baked pontification.
I just finished refactoring reek to drive in a major new chunk of functionality (configuration files) which I’ll release soon, when I’ve had time for some thorough testing.
The refactoring needed to accommodate the change was huge, occupying much of my free time over the course of two months. Pretty much the whole of the tool’s original architecture has been revised. Why so big and so complex? Because the original code relied heavily on constants and class methods; they helped me get the early versions written quickly, but they represented a significant barrier to long-term flexibility. I’ve been wondering why that should be; why do constants and class methods stand in the way of adaptable test-driven code?
I think the answer lies in viewing the application through the lens of Hexagonal Architecture. Let me explain…
It seems to me that constants, global variables, classes, class methods, etc all live in a space that’s “anchored” to the runtime environment, which is itself a singleton. Anything anchored to that singleton is going to hinder the independence and isolatedness of unit tests, and also reduce the application’s flexibility in well-known ways. So far so standard. Now, suppose we model the singleton as a notional point that is external to the application. Hexagonal Architecture tells us we must access the singleton via an Adapter — in this case, an Adapter provided by the programming language and/or runtime. I’ll refer to the singleton as the application’s Anchor, and therefore claim that it is accessed through language features in an Anchor Adapter.
Now, I believe that the Domain Middle should not depend directly on Adapters. So any code that makes direct use of the Anchor Adapter must therefore be considered outside of the Domain Middle, and hence part of an Adapter — and hence also inherently outside the space where unit tests live comfortably.
Which is why constants and class methods add friction to unit testing.
Or rather: This model fits nicely with my penchant for Hexagonal Architecture, and lets me justify my unease at testing in and around class methods. And probably adds nothing to our understanding of software development.

Ashley Moran
July 19, 2009
I’ve gone through the “how would you write this if Ruby didn’t have inheritance?” thought process, and concluded that the answer is always, “better”. Now I don’t use (class) inheritance any more.
So, as an idle question… how would you write code if Ruby didn’t have class methods?
Kevin Rutherford
July 19, 2009
Well,
newwould have to be redesigned, but that aside I don’t foresee any problems. Do you have a specific case in mind where class methods can’t be avoiced?Ashley Moran
July 19, 2009
No, I can’t think of any off the top of my head. How about this as an experiment: from now on (well, on some project it might work on) I will create only one constant of my own, to a class with exactly one class method, which will provide an object from which everything else can be generated.
Is that feasible, or is that just plain crazy?
Kevin Rutherford
July 19, 2009
I tend to think of the gloabl space as somewhere for the runtime to put things so I can get at them from anywhere; it’s certainly not somewhere I want to put any of my own code if I can possibly help it.
Ashley Moran
December 20, 2009
Do you think that constants that reference value types (and class-method constructors for them) also add friction?
Kevin Rutherford
December 21, 2009
Not the constants themselves, perhaps. But anything that uses them will be more difficult to test.