DRY vs. KISS

Shlomi Fish <shlomif-ik1l9ssToec+JF/[email protected]> Thu, 12 Nov 2009 19:24:19 +0200
Newsgroups gmane.culture.hackers.israel
Message-ID <[email protected]>
--2fsKsQxMTGrzz7eRPrXBaGM9ZmH6rcSYtW1tXUR
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi all!

First of all - DRY is http://en.wikipedia.org/wiki/Don%27t_repeat_yourself - 
the principle of software design where one assumes they should avoid duplicate 
code and repeating various stuff. Likewise - KISS is 
http://en.wikipedia.org/wiki/KISS_principle - "Keep it simple, stupid" - the 
principle of software design (or whatever) where you should try to avoid being 
too clever or doing too much.

Lately, I've often been thinking that some places where I tried to avoid 
repeating myself (and violate the DRY principle) have caused the code to 
become too clever and as result hard to get into, at least for the uninitiated 
(and thus violate the KISS principle). For example, in 
http://web-cpan.berlios.de/modules/Test-Run/ , I created a small abstraction 
to run several methods, one after the other in a sequence, after breaking 
several methods into shorter ones. So:

sub myfunc
{
	# $self is the object handle, $args are the other argument
	my ($self, $args) = @_;

	$self->one($args);
	$self->two($args);
	$self->three($args);

	# Return nothing because this is a procedure
	return;
}

Becomes something like

<<<<<<<<<<<
__PACKAGE__->add_seq_func( [ "myfunc" ] );

sub _myfunc__list
{
	return [ "one", "two", "three", ];
}
>>>>>>>>>>>

And add_seq_func will generate this method by using run-time code-generation 
(not necessarily string eval, but also possibly using closures, etc.). I gave 
the syntax in Perl out of convenience but such hackery is possibly in Ruby and 
other languages.

Now I think the second version, while being more modular, is very non-KISS, 
and will likely confuse people.

Today I ran into another example. In:

http://www.shlomifish.org/open-source/projects/XML-Grammar/Fiction/

(and XML-Grammar-Screenplay from which it was derived) I had something like 
that:

<<<<<<<<<<<<<<<<<<<

        $self->_with_curr_line(
            sub {

                my $l = shift;

		# Use a regex on the string pointed to by $l			
                
		${$l} =~ m{\G([^\<\[\]\&]*)}cgms;


>>>>>>>>>>>>>>>>>>>

What happens here is that _with_curr_line is a method that accepts a 
subroutine reference (that can be a closure), which in turn gets passed a 
reference (which is the Perl idea of a pointer) to the current line in the 
parser, which I can use while being able to modify it. Eventually I changed 
all the code there to:

<<<<<<<<<<<<<<<<<<
my $l = $self->_curr_line_ref();

# Do something with ${$l} and be happy.
>>>>>>>>>>>>>>>>>>

Arguably, I now have duplicate "my $l = $self->_curr_line_ref();" calls all 
over the code but the code is simpler this way. I'm not an anti-closure 
purist, and think they have many legitimate uses, but felt that the old 
version was confusing, and created another pattern in the code (and possibly 
an anti-pattern) that wasn't much better than what I had.

So the question to you is: do you think DRY and KISS can sometimes contradict 
one another? If so, which one is more important, or that you should just use 
your reason. I should also note that I've been feeling that less expressive 
languages sometimes result in being unable to avoid duplicate code or 
undesirable "patterns" in the code (in accordance to DRY). Possibly the only 
family of languages that completely avoids duplicate code is Lisp.

Regards,

	Shlomi Fish



-- 
-----------------------------------------------------------------
Shlomi Fish       http://www.shlomifish.org/
Interview with Ben Collins-Sussman - http://shlom.in/sussman

Chuck Norris read the entire English Wikipedia in 24 hours. Twice.

--2fsKsQxMTGrzz7eRPrXBaGM9ZmH6rcSYtW1tXUR
Content-Type: text/html; charset=US-ASCII
Content-Transfer-Encoding: 7bit




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
</head>







<body style="background-color: #fff;">
<span style="display:none">&nbsp;</span>

<!--~-|**|PrettyHtmlStartT|**|-~-->
<div id="ygrp-mlmsg" style="position:relative;">
  <div id="ygrp-msg" style="z-index: 1;">
<!--~-|**|PrettyHtmlEndT|**|-~-->

    <div id="ygrp-text" >
      
      
      <p>Hi all!<br>
<br>
First of all - DRY is <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself">http://en.wikipedia<wbr>.org/wiki/<wbr>Don%27t_repeat_<wbr>yourself</a> - <br>
the principle of software design where one assumes they should avoid duplicate <br>
code and repeating various stuff. Likewise - KISS is <br>
<a href="http://en.wikipedia.org/wiki/KISS_principle">http://en.wikipedia<wbr>.org/wiki/<wbr>KISS_principle</a> - &quot;Keep it simple, stupid&quot; - the <br>
principle of software design (or whatever) where you should try to avoid being <br>
too clever or doing too much.<br>
<br>
Lately, I've often been thinking that some places where I tried to avoid <br>
repeating myself (and violate the DRY principle) have caused the code to <br>
become too clever and as result hard to get into, at least for the uninitiated <br>
(and thus violate the KISS principle). For example, in <br>
<a href="http://web-cpan.berlios.de/modules/Test-Run/">http://web-cpan.<wbr>berlios.de/<wbr>modules/Test-<wbr>Run/</a> , I created a small abstraction <br>
to run several methods, one after the other in a sequence, after breaking <br>
several methods into shorter ones. So:<br>
<br>
sub myfunc<br>
{<br>
	# $self is the object handle, $args are the other argument<br>
	my ($self, $args) = @_;<br>
<br>
	$self-&gt;one($<wbr>args);<br>
	$self-&gt;two($<wbr>args);<br>
	$self-&gt;three(<wbr>$args);<br>
<br>
	# Return nothing because this is a procedure<br>
	return;<br>
}<br>
<br>
Becomes something like<br>
<br>
&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;<br>
__PACKAGE__-<wbr>&gt;add_seq_<wbr>func( [ &quot;myfunc&quot; ] );<br>
<br>
sub _myfunc__list<br>
{<br>
	return [ &quot;one&quot;, &quot;two&quot;, &quot;three&quot;, ];<br>
}<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
<br>
And add_seq_func will generate this method by using run-time code-generation <br>
(not necessarily string eval, but also possibly using closures, etc.). I gave <br>
the syntax in Perl out of convenience but such hackery is possibly in Ruby and <br>
other languages.<br>
<br>
Now I think the second version, while being more modular, is very non-KISS, <br>
and will likely confuse people.<br>
<br>
Today I ran into another example. In:<br>
<br>
<a href="http://www.shlomifish.org/open-source/projects/XML-Grammar/Fiction/">http://www.shlomifi<wbr>sh.org/open-<wbr>source/projects/<wbr>XML-Grammar/<wbr>Fiction/</a><br>
<br>
(and XML-Grammar-<wbr>Screenplay from which it was derived) I had something like <br>
that:<br>
<br>
&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;<wbr>&lt;&lt;&lt;&lt;&lt;&lt;&lt;<br>
<br>
$self-&gt;_with_<wbr>curr_line(<br>
            sub {<br>
<br>
my $l = shift;<br>
<br>
		# Use a regex on the string pointed to by $l			<br>
                <br>
		${$l} =~ m{\G([^\&lt;\[\<wbr>]\&amp;]*)}cgms;<br>
<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<wbr>&gt;&gt;&gt;&gt;&gt;&gt;&gt;<br>
<br>
What happens here is that _with_curr_line is a method that accepts a <br>
subroutine reference (that can be a closure), which in turn gets passed a <br>
reference (which is the Perl idea of a pointer) to the current line in the <br>
parser, which I can use while being able to modify it. Eventually I changed <br>
all the code there to:<br>
<br>
&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;<wbr>&lt;&lt;&lt;&lt;&lt;&lt;<br>
my $l = $self-&gt;_curr_<wbr>line_ref(<wbr>);<br>
<br>
# Do something with ${$l} and be happy.<br>
&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;<wbr>&gt;&gt;&gt;&gt;&gt;&gt;<br>
<br>
Arguably, I now have duplicate &quot;my $l = $self-&gt;_curr_<wbr>line_ref(<wbr>);&quot; calls all <br>
over the code but the code is simpler this way. I'm not an anti-closure <br>
purist, and think they have many legitimate uses, but felt that the old <br>
version was confusing, and created another pattern in the code (and possibly <br>
an anti-pattern) that wasn't much better than what I had.<br>
<br>
So the question to you is: do you think DRY and KISS can sometimes contradict <br>
one another? If so, which one is more important, or that you should just use <br>
your reason. I should also note that I've been feeling that less expressive <br>
languages sometimes result in being unable to avoid duplicate code or <br>
undesirable &quot;patterns&quot; in the code (in accordance to DRY). Possibly the only <br>
family of languages that completely avoids duplicate code is Lisp.<br>
<br>
Regards,<br>
<br>
	Shlomi Fish<br>
<br>
-- <br>
------------<wbr>---------<wbr>---------<wbr>---------<wbr>---------<wbr>---------<wbr>-<br>
Shlomi Fish       <a href="http://www.shlomifish.org/">http://www.shlomifi<wbr>sh.org/</a><br>
Interview with Ben Collins-Sussman - <a href="http://shlom.in/sussman">http://shlom.<wbr>in/sussman</a><br>
<br>
Chuck Norris read the entire English Wikipedia in 24 hours. Twice.<br>
</p>

    </div>
     

    <!--~-|**|PrettyHtmlStart|**|-~-->
    <div style="color: #fff; height: 0;">__._,_.___</div>

        
  
   
    <div id="ygrp-actbar" style="clear: both; margin-bottom: 10px; white-space: nowrap; color: #666; padding-top: 15px;">
      <div>
        <a href="mailto:shlomif-ik1l9ssToec+JF/[email protected]?subject=DRY vs. KISS">
          Reply to <span style="font-weight: 700;">sender</span></a>
          | <a href="mailto:[email protected]?subject=DRY vs. KISS">
        Reply to <span style="font-weight: 700;">group</span></a>
      </div>

                <a href="http://groups.yahoo.com/group/hackers-il/message/5094;_ylc=X3oDMTM0bnJzcjdmBF9TAzk3MzU5NzE0BGdycElkAzE4NTczMzIEZ3Jwc3BJZAMxNzA1MDA2NzY0BG1zZ0lkAzUwOTQEc2VjA2Z0cgRzbGsDdnRwYwRzdGltZQMxMjU4MDQ2Nzc1BHRwY0lkAzUwOTQ-">Messages in this topic</a>
          (<span style="font-weight: 700;">1</span>)
          </div> 
<!------- Start Nav Bar ------>

<!-- |**|begin egp html banner|**| -->
<div id="ygrp-vital" style="background-color: #e0ecee; font-family: Verdana; font-size: 10px; margin-bottom: 10px; padding: 10px;">
      <span id="vithd" style="font-weight: bold; color: #333; text-transform: uppercase; ">Recent Activity:</span>

    <ul style="list-style-type: none; margin: 0; padding: 0; display: inline;">
                                                    </ul>
    
  <div style="clear: both; padding-top: 2px; color: #1e66ae;">
    <a href="http://groups.yahoo.com/group/hackers-il;_ylc=X3oDMTJlNGRhcTZnBF9TAzk3MzU5NzE0BGdycElkAzE4NTczMzIEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTI1ODA0Njc3NQ--" style="border-right: 1px solid #000; padding-right: 5px; margin-right: 2px; text-decoration: none;">Visit Your Group</a>
    <a href="http://groups.yahoo.com/group/hackers-il/post;_ylc=X3oDMTJlcGdubmI1BF9TAzk3MzU5NzE0BGdycElkAzE4NTczMzIEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTI1ODA0Njc3NQ--" style="font-weight: 700; text-decoration: none;">Start a New Topic</a>
  </div>
</div>

              <div id="ygrp-mkp" style="border: 1px solid #d8d8d8; clear: both; float: left; font-family: Arial; margin: 5px 0 10px 0; padding: 0 10px;">
      <div id="hd" style="color: #628c2a; font-size: 85%; font-weight: 700; line-height: 122%; margin: 10px 0;">MARKETPLACE</div>
      <div id="ads" style="margin-bottom: 10px;">
                  <div class="ad" style="color: #628C2A; font-family: Arial; font-weight: 700; padding: 0 0;">
            <p><a href="http://us.ard.yahoo.com/SIG=14kmgrnhq/M=493064.12016295.13793596.10835568/D=groups/S=1705006764:MKP1/Y=YAHOO/EXP=1258053975/L=/B=UcTPPkPDhCg-/J=1258046775400064/K=m.losYg4RuNBpNKMv8KwTg/A=5898843/R=0/SIG=11kkq36go/*http://advision.webevents.yahoo.com/parentingzone/">Parenting Zone: Find useful resources for a happy, healthy family and home</a></p>           </div>
                              </div>
    </div>
  
<div id="ft" style="font-family: Arial; font-size: 11px; margin-top: 5px; padding: 0 2px 0 0; clear: both;">
  <a href="http://groups.yahoo.com/;_ylc=X3oDMTJkMW5jbDJuBF9TAzk3MzU5NzE0BGdycElkAzE4NTczMzIEZ3Jwc3BJZAMxNzA1MDA2NzY0BHNlYwNmdHIEc2xrA2dmcARzdGltZQMxMjU4MDQ2Nzc1" style="float: left;"><img src="http://l.yimg.com/a/i/us/yg/logo/us.gif" height="15" width="137" alt="Yahoo! Groups" style="border: 0;"/></a>
  <div style="color: #747575; float: right;">Switch to: <a href="mailto:[email protected]?subject=Change Delivery Format: Traditional" style="text-decoration: none;">Text-Only</a>, <a href="mailto:[email protected]?subject=Email Delivery: Digest" class="margin-rt" style="text-decoration: none;">Daily Digest</a> &bull; <a href="mailto:[email protected]?subject=Unsubscribe" style="text-decoration: none;">Unsubscribe</a> &bull; <a href="http://docs.yahoo.com/info/terms/" style="text-decoration: none;">Terms of Use</a></div>
</div>

<!-- |**|end egp html banner|**| -->

  </div> <!-- ygrp-msg -->

  <!-- Sponsor -->
  <!-- |**|begin egp html banner|**| -->
  <div id="ygrp-sponsor" style="width:160px; float:right; clear:none; margin:0 0 25px 0; background: #fff;">

<!-- Start Recommendations -->
<div id="ygrp-reco">
     </div>
<!-- End Recommendations -->



  </div>   <!-- |**|end egp html banner|**| -->

  <div style="clear:both; color: #FFF; font-size:1px;">.</div>
</div>

  <img src="http://geo.yahoo.com/serv?s=97359714/grpId=1857332/grpspId=1705006764/msgId=5094/stime=1258046775/nc1=4507179/nc2=3848641/nc3=5689707" width="1" height="1"> <br>

<div style="color: #fff; height: 0;">__,_._,___</div>
<!--~-|**|PrettyHtmlEnd|**|-~-->

</body>

<!--~-|**|PrettyHtmlStart|**|-~-->
<head>
  <style type="text/css">
  <!--
  #ygrp-mkp {
  border: 1px solid #d8d8d8;
  font-family: Arial;
  margin: 10px 0;
  padding: 0 10px;
}

#ygrp-mkp hr {
  border: 1px solid #d8d8d8;
}

#ygrp-mkp #hd {
  color: #628c2a;
  font-size: 85%;
  font-weight: 700;
  line-height: 122%;
  margin: 10px 0;
}

#ygrp-mkp #ads {
  margin-bottom: 10px;
}

