<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>Wide Awake Developers</title>
      <link>http://www.michaelnygard.com/blog/</link>
      <description>An ongoing examination of what it means to be an IT professional in today&apos;s world.</description>
      <language>en</language>
      <copyright>Copyright 2010</copyright>
      <lastBuildDate>Sun, 03 Jan 2010 17:16:06 -0600</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/?v=4.24-en</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

      
      <item>
         <title>Topics in Architecture</title>
         <description><![CDATA[<p>I'm working on a syllabus for an extensive course on web architecture.  This will be for experienced programmers looking to become architects.</p>

<p>Like all of my work about architecture, this covers technology, business, and strategic aspects, so there's an emphasis on creating high-velocity, competitive organizations.</p>

<p>In general, I'm aiming for a mark that's just behind the bleeding edge.  So, I'm including several of the NoSQL persistence technologies, for example, but not including <a href="http://wiki.github.com/krestenkrab/erjang">Erjang</a> because it's too early.  (Or is that "erl-y"? )</p>

<p>(What I'd really love to do is make a screencast series out of all of these.  I'm daunted, though.  There's a lot of ground to cover here!)</p>

<p>EDIT: Added function and OO styles of programming. (Thanks <a href="http://www.twitter.com/deanwampler">@deanwampler</a>.)  Added JRuby/Java under languages.  (Thanks <a href="http://www.twitter.com/glv">@glv</a>.)</p>

<p>I'm interested in hearing your feedback.  What would you add? Remove?</p>

<ul>
<li><p>Methods and Processes</p>

<ul>
<li>Systems Thinking/Learning Organization</li>
<li>High Velocity Organizations</li>
<li>Safety Culture</li>
<li>Error-Inducing Systems ("Normal Accidents")</li>
<li>Points of Leverage</li>
<li>Fundamental Dynamics: Iteration, Variation, Selection, Feedback, Constraint</li>
<li>5D architecture</li>
<li>Failures of Intuition</li>
<li>ToC</li>
<li>Critical Chain</li>
<li>Lean Software Development</li>
<li>Real Options</li>
<li>Strategic Navigation</li>
<li>OODA</li>
<li>Tempo, Adaptation</li>
<li>XP</li>
<li>Scrum</li>
<li>Lean</li>
<li>Kanban</li>
<li>TDD</li>
</ul></li>
<li><p>Architecture Styles</p>

<ul>
<li>REST / ROA</li>
<li>SOA</li>
<li>Pipes &amp; Filters</li>
<li>Actors</li>
<li>App-server centric</li>
<li>Event-Driven Architecture</li>
</ul></li>
<li><p>Web Foundations</p>

<ul>
<li>The "architecture" of the web</li>
<li>HTTP 1.0 &amp; 1.1</li>
<li>Browser fetch behaviors</li>
<li>HTTP Intermediaries</li>
</ul></li>
<li><p>The Nature of the Web</p>

<ul>
<li>Crowdsourcing</li>
<li>Folksonomy</li>
<li>Mashups/APIs/Linked Open Data</li>
</ul></li>
<li><p>Testing</p>

<ul>
<li>TDD</li>
<li>Unit testing</li>
<li>BDD/Spec testing</li>
<li>ScalaCheck</li>
<li>Selenium</li>
</ul></li>
<li><p>Persistence</p>

<ul>
<li>Redis</li>
<li>CouchDB</li>
<li>Neo4J</li>
<li>eXist</li>
<li>"Web-shaped" persistence</li>
</ul></li>
<li><p>Technical architecture</p>

<ul>
<li>8 Fallacies of Distributed Computing</li>
<li>CAP Theorem</li>
<li>Scalability</li>
<li>Reliability</li>
<li>Performance</li>
<li>Latency</li>
<li>Capacity</li>
<li>Decoupling</li>
<li>Safety</li>
</ul></li>
<li><p>Languages and Frameworks</p>

<ul>
<li>Spring</li>
<li>Groovy/Grails</li>
<li>Scala</li>
<li>Lift</li>
<li>Clojure</li>
<li>Compojure</li>
<li>JRuby</li>
<li>Rails</li>
<li>OSGi</li>
</ul></li>
<li><p>Design</p>

<ul>
<li>Code Smells</li>
<li>Object Thinking</li>
<li>Object Design</li>
<li>Functional Thinking</li>
<li>API Design</li>
<li>Design for Operations</li>
<li>Information Hiding</li>
<li>Recognizing Coupling</li>
</ul></li>
<li><p>Deployment</p>

<ul>
<li>Physical</li>
<li>Virtual</li>
<li>Multisite</li>
<li>Cloud (AWS)</li>
<li>Chef</li>
<li>Puppet</li>
<li>Capistrano</li>
</ul></li>
<li><p>Build and Version Control</p>

<ul>
<li>Git</li>
<li>Ant</li>
<li>Maven</li>
<li>Leiningen</li>
<li>Private repos</li>
<li>Collaboration across projects</li>
</ul></li>
</ul>
]]></description>
         <link>http://www.michaelnygard.com/blog/2010/01/topics_in_architecture.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/01/topics_in_architecture.html</guid>
         <category>Architecture</category>
         <pubDate>Sun, 03 Jan 2010 17:16:06 -0600</pubDate>
      </item>
      
      <item>
         <title>Coupling and Coevolution</title>
         <description><![CDATA[<p>The mighty Mississippi River starts in Minnesota, at Lake Itasca. Every kid in Minnesota has to make the ritual pilgrimage to <a href="http://www.dnr.state.mn.us/state_parks/itasca/index.html">Itasca State Park</a> at some point, where wading across North America's longest river is a rite of passage.</p>

<p><img src="http://farm4.static.flickr.com/3199/2369068347_2de8466d30_m.jpg" alt="Mississippi River Starts Here" title="" /></p>

<p>One of the very interesting things in Itasca State Park is a section of forest that is fenced off so that deer cannot enter it. It's part of a decades-long experiment to see how forests are affected by browsing herbivores.  What's really interesting is that not only are the quantity of plants different inside the protected area, but the types of plants and trees are different, too. Because deer prefer to nibble on younger trees, fewer saplings survive in the main body of the forest than in the fenced-off portion. Outside the fence, the distribution of tree size and age is biased toward older trees. The population of trees is weighted more toward resinous species like pines, which deer prefer not to eat. Inside the fence, more saplings survive into young maturity, so you see a more even distribution of tree ages and a wider diversity of species represented in the mature trees. The changes in the canopy affect the ground cover which, in turn, change how deer could (if allowed) reach the trees and browse them.</p>

<p>So, here's a feedback loop that involves deer, trees, leaves and brush. The net result is a different ecosystem (albeit a slightly artificial one.)</p>

<p>Most physical and biological systems are like this in several ways, particularly relating to feedback. In our artificial systems (electrical, mechanical, symbolic, or semantic) we build in feedback mechanisms as a deliberate control. These are often one dimensional, proportional, and negative.</p>

<p>In natural systems, feedback arises everywhere. Sometimes, it proves to be helpful for the long-term stability of the system. In which case, the feedback itself gets reinforced by the existence and perpetuation of the system it exists within. In a sense, the system adapts to reinforce beneficial feedback. Conversely, feedback webs that cause too much instability will, like an overly aggressive virus, lead to destruction of their host system and disappear. So, we can see the constituents of a system co-evolving with each other and the system itself.</p>

<p>The old "microphone-amplifier-speaker-squealing" example of feedback really fails here. We lack both language and metaphor to really grasp this kind of interaction over time. In part, I think that's because we like to separate the world into isolated components and only talk about components at a single level of abstraction.  The trouble is that abstractions like "level of abstraction" only exist in our minds.</p>

<p>Here's another example of coevolution, courtesy of Jared Diamond in "Guns, Germs, and Steel". I'll apologize in advance for oversimplifying; I'm devoting a paragraph to an argument he develops across entire chapters.</p>

<p>At some point, a group of nomads decided that the seeds of these particular grasses were tasty. In collecting the grasses, they spread it around. Some kinds of seeds survived the winter better and responded well to being sown by humans. Now, nobody sat down and systematically picked out which seeds grew better or worse. They didn't have to, because the seeds that grew better produced more seeds for the next generation. Over time, a tiny difference (fractions of a percent) in productivity would lead some strains to supplant the others. Meanwhile, inextricably linked, some humans figured out how to plants, harvest, and eat these early grains. These humans had an advantage over their neighbors, so they were able to feed more babies.  That turns out to be a benefit, because farming is hard work and requires more offspring to help produce food.  (Another feedback loop.) Oh, and this kind of labor makes it advantageous to keep livestock, too. Over time, these farmers would breed and feed more children than the nomads, so farmers would come to be a larger and larger percentage of the population.  Just as an added wrinkle, keeping livestock and fertilizing fields both lead to diseases that simultaneously harm the individuals and occasionally decimate the population, but also provide some long-term benefits such as better disease resistance and inadvertent biological warfare when encountering other civilizations.</p>

<p>Try to diagram the feedback loops here: nomads, farmers, livestock, grains, birthrates, and so on. Everything is connected to everything else. It's really hard to avoid slipping into teleological language here. We've got feedback and feedforward at several different levels and timescales here, from the scale of microbes to livestock to civilizations, and across centuries. This dynamic altered the course of many species evolution: cattle, wheat, maize, and yes, good old H. Sapiens.</p>

<p>This complexity of interaction extends to <a href="http://blogs.discovermagazine.com/80beats/2009/10/07/enormous-ghost-ring-is-found-around-saturn/">planetary</a> and <a href="http://www.scientificamerican.com/article.cfm?id=exoplanets-lithium">stellar</a> levels as well. At some sufficiently long time scale, the intergalactic medium is coupled to our planetary ecosystem.</p>

<p>The human intellectual penchant for decomposition, isolation, and leveled abstraction is purely an artifact of the size of our bodies and the duration of our lives.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/12/coupling_and_coevolution.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/12/coupling_and_coevolution.html</guid>
         <category>Stuff</category>
         <pubDate>Thu, 03 Dec 2009 11:12:03 -0600</pubDate>
      </item>
      
      <item>
         <title>GMail Outage Was a Chain Reaction</title>
         <description><![CDATA[<p>Google has published an <a href="http://gmailblog.blogspot.com/2009/09/more-on-todays-gmail-issue.html">explanation of the widespread GMail outage</a> from September 1st. In this explanation, they trace the root cause to a layer of "request routers":</p>

<blockquote>
  <p>...a few of the request routers became overloaded and in effect told the rest of the system "stop sending us traffic, we're too slow!". This transferred the load onto the remaining request routers, causing a few more of them to also become overloaded, and within minutes nearly all of the request routers were overloaded.</p>
</blockquote>

<p>This perfectly describes the "Chain Reaction" stability antipattern from <a href="http://www.amazon.com/gp/product/0978739213?ie=UTF8&amp;tag=michaelnygard-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0978739213">Release It</a>!</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/09/gmail_outage_chain_reaction.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/09/gmail_outage_chain_reaction.html</guid>
         <category>Architecture</category>
         <pubDate>Wed, 02 Sep 2009 09:25:03 -0600</pubDate>
      </item>
      
      <item>
         <title>Hadoop versus VPN</title>
         <description><![CDATA[<p>I've been doing some work with <a href="http://hadoop.apache.org">Hadoop</a> lately, and I just ran into an interesting problem with networking.  This isn't a bug, per se, but a conflict in my configuration.</p>

<p>I'm running on a laptop, using a <a href="http://hadoop.apache.org/common/docs/r0.20.0/quickstart.html#PseudoDistributed">pseudo-distributed</a> cluster. That means all the different processes are running, but they're all running on one box. That makes it possible to test jobs with full network communication, but without deploying to a production cluster.</p>

<p>I'm also working remotely, connecting to the corporate network by VPN. As is commonly done, our VPN is configured to completely separate the client machine from its local network. (If it didn't, you could use the VPN machine to bridge the secure corporate network to your home ISP, coffeeshop, airport, etc.)</p>

<p>Here's the problem: when on the VPN, my machine can't talk to its own IP address. Right now, <code>ifconfig</code> reports the laptops IP address as 192.168.1.105.  That's the address associated with the physical NIC on the machine.</p>

<p>The odd part is that Hadoop <em>mostly</em> works this way. I've configured the name node, job tracker, task tracker, datanodes, etc. to all use "localhost". I can use HDFS, I can submit jobs, and all the map tasks work fine. The only problem is that when the map tasks finish, the task tracker cannot send data from the map tasks to the reduce tasks.  The job appears to hang.</p>

<p>In the task tracker's log file, I see reports every 20 seconds or so that say</p>

<pre><code>2009-07-31 11:01:33,992 INFO org.apache.hadoop.mapred.TaskTracker: attempt_200907310946_003_r_000000_0 0.0% reduce &gt; copy &gt;
</code></pre>

<p>The instant I disconnected from the VPN, the copy proceeded and the reduce job ran.</p>

<p>I'm sure there's a configuration property somewhere within Hadoop that I can change. When (if) I find it, I'll update this post.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/07/hadoop_versus_vpn.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/07/hadoop_versus_vpn.html</guid>
         <category>Bugs and bothers</category>
         <pubDate>Fri, 31 Jul 2009 10:03:13 -0600</pubDate>
      </item>
      
      <item>
         <title>An AspectJ Circuit Breaker</title>
         <description><![CDATA[<p>Spiros Tzavellas pointed me to his implementation of Circuit Breaker. His approach uses AspectJ and can be applied using a bytecode weaver or AspectJ compiler.  He's also got unit tests with 85% coverage.</p>

<p>Spiros' project page is <a href="http://www.tzavellas.com/projects/circuit-breaker/">here</a>, and the code is (where else?) on <a href="http://github.com/sptz45/circuit-breaker/tree/master">GitHub</a>.  He appears to be quite actively developing the project.</p>

]]></description>
         <link>http://www.michaelnygard.com/blog/2009/07/an_aspectj_circuit_breaker.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/07/an_aspectj_circuit_breaker.html</guid>
         <category>Architecture</category>
         <pubDate>Thu, 16 Jul 2009 09:01:15 -0600</pubDate>
      </item>
      
      <item>
         <title>Two New Circuit Breaker Implementations</title>
         <description><![CDATA[<p>The excellent Will Sargent has created a Circuit Breaker gem that's quite nice. You can read the docs at <a href="http://rdoc.info/projects/wsargent/circuit_breaker">rdoc.info</a>. He's released the code (under LGPL) on <a href="http://github.com/wsargent/circuit_breaker/tree/master">GitHub</a>.
</p>

<p>
The other one has actually been out for a couple of months now, but I forgot to blog about it.  Scott Vlamnick created a <a href="http://www.grails.org/plugin/circuit-breaker">Grails plugin</a> that uses AOP to weave Circuit Breaker functionality as "around" advice. This one can also report its state via JMX.  In a particularly nice feature, this plugin supports different configurations in different environments.
</p>]]></description>
         <link>http://www.michaelnygard.com/blog/2009/07/two_new_circuit_breaker_implem.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/07/two_new_circuit_breaker_implem.html</guid>
         <category>Architecture</category>
         <pubDate>Thu, 16 Jul 2009 07:35:45 -0600</pubDate>
      </item>
      
      <item>
         <title>Workmen, tools, etc.</title>
         <description><![CDATA[<p>We've all heard the old saw, "It's a poor workman that blames his tools." Let's think about that for a minute. Does it actual mean that a skilled craftsman can do great work with shoddy implements?</p>

<p>Well, can a chef make a souffle with a skillet?</p>

<p>Can a cabinetmaker round an edge with dull router bits?</p>

<p>I'm not going to rule it out.  Perhaps there's a brilliant chef who---at this very moment---is preparing to introduce the world to the "skiffle."  And, it's possible that one could coax a dull router into making a better quarter round through care, attention, and good speed control.</p>

<p>Going by the odds, though, I'd bet on scrambled eggs and splinters.</p>

<p>Like a lot of old sayings, this one doesn't make much sense in it's usual interpretation. Most people take this proverb to mean that you should be able to turn out top-notch work with whatever tools you're given. It's an excuse for bad tools, or lack of interest in improving them.</p>

<p>This homily dates back to a time when workers would bring their own tools to the job, leading to the popular origin story for the phrase "getting sacked". (No comments about møøse bites, please.) Some crafts have evaded the assembly line, and in those, craftsman still bring their own tools. Chefs bring their prized knives. Fine carpenters bring their own hand and bench tools.</p>

<p>There is a grain of truth in the common interpretation that good tools don't make a good workman. There's another level of truth under the surface, though.  The 13th Century French version of this saying translates as, "A bad workman will never find a good tool."  I like this version a lot better. Tools cannot make one good, but bad tools can hurt a good worker's performance. That sounds a lot less like "quit whining and use whatever's at hand," doesn't it?</p>

<p>On the other hand, if you supply your own tools, you're not as likely to tolerate bad ones, are you?  I think this is the most important interpretation. Good workers---if given the choice---will select the best tools and keep them sharp.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/05/workman_tools_etc.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/05/workman_tools_etc.html</guid>
         <category>Articles</category>
         <pubDate>Wed, 20 May 2009 20:17:03 -0600</pubDate>
      </item>
      
      <item>
         <title>Minireview: Beginning Scala</title>
         <description><![CDATA[<p>As you can probably tell from my recent posts, I've been learning Scala.  I recently dug into another Scala book, <a href="http://www.amazon.com/gp/product/1430219890?ie=UTF8&amp;tag=michaelnygard-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=1430219890">Beginning Scala</a> by David Pollak.</p>

<p>Beginning Scala is a nice, gentle introduction to this language. It takes a gradual, example driven approach that emphasizes running code early.  This makes it a good intro for people who want to <em>use</em> the language for applications first, then worry about creating frameworks later.</p>

<p>Don't let that fool you, though. Pollak gets to the sophisticated parts soon enough.  I particularly like a example of creating a new "control structure" to execute stuff in the context of a JDBC connection. This puts some meat on the argument that Scala is a "scalable language."  Where other languages either implement this as a keyword (as in <a href="http://groovy.codehaus.org/">Groovy</a>'s "with") or a framework (<a href="http://www.springsource.org/">Spring</a>'s "templates"), here it can be added with one page of example code.</p>

<p>Beginning Scala also has a very thorough discussion of actors. I appreciate this, because actors were my main motivation for learning Scala in the first place.</p>

<p>Pollak separates the act of consuming a library from that of creating a library. He advises us to worry most about types, traits, co- and contravariance, etc. mainly when we are creating libraries. True to this notion, chapter 7 is called "Traits and Types and Gnarly Stuff for Architects". It doesn't sound like much fun, but it is important material.  I find that Scala makes me think more about the type system than other languages.  It's strongly, and statically, typed.  (So much so, in fact, that it makes me realize just how loose Java's own type system is.) As such, it pays to have a firm understanding of how code turns into types.  Scala has a rich set of tools for building an expressive type system, but there is also complexity there.  Checking in at 60 pages, this chapter covers Scala's tools along with guidance on good styles and idioms.</p>

<p>Interestingly, although there is a <a href="http://liftweb.net/">Lift</a> logo on the cover, there's nothing about Lift in the book itself. Considering that Pollak is the creator of Lift, it's curious that this book doesn't deal with it.  Perhaps that's being left for another title.</p>

<p>Overall, I endorse Beginning Scala.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/05/minireview_beginning_scala.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/05/minireview_beginning_scala.html</guid>
         <category>Books</category>
         <pubDate>Mon, 18 May 2009 14:41:57 -0600</pubDate>
      </item>
      
      <item>
         <title>Units of Measure in Scala</title>
         <description><![CDATA[<p>Failure to understand or represent units has caused several <a href="http://www.devtopics.com/20-famous-software-disasters-part-2/">major disasters</a>, including the costly Ariane 5 disaster in 1996. This is one of those things that DSLs often get right, but mainstream programming languages just ignore.  Or, worse, they implement a clunky unit of measure library that ensures you can never again write a sensible arithmetic expression.</p>

<p>While I was at <a href="http://jaoo.com.au">JAOO Australia</a> this week, <a href="http://www.pandamonial.com/">Amanda Laucher</a> showed some F# code for a recipe that caught my attention. It used numeric literals with that directly attached units to quantities.  What's more, it was intelligent about combining units.</p>

<p>I went looking for something similar in Scala.  I googled my fingertips off, but without much luck, until <a href="http://twitter.com/milessabin">Miles Sabin</a> pointed out that there's already a <a href="https://lampsvn.epfl.ch/trac/scala/browser/compiler-plugins/units/trunk">compiler plugin</a> sitting right next to the core Scala code itself.</p>

<h2>Installing Units</h2>

<p>Scala has it's own package manager, called sbaz.  It can directly install the units extension:</p>

<p>sbaz install units</p>

<p>This will install it under your default managed installation. If you haven't done anything else, that will be your Scala install directory.  If you have done something else, you probably already know what you're doing, so I won't try to give you instructions.</p>

<h2>Using Units</h2>

<p>To use units, you first have to import the library's "Preamble".  It's also helpful to go ahead and import the "StandardUnits" object.  That brings in a whole set of useful SI units.</p>

<p>I'm going to do all this from the Scala interactive interpreter.</p>

<pre><code>scala&gt; import units.Preamble._
import units.Preamble._

scala&gt; import units.StandardUnits._
import units.StandardUnits._
</code></pre>

<p>After that, you can multiply any number by a unit to create a dimensional quantity:</p>

<pre><code>scala&gt; 20*m
res0: units.Measure = 20.0*m

scala&gt; res0*res0
res1: units.Measure = 400.0*m*m

scala&gt; Math.Pi*res0*res0
res2: units.Measure = 1256.6370614359173*m*m
</code></pre>

<p>Notice that when I multiplied a length (in meters) times itself, I got an area (square meters).  To me, this is a really exciting thing about the units library.  It can combine dimensions sensibly when you do math on them.  In fact, it can help prevent you from incorrectly combining units.</p>

<pre><code>scala&gt; val length = 5*mm
length: units.Measure = 5.0*mm

scala&gt; val weight = 12*g
weight: units.Measure = 12.0*g

scala&gt; length + weight
units.IncompatibleUnits: Incompatible units: g and mm
</code></pre>

<p>I can't add grams and millimeters, but I can multiply them.</p>

<h2>Creating Units</h2>

<p>The StandardUnits package includes a lot of common units relating to basic physics.  It doesn't have any relating to system capacity metrics, so I'd like to create some units for that.</p>

<pre><code>scala&gt; import units._
import units._

scala&gt; val requests = SimpleDimension("requests")
requests: units.SimpleDimension = requests

scala&gt; val req = SimpleUnit("req", requests, 1.0)
req: units.SimpleUnit = req

scala&gt; val Kreq = SimpleUnit("Kreq", requests, 1000.0)
Kreq: units.SimpleUnit = Kreq
</code></pre>

<p>Now I can combine that simple dimension with others.  If I want to express requests per second, I can just write it directly.</p>

<pre><code>scala&gt; 565*req/s
res4: units.Measure = 565.0*req/s
</code></pre>

<h2>Conclusion</h2>

<p>This extension will be the first thing I add to new projects from now on.  The convenience of literals, with the extensibility of adding my own dimensions and units means I can easily keep units with all of my numbers.</p>

<p>There's no longer any excuse to neglect your units in a mainstream programming language.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/05/units_of_measure_in_scala.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/05/units_of_measure_in_scala.html</guid>
         <category>Design</category>
         <pubDate>Thu, 07 May 2009 22:00:09 -0600</pubDate>
      </item>
      
      <item>
         <title>Kudos to Relevance and Clojure</title>
         <description><![CDATA[<p>It's been a while since I blogged anything, mainly because most of my work lately has either been mind-numbing corporate stuff, or so highly contextualized that it wouldn't be productive to write about.</p>

<p>Something came up last week, though, that just blew me away.</p>

<p>For various reasons, I've engaged <a href="http://thinkrelevance.com/">Relevance</a> to do a project for me.  (Actually, the first results were so good that I've now got at least three more projects lined up.)  They decided---and by "they", I mean <a href="http://blog.thinkrelevance.com/2009/4/4/programming-clojure-beta-9-is-out">Stuart Halloway</a>---to write the engine at the heart of this application in Clojure. That makes it sound like I was reluctant to go along, but actually, I was interested to see if the result would be as expressive and compact as everyone says.</p>

<p>Let me make a brief aside here and comment that I'm finding it much harder to be the customer on an agile project than to be a developer.  I think there are two main reasons. First, it's hard for me to keep these guys supplied with enough cards to fill an iteration. They're outrunning me all the time.  Big organizations like my employer just take a long time to decide anything.  Second, there's nobody else I can defer to when the team needs a decision.  It often takes two weeks just for me to get a meeting scheduled with all of the stakeholders inside my company.  That's an entire iteration gone, just waiting to <em>get</em> to the meeting to make a decision!  So, I'm often in the position of making decisions that I'm not 100% sure will be agreeable to all parties.  So far, they have mostly worked out, but it's a definite source of anxiety.</p>

<p>Anyway, back to the main point I wanted to make.</p>

<p>My personal theme is making software production-ready. That means handling all the messy things that happen in the real world.  In a lab, for example, only one batch file ever needs to be processed at once.  You never have multiple files waiting for processing, and files are always fully present before you start working on them. In production, that only happens if you guarantee it.</p>

<p>Another example, from my system.  We have a set of rules (which are themselves written in Clojure code) that can be changed by privileged users.  After changing the configuration, you can tell the daemonized Clojure engine to "(reload-rules!)".  The "!" at the end of that function means it's an imperative with major side effects, so the rules get reloaded right now.</p>

<p>I thought I was going to catch them up when I asked, oh so innocently, "So what happens when you say (reload-rules!) while there's a file being processed on the other thread?"  I just love catching people when they haven't dealt with all that nasty production stuff.</p>

<p>After a brief sidebar, Stu and <a href="http://vanderburg.org/">Glenn Vanderburg</a> decided that, in fact, nothing bad would happen at all, despite reloading rules in one thread while another thread was in the middle of using the rules.</p>

<p>Clojure uses a flavor of transactional memory, along with persistent data structures. No, that doesn't mean they go in a database. It means that changes to a data structure can only be made inside of a transaction.  The new version of the data structure and the old version exist simultaneously, for as long as there are outstanding references to them. So, in my case, that meant that the daemon thread would "see" the old version of the rules, because it had dereferenced the collection prior to the "reload-rules!"  Meanwhile, the reload-rules! function would modify the collection in its own transaction.  The next time the daemon thread comes back around and uses the reference to the rules, it'll just see the new version of the rules.</p>

<p>In other words, two threads can both use the same reference, with complete consistency, because they each see a point-in-time snapshot of the collection's state.  The team didn't have to do anything special to make this happen... it's just the way that Clojure's references, persistent data structures, and transactional memory work.</p>

<p>Even though I didn't get to catch Stu and Glenn out on a production readiness issue, I still had to admit that was pretty frickin' cool.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/05/kudos_to_relevance_and_clojure.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/05/kudos_to_relevance_and_clojure.html</guid>
         <category>Architecture</category>
         <pubDate>Wed, 06 May 2009 01:18:26 -0600</pubDate>
      </item>
      
      <item>
         <title>JAOO Australia in 1 Month</title>
         <description><![CDATA[<p><img src="/images/badges/Speaking_at_JAOO.png" alt="Speaking at JAOO" title="" /> The <a href="http://jaoo.com.au/">Australian JAOO</a> conferences are now just one month away.  I've wanted to get to Australia for at least ten years now, so I am thrilled to finally get there.</p>

<p>I'll be delivering a tutorial on <a href="http://jaoo.com.au/sydney-2009/presentation/Release+IT">production ready software</a> in both the <a href="http://jaoo.com.au/brisbane-2009/">Brisbane</a> and <a href="http://jaoo.com.au/sydney-2009/">Sydney</a> conferences. This tutorial was a hit at <a href="http://qconlondon.com">QCon London</a>, where I first delivered it. The Australian version will be further improved.</p>

<p>During the main conference, I'll be delivering a two-part talk on <a href="http://jaoo.com.au/sydney-2009/presentation/Failure+Comes+in+Flavours+(Part+1">common failure modes</a>) of distributed systems break and <a href="http://jaoo.com.au/sydney-2009/presentation/Failure+Comes+in+Flavours+(Part+2">how to recover</a>) from such breakage. These talks apply whether you're building web facing systems or internal shared services/SOA projects.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/04/jaoo_australia_in_1_month.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/04/jaoo_australia_in_1_month.html</guid>
         <category>Speaking</category>
         <pubDate>Fri, 03 Apr 2009 12:12:06 -0600</pubDate>
      </item>
      
      <item>
         <title>Quantum Backups</title>
         <description><![CDATA[<p>Backups are the only macroscopic system we commonly deal with that exhibits quantum mechanical effects. This is odd enough that I've spent some time getting tangled up in these observations.</p>

<p>Until you attempt a restore, a backup set is neither good nor bad, but a superposition of both. This is the <em>superposition principle</em>.</p>

<p>The peculiarity of the superposition principle is dramatically illustrated with the experiment of <em>Schrödinger's backup</em>. This is when you attempt to restore Schrödinger's pictures of his cat, and discover that the cat is not there.</p>

<p>In a startling corollary, if you use offsite vaulting, a second quantum variable is introduced, in that the backup set exists and does not exist simultaneously. A curious effect emerges upon applying the Hamiltonian operator. The operator shows that certain eigenvalues are always zero, revealing that prime numbered tapes greater than 5 in a set never exist.</p>

<p>Finally, the <em>Heisenbackup principle</em> says that the user of a system is entangled with the system itself. As a result, within 30 days of consciously deciding that you do not need to run a backup, you will experience a complete disk crash.  Because you've just read this, your 30 days start now. </p>

<p>Sorry about that.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/03/quantum_backups.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/03/quantum_backups.html</guid>
         <category>Humor</category>
         <pubDate>Fri, 20 Mar 2009 08:40:54 -0600</pubDate>
      </item>
      
      <item>
         <title>Update: Sun Cloud API Not the Same as Amazon</title>
         <description><![CDATA[<p>It looks like the early reports that Sun's cloud API would be compatible with AWS resulted from the reporters' exuberance (or mere confusion.)</p>

<p>It's actually nicer than Amazon's.</p>

<p>It is based on the REST architectural style, with representations in JSON.  In fact, I might start using it as the best embodiment of REST principles.  You start with an HTTP GET of "/". In this repsonse to this and every other request, it is the hyperlinks in the response that indicate what actions are allowed.</p>

<p>Sun has a <a href="http://kenai.com/projects/suncloudapis/pages/Home">wiki</a> to describe the API, with a very nicely illustrated "<a href="http://kenai.com/projects/suncloudapis/pages/HelloCloud">Hello, Cloud</a>" example.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/03/update_sun_cloud_api_not_the_s.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/03/update_sun_cloud_api_not_the_s.html</guid>
         <category>Cloud Computing</category>
         <pubDate>Thu, 19 Mar 2009 07:29:33 -0600</pubDate>
      </item>
      
      <item>
         <title>Can you make that meeting?</title>
         <description><![CDATA[<p>I'm convinced that the next great productivity revolution will be de-matrixing the organizations we've just spent ten years slicing and dicing.</p>

<p>Yesterday, I ran into a case in point: What are the odds that three people can schedule a meeting this week versus having to push it into next week?</p>

<p>Turns out that if they're each 75% utilized, then there's only a 15% chance they can schedule a one hour meeting this week.  (If you always schedule 30 minute meetings instead of one hour, then the odds go up to about 25%.)</p>

<p>Here's the probability curve that the meeting can happen. This assumes, by the way, that there are no lunches or vacation days, and that all parties are in the same time zone. It only gets worse from here.</p>

<p><img src="/images/blog/meeting/meeting_odds_3_parties.png" style="float: none; border: none;" /></p>

<p>So, overall, there's about an 85% chance that 3 random people in a meeting-driven company will have to defer until next week.</p>

<p>Bring it up to 10 people, in a consensus-driven, meeting-oriented company, and the odds drop to 0.00095%.</p>

<p>No wonder "time to first meeting" seems to dominate "time to do stuff."</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/03/can_you_make_that_meeting.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/03/can_you_make_that_meeting.html</guid>
         <category>Business</category>
         <pubDate>Wed, 18 Mar 2009 15:55:13 -0600</pubDate>
      </item>
      
      <item>
         <title>Amazon as the new Intel</title>
         <description><![CDATA[<p><strong>Update: Please read <a href="http://www.michaelnygard.com/blog/2009/03/update_sun_cloud_api_not_the_s.html">this update</a>. The information underlying this post was based on early, somewhat garbled, reports.</strong></p>

<p>A brief digression from the <a href="http://www.michaelnygard.com/blog/2009/03/getting_real_about_reliability.html">unpleasantness of reliability</a>.</p>

<p>This morning, Sun announced their re-entry into the cloud computing market. After withdrawing Network.com from the marketplace a few months ago, we were all wondering what Sun's approach would be. No hardware vendor can afford to ignore the cloud computing trend... it's going to change how customers view their own data centers and hardware purchases.</p>

<p>One thing that really caught my interest was the description of Sun's cloud offering. It sounded really, really similar to <a href="http://aws.amazon.com">AWS</a>. Then I heard the E-word and it made perfect sense. Sun <a href="http://www.sun.com/aboutsun/pr/2009-03/sunflash.20090318.2.xml">announced</a> that they will use <a href="http://eucalyptus.cs.ucsb.edu/">EUCALYPTUS</a> as the control interface to their solution. EUCALYPTUS is an open-source implementation of the AWS APIs.</p>

<p>Last week at <a href="http://qconlondon.com">QCon London</a>, we heard <a href="http://www.linkedin.com/in/simonwardley">Simon Wardley</a> give a brilliant talk, in which he described <a href="http://www.canonical.com/">Canonical</a>'s plan to create a de facto open standard for cloud computing by seeding the market with open source implementations. Canonical's plan? <a href="http://www.ubuntu.com/">Ubuntu</a> and private clouds running EUCALYPTUS.</p>

<p>It looks like Amazon may be setting the standard for cloud computing, in the same way that Intel set the standard for desktop and server computing, by defining the programming interface.</p>

<p>I don't worry about this, for two reasons. One, it forestalls any premature efforts to force a de jure standard. This space is still young enough that an early standard can't help but be a drag on exploration of different business and technical models. Two, Amazon has done an excellent job as a technical leader. If their APIs "win" and become de facto standards, well, we could do a lot worse.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2009/03/amazon_as_the_new_intel.html</link>
         <guid>http://www.michaelnygard.com/blog/2009/03/amazon_as_the_new_intel.html</guid>
         <category>Cloud Computing</category>
         <pubDate>Wed, 18 Mar 2009 11:31:07 -0600</pubDate>
      </item>
      
   </channel>
</rss>
