
Rule of Three (Computer Programming) - thunderbong
https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)
======
not2b
To me, the real issue is that a design decision should ideally be expressed at
only one place in the code. Then, if that decision is changed, you change that
one place in the code. If the design decision is reflected in two or more
places, chances are that when changes are made, one of those places will be
missed. Some languages force you to write things twice (the prototype and the
definition in C and C++), but at least the compiler helps find mismatches.

------
crimsonalucard
More than just code duplication, what about functionality duplication? By
functionality I mean code that does the same thing but is written
significantly differently.

This is by far the most insidious problem as you can't just wrap duplicated
code up into a function and move all the code to one place.

Usually this problem appears not just as functionality duplicated in many
places but each time the functionality is also intertwined with other features
and cannot be decomposed to get rid of the duplication.

In most styles of programming there is no way to get around this issue as it
has to do with program "design." Unless you can make a design that anticipates
the duplication, likely a duplication is inevitable.

However, if you make your variables immutable as much as possible you can get
around this issue and solve what was seemingly a "design" problem but was in
fact only a problem with mutable variables. It's too bad the majority of
programmers don't know about this.

~~~
ksaj
This is how Lisp gets you to think about code. Minimize side effects
(essentially the same argument as immutable variables), and if you're likely
to use something more than once, turn it into its own function. Then stick it
into your private library if you're at all likely to see it again in the
future.

Something that doesn't occur often enough, but should: then rewrite the
function for various optimizations - speed, size, security, whatever, while
ensuring the same input will always produce the same output.

~~~
crimsonalucard
I'm from the haskell universe.

It's more than just side effects. A common design issue people hit is that
midway through a projects lifetime they hit a feature request that is
basically a slight permutation of an existing feature.

They realize that they cannot reuse the code because of the way they
"designed" the program. Ideally you want to reuse existing code, or if no
function specifically supports this feature you can encapsulate a relevant
line of code into some sort of container so that it can be reused in multiple
places. This is a way of decomposing your code, or aka: dividing a function
into multiple pieces so components can be deployed in multitudes of other
location thereby maximizing code re-use.

What happens is that most people realize that no matter how much they plan out
a design they cannot execute the decomposition procedure above. A design
choice made at the inception of the project fixes the shape of the code and
limits flexibility. Thus they do code duplication as a workaround hack.

I am saying that this problem is actually caused by mutability.

What is seemingly a structural problem only occurs because you have a mutable
variable. You can cut your code and divide a primitive into a thousand
possible pieces if you wanted too but the minute you have a mutable variable
in your code the division cannot be done.

Think about it. To surgically remove a mutable variable out of a piece of code
you must not just cut out the variable but you must also bring every function
or procedure that mutates that variable along for the ride. If your function
has an entire network of functions mutating procedures than that function
cannot be divided into smaller functions.

An immutable function can be cut into a thousand pieces and rebuilt in a
different way. This is the best known solution for program design and
organization.

------
nightsd01
The real problem is when you get to scale. At a company like Facebook or
Google, it seems like you end up spending half your time simply looking for
similar code that other developers wrote to solve a similar problem so that
you can avoid duplication in the codebase. When you have tens of thousands of
developers that becomes VERY challenging.

Code duplication is one of the biggest mistakes I made as a new developer. As
you became a better engineer, you learn how to simplify and extract common
patterns into shared classes/libraries/components to avoid duplication. Code
duplication is almost a cardinal sin due to the complexity and bugs that tend
to result.

------
lostmsu
I use a totally different rule, a rule of C: if you feel that a code block
needs a comment, extract it into a function with descriptive name.

With this rule duplicates rarely happen anywhere but in utility functions that
extend the standard library.

------
Stratoscope
Here's a discussion from last month about an encounter I had with this rule:

[https://news.ycombinator.com/item?id=22024294](https://news.ycombinator.com/item?id=22024294)

------
crimsonalucard
I kind of hate stuff like this. Why three? Why not four? Is it three because
the "rule of three" sounds quotable?

It's similar to KISS. Yes I get why simplicity is great but it doesn't mean
it's universally great. Is this acronym telling me to follow some random
principle because the acronym forms a word? Many Complex systems exist in the
world as an antithesis to KISS, so this principle isn't universal at all.

Why not stop duplication in ALL cases? What is the statistical evidence or
logical proof that justifies "three?"

~~~
samatman
The premise is that the second time you do the same thing, it's often unclear
if it's _really_ the same thing, or if it's just the same thing at the moment.

I stick with the Rule of Three as a rule of thumb, and it seems that the
repeated logic diverges about as often as it converges.

Once you start thinking about a third implementation, it's time to put the
logic in one place.

