Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

That’s inaccurate and unfair. Testability is useful precisely because it’s an effective, tangible proxy for other properties of software that are harder to anticipate or recognise: things like modularity, composability, reusability and so on.

The whole point of DHH is that the correlation between testability and other desirable qualities is not always positive, you have to make tradeoffs. Taking testability to the extreme you can end up with a ton of anemic classes with hardly any correspondence between the class breakdown, method signatures and so forth and the actual domain, which for me personally is the number one goal right after satisfying customer requirements.



I agree, but you’re projecting; DHH hasn’t said anything that nuanced.

He doesn’t explicitly touch on “other desirable qualities” of designs (other than the meretricious goal of “clarity”), nor how they relate to testability. He just makes fun of testability without exploring what it means, how it can imply those qualities, and how to decide which tradeoffs to make.

That’s a shame, considering how many people pay attention to what he says. He has the opportunity to promote a more thoughtful and consistent approach to building software, but doesn’t seem interested in exploiting it.


Might be it's not in the blog post, but he gave a keynote at RailsConf about this and that's pretty much what he said:

http://www.justin.tv/confreaks/b/522089408 http://www.justin.tv/confreaks/b/522101045


We just disagree, then.

To pick a tiny, arbitrary example from the keynote, he criticises this method[0]…

  def age(now = Date.today)
    now.year - birthday.year
  end
…as opposed to his preferred version…

  def age
    Date.today.year - birthday.year
  end
“Is [the method with the parameter] better? Is it simpler? Is it clearer?” He makes fun of it as though the second version is obviously simpler and clearer, presumably because it uses fewer characters/parameters/concepts, but in reality it’s not obvious. It depends what you want!

The first version makes it “clearer” that the method’s result is date-dependent, which makes it “simpler” to understand how it will behave as part of a larger system (e.g. is it cacheable?); this is a win for composability. If you want to call it from inside another method, you’ll need to get a date from somewhere — maybe you’ll already have the appropriate date to hand, or maybe you’ll choose to pass that responsibility onto your caller in turn, or maybe you’ll decide that this is the right place to reach for Date.today. Either way, you get a chance to think about it, and to be aware of how another part of the software is going to behave without needing to go and look at its source code. (This argument is essentially “referential transparency is good”.)

Now, it’s entirely plausible that you don’t care about that benefit, and you’d rather have a shorter method that works in the easiest possible way without regard for referential transparency, because your system is small, or this method is hardly called anywhere, or everything else in the application is time-dependent anyway so you don’t need to be reminded of it. That’s fine too! But DHH doesn’t go into any detail on the tradeoff; he just makes fun of the version that takes an argument, because it’s testable for the sake of it, and why would anyone bother with that?

He doesn’t seem interested in exploring the situation, or in interrogating what testability implies in this case, only in laying out his prejudices as if they’re indisputable common sense. They’re not.

[0] Since this is just example code, it’d be churlish to point out that it’s not the right way to calculate someone’s age in the first place.


First method works just fine if I want to calculate what was his age last year, and what will be his age at the year of 2021. The second method doesn't, so these are not even functionally equivalent.


> The whole point of DHH is that the correlation between testability and other desirable qualities is not always positive

But the correlation between testability (in the sense relevant to TDD) and an architecture of loosely-coupled, reusable modules with well-specified behavior is always positive. Or, at least, the latter necessarily implies the former.

> Taking testability to the extreme you can end up with a ton of anemic classes with hardly any correspondence between the class breakdown, method signatures and so forth and the actual domain

I don't think that's really taking "testability" to the extreme. That's just failing domain modelling while still designing for testability, equivalent to "normalizing" a RDBMS schema by decomposing everything into either one-attribute ID relations or two-attribute ID+value relations -- a kind of cargo-cult approach by someone who has learned something that is appropriate in the most extreme corner cases in a domain model and then applies it to everything without thought. It's not an extreme of testability, that's just understanding one corner case relating to testability without understand its context within testability or domain modelling.

Now, I've certainly heard from proponents of TDD that take that approach, but they aren't really representative of TDD as a whole. In any technique that is widespread enough to even have a name, you'll find cargo cult practitioners who do it badly based on a shallow knowledge of one or two elements without an understanding of its purpose -- but it doesn't make a lot of sense to criticize any technique based on how some cargo cultists approach it.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: