Go's Philosophy: DRY (Don't Repeat Yourself)

3,867 views
Skip to first unread message

Luke Mauldin

unread,
Nov 7, 2012, 8:42:39 AM11/7/12
to golan...@googlegroups.com
I have developed off-and-on in Go over the past few months and there are alot of things that I really like about the language.  However, I have noticed that it seems that the DRY principle is not highly-valued in Go programming land.  A few examples from the source distribution (1.0.3): sort.go:214-261 and regexp.go:895:965
This seems very counter-intuitive to me since I come from a Java/C# background and in that realm the general thought is that "if two sections of my code are very similar, I need to refactor to combine the similarities and improve the long-term maintenance of the codebase".  Is the Go philosophy different?  I read the article "Less is More" by Rob Pike and after reading that article, it does seems that he thinks that a certain amount of code duplication is reasonable as long as it reduces the overall complexity of the program.
Does anyone have any thoughts on this?  Am I thinking about it incorrectly?

Luke

Job van der Zwan

unread,
Nov 7, 2012, 8:51:12 AM11/7/12
to golan...@googlegroups.com
I suspect that Go's philosophy is that if interfaces aren't useful for generalising your problem, it's very likely it deserves some handcrafted code anyway. Doesn't always apply, of course. 

David Symonds

unread,
Nov 7, 2012, 9:06:01 AM11/7/12
to Luke Mauldin, golan...@googlegroups.com

DRY is good, but it's not a goal in itself. It is a useful guiding principle, but other concerns can trump it. You have to consider each case independently.

Jan Mercl

unread,
Nov 7, 2012, 9:16:43 AM11/7/12
to Luke Mauldin, golang-nuts
On Wed, Nov 7, 2012 at 2:42 PM, Luke Mauldin <lukem...@gmail.com> wrote:
> I have developed off-and-on in Go over the past few months and there are
> alot of things that I really like about the language. However, I have
> noticed that it seems that the DRY principle is not highly-valued in Go
> programming land. A few examples from the source distribution (1.0.3):
> sort.go:214-261 and regexp.go:895:965

i wonder what similarities you see between the two above quoted
sources. To me they seem completely unrelated. The
`sort.go:214-261`[1] part deals with slice sorting and checking if a
slice is already sorted. The `regexp.go:895-965` part deals with
regular expression matching in strings. What's "DRY" violating in
that?

-j

[1]: http://golang.org/src/pkg/sort/sort.go#L214
[2]: http://golang.org/src/pkg/regexp/regexp.go#L895

Luke Mauldin

unread,
Nov 7, 2012, 9:20:18 AM11/7/12
to golan...@googlegroups.com, Luke Mauldin
Jan,

The two examples I gave are unrelated.  The violation of the DRY principle occurs within each of the files.  For example, in regexp.go, the FindAll and FindAllString are very similar and likewise the FindAllIndex and FindAllStringIndex have alot of duplication.  The duplication in the sort package occurs mainly because of the different types (string vs int vs float64).  However, both regexp and sort demonstrate areas where Go has duplication of almost identical code in the standard library.

Luke

Jan Mercl

unread,
Nov 7, 2012, 9:39:57 AM11/7/12
to Luke Mauldin, golang-nuts
On Wed, Nov 7, 2012 at 3:20 PM, Luke Mauldin <lukem...@gmail.com> wrote:
> The two examples I gave are unrelated. The violation of the DRY principle
> occurs within each of the files. For example, in regexp.go, the FindAll and
> FindAllString are very similar and likewise the FindAllIndex and
> FindAllStringIndex have alot of duplication. The duplication in the sort
> package occurs mainly because of the different types (string vs int vs
> float64). However, both regexp and sort demonstrate areas where Go has
> duplication of almost identical code in the standard library.

OK, so then:

