<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8648268364549955959</id><updated>2011-11-25T13:05:53.661Z</updated><category term='acceptance testing'/><category term='ruby'/><category term='wikileaks'/><category term='google wave'/><category term='continuous integration'/><category term='literate programming'/><category term='domain-driven design'/><category term='java'/><category term='refactoring'/><category term='aesthetics'/><category term='metaphor'/><category term='C'/><category term='collaboration'/><category term='politics'/><category term='peer to peer'/><category term='philosophy'/><category term='mythology'/><category term='humanities'/><category term='user stories'/><category term='prolog'/><category term='rest'/><category term='literature'/><category term='continuous delivery'/><category term='accessibility'/><category term='agile'/><category term='hacks'/><category term='clean code'/><category term='haskell'/><category term='software engineering'/><category term='religion'/><category term='kanban'/><category term='mathematics'/><category term='unit testing'/><category term='email'/><category term='design'/><category term='tdd'/><category term='standards'/><category term='code reuse'/><category term='toyota production system'/><category term='testing'/><category term='architecture'/><category term='programming languages'/><category term='7languages7weeks'/><category term='xp'/><category term='science'/><category term='estimation'/><title type='text'>the literate programmer</title><subtitle type='html'>"Let us concentrate on explaining to human beings what we want a computer to do"</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>42</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-4892968408428699545</id><published>2011-11-25T13:05:00.000Z</published><updated>2011-11-25T13:05:53.668Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='acceptance testing'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='religion'/><category scheme='http://www.blogger.com/atom/ns#' term='domain-driven design'/><title type='text'>Overlapping magisteria</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I've written that &lt;a href="http://literateprogrammer.blogspot.com/2011/05/tdd-is-from-venus-bdd-is-from-mars.html"&gt;unit tests and acceptance tests represent two non-overlapping magisteria&lt;/a&gt;. I've realised I need to revise this.&lt;br /&gt;&lt;br /&gt;Unit tests and acceptance tests specify internal and external behaviour respectively. There is no inherent reason why external behaviour should be trivially translatable to internal behaviour, because the structure of the internals need not bear any&amp;nbsp;resemblance&amp;nbsp;to the model the system presents to the world.&lt;br /&gt;&lt;br /&gt;However, that is only true of systems in general. Systems produced using a domain-driven design methodology deliberately enforce structural similarity between the system's implementation and the domain it represents.&lt;br /&gt;&lt;br /&gt;Because of this, it's possible to make inferences between external and internal properties of the system. For example, if a &lt;pre&gt;LoginFailure&lt;/pre&gt;object returns &lt;pre&gt;true&lt;/pre&gt;to the method &lt;pre&gt;shouldLockAccount()&lt;/pre&gt;when its &lt;pre&gt;int&lt;/pre&gt;field called &lt;pre&gt;previousAttempts&lt;/pre&gt;is &lt;pre&gt;2&lt;/pre&gt;or greater, there's a good chance that if a user thrice enters the wrong password that their account will be disabled.&lt;br /&gt;&lt;br /&gt;If we know something about a well-designed system's external behaviour, we can generally extrapolate about its internal behaviour (and vice-versa).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-4892968408428699545?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/4892968408428699545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/11/overlapping-magisteria.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4892968408428699545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4892968408428699545'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/11/overlapping-magisteria.html' title='Overlapping magisteria'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7352071121107437125</id><published>2011-11-14T13:00:00.002Z</published><updated>2011-11-19T07:12:17.406Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='continuous delivery'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Continuous receipt - sacrificing versions</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Last week I received an email that convinced me that the way we think about versioning has&amp;nbsp;irrevocably&lt;br /&gt;changed. Here is the meat of the mail:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;IntelliJ's Perforce plugin now has job support.&lt;/i&gt;&lt;/blockquote&gt;While this is a valuable feature for me in my current project, it's hardly a major event for software in&amp;nbsp;general.&lt;br /&gt;&lt;br /&gt;What struck me was the author's implicit assumption that IntelliJ is a single continuous entity that changes&amp;nbsp;state. IntelliJ "now" behaves differently to what it did a month ago.&lt;br /&gt;&lt;br /&gt;To a user, "IntelliJ" is becoming less a description of an immutable executable than the name of an evolving&amp;nbsp;organism of features. Whereas once we spoke of the 2010 incarnation of a product verses the 2011 product,&amp;nbsp;soon we will speak of how a piece of software behaved in 2012 compared to 2013.&lt;br /&gt;&lt;br /&gt;Web applications like Facebook, Twitter and Gmail have been doing this for some time. It's becoming the norm&amp;nbsp;for desktop apps too.&lt;br /&gt;&lt;br /&gt;The frantic pace of continuously delivered versions is obliterating the end-user's concept of a version&amp;nbsp;altogether. Where previously we expected to pull new features by explicitly choosing to upgrade, we now&amp;nbsp;accept that our software will frequently be pushed changes - almost in real time.&lt;br /&gt;&lt;br /&gt;This large number of minutely differing versions is similar to how animation generates the illusion of&amp;nbsp;motion. The more frequent the changes, the smoother the effect. As video games have increased their&amp;nbsp;frame-rates they have made older games look clunky and awkward by comparison. Publishing games with 1995's&amp;nbsp;industry standard frame-rate would put a studio at a serious competitive disadvantage today.&lt;br /&gt;&lt;br /&gt;Developers who are unable to embrace the concepts of &lt;a href="http://continuousdelivery.com/"&gt;continuous delivery&lt;/a&gt; will find users perceive their&amp;nbsp;software in much the same way.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7352071121107437125?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7352071121107437125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/11/continuous-receipt-sacrificing-versions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7352071121107437125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7352071121107437125'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/11/continuous-receipt-sacrificing-versions.html' title='Continuous receipt - sacrificing versions'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-6347578555572525375</id><published>2011-08-21T19:35:00.000+01:00</published><updated>2011-08-21T19:35:22.312+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='programming languages'/><category scheme='http://www.blogger.com/atom/ns#' term='7languages7weeks'/><title type='text'>Designing Haskell</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;The other day I was struggling through quirk of &lt;a href="http://www.java.com/"&gt;Java&lt;/a&gt;'s generics (which are implemented with &lt;a href="http://download.oracle.com/javase/tutorial/java/generics/erasure.html"&gt;type erasure&lt;/a&gt;). I pondered that it would have been wonderful if generics had been properly baked into Java from the start instead of being superficially retrofitted.&lt;br /&gt;&lt;br /&gt;While I'm strengthening Java's type system, I thought, I should wish for &lt;a href="http://en.wikipedia.org/wiki/Type_inference"&gt;type inference&lt;/a&gt; to cut out all those redundant type annotations. And if I'm going to do that, I might as well ask for &lt;a href="http://openjdk.java.net/projects/lambda/"&gt;closures&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Of course, some of the worst things about Java are awkward and commonly misused features, like &lt;a href="http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake"&gt;nullability&lt;/a&gt;. I occasionally use it myself, but I'd prefer it if there were an alternative. And I'd gladly give up mutability, primitive types and implementation inheritance if only every other Java programmer had to give them up too.&lt;br /&gt;&lt;br /&gt;But, I considered, would I just be imposing my personal taste on others? I mean, I like significant whitespace, but I know some other programmers inexplicably prefer curly braces.&lt;br /&gt;&lt;br /&gt;If only there were already &lt;a href="http://www.haskell.org/"&gt;a magical programming language&lt;/a&gt; like this that I could switch to without disturbing the Java developers who are happy with things the way they are.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-6347578555572525375?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/6347578555572525375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/08/designing-haskell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6347578555572525375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6347578555572525375'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/08/designing-haskell.html' title='Designing Haskell'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7885942785957969058</id><published>2011-08-19T13:47:00.000+01:00</published><updated>2011-08-19T13:47:00.385+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><title type='text'>Eco on over-engineering</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt; This triumph of the mechanism produced a kind of giddiness, whereby the importance attached to what the machine actually produced was less than that attached to the extravagance of the mechanical resources required to produce it, and frequently many of these machines displayed a wholly disproportionate relationship between the simplicity of the effect they produced and the highly sophisticated means required to obtain it.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Umberto Eco, &lt;a href="http://www.amazon.co.uk/Beauty-History-Western-Idea/dp/0436205173"&gt;&lt;span style="font-style: italic;"&gt;On Beauty: A History of a Western Idea&lt;/span&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7885942785957969058?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7885942785957969058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/08/eco-on-over-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7885942785957969058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7885942785957969058'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/08/eco-on-over-engineering.html' title='Eco on over-engineering'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8721649174927200738</id><published>2011-07-13T17:13:00.000+01:00</published><updated>2011-07-13T17:13:55.303+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='toyota production system'/><category scheme='http://www.blogger.com/atom/ns#' term='estimation'/><category scheme='http://www.blogger.com/atom/ns#' term='mythology'/><title type='text'>Procrustean sizing</title><content type='html'>Conventional agile estimation involves assigning story points based on  the relative size of each piece of work. Most teams refuse to accept  stories whose size falls outside a certain limit and send them back for  further analysis. Teams using Procrustean sizing take this to the  extreme and only accept stories of a single, fixed size.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Procrustes"&gt;Procrustes&lt;/a&gt; was mythical ancient Greek bandit whose speciality was capturing unwary travellers and making them fit his iron bed. If they were too short, he would stretch them. If they were too tall, he would cut off an appropriate section of their legs.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Procrustean &lt;/i&gt;has come to describe the coercion of data into an arbitrary container or structure. The term is often used perjoratively to refer to a simplistic, one-size-fits all approaches.&lt;br /&gt;&lt;br /&gt;However, I believe that a Procrustean story sizing is a viable technique for teams using &lt;a href="http://en.wikipedia.org/wiki/Kanban_%28development%29"&gt;kanban&lt;/a&gt; to manage their work. Limiting all stories to a pre-determined size places extra restrictions on story formation but it provides stronger assurances about how work and value will flow through your team.&lt;br /&gt;&lt;br /&gt;When all stories are of the same size it becomes easier to reason about the backlog as a whole. Adding up stories of different sizes is dangerous because teams sometimes have a tendency to over or under-estimate differently for larger stories. An eight point story might take more or less than four times as long as a two-pointer when there is not a strictly linear relationship between story points and effort.&lt;br /&gt;&lt;br /&gt;This effect is stronger with greater variability. Some teams avoid the temptation to add up stories of different sizes by &lt;a href="http://blog.risingtideharbor.com/2011/05/woodland-creature-story-sizing.html"&gt;estimating in animals&lt;/a&gt; or some other arbitrary non-numeric scale. However, when there is only one size this complication is avoided and calculations of the total size of the backlog become more reliable.&lt;br /&gt;&lt;br /&gt;More importantly, limiting variability helps to maintain a constant flow. &lt;a href="http://en.wikipedia.org/wiki/Production_leveling"&gt;Production levelling&lt;/a&gt; (as described by &lt;a href="http://en.wikipedia.org/wiki/Taiichi_Ohno"&gt;Taiichi Ohno&lt;/a&gt; in his account of the &lt;a href="http://www.amazon.co.uk/Toyota-Production-System-Beyond-Large-scale/dp/0915299143"&gt;Toyota Production System&lt;/a&gt;) is essential for reducing waste because it ensures that all parts of the pipeline recieve work at a rate they can handle. Uneven flow (&lt;a href="http://en.wikipedia.org/wiki/Mura_%28Japanese_term%29"&gt;mura&lt;/a&gt;) results in work building up in some areas while other areas are forced to remain idle and disrupts feedback.&lt;br /&gt;&lt;br /&gt;Setting limits on &lt;a href="http://en.wikipedia.org/wiki/Work_in_process"&gt;work-in-progress&lt;/a&gt; (WIP) is also simpler when there is no distinction between points and stories. A WIP limit of story points can mean that there are too few stories in development to usefully work on in parallel, but a WIP limit of stories can allow too much work to be in progress at once if large stories are in development. When there is too much WIP, it takes longer for problems to show. Also, it becomes difficult to change priorities because expedited stories are blocked by large pieces of work already in progress.&lt;br /&gt;&lt;br /&gt;The most obvious disadvantage of the technique is that stories may need to be divided, even when the product owner envisages them as a single unit. This is a problem for any team that does not accept stories of an unlimited magnitude, but it happens more frequently when using Procrustean sizing.&lt;br /&gt;&lt;br /&gt;Adopting Procrustean sizing is a tradeoff. If reliable flow is more important than the narrative integrity of stories, then it can assist a team's development process. If preserving stories in the form that product owners originally imagined them is important for communicating with stakeholders, then levelling your stories may not be good option.&lt;br /&gt;&lt;br /&gt;Procrustean sizing forces teams to organise plan stories in the form that they can most easily be worked on. It's the software equivalent of Ohno's advice to reduce batch size in manufacturing and, like reducing batch size, takes discipline and effort. Procrustean sizing is a simple constraint, but kanban has already demonstrated the value and power of simple constraints correctly applied.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NB: I have not used this technique in its pure form on a real project. This post is intended as an &lt;a href="http://en.wikipedia.org/wiki/Request_for_Comments"&gt;RFC&lt;/a&gt; and exposition of the Procrustean sizing concept. I would be very interested in hearing others' experiences with this or similar ideas.&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8721649174927200738?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8721649174927200738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/07/procrustean-sizing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8721649174927200738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8721649174927200738'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/07/procrustean-sizing.html' title='Procrustean sizing'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-9073320769739705643</id><published>2011-06-18T19:03:00.001+01:00</published><updated>2011-06-18T22:16:17.064+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming languages'/><category scheme='http://www.blogger.com/atom/ns#' term='7languages7weeks'/><title type='text'>gets gets my goat</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I'm participating in a virtual study group on the book &lt;a href="http://pragprog.com/titles/btlang/seven-languages-in-seven-weeks"&gt;Seven languages in seven weeks&lt;/a&gt;. The first week has been on &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;, which has been a liberating and and frictionless experience - except for one glitch.&lt;br /&gt;&lt;br /&gt;One of the exercises in the book involves writing a primitive grep in Ruby. This program reads text line-by-line from &lt;a href="http://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29"&gt;stdin&lt;/a&gt; and echos the lines that contain a fragment specified as a command-line argument.&lt;br /&gt;&lt;br /&gt;My first attempt looked something like this:&lt;br /&gt;&lt;pre&gt;#!/usr/bin/ruby &lt;br /&gt;while line = gets&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; puts line if line.match ARGV[0]&lt;br /&gt;end &lt;br /&gt;&lt;/pre&gt;But when I tried to run it...&lt;br /&gt;&lt;pre&gt;&amp;gt; ./grep.rb foo&lt;/pre&gt;&lt;pre&gt;./grep.rb:3:in `gets': No such file or directory - foo (Errno::ENOENT)&lt;br /&gt; from ./grep.rb:3&lt;br /&gt;&lt;/pre&gt;After a lot of head-scratching, I finally figured out that gets behaves differently if there are command-line arguments. From &lt;a href="http://www.ruby-doc.org/core/classes/Kernel.html#M001404"&gt;the Ruby documentation on gets&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Returns (and assigns to $_) the next line from the list of files in ARGV (or $*), or from standard input if no files are present on the command line.&lt;/blockquote&gt;So, I actually needed to do this:&lt;br /&gt;&lt;pre&gt;#!/usr/bin/ruby &lt;br /&gt;while line = &lt;b&gt;STDIN&lt;/b&gt;.gets&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; puts line if line.match ARGV[0]&lt;br /&gt;end &lt;/pre&gt;After becoming a little frustrated at this seemingly inexplicable overloading of gets, I took a moment to think about why it bothered me so much.&lt;br /&gt;&lt;br /&gt;One benefit that Ruby advocates often cite about the language is its &lt;a href="http://www.artima.com/intv/ruby4.html"&gt;adherence to the Principle of Least Surprise&lt;/a&gt;. So in the case of this particular unpleasant surprise, I felt cheated.&lt;br /&gt;&lt;br /&gt;But then I realised that the strength of my reaction was a backhanded compliment to Ruby. The gets incident stuck in my mind only because it contrasts so strongly with the rest of my experience of Ruby as a consistent and well-designed programming language.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-9073320769739705643?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/9073320769739705643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/06/gets-gets-my-goat.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/9073320769739705643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/9073320769739705643'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/06/gets-gets-my-goat.html' title='gets gets my goat'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-3605750549046365764</id><published>2011-06-11T19:33:00.000+01:00</published><updated>2011-06-11T19:33:57.913+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile teams need the same skills</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;There is occasionally anxiety about how project managers, business analysts, QAs and other traditional roles fit into agile projects. A project manager new to agile development might feel that their skills and experience aren't valued because they don't see their old job title explicitly mentioned in a description of an agile team.&lt;br /&gt;&lt;br /&gt;Agile schedules still need to be managed. Agile requirements still need to be analysed. Agile codebases still need to be tested. The difference is that agile teams don't assume that these activities have to be done by dedicated team members.&lt;br /&gt;&lt;br /&gt;A cross-functional team needs a wide variety of skills to succeed. Sometimes these will be provided by specialists and sometimes by generalists. The balance has to be struck for the specific needs of a project and can't be determined by a crude, one-fits-all rule.&lt;br /&gt;&lt;br /&gt;Though agile is a great step forward in software development, it would be arrogant and unfair to think that there is no place in agile teams for software professionals that happen to come from traditionally structured organisations.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-3605750549046365764?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/3605750549046365764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/06/agile-teams-need-same-skills.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/3605750549046365764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/3605750549046365764'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/06/agile-teams-need-same-skills.html' title='Agile teams need the same skills'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7906645643249257995</id><published>2011-05-30T13:00:00.000+01:00</published><updated>2011-05-30T12:59:47.972+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Elastic teams absorb shocks</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I've come across the idea that because cross-functional teams need a variety of skills, members of the team should aspire to be generalists. I think that is overstating the case somewhat.&lt;br /&gt;&lt;br /&gt;Agile teams need to be able to handle workloads requiring varying mixtures of skillsets. In order to cope, teams need &lt;i&gt;elasticity&lt;/i&gt;, that is they need to be able to temporarily boost their capacity in a particular kind of work as the situation requires.&lt;br /&gt;&lt;br /&gt;This can be better achieved by a mixture of flexibility and focus than by either radical specialisation or radical generalisation.&lt;br /&gt;&lt;br /&gt;Specialisation has the obvious drawback that if the specialist in a given area is at full capacity the team cannot take on any more of this kind of work. This leads to the situation where some team members aren't fully utilised but the team cannot commit to taking any more stories to "done done" in the current iteration.&lt;br /&gt;&lt;br /&gt;Total generalisation doesn't produce idle team members, but it does prevent a team from reaching its maximum possible potential. Software development is full of difficult and technically-specific problems that may not be understood by someone who has not deeply immersed themselves in that discipline. Furthermore, it's hard for someone who isn't fully comfortable with a domain to coordinate others at the same level.&lt;br /&gt;&lt;br /&gt;I prefer teams where there is an expert ready to take charge in the face of any given challenge and who can rely on the rest of the team to fall in behind them. This happens best when team members are specialists in their own discipline and generalists in everything else.&lt;br /&gt;&lt;br /&gt;To return to the metaphor in the title of this post, effective agile teams have a definite shape but they have enough elasticity to absorb the shocks of atypical workloads.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7906645643249257995?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7906645643249257995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/elastic-teams-absorb-shocks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7906645643249257995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7906645643249257995'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/elastic-teams-absorb-shocks.html' title='Elastic teams absorb shocks'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-2120581254458774596</id><published>2011-05-18T15:04:00.001+01:00</published><updated>2011-05-19T09:00:38.915+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><category scheme='http://www.blogger.com/atom/ns#' term='domain-driven design'/><title type='text'>Domain-driven teams</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I just watched &lt;a href="http://fragmental.tw/"&gt;Phil&lt;/a&gt; present on why &lt;a href="http://fragmental.tw/2010/09/12/thoughtworks-australia-teamhug-2010-why-enterprise-architectures-suck/"&gt;enterprise architecture usually sucks&lt;/a&gt;, and it struck me that his talk resembled a formal argument:&lt;br /&gt;&lt;ol style="text-align: left;"&gt;&lt;li&gt;Design always reflects team structure (&lt;a href="http://en.wikipedia.org/wiki/Conway%27s_Law"&gt;Conway's law&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Design should reflect the business domain (&lt;a href="http://domaindrivendesign.org/resources/what_is_ddd"&gt;Domain-driven design&lt;/a&gt;)&lt;/li&gt;&lt;/ol&gt;It seems to me that the following conclusion is inevitable:&lt;br /&gt;&lt;ol start="3" style="text-align: left;"&gt;&lt;li&gt;&lt;b&gt;Therefore, team structure should reflect the business domain&lt;/b&gt;&lt;/li&gt;&lt;/ol&gt;Logically, Phil's maxim that "what’s easy to change in the business model should be easy to change in your architecture" can only be achieved by structuring teams around domain concepts and avoiding cross-cutting concerns.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-2120581254458774596?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/2120581254458774596/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/domain-driven-teams.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2120581254458774596'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2120581254458774596'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/domain-driven-teams.html' title='Domain-driven teams'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-6554164096954972234</id><published>2011-05-15T15:58:00.000+01:00</published><updated>2011-05-15T15:58:41.485+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='programming languages'/><title type='text'>Declarative management</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Broadly speaking, programming languages can be categorised as either &lt;i&gt;imperative &lt;/i&gt;or &lt;i&gt;declarative&lt;/i&gt;. This post will explain the difference, and also argue that a declarative approach to management leads to better outcomes.&lt;br /&gt;&lt;h2&gt;Imperative programming&lt;/h2&gt;Imperative programs are lists of commands. Here is a piece of &lt;a href="http://en.wikipedia.org/wiki/C_%28programming_language%29"&gt;C&lt;/a&gt; code that tells the computer how to make a meal based on a recipe. Get a bowl, start at the first ingredient, add and mix ingredients one at a time and stop when there are none left:&lt;br /&gt;&lt;pre&gt;Bowl make_recipe(char** ingredients, int num_ingredients)&lt;br /&gt;{&lt;br /&gt;  int bowl_size = number_of_ingredients / 3;&lt;br /&gt;  Bowl bowl = fetch_bowl(bowl_size);&lt;br /&gt;&lt;br /&gt;  for(int i=0; i &amp;amp;lt; number_of_ingredients; i++)&lt;br /&gt;  {&lt;br /&gt;    add_ingredient(ingredient_list[i], bowl);&lt;br /&gt;    mix(bowl);&lt;br /&gt;  }&lt;br /&gt;  return bowl;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;For some recipes it doesn't matter what order ingredients are added. It wouldn't make a whole lot of difference to your pancakes batter if you add the milk before the eggs or the other way around. But this code doesn't trust the computer to decide when rearranging ingredients is safe; they must be added in the exact order that they appear on the list.&lt;br /&gt;&lt;h2&gt;Declarative programming&lt;/h2&gt;&lt;a href="http://en.wikipedia.org/wiki/Prolog"&gt;Prolog&lt;/a&gt; is a kind of declarative language known as a logic programming language. I write Prolog code by declaring facts (Susan is Mark's parent) and rules (a grandparent is a parent of a parent):  &lt;br /&gt;&lt;pre class="Prolog" name="code"&gt;parent(susan, mark).&lt;br /&gt;parent(gerald, susan).&lt;br /&gt;&lt;br /&gt;grandparent(X, Z) :- parent(X, Y), parent(Y, Z).&lt;/pre&gt;&lt;pre class="Prolog" name="code"&gt;&lt;/pre&gt;I can now ask Prolog questions based on these declarations:  &lt;br /&gt;&lt;pre&gt;| ?- grandparent(gerald, mark).&lt;br /&gt;Yes&lt;/pre&gt;&lt;pre&gt;| ?- grandparent(mark, susan).&lt;br /&gt;No&lt;br /&gt;&lt;/pre&gt;I didn't describe how to arrive at those answers. I merely provided the necessary information and left the rest up to Prolog. If someone changes details in Prolog's algorithm it won't affect my program so long as it continues to interpret facts and rules in the same way.  There are many different kinds of declarative programming language but they all focus on &lt;i&gt;what &lt;/i&gt;needs to be achieved and leave the &lt;i&gt;how &lt;/i&gt;to the implementors' discretion. &lt;br /&gt;&lt;h2&gt;Declarative management&lt;/h2&gt;Declarative management describes the desired outcome but give the team freedom to achieve it in the way that appears best to them. One way that we encourage this on agile projects is &lt;a href="http://blog.mountaingoatsoftware.com/advantages-of-the-as-a-user-i-want-user-story-template"&gt;to make sure that all our stories have a "so that" clause that explains their intent&lt;/a&gt;. This allows requirements to be much more concise, because we concentrate on the things that matter - in other words the &lt;i&gt;what&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;If the story says "As a user, I want the system to know my favourite colour, so that the site can be personalised to suite my aesthetic taste", then the team are free to bring their expertise on the problem. The solution they come up with might even surprise the person who originally came up with the story. In the agile world, we call this "delighting the customer".&lt;br /&gt;&lt;br /&gt;On the other hand, imperative management is very specific about exactly &lt;i&gt;how &lt;/i&gt;the things must be done. To follow the recipe example above, workers in a fast-food chain might be given exact steps on how to put together a hamburger.&lt;br /&gt;&lt;br /&gt;There is a place for both imperative and declarative programming. Declarative programming is a good choice when it's important to make intent very clear or when the computer is in a position to make better optimisations than the programmer. Imperative languages are often the only sensible choice when the &lt;i&gt;how &lt;/i&gt;needs to be tightly controlled e.g. to ensure high performance in a video game. &lt;br /&gt;&lt;br /&gt;However, there is very little justification for imperative management. The only time that its helpful to give a team the &lt;i&gt;how &lt;/i&gt;is when you believe that they would come up with a worse solution than you. If you think that's true, you're probably either wrong or you haven't properly trained your team.&lt;br /&gt;&lt;br /&gt;I'm sure there are rare cases when imperative management can help the business. In the fast food example, the fastest possible way to assemble a burger might not be independently arrived at by every part-time employee. Just like a C++ programmer might use her detailed understanding of a PS3's hardware to force it to behave in a certain way, central management might find it advantageous to promulgate an optimised burger production process that's faster than what employees could come up with themselves. But as a general rule this doesn't happen, because while computers are naive and unable to show initiative, your employees are not.&lt;br /&gt;&lt;br /&gt;Imperative management is micromanagement. Declarative management is empowerment. And since your employees are (hopefully) better at their jobs than you are, empowerment is more likely to achieve the results you are after.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-6554164096954972234?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/6554164096954972234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/declarative-management.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6554164096954972234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6554164096954972234'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/05/declarative-management.html' title='Declarative management'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8582304655195816681</id><published>2011-04-14T12:27:00.000+01:00</published><updated>2011-04-14T12:27:13.548+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>The waterfall mindset</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Some developers are reluctant to delete code.&amp;nbsp;If I understand their logic correctly, it goes something like this:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Writing code takes effort. Therefore, removing code means wasted effort.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This relies on two fallacies.&lt;br /&gt;&lt;br /&gt;Firstly, it assumes that code is valuable in of itself. But code is a liability, not an asset. Removing code while maintaining functionality creates value because it improves agility without costing anything that stakeholders care about.&lt;br /&gt;&lt;br /&gt;Secondly, it assumes that code/functionality is the only purpose of development. But agile practitioners use development as a way of gaining information. So even if a change is fully backed-out and never restored, the process of developing that change yielded an improved understanding of the solution space.&lt;br /&gt;&lt;br /&gt;I realise that deconstructing fallacies is somewhat of a fallacy itself. Counterproductive practices are more likely to be driven by psychological factors than by logical errors. In this case,&amp;nbsp;I think that a reluctance to delete code is motivated by an attitude I call the waterfall mindset.&lt;br /&gt;&lt;br /&gt;Within the waterfall mindset, coding proceeds through a series of decisions that are never revisited once made. It's very similar to a sequential development process, except that the phases can be in the mind of a single developer. Like normal waterfall development, it relies on the supremely unlikely possibility of getting decisions right the first time:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Generating reports is too slow? Let's cache them on the webserver.&lt;/li&gt;&lt;li&gt;Cached files are out of date? Let's write a cron job to renew them every night.&lt;/li&gt;&lt;li&gt;The webserver is under unacceptable load during the regeneration process? Let's delegate to a separate report server.&lt;/li&gt;&lt;li&gt;Report generation fails silently when there are network problems? Let's develop a custom protocol with failure semantics so that the webserver knows when to re-send messages to the report server.&lt;/li&gt;&lt;li&gt;And so on...&lt;/li&gt;&lt;/ul&gt;Or perhaps the report generation process itself could be profiled and optimised, eliminating the need for a caching mechanism altogether.&lt;br /&gt;&lt;br /&gt;When I discover developers (including myself) in the grip of waterfall coding, I'm reminded of &lt;a href="http://www.poppyfields.net/poppy/songs/oldwoman.html"&gt;the nursery rhyme about the woman who swallowed a fly&lt;/a&gt;. It didn't work out well for her either.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8582304655195816681?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8582304655195816681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/04/waterfall-mindset.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8582304655195816681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8582304655195816681'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/04/waterfall-mindset.html' title='The waterfall mindset'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1187210134340725582</id><published>2011-03-28T18:12:00.001+01:00</published><updated>2011-05-30T14:48:30.618+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='acceptance testing'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Acceptance tests make big claims</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;i&gt;If we have good acceptance tests, why do we need unit tests?&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Acceptance tests tell us a lot. When they pass, they tell us things like:&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;A feature works from an end-user perspective.&lt;/li&gt;&lt;li&gt;All the components required to serve user requests have been wired up correctly.&amp;nbsp;&lt;/li&gt;&lt;li&gt;The supporting infrastructure has been installed and configured in the test environment.&lt;/li&gt;&lt;li&gt;The user interface has not significantly changed since the acceptance tests were first written.&lt;/li&gt;&lt;li&gt;An intermittant network outage did not occur.&lt;/li&gt;&lt;/ul&gt;But when they fail, they tell us very little. They make such ambitious claims about the state of the software that failures could indicate a large number of disparate underlying issues.&lt;br /&gt;&lt;br /&gt;Unit tests, on the other hand, claim very little. If a unit test fails, it is immediately obvious that there is a problem with a very specific section of code.&lt;br /&gt;&lt;br /&gt;In general, the easier it is for a test to fail, the less it tells us when it does. Failures from tests that intermittently break for no reason at all aren't very informative. But if there's a little red dot next to that test that "couldn't possibly fail" then you've just discovered something startlingly new about your system.&lt;br /&gt;&lt;br /&gt;Relying on acceptance tests makes sense if the code-base is relatively static, because failures will be relatively rare. But software that must change to remain valuable (i.e. almost all software) also needs fine-grained unit tests to give specific and actionable feedback on failures.&lt;br /&gt;&lt;ul style="text-align: left;"&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1187210134340725582?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1187210134340725582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/acceptance-tests-make-big-claims.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1187210134340725582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1187210134340725582'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/acceptance-tests-make-big-claims.html' title='Acceptance tests make big claims'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-2472171833397356335</id><published>2011-03-20T22:05:00.000Z</published><updated>2011-03-20T22:05:34.044Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Eliot on projects without Continuous Integration</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;blockquote&gt;&lt;i&gt;What are the roots that clutch, what branches grow  &lt;/i&gt;&lt;br /&gt;&lt;i&gt;Out of this stony rubbish? Son of man, &lt;/i&gt;&lt;br /&gt;&lt;i&gt;You cannot say, or guess, for you know only  &lt;/i&gt;&lt;br /&gt;&lt;i&gt;A heap of broken images, where the sun beats,  &lt;/i&gt;&lt;br /&gt;&lt;i&gt;And the dead tree gives no shelter, the cricket no relief,  &lt;/i&gt;&lt;br /&gt;&lt;i&gt;And the dry stone no sound of water.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;- T. S. Eliot, &lt;a href="http://www.amazon.co.uk/Waste-Land-Other-Poems/dp/057109712X"&gt;The Waste Land&lt;/a&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-2472171833397356335?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/2472171833397356335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/eliot-on-projects-without-continuous.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2472171833397356335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2472171833397356335'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/eliot-on-projects-without-continuous.html' title='Eliot on projects without Continuous Integration'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-5672406811122894947</id><published>2011-03-12T12:43:00.001Z</published><updated>2011-03-13T18:38:46.154Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='user stories'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>The value of the alternative vote</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;As someone on the U.K. electoral roll, I want to give an ordered list of preferences when I vote, so that the outcome can reflect my opinion of all the candidates. However, I think the pro-A.V. campaign has made a serious mistake that compromises its chance of success at the May 5 referendum. By &lt;a href="http://www.bbc.co.uk/news/uk-politics-10729454"&gt;describing the proposed system as the "alternative vote"&lt;/a&gt; they are emphasising implementation details over the value that voters stand to gain.&lt;br /&gt;&lt;br /&gt;The alternative vote is so named because if a voter's highest ranked candidate is unable to win, &lt;a href="http://en.wikipedia.org/wiki/Instant-runoff_voting"&gt;their vote goes to their highest ranked alternative&lt;/a&gt; i.e. their next preference. In other words, the alternative vote is named after a detail of the algorithm used to resolve voters' preferences into an electorial outcome. In Australia, where the system is used to elect our equivalent of Britain's House of Commons, we refer to it as &lt;a href="http://en.wikipedia.org/wiki/Preferential_voting"&gt;preferential voting&lt;/a&gt;. Technically, A.V. is just one possible implementation of a preferential system.&lt;br /&gt;&lt;br /&gt;The value of preferential voting is that it gives voters the opportunity to express their views on all the candidates - not just their most favoured. A supporter of the Conservative party living in a seat that is dominated by Labour and the Liberal Democrats should not have to vote tactically to have a say in the outcome. Rather, they should be able to give their first preference to the Conservative candidate and use their subsequent preferences to indicate which of the other two parties they prefer.&lt;br /&gt;&lt;br /&gt;The name "preferential voting" satisfies the need of the public to know why they should vote for the new system in the referendum. The name "alternative vote" satisfies the need of electoral reform wonks to discuss the technical details of their area of expertise.&lt;br /&gt;&lt;br /&gt;On software projects, we also have the problem that the &lt;i&gt;how &lt;/i&gt;can overwhelm the &lt;i&gt;why&lt;/i&gt;. Agile software practitioners address this issue by stating requirements as &lt;a href="http://en.wikipedia.org/wiki/User_story"&gt;user stories&lt;/a&gt; which include the expected value of the proposed feature. Typically, these stories are expressed using the &lt;a href="http://blog.mountaingoatsoftware.com/advantages-of-the-as-a-user-i-want-user-story-template"&gt;As a... I want... so that... &lt;/a&gt; template. The first sentence of this post is written in this format.&lt;br /&gt;&lt;br /&gt;By choosing a name that emphasises arcane details over delivered value, &lt;a href="http://www.yestofairervotes.org/"&gt;the Yes campaign&lt;/a&gt; has jeopardised its chances of success on May 5.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-5672406811122894947?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/5672406811122894947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/value-of-alternative-vote.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/5672406811122894947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/5672406811122894947'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/value-of-alternative-vote.html' title='The value of the alternative vote'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8843006225300500919</id><published>2011-03-06T22:53:00.002Z</published><updated>2011-03-07T10:01:42.734Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Freedom of movement</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;One of the key disciplines of agile software development is avoiding &lt;a href="http://en.wikipedia.org/wiki/Big_Design_Up_Front"&gt;Big Up Front Design&lt;/a&gt;. The&amp;nbsp;conscientious XP developer will resolutely refuse to build anything that isn't required for the current iteration. Speculative code is poison to a project's agility, because it costs effort to build, effort to maintain and obscures the code that is performing useful functions. And often, as &lt;a href="http://xprogramming.com/"&gt;Ron Jeffries'&lt;/a&gt; adage goes,&amp;nbsp;&lt;a href="http://www.xprogramming.com/Practices/PracNotNeed.html"&gt;you ain't gonna need it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Quality is ensured by a kind of &lt;a href="http://en.wikipedia.org/wiki/Mathematical_induction"&gt;mathematical induction&lt;/a&gt;. The original version of the application is small, focused and well-tested, which makes it responsive to change. By writing the minimum of new code every time a new feature is added, developers ensure that the code-base never accrues excess baggage that might impede it in the future.&lt;br /&gt;&lt;br /&gt;This approach is&amp;nbsp;counter-intuitive&amp;nbsp;at first, because most people associate planning ahead with saving effort. The idea is that tackling future challenges before they arise can be cheaper. The first catch is that if a developer guesses wrongly they will have spent effort actively contaminating the project with detritus. The second catch is that the first catch happens every time.&lt;br /&gt;&lt;br /&gt;However, I do not take this to mean that a developer should never look ahead when making decisions about the present. Simplicity is merely a means to an end, which is the greatest possible flexibility to take the project where it might need to go.&lt;br /&gt;&lt;br /&gt;Flexibility must be evaluated relative to the needs of the project in question. If a website is likely to be promoted to a mass audience, then preserving code quality means maintaining the option to introduce caching in a later iteration. It would be a mistake to introduce any caching logic "just in case", because performance optimisations are notoriously hard to second-guess. But it would also be a mistake to take a decision that would make caching hard or impossible to implement.&lt;br /&gt;&lt;br /&gt;The minimal solution is not the one with the least files, classes or lines of code. Minimal code makes the least possible number of assumptions about the future. Developers need to&amp;nbsp;interpret&amp;nbsp;what that means for their particular project by maintaining an awareness of upcoming requirements.&lt;br /&gt;&lt;br /&gt;Freedom of movement is only meaningful if you know what moves you might need to make.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8843006225300500919?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8843006225300500919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/freedom-of-movement.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8843006225300500919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8843006225300500919'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/03/freedom-of-movement.html' title='Freedom of movement'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1628841775166253585</id><published>2011-01-01T00:01:00.002Z</published><updated>2011-01-01T00:01:00.635Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='clean code'/><title type='text'>Clean coders are pragmatists</title><content type='html'>Every now and again, developers are faced with the choice between "doing things the right way" and "just getting it working". Those who attempt to maintain their professional standards under pressure are occasionally caricatured as idealists, clinging to a quaint notion of purity at the project's expense.&lt;br /&gt;&lt;br /&gt;The clean way is the pragmatic way almost every time. To compromise code hygiene for expediency is to believe in a world where that doesn't catch up with you. Dirty coders have an incredibly naive and demonstrably false idea of what poor quality craftsmanship does to an application over time.&lt;br /&gt;&lt;br /&gt;I've written dirty code. I've gambled on everything going right just this once. But rarely have I not regretted it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1628841775166253585?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1628841775166253585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2011/01/clean-coders-are-pragmatists.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1628841775166253585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1628841775166253585'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2011/01/clean-coders-are-pragmatists.html' title='Clean coders are pragmatists'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1562982226314423174</id><published>2010-12-14T21:41:00.000Z</published><updated>2010-12-14T21:41:15.977Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='collaboration'/><title type='text'>Coding with ghosts</title><content type='html'>Software development is one of the most intensely collaborative processes I know. But stereotypically, programming is often seen as an activity for loners.&lt;br /&gt;&lt;br /&gt;The majority of collaboration between developers is hidden because it happens across months and years. When I write code, I am working incredibly closely both with the original architect and with the future employee who hasn't graduated yet. I am communicating with people I may never meet, but also to past and future versions of myself.&lt;br /&gt;&lt;br /&gt;When I leave work, most of the collaboration that I have participated in that day hasn't even happened yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1562982226314423174?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1562982226314423174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/12/coding-with-ghosts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1562982226314423174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1562982226314423174'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/12/coding-with-ghosts.html' title='Coding with ghosts'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-6543141412536181506</id><published>2010-12-05T17:29:00.000Z</published><updated>2010-12-05T17:29:00.935Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='peer to peer'/><category scheme='http://www.blogger.com/atom/ns#' term='wikileaks'/><title type='text'>Wikileaks is Napster</title><content type='html'>Remember &lt;a href="http://en.wikipedia.org/wiki/Napster"&gt;Napster&lt;/a&gt;, the first widely successful peer-to-peer file-sharing service? In 2001, the &lt;a href="http://en.wikipedia.org/wiki/Recording_Industry_Association_of_America"&gt;Recording Industry Association of America&lt;/a&gt;&amp;nbsp;won a lawsuit that killed Napster as a free service.&lt;br /&gt;&lt;br /&gt;Lawsuits against Napster did not shut down peer-to-peer file-sharing because, like Wikileaks, Napster was&amp;nbsp;neither the source nor the ultimate destination of the information flowing through it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wikileaks.ch/"&gt;Wikileaks&lt;/a&gt;&amp;nbsp;is a peer-to-peer file-sharing service. Its current architecture is centralised, which is a weakness that it shares with Napster. But if the central node is taken out, it won't be long before a new service with a decentralised architecture springs up.&lt;br /&gt;&lt;br /&gt;The only thing that shutting down Wikileaks could possibly achieve is to make&amp;nbsp;whistle-blowing&amp;nbsp;slightly less convenient. For about a month.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-6543141412536181506?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/6543141412536181506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/12/wikileaks-is-napster.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6543141412536181506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6543141412536181506'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/12/wikileaks-is-napster.html' title='Wikileaks is Napster'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-9052766725819700188</id><published>2010-11-28T22:23:00.000Z</published><updated>2010-11-28T22:23:12.840Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Architecture is the opposite of surprise</title><content type='html'>Architects often disagree on technical matters. But there's also a surprising amount of disagreement on what software architecture actually &lt;i&gt;is&lt;/i&gt;. Here are a few definitions that I've come across:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;an abstract description of the system &lt;/li&gt;&lt;li&gt;work done by developers with the title "architect"&lt;/li&gt;&lt;li&gt;that diagram with clouds and arrows that somebody put on the network drive at the start of the project before we really knew what we were building&lt;/li&gt;&lt;li&gt;that document signed by the client at the start of the project before we really knew what we were  building&lt;/li&gt;&lt;/ul&gt;The problem with all these definitions is that they imply that systems that don't have architects don't have architectures. Any definition that can't cope with the majority of applications that have emerged without considered architectural analysis isn't very useful.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/"&gt;Martin Fowler&lt;/a&gt;'s definition is more useful and widely applicable. He suggests that software architecture is the set of &lt;a href="http://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf"&gt;“things that people perceive as hard to change.” [PDF]&lt;/a&gt; This characterisation is successful because it shifts the focus from the production to the consumption of architecture.&lt;br /&gt;&lt;br /&gt;Fowler's definition challenges &lt;a href="http://en.wikipedia.org/wiki/Intentional_fallacy"&gt;the intentional fallacy&lt;/a&gt; as it applies to software architecture, which is the idea that the meaning of a text belongs to its author. Fowler's architecture can therefore include elements that were never deliberately envisaged by an architect, which in turn lets us consider systems that never had an architect.&lt;br /&gt;&lt;br /&gt;A similar idea was advanced in the essay &lt;a href="http://www.deathoftheauthor.com/"&gt;The Death of the Author&lt;/a&gt; by the literary critic Roland Barthes:&lt;br /&gt;&lt;blockquote&gt;As soon as a fact is narrated no longer with a view to acting directly on reality but intransitively, that is to say, finally outside of any function other than that of the very practice of the symbol itself, this disconnection occurs, the voice loses its origin, the author enters into his own death, writing begins.&lt;/blockquote&gt;Substitute "architect" for "author" and "development begins" for "writing begins" and Barthes could be talking about what happens when a carefully prepared architecture document is handed over for implementation.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Claude_E._Shannon"&gt;Claude E. Shannon&lt;/a&gt;'s information theory formally analyses the consumption of texts. He measured &lt;a href="http://en.wikipedia.org/wiki/Information_entropy"&gt;the information content of written English&lt;/a&gt; by showing test subjects a truncated piece of English text and asking them to guess what letter would come next. They guessed correctly about half the time (which means that English contains roughly 1 bit of information per letter).&lt;br /&gt;&lt;br /&gt;The beauty of this experiment is that Shannon didn't need a model of his subjects' knowledge of English. All he had to do was observe was what happened when they applied that knowledge.&lt;br /&gt;&lt;br /&gt;Implicit in Shannon's experiment is the idea that English is the sum of all cues that inform speakers as to what could come next. Following his approach, I would define architecture as the sum of all cues that suggest to a developer how a feature should be implemented in a particular system.&lt;br /&gt;&lt;br /&gt;These cues can take many forms. Perhaps the arrows and clouds diagram tells a developer in which tier of the system to put a particular piece of logic. But developers are also guided by the language used by stakeholders, organisational structure and the culture of the technology stack. &lt;br /&gt;&lt;br /&gt;Under this definition, the more prescriptive a system's architecture, the less information developers need to absorb in order to understand a given feature. In other words, architecture is the opposite of surprise.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-9052766725819700188?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/9052766725819700188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/architecture-is-opposite-of-surprise.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/9052766725819700188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/9052766725819700188'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/architecture-is-opposite-of-surprise.html' title='Architecture is the opposite of surprise'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8860987033696387290</id><published>2010-11-17T19:35:00.001Z</published><updated>2011-03-20T22:02:33.436Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming languages'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><title type='text'>Russell on programming language design</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;blockquote&gt;&lt;i&gt;A good notation has a subtlety and suggestiveness which make it seem, at times, like a live teacher.&lt;/i&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;- Bertrand Russell, in the introduction to Ludwig Wittgenstein's &lt;a href="http://www.amazon.co.uk/Tractatus-Logico-Philosophicus-Routledge-Classics-Wittgenstein/dp/0415254086"&gt;&lt;i&gt;Tractatus Logico-Philosophicus&lt;/i&gt;&amp;nbsp;&lt;/a&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8860987033696387290?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8860987033696387290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/russell-on-programming-language-design.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8860987033696387290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8860987033696387290'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/russell-on-programming-language-design.html' title='Russell on programming language design'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7991114042096586329</id><published>2010-11-05T17:30:00.008Z</published><updated>2010-11-05T17:52:27.022Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='literate programming'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Communicative testing</title><content type='html'>A couple of weeks ago I proposed that &lt;a href="http://literateprogrammer.blogspot.com/2010/10/tests-are-facts-code-is-theory.html"&gt;tests could be thought of as facts that have to be 'explained' by code&lt;/a&gt;. In &lt;a href="http://literateprogrammer.blogspot.com/2010/10/tests-are-facts-code-is-theory.html?showComment=1287338490855#c3885694816612188929"&gt;a comment on that post&lt;/a&gt;, &lt;a href="http://www.blogger.com/profile/12675433085083111945" rel="nofollow"&gt;p.j. hartlieb&lt;/a&gt; pointed out that this paradigm relies high tests dependability. And &lt;a href="http://twitter.com/hlangeveld"&gt;@hlangeveld&lt;/a&gt; suggested that &lt;a href="http://bit.ly/c7dGCG"&gt;test runs should be seen as analogous to experiments&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.blogger.com/profile/12675433085083111945" rel="nofollow"&gt;p.j. hartlieb&lt;/a&gt; and &lt;a href="http://twitter.com/hlangeveld"&gt;@hlangeveld&lt;/a&gt; help drive home the point that the purpose of tests is to provide information. If your tests aren't telling you anything, they're useless.&lt;br /&gt;&lt;h2&gt;Normative tests&lt;/h2&gt;Test runs tell you whether you've finished new features and if you've broken old ones. I would call that &lt;a href="http://en.wikipedia.org/wiki/Normative#Standards_documents"&gt;&lt;i&gt;normative&lt;/i&gt;&lt;/a&gt; information, because it reports on conformance to requirements&lt;i&gt;.&lt;/i&gt; That kind of knowledge can answer questions like "Is this change ready to commit?" or "Can we go live on Monday?".&lt;br /&gt;&lt;br /&gt;Management love normative information because it helps them make decisions and measure progress. This naturally leads to an over-emphasis on tests' role as a source of normative information.&lt;br /&gt;&lt;h2&gt;Informative tests&lt;/h2&gt;Good tests are also be &lt;i&gt;informative. &lt;/i&gt;They explain the meaning of failures and communicate intent. Tests can serve as alternative requirements documentation. Indeed, systems like &lt;a href="http://fitnesse.org/"&gt;Fitnesse&lt;/a&gt; unify the two concepts by converting requirements into executable acceptance tests.&lt;br /&gt;&lt;br /&gt;The audience for informative tests is almost exclusively the development team. Informative tests provide an intimate perspective on the system's concepts that's necessary to work with the software on a daily basis. This is not information required by management, so the impetus to improve the tests' informative qualities needs to come from the development team themselves.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; system test that reports failure by dumping a raw exception stacktrace serves its normative function perfectly well. There has been a regression. We are not ready to release. Someone tell management so that they can manage the client's expectations. From &lt;a href="http://code.google.com/p/selenium/issues/detail?id=658"&gt;Issue 658&lt;/a&gt; in the Selenium bug tracker:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be clicked&lt;br /&gt;System info: os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.6.1', java.version: '1.6.0_15'&lt;br /&gt;Driver info: driver.version: remote&lt;br /&gt; at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)&lt;br /&gt; at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)&lt;br /&gt; at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)&lt;br /&gt; at java.lang.reflect.Constructor.newInstance(Constructor.java:513)&lt;br /&gt; at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:94)&lt;br /&gt; at org.openqa.selenium.remote.&lt;a href="http://code.google.com/p/selenium/wiki/RemoteWebDriver" title="Information about the RemoteWebDriver"&gt;RemoteWebDriver&lt;/a&gt;.execute(&lt;a href="http://code.google.com/p/selenium/wiki/RemoteWebDriver" title="Information about the RemoteWebDriver"&gt;RemoteWebDriver&lt;/a&gt;.java:327)&lt;br /&gt; at org.openqa.selenium.firefox.&lt;a href="http://code.google.com/p/selenium/wiki/FirefoxDriver" title="Information about the Firefox Driver"&gt;FirefoxDriver&lt;/a&gt;.execute(&lt;a href="http://code.google.com/p/selenium/wiki/FirefoxDriver" title="Information about the Firefox Driver"&gt;FirefoxDriver&lt;/a&gt;.java:191)&lt;br /&gt; at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:186)&lt;br /&gt; at org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:55)&lt;br /&gt; at org.openqa.selenium.internal.seleniumemulation.Click.handleSeleneseCommand(Click.java:33)&lt;br /&gt; at org.openqa.selenium.internal.seleniumemulation.Click.handleSeleneseCommand(Click.java:23)&lt;br /&gt; at org.openqa.selenium.internal.seleniumemulation.SeleneseCommand.apply(SeleneseCommand.java:30)&lt;br /&gt; at org.openqa.selenium.WebDriverCommandProcessor$1.call(WebDriverCommandProcessor.java:271)&lt;br /&gt; at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)&lt;br /&gt; at java.util.concurrent.FutureTask.run(FutureTask.java:138)&lt;br /&gt; at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)&lt;br /&gt; at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)&lt;br /&gt; at java.lang.Thread.run(Thread.java:637)&lt;/pre&gt;&lt;br /&gt;If this was all that appeared in your test log, it would be very difficult to interpret the failure. There is no context. It's not apparent what functionality the user has lost, whether the error was handled gracefully or even if the problem is a conflict between user stories.&lt;br /&gt;&lt;br /&gt;One way to make the result above more informative would be to catch the exception and log a message like "Error when an administrator attempted to reactivate a blocked account". Product owners don't care about the presence of divs. They care about functionality.&lt;br /&gt;&lt;h2&gt;Communicative tests&lt;/h2&gt;Testing consumes a lot of effort. The return for that investment is readily available information on the state of the software. The more useful and accessible that information is, the more valuable the tests are.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www-cs-faculty.stanford.edu/~uno/"&gt;Donald Knuth&lt;/a&gt;'s description of &lt;a href="http://www.literateprogramming.com/"&gt;literate programming&lt;/a&gt; is even more pertinent to testers than other programmers because the &lt;i&gt;only&lt;/i&gt; purpose of tests is "explaining to human beings what we want a computer to do."&lt;br /&gt;&lt;br /&gt;Blunt quantitative statements are sufficient to communicate normative information to people outside the development team. But to fulfill their potential within the team, test results must be qualitative, explanatory and &lt;i&gt;communicative&lt;/i&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7991114042096586329?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7991114042096586329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/communicative-testing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7991114042096586329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7991114042096586329'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/11/communicative-testing.html' title='Communicative testing'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8280499454830983739</id><published>2010-10-29T21:11:00.000+01:00</published><updated>2010-10-29T21:11:17.545+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='metaphor'/><title type='text'>Against technical debt</title><content type='html'>&lt;i&gt;Technical debt&lt;/i&gt; is a very useful concept for explaining the consequences of dirty code to management. However, there is a problem that I have with the debt metaphor. The phrase &lt;i&gt;technical debt&lt;/i&gt; implies that it's possible to avoid the debt. If I don't write shoddy code today, I wont have to pay for it tomorrow. &lt;br /&gt;&lt;br /&gt;This obscures the fact that though dirty code costs more than &lt;a href="http://literateprogrammer.blogspot.com/2010/01/clean-code.html"&gt;clean code&lt;/a&gt;, every line of code impedes your agility. Sometimes product owners ask for features that compromise a system's architecture or domain model. When I've tried to describe the technical debt that will be incurred by an awkward feature, I've (quite reasonably) been asked how much effort it would take to "do it properly". I'm stumped, because no matter how thoroughly I implement the feature, it will still cause problems down the line.&lt;br /&gt;&lt;br /&gt;Sometimes I fall back on &lt;i&gt;depreciation&lt;/i&gt;, which I can use to explain anything that reduces the system's ability to meet future needs. Unlike debt, depreciation isn't automatically reversible. I've also considered that &lt;a href="http://literateprogrammer.blogspot.com/2010/08/fear-based-estimation.html"&gt;fear-driven estimation&lt;/a&gt; might produce estimates that more accurately reflect the long-term cost of a story.&lt;br /&gt;&lt;br /&gt;I don't want to see the technical debt analogy deprecated, but I do want to encourage people to think critically about how they use it, because all metaphors have their limits.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8280499454830983739?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8280499454830983739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/against-technical-debt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8280499454830983739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8280499454830983739'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/against-technical-debt.html' title='Against technical debt'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7460014662133041149</id><published>2010-10-24T12:50:00.001+01:00</published><updated>2010-10-24T12:53:11.587+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='user stories'/><title type='text'>As a stakeholder</title><content type='html'>A common template for user stories is &lt;a href="http://blog.mountaingoatsoftware.com/advantages-of-the-as-a-user-i-want-user-story-template"&gt;"As a user, I want"&lt;/a&gt;. This forces stakeholders to make the business value of the story explicit and encourages consistency.&lt;br /&gt;&lt;br /&gt;However, there are some stories that this doesn't make sense for, including ones that are to the business' advantage and the users' detriment. Stating all stories in terms of users' wants can result in bizarre stories that conceal who has a stake in the their completion:&lt;br /&gt;&lt;blockquote&gt;As a user, I want my DVDs to not work in other regions, so that I have to buy them again if I move countries.&lt;/blockquote&gt;As much as we focus on users, we don't build commercial software for them. It just so happens that satisfying users is a necessary part of achieving our other aims - like making money.&lt;br /&gt;&lt;br /&gt;Users are stakeholders, but they aren't the only stakeholders. If we revise the template to "As a stakeholder, I want", then we're able to state anti-user stories much more naturally:&lt;br /&gt;&lt;blockquote&gt;As the sales department, I want to prevent DVDs bought in one region from being played in another, so that I can release and price DVDs in different markets independently.&lt;/blockquote&gt;Thanks to &lt;a href="http://twitter.com/MrsSarahJones"&gt;@MrsSarahJones&lt;/a&gt; for pointing this out to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7460014662133041149?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7460014662133041149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/as-stakeholder.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7460014662133041149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7460014662133041149'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/as-stakeholder.html' title='As a stakeholder'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-6296345541030881167</id><published>2010-10-16T21:42:00.000+01:00</published><updated>2010-10-16T21:42:14.892+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><title type='text'>Tests are facts. Code is theory.</title><content type='html'>Programmers have turned to science to help resolve the software crisis. But they're doing it wrong.&lt;br /&gt;&lt;h2&gt;Science envy &lt;/h2&gt;Programmers have science envy. We feel that, unlike much of our code, &lt;a href="http://xkcd.com/54/"&gt;science works&lt;/a&gt;. Scientists have spent hundreds of years honing a &lt;a href="http://en.wikipedia.org/wiki/Scientific_method"&gt;methodology&lt;/a&gt; that helps them assimilate new knowledge and correct error, while we have spent decades frantically accumulating complexity that we can't handle. Strangely, scientific theories become more accurate over time, whereas software systems often decay.&lt;br /&gt;&lt;br /&gt;The software industry has tried to learn from science and engineering's success. We call our programming degrees &lt;a href="http://www.csse.unimelb.edu.au/"&gt;"Computer Science" and "Software Engineering"&lt;/a&gt;, though they are neither. "Computer Science" students do almost no experiments. The "Software Engineering" concept of exhaustive up-front design has become so discredited that even those who can't imagine any other way feel obliged to pretend that they "don't do &lt;a href="http://en.wikipedia.org/wiki/Waterfall_model"&gt;Waterfall&lt;/a&gt;". &lt;br /&gt;&lt;br /&gt;Of course, science and engineering are just analogies when applied to programming. They are meant to be useful ways of imagining our profession, not to be literally true. But in their naive form, I don't think analogies between programming and science are very useful. If we want to benefit from scientific rigour, we need to be more rigorous in how we appropriate scientific concepts.&lt;br /&gt;&lt;h2&gt;Scientific testing &lt;/h2&gt;Some software testers have used the scientific method as a way of framing their testing activities. For example, David Saff, Marat Boshernitsan and Michael D. Ernst explicitly cite Karl Popper and the scientific method in their &lt;a href="http://groups.csail.mit.edu/pag/pubs/testing-theories-tr002-abstract.html"&gt;paper on test theories&lt;/a&gt;. Test theories&lt;i&gt; &lt;/i&gt;are invariant properties possessed by a piece of code which Saff &lt;i&gt;et al&lt;/i&gt; attempt to falsify over a wide range of data points with an extension to the &lt;a href="http://www.junit.org/"&gt;JUnit testing framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I find the reciprocal of this approach useful when debugging. I start with a defect, form a theory as to its cause, then design a test to try and falsify that theory. If I suspect that the issue is caused by rogue javascript, I'll disable javascript and attempt to reproduce the issue. If I can, I've disproved my theory and I need to find another explanation. This helps me to eliminate false causes and gradually home in on the bug.&lt;br /&gt;&lt;br /&gt;The problem with analogies that treat tests as theories and code as a phenomena is that they tell us nothing about how to write code. The software under test is like gravity, a chemical reaction or the weather. It may or may not have an underlying structure and beauty, but any insights we gain during testing are inevitably after-the-fact.&lt;br /&gt;&lt;br /&gt;Worse, they are static models. When software changes over time, the knowledge gathered through "scientific testing" may no longer apply. The scope of scientific testing is confined to a specific version of the software. For example, a tested and verified "theory" about the memory profile of an application may become invalid when a programmer makes a small change to a caching policy.&lt;br /&gt;&lt;h2&gt;Tests are facts. Code is theory.&lt;/h2&gt;Science's strength is its ability to assimilate new discoveries. If we want to share in its success, a scientific model of software development needs to preserve science's adaptability.&lt;br /&gt;&lt;br /&gt;We can go some way to achieving this by reversing the roles of testing and coding in the scientific testing model. Tests are facts. Code's role is as a theory that explains those facts as gracefully and simply as possible.&lt;br /&gt;&lt;br /&gt;New requirements mean new tests. New tests are newly discovered facts that must be incorporated into the code's model of reality. Software can be seen as a specialised theory that attempts to embody what the stakeholders want the application to do.&lt;br /&gt;&lt;h2&gt;How does that help us?&lt;/h2&gt;Once we accept that code as a theory, we are then in a position to justify employing the most powerful weapon in science's armoury - &lt;a href="http://en.wikipedia.org/wiki/Occam%27s_razor"&gt;Occam's razor&lt;/a&gt;. Our role is to write the simplest possible code that is consistent with the facts/tests/requirements. Whenever we have the opportunity to eliminate concepts from our code, we should.&lt;br /&gt;&lt;br /&gt;Simple code isn't just cheaper. It's more valuable too, because it's easier to change and extend. We can justify this with reference to scientists' experience that the simplest theory is the most likely to survive subsequent discoveries.&lt;br /&gt;&lt;br /&gt;As new requirements arrive and our understanding of the domain deepens, we have the opportunity to &lt;a href="http://www.refactoring.com/"&gt;refactor&lt;/a&gt;. Refactoring isn't rework or throwing away effort. Refactoring is enhancing code's value by incorporating new knowledge on what we want our software to do. This could be by adding functionality, or in reducing complexity. Either makes the software as a whole more valuable.&lt;br /&gt;&lt;br /&gt;Science celebrates refactoring. Each new piece of evidence clarifies scientists' understanding of phenomena and helps yield more useful theories. Often these refinements are small, but occasionally &lt;a href="http://en.wikipedia.org/wiki/Special_relativity"&gt;Einstein will have an insight&lt;/a&gt; that supercedes &lt;a href="http://en.wikipedia.org/wiki/Newton%27s_laws_of_motion"&gt;Newton's laws of motion&lt;/a&gt;. &lt;a href="http://domaindrivendesign.org/"&gt;Domain driven design&lt;/a&gt; founder Eric Evans describes such pivotal moments on software projects as &lt;a href="http://softwareengineering.vazexqi.com/2006/10/08/ddd-breakthrough"&gt;"breakthroughs"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Non-developers often assume an application is invariably more valuable with a feature than without it. Yet the example of special relativity allows us to explain otherwise. Newton's laws of motion are perfectly adequate for ordinary use. Unless we are interested in bodies moving close to the speed of light, it's not worth bothering with the additional complexity Einstein's theories bring.&lt;br /&gt;&lt;br /&gt;If stakeholders are willing to accept that the application targets the common case and excludes troublesome edge cases, they will enjoy software that is simpler and therefore cheaper and more valuable. Sometimes, there is value in absent features. Always, there is value in simpler code.&lt;br /&gt;&lt;br /&gt;Crave simplicity. Celebrate deletion. If science responded to new information by adding special cases then science would be in as big a mess as the software industry. As you incorporate new requirements, attempt to refine your code so that it remains flexible enough to accomodate tomorrow's requirements. Otherwise, your code will become less and less fit for its purpose, which is to provide business value.&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;When &lt;a href="http://www.economist.com/research/economics/alphabetic.cfm?letter=K"&gt;John Maynard Keynes&lt;/a&gt; was attacked for repeatedly revising his economic theories, he said, "When the facts change, I change my mind – what do you do, sir?" Take the same attitude with your code, but treat requirements and tests as your facts. And remember, your code is just your best approximation of what your stakeholders want it to be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-6296345541030881167?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/6296345541030881167/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/tests-are-facts-code-is-theory.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6296345541030881167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6296345541030881167'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/tests-are-facts-code-is-theory.html' title='Tests are facts. Code is theory.'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7343428137797367142</id><published>2010-10-02T17:41:00.005+01:00</published><updated>2010-10-02T18:00:52.977+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><title type='text'>My agile canon</title><content type='html'>As much as I enjoy reading blog posts, they cannot match the sustained argument from a well-written book. Fortunately, the agile movement has many articulate advocates who have been busy committing their thoughts to paper (and eReader) over the past few years.&lt;br /&gt;&lt;br /&gt;Here are some agile books that I recommend:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.co.uk/Extreme-Programming-Explained-Embrace-Change/dp/0201616416"&gt;Extreme Programming Explained&lt;/a&gt; by &lt;a href="http://www.threeriversinstitute.org/blog/"&gt;Kent Beck&lt;/a&gt; is the original XP manifesto.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.co.uk/Art-Agile-Development-James-Shore/dp/0596527675"&gt;The Art of Agile Development&lt;/a&gt; by &lt;a href="http://jamesshore.com/Blog/"&gt;James Shore&lt;/a&gt; is a comprehensive reference for agile/XP.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt; by &lt;a href="http://blog.objectmentor.com/articles/category/uncle-bobs-blatherings"&gt;Uncle Bob&lt;/a&gt; is a detailed manual for producing high quality code, right down to variable naming.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.co.uk/Art-Unit-Testing-Examples-NET/dp/1933988274"&gt;The Art of Unit Testing (with examples in .NET)&lt;/a&gt; by &lt;a href="http://weblogs.asp.net/ROsherove/"&gt;Roy Osherove&lt;/a&gt; is the only good book I've found specifically on unit testing.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt; by &lt;a href="http://michaelfeathers.typepad.com/"&gt;Michael Feathers&lt;/a&gt; is an interesting guide to bringing legacy code under test and under control.&lt;/li&gt;&lt;li&gt;I'm currently reading &lt;a href="http://www.amazon.co.uk/Agile-Estimating-Planning-Robert-Martin/dp/0131479415"&gt;Agile Estimating and Planning&lt;/a&gt; by &lt;a href="http://blog.mountaingoatsoftware.com/"&gt;Mike Cohn&lt;/a&gt;,  which covers story points, sprint length, agile planning and a lot of  other topics that are important for management to understand as well as  developers.&lt;/li&gt;&lt;li&gt;Two very reputable books on use cases and user stories are &lt;a href="http://www.amazon.co.uk/Writing-Effective-Crystal-Software-Development/dp/0201702258/"&gt;Writing Effective Use Cases&lt;/a&gt; by &lt;a href="http://alistair.cockburn.us/Blog"&gt;Alistair Cockburn&lt;/a&gt; and &lt;a href="http://www.amazon.co.uk/User-Stories-Applied-Development-Signature/dp/0321205685"&gt;User Stories Applied&lt;/a&gt; by &lt;a href="http://blog.mountaingoatsoftware.com/"&gt;Mike Cohn&lt;/a&gt;, but I've read neither (yet).&lt;/li&gt;&lt;/ul&gt;The exciting thing about reading these books is that they are part of an ongoing conversation. We haven't worked out how to build software well yet, but I think that these books bring us a little closer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7343428137797367142?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7343428137797367142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/my-agile-canon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7343428137797367142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7343428137797367142'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/10/my-agile-canon.html' title='My agile canon'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8296242671079231002</id><published>2010-08-24T22:38:00.001+01:00</published><updated>2010-08-24T22:38:00.855+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><title type='text'>Tolstoy on iterative development</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;But their mother country was too far off, and a man who has six or seven hundred miles to walk before reaching his destination must be able to put his final goal out of his mind and say to himself that he will 'do thirty miles today and then spend the night somewhere'; and during this first stage of the journey that resting-place for the night eclipses the image of his ultimate goal and absorbs all his hopes and desires.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Leo Tolstoy, &lt;a href="http://www.amazon.co.uk/Peace-Wordsworth-Classics-L-N-Tolstoy/dp/1853260622"&gt;&lt;span style="font-style: italic;"&gt;War and Peace&lt;/span&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8296242671079231002?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8296242671079231002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/08/tolstoy-on-iterative-development.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8296242671079231002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8296242671079231002'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/08/tolstoy-on-iterative-development.html' title='Tolstoy on iterative development'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-430037922996824394</id><published>2010-08-16T21:41:00.005+01:00</published><updated>2010-08-16T22:12:48.851+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='estimation'/><title type='text'>Fear-based estimation</title><content type='html'>I prefer agile development because early feedback mechanisms like TDD, pair-programming and frequent releases reduce my fear of the unknown. I don't like feeling afraid, but when I am I try to take notice, because it's usually an indication that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;something is&lt;/span&gt; not right.&lt;br /&gt;&lt;br /&gt;A great agile tradition is acknowledging the human element in software development. In that spirit, I'd like to suggest that developers' fear can be harnessed to improve estimation.&lt;br /&gt;&lt;br /&gt;Humans are notoriously bad at temporal reasoning and programmers are even-more-notoriously bad at guessing how long a given piece of work will take. Agile teams work around this by estimating effort in 'story points' that measure the comparative size of tasks. We might not be sure how long designing the new schema will take, but we assign it 2 story points because we know it will take twice as long as another task we gave 1 point.&lt;br /&gt;&lt;br /&gt;The rate at which a team completes points is known as its 'velocity' and can be determined by examining the team's progress over time. It's a robust, self-correcting system, but I've observed two drawbacks on projects I've worked:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The confidence of estimates isn't captured.&lt;/li&gt;&lt;li&gt;The technical debt incurred by a particular piece of work is ignored altogether.&lt;/li&gt;&lt;/ul&gt;A story that has a chance of going horribly wrong and that will in any case cripple the system's architecture could receive a low story point score because it (probably) won't take long to implement. Confronted with such a story, developers are terrified - and helpless.&lt;br /&gt;&lt;br /&gt;I propose that we estimate in terms of 'fear points' to give product owners a disincentive to prioritise dangerous stories. The question we ask in estimation meetings shouldn't be "how big is this task" but "how afraid does this task make you?".&lt;br /&gt;&lt;br /&gt;So long as the developers have an appropriate level of professional cowardice, a story's fear points will reflect the danger the story represents to the project's current and future &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;timelines&lt;/span&gt;. And I think that 'danger' is as useful to communicate to management as 'size'.&lt;br /&gt;&lt;br /&gt;If product owners want to negotiate a reduction in a story's fear points then they need to reduce uncertainty, remove risky features and compromise on ideas that would incur a lot of technical debt. They could also prioritise other stories that improve the team's confidence in the development process, like improved Continuous Integration.&lt;br /&gt;&lt;br /&gt;Whenever I have seen developers afraid of a feature, it turns out badly. It ends up buggy, expensive to change and probably doesn't serve its intended purpose. By gauging developers' fear, agile organisations have an opportunity to avoid trouble before it happens.&lt;br /&gt;&lt;br /&gt;If your developers are afraid of a feature - be very afraid.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-430037922996824394?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/430037922996824394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/08/fear-based-estimation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/430037922996824394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/430037922996824394'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/08/fear-based-estimation.html' title='Fear-based estimation'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-4781876985240716732</id><published>2010-05-17T17:28:00.005+01:00</published><updated>2010-05-18T09:23:51.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><title type='text'>Safe habits</title><content type='html'>When I was growing up, I found some of my parents' habits irritatingly conservative. Examples included:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Always lock doors from the outside using the key&lt;/li&gt;&lt;li&gt;Always turn on the cold tap before the hot tap&lt;/li&gt;&lt;/ul&gt;The idea was that following these habits guaranteed you could never burn yourself or lock yourself out. But I found these precautions frustrating because I knew that it was unlikely that I'd forget my keys or put my hand in the scalding water.&lt;br /&gt;&lt;br /&gt;However, I was mistaking the most likely outcome for the entire distribution. In &lt;a href="http://www.amazon.co.uk/Lifes-Grandeur-Spread-Excellence-Darwin/dp/0099893606"&gt;Life's Grandeur&lt;/a&gt;, Stephen Jay Gould calls this "reification" - fixating on the average case and ignoring variation and atypical outcomes.&lt;br /&gt;&lt;br /&gt;On any given occasion, my cavalier attitude would probably suffice. But sooner or later, if I locked doors by setting the snib and pulling them shut, my keys would not be in my pocket.&lt;br /&gt;&lt;br /&gt;My parents understood my fallibility better than I did. And they were in a better position to appreciate the myriad of door-locking scenarios that would confront me over my lifetime.&lt;br /&gt;&lt;br /&gt;That's why I like to think that if my mother were a programmer (and she'd make a good one) she would advocate &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd"&gt;TDD&lt;/a&gt;, which goes as follows:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write a failing test&lt;/li&gt;&lt;li&gt;Write the minimum of code to pass the test&lt;/li&gt;&lt;li&gt;Refactor&lt;/li&gt;&lt;/ol&gt;If you make TDD a permanent habit then you are inevitably at most 5 or 10 minutes away from working, tested code. And you know that every bit of code you write has a corresponding test.&lt;br /&gt;&lt;br /&gt;Be mindful of your development habits, and design them for the bad days, not the average days.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-4781876985240716732?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/4781876985240716732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/05/safe-habits.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4781876985240716732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4781876985240716732'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/05/safe-habits.html' title='Safe habits'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-3478144561502918589</id><published>2010-02-15T22:11:00.002Z</published><updated>2010-02-15T22:11:00.672Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>Descartes on Unit Testing</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;For he who attempts to view a multitude of objects with the one and the same glance, sees none of them distinctly; and similarly the man who is wont to attend to many things at the same time by a single act of thought is confused in mind.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- René Descartes, 'Rules for the direction of the mind' in &lt;a href="http://www.amazon.co.uk/Philosophical-Writings-Wordsworth-Classics-Literature/dp/1853264709"&gt;&lt;span style="font-style: italic;"&gt;Key Philosophical Writings&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-3478144561502918589?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/3478144561502918589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/02/descartes-on-unit-testing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/3478144561502918589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/3478144561502918589'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/02/descartes-on-unit-testing.html' title='Descartes on Unit Testing'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7330913749150066517</id><published>2010-02-06T20:10:00.005Z</published><updated>2010-02-06T22:21:49.119Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><title type='text'>Deconstructing The Savoy</title><content type='html'>The software industry has long looked to the construction industry for inspiration.&lt;br /&gt;&lt;br /&gt;We appropriate its vocabulary - programmers "build" software designed by "architects". We draw on its ideas - the seminal &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;Gang of Four&lt;span style="font-style: italic;"&gt; &lt;/span&gt;book&lt;/a&gt; adapted architect &lt;a href="http://en.wikipedia.org/wiki/Christopher_Alexander"&gt;Christopher Alexander&lt;/a&gt;'s concept of &lt;a href="http://www.patternlanguage.com/"&gt;design patterns&lt;/a&gt; for use in software construction. And the discipline of software engineering was founded on a desire to employ civil engineering practices to help us build complex software systems.&lt;br /&gt;&lt;br /&gt;For me, the most striking similarity between the two industries is the frequency of budget blowouts and schedule overruns. The great thing about this for software developers is that it gives us a tangible way of describing our otherwise inexplicable travails and catastrophes to ordinary people.&lt;br /&gt;&lt;br /&gt;Yesterday in &lt;a href="http://www.thisislondon.co.uk/standard/"&gt;The London Evening Standard&lt;/a&gt; I read &lt;a href="http://findarticles.com/p/news-articles/evening-standard-london-uk/mi_8010/is_20100205/savoy-rise-splendour-rubble/ai_n49166198/?tag=content;col1"&gt;an article&lt;/a&gt; about the renovations of &lt;a href="http://www.the-savoy.com/"&gt;The Savoy&lt;/a&gt;, the famous London hotel. It read almost word-for-word like a story about an overly ambitious IT migration project.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;When The Savoy closed on 15 December 2007 for a planned 16-month, £100 million makeover, it was hoped the hotel would quickly resume its status, buffed and restored to its former glory.&lt;/blockquote&gt;In the planning stages, optimism rules. The project is so large and complex that we can't possibly plan accurately, so in the absence of evidence one way or the other we assume the best.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;The original £100 million estimate for the work has been ripped up and although operators &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Fairmont&lt;/span&gt; Hotels and Resorts will not disclose the actual figure, the 15 months of work suggests it could be close to double that sum.&lt;/blockquote&gt;Once work begins, the fragility of the initial estimates is exposed. Often, the 'estimate' of how much a project will cost is as much based on the depth of the client's pockets as the actual effort required to get the job done (which of course no one knows in advance anyway).&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Part of the problem was The Savoy's unplanned, organic growth.&lt;/blockquote&gt;We have to live with the sins of those who came before us. In my experience, the quality of a system's legacy &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;code base&lt;/span&gt; has more impact on a project than the inherent difficulty of the project in question.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Although we had done two years of planning and tried to assess the level of issues behind the walls, it's only when you close the doors and open it up that you realise the amount of work is much more serious and extensive than first envisaged.&lt;/blockquote&gt;Unsurprisingly, once you are up to your elbows in a system's viscera, you have a much better idea about what you're in for. Exploratory surgery is the only way to be certain of how long changes will take.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;"What was an open courtyard suddenly became a room, with a mix of internal and external walls."&lt;/blockquote&gt;A system accrues &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;idiosyncrasies&lt;/span&gt; because it is inevitably patched, hacked and enhanced. Modules that were designed with one use-case in mind are re-purposed as business needs change. And scar tissue accumulates.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Digging up the roadway in Savoy Place, off the Strand &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;entrance&lt;/span&gt; - still the only place in the UK where one must legally drive on the right - he found a huge &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;gulley&lt;/span&gt; running around the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;perimeter&lt;/span&gt;, instead of a solid foundation. "We don't even know what it's for."&lt;/blockquote&gt;Users will adapt to visible peculiarities. They may even grow attached to them, even if the rationale for them has become obsolete (cars drive on the right in Savoy Place &lt;a href="http://en.wikipedia.org/wiki/Savoy_Hotel#Savoy_Court_and_Savoy_Pier"&gt;so that hansom cab drivers could open the door for their customers without leaving their seat&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;But much more frightening are the dull, blank blocks of obsolete code that loom like monoliths erected by a vanished civilisation. No one remembers what they were originally intended to do, and you can never be quite sure that the earth won't mysteriously stop turning if they are ever removed.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;The huge expense and loss of revenue mean The Savoy has to "hit the ground running" when it reopens if the money is ever to be recouped.&lt;/blockquote&gt;&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;Counter intuitively&lt;/span&gt;, the level of optimism rises as the schedule slips. It's very tempting to think that although we fell behind in phase 1, we can make up the time in phase 2. However, it's much more likely that if one part of a project runs into trouble, the rest will too.&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;As a manager at one said: "Hotel travellers are very promiscuous, they will, as it were, sleep around. While you are off the scene many will have happily moved on and it could take years to get them back."&lt;/blockquote&gt;Software users are even more promiscuous, especially on the web. They will cheerfully see your competitors behind your back, even in the good times. They will not tolerate a prolonged outage and they will complain loudly if your service is unavailable even for an hour.&lt;br /&gt;&lt;br /&gt;But I am not entirely pessemistic about the software development process. There is one important attribute that software has that buildings don't - malleability.&lt;br /&gt;&lt;br /&gt;We are able to follow agile methodologies and incrementally improve our programs. We don't have to follow The Savoy's example and attempt to implement an enormous modification in one go. We can embrace change and use the information we gather along the way to improve the end product. And if we refactor as we develop, we can reduce the amount of technical debt we bequeath to our successors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7330913749150066517?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7330913749150066517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/02/software-industry-has-long-looked-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7330913749150066517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7330913749150066517'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/02/software-industry-has-long-looked-to.html' title='Deconstructing The Savoy'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-179514756976748637</id><published>2010-01-14T16:30:00.004Z</published><updated>2010-01-14T18:30:26.276Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><title type='text'>Clean code</title><content type='html'>At the beginning of &lt;a href="http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt;, &lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Uncle Bob Martin&lt;/a&gt; enlists various well-respected programmers to explain what code cleanliness means to them. These luminaries include &lt;a href="http://www2.research.att.com/%7Ebs/"&gt;Bjarne Stroustrup&lt;/a&gt; (inventor of C++) and &lt;a href="http://c2.com/%7Eward/"&gt;Ward Cunningham&lt;/a&gt; (inventor of the wiki).&lt;br /&gt;&lt;br /&gt;Here is my definition:&lt;br /&gt;&lt;blockquote&gt;Clean code imposes minimal impedance between the reader and the intent of the author. It contains little accidental complexity and its meaning can be easily understood, verified and manipulated.&lt;/blockquote&gt;When I work with clean code I have a sensation of reaching through the code to directly engage with the system's concepts.&lt;br /&gt;&lt;br /&gt;When I work with unclean code my vision is clouded by weak naming, murky structure, inadequate commenting, convoluted dependencies and duplicated logic. Unclean code makes me afraid, because I cannot predict or understand the consequences of my changes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-179514756976748637?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/179514756976748637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2010/01/clean-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/179514756976748637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/179514756976748637'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2010/01/clean-code.html' title='Clean code'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1655657256554096346</id><published>2009-12-11T12:44:00.006Z</published><updated>2009-12-11T14:52:02.189Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><title type='text'>Thinking from the G.U.T.</title><content type='html'>A mathematical physicist friend of mine once said that he looks forward to the day when physicists will produce a &lt;a href="http://en.wikipedia.org/wiki/Grand_unification_theory"&gt;Grand Unified Theory (GUT)&lt;/a&gt; that will consolidate strong nuclear force, weak nuclear force and electromagnetism into a single interaction. This would be a stepping stone to the creation of a &lt;a href="http://en.wikipedia.org/wiki/Theory_of_everything"&gt;Theory of Everything&lt;/a&gt; that would also assimilate gravitation and thus unite all the strands of modern physics.&lt;br /&gt;&lt;br /&gt;I was struck by his certainty that such a theory is possible. He seemed to be making a scientific prediction based on an aesthetic sensibility - unified theories are more beautiful therefore a unified theory is correct.&lt;br /&gt;&lt;br /&gt;Unification is certainly an important part of the progress of a science. &lt;a href="http://en.wikipedia.org/wiki/Occam%27s_razor"&gt;Occam's razor&lt;/a&gt; is a well-established principle for judging the utility of a theory. &lt;i&gt;Entia non sunt multiplicanda praeter necessitatem&lt;/i&gt; - entities are not to be multiplied more than is necessary. In other words, the simplest theory that fits the data is the best.&lt;br /&gt;&lt;br /&gt;When &lt;a href="http://en.wikipedia.org/wiki/Nicolas_L%C3%A9onard_Sadi_Carnot"&gt;Sadi Carnot&lt;/a&gt; showed the equivalence of heat and mechanical work it was a victory for physics because physicists could now explain natural phenomena using less entities. At a superficial level, his discovery was useful because students now had to tax their brains with less concepts in order to understand both heat and motion.&lt;br /&gt;&lt;br /&gt;But Carnot's unification had also produced a theory was &lt;span style="font-style: italic;"&gt;more correct&lt;/span&gt; than earlier theories that thought of heat as a substance called "caloric". The &lt;a href="http://en.wikipedia.org/wiki/Theory_of_heat"&gt;mechanical theory of heat&lt;/a&gt; turned out to explain more phenomena than Carnot had originally considered. The laws of thermodynamics could not have been formulated without Carnot's insight.&lt;br /&gt;&lt;br /&gt;Why should the simpler theory prove more correct?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hutter1.net/"&gt;Marcus Hutter&lt;/a&gt; believes that understanding is fundamentally an act of mental unification. The &lt;a href="http://prize.hutter1.net/"&gt;Hutter prize&lt;/a&gt; offers a reward for anyone able to produce a better compression of Wikipedia. A high compression ratio requires a deep understanding of the corpus - in this case a snapshot of human knowledge. If unification is in some sense equivalent to understanding then a unified theory is more likely to be correct because it is a better approximation of the phenomena in question.&lt;br /&gt;&lt;br /&gt;(Interestingly, Hutter is also an advocate for a &lt;a href="http://www.hutter1.net/"&gt;physical Theory of Everything&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;However, it is a leap of blind optimism to assume that a G.U.T. is possible just because if it existed it would be useful, beautiful and likely to yield futher insight. Desirability does not imply feasibility.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959"&gt;The Mythical Man Month&lt;/a&gt; Fred Brooks draws a distinction between essential and accidental complexity in software systems that is very pertinent to the possibility of a G.U.T.&lt;br /&gt;&lt;br /&gt;Accidental complexity is caused by defficiencies in the solution. This kind of complexity can be eliminated by improving the approach to the problem. I would argue that the seperation of heat and mechanics was an example of accidental complexity caused by a lack of understanding of the nature of heat. The mechanical theory of heat was a successful simplification because it removed complexity that was never part of the phenomena itself.&lt;br /&gt;&lt;br /&gt;Essential complexity, on the other hand, is inherent in the problem. It is impossible to build a solution that is less complex than the problem it is designed to solve.&lt;br /&gt;&lt;br /&gt;The universe, like any other corpus, has an uncomputable &lt;a href="http://homepages.cwi.nl/%7Epaulv/kolmogorov.html"&gt;Kolmogorov complexity&lt;/a&gt; that limits how simple a correct theory of physics can be. Though we cannot ever know the essential complexity of the universe, it does have one. There is an unknown and absolute limit to the unifying efforts of physics, so we cannot ever be sure that further unification will be possible.&lt;br /&gt;&lt;br /&gt;Perhaps physics will encounter new phenomena that require new multiplication of entities to explain. Perhaps we are close to the limit and though we might incrementally simplify our theories we will never be able to reduce physics to less than four fundamental interactions.&lt;br /&gt;&lt;br /&gt;We cannot hope to make out theories more unified than the phenomena they describe and still hope to make them correct. As Albert Einstein said (my italics):&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://www.quotedb.com/quotes/1360"&gt;Make everything as simple as possible, &lt;span style="font-style: italic;"&gt;but not simpler&lt;/span&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1655657256554096346?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1655657256554096346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/12/thinking-from-gut.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1655657256554096346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1655657256554096346'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/12/thinking-from-gut.html' title='Thinking from the G.U.T.'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-2080971533169574598</id><published>2009-10-22T23:22:00.002+01:00</published><updated>2009-12-11T11:20:32.837Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='code reuse'/><title type='text'>Context is sticky</title><content type='html'>Code reuse is one of the holy grails of the software engineering movement. Across the world, developers are frantically &lt;a href="http://literateprogrammer.blogspot.com/2009/06/crime-punishment-and-reinventing-wheel.html"&gt;reinventing the wheel&lt;/a&gt;. The web groans under the weight of piles of functionally equivalent PHP applications for rendering the contents of database tables.&lt;br /&gt;&lt;br /&gt;If a larger portion of this torrent of code could be reused then an enormous amount of effort could be saved. Perhaps this effort could be diverted into improving the software quality and we could finally make a dent in the &lt;a href="http://en.wikipedia.org/wiki/Software_crisis"&gt;software crisis&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But though everyone has been talking about code reuse for decades, there has been very little progress.&lt;br /&gt;&lt;br /&gt;The code that has enjoyed a significant degree of reuse has been specifically designed for that purpose. &lt;a href="http://rubyonrails.org/"&gt;Frameworks&lt;/a&gt;, &lt;a href="http://logging.apache.org/log4net/index.html"&gt;libraries&lt;/a&gt; and &lt;a href="http://www.mozilla-europe.org/en/firefox/"&gt;plugin architectures&lt;/a&gt; are widespread. Even the mighty operating system exists to share functionality between applications. But serendipitous reuse of code that was originally designed to solve a singular problem is rare.&lt;br /&gt;&lt;br /&gt;I think that the reason that code reuse is hard is the same reason that the &lt;a href="http://infomesh.net/2001/swintro/"&gt;semantic web&lt;/a&gt; has failed to materialise. This makes sense, because code is just a particular kind of semantic content.&lt;br /&gt;&lt;br /&gt;As &lt;a href="http://www.shirky.com/"&gt;Clay Shirky&lt;/a&gt; has argued, the &lt;a href="http://www.shirky.com/writings/semantic_syllogism.html"&gt;the semantic web is a problematic ambition because it requires a universal worldview&lt;/a&gt;. The semantic web project envisages that information interoperability will be achieved by employing universal data formats. But data formats are contingent on worldview, which can never be universal. Shirky takes genetics as an example:&lt;br /&gt;&lt;blockquote&gt;It would be relatively easy, for example, to encode a description of genes in XML, but it would be impossible to get a universal standard for such a description, because biologists are still arguing about what a gene actually is. There are several competing standards for describing genetic information, and the semantic divergence is an artifact of a real conversation among biologists. You can't get a standard til you have an agreement, and you can't force an agreement to exist where none actually does.&lt;br /&gt;&lt;/blockquote&gt;Even something as apparently clear-cut as genetic science resists universal semantic presentation because the data is contaminated by its original context.&lt;br /&gt;&lt;br /&gt;The opinions, prejudices, needs and worldview of a programmer are imprinted on their code to a far greater degree. That class you wrote the other day to process form values assumes that every field has exactly one value. The HTML the form was displayed in uses classes unique to your site's CSS. And the coding standards the class conforms to differ from standard PHP conventions because your organisation wants to achieve consistency with its .NET projects.&lt;br /&gt;&lt;br /&gt;You &lt;span style="font-style: italic;"&gt;might&lt;/span&gt; be able to shoehorn this code into the next project you complete for the same organisation, but there is little chance of your form-processing class ever being used by someone else entirely. The &lt;a href="http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;cleaner&lt;/a&gt; and more decoupled your code is, the more use it might be to someone else, but you cannot entirely erase the imprint of its original context because context is what gives your code meaning.&lt;br /&gt;&lt;br /&gt;The way you can best foster reuse is to engineer a situation where the worldview embedded in your code is adopted by the reuser. Take Firefox as an example. The core functionality of the browser is &lt;a href="https://addons.mozilla.org/"&gt;leveraged by thousands of plugin developers&lt;/a&gt;. But the API these extensions work with was laid down by the developers of Firefox and has meaning only in the context of the Firefox browser.&lt;br /&gt;&lt;br /&gt;A cross-browser extension API would be very convenient, but the task of creating a plugin model that would apply as well to Chrome as to Firefox would be gargantuan. Witness how difficult it is to even get &lt;a href="http://acid3.acidtests.org/"&gt;HTML and CSS to render the same in more than one browser&lt;/a&gt;. A cross-browser API would take the compatibility issues from the DOM and spread them to every aspect of the browsing experience.&lt;br /&gt;&lt;br /&gt;Commonly-used frameworks also owe their success to prescribing a worldview. The only painless way to work with a framework is to follow &lt;a href="http://www.therailsway.com/"&gt;the Rails way&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/660836/django-way-of-specifying-channel-image-in-rss-feed"&gt;the Django way&lt;/a&gt; or &lt;a href="http://drupal.org/node/176252"&gt;the Drupal way&lt;/a&gt;. To reuse someone else's code you must make concessions to their way of doing things.&lt;br /&gt;&lt;br /&gt;There are a couple of current developments in software engineering that will help with the code reuse problem. &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd"&gt;Test driven development&lt;/a&gt; helps to make the assumptions embedded in code explicit by describing them using unit tests. The referential transparency fostered by the functional programming paradigm controls context by quarantining side-effects.&lt;br /&gt;&lt;br /&gt;But code reuse will always be intrinsically hard because context is sticky.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-2080971533169574598?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/2080971533169574598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/10/context-is-sticky.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2080971533169574598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2080971533169574598'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/10/context-is-sticky.html' title='Context is sticky'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1247923421475005481</id><published>2009-10-11T14:13:00.014+01:00</published><updated>2009-10-11T16:39:27.401+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>Vision is a feature</title><content type='html'>A few weeks ago &lt;a href="http://twitter.com/markwhiting"&gt;Mark Whiting&lt;/a&gt; and I had a brief Twitter conversation about his suggestion that &lt;a href="http://twitter.com/markwhiting/status/4056495900"&gt;&lt;q&gt;as design quality increases the designer disappears&lt;/q&gt;&lt;/a&gt;. He went on to suggest &lt;a href="http://twitter.com/markwhiting/status/4057863558"&gt;&lt;q&gt;that the formalism we when recognising a designer's work is as much an imperfection of the design as a feature&lt;/q&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I was not so sure. There are definitely instances where the designer's mark seems to contribute to the design. Programming languages are a good example. &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; would not be what it is without the strength of &lt;a href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto"&gt;Matz's&lt;/a&gt; personal vision.&lt;br /&gt;&lt;br /&gt;On the other hand, I do get annoyed when a designer's vanity tempts them to graffiti their signature onto a design that would have been better left alone. I'm thinking here of 'clever' designs like &lt;a href="http://www.findgift.com/gift-ideas/pid-60102/"&gt;teapots with two spouts&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The difference between these two scenarios is, in my opinion, is whether or not the design space is &lt;span style="font-style: italic;"&gt;convergent&lt;/span&gt;. I mean the term in the same sense as &lt;a href="http://en.wikipedia.org/wiki/Convergent_evolution"&gt;&lt;span style="font-style: italic;"&gt;convergent evolution&lt;/span&gt;&lt;/a&gt;. In a convergent design space, the differences between designs will gradually disappear over time as individual designers are gradually more successful at approximating the best solution to the problem at hand.&lt;br /&gt;&lt;br /&gt;In such a domain, it follows that any deviation from the one true design is noise. The designer's personal touch therefore detracts from their attempt to produce good design. A double-spouted teapot might help the designer express their individuality, but the result is just slightly less convenient tea.&lt;br /&gt;&lt;br /&gt;However, it's rare to find a design space where a Platonic 'best' design exists. When have the various stakeholders in the construction of a new building ever agreed what is best? And to revisit my earlier example, which language is 'best' is one of the most common topics of programming flame wars.&lt;br /&gt;&lt;br /&gt;Designers usually have to balance competing interests. How much should the finished product cost? What kind of user/customer should it be optimised for? What about older users/customers, or ones with disabilities? And not least, when is the deadline for the completed design? How designers balance these interests will inevitably affect the design. There is rarely any objective way to balance these subjective interests, so there is rarely an objective best design.&lt;br /&gt;&lt;br /&gt;In such open design spaces, the designer's vision serves an important purpose - coherence. There are so many elements in a complicated design that it can be hard to take them in all at once. A strong authorial vision helps users/customers by giving them a guide to predict and/or remember the designer's choices.&lt;br /&gt;&lt;br /&gt;Many Ruby admirers speak of the &lt;a href="http://en.wikipedia.org/wiki/Principle_of_least_surprise"&gt;&lt;q&gt;Principle of Least Surprise&lt;/q&gt;&lt;/a&gt;. Ruby is comparatively easy to learn and understand because its design choices aim to produce the least astonishment in the programmer. But since every programmer comes from a different background, they will each have different expectations and standards of astonishment.&lt;br /&gt;&lt;br /&gt;So more precisely, Ruby was designed &lt;a href="http://www.artima.com/intv/ruby4.html"&gt;according to the Principle of Matz's Least Surprise&lt;/a&gt;. Once the programmer gets a handle on Matz's programming aesthetic, they can make educated guesses about parts of the language that they have not yet encountered.&lt;br /&gt;&lt;br /&gt;So in conclusion, &lt;q&gt;the formalism we when recognising a designer's work&lt;/q&gt; &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; a feature because it makes understanding complicated design simpler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1247923421475005481?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1247923421475005481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/10/vision-is-feature.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1247923421475005481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1247923421475005481'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/10/vision-is-feature.html' title='Vision is a feature'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-6419842820229605308</id><published>2009-09-04T21:56:00.006+01:00</published><updated>2009-09-04T22:25:01.066+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>Using your browser to run an .msi as admin</title><content type='html'>Programmers &lt;a href="http://www.codinghorror.com/blog/archives/000891.html"&gt;should not use administrator accounts&lt;/a&gt; when developing. They should use accounts with the same privileges as the end users of the software. This minimises the chance of permission-related &lt;a href="http://www.codinghorror.com/blog/archives/000818.html"&gt;"it works on my machine"&lt;/a&gt; bugs occurring.&lt;br /&gt;&lt;br /&gt;Trouble is, developers frequently need to install programs. The nice way to handle this is to use something like &lt;a href="http://xkcd.com/149/"&gt;sudo&lt;/a&gt; (for *nix systems). A specific command can be executed with raised permissions, but for the rest of the time the user operates with normal privileges.&lt;br /&gt;&lt;br /&gt;However, some operating systems (like Windows XP), do not fully support the sudo approach. There is a command known as "&lt;a href="http://support.microsoft.com/kb/305780"&gt;runas&lt;/a&gt;", but this does not work in all circumstances. In particular, it is not available for .msi installer files.&lt;br /&gt;&lt;br /&gt;If you are running Windows XP on a non-administrator account, you need to install an .msi and you have the password of an administrator account, you do not have to take the trouble to logout and log back in. The following workaround lets you use your web browser as an .msi launcher and bypass the restriction:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use &lt;a href="http://support.microsoft.com/kb/305780"&gt;runas&lt;/a&gt; to launch your browser with admin privileges&lt;/li&gt;&lt;li&gt;Open the .msi in your browser, either from the web or your local filesystem&lt;/li&gt;&lt;li&gt;What you do next depends on what browser you use. In Firefox, you double click on the .msi in the download window which will launch it - as admin!&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;This works because a child process inherits its permissions from its parent.&lt;br /&gt;&lt;br /&gt;Needless to say, use this trick sparingly. Running your browser as administrator all the time is almost as bad as developing under an admin account.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-6419842820229605308?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/6419842820229605308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/09/using-your-browser-to-run-msi-as-admin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6419842820229605308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/6419842820229605308'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/09/using-your-browser-to-run-msi-as-admin.html' title='Using your browser to run an .msi as admin'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-2499407268808677004</id><published>2009-08-23T14:57:00.001+01:00</published><updated>2009-08-23T14:57:00.076+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><title type='text'>Minting MIME types</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Internet_media_type"&gt;MIME types&lt;/a&gt; are central to the &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST architectural style&lt;/a&gt; because they help define the interface between client and server. However they have to be registered with a central body, which is an incumberence when creating new MIME types.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://soundadvice.id.au/blog/"&gt;Benjamin Carlyle&lt;/a&gt; has a suggestion for how we might &lt;a href="http://soundadvice.id.au/blog/2009/08/16/"&gt;bypass the bottleneck of registering MIME types&lt;/a&gt; with the &lt;a href="http://www.iana.org/"&gt;IANA&lt;/a&gt;. &lt;a href="http://www.innoq.com/blog/st/"&gt;Stefan Tilkov&lt;/a&gt; has been &lt;a href="http://www.innoq.com/blog/st/2009/08/mime_types_holding_rest_back.html"&gt;following similar proposals&lt;/a&gt; for some time.&lt;br /&gt;&lt;br /&gt;There are two separate problems in this debate that I think are being confused.&lt;br /&gt;&lt;br /&gt;One is the identification of new resource types. The other is providing a definition of the format of resources e.g. an &lt;a href="http://www.w3.org/XML/Schema"&gt;XML schema&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Benjamin's proposal involves using a &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier"&gt;URI&lt;/a&gt; to identify resource types. If the resource definition URIs of two resources differ, then the client must interpret them as different resource types. Dereferencing a resource definition URI will yield a definition of that format.&lt;br /&gt;&lt;br /&gt;The difficulty as I see it is that multiple URIs could point to the same resource definition. Furthermore, the data format might be defined in multiple places and in multiple ways e.g. a &lt;a href="http://en.wikipedia.org/wiki/Document_Type_Definition"&gt;DTD&lt;/a&gt; and an XML schema. Ideally &lt;a href="http://en.wikipedia.org/wiki/Content_negotiation"&gt;conneg&lt;/a&gt; would be used to put equivalent definitions behind a single URI, but in practice conneg is oft-neglected.&lt;br /&gt;&lt;br /&gt;The process of agreeing on a canonical URI to use for a given format is no simpler than agreeing on an "x-" prefixed custom MIME type. So while Benjamin's proposal helps solve the resource type definition problem, I don't think it makes much progress on the resource type identification problem.&lt;br /&gt;&lt;br /&gt;Benjamin quite rightly points out that a key problem in resource identification is when resource types 'grow up' and move beyond the boundries of the organisation where they were created. However I fear that using URIs to identify formats makes this transition more difficult, because if the URI of the format description is changed then all clients using the format will have to be updated.&lt;br /&gt;&lt;br /&gt;If the original URI of the format was internal to the organisation's LAN, then the URI will be forced to change. At some stage during the format's development the URI will probably have to be changed anyway.&lt;br /&gt;&lt;br /&gt;In short, URIs are good for pointing to definitions of resource formats but are problematic for establishing the identity of resource types.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-2499407268808677004?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/2499407268808677004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/08/minting-mime-types.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2499407268808677004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/2499407268808677004'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/08/minting-mime-types.html' title='Minting MIME types'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1541600707225259559</id><published>2009-07-16T23:55:00.003+01:00</published><updated>2009-07-18T13:00:00.069+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mathematics'/><title type='text'>Discovery vs creation</title><content type='html'>One of the biggest differences between mathematics and programming is the question of authorship. Advances in maths are typically described as &lt;a href="http://science.discovery.com/convergence/100discoveries/big100/big100.html"&gt;discoveries&lt;/a&gt;, whereas new software is developed, created or invented. Though programming and mathematics employ similar notations, the uses of these notations are governed by strikingly dissimilar discourses.&lt;br /&gt;&lt;br /&gt;Even &lt;a href="http://en.wikipedia.org/wiki/Kurt_G%C3%B6del"&gt;Kurt Gödel&lt;/a&gt;, who's &lt;a href="http://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems"&gt;incompleteness theorems&lt;/a&gt; are perhaps the most well-known examples of the limitations of mathematics, is widely regarded as a &lt;a href="http://en.wikipedia.org/wiki/Platonism"&gt;Platonist&lt;/a&gt;. He, like many mathematicians, regarded mathematics as more real than the physical world. For a Platonist, theorems are timeless and eternal. Mathematicians' role is to discover and document them as purely as possible. &lt;a href="http://en.wikipedia.org/wiki/Paul_Erd%C5%91s"&gt;Paul Erdős&lt;/a&gt; expressed this sentiment by imagining that the most beautiful proofs came from a book written by God.&lt;br /&gt;&lt;br /&gt;On the other hand, few would claim that &lt;a href="http://www.linux.co.uk/"&gt;Linux&lt;/a&gt; existed before &lt;a href="http://en.wikipedia.org/wiki/Linus_Torvalds"&gt;Linus Torvalds&lt;/a&gt; started writing it in 1991. Even a software engineering concept like &lt;a href="http://en.wikipedia.org/wiki/Structured_programming"&gt;structured programming&lt;/a&gt; is usually described as being founded by &lt;a href="http://en.wikipedia.org/wiki/Edsger_W._Dijkstra"&gt;Edsger Dijkstra&lt;/a&gt;, even though the &lt;a href="http://en.wikipedia.org/wiki/Structured_program_theorem"&gt;mathematical theorem that underpins the movement&lt;/a&gt; could be said to have been discovered (by &lt;a href="http://en.wikipedia.org/wiki/Corrado_B%C3%B6hm" title="Corrado Böhm"&gt;Corrado Böhm&lt;/a&gt; and Giuseppe Jacopini).&lt;br /&gt;&lt;br /&gt;Some mathematicians do leave room for authorship in their understanding of their profession. &lt;a href="http://en.wikipedia.org/wiki/Leopold_Kronecker"&gt;Leopold Kronecker&lt;/a&gt; once said that &lt;q&gt;&lt;a href="http://everything2.com/title/God%2520made%2520the%2520integers%252C%2520all%2520else%2520is%2520the%2520work%2520of%2520man"&gt;God made the integers, all else is the work of man&lt;/a&gt;.&lt;/q&gt; &lt;a href="http://en.wikipedia.org/wiki/Bertrand_Russell"&gt;Bertrand Russell&lt;/a&gt; went further and said that integers were also created by man - or at least they could be constructed using mathematical logic.&lt;br /&gt;&lt;br /&gt;The defining characteristic of authorship (as opposed to invention) is that the subjectivity of the author is imprinted on the work. One example of this in mathematics is &lt;a href="http://en.wikipedia.org/wiki/Calculus"&gt;the calculus&lt;/a&gt;. &lt;a href="http://en.wikipedia.org/wiki/Isaac_Newton"&gt;Isaac Newton&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Gottfried_Leibniz"&gt;Gottfried Leibniz&lt;/a&gt; both discovered the calculus, but they approached it in different ways. I would argue that their divergent expressions of the same idea are best understood through the lens of authorship, especially given the importance Leibniz placed on notation and presenting his thoughts for human understanding.&lt;br /&gt;&lt;br /&gt;But by and large, mathematicians are better described by &lt;a href="http://en.wikipedia.org/wiki/Roland_Barthes"&gt;Roland Barthes'&lt;/a&gt; account of tellers of tales before modern authorship was invented:&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://evans-experientialism.freewebspace.com/barthes06.htm"&gt;In ethnographic societies the responsibility for a narrative is never assumed by a person but by a mediator, shaman or relator whose ‘performance’ — the mastery of the narrative code —may possibly be admired but never his ‘genius’. The author is a modern figure.&lt;/a&gt;&lt;/blockquote&gt;Mathematicians attach their names to their work, but more in the spirit of explorers naming newly discovered peaks than authors cultivating writing credits. It is this emphasis on discovery rather than creation that most clearly differentiates mathematical practice from programming and which means that &lt;a href="http://literateprogrammer.blogspot.com/2009/06/literate-programming.html"&gt;a purely mathematical education is not sufficient to understand software development&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1541600707225259559?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1541600707225259559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/07/discovery-vs-creation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1541600707225259559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1541600707225259559'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/07/discovery-vs-creation.html' title='Discovery vs creation'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-512487904411855025</id><published>2009-07-01T19:50:00.002+01:00</published><updated>2009-07-17T21:35:17.160+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>The professional is political</title><content type='html'>I wondered once whether my occupation influences my politics. Then I thought, &lt;strong&gt;of course it does&lt;/strong&gt;. Construction workers are more likely to be unionists, small business owners are more likely to be economically conservative and &lt;a href="http://en.wikipedia.org/wiki/Rahm_Emanuel"&gt;Barack Obama's chief of staff&lt;/a&gt; is more likely to be a Democrat. It's hard to make definite predictions (except possibly the last one), but what you do for eight hours a weekday &lt;em&gt;has&lt;/em&gt; to influence your view of the world.&lt;br /&gt;&lt;br /&gt;It's not immediately obvious what political stereotype to apply to software developers. One the one hand, computer systems are tightly controlled, deterministic universes where users can only venture if they provide the correct password (which the programmer has decreed shall contain no less than three non-alphanumeric characters).&lt;br /&gt;&lt;br /&gt;This suggests that programmers might have sympathy for centrally planned economies. Citizens' input will correctly &lt;a href="http://validator.w3.org/check?uri=www.literateprogrammer.blogspot.com"&gt;validate&lt;/a&gt; or they will be &lt;a href="http://en.wikipedia.org/wiki/Reeducation_through_labor"&gt;re-educated&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;On the other hand, a lot of our time as software designers is dedicated to preserving flexibility. We use factory methods and interfaces to give ourselves the freedom to change which class we wish to instantiate. We attempt to compose methods so that they can be re-used in other contexts. &lt;a href="http://www.codinghorror.com/blog/archives/000855.html"&gt;Nathaniel Borenstein captured this attitude perfectly&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure. Basic professional ethics would instead require him to write a DestroyCity procedure, to which Baghdad could be given as a parameter.&lt;/blockquote&gt;Some use C++ because they don't want some garbage-collecting &lt;a href="http://en.wikipedia.org/wiki/Nanny_state"&gt;nanny state&lt;/a&gt; managing their memory for them. I'm sure that &lt;a href="http://en.wikipedia.org/wiki/Margaret_Thatcher"&gt;Margaret Thatcher&lt;/a&gt; would have agreed with this sentiment had she studied programming rather than chemistry - though her declaration that &lt;a href="http://www.brainyquote.com/quotes/quotes/m/margaretth114265.html"&gt;&lt;q&gt;if you want to cut your own throat, don't come to me for a bandage&lt;/q&gt;&lt;/a&gt; does suspiciously like she's warning a junior developer away from pointer arithmetic.&lt;br /&gt;&lt;br /&gt;The common theme of these examples is that software developers are constantly struggling to capture logic at the appropriate place in their code. This is the key point I take from software to my own political opinions. When it comes right down to it, most of the political ideas and philosophies that I dislike are &lt;a href="http://www.codinghorror.com/blog/archives/001275.html"&gt;operating on the wrong level of abstraction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Great_Leap_Forward"&gt;Centralised steel quotas&lt;/a&gt; are a bad idea because production decisions are best made on a local level, not in Beijing. &lt;a href="http://www.efa.org.au/Issues/Censor/cens1.html"&gt;Internet censorship&lt;/a&gt; is problematic because an individual is best placed to decide what they do not wish to view. A single point of control is not appropriate for these examples.&lt;br /&gt;&lt;br /&gt;However, some political decisions cannot be left to the individual. Controlling greenhouse gas emissions is a good example of an issue that needs to be managed centrally to avoid a &lt;a href="http://dieoff.org/page95.htm"&gt;tragedy of the commons&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My instincts have always been libertarian. But my experiences as a software developer have taught me that there is no hard and fast rule for what level of abstraction decisions should be made at. As much as I'd like individuals to be given complete control over their lives, sometimes individuals simply do not have the necessary perspective to make the best decision.&lt;span style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;For example, &lt;a href="http://en.wikipedia.org/wiki/Ethical_consumerism"&gt;ethical consumerism&lt;/a&gt; is a laudable philosophy, but it does not work unless there is some &lt;a href="http://www.ethicalconsumer.org/"&gt;central agency capable of understanding the consequences of individual purchases&lt;/a&gt; who can guide consumers. And government schools are necessary because leaving it to parents to purchase education for their own children will lead to unacceptable inequality.&lt;br /&gt;&lt;br /&gt;Considering issues in isolation can also lead to short-sighted decisions. I disapprove of the &lt;a href="http://en.wikipedia.org/wiki/California_ballot_proposition"&gt;Californian system of referenda&lt;/a&gt;, because of course people will vote for lower taxes and higher spending if they are asked about these issues in isolation. Budgets need to be created from a perspective that allows consideration of all of a government's finances.&lt;br /&gt;&lt;br /&gt;To paraphrase &lt;a href="http://www.quotedb.com/quotes/1360"&gt;Einstein's well-known quote&lt;/a&gt;, make your code as simple (and generic) as possible, but no simpler. Give individuals as much liberty as possible, but no more. And when contemplating a political dilemma, consider what level of abstraction the problem would be best addressed at.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-512487904411855025?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/512487904411855025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/07/professional-is-political.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/512487904411855025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/512487904411855025'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/07/professional-is-political.html' title='The professional is political'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-4131357959160644832</id><published>2009-06-21T12:33:00.002+01:00</published><updated>2009-06-22T21:55:13.424+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google wave'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><title type='text'>Email considered harmful</title><content type='html'>I don't like email. More precisely, I'm disappointed that we don't have something that's better than email.&lt;br /&gt;&lt;br /&gt;I suppose it's to its creators' credit that we are still using a tool that was &lt;a href="http://tools.ietf.org/html/rfc561"&gt;standardised in close to its present form in 1973&lt;/a&gt;. But email has so many shortcomings in its very architecture that it's high time we upgraded to something else. There are many partial solutions to the problems listed below, but to properly fix them all requires a ground-up rebuild.&lt;br /&gt;&lt;h2&gt;No guarantee of delivery&lt;/h2&gt;If an SMTP server swallows your email, tough luck. An email is like a postcard hurled out into the void. If it disappears somehow then no one will ever know.&lt;br /&gt;&lt;h2&gt;No support for high-level abstractions like conversations&lt;/h2&gt;People do not send emails in isolation. Often, an email will be part of a series of replies, perhaps involving multiple recipiants.&lt;br /&gt;&lt;br /&gt;Email gives you no good way of grouping individual messages into a conversation, other than by dumping the entire previous contents of the conversation at the bottom of each message. &lt;a href="http://mail.google.com/"&gt;Gmail&lt;/a&gt; does a valiant job of threading emails, but the process it's using doesn't help you if you're not using Gmail, is unreliable and is inherently just a hack.&lt;br /&gt;&lt;br /&gt;The lack of any coherent high-level organising principle makes email communication chaotic when the number of messages involved is large. Sometimes this is so unmanagable that it causes individuals to take the drastic step of declaring email bankruptcy, notably including &lt;a href="http://www-cs-faculty.stanford.edu/%7Eknuth/email.html"&gt;Donald Knuth&lt;/a&gt; (founder of &lt;a href="http://www.literateprogramming.com/"&gt;literate programming&lt;/a&gt;) and &lt;a href="http://www.wired.com/culture/lifestyle/news/2004/06/63733"&gt;Lawrence Lessig&lt;/a&gt; (of the &lt;a href="http://creativecommons.org/"&gt;Creative Commons&lt;/a&gt; and the &lt;a href="http://www.eff.org/"&gt;EFF&lt;/a&gt;). &lt;h2&gt;No canonical and independent copy&lt;/h2&gt;An email exists in its sender's outbox and its receiver's inbox. It may also be stored by an email server somewhere. If these copies are deleted or lost then it's gone.&lt;br /&gt;&lt;br /&gt;If someone tampers with an email that you sent them, you may have no way of proving this to a third party. If someone tampers with your email en route then you have no way of proving this even to the receiver.&lt;br /&gt;&lt;br /&gt;There's also no good way to introduce someone into an email conversation they have not been following (you can forward an email containing a bunch of replies, but that's hardly usable). Emails don't have a URL that you can pass around or use as a reference if, for example, the email contains an important decision that needs documenting.&lt;br /&gt;&lt;h2&gt;No native encryption&lt;/h2&gt;It is possible to &lt;a href="http://netsecurity.about.com/cs/emailsecurity/a/aa051004.htm"&gt;encrypt emails&lt;/a&gt;. But if you do, then both sender and receiver need to be using email clients that support encryption.  The sender would also have to have access to the receiver's &lt;a href="http://en.wikipedia.org/wiki/Public-key_cryptography"&gt;public key&lt;/a&gt;.&lt;br /&gt;&lt;h2&gt;No way of verifying the sender's identity&lt;/h2&gt;The only way you know who sent an email is by looking at the 'from' field. If that field is filled out wrongly then there is no way to tell. Impersonating someone over email is technically trivial (unless you use &lt;a href="http://en.wikipedia.org/wiki/Digital_signature"&gt;digital signatures&lt;/a&gt;, which have the same disadvantages as encryption).&lt;br /&gt;&lt;h2&gt;The future&lt;/h2&gt;I have high hopes that &lt;a href="http://wave.google.com/"&gt;Google Wave&lt;/a&gt; will solve some or all of these problems. But there are there two big advantages email has over Google Wave:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It's proven&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It's widely supported and understood&lt;/li&gt;&lt;/ul&gt;Email is not going to disappear overnight. After all, fax machines are still reasonably common and faxes have been almost entirely superceded - &lt;em&gt;by emails&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;For Google to get wide adoption of Wave they're going to have to come up with a solution that allows incremental adoption. Perhaps the Google Wave client could support email as well as Waves so that I can communicate with the vast majority of my contacts who aren't bleeding-edge adoptors.&lt;br /&gt;&lt;br /&gt;But until then we're going to have to suffer the absurdity of disagreements and uncertainty about whether a particular email was sent, who sent it and what was in it - like this &lt;a href="http://www.theage.com.au/national/rudd-in-car-dealer-crisis-20090619-cr9e.html"&gt;Australian political scandal&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update:&lt;/strong&gt; The scandalous email has &lt;a href="http://www.theage.com.au/national/fake-email-trips-turnbull-20090622-ctzi.html"&gt;turned out to be a fake&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-4131357959160644832?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/4131357959160644832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/email-considered-harmful.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4131357959160644832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/4131357959160644832'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/email-considered-harmful.html' title='Email considered harmful'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-7874078878710638855</id><published>2009-06-13T17:24:00.002+01:00</published><updated>2009-07-17T21:37:36.791+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='google wave'/><category scheme='http://www.blogger.com/atom/ns#' term='standards'/><category scheme='http://www.blogger.com/atom/ns#' term='literature'/><title type='text'>Crime, punishment and reinventing the wheel</title><content type='html'>&lt;a href="http://www.amazon.com/Punishment-Bantam-Classics-Fyodor-Dostoevsky/dp/0553211757"&gt;Crime and Punishment&lt;/a&gt;, the classic 19th century novel by &lt;a href="http://en.wikipedia.org/wiki/Fyodor_Dostoyevsky"&gt;Fyodor Dostoevsky&lt;/a&gt;, describes the execution and aftermath of a brutal double murder committed by the poor ex-student Raskolnikov. I am not spoiling the ending by telling you this - the murder itself takes place early on and the bulk of the novel deals with Raskolnikov's guilt and mental anguish.&lt;br /&gt;&lt;br /&gt;Initially, Raskolnikov justifies his crime by imagining himself to be one of the elite few who transcend ordinary morality. Like &lt;a href="http://en.wikipedia.org/wiki/Napoleon_I_of_France"&gt;Napoleon Bonaparte&lt;/a&gt;, these extraordinary men are destined to seize society bend it to their will. Their higher purpose excuses them from the constraints of morality that ordinary members of society must abide by.&lt;br /&gt;&lt;br /&gt;The reader soon realises that Raskolnikov is not a member of this elite cadre. True Napoleons are too busy invading Spain to construct self-serving psuedo-philosophical justifications. As the novel progresses, Raskolnikov's crippling doubts reveal to him the fallacy of his delusions of grandeur. He realises that men who are preordained to shake civilisation to its very foundations do not agonise over their calling.&lt;br /&gt;&lt;br /&gt;In the world of software, it is not at all uncommon to encounter a developer who is convinced that they are a Napoleon. Perhaps it's ignorance. Perhaps it's arrogance. Whatever the reason, they are motivated to &lt;a href="http://thedailywtf.com/Articles/I_Think_I_0x27_ll_Call_Them__0x26_quot_0x3b_Transactions_0x26_quot_0x3b_.aspx"&gt;create their own inadequate solutions&lt;/a&gt; to &lt;a href="http://thedailywtf.com/Articles/Classic-WTF-The-Challenges-of-Negation.aspx"&gt;problems that have already been well and truly solved&lt;/a&gt;. Often they take it on themselves to improve upon things that ordinary programmers take as given (like &lt;a href="http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx"&gt;the nature of truth itself&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wave.google.com/"&gt;Google Wave&lt;/a&gt; may just be an example of a revolution that we actually need. Email is a tried-and-true technology, but &lt;a href="http://literateprogrammer.blogspot.com/2009/06/email-considered-harmful.html"&gt;it has its limits and could benefit from a ground-up redesign&lt;/a&gt;. The success of  &lt;a href="http://maps.google.com/"&gt;Google Maps&lt;/a&gt; certainly suggests that the Rasmussen brothers are candidates for web Napoleons.&lt;br /&gt;&lt;br /&gt;On the other hand, &lt;a href="http://code.google.com/apis/accounts/docs/OpenID.html"&gt;Google's non-standard implementation of OpenID&lt;/a&gt; looks more like it was designed by Rodion Romanovich Raskolnikov. The whole point of OpenID is that it is a universal protocol, yet they have extended it for their own specific needs (they want to be able to use gmail addresses rather than URLs). What's worse, every developer who wishes to accomodate Google OpenIDs on their site will have to contaminate their code with a special case to handle gmail addresses.&lt;br /&gt;&lt;br /&gt;If you are contemplating producing your own version of a well-established technology, it is just possible that you possess a unique insight and that by reinventing the wheel you will drag software in a bright new direction. But if you are not sure, then your code is more likely to resemble an opportunistic act of violence than the &lt;a href="http://en.wikipedia.org/wiki/Napoleonic_code"&gt;&lt;em&gt;Code Napoléon&lt;/em&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And even if you are certain that your way is better, you're probably still wrong.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-7874078878710638855?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/7874078878710638855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/crime-punishment-and-reinventing-wheel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7874078878710638855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/7874078878710638855'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/crime-punishment-and-reinventing-wheel.html' title='Crime, punishment and reinventing the wheel'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-8166018620352036477</id><published>2009-06-09T15:37:00.001+01:00</published><updated>2009-06-10T14:27:33.474+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>When is the right time for the fancy stuff?</title><content type='html'>Derek Featherstone wrote an interesting post on &lt;q&gt;&lt;a href="http://boxofchocolates.ca/archives/2009/03/22/the-right-time"&gt;When is the right time for accessibility?&lt;/a&gt;&lt;/q&gt; His thesis is that accessibility should be planned for at the design stage, but that implementing it should not be a high priority early on. The idea is that accessibility should be worked on as the product matures and included in a subsequent release.&lt;br /&gt;&lt;br /&gt;As far as web accessibility and interaction-heavy sites are concerned, he is asking the wrong question. What he should be wondering is, &lt;q&gt;When is the right time for the fancy stuff?&lt;/q&gt;&lt;br /&gt;&lt;br /&gt;Sites with a lot of flash and javascript tend to be the worst accessibility offenders because the meaning of the site is only apparent by interacting with scripts on the page. The content is not comprehensible from the DOM itself. If you're sight impaired, don't use a mouse or don't have the reflexes of a twenty-something-year-old flash developer then you might be out of luck.&lt;br /&gt;&lt;br /&gt;Derek is of course aware of the importance of accessibility. However his approach seems to be to build the stairs first and then put in the wheelchair ramp later, and no matter how well you plan you will always &lt;a href="http://failblog.org/2009/05/13/ramp-fail-2/"&gt;come across implementation problems you had not considered&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My main criticism of Derek's article is that he constructs a dichotomy between business imperatives (getting the site up) and doing the right thing (implementing accessibility). However there are tangible benefits for your project in getting accessibility right early on.&lt;br /&gt;&lt;br /&gt;Most importantly, there is one blind and deaf user that every web developer should be concerned about: &lt;a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;amp;answer=70897"&gt;Googlebot&lt;/a&gt;. If a site is not accessible for a human with a disability then it almost certainly will not be indexed properly by Google. You cannot improve your site through user feedback if you have no users because no one can find your site.&lt;br /&gt;&lt;br /&gt;The other main advantage of tackling accessibility early is that &lt;a href="http://en.wikipedia.org/wiki/Progressive_enhancement"&gt;progressive enhancement&lt;/a&gt; is a sounder development methodology than building everything big-bang style. Build your pages so that they work without any flash or javascript. Once you have that working, you have a sound basis on which to build your incredibly sexy ajax effects.&lt;br /&gt;&lt;br /&gt;That affords your testing finer granularity. You can test the plain version of your page before you spoon on the flash and javascript. If there is a bug, you will know whether it occurs as part of the form-submission process or in the interaction layer. That beats monitoring HTTP requests with &lt;a href="http://getfirebug.com/"&gt;Firebug&lt;/a&gt; trying to work out where the hell the problem is.&lt;br /&gt;&lt;br /&gt;Of course, a big motivation web developers to make their sites accessible is that &lt;em&gt;it's the right thing to do&lt;/em&gt;. And it is. But if you follow progressive enhancement and make accessibility part of your development process then you'll get more out of it than just a warm fuzzy feeling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-8166018620352036477?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/8166018620352036477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/when-is-right-time-for-fancy-stuff.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8166018620352036477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/8166018620352036477'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/when-is-right-time-for-fancy-stuff.html' title='When is the right time for the fancy stuff?'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8648268364549955959.post-1772430020313641375</id><published>2009-06-07T19:47:00.002+01:00</published><updated>2009-07-18T12:57:30.913+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='literate programming'/><category scheme='http://www.blogger.com/atom/ns#' term='science'/><category scheme='http://www.blogger.com/atom/ns#' term='humanities'/><title type='text'>Literate programming</title><content type='html'>&lt;p&gt;The title of this blog is a reference to &lt;a href="http://www.literateprogramming.com/"&gt;literate programming&lt;/a&gt;, a software development methodology founded by &lt;a href="http://www-cs-faculty.stanford.edu/%7Eknuth/"&gt;Donald Knuth&lt;/a&gt;. Literate programming is best described in Knuth's own words:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.&lt;/p&gt;&lt;p&gt;The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.&lt;/p&gt;&lt;p&gt;- Donald Knuth, "Literate Programming" (1984)&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;I have great affinity for this way of viewing software development. Software design has &lt;a href="http://literateprogrammer.blogspot.com/2009/07/discovery-vs-creation.html"&gt;more in common with the composition of an essay than any strictly scientific activity&lt;/a&gt;. I think it's an accident of history that programming is placed within engineering faculties rather than being understood as an outgrowth of philosophy and formal logic.&lt;/p&gt;&lt;p&gt;Literate programming acknowledges software development's place among the humanities. By extension, it acknowledges the relevence of non-scientific ideas to the process of cutting code. Our craft requires the creative and disciplined presentation of thought, so we would be foolhardy to ignore thousands of years of the history of ideas. Programming does not exist inside a vaccuum. Neither should the programmer.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I am not trying to argue that programmers do not need a firm grasp of science. But good programmers cannot rely solely on scientific concepts if they wish their code to be comprehensible to their peers (or future selves).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In the spirit of literate programming I will use this blog to explore software development and its interplay with literature, philosophy, politics and mathematics.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8648268364549955959-1772430020313641375?l=literateprogrammer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://literateprogrammer.blogspot.com/feeds/1772430020313641375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/literate-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1772430020313641375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8648268364549955959/posts/default/1772430020313641375'/><link rel='alternate' type='text/html' href='http://literateprogrammer.blogspot.com/2009/06/literate-programming.html' title='Literate programming'/><author><name>ctford</name><uri>http://www.blogger.com/profile/05464902188219000642</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://2.bp.blogspot.com/_qPvFtVe3LUc/Si5dTSAg_EI/AAAAAAAAAAM/ny8Z8TUsJ0o/S220/profile.jpg'/></author><thr:total>0</thr:total></entry></feed>