#ygrp-mkp .ad {
  padding: 0 0;
}

#ygrp-mkp .ad a {
  color: #0000ff;
  text-decoration: none;
}
  #ygrp-sponsor #ygrp-lc {
  font-family: Arial;
}

#ygrp-sponsor #ygrp-lc #hd {
  margin: 10px 0px;
  font-weight: 700;
  font-size: 78%;
  line-height: 122%;
}

#ygrp-sponsor #ygrp-lc .ad {
  margin-bottom: 10px;
  padding: 0 0;
}

  a {
    color: #1e66ae;
  }

  #actions {
    font-family: Verdana;
    font-size: 11px;
    padding: 10px 0;
  }

  #activity {
    background-color: #e0ecee;
    float: left;
    font-family: Verdana;
    font-size: 10px;
    padding: 10px;
  }

  #activity span {
    font-weight: 700;
  }

  #activity span:first-child {
    text-transform: uppercase;
  }

  #activity span a {
    color: #5085b6;
    text-decoration: none;
  }

  #activity span span {
    color: #ff7900;
  }

  #activity span .underline {
    text-decoration: underline;
  }

  .attach {
    clear: both;
    display: table;
    font-family: Arial;
    font-size: 12px;
    padding: 10px 0;
    width: 400px;
  }

  .attach div a {
    text-decoration: none;
  }

  .attach img {
    border: none;
    padding-right: 5px;
  }

  .attach label {
    display: block;
    margin-bottom: 5px;
  }

  .attach label a {
    text-decoration: none;
  }
  
  blockquote {
    margin: 0 0 0 4px;
  }

  .bold {
    font-family: Arial;
    font-size: 13px;
    font-weight: 700;
  }

  .bold a {
    text-decoration: none;
  }

  dd.last p a {
    font-family: Verdana;
    font-weight: 700;
  }

  dd.last p span {
    margin-right: 10px;
    font-family: Verdana;
    font-weight: 700;
  }

  dd.last p span.yshortcuts {
    margin-right: 0;
  }

  div.attach-table div div a {
    text-decoration: none;
  }

  div.attach-table {
    width: 400px;
  }

  div.file-title a, div.file-title a:active, div.file-title a:hover, div.file-title a:visited {
    text-decoration: none;
  }

  div.photo-title a, div.photo-title a:active, div.photo-title a:hover, div.photo-title a:visited {
    text-decoration: none;
  }

  div#ygrp-mlmsg #ygrp-msg p a span.yshortcuts {
    font-family: Verdana;
    font-size: 10px;
    font-weight: normal;
  }

  .green {
    color: #628c2a;
  }

  .MsoNormal {
    margin: 0 0 0 0;
  }

  o {
    font-size: 0;
  }

  #photos div {
    float: left;
    width: 72px;
  }

  #photos div div {
    border: 1px solid #666666;
    height: 62px;
    overflow: hidden;
    width: 62px;
  }

  #photos div label {
    color: #666666;
    font-size: 10px;
    overflow: hidden;
    text-align: center;
    white-space: nowrap;
    width: 64px;
  }

  #reco-category {
    font-size: 77%;
  }

  #reco-desc {
    font-size: 77%;
  }

  .replbq {
    margin: 4px;
  }

  #ygrp-actbar div a:first-child {
   /* border-right: 0px solid #000;*/
    margin-right: 2px;
    padding-right: 5px;
  }

  #ygrp-mlmsg {
    font-size: 13px;
    font-family: Arial, helvetica,clean, sans-serif;
    *font-size: small;
    *font: x-small;
  }

  #ygrp-mlmsg table {
    font-size: inherit;
    font: 100%;
  }

  #ygrp-mlmsg select, input, textarea {
    font: 99% Arial, Helvetica, clean, sans-serif;
  }

  #ygrp-mlmsg pre, code {
    font:115% monospace;
    *font-size:100%;
  }

  #ygrp-mlmsg * {
    line-height: 1.22em;
  }

  #ygrp-mlmsg #logo {
    padding-bottom: 10px;
  }

  #ygrp-mlmsg a {
    color: #1E66AE;
  }

  #ygrp-msg p a {
    font-family: Verdana;
  }

  #ygrp-msg p#attach-count span {
    color: #1E66AE;
    font-weight: 700;
  }

  #ygrp-reco #reco-head {
    color: #ff7900;
    font-weight: 700;
  }

  #ygrp-reco {
    margin-bottom: 20px;
    padding: 0px;
  }

  #ygrp-sponsor #ov li a {
    font-size: 130%;
    text-decoration: none;
  }

  #ygrp-sponsor #ov li {
    font-size: 77%;
    list-style-type: square;
    padding: 6px 0;
  } 

  #ygrp-sponsor #ov ul {
    margin: 0;
    padding: 0 0 0 8px;
  }

  #ygrp-text {
    font-family: Georgia;
  }

  #ygrp-text p {
    margin: 0 0 1em 0;
  }

  #ygrp-text tt {
    font-size: 120%;
  }

  #ygrp-vital ul li:last-child {
    border-right: none !important; 
  } 
  -->
  </style>
</head>

<!--~-|**|PrettyHtmlEnd|**|-~-->
</html>
<!-- end group email -->


--2fsKsQxMTGrzz7eRPrXBaGM9ZmH6rcSYtW1tXUR--