- In the regexp package case, those similar parts of the functions are
quite short (4 lines prologue and 4 lines epilogue). Factoring out 4
lines into a shared function saves 3 lines per instance at a cost of
setting up the parameters/results stack frames and risking a possible,
avoidable, stack split. I would write the function in the same way as
the are written now.

- In the sort package case, that must be IMO an misunderstanding. The
methods for different types do not apply for the DRY principle Every
method implementation can be attached to only one named type (so the
function "header" is mandatory and the bodies are one-liners in this
case). Then there are the functions (not methods), which are "type
specialized". As long as Go has no generics, there's no other
reasonable way to how to do that. Changing it (DRY-ishly) to a single
implementation w/ `interface{}` parameters leads to lost static type
checking and performance penalties.

In summary, the examples provided by you are IMHO not violating the
DRY principle, as that doesn't demand sacrificing type
safety/performance just to not repeat oneself, and in the methods case
it is simply out of the specs.

-j

Miguel Pignatelli

unread,
Nov 7, 2012, 10:28:08 AM11/7/12
to Jan Mercl, Luke Mauldin, golang-nuts
On 07/11/12 14:39, Jan Mercl wrote:
>
> As long as Go has no generics, there's no other
> reasonable way to how to do that.
[...]
>
> In summary, the examples provided by you are IMHO not violating the
> DRY principle,

I think it is reasonable to say that the lack of generics impedes Go to
comply the "DRY principle" in many cases.
I am not saying that this is bad in all the cases. Being able to read
and follow the code without having to jump to different
packages/modules/inheritance levels improves my cognitive ease.

M;

>
> -j
>

Ethan Burns

unread,
Nov 7, 2012, 11:03:38 AM11/7/12
to golan...@googlegroups.com
Reducing complexity sounds like a great goal in any language, not just Go.  If that means that you use an abstraction to remove some code duplication then that's fine; if that means that you duplicate some code, because the abstraction would be complex, then that's fine too.  I think that the goal is to make simple, effective, and maintainable programs, not to find the most places in which a principle (like DRY) is applicable.

Best,
Ethan

Shivakumar GN

unread,
Nov 7, 2012, 11:28:53 AM11/7/12
to golang-nuts
On Wed, Nov 7, 2012 at 8:58 PM, Miguel Pignatelli <eme...@gmail.com> wrote:
I think it is reasonable to say that the lack of generics impedes Go to comply the "DRY principle" in many cases.


And the lack of inheritance as well.

But then it offers flexibility in the form of composition. An excellent trade-off IMHO.

Kamil Kisiel

unread,
Nov 7, 2012, 12:41:02 PM11/7/12
to golan...@googlegroups.com
Sometimes repeating code is simpler and easier to understand than trying to force an abstraction just to avoid duplication. I think code readability and ease of understanding trumps other concerns. I would rather have a function I can read top to bottom and understand what is happening than to avoid duplication just for the sake of DRY. I think Go hits the sweet spot in this regard. I've had nightmares debugging in dynamic languages where DRY is taken to the extreme and you are lost in a maze of indirection because the library authors wanted to avoid repeating a couple lines of code here and there.

si guy

unread,
Nov 7, 2012, 6:01:52 PM11/7/12
to golan...@googlegroups.com
With a modern editor: vim, emacs, st2, ms-vs, etc., repeated code is easy to manage with multiple select, refactoring tools, macros, etc.

DRY seems a little outdated, maybe it stands as a secondary principle to help readability...

-Simon Watt

Steven Johnson

unread,
Nov 7, 2012, 6:15:15 PM11/7/12
to si guy, golan...@googlegroups.com
On Wed, Nov 7, 2012 at 3:01 PM, si guy <sjw...@gmail.com> wrote:
> With a modern editor: vim, emacs, st2, ms-vs, etc., repeated code is easy to manage
> with multiple select, refactoring tools, macros, etc.

If you accept "sufficiently advanced editor" as a necessity to work
around language shortcomings...

