<?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>Wed, 21 Apr 2010 08:00:00 -0600</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/?v=4.24-en</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

      
      <item>
         <title>Time motivates architecture</title>
         <description><![CDATA[<p>Let's engage in a thought experiment for a moment. Suppose that software was trivial to create and only ever needed to be used once. Completely disposable. So, somebody comes to you and says, "I have a problem and I need you to solve it. I need a tool that will do blah-de-blah for a little while." You could think of the software the way that a carpenter thinks of a jig for cutting a piece of wood on a table saw, or a metalworker thinks of creating a jig to drill a hole at the right angle and depth.</p>

<p>If software were like this, you would never care about its architecture. You would spend a few minutes to create the thing that was needed, it would be used for the job at hand, and then it would be thrown away. It really wouldn't matter how good the software was on the inside--how easy it was to change--because you'd never change it! It wouldn't matter how it adapted to changing business requirements, because you'd just create a new one when the new requirement came up. In this thought experiment we wouldn't worry about architecture.</p>

<p>The key difference between this thought experiment and actual software? Of course, actual software is <em>not</em> disposable. It has a lifespan over some amount of time. Really, it's the time dimension that makes architecture important.</p>

<p>Over time, we need for many different people to work effectively in the software. Over time, we need the throughput of features to stay constant, or hopefully not decrease too much. Maybe it even increases in particularly nice cases. Over time, the business needs change so we need to adapt the software.</p>

<p>It's really time that makes us care about architecture.</p>

<p>Isn't it interesting then, that we never include time as a dimension in our architecture descriptions?</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2010/04/time_motivates_architecture.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/04/time_motivates_architecture.html</guid>
         <category></category>
         <pubDate>Wed, 21 Apr 2010 08:00:00 -0600</pubDate>
      </item>
      
      <item>
         <title>Circuit Breaker in Scala</title>
         <description><![CDATA[<p><a href="http://blog.fakod.eu/">FaKod</a> (I think that translates as "The Fatalistic Coder"?) has written a nice Scala implementation of the Circuit Breaker pattern, and even better, has made it available on GitHub.</p>

<p>Check out <a href="http://github.com/FaKod/Circuit-Breaker-for-Scala">http://github.com/FaKod/Circuit-Breaker-for-Scala</a> for the code.</p>

<p>The Circuit Breaker can be mixed in to any type. See <a href="http://wiki.github.com/FaKod/Circuit-Breaker-for-Scala/">http://wiki.github.com/FaKod/Circuit-Breaker-for-Scala/</a> for an example of usage.</p>
]]></description>
         <link>http://www.michaelnygard.com/blog/2010/04/circuit_breaker_in_scala.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/04/circuit_breaker_in_scala.html</guid>
         <category>Books</category>
         <pubDate>Wed, 21 Apr 2010 06:00:00 -0600</pubDate>
      </item>
      
      <item>
         <title>The Future of Software Development</title>
         <description><![CDATA[<p>I've been asked to sit on a panel regarding the future of software
development. This is always risky and makes me nervous, for two reasons. First, prediction is a notoriously low success-rate activity. Second, the people you always see making predictions like this are usually well past their "use by" date. Nevertheless, here are a collection of barely-related thoughts I have on that subject.</p>

<ul>
<li><p>Two obvious trends are cloud computing and mobile access. They are
complementary. As the number of people and devices on the net
increases, our ability to shape traffic on the demand side gets
worse. Spikes in demand will happen faster and reach higher levels
over time. Mobile devices exacerbate the demand side problems by
greatly increasing both the number of people on the net and the
fraction of their time they are able to access it.</p></li>
<li><p>Large traffic volumes both create and demand large data. Our tools
for processing tera- and petabyte datasets will improve
dramatically. Map/Reduce computing (a la Hadoop) has created
attention and excitement in this space, but it is ultimately just
one tool among many. We need better languages to help us think and
express large data problems. In particular, we need a language that
makes big data processing accessible to people with little
background in statistics or algorithms.</p></li>
<li><p>Speaking of languages, many of the problems we face today cannot be
solved inside a single language or application. The behavior of a
web site today cannot be adequately explained or reasoned about just
by examining the application code. Instead, a site picks up
attributes of behavior from a multitude of sources: application
code, web server configuration, edge caching servers, data grid
servers, offline or asynchronous processing, machine learning
elements, active network devices (such as application firewalls),
and data stores. "Programming" as we would describe it today--coding
application behavior in a request handler--defines a diminishing
portion of the behavior. We lack tools or languages to express and
reason about these distributed, extended, fragmented
systems. Consequently, it is difficult to predict the functionality,
performance, capacity, scalability, and availability of these
systems.</p></li>
<li><p>Some of this will be mitigated naturally as application-specific
functions disappear into tools and frameworks. Companies innovating
at the leading edge of scalability today are doing things in
application-specific behavior to compensate for deficiencies in
tools and platforms. For example, caching servers could arguably
disappear into storage engines and no-one would complain. In other
words, don't count the database vendors out yet. You'll see
key-value stores and in-memory data grid features popping up in
relational databases any day now.</p></li>
<li><p>In general, it appears that Objects will diminish as a programming
paradigm. Object-oriented programming will still exist... I'm not
claiming "the death of objects" or something silly like
that. However, OO will become just one more paradigm among several,
rather than the dominant paradigm it has been for the last 15
years. "Object oriented" will no longer be synonymous with
"good".</p></li>
<li><p>Some people have talked about "polyglot programming". I think this
is a red herring. Polylgot is a reality, but it should not be a
goal. That is, programmers should know many languages and paradigms,
but deliberately mixing languages in a single application should be
avoided. What I think we will find instead is mixing of paradigms,
supported by a single primary language, with adjunct languages used
only as needed for specialized functions. For example, an
application written in Scala may mix OO, functional, and actor-based
concepts, and it may have portions of behavior expressed in SQL and
Javascript. Nevertheless, it will still primarily be a Scala
application. The fact that Groovy, Scala, Clojure, and Java all run
on Java Virtual Machine shouldn't mislead us into thinking that they
are interchangeable... or even interoperable!</p></li>
<li><p>Regarding Java. I fear that Java will have to be abandoned to the
"Enterprise Development" world. It will be relegated to the hands of
cut-rate business coders bashing out their gray business
applications for $30 / hour. We've passed the tipping point on this
one. We used to joke that Java would be the next COBOL, but that
doesn't seem as funny now that it's true. Java will continue to
exist. Millions of lines of it will be written each year. It won't
be the driver of innovation, though. As individual programmers, I'd
recommend that you learn another language immediately and
differentiate yourself from the hordes of low-skill, low-rent
outsource coders that will service the mainstream Java consumer.</p></li>
<li><p>Where will innovation come from? Although some of the blush seems to
be coming off Ruby, the reduction in hype has mainly allowed Ruby
and Ruby on Rails developers to knuckle down and <em>produce</em>. That
community continues to drive tremendous innovation. Many of the
interesting developments here relate to process. Ruby developers
have given us fantastic tools like Gems and Capistrano, that let
small teams outperform and outproduce groups four times their size.</p></li>
<li><p>To my great surprise, data storage has become a hotbed of innovation
in the last few years. Some of this is driven by the
high-scalability fetishists, which is probably the wrong reason for
98% of companies and teams. However, innovations around column
stores, graph databases, and key-value stores offer developers new
tools to reduce the impedance mismatch between their data storage
and their programming language. We spent twenty years trying to
squeeze objects into relational databases. Aside from the object
databases, which were an early casualty of Oracle's ascension, we
mostly focused on changing the application code through framework
after framework and ORM after ORM. It's refreshing to see storage
models that are easier to use and easier to modify.</p></li>
<li><p>This will also cause another flurry of "reactive innovation" from
the database vendors, just as we saw with "Universal Databases" in
the mid-90s. The big players here--Microsoft and Oracle--won't let
some schemaless little upstarts erode their market share. More
significantly, they aren't about to let their flagship products--and
the ones which give them beachheads inside every major
corporation--get intermediated by some open-source frameworks banged
up by the social network giants. Look for big moves by these vendors
into high scalability, agile storage, and eventual consistency
storage.</p></li>
</ul>
]]></description>
         <link>http://www.michaelnygard.com/blog/2010/04/the_future_of_software_develop.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/04/the_future_of_software_develop.html</guid>
         <category>Speaking</category>
         <pubDate>Tue, 20 Apr 2010 06:00:00 -0600</pubDate>
      </item>
      
      <item>
         <title>Failover: Messy Realities</title>
         <description><![CDATA[		<p>
			People who don't live in operations can carry some funny misconceptions in their heads. Some of my personal faves:
		</p>
		<ul>
			<li>Just add some servers!
			</li>
			<li>I want a report of every configuration setting that's different between production and QA!
			</li>
			<li>We're going to make sure this (outage) never happens again!
			</li>
		</ul>
		<p>
			I've recently been reminded of this during some discussions about disaster recovery. This topic seems to breed misconceptions. Somewhere, I think most people carry around a mental model of failover that looks like this:
		</p>
		<p>
			<a href="/images/blog/failover/mental_model.png" target="_blank"><img src="/images/blog/failover/mental_model.png" style="border: none; float: none;" alt="Normal operations transitions directly and cleanly to failed over" width="297" height="345"></a>
		</p>
		<p>
			That is, failover is essentially automatic and magical.
		</p>
		<p>
			Sadly, there are many intermediate states that aren't found in this mental model. For example, there can be quite some time between failure and it's detection. Depending on the detection and notification, there can be quite a delay before failover is initiated at all. (I once spoke with a retailer whose primary notification mechanism seemed to be the Marketing VP's wife.)
		</p>
		<p>
			Once you account for delays, you also have to account for faulty mechanisms. Failover itself often fails, usually due to configuration drift. Regular drills and failover exercises are the <em>only</em> way to ensure that failover works when you need it. When the failover mechanisms themselves fail, your system gets thrown into one of these terminal states that require manual recovery.
		</p>
		<p>
			Just off the cuff, I think the full model looks a lot more like this:
		</p>
		<p>
			<a href="/images/blog/failover/real_states.png" target="_blank"><img src="/images/blog/failover/real_states.png" style="border: none; float: none;" alt="Many more states exist in the real world, including failure of the failover mechanism itself." width="597" height="696"></a>
		</p>
		<p>
			It's worth considering each of these states and asking yourself the following questions:
		</p>
		<ul>
			<li>Is the state transition triggered automatically or manually?
			</li>
			<li>Is the transition step executed by hand or through automation?
			</li>
			<li>How long will the state transition take?
			</li>
			<li>How can I tell whether it worked or not?
			</li>
			<li>How can I recover if it didn't work?
			</li>
		</ul>
]]></description>
         <link>http://www.michaelnygard.com/blog/2010/04/failover_messy_realities.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/04/failover_messy_realities.html</guid>
         <category>Architecture</category>
         <pubDate>Mon, 19 Apr 2010 06:00:00 -0600</pubDate>
      </item>
      
      <item>
         <title>Life&apos;s Little Frustrations</title>
         <description><![CDATA[<blockquote>A distributed system is one in which the failure of a computer you didn't even know existed can render your own computer unusable. -Leslie Lamport</blockquote>

<p>
On my way to <a href="http://qcontokyo.com/">QCon Tokyo</a> and <a href="http://www.qconbeijing.com/">QCon China</a>, I had some time to kill so I
headed over to <a href="http://www.delta.com/traveling_checkin/airport_information/delta_sky_club/index.jsp">Delta's Skyclub</a> lounge. I've been a member for a few
years now. And why not? I mean, who could pass up tepid coffee, stale
party snacks, and a TV permanently locked to CNN?  Wait... that actually
doesn't sound like such a hot deal.
</p>

<p>
Oh! I remember, it's for the wifi access. (Well, that plus reliably
clean bathrooms, but we need not discuss that.) Being able to count on
wifi access without paying for yet another data plan has been pretty
helpful for me. (As an aside, I might change my tune once I try a <a href="http://www.verizonwireless.com/b2c/mobilebroadband/?page=products_mifi">mifi</a> box. Carrying my own hotspot sounds even better.)
</p>

<p>
Like most wifi providers, the Skyclub has a captive portal. Before you
can get a TCP/IP connection to anything, you have to submit a form
with a checkbox to agree to 89 pages of terms and conditions. I'm well
aware that Delta's lawyers are trying to make sure the company isn't
liable if I go downloading bootlegs of every <a href="http://en.wikipedia.org/wiki/List_of_Ally_McBeal_episodes">Ally McBeal episode</a>. But
I really don't know if these agreements are enforceable. For all I
know, page 83 has me agreeing to 7 years indentured servitude cleaning
Delta's toilets.
</p>

<p>
Anyway, Delta has outsourced operations of their wifi network to
<a href="http://www.concoursecommunications.com/">Concourse Communications</a>. And apparently, they've had an outage all
morning that has blocked anyone from using wifi in the Minneapolis
Skyclubs. When I submit the form with the checkbox, I get the
following error page:
</p>

<a target="_blank" href="/images/blog/skyclub/skyclub_error_1.png">
<img width="622" height="211" style="border: none; float: none;" src="/images/blog/skyclub/skyclub_error_1.png" /></a>

<p>
Including this bit of stacktrace:
</p>

<a target="_blank" href="/images/blog/skyclub/skyclub_error_1.png
/images/blog/skyclub/skyclub_error_2.png">
<img width="537" height="58" border="0" style="border: none; float: none;" src="/images/blog/skyclub/skyclub_error_2.png"/></a>

<p>
There's a lot to dislike here.
</p>

<ol>
<li>
Why is this yelling at me, the user? To anyone who <i>isn't</i> a web
site developer, this makes it sound like the user did something
wrong. There's a ton of scary language here: &quot;instance-specific
error&quot;, &quot;allow remote connections&quot;, &quot;Named Pipes Provider&quot;... heck,
this sounds like it's accusing the user of hacking servers.  &quot;Stack
trace&quot; sure sounds like the Feds are hot on somebody's trail, doesn't
it?
</li>

<li>
Isn't it fabulous to know that Ken keeps his projects on his D:
drive? If I had to lay bets, I'd say that Ken screwed up his
configuration string. In fact, the whole problem smells like a failed
deployment or poorly executed change. Ken probably pushed some code
out late on a Friday afternoon, then boogied out of town. My
prediction (totally unverifiable, of course) is that this problem will
take less than 5 minutes to resolve, once Ken gets his ass back from
the beach.
</li>

<li>
We mere users get to see quite a bit of internal
information here. Nothing really damaging, unless of course <a href="http://www.ormapper.net/">Wilson
ORMapper</a> has some security defects or something like that.
</li>

<li>
Stepping back from this specific error message, we have the larger
question: is it sensible to couple availability of the network to the
availability of this check-the-box application? Accessing the network
is the primary purpose of this whole system. It is the most critical
feature. Is collecting a compulsory boolean &quot;true&quot; from every user
really as important as the reason the whole damn thing was built in
the first place? Of course not!  (As an aside, this is an example of <a href="http://en.wikipedia.org/wiki/Systemantics">Le Chatelier's Principle</a>: &quot;Complex systems tend to oppose their own proper function.&quot;)
</li>
</ol>

<p>
We see this kind of operational coupling all the time. Non-critical
features are allowed to damage or destroy critical features. Maybe
there's a single thread pool that services all kinds of requests,
rather than reserving a separate pool for the important things. Maybe
a process is overly linearized and doesn't allow for secondary,
after-the-fact processing. Or, maybe a critical and a non-critical
system both share an enterprise service---producing a common-mode
dependency.
</p>

<p>
Whatever the proximate cause, the underlying problem is
lack of diligence in operational decoupling.
</p>]]></description>
         <link>http://www.michaelnygard.com/blog/2010/04/lifes_little_frustrations.html</link>
         <guid>http://www.michaelnygard.com/blog/2010/04/lifes_little_frustrations.html</guid>
         <category>Architecture</category>
         <pubDate>Sun, 18 Apr 2010 18:24:40 -0600</pubDate>
      </item>
      
      <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>
      
   </channel>
</rss>
