N = 2 leads to N >= 3 most of the time. I get the point and I also don't abstract out things immediately, but rather than follow hard rules, we can say that ... I don't know it seems like 99% of code is going to be used either once, or more than 2 times. Something to get used exactly 2 times would be very rare.
Also in general programming, abstraction isn't the only way to avoid repetition.
And the main reason for DRY is to not have to change the code in 7 places when something changes.
So you kinda have to know which things logically belong together. Very often that's things that share the exact same code, but sometimes it isn't.
A good reason to wait until you have three or more repetitions is that it helps you prevent writing abstractions that take ten arguments.
*You may think "oh, this code here repeated here, and here" so you write an abstraction. Then you add a third variation, and realize you need a height argument, so you redefine it with a default of None. Then repetition four requires a colour. And before you know it, your abstraction ends up with 10 different branches and becomes 🍝.
On the other hand, if you do write it in different places, you'll see what the differences are, and maybe abstract it into 3 didn't functions that only do one thing, so you don't end up with abstractions that you end up refactoring anyways.
(*Impersonal you - not saying you're guilty of that, as it gets easier to predict with experience, but good habit to develop early on).
This is very well put. There are many ways to abstract something and you don't know what the best abstraction is going to be until you have a large enough sample of sub-problems to be able to make an informed decision.
Choosing the wrong abstraction is costly and leads to complexity bloat because developers have a natural tendency to keep adding new abstractions on top instead of refactoring or deleting existing ones.
Also, every time you invent a new abstraction to reduce repetition, you introduce one more concept that people have to learn in order to make sense of your code and it adds up; especially if the abstractions are contrived technical concepts and not strongly rooted in an underlying business domain.
This only works if you have excellent communication between your devs. Otherwise if you have three devs, each recreating the wheel three times, that's nine repetitions.
It also depends on what the item is... if you are writing a way to find the next recurring date/time using an RRULE (RFC 5545), then you should definitely write that only once and have everyone use only that one. Otherwise one iteration will work if a daylight savings boundary is crossed, and the next two iterations will not, as an example...
Yes.
So summarizing: only make an abstraction for something if you can remove three repetitions.
N = 2 leads to N >= 3 most of the time. I get the point and I also don't abstract out things immediately, but rather than follow hard rules, we can say that ... I don't know it seems like 99% of code is going to be used either once, or more than 2 times. Something to get used exactly 2 times would be very rare.
Also in general programming, abstraction isn't the only way to avoid repetition.
And the main reason for DRY is to not have to change the code in 7 places when something changes.
So you kinda have to know which things logically belong together. Very often that's things that share the exact same code, but sometimes it isn't.
A good reason to wait until you have three or more repetitions is that it helps you prevent writing abstractions that take ten arguments.
*You may think "oh, this code here repeated here, and here" so you write an abstraction. Then you add a third variation, and realize you need a height argument, so you redefine it with a default of
None
. Then repetition four requires a colour. And before you know it, your abstraction ends up with 10 different branches and becomes 🍝.On the other hand, if you do write it in different places, you'll see what the differences are, and maybe abstract it into 3 didn't functions that only do one thing, so you don't end up with abstractions that you end up refactoring anyways.
(*Impersonal you - not saying you're guilty of that, as it gets easier to predict with experience, but good habit to develop early on).
This is very well put. There are many ways to abstract something and you don't know what the best abstraction is going to be until you have a large enough sample of sub-problems to be able to make an informed decision.
Choosing the wrong abstraction is costly and leads to complexity bloat because developers have a natural tendency to keep adding new abstractions on top instead of refactoring or deleting existing ones.
Also, every time you invent a new abstraction to reduce repetition, you introduce one more concept that people have to learn in order to make sense of your code and it adds up; especially if the abstractions are contrived technical concepts and not strongly rooted in an underlying business domain.
This only works if you have excellent communication between your devs. Otherwise if you have three devs, each recreating the wheel three times, that's nine repetitions.
It also depends on what the item is... if you are writing a way to find the next recurring date/time using an RRULE (RFC 5545), then you should definitely write that only once and have everyone use only that one. Otherwise one iteration will work if a daylight savings boundary is crossed, and the next two iterations will not, as an example...
I remember this as "Generalize at n = 3"