voila, may I present to you: Eclipse and Java.

Michael Hofmann

unread,
Nov 7, 2012, 7:47:40 PM11/7/12
to golan...@googlegroups.com
IMHO these are violations of the DRY principle only when viewed through Java-colored glasses. There are no generic types in Go, so there is no simple way to replace these methods by a single, type-safe and performant implementation. Just like any other principle in programming, the scope of applicability of DRY is defined by the features of the programming language in use. Thus, from the point of view of a Java- or C# programmer, Go might look repetitive in some places because has no generics. An experienced Lisp programmer will have the same impression of Java and C# because they lack metaprogramming facilities. Neither of these observations makes much sense - you can't judge the quality of code written in one language by another language's standards.

Michael

Paulo Pinto

unread,
Nov 8, 2012, 3:48:06 AM11/8/12
to golang-nuts
Ah you mean tools like gotgo?

Luke Mauldin

unread,
Nov 8, 2012, 9:15:07 AM11/8/12
to golan...@googlegroups.com
Michael,

I like your the point that violations of DRY are dependent upon our language experiences.  I hadn't thought that a Lisp programmer might look at other languages like I am looking at Go.

Luke

stevewang

unread,
Nov 8, 2012, 9:44:36 AM11/8/12
to golan...@googlegroups.com
I think it's the best time to eliminate the duplication in your code when you will have to copy the similar code snippet here and there more than three times.

Miguel Pignatelli

unread,
Nov 8, 2012, 10:10:53 AM11/8/12
to stevewang, golan...@googlegroups.com
On 08/11/12 14:44, stevewang wrote:
> I think it's the best time to eliminate the duplication in your code
> when you will have to copy the similar code snippet here and there more
> than three times.
>

Or when you find yourself fixing the same copy/pasted code often.
Or if you are frequently bitten by fixes you have made in one piece of
code and not in a copy/pasted version of it
etc...

M;


stevewang

unread,
Nov 8, 2012, 10:13:37 AM11/8/12
to golan...@googlegroups.com
Well, I should say "a good time", but not "the best time".
Although this topic is beyond golang itself, I would like to say I deem that the code snippets accused by you in regexp is too small and too unrecurring to be worthy of refactoring.
Message has been deleted

stevewang

unread,
Nov 8, 2012, 10:20:00 AM11/8/12
to golan...@googlegroups.com, stevewang
Yes.
There are more cases which can be found in book 《refactoring》 written by Martin Fowler.

Bill Katz

unread,
Nov 8, 2012, 3:23:12 PM11/8/12
to golan...@googlegroups.com
There are definite cases where Go authors duplicate code to reduce complexity.  For example,  "Dependency hygiene trumps code reuse" with an example of the net package having its own itoa to avoid dependency on strconv:


-Bill

On Wednesday, November 7, 2012 8:42:39 AM UTC-5, Luke Mauldin wrote:

Øyvind Teig

unread,
Nov 9, 2012, 7:52:01 AM11/9/12
to golan...@googlegroups.com
As an embedded (non-Go, of course) programmer, my experience is that type width is a primary concern. Making a generic function that would treat both 8, 16 and 32 bits FFT (f.ex.) would not be what I would long for. Even if the pattern (algorithm) in them would be equal. My head would be so full with overflow/underflow handling when reading those functions that cognitively I would feel much more on dry land with FFT8, FFT16 and FFT32. The fact the Go would not allow anything else than that is OK with me. But of course, DRY is fine, as a generic means. 

Another thing is that I see thet the compilers these days seem to do some kind of correlation of code, and makes functions of code snippets that have been duplicated. I have an example of a very readble non-LEX/YACC-based parser, that does a lot if if then else's, over and over. Easy to read, easy to debug, easy to modify. And the compiler builds functions for me, so speed and code size are ok.

/ Øyvind Teig
Reply all
Reply to author
Forward
0 new messages