Sandi Metz

sandimetz.com · Personal blog · on HN since 2014

Sandi Metz, author on object-oriented design, writes about abstraction, code evolution and Ruby, and is known for her books on code design.

What HN saysHN commenters repeatedly cite "The Wrong Abstraction" as a classic and recommend her books on code design.
95HN people shared it
67linked it in comments
32stories submitted
2.5Kstory points
3 months agolast shared
2014people per year2026

Most-shared posts

  1. 1
    The Wrong Abstraction (2016)
    62 people · 1.7K points · first shared 2016 · 240 comments on HN
  2. 2
    99 Bottles of OOP now available in Python
    13 people · 422 points · first shared 2016 · 86 comments on HN
  3. 3
    The Half-Life of Code (2017)
    4 people · 66 points · first shared 2017 · 5 comments on HN
  4. 4
    What Does OO Afford? (2018)
    4 people · 9 points · first shared 2018 · discussion on HN
  5. 5
    Breaking Up the Behemoth – How Applications Evolve
    3 people · 2 points · first shared 2017 · discussion on HN
  6. 6
    Why we argue style
    2 people · 4 points · first shared 2017 · discussion on HN
  7. 7
    Prefer duplication over the wrong abstraction
    1 people · 204 points · first shared 2016 · 96 comments on HN
  8. 8
    How Shall We Define Design?
    1 people · 9 points · first shared 2020 · discussion on HN
  9. 9
    The Wrong Abstraction
    1 people · 3 points · first shared 2017 · discussion on HN
  10. 10
    Ruby – Suspicions of nil
    1 people · 3 points · first shared 2015 · discussion on HN
  11. 11
    Getting It Right by Betting on Wrong
    1 people · 2 points · first shared 2014 · discussion on HN
  12. 12
    Postcard
    1 people · first shared 2016
  13. 13
    99bottles sample ruby
    1 people · first shared 2024
  14. 14
    Products
    1 people · first shared 2016
  15. 15
    Homepage
    1 people · first shared 2025

What HN people wrote when they linked it

