Hacker News new | past | comments | ask | show | jobs | submit login

Yup, instead of DRY I'm a big fan of WET, Write Everything Twice.

Third time? Maybe consider a refactor at that point.




I learned this from the smartest dev manager I've ever had in the second or third week at the job, it really tore down a lot of the notions I'd formed as a self taught developer.

We were looking at a pull I'd created and he asked 'are these things really the same or is it just a coincidence because the features aren't mature enough yet?'. And yes I'd conflated two things with entirely different intents by over-abstracting.


Wow, you just blew my mind. "Don't Repeat Yourself" could just be premature optimization and overfitting on a tiny data set.


Absolutely. This has been discussed here quite a bit (e.g. https://news.ycombinator.com/item?id=120614530). In real life it's often visible when you have methods that take one or more flags to tell them how to behave. Fixing involves duplicating the method - one copy for calls where the flag is true, one for where it is false. Then simplifying, then repeating. The code that falls out at the end is often dramatically simpler than what was there before. It makes me wonder about some of these programming aphorisms - they only seem to work if you are already experienced enough to know to take them with a pinch of salt.


DRY is really valuable for noobs. Like, defining magic numbers twice in adjacent functions is really common behavior for beginners. Likewise, writing the same exact logic several times in different parts of the code without encapsulating into a function. Stuff that would be obvious for even junior devs.

But I do think it falls apart when applied at a more macro level.


The book "Pragmatic Programmer" talks about this in chapter 2, topic 9.

The kind of duplication you want to avoid is knowledge duplication. If two pieces of code literally do the same thing but for different reasons/purposes, it may not be a good idea to deduplicate them.


Very early versions of the my compiler's code generator were set up to minimize code size, for the simple reason that 640K wasn't enough. This meant merging disparate sequences of code, often with goto's.

The result made it hard to understand the code, and hard to graft in new functionality. So over time I refactored it to duplicate the code, but each string of code is a lot easier to understand.


I've got the bunch of services that all do the same thing on a different data model. Originally they were all different and completely custom. Over time, I've managed to get nearly all of the code practically identical across 8 services. The same code is duplicated 8 times, but I prefer that over when they were all different, because then they were all doing basically the same thing in 8 different ways.

I know that eventually I can move all the identical code out of there to its own service, and replace the 8 services with just 8 simple configuration lists, and that's definitely where we're going at some point in the future, but for now, the 8 times duplication is actually fine. People know these services and what they do, and I know they're conceptually all instances of the same thing, it's just not quite represented that way in the code yet. We'll get there.

It's possible a few still have some exceptions, so that needs to be figured out first, but due to the way the code is put together, there's no rush; people are only changing the parts they're meant to change anyway.


Yeah I think DRY has been bastardized to mean dont repeat code when it actually means encode business logic in one place.


I mind duplicated code a lot less than duplicated data. If two things have to match, but they're using two different configurations, then there's going to be a mismatch some day. I'd rather create the second config out of the first one. If front- and backend need to know something, have the front-end get its config from the backend, instead of hard-coding it in two places.


I’ve inherited codebases like this, they almost always have subtle bugs because people changed something but missed the other place the logic needed to be modified. My thought is that functionally cohesive blocks of code should almost always be extracted to a function and named: if this causes a bad abstraction, you can always either duplicate the function and rename or inline the function and re-abstract.


I've had the opposite experience: bad abstractions generally cause more pain than duplicated code. Generally this is because bad abstractions tend to leak their bad-ness into the code around them.


People think I'm a charlatan when I advocate copy and pasting code around, but really it just takes a few seconds so I don't think time concerns are a good argument against it.

Rather you should ask yourself if you want these two functions to be coupled? So that by changing one you are forced to change both. This is very desirable in some cases, but when you don't want components bolted together just copy and paste.


I think the problem with copy pasting is that it implies you're copying a chunk big enough to be worth taking the shortcut. If you happen to have two of the same two-liners, then there's a good chance they shouldn't be abstracted. But if they're five-liners that probability goes way down.

I'd guess that most devs don't c/p two lines, unless they're particularly slow typers. Or you're one of those fancy vim people that jumps all over the joint with keystrokes instead of having to move to the mouse to select text.

Also, the reason I basically never c/p is because I do it manually. I have a habit of using old code as a reference while I write new code, and the two pieces of code somehow end up being the same. The difference is, I've vetted every single line of what I've written, even if it's a duplicate, so I know it's relevant to the new context I'm working in. If you c/p, there's no requirement for you to mentally check that the new code is all relevent, and correct, for the new context.


This is fine until the copy/paste paradigm escapes the sensible boundary.

Copying the code - 2 seconds. Copy the unit tests? Another 2 seconds? Refactoring the copy pasted thing that is now in 25 different git repos? Sad face


Oftentimes it is better to make code that is easily copy pasted/edited later than to make reusable code IMO.

I think knuth was the first time I heard of reeditable.

For example I had to recently write some code to center a form shown as a dialog based on the overlying window. Because we use a MDI. I had to take into account local to screenspace coordinates.

Once it was a usercontrol embedded in a form, once just a form and once the top window, etc. All of those needed just tiny adjustments, while rolling it into one function would be MUCH more cumbersome.


I prefer Write Everything Thrice.


Thanks for adding that acronym to my vocabulary. I use this strategy for a long time but needed more words to explain it.



I have seen code based that were following this principle, but nobody realised they were writing the same thing for the 5th time.


If I recall correctly this is also the advice PG gives in On Lisp when deciding whether or not it is time to write a new function.


I just wet myself! Love this!


just be sure to stop before it just becomes "We Enjoy Typing"


I think that's called technical debt.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

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

Search: