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"> </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> - "Keep it simple, stupid" - 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->one($<wbr>args);<br>
$self->two($<wbr>args);<br>
$self->three(<wbr>$args);<br>
<br>
# Return nothing because this is a procedure<br>
return;<br>
}<br>
<br>
Becomes something like<br>
<br>
<<<<<<<<<<<<br>
__PACKAGE__-<wbr>>add_seq_<wbr>func( [ "myfunc" ] );<br>
<br>
sub _myfunc__list<br>
{<br>
return [ "one", "two", "three", ];<br>
}<br>
>>>>>>>>>>><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>
<<<<<<<<<<<<<wbr><<<<<<<<br>
<br>
$self->_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([^\<\[\<wbr>]\&]*)}cgms;<br>
<br>
>>>>>>>>>>>><wbr>>>>>>>><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>
<<<<<<<<<<<<<wbr><<<<<<<br>
my $l = $self->_curr_<wbr>line_ref(<wbr>);<br>
<br>
# Do something with ${$l} and be happy.<br>
>>>>>>>>>>>><wbr>>>>>>><br>
<br>
Arguably, I now have duplicate "my $l = $self->_curr_<wbr>line_ref(<wbr>);" 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 "patterns" 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> • <a href="mailto:[email protected]?subject=Unsubscribe" style="text-decoration: none;">Unsubscribe</a> • <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--