dhorthy · 2025-09-23
I would say its much more about abstraction and the leverage abstractions give you. You'll also note that while I talk about "spec driven development", most of the tactical stuff we've proven out is downstream of having a good spec. But in the end a good spec is probably "the right abstraction" and most of these techniques fall out as implementation details. But to paraphrase sandy metz - better to stay in the details than to accidentally build against the wrong abstraction (https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction) I don't think delegation is right - when me and vaibhav shipped a week's worth of work in a day, we were DEEPLY engaged with the work, we didn't step away from the desk, we were constantly resteering and probably sent 50+ user messages that day, in addition to some point-edits to markdown files along the way.
drivers99 · 2025-08-31
The related blog post (I just found thanks to watching that and then searching for her site) is great too: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction It explains so much of what has been bothering me about what I work on at work, and now I understand why and some of what to do about it.
andrei_says_ · 2025-06-07
Sandi Metz’ books on code design are I think exactly what you need. https://sandimetz.com/
daxfohl · 2025-05-17
Yeah, I immediately thought of "The Wrong Abstraction" by the same author. Putting the branch inside the for loop is an abstraction, saying "the for loop is the rule, and the branch is the behavior". But very often, some new requirement will break that abstraction, so you have to work around it, and the resulting code has an abstraction that only applies in some cases and doesn't in others, or you force a bunch of extra parameters into the abstraction so that it applies everywhere but is hard to follow. Whereas if you hadn't made the abstraction in the first place, the resulting code can be easier to modify and understand. https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
pydry · 2024-05-30
I don't know about anyone else, but I've been deeply unimpressed with the output of the google testing blog. This example is not wrong, but it's not particularly insightful either. Sandi Metz said it better here, 8 years ago https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction The testing pyramid nonsense is probably the worst one though. Instead of trying to find a sensible way to match the test type to the code, they pulled some "one size fits all" shit while advertising that they aren't that bothered about fixing their flaky tests.
salomon812 · 2023-04-14
This feels like another wording of the motto from a great blog post by Sandi Metz: "Prefer duplication over the wrong abstraction" https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction I find myself reaching for this all the time after my first instinct is DRY. Makes me thing hard about if I should couple things or not.
e_i_pi_2 · 2022-09-24
Definitely a good point, refactoring is great and has a bunch of benefits but can also be overdone and create problems. I've heard/read Sandi Metz talk about this as "The Wrong Abstraction"[1]. The basic argument is that any time you do an extract refactor you're creating a new layer of abstraction that the next reader will have to learn and understand. This can also get worse over time as the abstractions drift away from their original purpose. The solution she provides is to be okay with a little bit of duplication, then as patterns naturally arise in the codebase you can refactor when you know a few use cases and can clearly define the concept. [1]: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
djhaskin987 · 2022-07-07
I often find that DRY is in conflict with Conway's law[1]. It's almost always better to let Conway's law win. If I help write a build script for one team, I often copy and paste it into another's git repo to instead of trying to share it. It's often way better than factoring it poorly[2] or getting the two teams to coordinate on changes they need to make to it. Best to let the two copies diverge in that case. 1: https://www.wingolog.org/archives/2015/11/09/embracing-conways-law 2: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
darekkay · 2021-05-26
> I don't recall where I picked up from, but the best advice I've heard on this is a "Rule of 3" I know this as AHA = Avoid Hasty Abstractions: - https://kentcdodds.com/blog/aha-programming - https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
Trufa · 2021-04-07
This reminds me of one of my favorite HN entries: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction >> Existing code exerts a powerful influence. Its very presence argues that it is both correct and necessary.
mumblemumble · 2020-12-19
Reminds me of an excellent blog post (and talk) by Sandi Metz: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction In it she also offers some great advice on what to do if you find yourself stuck with a bad abstraction.
cheshire_cat · 2020-01-12
Sandi Metz wrote a blog post about this: https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction > The moral of this story? Don't get trapped by the sunk cost fallacy. If you find yourself passing parameters and adding conditional paths through shared code, the abstraction is incorrect. It may have been right to begin with, but that day has passed. Once an abstraction is proved wrong the best strategy is to re-introduce duplication and let it show you what's right. Although it occasionally makes sense to accumulate a few conditionals to gain insight into what's going on, you'll suffer less pain if you abandon the wrong abstraction sooner rather than later.
doc_gunthrop · 2019-10-30
That coincides with the following: > Code is read many more times than it is written. Writing code costs something, but over time the cost of reading is often higher. Anyone who ever looks at a piece of code has to invest brain-power into figuring out what it does.[1] This is also noted in PEP8: > One of Guido's key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, "Readability counts".[2] [1]: https://www.sandimetz.com/blog/2017/6/1/the-half-life-of-code [2]: https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the…
auxbuss · 2018-05-23
There's an excellent discussion on this topic in the sample chapter, Rediscovering Simplicity[0], from Sandi Metz's book, 99 Bottles of OOP[1]. I often use it as a source for discussion with devs. [0] https://www.sandimetz.com/99bottles/sample [1] https://www.sandimetz.com/99bottles
rimliu · 2018-01-02
I recommend https://www.sandimetz.com/99bottles/ to everyone. Also her other book, Practical Object Oriented Design in Ruby. They both communicate the essential points very clearly. Also, after reading those books I got a better idea why OOP has a bad reputation, and why people are so bad at writing tests. Somehow these skills are presumed to be easy and already there when in reality they need practice, a lot of it.
rimantas · 2016-09-14
If you only get one book, get this one. It is more about 'why' than about 'how' and shows what tradeofs are involved in one or another design, what problems you can run into with different solutions. Also, there is a new book by Sandi coming out: http://www.sandimetz.com/99bottles/ Her talks are highly recommended too.
akkartik · 2016-02-28
> which is an abuse of DRY because it should only apply to concepts, not code As a 'copyista', I would change this to "DRY should only apply to production code, not tests." It wasn't clear from your reply if you agree or disagree. A couple of great recent links about this IMO under-discussed topic: http://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction http://programmingisterrible.com/post/139222674273/write-code-that-is-… http://bravenewgeek.com/abstraction-considered-harmful
Tainnor · 2023-07-21
> I thought I adressed that; everything I mentioned - explicit error returns, pure functions, no global state, and no metaprogramming - all show their true worth in large and/or unfamiliar codebases. I agree with all of those. I try to avoid these things whenever I write code (in rare cases, there are valid reasons for using them, but I agree they are overused). But that still leaves tons of room for different ways of writing code, and it's very hard to say which one of these is "obvious". Obvious to whom? Some people want to have large methods, so they can see everything at a glance, others prefer to have more smaller function so they can see the high-level picture before they see the details. Which one of them is right? I can't say - it depends on the person, on the problem, and on many other factors. What is missing from your list is "don't use advanced language features". You can do all the things you mentioned and still use "advanced" language features. And the debate about Go is often about how (presumably) the absence of "complex" features (something which is IMHO a bit subjective) makes code more "obvious". But you can have generics (or, more broadly, polymorphism), interfaces, higher order functions, proper algebraic data types, etc. and still uphold all the features you've quoted. That's what I meant with the Haskell comment (but supposedly the same would be true for e.g. Lisp). Since you shared a talk with me (which I intend to watch, but I haven't had time…
Mawr · 2023-07-20
> I'm not sure why you think that quoting random HN users proves anything except personal opinions of specific people? These are fine, but other people have other opinions. They support my argument so I included them. I don't see a practical difference between a "random HN user" and a random blog post or anything else. A good idea is a good idea, regardless of the medium. > I don't oppose the "principles" you've quoted, but they would just as easily apply to e.g. Haskell Possibly, I threw it together pretty quickly, so it's not very thought-out. > (maybe except for the "there's only one way to do it" which however has never been true of any language, including Python). It's not binary, but a spectrum. No language has just literally one way to express each concept. However, Python is definitely further towards the "one way to do it" end of the scale. Perhaps not as much these days as it used to, but still far more than for example Ruby or Perl. > I feel like you missed my larger point. It's not terribly difficult to write code that you can understand line by line. It's incredibly hard to write a huge code base in a way that you can reason about many code paths simultaneously, however. That's where the abstractions start to make sense. I thought I adressed that; everything I mentioned - explicit error returns, pure functions, no global state, and no metaprogramming - all show their true worth in large and/or unfamiliar codebases. > I don't understand why people think…
a4isms · 2023-02-27
I feel there are two separate things going on: First, the question of deduplication a/k/a normalization. Deduplication is cheap, and it's "a two-way door, not a one-way turnstile:" It's cheap to re-duplicate when you find that one of the users of your de-duplicated function or whatever needs new behaviour. Second, there is the question of the right versus wrong abstraction: If two different things use the same thing, that doesn't necessarily mean that they share the same abstraction conceptually. But of course, sometimes the duplication is a hint that there is some semantic commonality, and when you get this right, it's glorious, but if instead of de-duplicating we actually build the wrong abstraction, it can be extremely expensive to fix. That's more of a "one-way turnstile" problem. To me, when I see code that could be "DRY'd up," I have to ask myself whether it represents an opportunity to write a better abstraction, but I treat that decision conservatively, because of the cost of getting it wrong. In many cases, I choose to de-duplicate the code without creating what might be "the wrong abstraction," and it is often less expensive and lower risk to start there and only later consider abstractioneering. p.s. The tension between de-duplication and abstractioneering resembles the tension between is-a and has-a, often expressed by classical OO programmers as "inheritance" In those terms, I'm really describing my inclination as "Prefer composition to inheritance by…
svieira · 2022-07-07
This is discussed in detail in "The Wrong Abstraction" by Sandi Metz https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction Quote follows: ---- The strength of the reaction made me realize just how widespread and intractable the "wrong abstraction" problem is. I started asking questions and came to see the following pattern: 1. Programmer A sees duplication. 2. Programmer A extracts duplication and gives it a name. This creates a new abstraction. It could be a new method, or perhaps even a new class. 3. Programmer A replaces the duplication with the new abstraction. Ah, the code is perfect. Programmer A trots happily away. 4. Time passes. 5. A new requirement appears for which the current abstraction is almost perfect. 6. Programmer B gets tasked to implement this requirement. Programmer B feels honor-bound to retain the existing abstraction, but since isn't exactly the same for every case, they alter the code to take a parameter, and then add logic to conditionally do the right thing based on the value of that parameter. What was once a universal abstraction now behaves differently for different cases. 7. Another new requirement arrives. Programmer X. Another additional parameter. Another new conditional. Loop until code becomes incomprehensible. 8. You appear in the story about here, and your life takes a dramatic turn for the worse. Existing code exerts a powerful influence. Its very presence argues that it is both correct and necessary. We know that…
dimgl · 2022-01-05
I've seen this sentiment more and more recently. This sentiment is shared with books like Clean Code, which, when I first heard this, was shocking. Clean Code was one of the best books I ever read on programming, and at the time was hugely influential to my career growth. In fact, it helped me so much that I was able to uplevel other engineers by mentorship at several organizations that I've worked at. That being said, there have been some great critiques of these books and it's kept me wondering if maybe I'm misremembering these books for what they were. Here's a critique on Clean Code: https://qntm.org/clean Has it really been that long? Are these books really this outdated now? I saw a similar thread on Reddit recently and the alternative they recommended was this book... https://sandimetz.com/99bottles I've read only a couple of chapters, and I'm struggling to see why this book is so much better. Anyone have any opinions on this?
donw · 2020-06-24
The short answer is: don't design for future use-cases. Period. Instead, only build what you need to solve the problems you have in-hand, but do so in such a way that your software and your systems are as easy to change as possible in the future. Because you very, very rarely know what your future use-cases really are. Markets change over time, and your understanding of the market will also shift, both because some of your assumptions were wrong, and because you can never really have a total understanding of such a complex phenomenon. Your business needs will change as well; your top priority from 2019 is likely very different than it is today. That is why you build to embrace change, rather than barricade against it. As to how, I'd start with Sandi Metz's 99 Bottles of OOP: https://www.sandimetz.com/99bottles Learning to write readable code is also pretty important; Clean Code is a good starting point (https://amzn.to/3168z3A), but I'd be keen to know of any shorter books that cover the same materials. Growing Object-Oriented Software Guided By Tests (GOOSGT) is a good read as well: https://amzn.to/3du1sEL
pure-awesome · 2020-01-15
I used to think that if something is done twice, it should be abstracted. Now, I'm a bit more careful. There's a pretty famous quote by Sandi Mentz: "Duplication is far cheaper than the wrong abstraction." https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction Make sure that you're picking the write way to think about the task at hand, rather than blindly following DRY. There are times when even a single instance of a code call would be made clearer with abstraction, and there are times where having the same piece of code duplicated multiple times (or duplicated with one piece changed) is far clearer than trying to abstract it. This Reddit Comment also has an interesting take: https://www.reddit.com/r/programming/comments/5txp5t/duplication_is_fa… > The main purpose of abstractions is not to remove or reduce duplication, and not even to make code "reusable"; it is to make semantic patterns and assumptions explicit and, if possible, first-class. The further comments provide more discussion. --- I agree with the rest of your comment that refactoring and code-cleanup should be done in pieces and that, as with everything, striking the right balance is key.
spion · 2026-07-24
https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction probably describes what happens with sufficient nuance
marcus_holmes · 2026-04-13
"Duplication is far cheaper than the wrong abstraction" Sandi Metz https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
tinodb · 2026-03-11
It certainly isn’t. It is more a way of discovery on how to implement something, with the benefit of being able to safely (and thus easily) change it later. The 99 Bottles book by Sandi Metz [0] is a good short display of how it works and where it helps actually building maintainable software [0] https://sandimetz.com/99bottles
jonathaneunice · 2026-01-05
This seems very consistent with the refactoring techniques taught by Sandi Metz (https://sandimetz.com/99bottles). After taking her course, I successfully applied those techniques to good ends and outcomes. Not sure "refactor in context" is the tool for every single last refactoring job in the universe. Some plumbing changes may be large or systematic enough that they need to be separately planned and applied, especially as explaining "oh I changed the fundamental way we do things, just in passing" can be a hard PR to present. OTOH, since adopting the "in context" approach I have had many fewer refactoring attempts abandoned, and refactoring seems much more logical and purposeful. So it works IME.
dcre · 2025-05-17
I took a version of this away from Sandi Metz’s 99 Bottles of OOP. It’s not really my style overall, but the point about moving logic forks up the call stack was very well taken when I was working on a codebase where we had added a ton of flags that got passed down through many layers. https://sandimetz.com/99bottles

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close