<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">

  <title>def euler(x); cos(x) + i*sin(x); end</title>
  <link href="http://brixen.io/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://brixen.io/" rel="alternate" type="text/html"/>
  <updated>2012-04-09T13:30:36-07:00</updated>
  <id>blog.brightredglow.com/</id>

  
  <entry>
    <title>Is Node.js Better?</title>
    <id>http://brixen.io/2012/4/9/is_node_js_better</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2012/4/9/is_node_js_better" />
    <published>2012-04-09T00:00:00-07:00</published>
    <updated>2012-04-09T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; &lt;em&gt;This is essentially a transcript of (though mostly written before)
my JSConf 2012 talk, &amp;ldquo;Is Node.js better?&amp;rdquo;. It&amp;rsquo;s long, I know. There is no
tl;dr, sorry.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this better than that?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a question that we confront constantly. Numerous times a day, in fact.
And sometimes a lot rides on the answer. Is this job offer better than that
one? Is this car better than that one? Is this home for my ailing mother
better than that one? Is this billing system better than that one? Is this tax
plan better than that one?&lt;/p&gt;

&lt;p&gt;This question is everywhere. We cannot escape it. Yet for the frequency with
which we confront it, our approach to resolving the question is quite likely
&lt;em&gt;not&lt;/em&gt; objective. Which is to say, we are probably not answering the question
in a way that is mostly likely to benefit us. Many used car sales, software
system sales, and political campaigns, to mention a few things, profit from
our incompetence answering this question. We&amp;rsquo;ll consider some of the reasons
why that is true later. But just recognizing this is rather distressing.&lt;/p&gt;

&lt;p&gt;But we&amp;rsquo;re not just asking, &amp;ldquo;is this better than that?&amp;rdquo; in general; we&amp;rsquo;re here
at JSConf and this talk is about Node.js. Why? You probably know that I&amp;rsquo;m not
a notable member of the Javascript community. I have not authored a single JS
library. I&amp;rsquo;ve never given a talk at a JSConf. Why am I here? And why am I
talking about Node.js?&lt;/p&gt;

&lt;p&gt;I met Chris Williams at &lt;a href=&quot;http://codeconf.com/&quot;&gt;CodeConf 2011&lt;/a&gt;, organized by
&lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;. Chris sat down next to me during the Node.js
talk by Ryan Dahl. I found the talk fascinating because much of it focused on
improving the non-blocking I/O facilities in V8 for both Windows and Unix-ish
platforms. This was something that we have a lot of interest in for the
Rubinius project and I had then recently started porting Rubinius to Windows.&lt;/p&gt;

&lt;p&gt;At the time, I had no idea who Chris was. But we chatted a bit and at the
break, Chris stood up and said, &amp;ldquo;I&amp;rsquo;m going to get some more beer, would you
like some?&amp;rdquo; Holy shit. &lt;em&gt;That&amp;rsquo;s why I had been smelling beer for the last 45
minutes!&lt;/em&gt; Chris had a coffee cup full of beer. Hilarious. One person&amp;rsquo;s
moderation is another person&amp;rsquo;s excess.&lt;/p&gt;

&lt;p&gt;I declined the beer then but we exchanged contact info and Chris put me in
touch with folks from Microsoft who were assisting with getting Node.js
running well on Windows. Chris also informed me of the upcoming JSConf that
was being held in Portland, where I live. It was too late to get tickets but I
was able to attend the opening party and made a point to hang out as much as I
could with the other attendees at conference events. At the time of CodeConf,
I was merely curious about Node.js, but I didn&amp;rsquo;t have much of an opinion.&lt;/p&gt;

&lt;p&gt;Fast-forward almost nine months. I was seeing a flurry of tweets about
Node.js. This got my attention, in part because of the people who where
tweeting about it. I use Twitter as one of my main sources of information
about developing technology. The more tweets I saw, the more uneasy I felt.
Finally, one morning I posted this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/node_challenge.png&quot; alt=&quot;Node.js challenge&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My intent was not to be antagonistic. Rather, my challenge was focused on
finding out what sort of problems people were solving with Node.js. But any
challenge, even a sincere one, carries a connotation of aggressiveness. And it
is a fact of human nature that when pushed, people tend to push back. Some of
the responses to my tweet attempted to share knowledge but others were
understandably of the genre, &amp;ldquo;if you&amp;rsquo;re looking for a fight, you&amp;rsquo;ll find one
here.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;It wasn&amp;rsquo;t long before Chris DM&amp;rsquo;d me and basically said, &amp;ldquo;What&amp;rsquo;s up with this
&amp;lsquo;challenge&amp;rsquo;? You are working on important stuff, why are you wasting time on
this?&amp;rdquo; I answered that I was genuinely interested in understanding why people
are using Node.js. We exchanged a few comments over a several days and Chris
asked if I was willing to do a talk on the subject. So that is how I got here,
talking about Node.js at JSConf. It is a honor and privilege to be here and I
thank Chris and the conference organizers, as well as all of you.&lt;/p&gt;

&lt;p&gt;So who am I? I&amp;rsquo;ve been working on the &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; project for
the past five years, and four of those while employed full-time by &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine
Yard&lt;/a&gt;. I started the &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpec&lt;/a&gt;
project as part of my work on Rubinius. Through my work on Rubinius, I have
learned a lot about compilers, virtual machines, garbage collectors, and
importantly, concurrency. One of the notable points about Rubinius is we have
removed the global interpreter lock (GIL) so that multiple native threads can
run Ruby code in parallel on multi-core or multi-CPU hardware. We see this
ability as vital to the success of Rubinius.&lt;/p&gt;

&lt;p&gt;Now that you know how I came to be speaking at JSConf and you know a little
about what I do, the question remains, &amp;ldquo;&lt;em&gt;Why&lt;/em&gt; am I speaking at JSConf? Why do
I care about Node.js?&amp;rdquo; The answer to that will take us on a journey through
some interesting territory. I only ask that you suspend prejudice and follow
along. If you ultimately disagree with me, there is nothing wrong with that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Organizations tend to perpetuate the problem they were created to solve.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don&amp;rsquo;t remember exactly when I was introduced to this idea, but it had a
significant effect on me. There are a lot of difficult problems to solve in
the world and one of the first things we tend to do is create an organization
that is dedicated to some aspect or another of a solution. Notice that there
is a difference between people organizing to solve a problem and an
organization. As soon as we have an organization, it will tend to take actions
to perpetuate itself. Of course, these actions are really the decisions of
people &lt;em&gt;in&lt;/em&gt; the organization. The organization has no effective power
independent of the people who comprise it, yet the organization as a whole is
a system, and will tend to exhibit life-preserving actions. If an organization
exists to solve a problem, and that problem is solved, the organization ceases
to have a reason to exist.&lt;/p&gt;

&lt;p&gt;Every time we organize for any reason, there is a tendency for structures to
solidify. The rigidity of those structures tend to inhibit movement and change
as circumstances change. Therefore, a vital force in social organization is
the force that opposes established order. There is a name for this force:
&lt;em&gt;subversive&lt;/em&gt;, something seeking or intending to subvert an established system
or institution. People who participate in subversive activities are called
subversives.&lt;/p&gt;

&lt;p&gt;There is another aspect to this that is important. People tend to be in one of
two groups: those who fear change and those who create change. When we think
of &amp;ldquo;change&amp;rdquo;, it usually has a positive connotation, and &amp;ldquo;subversive&amp;rdquo; has a
negative connotation. But they are often the same thing. Change can be
positive or negative. But as it has been said, &amp;ldquo;there is only one constant:
change.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Javascript has been an amazing technology wielded by people who have radically
and fundamentally changed how we interact on the web. This is fascinating and
tremendously valuable for societies all over the world. So part of the reason
why I&amp;rsquo;m speaking here is that people enthusiastic about Javascript are people
who are creating change. I want to acknowledge, assist, encourage, collaborate
with, and influence people who are actively working to change the world for
the better.&lt;/p&gt;

&lt;p&gt;This talk is about conflict resolution. Conflict is inherent in the question,
&amp;ldquo;Is this better than that?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s important to note that any contrast implies conflict. Sometimes people
assert that you should be able to promote something without saying anything
bad about something else. This idea is impossible to comprehend. If I say,
&amp;ldquo;water is good,&amp;rdquo; it is inherent, even when implicit, that I&amp;rsquo;m saying water has
value and value is a concept that relies on a context and a standard. There is
no concept of value that is not relational. Something is only good relative to
what you are judging it against.&lt;/p&gt;

&lt;p&gt;Criticism is advocacy; advocacy is criticism. Criticism is also controversy
and controversy is entertaining. However, despite the entertainment value,
different ways of resolving conflict can have very negative consequences.
Usually when there is conflict, we address it with aggression. We talk about
having a &amp;ldquo;shootout&amp;rdquo;, &amp;ldquo;fight&amp;rdquo;, &amp;ldquo;throw down&amp;rdquo;, etc. But are fights a healthy,
beneficial way to resolve controversy?&lt;/p&gt;

&lt;p&gt;Further, when a person comes out as a strong advocate for some technology,
people opposed to the technology will hurl the epithet &amp;ldquo;fanboi&amp;rdquo; as an attempt
to discredit the idea by attacking the person. From the other direction, if we
don&amp;rsquo;t like someone&amp;rsquo;s criticism, we may call the person a &amp;ldquo;troll&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Other times, we will simply attempt to avoid conflict entirely. In Ruby, there
is this idea, MINASWAN: &lt;em&gt;Matz is nice and so we are nice.&lt;/em&gt; There is nothing
wrong with being nice, but why is &amp;ldquo;nice&amp;rdquo; contrasted with &amp;ldquo;criticism&amp;rdquo;? Are we
supposed to never challenge someone because being &amp;ldquo;nice&amp;rdquo; is more important and
challenging them is inherently not nice?  What if someone is doing something
that from our experience is not beneficial to themselves or others?&lt;/p&gt;

&lt;p&gt;For the most part, this is how I see us dealing with conflict. We either avoid
it or we attempt to devalue the person rather than discuss the idea. This is
dysfunctional. Basically, we suck at conflict.&lt;/p&gt;

&lt;p&gt;How can we improve how we deal with conflict?&lt;/p&gt;

&lt;p&gt;I assert that we need to use science. But how? What does that mean? To
understand this, we need to look more deeply at how we as humans think. But
before we get to that, let&amp;rsquo;s consider a very common aspect of social
organization: the tendency to surrender our own judgment to that of an
&amp;ldquo;expert&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In 1948, Alex Osborn, who was an ad man at B.B.D.O., wrote a book, &lt;em&gt;Your
Creative Power&lt;/em&gt;, where he introduced &amp;ldquo;brainstorming&amp;rdquo;. Essentially, a group of
people toss out solutions to a problem under consideration. The emphasis is on
generating as many ideas as possible. A key element of the activity is that
everyone is told not to criticize their own or other&amp;rsquo;s ideas. It was asserted
that creativity was too delicate a process to withstand the harsh light of a
critical challenge.&lt;/p&gt;

&lt;p&gt;Of course, that made a lot of sense to people. Over the years, brainstorming
has been used extensively in problem solving. It is still heavily used. The
problem is, the method is flawed. The proscription against criticism happens
to be wrong.&lt;/p&gt;

&lt;p&gt;There were two studies that tested the two main components of the
brainstorming methodology for discovering creative solutions. The first
focused on individuals versus groups. The result was that people working alone
produced not just more but better ideas than the groups.&lt;/p&gt;

&lt;p&gt;The second study focused on the suspension of criticism. The subjects were
divided into three groups. The first group were instructed to use
brainstorming and told not to criticize their own or each other&amp;rsquo;s ideas. The
second group were instructed to challenge and debate one another. The last
group was allowed to organize themselves without any instruction in a
particular method. The results from this experiment were unambiguous. The
debaters significantly outscored both other groups. The act of criticizing
other&amp;rsquo;s ideas causes both the questioner to understand the idea more fully and
the person proposing the idea to go more deeply into it.&lt;/p&gt;

&lt;p&gt;The important lesson is two-fold. Criticism is an important aspect of
creative, intellectual effort. Despite the proscription against criticism
having superficial validity, it was rather easily disproved.&lt;/p&gt;

&lt;p&gt;Another interesting study related to creativity examined whether there was a
correlation between the success of Broadway musicals and how well the team
producing the musical knew each other. The measure of team familiarity was
named the Q factor. A team where all the members had worked together before
would have a high Q factor. A team where no members had worked together before
would have a low Q factor. The study found that there was indeed a significant
statistical correlation between Q factor and success of a musical. In other
words, a certain range of Q factor was a good predictor of success. The value
of Q that was most likely to predict success was from a team where most
members had worked together previously but some members had not. A team where
no one had worked together wasn&amp;rsquo;t able to communicate effectively enough. A
team where everyone had worked together didn&amp;rsquo;t benefit from an outsider&amp;rsquo;s
perspective challenging ideas.&lt;/p&gt;

&lt;p&gt;These results are reported in &lt;em&gt;Groupthink: The Brainstorming Myth&lt;/em&gt; by Jonah
Lehrer, published in &lt;em&gt;New Yorker&lt;/em&gt; magazine, January 30th, 2012. The lesson we
can take is that criticism is important to creative solutions to problems and
we should be seeking people who are unfamiliar with our favorite language or
framework to join us and help our understanding of problems and the solutions
we are building.&lt;/p&gt;

&lt;p&gt;Another lesson is that there is nothing that prevents a well-meaning and
experienced expert from being wrong. One thing that we should all be
challenging is &amp;ldquo;appeals to authority&amp;rdquo; in decision making. As you can see from
the following tweet, Ward Cunningham thinks Node.js is the future of the
server side. However, that assertion is most likely not taken by readers of
the tweet as a neutral assertion of fact about Ward&amp;rsquo;s opinion. It is taken as
meaningful because Ward said it. Further, it is unremarkable that the
assertion is unaccompanied by any evidence with which to help determine the
validity of the assertion. Assertions by experts with no accompanying evidence
are the &lt;em&gt;status quo&lt;/em&gt; in our industry, and that should be extremely
embarrassing.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/node_future.png&quot; alt=&quot;Appeal to authority&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The next part of our journey takes us to one of the most interesting books I
have read. &lt;em&gt;Thinking Fast and Slow&lt;/em&gt; by Daniel Kahneman (Farrar, Straus and
Giroux, 2011) is a book about how our minds work. There are basically two
modes that have distinct and surprising features in the way we think. These
two modes influence one another.&lt;/p&gt;

&lt;p&gt;One mode is called fast thinking because our brains activate an entire network
of associations in a sub-second burst of activity. For example, if I display
the word &amp;ldquo;bacon&amp;rdquo;, you will immediately have numerous memories and associations
with bacon coming into awareness. This fast mode is all about pattern matching
and the associations activated can be extensive and surprising. In this mode,
the brain over-achieves, if you will. It activates far more associations than
may be needed. And some associations may be surprising. It is up to the second
mode to use those associations depending on the task we are confronted with.&lt;/p&gt;

&lt;p&gt;The other mode is called slow thinking and is related to such activities as
concentration, judgment, monitoring, and selecting. If I ask, &amp;ldquo;what is 23 x
47?&amp;rdquo; Answering this requires deliberate application of a set of tasks to
arrive at the answer, unless the problem is one we are quite familiar with,
in which case the fast thinking would just produce the answer as an
association.&lt;/p&gt;

&lt;p&gt;The book is filled with fascinating knowledge about how our thinking works and
I cannot recommend it highly enough. It discusses numerous ways in which our
thinking can produce erroneous beliefs and ideas. One of the very interesting
results is that our deliberate, slow thinking can be easily fooled into
accepting a wrong answer provided by our fast thinking mode if we feel at
ease. But if we feel anxious, our slow thinking mode will be more critical and
less likely to just accept an answer provided by our fast thinking mode.&lt;/p&gt;

&lt;p&gt;Reading &lt;em&gt;Thinking Fast and Slow&lt;/em&gt; and reflecting on the complex and
inter-related behaviors that scientists have been able to discover facts about
led me to the following conclusion:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Programming is a behavioral science.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Behavioral science is a very broad category that encompasses disciplines that
explore the activities and interactions among organisms through systematic
analysis and investigation using controlled observation and scientific
experimentation.&lt;/p&gt;

&lt;p&gt;There is a distinction between programming and computer science. Writing
software is an activity that is mostly centered on human behaviors. Most
software will interact with people at some point. Basically, it is written by
people, for people, and funded by people. Of course, there are mathematical
foundations of computing and algorithms, but those are rarely the most
important elements of the process of creating software.&lt;/p&gt;

&lt;p&gt;If you are familiar with the many methodologies under the &amp;ldquo;Agile&amp;rdquo; umbrella,
you know that dealing with changing requirements is one of the most complex
aspects of software construction. But note that those changes are almost
entirely due to human behaviors. If we build a bridge, an environmental study
will determine most of the forces that the bridge design must account for.
Further, the laws of physics are quite well established. Engineering the
bridge is not a terribly complex activity. However, in software, there is not
a good way to clearly establish the constraints for the system we are
building. People are responsible for most of the complexity in programming.
That is why I assert it is a behavioral science.&lt;/p&gt;

&lt;p&gt;What is curious to me is that a typical undergrad psychology student will
likely have more exposure to research methods than a typical computer science
undergrad or even graduate student. Research methods are activities directed
at determining the &lt;em&gt;validity&lt;/em&gt; of assertions. They are what enable us to
separate knowledge from opinion. Fundamentally, they are related to two
aspects of existence: the nature of the world (meta-physics) and the theory of
knowledge (epistemology). To learn more about this, I would recommend
&lt;em&gt;Research Methods: the basics&lt;/em&gt; by Nicholas Walliman (Routledge 2011).&lt;/p&gt;

&lt;p&gt;Turning from this general information about applying science to thinking and
learning about research methods, let&amp;rsquo;s look at Node.js again. One of the major
assertions about Node.js is that it permits writing efficient web servers that
must deal with many concurrent connections. So, let&amp;rsquo;s look at some basic
features of concurrency, including a possible definition of concurrency.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;People are selfish, lazy, and easily bored.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I say that without any moral judgment. I think these are all biologically
desirable features of organisms. We are selfish because we are responsible for
our own well-being. We are lazy so we don&amp;rsquo;t waste precious and
costly-to-obtain energy. We are easily bored because we must constantly
incorporate new material to maintain our existence. Of course, each of these
attributes has an opposite and any individual will exhibit a combination of
these behaviors. But these three attributes are interesting to consider in
this context.&lt;/p&gt;

&lt;p&gt;Scarcity is a fact of life. Infinity is a mathematical fantasy. There are a
finite number of computers.&lt;/p&gt;

&lt;p&gt;Combine scarcity with the attributes above about people and we have a reason
for concurrency in computation.&lt;/p&gt;

&lt;p&gt;When a single CPU with a single core is running, it can basically execute one
instruction at a time. Of course, this is a simplification, but it is
basically true. If we consider a program to be a sequence of instructions,
I&lt;sub&gt;1&lt;/sub&gt;..I&lt;sub&gt;n&lt;/sub&gt;, every possible ordering of those instructions is
a plausible definition of concurrency. For example, a four instruction program
could be I&lt;sub&gt;1&lt;/sub&gt;, I&lt;sub&gt;2&lt;/sub&gt;, I&lt;sub&gt;3&lt;/sub&gt;, I&lt;sub&gt;4&lt;/sub&gt; or
I&lt;sub&gt;3&lt;/sub&gt;, I&lt;sub&gt;1&lt;/sub&gt;, I&lt;sub&gt;2&lt;/sub&gt;, I&lt;sub&gt;4&lt;/sub&gt;, etc. Not all
orderings are going to be meaningful given the semantics we expect from the
program.&lt;/p&gt;

&lt;p&gt;Now, consider that the program would be 100% efficient if all the instructions
are dedicated to solving the problem for which the program exists. However, if
any instructions are dedicated to changing the order of instructions, those
would reduce the efficiency of the program by doing work that is not directly
related to solving the problem.&lt;/p&gt;

&lt;p&gt;Once upon a time, computers solved problems one at a time. The jobs were
processed from start to finish one at a time. This is great for efficiency but
not great for people. People don&amp;rsquo;t want to wait for everyone else&amp;rsquo;s job to
finish before theirs. Nor are they willing to do a lot of extra work to make
the computer most efficient. So the idea of time-sharing systems was born.
Essentially, everyone got a little slice of time to use the CPU. Even though
some efficiency was lost, and so everyone&amp;rsquo;s program would ultimately take
longer to complete, the average time to wait went from hours (a whole day,
perhaps) to possibly a few minutes. Computers became interactive.&lt;/p&gt;

&lt;p&gt;There are only a few mechanisms to re-order the instructions of a sequential
program. (Note that we can generalize from the instructions of a single
program to the instructions of a set of programs concatenated together. The
fundamental considerations do not change.) One way would be to do a little
work and then voluntarily yield control of the CPU to another program.  At
some later time, another program would yield control back to us. This would
implement cooperative multitasking. Another way would be for some sort of
supervisor to allocate a short amount of time to each program in sequence.
This would implement pre-emptive multitasking. Once your time-slice is over,
you simply have to wait until everyone else gets a time-slice before you can
run again. Yet another way would be to allow a program to run until it
performed some action, like writing to the display or reading from the disk.&lt;/p&gt;

&lt;p&gt;Each of these mechanisms for interleaving the instructions of a serial program
may have different trade-offs, and consequently, different efficiencies.
However, there is nothing inherent in any method that dictates it would be
more efficient than any other. I consider this a very important point missing
from almost every assertion about the uniqueness of Node.js. People are
saying, and others are repeating, that Node.js enables solutions that are not
possible with other programming languages and frameworks. This is absolutely
false.&lt;/p&gt;

&lt;p&gt;There is a lot more to understand about concurrency, modern CPUs, and
efficiency than we can cover here. However, if you are concerned with the
validity of the assertion that Node.js is good technology for writing
efficient web servers, then you may want to understand more about concurrency.&lt;/p&gt;

&lt;p&gt;Besides concurrency, there are a number of justifications given for using
Node.js. Are these justifications valid? I think consistency is important. If
I say X is better than some Y because of some reason J, and there is some X&amp;rsquo;
that is basically equivalent to X and Y&amp;rsquo; equivalent to Y, then X&amp;rsquo; should
probably be better than Y&amp;rsquo; for the same reason J. That idea is expressed in
symbols below, where the long horizontal line means that the statements above
logically &lt;em&gt;imply&lt;/em&gt; the statement below the line.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/justification.png&quot; alt=&quot;Justification&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One reason given for using Node.js is that the same language, Javascript, can
be used on both the client and the server. If that is true, then why shouldn&amp;rsquo;t
someone use &lt;a href=&quot;https://developers.google.com/web-toolkit/&quot;&gt;GWT&lt;/a&gt; and use Java on
both the client and server? Since the JVM works very well on the server,
certainly the effort put into GWT could be seen as the equivalent of the
effort put into Node.js to make a browser technology work well on the server.
At the least, when you hear the &amp;ldquo;same language&amp;rdquo; justification, you should be
looking for places where the same justification could be made but you don&amp;rsquo;t
find it convincing. If the justification isn&amp;rsquo;t convincing when you substitute
analogous elements, then either the justification is flawed or it is missing
something that would differentiate the two situations.&lt;/p&gt;

&lt;p&gt;Often, the same language justification for using Node.js is promoted by people
who are also bragging about being polyglot programmers. Not only is knowing
more than one programming language beneficial, it&amp;rsquo;s basically required these
days. But if knowing more than one language is offered as a positive, why is
it important to use the same language on client and server? I&amp;rsquo;m not saying
this argument is invalid, but rather that the justification should examined
for consistency.&lt;/p&gt;

&lt;p&gt;Another reason given for using Node.js is that there are many Javascript
programmers. However, statistically, that means there are many mediocre or
poor quality Javascript programmers. And if concurrent applications are so
hard, do you want a lot of mediocre or poor programmers building them? Again,
many Javascript programmers &lt;em&gt;may&lt;/em&gt; be a justification for using Node.js but by
itself, the justification is problematic. It&amp;rsquo;s likely an extreme
over-simplification. As such, it has dubious value as more than just a
convenient dismissal of someone who challenges the rationale for using
Node.js.&lt;/p&gt;

&lt;p&gt;It may be that using Node.js is just more fun for many people. This is a great
reason to use Node.js. However, it is not one that can be used to evaluate the
technical merit of the technology. Which is fine. Recall that I&amp;rsquo;m asserting
programming is a &lt;em&gt;behavioral&lt;/em&gt; science. We should be studying and giving
adequate weight to considerations that are not merely technical. Humans are
using Node.js.&lt;/p&gt;

&lt;p&gt;Finally, despite being controversial, I&amp;rsquo;m going to give some opinions about
Node.js based on my experience. The point is not whether you believe me or
not.  These opinions should be examined critically with the objective of
determining their validity using methods suggested above.&lt;/p&gt;

&lt;p&gt;More CPU cores is the trend for the future. Typical programs have a huge
amount of state. Every library loaded is program state. Running multiple
processes demands duplicating the memory used by each process times the
number of running processes. As long as the total memory needed to saturate
the CPU cores is less than the memory available, using processes should not be
a problem. However, we have seen in Ruby, at least, that it is not typically
the case. Memory pressure is a constant problem. Solutions to this memory
pressure like copy-on-write (CoW) friendly garbage collection are hard and not
guaranteed to be that effective. If the mutable part of the heap is small
then there is also very likely little shared state that would complicate
simply using threads. If the mutable part is large, you get the same memory
pressure over time regardless of CoW-friendly GC.&lt;/p&gt;

&lt;p&gt;Since it is extremely unlikely that Javascript will add threads to the
standard, Node.js will either be essentially single-threaded or programs will
use non-standard libraries to introduce threading. This forces Node.js to use
process concurrency to achieve parallelism. In this respect, I think that
Node.js rejects the multi-core reality that confronts us.&lt;/p&gt;

&lt;p&gt;In fact, Node.js is already confronting the issue of process concurrency. In
Ruby, we have &lt;a href=&quot;http://www.modrails.com/&quot;&gt;Passenger&lt;/a&gt; for managing multiple
worker processes.  There is now a similar system for Node.js called
&lt;a href=&quot;http://learnboost.github.com/cluster/&quot;&gt;Cluster&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another concern is that an entire ecosystem of libraries and tools must be
built up for Node.js. Javascript was confined to the browser of a long time,
and that environment is quite impoverished. In building those libraries, many
mistakes that have been make in other languages will be made again. That is
simply the nature of humans doing work. We make mistakes. Ruby and other
languages have repeated mistakes from languages that came before them. I&amp;rsquo;m not
saying that the work that must be done won&amp;rsquo;t be offset by its future value. I
am saying the work must be done and its value should be questioned. There is
always an opportunity cost for choosing to do an activity. It is the cost of
not doing another activity. In attempting to answer the question whether
Node.js is better for our problem, we must consider these issues.&lt;/p&gt;

&lt;p&gt;Concurrency is definitely a concern for practically every currently popular
programming language. If you have heard that Node.js enables solutions not
possible in other languages, I encourage you to look more deeply into the
situation. In Ruby, I recommend checking out the
&lt;a href=&quot;https://github.com/celluloid&quot;&gt;Celluloid&lt;/a&gt; project by Tony Arcieri. The
project&amp;rsquo;s aim is to bring various concurrency mechanisms to Ruby. He is
someone with a lot of experience and accomplishments and I&amp;rsquo;m confident his
projects will advance the state of the art in Ruby and hopefully other
languages as well. If you are a Clojure enthusiast, you may want to look at
Carl Lerche&amp;rsquo;s &lt;a href=&quot;https://github.com/momentumclj/momentum&quot;&gt;momentum&lt;/a&gt; project. Of
course, there are many languages and frameworks that handle concurrency and
more are under active development. Node.js is not new technology; it&amp;rsquo;s merely
new for Javascript.&lt;/p&gt;

&lt;p&gt;Ultimately, the answer to, &amp;ldquo;Is Node.js better?&amp;rdquo; is not that important. People
will use Node.js even if it&amp;rsquo;s not the best solution to their problem. Other
people will not use it even if it is great for their particular problem. Both
results limit the benefits available to all of us. Further, we will continue
to confront the question, &amp;ldquo;is this better than that?&amp;rdquo; If we improve our
ability to answer that question, hopefully we will increase the benefit to us
all.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Slides for "Nikita - The Ruby Secret Agent"</title>
    <id>http://brixen.io/2011/10/3/nikita-the-ruby-secret-agent-slides</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2011/10/3/nikita-the-ruby-secret-agent-slides" />
    <published>2011-10-03T00:00:00-07:00</published>
    <updated>2011-10-03T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;ED.&lt;/strong&gt; I&amp;rsquo;ve converted the slides to PDF and uploaded them to
&lt;a href=&quot;http://speakerdeck.com/u/brixen/p/nikita-the-ruby-secret-agent&quot;&gt;speakerdeck.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://speakerdeck.com/u/brixen/p/nikita-the-ruby-secret-agent&quot;&gt;
  &lt;img src=&quot;/images/nikita_slides.jpg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ED.&lt;/strong&gt; The except from the 2011 OSCON Twitter talk is below.&lt;/p&gt;

&lt;iframe src=&quot;http://player.vimeo.com/video/29993216?title=0&amp;amp;byline=0&amp;amp;portrait=0&quot; width=&quot;750&quot; height=&quot;420&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;

</content>
  </entry>
  
  <entry>
    <title>A VM by any other name</title>
    <id>http://brixen.io/2009/3/18/a-vm-by-any-other-name</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/3/18/a-vm-by-any-other-name" />
    <published>2009-03-18T00:00:00-07:00</published>
    <updated>2009-03-18T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;With the recent switch away from the spaghetti stack execution model, &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; has also acquired native threads. A big part of understanding something is syncing up our mental model with reality. If you&amp;#8217;ve ever tried to explain what an OS is to your mom, you know that can be a challenge. So let&amp;#8217;s peel back a few layers and see where these native thread critters fit into Rubinius.&lt;/p&gt;
&lt;p&gt;Rubinius is an implementation of the Ruby programming language. One of the bigger components is the virtual machine. But what is that? Unfortunately, &lt;em&gt;virtual machine&lt;/em&gt; is a label for a category of software (and maybe hardware) that, well, does a bunch of different things. Virtual machines are often thought of as virtual computers or virtual CPUs. The problem with trying to equate two things is that you look at the one you know about and try to understand the one you do not by looking for analogous structures. Therein lie the seeds of misunderstanding. Since Rubinius has this &lt;code&gt;vm/&lt;/code&gt; directory, we&amp;#8217;ve got to try to nail some of this gelatin to the wall.&lt;/p&gt;
&lt;p&gt;Thinking about threads running inside a physical computer, you might visualize the relationship something like the following Ruby-ish pseudo code. As the program starts up, it creates a virtual machine.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;VM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# do some setup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sometime later in the program, you add a new thread, which might be implemented something like this.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;VM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;threads&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You might imagine the &lt;code&gt;VM&lt;/code&gt; instance having a &lt;code&gt;Scheduler&lt;/code&gt; component that would supervise the threads and arrange for running them on one or more processors or cores. In this model, the VM is really like a virtual computer in which all execution is occurring. In other words, the VM is composed of multiple threads of execution.&lt;/p&gt;
&lt;p&gt;The point of this mental exercise is to expose the tacit assumptions we might have about our mapping between a real computer and the virtual machine. Now let&amp;#8217;s delve into Rubinius.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; function is located in &lt;code&gt;vm/drivers/cli.cpp&lt;/code&gt;. The first thing it does is create an instance of &lt;code&gt;Environment&lt;/code&gt;, which is composed of an instance of &lt;code&gt;VMManager&lt;/code&gt;, &lt;code&gt;SharedState&lt;/code&gt;, and &lt;code&gt;VM&lt;/code&gt;. In the &lt;code&gt;Environment&lt;/code&gt; constructor, the command line is parsed for configuration options. Then the manager creates a new shared state. The shared state creates a vm. And finally the vm is initialized. During initialization, the &lt;code&gt;ObjectMemory&lt;/code&gt; is created. The object memory in turn is composed of garbage collected heaps for the young and mature generations.&lt;/p&gt;
&lt;p&gt;Back in &lt;code&gt;main&lt;/code&gt;, a platform-specific configuration file is loaded, the &amp;#8220;vm&amp;#8221; is booted, the command line is loaded into &lt;code&gt;ARGV&lt;/code&gt;, the kernel is loaded (i.e. the compiled versions of the files located in the &lt;code&gt;kernel/&lt;/code&gt; directory), the preemption and signal threads are started, and finally the compiled version of &lt;code&gt;kernel/loader.rb&lt;/code&gt; is run, which will process the command line arguments, run scripts, start &lt;span class=&quot;caps&quot;&gt;IRB&lt;/span&gt;, etc. When your script, &lt;span class=&quot;caps&quot;&gt;IRB&lt;/span&gt;, &lt;code&gt;-e&lt;/code&gt; command, etc. finish running, &lt;code&gt;loader.rb&lt;/code&gt; finishes, &lt;code&gt;main&lt;/code&gt; finishes, resources are cleaned up, and finally the process exits.&lt;/p&gt;
&lt;p&gt;Whew. The point of this whirlwind tour is to illustrate that &lt;em&gt;VM&lt;/em&gt; is a rather fuzzy concept, even though we have a class named &lt;code&gt;VM&lt;/code&gt;. Now let&amp;#8217;s take a look at how threads fit in.&lt;/p&gt;
&lt;p&gt;Rubinius has a 1:1 native thread model. In other words, each time you do &lt;code&gt;Thread.new&lt;/code&gt; in your Ruby code, the instance returned maps to a single native thread. In fact, let&amp;#8217;s look at the code for &lt;code&gt;Thread.new&lt;/code&gt; in &lt;code&gt;kernel/common/thread.rb&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allocate&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initialize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;7&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;thr&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;8&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The calls to &lt;code&gt;allocate&lt;/code&gt; and &lt;code&gt;fork&lt;/code&gt; are implemented as primitives in C++ code. They are short, so we&amp;#8217;ll take a look at them, too.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;cpp&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;VM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;thread&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interrupts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable_preempt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;native_thread_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NativeThread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Let it run.&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;native_thread_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Qnil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The call to &lt;code&gt;allocate&lt;/code&gt; creates a new instance of &lt;code&gt;VM&lt;/code&gt; as thread local data. The call to &lt;code&gt;fork&lt;/code&gt; creates the new native thread. The call to &lt;code&gt;native_thread_-&amp;gt;run()&lt;/code&gt; will eventually call the &lt;code&gt;__run__&lt;/code&gt; method in &lt;code&gt;kernel/common/thread.rb&lt;/code&gt;. Something to note about this snippet of C++ code is the nice consistency between the primitives and the Ruby code that calls them.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve encountered the &lt;code&gt;VM&lt;/code&gt; class in two contexts: 1) when starting up the Rubinius process, and 2) when creating a new &lt;code&gt;Thread&lt;/code&gt;. We can consider the &lt;code&gt;VM&lt;/code&gt; instance to be an abstraction of the state of a single thread of execution, and in fact, &lt;code&gt;state&lt;/code&gt; is the name most often given to an instance of &lt;code&gt;VM&lt;/code&gt; in the Rubinius source.&lt;/p&gt;
&lt;p&gt;As we&amp;#8217;ve seen, Rubinius as a running process is composed of various abstractions, including the &lt;code&gt;Environment&lt;/code&gt;, &lt;code&gt;SharedState&lt;/code&gt;, &lt;code&gt;NativeThread&lt;/code&gt;, and &lt;code&gt;VM&lt;/code&gt; to name a few. While it is accurate to call Rubinius a virtual machine, it is apparent that concept can cover a fair bit of complexity. But breaking it into parts makes it fairly easy to understand. Let us know what things you&amp;#8217;d like to understand better. We have the &lt;code&gt;doc/&lt;/code&gt; directory in the source that we&amp;#8217;re (slowly) building out. If you&amp;#8217;re interested in contributing, docs would be a great way to help everyone.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Come to the Open Source Bridge conference</title>
    <id>http://brixen.io/2009/3/6/come-to-the-open-source-bridge-conference</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/3/6/come-to-the-open-source-bridge-conference" />
    <published>2009-03-06T00:00:00-08:00</published>
    <updated>2009-03-06T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;If you live in or would like to visit beautiful Portland, OR, consider &lt;a href=&quot;http://opensourcebridge.org/attend/&quot;&gt;signing up&lt;/a&gt; for the &lt;a href=&quot;http://opensourcebridge.org/&quot;&gt;Open Source Bridge&lt;/a&gt; conference. I will (probably) be giving a talk on &lt;a href=&quot;http://opensourcebridge.org/proposals/13&quot;&gt;RubySpec&lt;/a&gt; and &lt;a href=&quot;http://opensourcebridge.org/proposals/12&quot;&gt;Rubinius 1.0&lt;/a&gt;. There&amp;#8217;s lots of interesting folks giving great &lt;a href=&quot;http://opensourcebridge.org/events/2009/proposals/&quot;&gt;talks&lt;/a&gt;. This is an opportunity to hear how people are developing the open-source community.&lt;/p&gt;
&lt;p&gt;Hope to see you there!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>When describe'ing it ain't enough</title>
    <id>http://brixen.io/2009/3/3/when-describe-ing-it-ain-t-enough</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/3/3/when-describe-ing-it-ain-t-enough" />
    <published>2009-03-03T00:00:00-08:00</published>
    <updated>2009-03-03T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;One of the things I like about the &lt;a href=&quot;http://rspec.info&quot;&gt;RSpec&lt;/a&gt; syntax is that it packs a lot of information into a few concise, consistent constructs. It&amp;#8217;s relatively easy to read through a spec file and pick out what I am looking for. The use of blocks both enable flexible execution strategies and provide simple containment boundaries.&lt;/p&gt;
&lt;p&gt;Perhaps the most valuable aspect, though, is the ability to extend the RSpec syntax constructs easily and consistently. No need to grow a third arm here. In &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;, we recently encountered a situation needing some extra sauce when fixing our compiler specs.&lt;/p&gt;
&lt;p&gt;A compiler can be thought of as something that chews up data in one form and spits it out in another, equivalent, form. Typically, these transformations from one form to another happen in a particular order. And there may be several of them from the very beginning to the very end of the compilation process.&lt;/p&gt;
&lt;p&gt;To write specs for such a process, it would be nice to focus just on the forms of the data (that&amp;#8217;s what we care about) with as little noise as possible about how they got there. Here&amp;#8217;s what we have in Rubinius:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;An And node&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;relates&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;(a and b)&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:and&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arglist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arglist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]]&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;lhs_true&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_label&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lhs_true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;lhs_true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set!&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;relates&lt;/code&gt; block introduces the Ruby source code and contains the blocks that show various intermediate forms. A single word like &lt;code&gt;parse&lt;/code&gt; and &lt;code&gt;compile&lt;/code&gt; encapsulates the process of generating that particular form, as well as concisely documenting the specs.&lt;/p&gt;
&lt;p&gt;The format is sufficiently flexible to allow for other forms. For instance, &lt;code&gt;ast&lt;/code&gt; for generating an &lt;span class=&quot;caps&quot;&gt;AST&lt;/span&gt; directly from the parse tree rather than using the sexp as an intermediate form. Or &lt;code&gt;llvm&lt;/code&gt; to emit &lt;a href=&quot;http://llvm.org&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLVM&lt;/span&gt;&lt;/a&gt; IR directly from our compiler.&lt;/p&gt;
&lt;p&gt;Another interesting aspect of this, it was possible with only a few custom extensions to &lt;a href=&quot;http://github.com/rubyspec/mspec/commits/master&quot;&gt;MSpec&lt;/a&gt;. Recently, I had added custom options to the MSpec runner scripts to enable such things as our &lt;code&gt;--gc-stats&lt;/code&gt;. I didn&amp;#8217;t know how easy it would be to add something more extensive. Turns out it was pretty easy. You can check out the source in our &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/master/spec/custom&quot;&gt;spec/custom&lt;/a&gt; directory.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>What is RubySpec?</title>
    <id>http://brixen.io/2009/3/3/what-is-rubyspec</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/3/3/what-is-rubyspec" />
    <published>2009-03-03T00:00:00-08:00</published>
    <updated>2009-03-03T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;According to the folks over at &lt;a href=&quot;http::rubyspec.org&quot;&gt;http://rubyspec.org&lt;/a&gt;, &amp;#8220;RubySpec is a project to write a complete, executable specification for the Ruby programming language.&amp;#8221; As with any sufficiently concise summary, there&amp;#8217;s some opportunity for misunderstanding here, so let&amp;#8217;s explore a few aspects of this definition.&lt;/p&gt;
&lt;p&gt;Since this post is a bit long, here&amp;#8217;s a summary:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;There is one &lt;em&gt;standard&lt;/em&gt; definition of Ruby.&lt;/li&gt;
	&lt;li&gt;RubySpec benefits the whole Ruby ecosystem.&lt;/li&gt;
	&lt;li&gt;RubySpec does not guarantee that program A will run on implementation B.&lt;/li&gt;
	&lt;li&gt;RubySpec includes only specs for the correct behavior when bugs are discovered in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;.&lt;/li&gt;
	&lt;li&gt;Help your favorite Ruby implementation by contributing to RubySpec.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;First, what does it mean to be &amp;#8220;the Ruby programming language&amp;#8221;? The answer to this question used to be a little simpler before Ruby 1.9. Originally, there was the single Ruby implementation that Matz and friends built, referred to as &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; (Matz&amp;#8217;s Ruby Interpreter). Now there is also RubyVM or &lt;span class=&quot;caps&quot;&gt;KRI&lt;/span&gt; (Koichi&amp;#8217;s Ruby Implementation) or simply Ruby 1.9. Either way, &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; 1.8.x and [KM]RI 1.9.x are the &lt;em&gt;standard&lt;/em&gt; or &lt;em&gt;reference&lt;/em&gt; implementations for Ruby. Everyone else is making an alternative implementation that either complies with the standard or deviates from it.&lt;/p&gt;
&lt;p&gt;This is the way RubySpec is written. I realize that it&amp;#8217;s possible to consider &amp;#8220;the Ruby programming language&amp;#8221; to be an abstract thing and &lt;em&gt;all&lt;/em&gt; the Ruby projects as merely more or less equal attempts to implement the language. I won&amp;#8217;t try to convince you that either way of viewing this is more or less correct. I just want to be clear about the way RubySpec views it.&lt;/p&gt;
&lt;p&gt;At the time I began writing what eventually became RubySpec, the only Ruby implementation in wide-spread use was &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;. My biggest concern when getting involved with &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; was that the project would be consistent with Ruby the way Matz defines it and not cause fragmentation of the language. My reason was quite selfish. I loved programming in Ruby and I wanted to see the language thrive.&lt;/p&gt;
&lt;p&gt;So, RubySpec&amp;#8217;s over-arching value proposition is a single, comprehensive definition of the Ruby programming language. To see if the value proposition is actually universal, let&amp;#8217;s examine the three categories of people involved with Ruby: consumers, programmers, and implementers.&lt;/p&gt;
&lt;p&gt;I define &lt;em&gt;consumers&lt;/em&gt; as anyone who depends on a product or service written in Ruby. Consumers may use these products and services directly, or they may own or work for companies that provide them, or they may use products and services that are themselves supported by software written in Ruby. Consumers are the biggest part of the Ruby ecosystem.&lt;/p&gt;
&lt;p&gt;Interacting closely with the consumers are &lt;em&gt;programmers&lt;/em&gt;, the men and women who write software or frameworks in Ruby. In fact, the same folks may be both consumers and programmers.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;implementers&lt;/em&gt; are the people writing Ruby implementations for the programmers and consumers. They want to experiment with ways to better support programmers without worrying that they are breaking their programs in unknown ways. Again, the implementers may be programmers or consumers themselves.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve ever used a proprietary implementation of a programming language or know what vendor lock-in means, then I am preaching to the choir. If not, then consider that system requirements change, hardware changes, services change, customers change, development teams change, everything changes.&lt;/p&gt;
&lt;p&gt;Consumers want assurance that the products and services on which they depend will remain available and will grow with their needs. Programmers want assurance that they will be able to meet their customers&amp;#8217; needs. Implementers want to provide programmers the ability to do so. A single, consistent Ruby language really is a win-win-win situation.&lt;/p&gt;
&lt;p&gt;With everything seeming so sunny, one may be tempted to think: &amp;#8220;If implementation A and B perform the same on RubySpec, then a program running on A now should run just fine on B.&amp;#8221; Unfortunately, it is not quite that simple. Just as a program may not run on both OS X and Linux simply because &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; runs on both. Once in a while, RubySpec finds bugs in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, though not that often considering the tens of thousands of expectations. Since a lot of the code in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; has been around for years, this illustrates that even running thousands of programs (RubySpec is just another program) is no guarantee that there are not bugs lurking around the corner.&lt;/p&gt;
&lt;p&gt;What can tell you whether a program will (likely) run on both A and B is the program&amp;#8217;s own test suite. In this regard, the program&amp;#8217;s test suite and RubySpec are complementary. If the tests discover something that RubySpec did not, it is an opportunity to enhance RubySpec. If running on another implementation expose issues not uncovered by the program&amp;#8217;s tests, it is an opportunity to enhance the tests.&lt;/p&gt;
&lt;p&gt;Ruby versioning is complex affair and another area where possible misunderstandings exist about RubySpec. It seems pretty simple that Ruby 1.8 and Ruby 1.9 are different. But then there is 1.8.7, which is like 1.8.6 and 1.9. And there may be 1.8.8, which will likely be different than 1.8.6 and 1.8.7 and 1.9. It is dizzying. RubySpec handles the different versions by using the &lt;code&gt;ruby_version_is&lt;/code&gt; guard. (Read the &lt;a href=&quot;http://rubyspec.org/wiki/rubyspec/Guards&quot;&gt;guard documentation&lt;/a&gt; for full details.)&lt;/p&gt;
&lt;p&gt;Generally, the version guards work fine. Each implementation provides the &lt;code&gt;RUBY_VERSION&lt;/code&gt; constant and based on its value, the guards permit the correct specs to run. Some have assumed this means RubySpec will tell you that alternate implementation A is just like &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; version X.Y.Z &amp;#8220;bugs and all&amp;#8221; because A says it is version X.Y.Z.&lt;/p&gt;
&lt;p&gt;The principles RubySpec strives for are correctness, clarity, and consistency. There is no way to provide &lt;em&gt;clear&lt;/em&gt; and &lt;em&gt;consistent&lt;/em&gt; results if RubySpec included specs for the &lt;em&gt;wrong&lt;/em&gt; behavior as well as specs for the correct behavior. Either clarity or consistency suffer, badly. Matz is the one who ultimately determines whether a behavior is a bug or not. RubySpec simply includes specs for only correct behaviors.&lt;/p&gt;
&lt;p&gt;These are some of the factors that complicate this issue:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;There is no definition of what &lt;em&gt;is&lt;/em&gt; a bug. It may be a segfault, an incorrect value computed, a frozen state not set or respected, the wrong exception class raised. The list is endless and impossible to consistently categorize.&lt;/li&gt;
	&lt;li&gt;All implementations, including &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, have their own release processes and schedules.&lt;/li&gt;
	&lt;li&gt;RubySpec is a social as well as technical project. An aspect of the value-added proposition for any given implementation is the quality that they provide. There is no way the alternative implementations will consistently agree to defer fixing bugs until &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; releases a fix. Rather than supporting cherry-picking which bugs to fix, RubySpec only includes correct specs.&lt;/li&gt;
	&lt;li&gt;Bugs discovered by RubySpec in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; are quite rare.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Finally, contributing to RubySpec is one of the lowest barriers-to-entry means of supporting your favorite Ruby implementation and the Ruby ecosystem as a whole.&lt;/p&gt;
&lt;p&gt;Consider what the view looks like from the outside: Ruby has a vibrant community of implementations meeting consumers&amp;#8217; and programmers&amp;#8217; needs on virtually every significant platform, including on Java, .&lt;span class=&quot;caps&quot;&gt;NET&lt;/span&gt;, Mac (Obj-C), and semi-platform-agnostic implementations like &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; and Rubinius. Internally, it means that Ruby programmers can focus more on writing their programs using the best tools for the job, confident that if requirements change they can move to a different platform with ease and confidence.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;http://rubyspec.org/wiki/rubyspec&quot;&gt;RubySpec docs&lt;/a&gt; if you are interested in helping out.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Boxers or Briefs? -- Neither?!</title>
    <id>http://brixen.io/2009/3/3/boxers-or-briefs-neither</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/3/3/boxers-or-briefs-neither" />
    <published>2009-03-03T00:00:00-08:00</published>
    <updated>2009-03-03T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;The emperor is wearing clothes and everything looks hunky-dory and sane on the outside. Usually, that&amp;#8217;s a good thing. For instance, when running &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpec&lt;/a&gt; on a released version of &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, it&amp;#8217;s good to know that things are behaving as expected and &lt;em&gt;all known issues&lt;/em&gt; are accounted for. In other words, you won&amp;#8217;t see any failures unless a spec is broken or a new spec has uncovered a bug.&lt;/p&gt;
&lt;pre&gt;
$ mspec library/stringio/reopen_spec.rb 
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
........................

Finished in 0.021797 seconds

1 file, 24 examples, 59 expectations, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;While the above can be reassuring, it may not tell the whole story. RubySpec uses &lt;a href=&quot;http://rubyspec.org/wiki/rubyspec/Guards&quot;&gt;guards&lt;/a&gt; to control which specs are run. This enables the specs to accommodate differences in behavior due to varying platforms, versions, implementations, and bugs.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve added a couple features to &lt;a href=&quot;http://github.com/rubyspec/mspec/commits/master&quot;&gt;MSpec&lt;/a&gt; to enable discrete and not-so-discrete peeks under the robes, as it were. The first of these is akin to just yanking down the trousers. By passing the &lt;code&gt;--no-ruby_bug&lt;/code&gt; option, all &lt;code&gt;ruby_bug&lt;/code&gt; guards are disabled and the guarded specs are run.&lt;/p&gt;
&lt;pre&gt;
$ mspec --no-ruby_bug library/stringio/reopen_spec.rb 
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
............FF.....FF.....FF......

1)
StringIO#reopen when passed [Object, Object] resets self's position to 0 FAILED
Expected 5
 to have same value and type as 0

./library/stringio/reopen_spec.rb:117
./library/stringio/reopen_spec.rb:110:in `all?'
./library/stringio/reopen_spec.rb:61

---- snip ----

Finished in 0.022210 seconds

1 file, 34 examples, 76 expectations, 6 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;If you cringe a little when blasted by a bunch of failures, don&amp;#8217;t worry, So do I. For a more subtle examination, there is also the ability to run the specs and note which specs &lt;em&gt;would have run&lt;/em&gt; but did not due to guards.&lt;/p&gt;
&lt;pre&gt;
$ mspec --report library/stringio/reopen_spec.rb 
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
........................

Finished in 0.009809 seconds

1 file, 24 examples, 59 expectations, 0 failures, 0 errors, 10 guards


4 specs omitted by guard: ruby_bug #, 1.8.6.114:

StringIO#reopen reopens a stream when given a String argument
StringIO#reopen reopens a stream in append mode when flagged as such
StringIO#reopen reopens and truncate when reopened in write mode
StringIO#reopen truncates the given string, not a copy

6 specs omitted by guard: ruby_bug #, 1.8.7:

StringIO#reopen when passed [Object, Object] resets self's position to 0
StringIO#reopen when passed [Object, Object] resets self's line number to 0
StringIO#reopen when passed [String] resets self's position to 0
StringIO#reopen when passed [String] resets self's line number to 0
StringIO#reopen when passed no arguments resets self's position to 0
StringIO#reopen when passed no arguments resets self's line number to 0
&lt;/pre&gt;
&lt;p&gt;The guards are reported only if they have altered how the specs were run. Since the &lt;code&gt;ruby_bug&lt;/code&gt; guard can only prevent specs from running on the &lt;em&gt;standard implementation&lt;/em&gt;, &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, those guards are not reported when running under JRuby, for instance.&lt;/p&gt;
&lt;pre&gt;
$ mspec -t jruby --report library/stringio/reopen_spec.rb 
jruby 1.2.0RC1 (ruby 1.8.6 patchlevel 287) (2009-02-26 rev 9326) [i386-java]
..................................

Finished in 0.257000 seconds

1 file, 34 examples, 76 expectations, 0 failures, 0 errors, 0 guards
&lt;/pre&gt;
&lt;p&gt;So, if you are wondering what is going on with some specs for a particular library, you can get a quick peek using the &lt;code&gt;--report&lt;/code&gt; option before digging into the spec files. There is also a &lt;code&gt;--report-on GUARD&lt;/code&gt; option that allows you to narrow the focus of your peeking.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Warning: Includes Known Bugs</title>
    <id>http://brixen.io/2009/2/26/warning-includes-known-bugs</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/2/26/warning-includes-known-bugs" />
    <published>2009-02-26T00:00:00-08:00</published>
    <updated>2009-02-26T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; In further discussions with Jim Deville of IronRuby it appears that there may be a legal issue preventing IronRuby devs from patching Ruby code themselves. However it may be possible for IronRuby to use a commonly maintained and patched version of the standard library.&lt;/p&gt;
&lt;p&gt;Reviewing the logs and considering this was Shri&amp;#8217;s first major discussion in the &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; channel, I unfortunately grouped him in with Charles&amp;#8217; intolerable behavior and personal attacks which have occurred on a number of occasions in #rubyspec and #rubinius. My apologies to Shri. The struck out text below remains merely for historical accuracy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; Charles response to this post wasn&amp;#8217;t exactly positive, but I think it&amp;#8217;s fair to have this discussion in public: &lt;a href=&quot;http://pastie.org/400493&quot;&gt;http://pastie.org/400493&lt;/a&gt; Also, please note that I&amp;#8217;ve struck out Shri&amp;#8217;s name below as I may have misunderstood him in the earlier discussion.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;You, the trusting consumer, would probably like to receive such cautionary advertisement were you to use a product that did, in fact, ship to you code that includes known bugs. And not just known bugs, but known bugs that have fixes for them.&lt;/p&gt;
&lt;p&gt;You would like to know this, right? I mean, I&amp;#8217;m not just some hard-headed asshole that thinks there&amp;#8217;s something a bit whack here, am I? Please, do tell me.&lt;/p&gt;
&lt;p&gt;Well, as luck would have it, you can also tell this to &lt;a href=&quot;http://http://blog.headius.com/&quot;&gt;Charles Oliver Nutter&lt;/a&gt; of &lt;a href=&quot;http://jruby.codehaus.org/&quot;&gt;JRuby&lt;/a&gt; &lt;del&gt;and &lt;a href=&quot;http://blogs.msdn.com/shrib/&quot;&gt;Shri Borde&lt;/a&gt; of &lt;a href=&quot;http://www.ironruby.net/&quot;&gt;IronRuby&lt;/a&gt;&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the drama: There&amp;#8217;s this project &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpec&lt;/a&gt;. You may have heard of it. It attempts to describe the behavior of the Ruby programming language. All the alternative Ruby implementations use the RubySpec project to attempt to show that they are &amp;#8220;Ruby&amp;#8221;.&lt;/p&gt;
&lt;p&gt;All the alternative implementations also choose to ship some version or other of the Ruby standard library. At least the parts written in Ruby. Makes sense, since they all implement the Ruby programming language.&lt;/p&gt;
&lt;p&gt;As is the case with all software, from time to time bugs are discovered in Ruby. Usually, these are fixed soon after they are discovered and the fix is committed to the trunk version of &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; (Matz&amp;#8217;s Ruby Implementation). Eventually, trunk becomes another stable release with a particular patchlevel.&lt;/p&gt;
&lt;p&gt;The RubySpecs deal with this situation with a &lt;code&gt;ruby_bug&lt;/code&gt; guard. You can read the details of &lt;a href=&quot;http://rubyspec.org/wiki/rubyspec/Guards&quot;&gt;RubySpec guards&lt;/a&gt;. This particular guard has two functions:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;It prevents the guarded spec from executing on any version of &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; less than or equal to the version specified in the guard. This is because &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; cannot re-release a particular patchlevel &lt;em&gt;after&lt;/em&gt; it has been released. And the bugs are discovered &lt;em&gt;after&lt;/em&gt; a release.&lt;/li&gt;
	&lt;li&gt;It documents the spec, which shows what the correct behavior should be.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A key feature of the &lt;code&gt;ruby_bug&lt;/code&gt; guard is that it &lt;em&gt;does not&lt;/em&gt; prevent the spec from running on any alternative implementation. That is because every alternative implementation is expected to have the &lt;em&gt;correct&lt;/em&gt; behavior. Additionally, these guards are only added after Matz or ruby-core has stated that the behavior at issue is a bug and the behavior of the spec is the correct behavior.&lt;/p&gt;
&lt;p&gt;Now here is the rub, Charles does not want to manage patching the Ruby standard library that he ships with JRuby &lt;em&gt;with the patches that already exist for known bugs&lt;/em&gt;. He wants to ship whatever version &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; has most recently released. Further, when you run the RubySpecs with JRuby, he wants to &lt;em&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;MASK&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt; those bugs because he doesn&amp;#8217;t think it&amp;#8217;s fair that JRuby fails a spec which shows a known bug in the Ruby standard library for which patches are available.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s Charles choice of strategies for managing JRuby packaging. I&amp;#8217;m strongly of the opinion that you, the user, would like to know that. Charles apparently disagrees.&lt;/p&gt;
&lt;p&gt;In fact, he disagrees so vehemently that he takes to calling me names in the #rubyspec &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; channel because I refuse to change the fact that the &lt;code&gt;ruby_bug&lt;/code&gt; guard will not silently mask spec failures on JRuby or any other alternative implementation. Aside from being immature, I think there is a real problem with this. Don&amp;#8217;t you?&lt;/p&gt;
&lt;p&gt;Charlie will argue that it is simply impossible to ship the trunk version of Ruby standard library because it is an unknown quantity? However, the best defense against bugs in the Ruby standard library is better specs. And we&amp;#8217;re talking about specs here that &lt;em&gt;show the bugs&lt;/em&gt; and for which patches exist. Furthermore, there are actually relatively few bugs noted in the specs and most of those are in older versions of Ruby, not the current stable release.&lt;/p&gt;
&lt;p&gt;So, here&amp;#8217;s my question to you: Would you like to know that JRuby &lt;del&gt;and possibly IronRuby&lt;/del&gt; ship you code that contains know bugs for which patches exist? Would you also like to know that Charles wants you to run RubySpec on JRuby and not know there is a bug?&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Caveat Lector</title>
    <id>http://brixen.io/2009/2/20/caveat-lector</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/2/20/caveat-lector" />
    <published>2009-02-20T00:00:00-08:00</published>
    <updated>2009-02-20T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I really did double-check this time and I won&amp;#8217;t be making any wild claims here. Sorry to disappoint.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to be running &lt;a href=&quot;http://antoniocangiano.com/&quot;&gt;Antonio&amp;#8217;s&lt;/a&gt; &lt;a href=&quot;http://github.com/acangiano/ruby-benchmark-suite/tree/master&quot;&gt;Ruby Benchmark Suite&lt;/a&gt; daily to track our progress on performance in &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;. The current &lt;span class=&quot;caps&quot;&gt;RBS&lt;/span&gt; is a bit of a beast so I imported the files into the Rubinius &lt;a href=&quot;http://github.com/evanphx/rubinius/commits/master&quot;&gt;repository&lt;/a&gt; and did some refactoring. You can &lt;a href=&quot;http://groups.google.com/group/ruby-benchmark-suite/browse_frm/thread/34b7b7472fa5b80&quot;&gt;read the details&lt;/a&gt; and up-vote that if you&amp;#8217;d like to see this merged back.&lt;/p&gt;
&lt;p&gt;Now, for some baseline &lt;span class=&quot;caps&quot;&gt;RBS&lt;/span&gt; results. If you want to follow along at home, here&amp;#8217;s what I did. I generated these by running the &lt;code&gt;rake bench&lt;/code&gt; task using the &lt;code&gt;VM&lt;/code&gt; option (see the benchmark/utils/&lt;span class=&quot;caps&quot;&gt;README&lt;/span&gt; in the Rubinius repository) for Rubinius on the &lt;code&gt;stackfull&lt;/code&gt; and &lt;code&gt;master&lt;/code&gt; branch and for &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; using the version installed on Debian lenny, 1.8.7p22. The system is a dual Intel&amp;#174; Xeon&amp;#8482; &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; 2.40GHz. Then I ran the &lt;code&gt;rake bench:to_csv&lt;/code&gt; task, imported the &lt;span class=&quot;caps&quot;&gt;CSV&lt;/span&gt; file into Google Docs, added the comparison columns and colors, and exported to &lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.brightredglow.com/assets/2009/2/20/mini-rbx-shootout.jpg&quot;&gt;Here&amp;#8217;s what I got.&lt;/a&gt; The green is faster, the red is slower. The reported time is the minimum time recorded in five &amp;#8220;iterations&amp;#8221; of each benchmark per input. The maximum time allowed to run five iterations is 300 seconds, or an average of 60 seconds per iteration.&lt;/p&gt;
&lt;p&gt;A few notes about these numbers:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;We&amp;#8217;re still fixing the breakage on the stackfull branch, so it is not surprising, for instance, that all the thread benchmarks errored out. The new native thread support is not 100% done.&lt;/li&gt;
	&lt;li&gt;There are a couple speed regressions on the stackfull branch, most minor. We&amp;#8217;ll fix those.&lt;/li&gt;
	&lt;li&gt;Most of the benches do run on the stackfull branch.&lt;/li&gt;
	&lt;li&gt;On most of the benches that run slower in stackfull than &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, we&amp;#8217;re 2x or less slower than &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;.&lt;/li&gt;
	&lt;li&gt;We are &lt;em&gt;a lot&lt;/em&gt; faster than &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; on quite a few benchmarks.&lt;/li&gt;
	&lt;li&gt;Rubinius on either branch does quite well relative to &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; on benches that &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; times-out on for certain inputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perhaps the biggest point about the stackfull branch is that we haven&amp;#8217;t done much optimization at all. Evan&amp;#8217;s been coding in the basic new interpreter architecture, fixing the GC interaction, adding the native threading. We&amp;#8217;re fixing breakage now so we can get this merged into the master branch. The &lt;span class=&quot;caps&quot;&gt;JIT&lt;/span&gt; is not hooked up. The new GC work is not done. There is no inlining. In other words, there is lots of head room. And that is the key point. You can&amp;#8217;t just &amp;#8220;make it faster&amp;#8221;. Architecture is crucial. Since RailsConf 2008, we&amp;#8217;ve been working hard to lay the architectural foundations. With those (and the switch away from stackless), we can start focusing on the real dynamic language optimizations.&lt;/p&gt;
&lt;p&gt;While the benchmarks tell part of the story, there&amp;#8217;s another part that is even more interesting &lt;span class=&quot;caps&quot;&gt;IMO&lt;/span&gt;. And this is the part that &lt;a href=&quot;http://blog.brightredglow.com/2009/2/12/all-shiny-and-new&quot;&gt;got me so excited&lt;/a&gt; I, um, well I &lt;a href=&quot;http://blog.brightredglow.com/2009/2/12/this-is-not-cold-fusion&quot;&gt;just got excited&lt;/a&gt;&amp;#8230;&lt;/p&gt;
&lt;p&gt;The two biggest pieces of Ruby software that we most often run are the Rubinius compiler and the &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpecs&lt;/a&gt;. The RubySpecs are much more &amp;#8220;real-world&amp;#8221; than these benchmarks. Here are the results of two complete CI runs on master and stackfull. Note that we are not quite running all the basic CI specs on stackfull, but we&amp;#8217;ll figure in that difference in our calculations below.&lt;/p&gt;
&lt;p&gt;First, on master:&lt;/p&gt;
&lt;pre style=&quot;overflow:auto&quot;&gt;
  $ bin/mspec ci --gc-stats
  rubinius 0.10.0 (ruby 1.8.6) (f4c5576c4 12/31/2009) [i686-apple-darwin9.6.0]

  Finished in 131.248169 seconds

  1430 files, 6927 examples, 23006 expectations, 0 failures, 0 errors

  Time spent in GC: 51.6s (39.3%)
&lt;/pre&gt;
&lt;p&gt;And then on stackfull:&lt;/p&gt;
&lt;pre style=&quot;overflow:auto&quot;&gt;
  $ bin/mspec ci --gc-stats
  rubinius 0.11.0-dev (ruby 1.8.6) (e7b6a2d56 12/31/2009) [i686-apple-darwin9.6.0]

  Finished in 66.357996 seconds

  1349 files, 6298 examples, 21344 expectations, 0 failures, 0 errors

  Time spent in GC: 12.7s (19.1%)
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s calculate how we do in expectations per second:&lt;/p&gt;
&lt;pre&gt;
  $ irb
  &amp;gt;&amp;gt; master = 23006 / 131.248169
  =&amp;gt; 175.286254850534
  &amp;gt;&amp;gt; stackfull = 21344 / 66.357996
  =&amp;gt; 321.649255351232
  &amp;gt;&amp;gt; stackfull / master
  =&amp;gt; 1.83499416782851
&lt;/pre&gt;
&lt;p&gt;So, compiling and running the specs is about 1.8 times faster on stackfull. This is upside down from the normal results. Normally, we do better on the micro benchmarks and see that invert on &amp;#8220;macro&amp;#8221; benchmarks. On the &lt;span class=&quot;caps&quot;&gt;RBS&lt;/span&gt; benches, stackfull is not 1.8 times faster than master. If I average the &amp;#8220;x Master&amp;#8221; column, I get 1.39.&lt;/p&gt;
&lt;p&gt;There was something else in those spec run numbers I wanted to talk about&amp;#8230; oh yeah, GC stats. We have a very simple GC timer stat right now. I&amp;#8217;m going to be adding a few more stats. But what we see here is that the overall percentage of time spent in GC drops by half in stackfull. Even so, 19% is too much time to spend in GC. We expect to drop that by half again. Basically, leaning more on structures &lt;code&gt;alloca'd&lt;/code&gt; on the C stack reduces a lot of pressure on the GC.&lt;/p&gt;
&lt;p&gt;Some would toss out that it&amp;#8217;s not hard to be faster than &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;. Perhaps. But it is an accomplishment to write a reasonably good VM, garbage collector, compiler, and Ruby standard library without importing anyone else&amp;#8217;s code. And, lest we forget, that is two VM&amp;#8217;s in about 27 months of a public project.&lt;/p&gt;
&lt;p&gt;Some would also question the sanity of writing a VM and garbage collector when crazy smart people do things like that. Well, crazy smart people write papers that reasonably smart people can read and understand. From the benchmark result above, that is working pretty well.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the point: Don&amp;#8217;t ever let anyone tell you that something is a bad idea. Make your own decisions. We probably wouldn&amp;#8217;t have Ruby itself if Matz fretted over whether Larry Wall or Adele Goldberg were smarter than he. My most recent favorites in this space: &lt;a href=&quot;http://factorcode.org/&quot;&gt;Factor&lt;/a&gt;, &lt;a href=&quot;http://clojure.org&quot;&gt;Clojure&lt;/a&gt;, and yes, &lt;a href=&quot;http://code.macournoyer.com/tinyrb/&quot;&gt;tinyrb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re working frantically to get the stackfull branch breakages fixed and the branch merged back into master. Feel free to poke around and ask questions.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>This is NOT cold fusion</title>
    <id>http://brixen.io/2009/2/12/this-is-not-cold-fusion</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/2/12/this-is-not-cold-fusion" />
    <published>2009-02-12T00:00:00-08:00</published>
    <updated>2009-02-12T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Um, whoops. It was really late last night. Have I mentioned you&amp;rsquo;re wearing a great outfit today. Ok, already.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s this slight matter of &lt;code&gt;DEV=1 rake build&lt;/code&gt; in Rubinius. Yes, I was debugging something. Started running some stuff under the stackfull branch, was intrigued by what I was seeing, decided to make some comparisons, could swear I ran &lt;code&gt;rake clean; rake&lt;/code&gt; in the master branch, had a lot of green tea yesterday&amp;hellip;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All right already&lt;/em&gt;. It&amp;rsquo;s not 4x faster. Here&amp;rsquo;s some new numbers:&lt;/p&gt;

&lt;p&gt;Master branch:&lt;/p&gt;

&lt;pre style=&quot;overflow:auto&quot;&gt;
$ bin/mspec ci core/string
rubinius 0.10.0 (ruby 1.8.6) (781eb14d3 12/31/2009) [i686-apple-darwin9.6.0]
.....................................................................

Finished in 10.576468 seconds

69 files, 763 examples, 5632 expectations, 0 failures, 0 errors

&lt;/pre&gt;

&lt;p&gt;Stackfull:&lt;/p&gt;

&lt;pre style=&quot;overflow:auto&quot;&gt;
rubinius 0.10.0 (ruby 1.8.6) (325174a8e 12/31/2009) [i686-apple-darwin9.6.0]
..................E.....E...E...F............E..E.EE..E........F..F..

Finished in 6.124444 seconds

69 files, 763 examples, 5545 expectations, 6 failures, 19 errors
&lt;/pre&gt;

&lt;p&gt;That&amp;rsquo;s about 58% as long, or 42% faster, or creeping up on 2x. &lt;/p&gt;

&lt;p&gt;If you rushed out and bought Evan a Valentine&amp;rsquo;s bear, I do apologize. But send
it anyway. All the rest in my &lt;a href=&quot;/2009/2/12/all-shiny-and-new&quot;&gt;previous post&lt;/a&gt; about this being the beginning of a very good thing still holds. We&amp;rsquo;ll be getting more results soon and fixing the spec breakage on the stackfull branch. Stay tuned!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>All shiny and new</title>
    <id>http://brixen.io/2009/2/12/all-shiny-and-new</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2009/2/12/all-shiny-and-new" />
    <published>2009-02-12T00:00:00-08:00</published>
    <updated>2009-02-12T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt; 2.0:&lt;/strong&gt; You really did see the update below, right? You&amp;#8217;re getting &lt;a href=&quot;http://blog.headius.com/&quot;&gt;Charlie&lt;/a&gt; all worried with your enthusiasm for Rubinius.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; Ahem, you should probably also read: &lt;a href=&quot;http://blog.brightredglow.com/2009/2/12/this-is-not-cold-fusion&quot;&gt;This is &lt;span class=&quot;caps&quot;&gt;NOT&lt;/span&gt; cold fusion&lt;/a&gt;. No, it&amp;#8217;s not April 1st. Sorry about that. Are you still excited? Read on!&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s a pattern I&amp;#8217;m fairly familiar with now. &lt;a href=&quot;http://blog.fallingsnow.net/&quot;&gt;Evan&lt;/a&gt; will be pondering an issue with &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;. I&amp;#8217;ll catch wind of it when he starts asking some questions of smart people, reading academic CS papers, other implementation&amp;#8217;s code, and tossing out some &amp;#8220;what if&amp;#8230;&amp;#8221; questions. Next thing you know, he&amp;#8217;s frenetically churning out code. Suddenly, Rubinius is much better, and in this case, &lt;em&gt;faster&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Well, it&amp;#8217;s happened again and the preliminary results are &lt;em&gt;outstanding_. A couple weeks ago, Evan began coding some changes to the way the Rubinius bytecode interperter works. He changed the stackless execution architecture that implemented an optimized kind of &lt;a href=&quot;http://en.wikipedia.org/wiki/Spaghetti&quot;&gt;spaghetti stack&lt;/a&gt;&lt;/em&gt;stack to use the C stack more directly and naturally. This better enables the &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; optimizations of the past dozen years to work. It also significantly simplifies the code for our &lt;span class=&quot;caps&quot;&gt;FFI&lt;/span&gt;, C-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; for C extensions, &lt;span class=&quot;caps&quot;&gt;JIT&lt;/span&gt;, and for potentially leveraging &lt;span class=&quot;caps&quot;&gt;LLVM&lt;/span&gt; much more effectively. This change also brings native threads, and a much better GC for the mature generation is also in the works.&lt;/p&gt;
&lt;p&gt;Now, for some details. Again, these results are preliminary. There is still a lot of breakage on the &lt;a href=&quot;http://github.com/evanphx/rubinius/commits/stackfull&quot;&gt;stackfull&lt;/a&gt; branch but MSpec is already running and &lt;em&gt;many&lt;/em&gt; of the CI specs run. I&amp;#8217;ll be getting a new CI set in place today and we&amp;#8217;ll get the remaining breakage fixed quickly (don&amp;#8217;t ya just love those specs).&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s some numbers for compiling and running the String specs.&lt;/p&gt;
&lt;p&gt;First, on the Rubinius master branch:&lt;/p&gt;
&lt;pre&gt;
    Finished in 25.829773 seconds

    69 files, 763 examples, 5632 expectations, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;Now, on the Rubinius stackfull branch:&lt;/p&gt;
&lt;pre&gt;
    Finished in 5.834874 seconds

    69 files, 754 examples, 5563 expectations, 6 failures, 19 errors
&lt;/pre&gt;
&lt;p&gt;Here&amp;#8217;s the numbers for running after the specs have been compiled.&lt;/p&gt;
&lt;p&gt;Again, on the master branch:&lt;/p&gt;
&lt;pre&gt;
    Finished in 5.101799 seconds

    69 files, 763 examples, 5632 expectations, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;And now the stackfull branch:&lt;/p&gt;
&lt;pre&gt;
    Finished in 1.564942 seconds

    69 files, 754 examples, 5563 expectations, 6 failures, 19 errors
&lt;/pre&gt;
&lt;p&gt;I&amp;#8217;ll let that sink in a bit&amp;#8230;&lt;/p&gt;
&lt;p&gt;The numbers for Hash with compilation are similar.&lt;/p&gt;
&lt;p&gt;Master:&lt;/p&gt;
&lt;pre&gt;
    Finished in 5.379050 seconds

    48 files, 195 examples, 425 expectations, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;Stackfull:&lt;/p&gt;
&lt;pre&gt;
    Finished in 1.295544 seconds

    48 files, 193 examples, 421 expectations, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;That&amp;#8217;s right, &lt;del&gt;between 4.1 and 4.4&lt;/del&gt; &lt;strong&gt;approaching 2&lt;/strong&gt; &lt;em&gt;times&lt;/em&gt; faster (see the &lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt; above). And we are just getting started. The significant GC changes are not in yet. We are not &lt;em&gt;yet&lt;/em&gt; doing any significant optimizations in the compiler, no profile-directed optimizations at runtime, and our nascent &lt;span class=&quot;caps&quot;&gt;JIT&lt;/span&gt; is not hooked up by default. As I said at the outset, these optimizations are made easier by this architecture change.&lt;/p&gt;
&lt;p&gt;While I&amp;#8217;m breaking the news, Evan deserves the credit for the architecture decisions and generally being courageous enough to try and learn (some would say fail) and try again. Some have doubted that the lofty goals Rubinius has set are realistic. Doubters have a seat.&lt;/p&gt;
&lt;p&gt;If you want to try this at home, clone the &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/master&quot;&gt;Rubinius Github&lt;/a&gt; repository and do the following:&lt;/p&gt;
&lt;pre&gt;
    $ git branch --track stackfull origin/stackfull
    $ rake build
    $ bin/mspec ci core/string
&lt;/pre&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; for trusting in Evan&amp;#8217;s excellent judgment and system architecture talents and in all our hard work even if it doesn&amp;#8217;t look immediately relevant. The path is clear. The goods are in the truck and they will be delivered.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Call of the lemming</title>
    <id>http://brixen.io/2008/11/23/call-of-the-lemmings</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/11/23/call-of-the-lemmings" />
    <published>2008-11-23T00:00:00-08:00</published>
    <updated>2008-11-23T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;It&amp;#8217;s sometimes hard to gauge troll, tirade, or spirited challenge online. &lt;a href=&quot;http://kirindave.tumblr.com/post/60776407/the-opposite-of-momentum&quot;&gt;The Opposite of Momentum&lt;/a&gt; strikes me as a mix, though in what percentages, I haven&amp;#8217;t decided. KirinDave is a little late to the bag&amp;#45;on&amp;#45;Ruby party, and if it&amp;#8217;s Javascript he wants, &lt;a href=&quot;http://steve-yegge.blogspot.com/&quot;&gt;Yegge&lt;/a&gt; was there well over a year ago. Browse some of the mind-expanding comments by the bottom feeders at &lt;a href=&quot;http://www.reddit.com/r/programming/comments/7epu0/ruby_and_the_opposite_of_momentum/&quot;&gt;Reddit&lt;/a&gt; chewing on KirinDave&amp;#8217;s post. It&amp;#8217;s a reassuring, if disappointing, commentary on the consistency of human behavior: it is always easier to complain than to fix.&lt;/p&gt;
&lt;p&gt;But, anyway.&lt;/p&gt;
&lt;p&gt;True, the reference implementation of Ruby has some problems. But, Rubinius has a precise, generational garbage collector. It is definitely not &amp;#8220;technically stagnant&amp;#8221;, nor is it &amp;#8220;in implementation limbo&amp;#8221;. It was only in May of this year, before RailsConf, that we first got Rails running on Rubinius. We are close to getting it running again on the new VM. If we do that by year&amp;#8217;s end, we will surely have some kind of record. For all the thousands of lines of Ruby code he&amp;#8217;s written, KirinDave hasn&amp;#8217;t contributed any code to Rubinius. That&amp;#8217;s too bad.&lt;/p&gt;
&lt;p&gt;Ruby isn&amp;#8217;t that extraordinary as a language. But it is a very good language. What is more, Ruby is a &lt;em&gt;humane&lt;/em&gt; language, in the spirit of &lt;a href=&quot;http://en.wikipedia.org/wiki/Jef_Raskin&quot;&gt;Jef Raskin&amp;#8217;s&lt;/a&gt; &lt;a href=&quot;http://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1227419893&amp;amp;sr=8-1&quot;&gt;The Humane Interface&lt;/a&gt;. Furthermore, now like never before is the age of the dynamic programming language. The technical hurdles are being explored all around us. In fact, before the year is over, you should spend a few quality hours with one or more of the following languages.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.factorcode.org/&quot;&gt;Factor&lt;/a&gt;. This fascinating &lt;a href=&quot;http://en.wikipedia.org/wiki/Concatenative_language&quot;&gt;concatenative&lt;/a&gt; language will definitely get you thinking outside of the box. Rubinius is a stack-based VM. Writing some Factor code is a little like peeling back the syntax layer of Ruby and watching the muscles and tendons work. Check out the quotations and combinators and think about how you write functional code with Ruby. Don&amp;#8217;t miss the Google &lt;a href=&quot;http://www.youtube.com/watch?v=f_0QlhYlS8g&quot;&gt;tech talk&lt;/a&gt; by Factor&amp;#8217;s creator, Slava Pestov.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://clojure.org/&quot;&gt;Clojure&lt;/a&gt;. This is another fascinating language by another wicked smart guy, Rich Hickey (check out &lt;a href=&quot;http://blip.tv/file/812787&quot;&gt;the video&lt;/a&gt;). In fact, this is currently my favorite language to study. It&amp;#8217;s the Ruby of Lisps, in my opinion. And it contains a wealth of ideas that could be useful for implementing Rubinius, not to mention, thinking about writing concurrent programs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.iolanguage.com/&quot;&gt;Io&lt;/a&gt;. Like Javascript? You owe it to yourself to play with this language a bit. I&amp;#8217;d be interested to see about an implementation of Io on &lt;a href=&quot;http://webkit.org/blog/214/introducing-squirrelfish-extreme/&quot;&gt;SquirrelFish Extreme&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://haskell.org/&quot;&gt;Haskell&lt;/a&gt;. Amaze your friends and improve your sex life. Jump stateful, side-effect tangled heaps of code with a single Monad. There is a cool new &lt;a href=&quot;http://book.realworldhaskell.org/&quot;&gt;online book&lt;/a&gt; that will soon be released in print as well.&lt;/p&gt;
&lt;p&gt;Seriously, if you are a Ruby programmer, you could hardly do poorly by adopting any one of these languages. If Javascript makes your curly braces tingle, who am I to ridicule you. But if Ruby continues to maintain its captivating hold on your attention, don&amp;#8217;t be disappointed. There is some awesome sauce in there, and we&amp;#8217;re working on the recipe that really makes the flavor pop. Just a little request, instead of bitchin&amp;#8217;, &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/master/doc/contributing.txt&quot;&gt;pitch in&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Rubinius is a community project</title>
    <id>http://brixen.io/2008/11/18/rubinius-is-a-community-project</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/11/18/rubinius-is-a-community-project" />
    <published>2008-11-18T00:00:00-08:00</published>
    <updated>2008-11-18T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Yesterday was a tough day. You can read the &lt;a href=&quot;http://blog.engineyard.com/2008/11/17/rubinius-past-present-and-future&quot;&gt;details&lt;/a&gt; and &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&amp;#8217;s&lt;/a&gt; &lt;a href=&quot;http://blog.fallingsnow.net/2008/11/18/a-sad-day/&quot;&gt;thoughts&lt;/a&gt; about it.&lt;/p&gt;
&lt;p&gt;It was especially hard for me because &lt;a href=&quot;http://metaclass.org/&quot;&gt;Wilson&lt;/a&gt; was a mentor of sorts and the first person I talked to when I dropped into the #rubinius channel nearly two years ago. He allayed any fear I had that Rubinius would fragment the Ruby community and helped me get started contributing.&lt;/p&gt;
&lt;p&gt;And &lt;a href=&quot;http://journal.kittensoft.org/&quot;&gt;Eero&lt;/a&gt;, among many other things, jumped on board right away and toiled for many hours on the early specs, putting up with my dead ends when the project that is now &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpec&lt;/a&gt; was merely an expedient to fast-track Rubinius development.&lt;/p&gt;
&lt;p&gt;So, I want to express my thanks to my teammates and wish them the best in their next endeavors. And I want to emphasize something that is well known to those of us who have worked hard on Rubinius from long before &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; began to support the project: &lt;strong&gt;Rubinius is a community project&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Evan&amp;#8217;s free-flowing commit bit, the early adoption of Git, and the emphasis on writing specs while developing are just a few aspects that have helped propel Rubinius very quickly in its couple year history. And there is still plenty of exciting and interesting work to be done. We are all very grateful for Engine Yard&amp;#8217;s support of the project, and that support remains strong and dedicated.&lt;/p&gt;
&lt;p&gt;But the key to Rubinius&amp;#8217; success is the community. In the past year, I feel we have to some extent let you, the community, down. We need to make Rubinius even easier to try out, understand, and contribute to. And we need your feedback on ways we can do this. The recent VM rewrite has been a huge step forward in this regard. But have you opened up the code, poked around, asked us about stuff that doesn&amp;#8217;t make sense? If you haven&amp;#8217;t, let us know why not. Have you taken a look at a failing spec for the core library? There&amp;#8217;s tons of beautiful Ruby code just begging for some love. Let us know what barriers prevent you from spending some free time in there.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re worried that development on Rubinius will slow down, I would challenge you to not let that happen. Evan produces prodigious amounts of code and has a terrific mix of genius and pragmatism. I will certainly not be working any less hard than I have for the past two years. So if you, like me, believe that Rubinius can be a terrific platform for Ruby, jump in. No contribution is too small. And we&amp;#8217;re building on a solid foundation of past success.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Hash is all ponies</title>
    <id>http://brixen.io/2008/9/3/hash-is-all-ponies</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/9/3/hash-is-all-ponies" />
    <published>2008-09-03T00:00:00-07:00</published>
    <updated>2008-09-03T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;We&amp;#8217;ve been hard at work replacing the C virtual machine in &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; with one written in C++. Along the way, we decided to use a simpler data structure internally where we had been using a Hash before. This allowed us to rewrite Hash in pure Ruby. Since our goal is to write as much &lt;a href=&quot;http://blog.brightredglow.com/2008/4/28/ruby-in-ruby-seriously&quot;&gt;Ruby in Ruby&lt;/a&gt;, I was happy to work on this rewrite.&lt;/p&gt;
&lt;p&gt;You can check out the resulting code &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/cpp/kernel/bootstrap/hash.rb&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/cpp/kernel/common/hash.rb&quot;&gt;here&lt;/a&gt;. It hasn&amp;#8217;t been polished much yet, but the idea was to use expressive and natural Ruby. I didn&amp;#8217;t take any performance-conscious tacks. Hash should provide a great case study for looking at optimizations in our compiler and VM. For example, &lt;code&gt;Hash#keys&lt;/code&gt; can be succinctly written as:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since &lt;code&gt;#inject&lt;/code&gt; comes from the &lt;code&gt;Enumerable&lt;/code&gt; module, we know it&amp;#8217;s using &lt;code&gt;#each&lt;/code&gt; internally. And for Hash, I implemented an external iterator of sorts to help hide the implementation details. That iterator is making a method call for each item. So we&amp;#8217;ve piled on two block calls and a method call for each item. The point is, we want that expressive Ruby code in our applications and let the implementation optimize it. So far, we really haven&amp;#8217;t had any Ruby implementation to give us that.&lt;/p&gt;
&lt;p&gt;Another thing to check out is the structure of our &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/7f8af1531125850bc75b8315269a7e0528e98c50/kernel&quot;&gt;kernel directory&lt;/a&gt;. Talking to the folks working on &lt;a href=&quot;http://ruby.gemstone.com/&quot;&gt;MagLev&lt;/a&gt;, we&amp;#8217;ve restructured our runtime kernel (aka Ruby standard library) to better allow sharing with other implementations. The &lt;code&gt;bootstrap&lt;/code&gt; and &lt;code&gt;delta&lt;/code&gt; directories are implementation specific, while the &lt;code&gt;common&lt;/code&gt; directory is intended to be shared. The &lt;code&gt;bootstrap&lt;/code&gt; directory provides just enough functionality to load the &lt;code&gt;common&lt;/code&gt; directory. The &lt;code&gt;delta&lt;/code&gt; directory provides a location for implementation specialization where specific methods can be replaced with more performant or otherwise specialized versions.&lt;/p&gt;
&lt;p&gt;As always, we love to hear from folks about what&amp;#8217;s bugging them with Ruby. Drop by #rubinius on freenode.net or check out the &lt;a href=&quot;http://github.com/evanphx/rubinius/tree/master&quot;&gt;Rubinius&lt;/a&gt; project on &lt;a href=&quot;http://github.com&quot;&gt;Github&lt;/a&gt;. Even though we&amp;#8217;re in the middle of this VM rewrite, there&amp;#8217;s plenty still to be done on the Ruby standard library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt; points out that this is a better implementation of &lt;code&gt;#keys&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
  </entry>
  
  <entry>
    <title>As del.icio.us as a giant, steaming turd</title>
    <id>http://brixen.io/2008/8/1/as-del-icio-us-as-a-giant-steaming-turd</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/8/1/as-del-icio-us-as-a-giant-steaming-turd" />
    <published>2008-08-01T00:00:00-07:00</published>
    <updated>2008-08-01T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I often dislike the interfaces that I&amp;#8217;m forced to use. Banking sites are about the highest on my list of horrid. The pain these things inflict.&lt;/p&gt;
&lt;p&gt;However, today I got a new jolt. Clicked on my handy &lt;a href=&quot;http://del.icio.us&quot;&gt;del.icio.us&lt;/a&gt; shortcut in Firefox and was greeted by a bizarre interface. Not to worry, I powered on, since of course, the reason I use &lt;a href=&quot;http://del.icio.us&quot;&gt;del.icio.us&lt;/a&gt; in the first place is because it was super quick and easy to add a bookmark. Quick is no longer in the vocabulary for &lt;a href=&quot;http://del.icio.us&quot;&gt;del.icio.us&lt;/a&gt;. Instead of simply typing a few characters, hitting &amp;lt;tab&amp;gt; and being done with it, I now have to arrow in this stupid drop-down? Amazed, I started taking a closer look at the unwelcome intruder in my nice browse + bookmark flow.&lt;/p&gt;
&lt;p&gt;The lame new auto-complete behavior is a breaker for me. However, it&amp;#8217;s hard to say if that&amp;#8217;s the worst of the UI redesign. The 3-option choice for the main list display goes from bad to worse to horrid. Is the date, in washed out grey, &lt;em&gt;really&lt;/em&gt; the most important piece of info that I need to see in my normal scan from left-to-right? I can barely scan any of the options quickly for the information I need to help me select a link. And where did my nice big entry field go for typing in a tag? Oh, there it is, camouflaged in that bar at the top of the list. Don&amp;#8217;t really want me to use that, huh?&lt;/p&gt;
&lt;p&gt;I could go on, but what&amp;#8217;s the use. The amazing thing to me is that someone, somewhere thought this was a good idea. Have these idiots never heard of Alan Cooper, IxD, the rich body of books describing why you don&amp;#8217;t design interfaces like this? Harsh? Damn, right. Horrid.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>OSCON 2008</title>
    <id>http://brixen.io/2008/7/21/oscon-2008</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/7/21/oscon-2008" />
    <published>2008-07-21T00:00:00-07:00</published>
    <updated>2008-07-21T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;If you&amp;#8217;re headed to &lt;a href=&quot;http://en.oreilly.com/oscon2008/public/content/home&quot;&gt;&lt;span class=&quot;caps&quot;&gt;OSCON&lt;/span&gt; 2008&lt;/a&gt;, I hope I&amp;#8217;ll have a chance to meet you. I&amp;#8217;ll be speaking on Thursday afternoon, something about Ruby performance. Come and heckle me if you wish. Here&amp;#8217;s the talk details:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.oreilly.com/oscon2008/public/schedule/detail/2333&quot;&gt;Who Wants a Faster Ruby?&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;07/24/2008&lt;/li&gt;
	&lt;li&gt;2:35pm &amp;#8211;  3:20pm &lt;span class=&quot;caps&quot;&gt;PDT&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;Room: F151&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, please do come check out &lt;a href=&quot;http://pdxfoscon.org/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;FOSCON&lt;/span&gt;&lt;/a&gt;. This is the 4th year for &lt;span class=&quot;caps&quot;&gt;FOSCON&lt;/span&gt;. w00t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; Thanks to all who attended my talk. I&amp;#8217;ve uploaded the &lt;a href=&quot;http://blog.brightredglow.com/assets/2008/7/24/faster_ruby_oscon08.pdf&quot;&gt;slides&lt;/a&gt;. If you attended, please take a moment to &lt;a href=&quot;http://en.oreilly.com/oscon2008/public/schedule/evaluate/2333&quot;&gt;send feedback&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Implementers Unite!</title>
    <id>http://brixen.io/2008/5/16/implementers-unite</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/5/16/implementers-unite" />
    <published>2008-05-16T00:00:00-07:00</published>
    <updated>2008-05-16T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;There&amp;#8217;s a lot of things that &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;, &lt;a href=&quot;http://ruby-lang.org/en/about&quot;&gt;MatzRuby&lt;/a&gt; (including &lt;a href=&quot;http://www.atdot.net/yarv/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;YARV&lt;/span&gt;&lt;/a&gt;), &lt;a href=&quot;http://jruby.codehaus.org&quot;&gt;JRuby&lt;/a&gt;, &lt;a href=&quot;http://www.ironruby.net/&quot;&gt;IronRuby&lt;/a&gt;, &lt;a href=&quot;http://ruby.macosforge.org/trac/wiki/MacRuby&quot;&gt;MacRuby&lt;/a&gt;, &lt;a href=&quot;http://rubyurl.com/XN99&quot;&gt;Ruby.&lt;span class=&quot;caps&quot;&gt;NET&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://ruby.gemstone.com/&quot;&gt;MagLev&lt;/a&gt; don&amp;#8217;t agree on. But that&amp;#8217;s ok, because above all, they seem to agree that &lt;a href=&quot;http://ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; is one awesome language. And lately, that apparent agreement has gotten a boost of sorts.&lt;/p&gt;
&lt;p&gt;Earlier this week, Rubinius (an &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; project) &lt;a href=&quot;http://groups.google.com/group/ruby-talk-google/browse_thread/thread/e20f76ca2b8afe78&quot;&gt;announced&lt;/a&gt; the &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpec&lt;/a&gt; project at &lt;a href=&quot;http://rubyspec.org&quot;&gt;rubyspec.org&lt;/a&gt;. The effort to write an executable specification using &lt;a href=&quot;http://rspec.info&quot;&gt;RSpec-style&lt;/a&gt; specs started with the Rubinius project in late December 2006. Since then, many people all over the world have contributed to the effort, including core folks from JRuby. &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; has been financially supporting significant development of the RubySpecs since hiring &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt; in June 2007 and other full-time developers (myself included) in Jan 2008. All this effort has been to ensure that the Ruby programming language continues to evolve and receive the recognition it deserves.&lt;/p&gt;
&lt;p&gt;Another recent development has been a regular meeting of folks working on various Ruby implementations. These &lt;a href=&quot;http://ruby-design.pbwiki.com/&quot;&gt;Ruby design meetings&lt;/a&gt; are bringing together folks to discuss tough issues with Matz and everyone else.&lt;/p&gt;
&lt;p&gt;Well, after last night&amp;#8217;s meeting, Tanaka Akira (sorry, I don&amp;#8217;t have a link to his website; if you do, please let me know) checked in some &lt;a href=&quot;http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&amp;amp;revision=16430&quot;&gt;changes&lt;/a&gt; to the ruby-core Makefile to fetch and run the RubySpecs. This is a very proud moment for me.&lt;/p&gt;
&lt;p&gt;If you love Ruby, it doesn&amp;#8217;t matter what color shirt you wear, what language you play with, or what country you live in. You can play a valuable role in helping make Ruby a wonderful language for everyone. Please help us with the &lt;a href=&quot;http://rubyspec.org&quot;&gt;RubySpecs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I changed the link to the changeset for the Makefile. Thanks Michael.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Ruby in Ruby--Seriously</title>
    <id>http://brixen.io/2008/4/28/ruby-in-ruby-seriously</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/4/28/ruby-in-ruby-seriously" />
    <published>2008-04-28T00:00:00-07:00</published>
    <updated>2008-04-28T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;All the attention that the various &lt;a href=&quot;http://ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; implementations are getting these days is a wonderful thing. Competition and lots of people trying out different ideas is a win for everyone. That said, there are still the silly human issues of ego and vested interest, always exacerbated by tossing some green into the mix.&lt;/p&gt;
&lt;p&gt;I would definitely assert that &lt;a href=&quot;http://jruby.codehaus.org&quot;&gt;JRuby&lt;/a&gt; is one of the more impressive stabs at a Ruby implementation. And we have, in large measure, to thank &lt;a href=&quot;http://headius.blogspot.com&quot;&gt;Charles&lt;/a&gt; for that. But, at the same time, Charles can write &lt;a href=&quot;http://headius.blogspot.com/2008/04/promise-and-peril-for-alternative-ruby.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;FUD&lt;/span&gt;&lt;/a&gt; like the best of them. I haven&amp;#8217;t made it through the whole article yet (it does ramble on a bit), but I should point out a couple things.&lt;/p&gt;
&lt;p&gt;Method dispatch is hard to get fast in Ruby, no matter what. Substitute a VM for an interpreter, C# for C for Java, whatever. And if you read carefully about what Charles is pinning his hopes on for the future of JRuby, it is precisely optimizations in the new &lt;span class=&quot;caps&quot;&gt;JVM&lt;/span&gt; for better method dispatch. Rubinius will address these issues for sure. But instead of working on this with something like &lt;strong&gt;143,866&lt;/strong&gt; lines of Java code, we have something like this: In the new C++ VM (which is not yet complete but substantially implemented), we have &lt;strong&gt;12,619&lt;/strong&gt; lines of &lt;code&gt;C++&lt;/code&gt;, and in our kernel directory, we have &lt;strong&gt;23,882&lt;/strong&gt; lines of, what now, oh, right &lt;em&gt;Ruby&lt;/em&gt; code. What you might miss when you think about the &lt;strong&gt;143,866&lt;/strong&gt; lines of Java code is the several hundred thousand lines of &lt;code&gt;C++&lt;/code&gt; that make up the &lt;span class=&quot;caps&quot;&gt;JVM&lt;/span&gt;. Hmm.&lt;/p&gt;
&lt;p&gt;So, ultimately, Charles hopes to make JRuby fast using the same basic techniques that Rubinius does and will use. Except, it seems he&amp;#8217;d rather use a 747 passenger jet to mow his lawn, rather than a comfy John Deere riding mower that your average small engine enthusiast can tinker with when something goes awry.&lt;/p&gt;
&lt;p&gt;Seriously, the &amp;#8220;Ruby in Ruby&amp;#8221; meme &lt;em&gt;must not die&lt;/em&gt;. It is an inspiration to a lot of folks and, most importantly, it has great promise. Press Charles on the issue and he will admit he&amp;#8217;d rather have more of JRuby written in Ruby. I sense something of &amp;#8220;bitter-gate&amp;#8221; in Charles&amp;#8217; post. We don&amp;#8217;t cling to Ruby because we can&amp;#8217;t write C#, C, Java, etc. We don&amp;#8217;t just like Ruby when it&amp;#8217;s fun and fashionable and hyped. We are demonstrating that Ruby can be sanely implemented and push the state of the art for the language forward.&lt;/p&gt;
&lt;p&gt;The C VM (named shotgun) was not our last word. Nor is the next generation C++ VM. They are both pragmatic steps toward a higher goal. And, let&amp;#8217;s be very clear. We have not recently implemented a bunch of core methods in C. I&amp;#8217;ve done two major pieces of rework recently that introduced a number of primitives (chunks of C code that access the VM directly). One was LookupTable, which was written in C because it is used heavily in the VM. However, it is exposed to Ruby code as well because, oh yes, we write a ton of stuff in Ruby, like stuff related to method and constant lookup. LookupTable acts a lot like a Hash, but separating it from Hash actually made Hash more clear and enabled writing &lt;em&gt;even more&lt;/em&gt; of Hash in Ruby.&lt;/p&gt;
&lt;p&gt;Another piece of work was optimizing some of String&amp;#8217;s methods. You can see the performance enhancements in &lt;a href=&quot;http://rubinius.lighthouseapp.com/projects/5089/tickets/359-task-improve-performance-of-string&quot;&gt;this ticket&lt;/a&gt;. I did introduce a couple new primitives in this rework, mostly to make a more sane set of composable primitives that were useful in many String methods. Primitives are a necessary fact of life in this composite implementation. Something has to bridge Ruby and &lt;code&gt;C/C++&lt;/code&gt;. Also, by using a well-defined set of primitives, it makes it very easy to take our Ruby core libs and run them on something else. Ask Charles and he will tell you this. And if we write a little &lt;code&gt;C/C++&lt;/code&gt; to get the performance of a large number of Ruby methods up to par, that&amp;#8217;s a huge win.&lt;/p&gt;
&lt;p&gt;So again, the &amp;#8220;Ruby in Ruby&amp;#8221; meme is &lt;em&gt;really&lt;/em&gt; important. Don&amp;#8217;t let it die. And don&amp;#8217;t let Charles tell you otherwise. While he can make snarky comments about our &lt;code&gt;C/C++&lt;/code&gt; VM, he should really look at his own kettle of &lt;strong&gt;143,866&lt;/strong&gt; lines of Java code plus hundred thousands more lines of &lt;code&gt;C++&lt;/code&gt; &lt;span class=&quot;caps&quot;&gt;JVM&lt;/span&gt;. The goal is a first-rate, powerful, extensible, approachable implementation of Ruby. Everyone in the Ruby ecosystem is contributing to that in various ways. Rubinius just seems to be putting the best pieces together, if I do say so myself.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Rubinius runs RSpec 1.1.2</title>
    <id>http://brixen.io/2008/1/18/rubinius-runs-rspec-1-1-2</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/1/18/rubinius-runs-rspec-1-1-2" />
    <published>2008-01-18T00:00:00-08:00</published>
    <updated>2008-01-18T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;This day has been a long time coming. About a year ago, I started trying to get &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; to run &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt;. Hats off to all the wonderful Rubinius contributors and special mention to the cool guys who hung out with me at &lt;a href=&quot;http://rubini.us/forums/5/topics/11&quot;&gt;pdx.rbc meetups&lt;/a&gt; in early 2007. (Unfortunately, the page in that link will disappear soon. Maybe I&amp;#8217;ll make a pdf out of it and keep it here. You know, nostalgia.)&lt;/p&gt;
&lt;p&gt;Everyone&amp;#8217;s efforts have paid off and here is the proof:&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;
$ shotgun/rubinius -I ../rspec-1.1.2/lib/ ../rspec-1.1.2/bin/spec spec/ruby/1.8/core/true/
.....

Finished in 0.988572 seconds

5 examples, 0 failures

&lt;/pre&gt;
&lt;p&gt;The TrueClass specs were some of the very first ones I wrote, so I thought it fitting those be the first ones I ran successfully with RSpec.&lt;/p&gt;
&lt;p&gt;Congratulations everyone!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Evil can be dangerous</title>
    <id>http://brixen.io/2008/1/17/evil-can-be-dangerous</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/1/17/evil-can-be-dangerous" />
    <published>2008-01-17T00:00:00-08:00</published>
    <updated>2008-01-17T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;The first post I read by &lt;a href=&quot;http://blog.fallingsnow.net/&quot;&gt;Evan&lt;/a&gt; about &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; had a quote about &lt;a href=&quot;http://blog.fallingsnow.net/rubinius/&quot;&gt;evil built in&lt;/a&gt;. Of course, that caught my eye. What was Evan&amp;#8217;s point? Legend has it (I wasn&amp;#8217;t there) that during Q&amp;amp;A someone asked about fundamental aspects of the Rubinius system being available for modification from normal user code. The issue was raised that perhaps something should restrict that unlimited power. Evan&amp;#8217;s response was that Rubinius sorta has evil built in. Usually, that&amp;#8217;s a good thing.&lt;/p&gt;
&lt;p&gt;In fact, it&amp;#8217;s a very sharp double-edged blade. We all cherish the dynamic nature of Ruby when it allows us to do useful things. For example, the following works great in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fixnum&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quo&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That little snippet and you&amp;#8217;ve redefined fixed-point math to return a floating point number. That gem is one of the core pieces of the Mathn library in the Ruby standard library collection. Together with the Rational library, you can do some cool stuff:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
$ irb
&amp;gt;&amp;gt; require 'rational'
=&amp;gt; false
&amp;gt;&amp;gt; require 'mathn'
=&amp;gt; true
&amp;gt;&amp;gt; 1 / 2
=&amp;gt; 1/2
&amp;gt;&amp;gt; 1 / 2 + 3 / 8
=&amp;gt; 7/8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Combine that with Matrix and Rational and you have at your disposal some pretty powerful tools for doing more realistic mathematics. Take a look at &lt;a href=&quot;http://google.com/codesearch?q=lang%3Aruby+require+mathn&amp;amp;hl=en&amp;amp;btnG=Search+Code&quot;&gt;what some folks do&lt;/a&gt; with it.&lt;/p&gt;
&lt;p&gt;Fortunately, and unfortunately, Rubinius is very different than every other implementation of Ruby that I&amp;#8217;m aware of. Rubinius follows the Smalltalk model and uses the Ruby language itself to build the implementation. That means that Array, for instance, calculates values for its internal operations using none other than the same Fixnum values that you use in your Ruby code. So, what happens when we redefine Fixnum#/ to return a Float instead?&lt;/p&gt;
&lt;p&gt;Yes, you guessed right. Things work differently. In fact, not at all.&lt;/p&gt;
&lt;p&gt;Since we&amp;#8217;re not about to rescind the promise of a better Ruby, we have to figure out some way to deal with this. There are several approaches possible. One would be to code all of the core library with a different set of numeric classes, say BasicFixnum and BasicBignum, that are superclasses of Fixnum and Bignum. That would be really cumbersome. Another approach would be to use different methods in the core library. Again, cumbersome. So, this sounds like there are some basic goals we have in mind. In fact, there are. We want to keep the core library code as simple as possible and provide the full power of Ruby at every level, to the greatest extent possible.&lt;/p&gt;
&lt;p&gt;This isn&amp;#8217;t necessarily the ultimate approach we&amp;#8217;ll use, but I checked in some code today that leverages a very slick feature that Evan built into the compiler. I created the following compiler plugin:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SafeMathOperators&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Plugin&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;plugin&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:safemath&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;   &lt;span class=&quot;no&quot;&gt;MathOps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;:/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:divide&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;   
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MathOps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argcount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emit_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;receiver_bytecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Essentially, what this does is map any calls to the #/ method to the #divide method. I&amp;#8217;ve changed the core library classes Fixnum, Bignum, Float, and Numeric to handle this. So, the code in core looks the same, but is protected from the redefinition that the Mathn library performs. The compiler plugin is activated with the -frbx-safe-math switch only when compiling the Rubinius core libraries.&lt;/p&gt;
&lt;p&gt;&amp;gt; &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; Note that you do not have to do anything differently. The compiler flag is passed in automatically when you type &lt;code&gt;rake&lt;/code&gt; to build the Rubinius libraries. If you are writing user code, you also do not need to do anything differently. You just write your code as you normally would. If you require the Mathn library, &lt;code&gt;1 / 2 =&amp;gt; 0.5&lt;/code&gt;. If you also require the Rational library &lt;code&gt;1 / 2 =&amp;gt; 1/2&lt;/code&gt;. Invisible, maybe even a little evil.&lt;/p&gt;
&lt;p&gt;Again, this is not necessarily the way we&amp;#8217;ll always do it. The lessons are:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Ruby is a great, powerful language&lt;/li&gt;
	&lt;li&gt;Rubinius makes Ruby even more powerful&lt;/li&gt;
	&lt;li&gt;We can work around snags pretty dang easily, even if temporarily&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course, we&amp;#8217;re always learning. Any papers, systems, code, etc that you can point me to?&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Contra--what?</title>
    <id>http://brixen.io/2008/1/17/contra-what</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/1/17/contra-what" />
    <published>2008-01-17T00:00:00-08:00</published>
    <updated>2008-01-17T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I&amp;rsquo;m going to be pedantic for a minute. If you are Betrand Russell, feel free to spend your time more productively. Everyone else, don&amp;rsquo;t be afraid of a few symbols.&lt;/p&gt;

&lt;p&gt;If you read my &amp;ldquo;last post&amp;rdquo;:http://blog.brightredglow.com/2008/1/17/evil-can-be-dangerous, you might be inclined, as is every human mind, to reduce all those words to something simple you can put in your back pocket (maybe take it out later and show it to a friend). Perhaps something like this:&lt;/p&gt;

&lt;pre&gt;
  Immutable == Security == Good
&lt;/pre&gt;

&lt;p&gt;If you do that, you might get lots of nods and a fair bit of affirmation from folks. Makes perfect sense, right. You can make all sorts of analogies that &lt;em&gt;prove&lt;/em&gt; this to you. Consider my front door, if it&amp;rsquo;s not easily opened, I feel more secure. Perfect. Must be true.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s not. Things are not so easily distilled into such nifty little boxes.&lt;/p&gt;

&lt;p&gt;Now, once they have this shiny, handy, palm-sized summary in their back pocket, folks tend to go the extra mile. They decide to make one of the most fundamental logic errors. Essentially, trying to think all the way around this hairy problem, they decide:&lt;/p&gt;

&lt;pre&gt;
  If Immutable == Security
  Then Not Immutable == Not Security
&lt;/pre&gt;

&lt;p&gt;Doh. That&amp;rsquo;s where this contra thing comes in. Read the gory details on &amp;ldquo;Wikipedia&amp;rdquo;:http://en.wikipedia.org/wiki/Contraposition, but here&amp;rsquo;s the summary:&lt;/p&gt;

&lt;p&gt;In logic, something like &lt;code&gt;A -&amp;gt; B&lt;/code&gt; is read &amp;ldquo;A implies B&amp;rdquo; or &amp;ldquo;if A then B&amp;rdquo;. It is very tempting to then think, &amp;ldquo;if not A then not B&amp;rdquo;. Unfortunately, that is not generally true. Given &amp;ldquo;A implies B&amp;rdquo;, the statement &amp;ldquo;if not A then not B&amp;rdquo; is called the &lt;em&gt;inverse&lt;/em&gt;. Again, these are not generally logically equivalent. The statement &amp;ldquo;if not B then not A&amp;rdquo; is called the &lt;em&gt;contrapositive&lt;/em&gt;, and it &lt;em&gt;&lt;strong&gt;is&lt;/strong&gt;&lt;/em&gt; generally true that a statement and it&amp;rsquo;s contrapositive are logically equivalent.&lt;/p&gt;

&lt;p&gt;Applying this to the above, we can see that &lt;em&gt;IF&lt;/em&gt; (a very big if) it is true that &amp;ldquo;if Immutable then Secure&amp;rdquo; is true, then the statement &amp;ldquo;if not Secure then not Immutable&amp;rdquo; is equivalently true. However, it has not been demonstrated that immutability is equivalent to security. And indeed there are numerous ways to achieve &amp;ldquo;security&amp;rdquo; (a word that begs precise definition) in a variety of different systems.&lt;/p&gt;

&lt;p&gt;So, before you start touting something like Java because it is statically typed, immutable and &amp;ldquo;secure&amp;rdquo;, consider whether you are making the mistake of confusing the inverse for the contrapositive. If you&amp;rsquo;re feeling extra nimble and up for some mental gymnastics, consider this rather hyperbolic assertion:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ruby is a very, very sharp knife. Java is a little more like a butter knife. We safely leave butter knives on the table when the kids are around. But, we probably grumble more than a little when trying to cut our steak with a butter knife.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we want to make Ruby &amp;ldquo;safer&amp;rdquo;, it&amp;rsquo;s possible to do so in the same manner as dealing with sharp knives: we make something like a sheath. We don&amp;rsquo;t just take a hammer to the blade and dull it.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Irb in the house</title>
    <id>http://brixen.io/2008/1/5/irb-in-the-house</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2008/1/5/irb-in-the-house" />
    <published>2008-01-05T00:00:00-08:00</published>
    <updated>2008-01-05T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I&amp;#8217;m going to give this live blogging thing a go. As of 14:52 &lt;span class=&quot;caps&quot;&gt;PST&lt;/span&gt;, &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt; announced that &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; runs &lt;code&gt;irb&lt;/code&gt;. It hasn&amp;#8217;t landed in the repository yet, but this is great news. Just a little while ago, we &lt;a href=&quot;http://blog.brightredglow.com/2007/2/11/sirb-the-rubinius-loupe&quot;&gt;started with an irb wannabe&lt;/a&gt;. I guess a lot can happen in a year.&lt;/p&gt;
&lt;p&gt;Congrats to Evan and all the fantastic Rubinius supporters and contributors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; So, I&amp;#8217;m not a very good reporter. There&amp;#8217;s some other very big news related to getting &lt;code&gt;irb&lt;/code&gt; working. Evan &lt;a href=&quot;http://git.rubini.us/?p=code;a=commit;h=d54ed8791a74661adb87c938e92e037ece924c90&quot;&gt;checked in&lt;/a&gt; a working &lt;code&gt;eval&lt;/code&gt; yesterday. Enjoy!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Looking yourself in the eye</title>
    <id>http://brixen.io/2007/12/6/looking-yourself-in-the-eye</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/12/6/looking-yourself-in-the-eye" />
    <published>2007-12-06T00:00:00-08:00</published>
    <updated>2007-12-06T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I&amp;#8217;m hanging out this week at the &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt; office in South Park hoping to catch a glimpse of Cartman and pals (I wish!). You&amp;#8217;ve heard it all before but I would be remiss to not toss in my congratulations to my new (very soon) colleagues. &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt;, &lt;a href=&quot;http://metaclass.org/&quot;&gt;Wilson&lt;/a&gt;, &lt;a href=&quot;http://blog.zenspider.com/&quot;&gt;Ryan&lt;/a&gt;, and &lt;a href=&quot;http://blog.segment7.net/&quot;&gt;Eric&lt;/a&gt; are a stellar group of folks and a great bunch of personalities to boot. I am honored and extremely happy to be working closely with them, as well as the fantastic group of contributors world-wide.&lt;/p&gt;
&lt;p&gt;Everyone at Engine Yard deserves big accolades for the vision, daring, and execution in making all this possible. Here&amp;#8217;s my opinion (and gauntlet): This is why it is always the little companies that do something great. I see Ruby in general and &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; in particular as a powerful antidote to insane lumbering companies that have foisted agony, fear, and self-loathing on legions of otherwise decent folks with their sharp, pointy brackets and stupidly limited language features. Bring your hungry masses to our shores. We have the very ambitious intent to build the best programming language and system to date. Hubris? We&amp;#8217;ll see.&lt;/p&gt;
&lt;p&gt;Oh yeah, but about this looking at your own eyeball without a mirror thing. Some of you may recall that I&amp;#8217;ve been working a bit on writing specs for Ruby as part of this project. Since we could not run &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt; initially because of its extensive use of very advanced Ruby features, we wrote a minimal replacement for it that I affectionately dubbed mini_rspec. At the time I wrote this, we were converting a ton of specs from the early host/target architecture I started with. We may have been able to run miniunit at that time, but my intention was to write specs for mini_rspec as I went along evolving the features of the framework itself. This is a very difficult bootstrap process akin to looking at your own eyeball&amp;#8230; you get the picture. So, I must say I&amp;#8217;m solely responsible for this little gem:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/../spec_helper&amp;#39;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# hmm, this is embarrassing&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;mini rspec&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Of course, I took a nice bit of friendly needling (or should I say snickering) from Ryan for that one. But let&amp;#8217;s not dwell on the sordid details of the past. Currently, in my branch I have a rewritten (and renamed) mSpec. This is a little better:&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;&lt;code&gt;
euler:rubinius brian$ spec mspec/spec
.................................................................................................................................................................

Finished in 0.062927 seconds

161 examples, 0 failures

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#8217;s what I&amp;#8217;m talking about. This time, I wisely just used existing RSpec to write the specs because my goal is not necessarily to be able to run the mSpec specs with mSpec, but to be able to evolve the system while still keeping layers of it so simple that nascent Ruby implementations will actually be able to use it.&lt;/p&gt;
&lt;p&gt;A final word about the other approach. We wrote thousands of specs for Ruby using mini_rspec. We ran these specs against &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; 1.8.6 and they behaved as expected. So, those specs were essentially an indirect spec for mini_rspec. The challenge of that approach, of course, is that you do not have a simple and clear way to observe the impact of changes you make to the mini_rspec system. Anyway, I should finish up this massive bunch of changes very soon and push it out.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Send my love to Ruby II</title>
    <id>http://brixen.io/2007/9/20/send-my-love-to-ruby-ii</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/9/20/send-my-love-to-ruby-ii" />
    <published>2007-09-20T00:00:00-07:00</published>
    <updated>2007-09-20T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;In the &lt;a href=&quot;http://blog.brightredglow.com/2007/9/20/send-my-love-to-ruby&quot;&gt;last post&lt;/a&gt;, we saw a nice use case for the &lt;code&gt;#send&lt;/code&gt; method. Now, we&amp;#8217;ll see some coolness that Rubinius adds. First, some code:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Apple&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;seed&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Apple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;7&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:seed&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__send__&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:seed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, with the convenient and useful &lt;code&gt;describe&lt;/code&gt; facility of the Rubinius compiler, we can see something interesting:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
$ shotgun/rubinius describe send.rb
Path: send.rb
Size: 79 bytes

Sexp:
  [:block, 
  [:newline, 1, &quot;(eval)&quot;, 
    [:class, [:colon2, :Apple], nil, 
      [:scope, 
        [:newline, 2, &quot;(eval)&quot;, set_local_fp 1 ; local a

---- snip ----

pop
#line 8
push_literal 1
get_local_fp 1 ; local a
send send 1
pop
#line 9
get_local_fp 1 ; local a
push nil
push_literal 2
dup
is_symbol
git send_lbl1
send to_sym 0
send_lbl1:
push 0
set_args
send_off_stack
pop
push true
ret

---- snip ----
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#8217;ve truncated that output, but feel free to run this at home. (There&amp;#8217;s no long lasting side effects other than an itching desire to contribute to the Rubinius project.) If you correlate the assembly with the line numbers in the source, you&amp;#8217;ll notice that the two sends are not turning out to be the same. That&amp;#8217;s right. We have a special, and fast, &lt;code&gt;__send__&lt;/code&gt; operation.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;#send&lt;/code&gt; method is a highly useful bit of Ruby. Unfortunately, there&amp;#8217;s some concern that using it can hurt performance. Well, with Rubinius you can have your send and use it, too.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Send my love to Ruby</title>
    <id>http://brixen.io/2007/9/20/send-my-love-to-ruby</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/9/20/send-my-love-to-ruby" />
    <published>2007-09-20T00:00:00-07:00</published>
    <updated>2007-09-20T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Over at the &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; project, in between hatching plots to take over the world, we fit in some time for recreation. For example, we&amp;#8217;ve got this masochistic interest in writing &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt; compatible specs for the Ruby core library. One of the challenges there is the large number of aliased methods that Ruby has. Using RSpec&amp;#8217;s shared behaviors as an example, I&amp;#8217;ve created a flavor of shared behaviors in our &lt;code&gt;mini_rspec&lt;/code&gt; implementation. As the code below shows, this makes it straightforward to spec all these aliases.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash_store&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shared&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hash#store&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hash#&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;associates the key with the value and return the value&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;duplicates and freezes string keys&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frozen?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;duplicates string keys using dup semantics&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# dup doesn&amp;#39;t copy singleton methods&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;26&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;oof&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;  
&lt;span class=&quot;lineno&quot;&gt;28&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;29&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;raises TypeError if called on a frozen instance&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;should_raise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;35&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hash#[]=&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;it_behaves_like&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash_store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:[]=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The very cool thing about this is how useful Ruby&amp;#8217;s &lt;code&gt;send&lt;/code&gt; method is. And in Rubinius, it gets even cooler, as you&amp;#8217;ll see in &lt;a href=&quot;http://blog.brightredglow.com/2007/9/20/send-my-love-to-ruby-ii&quot;&gt;part II&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Rubinius sprint retrospective</title>
    <id>http://brixen.io/2007/9/17/rubinius-sprint-retrospective</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/9/17/rubinius-sprint-retrospective" />
    <published>2007-09-17T00:00:00-07:00</published>
    <updated>2007-09-17T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Last week, &lt;a href=&quot;http://blog.fallingsnow.net/&quot;&gt;Evan Phoenix&lt;/a&gt;, &lt;a href=&quot;http://metaclass.org/&quot;&gt;Wilson Bilkovich&lt;/a&gt; and I met up in Denver (ok, &lt;em&gt;near&lt;/em&gt; Denver) for some serious &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; coding, aka a sprint. &lt;a href=&quot;http://headius.blogspot.com/&quot;&gt;Charles Nutter&lt;/a&gt; (of &lt;a href=&quot;http://jruby.codehaus.org/&quot;&gt;JRuby&lt;/a&gt; fame) flew in just to hack with us for 15 hours straight and then flew back home. Very cool. When do you get collaboration like that from someone on a project that could be seen as a competitor? That&amp;#8217;s some serious goodwill, folks, and much appreciated. Charles had his laptop out on the taxi ride from the airport digging into some issues we have with including modules. If you hang out in #rubinius, you know there&amp;#8217;s a lot of collaboration occurring on different fronts.&lt;/p&gt;
&lt;p&gt;This was only the second time I&amp;#8217;ve had the pleasure to hang out with these folks in person. The sprint was intended to enable us to get some face-to-face time and work out some foundational issues, hopefully speeding other development and contribution as we head toward &lt;a href=&quot;http://www.rubycentral.org&quot;&gt;RubyConf07&lt;/a&gt;. Here&amp;#8217;s a few things we accomplished (in no particular order):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Evan hooked up Syck (the &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; parser) using our very cool &lt;em&gt;subtend&lt;/em&gt; (Ruby C &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; compatibility) component.&lt;/li&gt;
	&lt;li&gt;Wilson hammered out a bunch of StringIO specs in a couple hours.&lt;/li&gt;
	&lt;li&gt;Evan promptly began writing a Ruby StringIO that passed the specs.&lt;/li&gt;
	&lt;li&gt;Charles whipped out a bunch of &lt;code&gt;def&lt;/code&gt; and &lt;code&gt;case&lt;/code&gt; specs, the latter being a serious beast to compile.&lt;/li&gt;
	&lt;li&gt;Wilson added these wicked colorized backtraces that enable you to quickly pick out the ultimate failure line and some significant points in the backtrace.&lt;/li&gt;
	&lt;li&gt;Wilson implemented the rest of the missing &lt;code&gt;case&lt;/code&gt; support in the compiler.&lt;/li&gt;
	&lt;li&gt;Charles added some basic ObjectSpace support.&lt;/li&gt;
	&lt;li&gt;I checked in a complete reorganization and a lot of fixes to our Ruby core library specs. We have around 2,800 specs, of which we&amp;#8217;re passing over two thirds. We still have nearly 50% of the core library specs to complete.&lt;/li&gt;
	&lt;li&gt;Evan fixed our Thread support and added some preemption.&lt;/li&gt;
	&lt;li&gt;I added (with much help from Evan and some serious gdb sessions looking at x86 machine code) some coolness to our foreign function interface (&lt;span class=&quot;caps&quot;&gt;FFI&lt;/span&gt;) to support reading and writing to C integers and doubles from Ruby. (The doubles support still needs a magic touch or two from Evan.) With that I was able to finish off our Math methods support and the rest of the Math specs.&lt;/li&gt;
	&lt;li&gt;Wilson hammered out a ton of the machinery necessary to support compiling &lt;code&gt;eval&lt;/code&gt;. If you don&amp;#8217;t realize how awesome (and painful) this is, don&amp;#8217;t blame me.&lt;/li&gt;
	&lt;li&gt;I started on an implementation of &lt;code&gt;File.fnmatch&lt;/code&gt; in preparation for &lt;code&gt;Dir.glob&lt;/code&gt; (or &lt;a href=&quot;http://blog.brightredglow.com/2007/9/17/dear-glob&quot;&gt;dear glob&lt;/a&gt; is it is not-so-affectionately known to me) and cleaned up our fnmatch specs a bunch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&amp;#8217;s more where that came from. For all the nitty gritty details, browse the &lt;a href=&quot;http://git.rubini.us/?p=code;a=summary&quot;&gt;git repository&lt;/a&gt;. There&amp;#8217;s some cool stuff just over the horizon that we didn&amp;#8217;t get to. Evan explained in more detail the architecture of our sampling profiler and our debugger support. Let&amp;#8217;s just say you&amp;#8217;ll be able to profile a Rails app in production with no significant performance penalty. And remote debugging is on it&amp;#8217;s way. Seriously, let that sink in for a minute.&lt;/p&gt;
&lt;p&gt;Interestingly, we did not consume 50 liters of coffee each and we had some incredible Japanese food one evening, thanks to a recommendation from one of Wilon&amp;#8217;s contacts. Overall, I&amp;#8217;m quite impressed with our progress and highly impressed with the technical prowess of these guys. The point it, Rubinius is quite accessible. It&amp;#8217;s also some very cool and very real technology that&amp;#8217;s going to make writing, running, living, breathing, and enjoying Ruby &lt;em&gt;a lot&lt;/em&gt; better.&lt;/p&gt;
&lt;p&gt;And last but not least, a big thanks to &lt;a href=&quot;http://www.sun.com&quot;&gt;Sun&lt;/a&gt; for their sponsorship, and in particular &lt;a href=&quot;http://www.tbray.org/ongoing/&quot;&gt;Tim Bray&lt;/a&gt; for his advocacy. Rubinius is a small, ambitious project. But at heart, it&amp;#8217;s very true to the value of making Ruby fun.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Dear glob</title>
    <id>http://brixen.io/2007/9/17/dear-glob</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/9/17/dear-glob" />
    <published>2007-09-17T00:00:00-07:00</published>
    <updated>2007-09-17T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;At some point, you likely needed to grab some files and do something with them. You probably had a vague recollection about &lt;code&gt;Dir[]&lt;/code&gt; from reading the Pickaxe book. To refresh your memory, you crack it open and fire up irb. Ah, easy&amp;#8230;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
  irb(main):001:0&amp;gt; Dir['spec/**/*_spec.rb'].each do |file|
  irb(main):002:1* puts file
  irb(main):003:1&amp;gt; end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&amp;#8217;s no denying that Ruby makes this task dead simple. So simple, in fact, that you probably don&amp;#8217;t think twice about how that nifty &lt;code&gt;Dir[]&lt;/code&gt; method does its work. That is, unless you&amp;#8217;re trying to implement it.&lt;/p&gt;
&lt;p&gt;During the &lt;a href=&quot;http://rubini.us/forums/6/topics/59&quot;&gt;Rubinius sprint&lt;/a&gt;, I realized that having this in Rubinius would enable me to make our continuous integration spec runner much better. Now, I know that there&amp;#8217;s a &lt;code&gt;glob&lt;/code&gt; function in C that provides behavior similar to what you get in the shell using * and ? to match file names. There&amp;#8217;s also a function &lt;code&gt;fnmatch&lt;/code&gt; that wraps up some of that magic. No problem. We&amp;#8217;ve got this nifty foreign-function interface (&lt;span class=&quot;caps&quot;&gt;FFI&lt;/span&gt;) that &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt; has graciously provided. Evan recommended I take that route first. Yep, took all of 10 minutes to hook everything up.&lt;/p&gt;
&lt;p&gt;Of course, it wouldn&amp;#8217;t be &lt;em&gt;that&lt;/em&gt; interesting were this the end of the story. It&amp;#8217;s not. Our fnmatch specs were mostly passing, but when I looked into the failing ones, I discovered something that I&amp;#8217;d probably tried to shield my psyche from. Ruby implements its own fnmatch and glob functions. And when I say &amp;#8216;implements&amp;#8217;, it doesn&amp;#8217;t really give you any idea of the pain and suffering involved. Do take a peek:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The &lt;a href=&quot;http://svn.ruby-lang.org/repos/ruby/tags/v1_8_6/dir.c&quot;&gt;Ruby source&lt;/a&gt; (stable 1.8.6)&lt;/li&gt;
	&lt;li&gt;The &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/src/org/jruby/util/Dir.java&quot;&gt;JRuby source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It doesn&amp;#8217;t take but a minute to see that &lt;a href=&quot;http://ola-bini.blogspot.com/&quot;&gt;Ola Bini&amp;#8217;s&lt;/a&gt; java code is extraordinarily more readable than the &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; source. But both are daunting to say the least. So, I&amp;#8217;ve decided to take a different route.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fnmatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StringValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StringValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;escape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FNM_NOESCAPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;pathname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FNM_PATHNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;nocase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FNM_CASEFOLD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;period&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FNM_DOTMATCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;subs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /\*{1,2}/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;(.*)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /\?/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;(.)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /\{/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\{&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /\}/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\}&amp;#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;     
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;?.&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;?.&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;period&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\.&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/(?&amp;lt;pg&amp;gt;\[(?:\\[\[\]]|[^\[\]]|\g&amp;lt;pg&amp;gt;)*\])/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;?[&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\\([*?])/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\[!/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;[^&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;subs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;escape&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt;           &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\\(.)/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt;           &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/(\\)([^*?\[\]])/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;\1\1\2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25&lt;/span&gt;     
&lt;span class=&quot;lineno&quot;&gt;26&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Regexp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;^&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nocase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Regexp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;IGNORECASE&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pathname&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;captures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32&lt;/span&gt;         
&lt;span class=&quot;lineno&quot;&gt;33&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StringValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36&lt;/span&gt;         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;40&lt;/span&gt;       &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This code is only passing 80% of our existing specs for &lt;code&gt;File.fnmatch?&lt;/code&gt;, so the jury is still out. And I&amp;#8217;m sure someone can make this much better. The lesson for me is that 1) Ruby&amp;#8217;s implementation is typically &lt;em&gt;not&lt;/em&gt; accessible (I already knew that), and 2) writing Ruby code is a good way to handle tough problems.&lt;/p&gt;
&lt;p&gt;But then, you already knew that. ;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; I&amp;#8217;ve changed the code here to reflect our current version. It&amp;#8217;s now passing 100% of the existing specs.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>RailsConf 2007: The case of the missing BDD</title>
    <id>http://brixen.io/2007/5/19/railsconf-2007-the-case-of-the-missing-bdd</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/5/19/railsconf-2007-the-case-of-the-missing-bdd" />
    <published>2007-05-19T00:00:00-07:00</published>
    <updated>2007-05-19T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Looks like the &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt; folks dropped 1.0. Awesome! Congratulations!&lt;/p&gt;
&lt;p&gt;Hmm, where&amp;#8217;s the applause? This is the good shit. People should be knowing about this. So, as I sit here at &lt;a href=&quot;http://conferences.oreillynet.com/rails/&quot;&gt;RailsConf 2007&lt;/a&gt; looking over the schedule, I&amp;#8217;m not seeing any talks scheduled for &lt;a href=&quot;http://behavior-driven.org&quot;&gt;&lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt;&lt;/a&gt; or &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt;. That&amp;#8217;s regrettable. So, my goal will be to embarrass, cajole, entice, encourage (pick your emotional poison) you into trying RSpec. Not sure if it&amp;#8217;s right for you? Try it. Not sure if it will work well? Try it. Don&amp;#8217;t get it yet? Try it, already!&lt;/p&gt;
&lt;p&gt;And while you&amp;#8217;re trying it, think about this: How can descriptions of the behavior of a system form the common language that spans the spectrum of development from clients to developers. Do you think your clients care about how many &lt;code&gt;def test_should_be_super_duper&lt;/code&gt; methods are in your tests? Why would they?&lt;/p&gt;
&lt;p&gt;Would your customer care about something like this?&lt;/p&gt;
&lt;pre&gt;
The Home page
- has an entry field for username labelled 'User name'
- has an entry field for password labelled 'Password'
- has a submit button labeled 'Log in'
- has a link to retrieve a lost password FAILED

1) The Home page has a link to retrieve a lost password FAILED
   &amp;lt;insert client comprehensible failure message here&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Do you think this could form the basis of a dialogue with your clients? Would it be easier to trouble shoot this over a client saying, &amp;#8220;The lost password link doesn&amp;#8217;t work.&amp;#8221; Do you see how this could make everyone&amp;#8217;s life easier?&lt;/p&gt;
&lt;p&gt;Is this all there is to &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; and RSpec? No, not by a long shot. So&amp;#8230; yeah, you guessed it. Try it.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Oh, _why!</title>
    <id>http://brixen.io/2007/5/19/oh-_why</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/5/19/oh-_why" />
    <published>2007-05-19T00:00:00-07:00</published>
    <updated>2007-05-19T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;This post has no nutritional value. Feel free to put it over there by the jelly-filled pastry, bearclaw, and glazed pop tart, go back to your granola. You health nuts, you.&lt;/p&gt;
&lt;p&gt;Now, to the jelly filling. Seems that _why dropped by #rubinius, not once, but twice yesterday. I missed it, but hopefully he&amp;#8217;ll be back. For your viewing pleasure (no names have been changed to protect the innocents).&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;
19:06   _why &amp;gt;&amp;gt; whoa
19:06   _why &amp;gt;&amp;gt; well fellows
19:06   _why &amp;gt;&amp;gt; i am blown away!
19:07   _why &amp;gt;&amp;gt; looks like things are really comin along
...
19:30   _why &amp;gt;&amp;gt; oh backflip
19:30   _why &amp;gt;&amp;gt; interpolation works, splat works, IO works
19:30   Vagabond &amp;gt;&amp;gt; spat is pretty new
19:30   Vagabond &amp;gt;&amp;gt; I think it's not completely tested
19:30   shadowfiend &amp;gt;&amp;gt; Yeah, like a couple of hours old :-)
19:31   Vagabond &amp;gt;&amp;gt; it's remarkable how much is actually implemented though
19:31   _why &amp;gt;&amp;gt; yeah it's got that new splat smell

&lt;/pre&gt;</content>
  </entry>
  
  <entry>
    <title>The Dev'ilz in ur projects, trackin' ur changz</title>
    <id>http://brixen.io/2007/5/8/the-dev-ilz-in-ur-projects-trackin-ur-changz</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/5/8/the-dev-ilz-in-ur-projects-trackin-ur-changz" />
    <published>2007-05-08T00:00:00-07:00</published>
    <updated>2007-05-08T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;http://devil.brightredglow.com&quot;&gt;Dev&amp;#8217;il&lt;/a&gt; is out; get it while it&amp;#8217;s hot. What&amp;#8217;s that? you&amp;#8217;re wondering.&lt;/p&gt;
&lt;p&gt;This is the story behind it. The &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; project (where &lt;strong&gt;The Best Ruby VM of All Time&lt;/strong&gt; &amp;trade; is being built) had tried a couple project collaboration tools before &lt;a href=&quot;http://blog.fallingsnow.net&quot;&gt;Evan&lt;/a&gt; gave me the ok to try something different. My goal was a project collaboration tool that collected the relevant information in one place, making it easy to access and modify. Communication is key, so I decided to build on the excellent &lt;a href=&quot;http://beast.caboo.se&quot;&gt;Beast&lt;/a&gt; forum.&lt;/p&gt;
&lt;p&gt;The big question is: What is &lt;em&gt;relevant&lt;/em&gt; information? I have some opinions about that. We have a liberal commit bit policy, which encourages a lot of participation. To balance that, we need to always stay on top of what is being committed. In my experience, that means &lt;span class=&quot;caps&quot;&gt;RSS&lt;/span&gt; and graphical browsing of Subversion changes. We need tickets to track bugs. However, our tickets are super light. Basically, a ticket has a title, body, and status. A user can &lt;em&gt;take&lt;/em&gt; a ticket to indicate that she is working on it. There are no comments, and no priorities. Tickets are versioned, so a user cannot destroy pertinent information. The ticket body should always be the definitive statement of the problem. No browsing through comments and attachments trying to figure out what is relevant. I&amp;#8217;ll be writing more about the design decisions in the &lt;a href=&quot;http://devil.brightredglow.com/pages&quot;&gt;Dev&amp;#8217;il docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I do owe a big debt to &lt;a href=&quot;http://trac.edgewall.org/&quot;&gt;Trac&lt;/a&gt; , &lt;a href=&quot;http://collaboa.org&quot;&gt;Collaboa&lt;/a&gt;, &lt;a href=&quot;http://software.pmade.com/devalot&quot;&gt;Devalot&lt;/a&gt; , &lt;a href=&quot;http://retrospectiva.org&quot;&gt;Retrospectiva&lt;/a&gt;, mostly for showing me (especially Trac) what I did not want to do, which can be a great source of inspiration. The name itself came from a combination of pure frustration working on Devalot and Evan&amp;#8217;s quote about rubinius having &amp;#8220;a little evil built in&amp;#8221;. It was mostly a response to the &amp;#8220;alot&amp;#8221; in Devalot. I wanted something much lighter and easier to understand and use. Anyway, if you&amp;#8217;re offended by the name, it&amp;#8217;s very easy to change: drop a file named &lt;code&gt;project.rb&lt;/code&gt; in your lib directory that contains your project name.&lt;/p&gt;
&lt;p&gt;The project is still under development. I&amp;#8217;ve released the source because a few folks were clamoring for it. Drop by the &lt;a href=&quot;http://devil.brightredglow.com/forums&quot;&gt;Dev&amp;#8217;il forums&lt;/a&gt; for features in the works and to offer up some feedback.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Ctrl-C is deprecated</title>
    <id>http://brixen.io/2007/5/8/ctrl-c-is-deprecated</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/5/8/ctrl-c-is-deprecated" />
    <published>2007-05-08T00:00:00-07:00</published>
    <updated>2007-05-08T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Well, not exactly. But here&amp;#8217;s a nice anecdote that will give you pause then next time you sprint for the ^C escape hatch.&lt;/p&gt;
&lt;p&gt;Yesterday, while compiling Subversion 1.4.3 from source on Ubuntu 6.06, I had invoked the command &lt;code&gt;sudo checkinstall make install-swig-rb&lt;/code&gt; and, thinking it was going to overwrite my previous .deb package for subversion, hit ^C. Now that&amp;#8217;s something I&amp;#8217;ve done a million times, I&amp;#8217;m sure. It&amp;#8217;s the panic, &amp;#8220;Oh shit, I don&amp;#8217;t really want to do that&amp;#8221; button. When you realize in a split second that there may be dire consequences from that ill-thought command, it&amp;#8217;s a natural reflex.&lt;/p&gt;
&lt;p&gt;But on that fine day, ^C left me with a root directory that had 700 permissions. The consequence was that nothing except a root shell could spawn. I couldn&amp;#8217;t even &lt;code&gt;su &amp;lt;user&amp;gt;&lt;/code&gt; as root. Yeah, that&amp;#8217;s right. Insane. And this was on a &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;. Lucky for me, &lt;a href=&quot;http://quantact.com&quot;&gt;Quantact&lt;/a&gt; has their Xen &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; setup configured so you can actually access a console remotely without needing to go through your VPS&amp;#8217;s networking. Tim at Quantact took a look and suggested that the permissions could be causing the issue. He was right and boy, was I happy that&amp;#8217;s all it was.&lt;/p&gt;
&lt;p&gt;Most likely, something in &lt;code&gt;checkinstall&lt;/code&gt; misbehaved, but needless to say, I didn&amp;#8217;t try to reproduce the problem. Now, whenever I head for ^C there will undoubtedly be a microsecond pause to evaluate the relative merits. Hopefully, that won&amp;#8217;t result in a &lt;a href=&quot;http://en.wikipedia.org/wiki/Buridan&amp;#39;s_ass&quot;&gt;Buridan&amp;#8217;s Ass&lt;/a&gt; dilemma.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Needmore Designs</title>
    <id>http://brixen.io/2007/4/12/needmore-designs</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/4/12/needmore-designs" />
    <published>2007-04-12T00:00:00-07:00</published>
    <updated>2007-04-12T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;That pretty much sums up my feelings about the majority of the interactive gadgets I encounter, soft or hardware. So, I&amp;#8217;m delighted to have the good fortune of joining the talented folks at &lt;a href=&quot;http://needmoredesigns.com&quot;&gt;Needmore Designs&lt;/a&gt;. It&amp;#8217;ll be a challenge to keep the code as beautiful as &lt;a href=&quot;http://needmoredesigns.com/projects/&quot;&gt;these designs&lt;/a&gt;, but using &lt;a href=&quot;http://ruby-lang.org&quot;&gt;Ruby&lt;/a&gt; makes that a delicious challenge indeed.&lt;/p&gt;
&lt;p&gt;One particularly generous perk for a company this size is that I&amp;#8217;ll be able to spend around 20% of my time working on, I like to call them, &amp;#8220;personal development&amp;#8221; projects. Of course, I plan to contribute that to bettering the Ruby community. In particular, I&amp;#8217;ll be spending a good portion on the &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; project. This alternative Ruby implementation aims to create an accessible, extensible, powerful, and &lt;em&gt;fast&lt;/em&gt; virtual machine. We&amp;#8217;re implementing as much as possible in Ruby and we have a lot of very cool things either implemented or in the works.&lt;/p&gt;
&lt;p&gt;Not only will this project contribute to Ruby being more suitable for a wider variety of computing tasks, but using rubinius will actually be great for the environment, too! Far fetched? Nope. Our continual thirst for more computing power translates to increasing demand for energy. Any type of energy pretty much means some contribution of carbon to the already overloaded atmosphere. So, when rubinius runs your favorite Ruby applications and web 2.0 sites more efficiently, that reduces the required energy and that&amp;#8217;s better for the environment. Ok, I&amp;#8217;ve never made that pitch before but it&amp;#8217;s a great reason join up and help out.&lt;/p&gt;
&lt;p&gt;So, your moment of zen: not only has &lt;a href=&quot;http://needmoredesigns.com&quot;&gt;Needmore&lt;/a&gt; given me this great opportunity to work with talented design professionals, but they&amp;#8217;re also contributing to a better environment. And if you treasure the abundance of green that we are privileged to have all around &lt;a href=&quot;http://maps.google.com/maps?f=q&amp;amp;hl=en&amp;amp;q=Portland,+OR&amp;amp;layer=&amp;amp;ie=UTF8&amp;amp;z=12&amp;amp;om=1&quot;&gt;Portland&lt;/a&gt;, you know that&amp;#8217;s a very cool thing. Around the circle goes.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Behavior-Driven Collaboration</title>
    <id>http://brixen.io/2007/3/28/behavior-driven-collaboration</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/3/28/behavior-driven-collaboration" />
    <published>2007-03-28T00:00:00-07:00</published>
    <updated>2007-03-28T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Eegads, how time flies. At the March 6th meeting of &lt;a href=&quot;http://pdxruby.org&quot;&gt;pdx.rb&lt;/a&gt;, I gave a short talk introducing &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; (Behavior-driven development) with a couple examples from &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt;. Since &lt;a href=&quot;http://blog.davidchelimsky.net/&quot;&gt;David Chelimsky&lt;/a&gt; has already done a terrific job writing an introduction &lt;a href=&quot;http://rspec.rubyforge.org/tutorials/index.html&quot;&gt;tutorial&lt;/a&gt;, I decided to focus more on the big picture of &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt;. My take is that &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; is some rather sweet glue that can foster collaboration across the spectrum of folks involved in software development, from clients to designers to developers to users. So far, we&amp;#8217;ve got a lot of turf wars going on, and as in any war, there are casualties. In software there are crappy products, tortured users, unhappy developers, exasperated designers, cost overruns, and misunderstandings galore. &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; isn&amp;#8217;t some magic salve that can be slathered on a messy process like butter on a toasty English muffin and make it all better, but I do believe it has promise.&lt;/p&gt;
&lt;p&gt;So, here are the &lt;a href=&quot;http://blog.brightredglow.com/assets/2007/3/28/behavior-driven.pdf&quot;&gt;slides&lt;/a&gt; from my talk. (Right-click and Save As&amp;#8230; Sorry, &lt;span class=&quot;caps&quot;&gt;MIME&lt;/span&gt; types are not set right at the moment.) Unfortunately, in a tremendously idiotic move born of high stress, I deleted the original slides before I had uploaded them. Fortunately, I had some notes and a partial earlier draft, so I was (mostly I hope) able to reconstruct them. There is unfortunately no audio from the talk. As with most slides, these are marginally useful without it, but browse and feel free to ask questions.&lt;/p&gt;
&lt;p&gt;There is one part that seems highly promising to me and easily attainable now. As you know, RSpec allows you to spec the views separately from the controller. This is a fantastic tool that interaction designers could use to communicate with developers. The syntax that an interaction designer would need to learn is fairly simple (most interaction designers are not developers), and you shouldn&amp;#8217;t have much (if any) conditional code in your specs anyway (conditionals being one of the more difficult parts of programming to get right in my experience). The specs can accompany wireframes and provide another artifact of communication that bridges the different domains of interaction/interface design and development. Exciting stuff.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Rubinius Hits Primetime: Let the FUD Begin</title>
    <id>http://brixen.io/2007/2/14/rubinius-hits-primetime-let-the-fud-begin</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/14/rubinius-hits-primetime-let-the-fud-begin" />
    <published>2007-02-14T00:00:00-08:00</published>
    <updated>2007-02-14T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;For being a very young project (Evan&amp;#8217;s been working on it &lt;a href=&quot;http://blog.fallingsnow.net/rubinius&quot;&gt;about a year&lt;/a&gt;, but it&amp;#8217;s only been in the public view for a few months), Rubinius has quickly hit primetime with the first (that I know of) &lt;a href=&quot;http://jesusphreak.infogami.com/blog/rubinius_fights_on&quot;&gt;&lt;span class=&quot;caps&quot;&gt;FUD&lt;/span&gt;-ish review&lt;/a&gt; The basic premise is that pypy had money, minds, and at least one goal to produce a simpler VM than CPython, but as it nears 1.0 it&amp;#8217;s much more complex than CPython. And since Rubinius is at least lacking in official monetary backing, it&amp;#8217;s got a real tough row to hoe. Maybe; but I&amp;#8217;m unconvinced.&lt;/p&gt;
&lt;p&gt;The jury is still out on the mind-share Rubinius will ultimately attract. We&amp;#8217;re certainly not sneezing at anyone&amp;#8217;s contribution. And if you hang out in the channel, you might notice some rather interesting conversations between the JRuby folks and the Rubinius folks. You&amp;#8217;ll definitely hear conversations about &lt;span class=&quot;caps&quot;&gt;PIC&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;STM&lt;/span&gt;, concurrency models that make you go &amp;#8220;Ohh&amp;#8221; (thanks &lt;a href=&quot;http://moonbase.rydia.net/mental/blog/programming/concurrency-five-ways.html&quot;&gt;MenTaLguY&lt;/a&gt;), the possibilities of &lt;span class=&quot;caps&quot;&gt;LLVM&lt;/span&gt;, even JIT&amp;#8217;ing (though, to hear JP tell it, we&amp;#8217;re hopelessly unqualified for that). I&amp;#8217;d guess a who&amp;#8217;s-who on Rubinius would turn up some rather accomplished folks. Personally, It is encouraging that I didn&amp;#8217;t have to write the &lt;a href=&quot;http://www.amazon.com/gp/product/0321486811/104-8500968-6579924&quot;&gt;book on compilers&lt;/a&gt; to be able to hack on Rubinius. But really, do you have to know everything to jump into a project and start learning and applying it?&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s just say, I&amp;#8217;m sure glad Linus was not deterred by the fact that &lt;span class=&quot;caps&quot;&gt;IBM&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;SCO&lt;/span&gt;, AT&amp;amp;T, and Micro$oft had billions of dollars to spend on operating system development. Anyway, I&amp;#8217;ll bet the &amp;#8220;Yes, but does it scale?&amp;#8221; posts will be showing up shortly. C&amp;#8217;mon JP, live a little.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>TSort in sirb</title>
    <id>http://brixen.io/2007/2/13/tsort-in-sirb</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/13/tsort-in-sirb" />
    <published>2007-02-13T00:00:00-08:00</published>
    <updated>2007-02-13T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;They say good things come in threes, or perhaps I&amp;#8217;ll bore you with another post about Rubinius, but what the heck. So, the other day I imported Ruby&amp;#8217;s standard library from the &lt;span class=&quot;caps&quot;&gt;SVN&lt;/span&gt; repository into the Rubinius repository. I&amp;#8217;ve been itching to go through and see what successfully loads. Ah, now that we have &lt;code&gt;sirb&lt;/code&gt;, the perfect opportunity presents itself.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto&quot;&gt;&lt;code&gt;
$ ./shotgun/rubinius apps/irb/sirb.rb
sirb(eval):000&amp;gt; require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
Unable to find 'tsort' to load
                 main.raise at bootstrap/04kernel.rb:26
               main.require at core/compile.rb:91
       main.__eval_script__ at (eval):1
    CompiledMethod#activate at bootstrap/compiled_method.rb:52
            main.__script__ at apps/irb/sirb.rb:79
                  main.load at core/compile.rb:56
            main.__script__ at core/__loader.rb:50
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmm. Oh, yes! I think we need to check load path. (I&amp;#8217;ve since added &lt;code&gt;stdlib&lt;/code&gt; to the default load path.)&lt;/p&gt;
&lt;pre style=&quot;overflow: auto&quot;&gt;&lt;code&gt;
sirb(eval):001&amp;gt; p $:
[&quot;.&quot;, &quot;runtime/compiler.rba&quot;, &quot;lib&quot;]
=&amp;gt; nil
sirb(eval):002&amp;gt; $:.push &quot;stdlib&quot;
=&amp;gt; [&quot;.&quot;, &quot;runtime/compiler.rba&quot;, &quot;lib&quot;, &quot;stdlib&quot;]
sirb(eval):003&amp;gt; require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh baby. Just ignore those couple complaints. It&amp;#8217;s that &lt;code&gt;=&amp;gt; true&lt;/code&gt; that we&amp;#8217;re looking for. Nice! Now, we&amp;#8217;ll just try the example in the &lt;code&gt;tsort.rb&lt;/code&gt; file.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto&quot;&gt;&lt;code&gt;
sirb(eval):004&amp;gt; class Hash
sirb(eval):005&amp;gt;   include TSort
sirb(eval):006&amp;gt;   alias :tsort_each_node :each_key
sirb(eval):007&amp;gt;   def tsort_each_child(node, &amp;amp;block)
sirb(eval):008&amp;gt;     fetch(node).each(&amp;amp;block)
sirb(eval):009&amp;gt;   end
sirb(eval):010&amp;gt; end
=&amp;gt; nil
sirb(eval):011&amp;gt; {1=&amp;gt;[2, 3], 2=&amp;gt;[3], 3=&amp;gt;[], 4=&amp;gt;[]}.tsort
=&amp;gt; [3, 2, 1, 4]
sirb(eval):012&amp;gt; {1=&amp;gt;[2], 2=&amp;gt;[3, 4], 3=&amp;gt;[2], 4=&amp;gt;[]}.strongly_connected_components
=&amp;gt; [[4], [2, 3], [1]]
sirb(eval):013&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Excellent! Er, what&amp;#8217;s that? Did I hear you say, &amp;#8220;So, big deal, &lt;code&gt;tsort.rb&lt;/code&gt; isn&amp;#8217;t that tough&amp;#8221;? Well, ok, it isn&amp;#8217;t. (I didn&amp;#8217;t even know about &lt;code&gt;TSort&lt;/code&gt; before browsing through the source.) But, we can do other stuff, too.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto&quot;&gt;&lt;code&gt;
sirb(eval):008&amp;gt; require 'csv'
=&amp;gt; true
sirb(eval):009&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yep, that&amp;#8217;s right, &lt;code&gt;csv.rb&lt;/code&gt; compiles! But, I&amp;#8217;ll spare you the pain that ensued trying to use it. Baby steps. Ok, enough fun. C&amp;#8217;mon kids, there&amp;#8217;s a bunch of the core library still to implement!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Sirb: The Rubinius Loupe</title>
    <id>http://brixen.io/2007/2/11/sirb-the-rubinius-loupe</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/11/sirb-the-rubinius-loupe" />
    <published>2007-02-11T00:00:00-08:00</published>
    <updated>2007-02-11T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;If &lt;a href=&quot;http://blog.brightredglow.com/2007/2/11/irb-on-rubinius&quot;&gt;my previous post&lt;/a&gt; about &lt;code&gt;sirb&lt;/code&gt; got you drooling a bit, read on. I&amp;#8217;ve added some simple command line arguments to &lt;code&gt;sirb&lt;/code&gt; that enable you to request that s-expressions, assembly, or bytecodes (or all of them) are printed each time through the &lt;span class=&quot;caps&quot;&gt;RCEPL&lt;/span&gt; loop. You can get a hint at all the goodness by passing the &lt;code&gt;-h&lt;/code&gt; switch.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;&lt;code&gt;
$ ./shotgun/rubinius apps/irb/sirb.rb -h -p -x -s -b
  Usage: sirb [options]
    sirb is a RCEPL (read, compile, execute, print, loop) program for rubinius

    Options: 
            -p   Print the parsed s-expression
            -x   Print the normalized s-expression.
            -s   Print assembly instructions.
            -b   Print bytecode encoding.

sirb(eval):0&amp;gt; puts &quot;Hello, Rubinius. You rock my world!&quot; 

S-exp:
[:newline, 1, &quot;(eval)&quot;, [:fcall, :puts, [:array, [:str, &quot;Hello, Rubinius. You rock my world!&quot;, 0]]]]

Normalized S-exp:
[:newline, 1, &quot;(eval)&quot;, [:call, [:self], :puts, [:array, [:str, &quot;Hello, Rubinius. You rock my world!&quot;, 0]]]]

Asm:
#line 1
push_literal 0
string_dup
push self
send puts 1
ret


Bytecodes:
&quot;\v\000\000\000\000:\f)\000\000\000\001\000\000\000\001'\000\000\000&quot;
Hello, Rubinius. You rock my world!
=&amp;gt; nil
sirb(eval):1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As I mentioned, &lt;code&gt;sirb&lt;/code&gt; is rudimentary at the moment. But it shows you how much can be done with &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; right now. Swell! And, a big thanks to &lt;a href=&quot;http://mattelder.org/&quot;&gt;&lt;strong&gt;mae&lt;/strong&gt;&lt;/a&gt; for fixing up how the output of the execution prints (no more &lt;code&gt;[&quot;foo&quot;]&lt;/code&gt;).&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Irb on Rubinius</title>
    <id>http://brixen.io/2007/2/11/irb-on-rubinius</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/11/irb-on-rubinius" />
    <published>2007-02-11T00:00:00-08:00</published>
    <updated>2007-02-11T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;There are cat people and dog people, but when I say &amp;#8220;Man&amp;#8217;s best friend&amp;#8221;, I don&amp;#8217;t mean either. I&amp;#8217;m talking about that program that feels like a home away from home: &lt;code&gt;irb&lt;/code&gt;. So, I&amp;#8217;ve been chomping at the bit to get something resembling &lt;code&gt;irb&lt;/code&gt; running with &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Today, a few of us pdx.rb folks got together for some Rubinius hacking. Of course, &lt;code&gt;irb&lt;/code&gt; was one of the things I proposed that we work on. We had a go at it, but in the end we didn&amp;#8217;t get too far. &lt;code&gt;irb&lt;/code&gt; is no trivial application. But, I think a good part of it was my fault. I&amp;#8217;ve been working on these specs for so long, where at the moment we&amp;#8217;re forced to send everything to &lt;code&gt;rubinius&lt;/code&gt; in a subprocess, that I failed to grasp that we would have a persistent machine. Anyway, let&amp;#8217;s cut this short: Folks, we have a rudimentary &lt;code&gt;sirb&lt;/code&gt;!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
sirb(eval):0&amp;gt; class Hello
sirb(eval):1&amp;gt; def greet
sirb(eval):2&amp;gt; puts &quot;Hello, irb!&quot;
sirb(eval):3&amp;gt; end
sirb(eval):4&amp;gt; end
=&amp;gt; nil
sirb(eval):5&amp;gt; Hello.new.greet
=&amp;gt; Hello, irb!
[&quot;Hello, irb!&quot;]
sirb(eval):6&amp;gt; @s = &quot;Hello, earthling&quot;
=&amp;gt; &quot;Hello, earthling&quot;
sirb(eval):7&amp;gt; p @s
=&amp;gt; &quot;Hello, earthling&quot;
[&quot;Hello, earthling&quot;]
sirb(eval):8&amp;gt; Hello
=&amp;gt; Hello
sirb(eval):9&amp;gt; Hello.class
=&amp;gt; Class
sirb(eval):10&amp;gt; Hello.new
=&amp;gt; #&amp;lt;Hello:0x6696cc&amp;gt;
sirb(eval):11&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the words of Napolean Dynamite: &lt;strong&gt;Sweet.&lt;/strong&gt; Of course, it &lt;em&gt;is&lt;/em&gt; pretty rough right now. You&amp;#8217;ll notice the use of an instance variable, @a. That&amp;#8217;s because I couldn&amp;#8217;t figure out how to get local variables to work. Basically, everything is evaluating with the default receiver being an instance of Object.&lt;/p&gt;
&lt;p&gt;Well, warts and all, I think it&amp;#8217;s a beautiful thing.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Waiter, there's a Tuple in my Array</title>
    <id>http://brixen.io/2007/2/9/waiter-there-s-a-tuple-in-my-array</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/9/waiter-there-s-a-tuple-in-my-array" />
    <published>2007-02-09T00:00:00-08:00</published>
    <updated>2007-02-09T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Implementing Ruby in Ruby raises some challenges. In the beginning, Ruby was implemented in C. Well, at least the interpreter and core libraries. In C, you have the standard library that provides things like the math functions, functions for manipulating arrays of chars, which can be considered strings of text, etc. So, what happens when you want to build Ruby with Ruby? Well, you use Ruby, of course. And since Ruby is a class-based language, you probably will use a class. Ladies and Gentlemen, meet Tuple.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt;, the class Tuple is present for all to see. And it&amp;#8217;s put to good use, underlying the implementation of Array for instance. You can use it, too:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
sirb:001&amp;gt; t = Tuple.new(3) =&amp;gt; #&amp;lt;Tuple: nil, nil, nil&amp;gt;
sirb:002&amp;gt; t.put(1, &quot;foo&quot;)  =&amp;gt; #&amp;lt;Tuple: nil, &quot;foo&quot;, nil&amp;gt;
sirb:003&amp;gt; t.shift          =&amp;gt; #&amp;lt;Tuple: nil, &quot;foo&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here&amp;#8217;s another example. Have you noticed the &lt;code&gt;chr&lt;/code&gt; method available on instances of &lt;code&gt;Integer&lt;/code&gt;. Well, while implementing some &lt;code&gt;String&lt;/code&gt; methods, I decided it would be nice to say, &lt;code&gt;some_str[i].isspace&lt;/code&gt;. If you&amp;#8217;ve used C, you know that there is this thing &lt;code&gt;ctype&lt;/code&gt; that has macros or functions like &lt;code&gt;isspace&lt;/code&gt;. Stumbling around a bit, I finally decided to add a module &lt;code&gt;CType&lt;/code&gt; and mix that in to &lt;code&gt;Integer&lt;/code&gt;. Works pretty well.&lt;/p&gt;
&lt;p&gt;So, there&amp;#8217;s Tuple in all its glory sitting right in the middle of your Array. Is that a problem? I don&amp;#8217;t think so. This is &lt;em&gt;Ruby&lt;/em&gt;, folks. Duck typing, open classes, mixins, methods appearing and disappearing any old time of the day are &lt;em&gt;the norm&lt;/em&gt;. To clarify, the &lt;em&gt;behavior&lt;/em&gt; of the core classes, like Array, which have a different &lt;em&gt;implementation&lt;/em&gt; in Rubinius from that of the C one used in &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;, will not change. In other words, if you use Array methods, they&amp;#8217;ll behave like Array methods.&lt;/p&gt;
&lt;p&gt;I say, if your code depends on a class only having certain elements when you invoke &lt;code&gt;Foo.ancestors&lt;/code&gt;, for Pete&amp;#8217;s sake, refactor. And if you happen to have a ByteArray or Tuple in your application, refactor that, too. We&amp;#8217;re the VM, we get certain privileges. Now, suppose you wrote your application to use all the deliciousness of Rubinius, thereby demonstrating you are a wise and thoughtful old soul. (Yes, that&amp;#8217;s right, CompiledMethod, Method, MethodContext, BlockContext, BlockEnvironment, and more are &lt;em&gt;classes&lt;/em&gt;. Yum. And that is just the tip of the iceberg, I assure you.) But, you heavily built in dependencies on, say, Tuple, and now you&amp;#8217;re complaining it doesn&amp;#8217;t run on &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt;&amp;#8230; Well, here&amp;#8217;s your warning. In other words, don&amp;#8217;t be that silly.&lt;/p&gt;
&lt;p&gt;However, if this raises concerns for you, here&amp;#8217;s a suggestion: We&amp;#8217;re working feverishly on &lt;a href=&quot;http://rspec.rubyforge.org&quot;&gt;RSpec&lt;/a&gt; specs for all of the core and standard Ruby libraries. We also have a directory for incompatibilities in the Rubinius implementation, which is predictably found in &lt;code&gt;spec/core/incompatible&lt;/code&gt;. Feel free to join us in writing these specs. That way, you can run them against your favorite Ruby implementation and know what works. Perhaps, you can even integrate this knowledge into your own project&amp;#8217;s specs. You &lt;em&gt;are&lt;/em&gt; writing specs for your projects, aren&amp;#8217;t you?&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Happy New Year</title>
    <id>http://brixen.io/2007/2/8/happy-new-year</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2007/2/8/happy-new-year" />
    <published>2007-02-08T00:00:00-08:00</published>
    <updated>2007-02-08T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Sometime between Jan 1 and Chinese New Year it finally dawns on me that we&amp;#8217;ve begun a, well, new year. I start writing the correct dates on checks, the bank honors them, the rent gets paid. Things go much more smoothly.&lt;/p&gt;
&lt;p&gt;So, while trying to keep up with the homework from my &lt;a href=&quot;http://www.mth.pdx.edu/people/faculty_page.asp?id=82&quot;&gt;brilliant professor&lt;/a&gt; of &lt;a href=&quot;http://en.wikipedia.org/wiki/Game_theory&quot;&gt;game theory&lt;/a&gt;, I thought I&amp;#8217;d write a few predictions for 2007. Sure, some of these you could call resolutions, but since it&amp;#8217;s up to me to do them, lumping them into the predictions category might up my percentage correct score.&lt;/p&gt;
&lt;p&gt;This blog will finally get a real theme, shorter posts, an articles section, recent and popular links. Also, I&amp;#8217;m going to spruce up the &lt;span class=&quot;caps&quot;&gt;RSS&lt;/span&gt; served to be more useful in a reader. Finally, to break the asymmetry of time, I&amp;#8217;ll be putting titles of upcoming posts in before the post appears. When it does, the title will become a link.&lt;/p&gt;
&lt;p&gt;2007 will be the year of the alternate Ruby implementations. Several will be competing with &lt;span class=&quot;caps&quot;&gt;MRI&lt;/span&gt; (Matz&amp;#8217;s Ruby Interpreter) for your love and admiration. Among these are &lt;a href=&quot;http://atdot.net/yarv/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;YARV&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://jruby.sourceforge.net/&quot;&gt;JRuby&lt;/a&gt; and &lt;a href=&quot;http://rubini.us&quot;&gt;Rubinius&lt;/a&gt; . One of those will have a tremendous impact on enterprise coding and another will have a tremendous impact on CS in general. We&amp;#8217;ll see how that pans out. I&amp;#8217;ll be posting more about Rubinius soon. In the meantime, don&amp;#8217;t miss the wonderful, appreciated, and tireless work of Pat on the &lt;a href=&quot;http://on-ruby.blogspot.com&quot;&gt;On-Ruby Blog&lt;/a&gt; to evangelize Rubinius and other cool projects.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be learning at least one new application this year: &lt;a href=&quot;http://www.omnigroup.com/applications/omnigraffle/&quot;&gt;Omnigraffle&lt;/a&gt;. This comes highly recommended by our &lt;a href=&quot;http://www.planetargon.com/about.html&quot;&gt;Creative Director&lt;/a&gt;, &lt;a href=&quot;http://www.allisbe.com/&quot;&gt;Allison&lt;/a&gt;. Truth is, design and graphics is way more interesting to me than plain ol&amp;#8217; code, but writing code usually wins out in a duel, so I&amp;#8217;m hoping to even things out a bit.&lt;/p&gt;
&lt;p&gt;Finally, I hope to collaborate on writing a book; I&amp;#8217;ll let you guess the topic. And if things go well, I&amp;#8217;ll be co-announcing a currently top secret project. Ahh, I see the eyebrows rising. Also on my list of things to write about are some more thoughts on &lt;a href=&quot;http://dialogue-driven.org&quot;&gt;d3&lt;/a&gt; and our experiences with it at &lt;a href=&quot;http://www.planetargon.com&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PLANET&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;ARGON&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the near future, check out &lt;em&gt;What&amp;#8217;s the Big Idea&lt;/em&gt; and &lt;em&gt;Another Liberating Constraint: Contracts&lt;/em&gt;.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Tuesday: partly sunny, chances of showers</title>
    <id>http://brixen.io/2006/11/15/tuesday-partly-sunny-chances-of-showers</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/15/tuesday-partly-sunny-chances-of-showers" />
    <published>2006-11-15T00:00:00-08:00</published>
    <updated>2006-11-15T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Maybe it&amp;#8217;s all the rain during this season. I sure look forward to those dry, maybe sunny days when I notice them on my dashboard weather widget. Alas, I&amp;#8217;m often disappointed. A nice, bright sun a few days away mysteriously turns into a cloud or rain drops. It&amp;#8217;s a big disappointment. Often I call up the weather station and complain. Why can&amp;#8217;t they be more accurate? Why don&amp;#8217;t they develop better processes? Sometimes it gets nasty and I threaten to sue them. I mean, if I&amp;#8217;ve planned my picnic because Saturday is forecasted to be sunny, shouldn&amp;#8217;t somebody have to pay to clean my soggy picnic blanket?&lt;/p&gt;
&lt;p&gt;Actually, that doesn&amp;#8217;t happen. In fact, we&amp;#8217;d consider somebody a tad looney if they asserted that somehow the weather forecast should be guaranteed. We know that science is always advancing but weather forecasting is imprecise because the complexity of the &amp;#8220;weather system&amp;#8221; ensures it is affected by processes described by chaos and complexity theory. There is an inherent limit on precision.&lt;/p&gt;
&lt;p&gt;The most common analogy for software development is some form of construction. In fact, we talk about system architecture, building components, software construction. Creating software is less like building and more like weather forecasting.&lt;/p&gt;
&lt;p&gt;Methods and processes for constructing buildings are quite well established. And all buildings share far more commonalities than differences. Most importantly, interacting with buildings involves human cognition in extremely limited ways. Software, on the other hand, involves a tremendous amount of human cognition and social effects. There is conceptualization, definition, communication, attitudes, opinions, assumptions, the entire spectrum of human complexity. Given this, we might be advised to study meteorology as much as architecture.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Good fences make good neighbors</title>
    <id>http://brixen.io/2006/11/15/good-fences-make-good-neighbors</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/15/good-fences-make-good-neighbors" />
    <published>2006-11-15T00:00:00-08:00</published>
    <updated>2006-11-15T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;We might as well accept it now: &lt;a href=&quot;http://en.wikipedia.org/wiki/An_Inconvenient_Truth&quot;&gt;global warming is real&lt;/a&gt;. We live in a finite world with finite resources. Given that, why would we want to expend time and effort building fences. They just sit there. Maybe they contribute to the aesthetic but they won&amp;#8217;t help the wheat grow any better in the field. Building them diverts productive capacity from planting, tending, harvesting. Be that as it may, long ago folks realized that good fences serve a purpose.&lt;/p&gt;
&lt;p&gt;Fences create boundaries and boundaries define areas. And that&amp;#8217;s the value: this is my area, that is yours. Positive relationships also depend on boundaries: this is my responsibility, that is yours. Contracts are like fences: they describe boundaries that define areas. We may be tempted to think that nice, intelligent, professional people can work out differences of understanding without the need for lawyers and contracts. But be not tempted. The jury may still be out on the question of whether there exist nice, intelligent, professional people. But the lawyers are here to stay.&lt;/p&gt;
&lt;p&gt;Good neighbors build and maintain fences together. They share the responsibility and share the benefits. Contracts are necessary; collaboration is necessary. Contracts &lt;em&gt;through&lt;/em&gt; collaboration. It&amp;#8217;s less of a prioritization of values and more a matter that good collaboration generates good contracts, and good contracts support good collaboration. Good!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>What the hell</title>
    <id>http://brixen.io/2006/11/7/what-the-hell</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/7/what-the-hell" />
    <published>2006-11-07T00:00:00-08:00</published>
    <updated>2006-11-07T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Warning. Long quote to follow. There, I&amp;#8217;ve warned you.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most useful products are those where the developers have understood what the product is intended to accomplish for its users and how it must accomplish that purpose. To understand these things, you must understand what kind of work the users want to do and how the product will affect that work and fit into the organization&amp;#8217;s goals. What the product does for its users and which constraints it must satisfy in this context are the product&amp;#8217;s requirements. Apart from a few fortuitous accidents, no product has ever succeeded without prior understanding of its requirements. It does not matter what kind of work the user wishes to do, be it scientific, commercial, e-commerce, or word processing. Nor does it matter which programming language or development tools are used to construct the product. The development process&amp;mdash;whether agile, eXtreme Programming, prototyping, the Rational Unified Process, or any other method&amp;mdash;is irrelevant to the need for understanding the requirements. &lt;em&gt;One fact always emerges: You must come to the correct understanding of the requirements, and have your client understand them, or your product or project will fail.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Emphasis added. Quoted from &lt;a href=&quot;http://www.amazon.com/Mastering-Requirements-Process-Suzanne-Robertson/dp/0321419499/sr=8-1/qid=1162876588/ref=pd_bbs_sr_1/104-8500968-6579924?ie=UTF8&amp;amp;s=books&quot;&gt;Mastering the Requirements Process, 2nd Ed.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To paraphrase: Knowing what you are doing is an absolute prerequisite to successfully doing it. It&amp;#8217;s not a guarantee you&amp;#8217;ll be successful, but there&amp;#8217;s no substitute for it.&lt;/p&gt;
&lt;p&gt;Agile means different things to different people. At times, &lt;em&gt;responding to change over following a plan&lt;/em&gt; is translated by someone into &lt;em&gt;planning is not agile; just jump in and see what happens because you won&amp;#8217;t know until you get there anyway&lt;/em&gt;. There&amp;#8217;s also the agile concept of not doing more than necessary at each point. So, there&amp;#8217;s a tension set up between looking forward to where you&amp;#8217;re going and looking down at what you&amp;#8217;re doing. Overdoing either get&amp;#8217;s you in trouble. Like reading a newspaper while walking through a crowd. Pay too much attention to the people and you don&amp;#8217;t get reading done. Read too much and you&amp;#8217;ll bump into people.&lt;/p&gt;
&lt;p&gt;A few months ago, when Rails was really new, there was this idea circulating that Rails made it so easy, one didn&amp;#8217;t even really have to know Ruby to program with Rails. Yeah, uh, right. Unfortunately, claiming to be &lt;em&gt;agile&lt;/em&gt; is also often substituted for knowing what you&amp;#8217;re doing. It takes a lot of knowledge and experience to balance the tension described above. It takes a lot of judgment to know &lt;em&gt;how much do I need to do right now?&lt;/em&gt; Agile is not a substitute for knowledge and experience, although it may guide you to better apply those.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Dine in or take out: it's all free</title>
    <id>http://brixen.io/2006/11/6/dine-in-or-take-out-it-s-all-free</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/6/dine-in-or-take-out-it-s-all-free" />
    <published>2006-11-06T00:00:00-08:00</published>
    <updated>2006-11-06T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;One of the more amazing and wonderful things about the internet is the sheer volume of information available for free. And just like going to a friend&amp;#8217;s party, one way to show appreciation is to partake of the feast prepared in honor of the guests. But a lot of the time it&amp;#8217;s more like a grocery store than a nice restaurant. Lots of food but not the place to savor the cooking. Once in a while, though, you happen across a gem.&lt;/p&gt;
&lt;p&gt;Since everyone has a different background, we&amp;#8217;re all learning at our own rates. If you&amp;#8217;ve always wanted to understand more about declarative versus imperative languages, syntactic sugar, dynamic versus static typing, tail recursion, lazy evaluation, currying, concurrency, exceptions, computation models, polymorphism, etc. &lt;em&gt;and&lt;/em&gt; you&amp;#8217;d like to learn about it in a comprehensive, integrated fashion, then definitely grab a copy of &lt;a href=&quot;http://www.info.ucl.ac.be/~pvr/book.html&quot;&gt;Concepts, Techniques, and Models of Computer Programming&lt;/a&gt;, here&amp;#8217;s a direct link &lt;a href=&quot;http://www.ulb.ac.be/di/rwuyts/INFO020_2003/vanRoyHaridi2003-book.pdf&quot;&gt;to the pdf.&lt;/a&gt; The book teaches the main concepts of computer science using the &lt;a href=&quot;http://www.mozart-oz.org/&quot;&gt;Mozart Programming System&lt;/a&gt; based on the &lt;a href=&quot;http://en.wikipedia.org/wiki/Oz_programming_language&quot;&gt;Oz programming language.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, for the fun part. If you&amp;#8217;re using OS X and have ports installed, getting the Mozart system is as easy as:&lt;/p&gt;
&lt;pre&gt;
sudo port install mozart
&lt;/pre&gt;
&lt;p&gt;There, you&amp;#8217;re ready to dive right in. However, one thing will make your experience much easier. Install &lt;a href=&quot;http://aquamacs.org/&quot;&gt;Aquamacs: Emacs for OS X.&lt;/a&gt; Mozart will use it if it finds it, and for me it&amp;#8217;s a nicer experience than Emacs in iTerm.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Mephisto trunk + svk + svn + cap = blogtastic</title>
    <id>http://brixen.io/2006/11/5/mephisto-trunk-svk-svn-cap-blogtastic</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/5/mephisto-trunk-svk-svn-cap-blogtastic" />
    <published>2006-11-05T00:00:00-08:00</published>
    <updated>2006-11-05T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;One &lt;a href=&quot;http://mephistoblog.com/&quot;&gt;Mephisto&lt;/a&gt; feature I really like is saving an article as a draft. Unfortunately, I&amp;#8217;m more likely to start an article than finish it. So, I&amp;#8217;m looking forward to that auto-write feature that maybe Rick is working on. Until then, I&amp;#8217;ll just have to continue finishing them on my own, even if it takes a few weeks. Ahem, like this one.&lt;/p&gt;
&lt;p&gt;Inspired by &lt;a href=&quot;http://octopod.info/2006/8/19/managing-multiple-local-mephisto-repos-with-svk&quot;&gt;Octopod&lt;/a&gt; yet &lt;a href=&quot;http://blog.brightredglow.com/2006/5/1/xen-and-the-art-of-noise-management&quot;&gt;again&lt;/a&gt;, I&amp;#8217;ve got the best of worlds: Mephisto edge at my chosen version mirrored to my own svn repository for my own hacking, all &lt;code&gt;cap deploy&lt;/code&gt;&amp;#8217;d to my &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I decided to put my svn repository on my &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; and develop in that. Basically, I use svk as a fancy adapter with the added advantage that I can update from Mephisto edge whenever it&amp;#8217;s convenient for me. Installing svk on Ubuntu 6.06 was a breeze. From there, I mostly followed Octopod&amp;#8217;s recipe: First, I create a mirror for Mephisto in my svk repository, then pull in Mephisto.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;&lt;code&gt;
svk mkdir //mirror
svk mkdir //mirror/mephisto
svk mirror http://svn.techno-weenie.net/projects/mephisto/trunk //mirror/mephisto/trunk
svk sync //mirror/mephisto/trunk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#8217;s the Mephisto side of the cable. Now, for my local svn side.&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;&lt;code&gt;
svk mkdir //svn
svk mkdir //svn/mephisto
svk mirror svn://svn.brightredglow.com/mephisto/trunk //svn/mephisto/trunk
svk smerge --baseless //mirror/mephisto/trunk //svn/mephisto/trunk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I simply use the &lt;code&gt;sync&lt;/code&gt; command above to pull new Mephisto changes to my svk repository and the following command to push those changes to my svn repository:&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;&lt;code&gt;
svk smerge --incremental --log //mirror/mephisto/trunk //svn/mephisto/trunk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here, it&amp;#8217;s pretty simple. I check out a working copy of my svn Mephisto trunk and work normally. Using &lt;a href=&quot;http://rubyforge.org/projects/capistrano/&quot;&gt;Capistrano&lt;/a&gt;, I can &lt;code&gt;cap deploy&lt;/code&gt; or &lt;code&gt;cap rollback&lt;/code&gt; to my heart&amp;#8217;s content.&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href=&quot;http://mongrel.rubyforge.org/index.html&quot;&gt;Mongrel&lt;/a&gt; + &lt;a href=&quot;http://nginx.net/&quot;&gt;Nginx&lt;/a&gt; + Mephisto are working flawlessly. My mongrel processes never get over about 35MB and they hum along day after day, week after week. Sometimes load gets too high for my &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;, but I can live with that. Speaking of &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;, &lt;a href=&quot;http://www.quantact.com&quot;&gt;Quantact&lt;/a&gt; has recently added OpenVZ options. They&amp;#8217;re quiet but dependable. And recently I logged in to my control panel to find that I had 33% more &lt;span class=&quot;caps&quot;&gt;RAM&lt;/span&gt; and another gig of disk space. I&amp;#8217;m not saying they do this all the time, but for whatever reason they did it, I appreciate it.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Inspiration under a rock</title>
    <id>http://brixen.io/2006/11/5/inspiration-under-a-rock</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/11/5/inspiration-under-a-rock" />
    <published>2006-11-05T00:00:00-08:00</published>
    <updated>2006-11-05T00:00:00-08:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.planetargon.com&quot;&gt;&lt;span class=&quot;caps&quot;&gt;PLANET&lt;/span&gt; ARGON&amp;#8217;s&lt;/a&gt; office is a hop, skip, and a jump (about 3 city blocks) from Portland&amp;#8217;s &lt;a href=&quot;http://www.explorethepearl.com/history.htm&quot;&gt;Pearl District&lt;/a&gt;, which is a really nice thing for lunch with one&amp;#8217;s girlfriend. Everyone knows that girls love to shop, right? Gross over-generalization or not, it&amp;#8217;s true. Anyway, while browsing through &lt;a href=&quot;http://www.anthropologie.com/jump.jsp?itemID=0&amp;amp;itemType=HOME_PAGE&quot;&gt;Anthropologie&lt;/a&gt;, I&amp;#8217;m of course drawn to any stack of books I see. On a nice diagonal book shelf, I located two quite interesting books: &lt;a href=&quot;http://www.amazon.com/gp/product/0060394420/ref=wl_it_dp/104-8500968-6579924?ie=UTF8&amp;amp;coliid=I26HUYE8IJG7NR&amp;amp;colid=1RKL9HG42CFPO&quot;&gt;Modern Glamour: The Art of Unexpected Style&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/gp/product/0060796634/ref=wl_it_dp/104-8500968-6579924?ie=UTF8&amp;amp;coliid=I3QOPAZJNHPLTH&amp;amp;colid=1RKL9HG42CFPO&quot;&gt;China Chic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Yeah, both a little different than typical books I read, but they got me thinking. First, they have lots of interesting compositions; colors, shapes, arrangements that are a pleasure to look at. Second, the compositions are, of course, much more than &lt;em&gt;just&lt;/em&gt; collections of colors and shapes. It&amp;#8217;s the arrangement part, the whole design, that got me thinking.&lt;/p&gt;
&lt;p&gt;With software, we&amp;#8217;re often confronted with a level of granularity that isn&amp;#8217;t very useful. If an application has some sort of access control, we may be required to twiddle read/write/execute-type permissions for each object. That&amp;#8217;s just an example, but one that is particularly problematic for non-savvy users. The implementation model is bleeding through worse than a horror-flick bloody corpse. At that level of granularity, it&amp;#8217;s like all the fabrics, wall-hangings, window-treatments, and furniture are arranged in a nice matrix of boxes in the middle of the room instead of making up the room as a whole.&lt;/p&gt;
&lt;p&gt;For one of our projects, we&amp;#8217;re exploring how we can create idioms that allow the user to manipulate objects at a much higher level. For example, adding someone as a co-worker to a project allows them to make changes, while sharing the project with a friend allows the friend to leave comments but not make changes.&lt;/p&gt;
&lt;p&gt;So, are you creating stylish, integrated, holistic rooms in your software? And where do you find odd inspiration in your everyday life?&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Principles of d3: simplicity</title>
    <id>http://brixen.io/2006/10/12/principles-of-d3-simplicity</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/10/12/principles-of-d3-simplicity" />
    <published>2006-10-12T00:00:00-07:00</published>
    <updated>2006-10-12T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;If you&amp;#8217;ve paid any attention to our discussion of &lt;a href=&quot;http://www.dialogue-driven.org&quot;&gt;d3&lt;/a&gt;, you&amp;#8217;ve noticed that we&amp;#8217;re just beginning. We&amp;#8217;re trying to articulate the principles that we believe define an effective approach to &amp;#8220;client&amp;#8221; interaction. I say &amp;#8220;client&amp;#8221; because it&amp;#8217;s not necessarily true that the people are clients in the traditional sense. Organizations often address that with a term like &amp;#8220;internal client&amp;#8221; to refer to another department, for instance. But that&amp;#8217;s a different topic.&lt;/p&gt;
&lt;p&gt;In the #d3 channel on irc.freenode.net the other day, &lt;a href=&quot;http://ibrasten.com&quot;&gt;Brasten&lt;/a&gt; posted this:&lt;/p&gt;
&lt;pre style=&quot;overflow: auto;&quot;&gt;
17:23   brasten &amp;gt;&amp;gt; anecdote--
17:24   brasten &amp;gt;&amp;gt; spend 30 minutes on the phone with a client discussing a project...  going over all the features he 
                   wanted.
17:25   brasten &amp;gt;&amp;gt; weird stuff.... needed to send small emails with outlook-compatible attachments... import CVS 
                   documents, yadda yadda... none of it made any sense...
17:25   brasten &amp;gt;&amp;gt; finally I asked, &quot;what exactly is the PROBLEM you're having that this project needs to address??&quot;
17:26   brasten &amp;gt;&amp;gt; the guy literally sighed.. paused... and said, &quot;I just want to be able to run my business from my 
                   BlackBerry.&quot;     ahhh.... now that's a very different project....we can solve that.
17:26   brasten &amp;gt;&amp;gt; and we were the first developers to actually ask him that.
17:27   tacodog &amp;gt;&amp;gt; hah
17:27   brasten &amp;gt;&amp;gt; -- end anecdote.
&lt;/pre&gt;
&lt;p&gt;You may have had this same experience numerous times. It happens frequently enough to make us ask, &amp;#8220;what&amp;#8217;s the dynamic here?&amp;#8221;&lt;/p&gt;
&lt;p&gt;I think this exchange illustrates one of the core principles we&amp;#8217;re after: we prefer problem statements because they will always be simpler than a solution or implementation. The problem statement is at a different level of abstraction. It is easier to understand, and thus easier to talk about. The problem statement is as close as we can get to the core. Every possible solution or implementation will be layered around this.&lt;/p&gt;
&lt;p&gt;Simplicity is an interesting concept. My dashboard dictionary has this as one definition:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;the quality or condition of being easy to understand or do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We often refer to implementations in terms of simplicity, or simple versus complicated. It&amp;#8217;s hard to imagine a compelling argument for something being more complicated than it needs to be. In general, we tend to equate &amp;#8220;simpler&amp;#8221; with &amp;#8220;better&amp;#8221;.&lt;/p&gt;
&lt;p&gt;As a principle of d3, we want our client interaction to be simpler. So we want to talk about problems with our clients. We want these to be the concrete, explicit elements we dialogue about.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll admit, I feel silly sometimes trying to describe these ideas. They seem really basic. But if this whole dialogue thing were that simple (pun intended), we would rarely, rather than frequently, have exchanges like that above. So, drop by #d3 and help us figure out how to make it as simple as it should be, but no simpler.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>User interaction blunders</title>
    <id>http://brixen.io/2006/10/8/user-interaction-blunders</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/10/8/user-interaction-blunders" />
    <published>2006-10-08T00:00:00-07:00</published>
    <updated>2006-10-08T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I typically conduct all of my personal business online: mortgage, credit card bills, utility bills, cell phone bill, etc. It&amp;#8217;s a great convenience. That&amp;#8217;s probably the primary reason. It&amp;#8217;s simply more convenient than anything else. I can&amp;#8217;t think of any other reason I do it. If there were some attendant in a window I frequently walked by, I&amp;#8217;d just as soon give the person a check or credit card to pay a bill. With no waiting line, it would take about the same amount of time.&lt;/p&gt;
&lt;p&gt;But since online is the most convenient, I usually use it. Now, since paying these bills means I&amp;#8217;m parting with hard-earned money, I tend to be pretty critical of the process. Add to that the fact that these folks, bankers, etc. generally have a ton of money, I expect them to present a pretty nice experience when separating me and my cash. If not nice exactly, it should work well.&lt;/p&gt;
&lt;p&gt;So after an experience with Chase&amp;#8217;s credit card site, I decided to send them a little note of helpful criticism. I will say, that Chase&amp;#8217;s newly redesigned site is probably the best of the 8 or so I frequently use. Even so, I don&amp;#8217;t understand how stuff like this gets into the website. Maybe I just have too high of expectations.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I just went in to update my business phone number today and was required to fill out every piece of information about my address and personal phone number. That is plainly stupid. I wanted to change one small bit of info and I had to retype everything. There was not even a way to load the existing values into the form.&lt;/p&gt;
&lt;p&gt;Please consider your user when designing these forms. Making me enter all that information again when I did not want to change it was both a waste of my time and created the potential for me to accidentally enter incorrect information.&lt;/p&gt;
&lt;p&gt;Overall, your site redesign is quite nice and I enjoy using this website much more than the last one. However, things like this form are awfully annoying when forced to deal with them. It creates the tendency to not want to update information because of the hassle. That&amp;#8217;s surely not the result you&amp;#8217;re aiming at.&lt;/p&gt;
&lt;p&gt;Hope you can get these things straightened out. Just because they may be rarely used parts of the website doesn&amp;#8217;t mean they should not get the same level of intelligent design. And if the folks who are designing the website don&amp;#8217;t understand these issues, that&amp;#8217;s a big problem.&lt;/p&gt;
&lt;p&gt;Cheers,&lt;br /&gt;
Brian&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, do you think I&amp;#8217;m expecting too much? What are your favorite examples of websites that should be a cut above, but often fall flat on their faces?&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>What's it worth to me?</title>
    <id>http://brixen.io/2006/10/4/what-s-it-worth-to-me</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/10/4/what-s-it-worth-to-me" />
    <published>2006-10-04T00:00:00-07:00</published>
    <updated>2006-10-04T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;After you begin practicing &lt;a href=&quot;http://www.testdriven.com&quot;&gt;&lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;&lt;/a&gt;, or better &lt;a href=&quot;http://www.behavior-driven.org&quot;&gt;&lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt;&lt;/a&gt;, for even a short while, it clicks. Once you get in the habit of thinking about the behavior you expect and describing that first in a test or spec, you realize there is a qualitative difference in how you are writing code. It&amp;#8217;s not simply that you are writing code faster, or writing better code. You are working differently. A quantum leap, if you will. It&amp;#8217;s a great, &amp;#8220;Ah, hah!&amp;#8221; experience.&lt;/p&gt;
&lt;p&gt;I sketched a couple diagrams to try to describe this difference while chatting with &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; about &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/09/27/project-enlightenment-with-d3&quot;&gt;creating shared meaning&lt;/a&gt; with clients. Check them out below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.brightredglow.com/assets/2006/10/4/linear_development.png&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
p. Figure 1. Traditional linear perspective&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://blog.brightredglow.com/assets/2006/10/4/bdd_development.png&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
p. Figure 2. Circular &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; perspective&lt;/p&gt;
&lt;p&gt;The, seemingly, traditional view is linear. You start with no feature, do a bunch of whatever, and at the end you have the feature completed. The &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;/&lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; view is quite different. Following the mantra&amp;mdash;red, green, refactor&amp;mdash;you start with a description of your expectations, you generate code that meets those expectations, and then you refactor. For all but the simplest bits of code, you will likely refactor numerous times. Refactoring is an explicit, purposeful, integral, regular part of creating code. And it&amp;#8217;s not, typically, something you do to fix errors, which is how someone with a traditional view tends to understand refactoring. You refactor when your code is meeting your expectations (tests, specs) and those ensure that the product of your refactoring continues to meet your expectations. You refactor because the process of writing code changes how you are thinking about and understanding the code you write.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s difficult to find an analogue to this process in our everyday world. In construction, we would surely not build a room and then tear it down to rebuild it because our understanding changed. But an architect may well do that many times with a model in the attempt to create a solution that works. There&amp;#8217;s no accurate, faithful way to transfer the architecture paradigm to software development. Many have tried, failed, and many will try again. Instead, &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; is an essential part of the software development paradigm and it&amp;#8217;s processes should be understood, to some degree, by everyone participating in software development, clients included.&lt;/p&gt;
&lt;p&gt;One significant challenge that we encounter is communicating the importance or value of a particular recommendation. There is more than conveying the information. We have experienced explaining to a client why it was necessary to refactor a particularly important part of an application. (In this case, it was more of a redesign, but since the behavior of the application was not intended to changed, we viewed it as a large scale refactoring.) The client acknowledged that our recommendation had technical merit, in some sense, but continued to view it as something of a diversion with little practical value. After all, the &amp;#8220;features&amp;#8221; were in place. We weren&amp;#8217;t asserting that we would significantly change anything that the user interacted with. And the client was feeling the crunch of getting new features in front of the users.&lt;/p&gt;
&lt;p&gt;So, the problem is much more than communicating information between developers and clients. It is essential to dialogue in a way that shared meaning evolves. The shared meaning brings our values into alignment. Then a true, rewarding process of collaboration powers the endeavor.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Pardon my dust</title>
    <id>http://brixen.io/2006/10/3/pardon-my-dust</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/10/3/pardon-my-dust" />
    <published>2006-10-03T00:00:00-07:00</published>
    <updated>2006-10-03T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;And now for a public service announcement&amp;#8230;&lt;/p&gt;
&lt;p&gt;Over the past month I&amp;#8217;ve made a lot of changes to my &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt;. Plug for &lt;a href=&quot;http://www.quantact.com&quot;&gt;Quantact&lt;/a&gt;, they&amp;#8217;ve been great. Actually, I almost never talk to them. Which is just the way I like it; means everything is running fine.&lt;/p&gt;
&lt;p&gt;So, a few highlights if you&amp;#8217;re interested:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Debian 3.1 to Ubuntu 6.06 Dapper Drake.&lt;/li&gt;
	&lt;li&gt;lighttpd+fcgi to lighttpd+mod_proxy&lt;/li&gt;
	&lt;li&gt;lighttpd+mod_proxy to nginx&lt;/li&gt;
	&lt;li&gt;Typo to Mephisto&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You probably haven&amp;#8217;t noticed much but the last one. Hopefully I didn&amp;#8217;t put any wrinkles in your day. I&amp;#8217;ve been using Feedburner almost since the beginning of this blog. That feed has been updated and I believe is working. I&amp;#8217;ve set up a route for the old Typo-style URLs so your links should not break. I&amp;#8217;ll be getting tag based feeds going as soon as I can. And I&amp;#8217;ll lovingly replace this awful default Mephisto theme. &lt;a href=&quot;http://encytemedia.com/&quot;&gt;Justin Palmer&lt;/a&gt; is awesome, &lt;del&gt;but I think he stubbed his big toe with this one&lt;/del&gt;. (Oops, the Hemingway theme is by Kyle Neath. Sorry Justin.)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll post soon about setting up Mephisto in svk and svn, thanks to inspiration from &lt;a href=&quot;http://octopod.info/2006/8/19/managing-multiple-local-mephisto-repos-with-svk&quot;&gt;Octoblog&lt;/a&gt;. Actually, double thanks, since Octopod inspired me to set up my &lt;span class=&quot;caps&quot;&gt;VPS&lt;/span&gt; in the beginning.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Why we focus on solutions, not products</title>
    <id>http://brixen.io/2006/9/21/why-we-focus-on-solutions-not-products</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/9/21/why-we-focus-on-solutions-not-products" />
    <published>2006-09-21T00:00:00-07:00</published>
    <updated>2006-09-21T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Developing anything in the digital realm can be fantastically rewarding precisely because the ropes on our wings of fantasy are greatly weakened. We can imagine practically anything, and we can implement a lot of what we can imagine. The whir of excitement in our stomachs at the vision of some excellent idea prompts my favorite utterance, &amp;ldquo;Wouldn&amp;rsquo;t it be cool if&amp;hellip;&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Unfortunately, our flights of fantasy must interface with the &amp;ldquo;physical&amp;rdquo; world, even if through the digital medium. Faster than light travel doesn&amp;rsquo;t exist. Perpetual motion doesn&amp;rsquo;t exist. There is a cost for everything, and it&amp;rsquo;s thousands of orders of magnitude greater than the few molecules of ATP that literally fueled our fantasy.&lt;/p&gt;

&lt;p&gt;No great revelations there. But it sure helps to ground ourselves with this frequent reminder.&lt;/p&gt;

&lt;p&gt;When it comes to software, I find that the single most difficult thing for &lt;em&gt;anyone&lt;/em&gt; to do is think outside of the &lt;strong&gt;Feature Fantasy&lt;/strong&gt;. This applies to everyone, developers, designers, clients, users, people. Everyone. With a breathless hop, skip, and jump, we leap right over the problem, the solution, and into some particular implementation. It&amp;rsquo;s so automatic I would have assumed that we&amp;rsquo;d been taught how to do this in specialized classes since grade school, with some folks getting advanced university degrees in it.&lt;/p&gt;

&lt;p&gt;At &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;, one thing we are trying to develop through our process and our exploration of &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/08/08/d3-not-ddd&quot;&gt;d3&lt;/a&gt;, is how to effectively separate the problem, the solution, and the implementation. I would say better than 90% of our discussions start out at the feature, or implementation level. We actively and tireless attempt to refocus this back on the problem, describing and documenting it so we can think and dialogue about solutions.&lt;/p&gt;

&lt;p&gt;As &lt;a href=&quot;http://www.jvoorhis.org&quot;&gt;Jeremy&lt;/a&gt; has explored a bit in his article on &lt;a href=&quot;http://www.jvoorhis.org/articles/2006/09/20/feature-ecology&quot;&gt;Feature Ecology&lt;/a&gt;, the interaction or relation between features actually alters the product as a whole. Again, not an astounding idea, but the consequence of this is that a lot of time is spent chasing your tail if you focus on features without the benefit of well understanding the problem and solution.&lt;/p&gt;

&lt;p&gt;Another benefit of focusing on the problem and solution is that it provides a natural meeting ground between clients and developers. Often the clients are not the users of the software. This makes it even more important to explore the problem to be solved rather than the client&amp;rsquo;s ideas of particular features. One of the most valuable things I took from reading Alan Cooper&amp;rsquo;s original &lt;em&gt;About Face&lt;/em&gt; almost a decade ago is that no one would use your software if they didn&amp;rsquo;t have to. How&amp;rsquo;s that for a response to, &amp;ldquo;wouldn&amp;rsquo;t it be cool if&amp;hellip;&amp;rdquo;&lt;/p&gt;

&lt;p&gt;If you want to create software that people won&amp;rsquo;t hate using, focus on the problem and a very good description of a solution. Use your solution to implement a product. Get feedback from people on your understanding of the problem, your description of a solution, and only lastly, on your implementation of the product.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Are your tests findable</title>
    <id>http://brixen.io/2006/9/20/are-your-tests-findable</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/9/20/are-your-tests-findable" />
    <published>2006-09-20T00:00:00-07:00</published>
    <updated>2006-09-20T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I probably use Google search on average 20-30 times a day. It&amp;rsquo;s an indispensable tool for me. It&amp;rsquo;s definitely not the last word in search engines. I can imagine a lot of additional functionality, like contextualizing my searches over time or within categories. But overall, it works reasonably well.&lt;/p&gt;

&lt;p&gt;Lately, I&amp;rsquo;ve been reading &lt;em&gt;Ambient Findability&lt;/em&gt; by Peter Morville. He provides this definition for findability:&lt;/p&gt;

&lt;blockquote&gt;
findability &lt;em&gt;n&lt;/em&gt;
&lt;ol&gt;
&lt;li&gt;The quality of being locatable or navigable.&lt;/li&gt;
&lt;li&gt;The degree to which a particular object is easy to discover or locate.&lt;/li&gt;
&lt;li&gt;The degree to which a system or environment supports navigation and retrieval.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Peter explains that findability is defined at both the object and system levels. For example, the title of a document or the color of a pen on your desk. At the system level, you can ask questions like, &amp;ldquo;Can a traveler navigate an airport,&amp;rdquo; or &amp;ldquo;Can a user navigate a website.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;While these ideas help us frame the concepts, how do we evaluate findability in concrete situations. Not surprisingly, there are elements of findability that we can examine:&lt;/p&gt;

&lt;blockquote&gt;
Findability requires definition, distinction, difference. In physical environments, size, shape, color, and location set objects apart. In the digital realm, we rely heavily on words. Words as labels. Words as links. Keywords.
&lt;/blockquote&gt;

&lt;p&gt;Hmm, interesting. At &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;, we have been evaluating using the &lt;em&gt;rspec_for_rails&lt;/em&gt; plugin to focus more heavily on &lt;a href=&quot;http://behavior-driven.org/&quot;&gt;BDD&lt;/a&gt;. One of the things BDD emphasizes is leveraging the power of words to help us think more effectively (accurately) about our code. We have been incorporating BDD style method naming into our TDD practices, as well as refining our ability to specify application behavior in our tests.&lt;/p&gt;

&lt;p&gt;One thing I dislike about the regular &lt;code&gt;Test::Unit&lt;/code&gt; framework is that the methods are often organized ad hoc. Whatever makes the most sense to the programmer when adding those particular tests. Sometimes it&amp;rsquo;s just appending the method to the list of existing methods. Most often, I notice some sort of organization. Which makes sense; that&amp;rsquo;s how we deal with information. But the framework doesn&amp;rsquo;t provide any guidance here.&lt;/p&gt;

&lt;p&gt;With the &lt;a href=&quot;http://rspec.rubyforge.org/&quot;&gt;RSpec&lt;/a&gt; framework (check out &lt;a href=&quot;http://rspec.rubyforge.org/tools/rails.html&quot;&gt;RSpec on Rails&lt;/a&gt;), you can arrange your methods into contexts. I think this encourages better organization and contributes to the quality of findability as discussed above. Tests are just another type of information we interact with. How much effort does it take to locate what you&amp;rsquo;re looking for, understand what the tests are saying, understand the output when a test fails? Following along &lt;a href=&quot;http://www.jvoorhis.com&quot;&gt;Jeremy&amp;rsquo;s&lt;/a&gt; questions about &lt;a href=&quot;http://www.jvoorhis.org/articles/2006/08/26/is-your-test-suite-acceptable&quot;&gt;acceptable&lt;/a&gt; tests:&lt;/p&gt;

&lt;p&gt;Are your tests findable?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The tangled web: data migrations</title>
    <id>http://brixen.io/2006/9/6/the-tangled-web-data-migrations</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/9/6/the-tangled-web-data-migrations" />
    <published>2006-09-06T00:00:00-07:00</published>
    <updated>2006-09-06T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Migrations are one of my favorite things about Rails. I remember being amazed at the simplicity and usefulness when I first saw them. I also remember a previous boss asserting that we would just use &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; in the migrations because, to paraphrase, that way we would know what was happening. There&amp;#8217;s that saying about tossing rubies before chickens, or something. But as I was saying, migrations.&lt;/p&gt;
&lt;p&gt;One thing that makes migrations particularly useful is when they are the only means used to change the database. That way, you know the state you are in and unless you have a rare, non-reversible migration, you can migrate up and down at will. That all works great for the database structure. But what about data? We obviously won&amp;#8217;t be funneling all the data changes through migrations. This isn&amp;#8217;t much of an issue if your application starts as a blank slate and acquires data through use.&lt;/p&gt;
&lt;p&gt;Recently we had an application that needed a bunch of preloaded data. Unfortunately, it wasn&amp;#8217;t a one-shot loading of data once the structure was mostly solidified. I needed to try out stuff and wanted the super useful migrations to be my tool. Previously, this had been done with some ad hoc `rake` tasks, which turned out to be, frankly, a mess.&lt;/p&gt;
&lt;p&gt;The single biggest challenge working with the data was the fact that the state of the data would be changing independent of the migrations. There was no way to ensure the state between one migration and the next.&lt;/p&gt;
&lt;p&gt;I decided that the one thing I could assert before and after a migration was that certain records with certain id&amp;#8217;s did not exist (pre-) and then did exist (post-migration) (reverse that for migrating down). It turned out this would be good enough for what I needed.&lt;/p&gt;
&lt;p&gt;My first stab at implementing this was a couple helper functions that I used in migrations to update the datafiles (in yaml format) with keys for the id&amp;#8217;s. This was a big problem because the files would be changing and were tracked in subversion, so they couldn&amp;#8217;t really be shared by more than one developer. Playing around a bit, I came across this idea:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateGeographicTypesFacts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;up&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;capture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:details&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt; 			&lt;span class=&quot;c1&quot;&gt;# do whatever needed to create records&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;down&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;release&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:details&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Basically, as the data migration runs, I want to keep track of what records are created (and which of those are possibly destroyed). Obviously, this assumes that I&amp;#8217;ll be adding data on the up migration and removing it on the down. To implement this, I opened up the `ActiveRecord::Migration` class and added a couple methods:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;capture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constantize&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class_eval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;end_eval&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      @@capture_ids = []&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      def self.capture_ids&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;        @@capture_ids.uniq&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      after_create do |obj|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;        @@capture_ids &amp;lt;&amp;lt; obj.id&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      after_destroy do |obj|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;        @@capture_ids.remove obj.id&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;      end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;    end_eval&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;20&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;22&lt;/span&gt;   &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_migration_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  
&lt;span class=&quot;lineno&quot;&gt;24&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constantize&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25&lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capture_ids&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26&lt;/span&gt;       &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_yaml&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This `capture` method adds callbacks for `after\&lt;em&gt;create` and `after\&lt;/em&gt;destroy` to keep track of the id&amp;#8217;s. This is written out to a file in a `data` subdirectory of the `db/migrate` directory. These files can be ignored by Subversion so each developer can run the migrations on their own databases without clashing.&lt;/p&gt;
&lt;p&gt;Migrating down is basically a matter of removing the records that were created when migrating up.&lt;br /&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;data_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_migration_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:down&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;r+&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;YAML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compact&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;constantize&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;klass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blank?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13&lt;/span&gt;   &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlink&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_file&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&amp;lt;span class=&quot;lineno&quot;&amp;gt; 1&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;k&quot;&amp;gt;def&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;nc&quot;&amp;gt;self&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;nf&quot;&amp;gt;release&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;*&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;args&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 2&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;n&quot;&amp;gt;data_file&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;data_migration_file&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;ss&quot;&amp;gt;:down&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 3&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;n&quot;&amp;gt;data&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;no&quot;&amp;gt;File&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;open&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;data_file&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;s1&quot;&amp;gt;&amp;amp;#39;r+&amp;amp;#39;&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;p&quot;&amp;gt;{&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;no&quot;&amp;gt;YAML&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;load&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;f&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;p&quot;&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 4&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;k&quot;&amp;gt;if&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;nb&quot;&amp;gt;block_given?&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 5&amp;lt;/span&amp;gt;     &amp;lt;span class=&quot;k&quot;&amp;gt;yield&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;*&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;args&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;inject&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;[]&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;p&quot;&amp;gt;{&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;list&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;p&quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;list&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;&amp;amp;lt;&amp;amp;lt;&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;data&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;]&amp;lt;/span&amp;gt; 
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 6&amp;lt;/span&amp;gt;     &amp;lt;span class=&quot;p&quot;&amp;gt;}&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;compact&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;k&quot;&amp;gt;if&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;nb&quot;&amp;gt;block_given?&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 7&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;k&quot;&amp;gt;else&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 8&amp;lt;/span&amp;gt;     &amp;lt;span class=&quot;n&quot;&amp;gt;args&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;each&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;k&quot;&amp;gt;do&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;|&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt; 9&amp;lt;/span&amp;gt;       &amp;lt;span class=&quot;n&quot;&amp;gt;klass&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;o&quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;to_s&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;classify&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;constantize&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt;10&amp;lt;/span&amp;gt;       &amp;lt;span class=&quot;n&quot;&amp;gt;klass&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;delete&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;data&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;k&quot;&amp;gt;unless&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;data&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;nb&quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;].&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;blank?&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt;11&amp;lt;/span&amp;gt;     &amp;lt;span class=&quot;k&quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt;12&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;k&quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt;13&amp;lt;/span&amp;gt;   &amp;lt;span class=&quot;no&quot;&amp;gt;File&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;o&quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class=&quot;n&quot;&amp;gt;unlink&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;n&quot;&amp;gt;data_file&amp;lt;/span&amp;gt;
&amp;lt;span class=&quot;lineno&quot;&amp;gt;14&amp;lt;/span&amp;gt; &amp;lt;span class=&quot;k&quot;&amp;gt;end&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;If you provide a block to the `release` method, you take care of doing whatever you want to the records. If you just want to delete them, don&amp;#8217;t pass a block and `release` will delete them. I used `delete` rather than `destroy` so that everything you specify on capture is deleted without running into issues with `:dependent =&amp;gt; :destroy`.&lt;/p&gt;
&lt;p&gt;This has been useful for add and removing data while trying out different table structures. Obviously, it&amp;#8217;s a rather targeted solution. I&amp;#8217;ll be packaging it as a plugin and posting it to [&lt;span class=&quot;caps&quot;&gt;PLANET&lt;/span&gt; ARGON&amp;#8217;s](http://www.planetargon.org) community site soon.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Testing the tester</title>
    <id>http://brixen.io/2006/8/30/testing-the-tester</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/30/testing-the-tester" />
    <published>2006-08-30T00:00:00-07:00</published>
    <updated>2006-08-30T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I recently wrote about the &lt;a href=&quot;http://blog.brightredglow.com/articles/2006/08/27/assert_cookie-for-ooey-gooey-fun&quot;&gt;assert_cookie&lt;/a&gt; custom test assertion plugin I put together. When I started writing the assertion, it was just a helper method to wrap up the funky logic for testing stuff about a cookie. I wasn&amp;rsquo;t thinking about tests. And my first tries were definitely not test-driven.&lt;/p&gt;

&lt;p&gt;When I was wrapping it up as a plugin, this started bugging me a lot. Especially because my first tries at the assertion method weren&amp;rsquo;t very good. (Ugh! &lt;code&gt;svn diff -r59:72 http://svn.planetargon.org/rails/plugins/assert\_cookie/lib/assert\_cookie.rb&lt;/code&gt;) But the idea of testing it was confounding. How do you think about testing the tester?&lt;/p&gt;

&lt;p&gt;The first thing I had to get straight was what I expected. It basically reduced to expecting the assertion to pass or fail. When an assertion fails, it raises the &lt;code&gt;AssertionFailedError&lt;/code&gt; exception. Excellent, now I was making progress.&lt;/p&gt;

&lt;p&gt;I started writing tests like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_assertion_cookie_is_secure_should_pass_when_cookie_is_secure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_nothing_raised&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_cookie&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:secure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_assertion_cookie_is_secure_should_fail_when_cookie_is_not_secure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_raise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;AssertionFailedError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_cookie&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:open_secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;7&lt;/span&gt;       &lt;span class=&quot;ss&quot;&gt;:secure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;and notices a lot of repetition of &lt;code&gt;assert\_raise(AssertionFailedError)&lt;/code&gt; and &lt;code&gt;assert\_nothing\_raised&lt;/code&gt;. It was ugly to read. I decided to write a couple helper assertions:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt; 1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assert_pass&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;assert_pass must be called with a block.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 6&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assert_fail&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;assert_fail must be called with a block.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;AssertionFailedError&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The hard part again was figuring out what I was expecting. My first try was to use &lt;code&gt;assert\_raise&lt;/code&gt; and &lt;code&gt;assert\_nothing\_raised&lt;/code&gt; as before. But those failed miserable because they call &lt;code&gt;yield&lt;/code&gt;. I lamented to &lt;a href=&quot;http://www.stopdropandrew.com/&quot;&gt;Andrew&lt;/a&gt; that I wished &lt;code&gt;yield&lt;/code&gt; would work like &lt;code&gt;raise&lt;/code&gt;. After thinking a bit more, I realized I only cared whether an &lt;code&gt;AssertionFailedError&lt;/code&gt; exception was raised or not. The previous tests now look like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;lineno&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_assertion_cookie_is_secure_should_pass_when_cookie_is_secure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;2&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_pass&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_cookie&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:secure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;4&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_assertion_cookie_is_secure_should_fail_when_cookie_is_not_secure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;6&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;assert_fail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_cookie&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:open_secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:secure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There is one last thing that bugs me. I wanted the tests to run outside of Rails but function correctly in Rails. Rails adds a method to &lt;code&gt;Test::Unit::Assertions&lt;/code&gt; called &lt;code&gt;clean\_backtrace&lt;/code&gt;. I couldn&amp;rsquo;t figure out how to get that required correctly, so I created a stub in &lt;code&gt;test\_helper.rb&lt;/code&gt;. Can anyone help me fix this?&lt;/p&gt;

&lt;p&gt;Install the plugin with &lt;code&gt;script/plugin install http://svn.planetargon.org/rails/plugins/assert_cookie&lt;/code&gt;. Navigate to the &lt;code&gt;vendor/plugins/assert_cookie&lt;/code&gt; directory, type &lt;code&gt;rake&lt;/code&gt; and watch the tests run. :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Tracer bullets are about aiming, not firing</title>
    <id>http://brixen.io/2006/8/29/tracer-bullets-are-about-aiming-not-firing</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/29/tracer-bullets-are-about-aiming-not-firing" />
    <published>2006-08-29T00:00:00-07:00</published>
    <updated>2006-08-29T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;There&amp;rsquo;s more than one way to shoot down a moving target. &lt;a href=&quot;http://blogs.pragprog.com/cgi-bin/pragdave.cgi&quot;&gt;Dave Thomas&lt;/a&gt; and &lt;a href=&quot;http://www.toolshed.com/blog/&quot;&gt;Andy Hunt&lt;/a&gt; have used the metaphor of tracer bullets to describe an approach to software development. &lt;a href=&quot;http://martin.ankerl.org/2006/03/03/tracer-bullet-development-versus-extreme-programming/&quot;&gt;Martin&lt;/a&gt;, &lt;a href=&quot;http://www.badgerism.com/archives/2005/11/21/ship-it-chapter-3-pragmatic-project-techniques-2/&quot;&gt;Badgerism&lt;/a&gt;, &lt;a href=&quot;http://www.pbell.com/index.cfm/2006/7/9/Ready-Fire-Aim&quot;&gt;Peter&lt;/a&gt;, &lt;a href=&quot;http://www.lightsoutproduction.com/index.php?option=com_content&amp;amp;task=view&amp;amp;id=32&amp;amp;Itemid=71&quot;&gt;Lights Out Production&lt;/a&gt;, and &lt;a href=&quot;http://www.codinghorror.com/blog/archives/000256.html&quot;&gt;Jeff&lt;/a&gt;, in no particular order&lt;a href=&quot;#sub1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; and among many others, have weighed in with their thoughts.&lt;/p&gt;

&lt;p&gt;But how does firing at a moving target with tracer bullets work? It&amp;rsquo;s a gross over-simplification to say you just fire-aim-fire-aim. In fact, the key to the process is how aiming itself provides immediate feedback to refine aiming. As Dave himself says,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Basically, it all comes down to feedback. The more quickly you can get feedback, the less change you need to get back on target.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, the process actually goes something like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you have already acquired a target&lt;/li&gt;
  &lt;li&gt;you have initially aimed the gun&lt;/li&gt;
  &lt;li&gt;you fire and watch where the tracers go&lt;/li&gt;
  &lt;li&gt;you re-aim based on where the target is now in relation to the tracers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That&amp;rsquo;s a single person aiming, firing, watching, aiming, &amp;hellip; That&amp;rsquo;s a process that is happening over short instants of time. Where you aimed a fraction of a second ago is still visible in the stream of tracer bullets when you adjust your aim.&lt;/p&gt;

&lt;p&gt;Now translate that to a team developing software. No longer is it one person. No longer is the feedback loop on the order of fractions of a second. Time stretches to weeks or months between the initial target acquisition and aiming until the feedback comes in. How does that feedback inform the original rationale for the design decisions or even for the target acquisition?&lt;/p&gt;

&lt;p&gt;In the process we are refining at &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;, we insist that we document the rationale for our design decisions. This includes documenting our discussions with the client and domain experts to identify the goals of the software and its users. This is a very lightweight process, usually about a small paragraph per major design decision. We typically use a wiki to record the documentation and aggregate in the same place useful references, project documentation, interviews, etc.&lt;/p&gt;

&lt;p&gt;To some folks, documentation may be a dirty word, something to shun or dread. Not for us. Documentation is simply our way of providing a record of the decisions we make so that feedback can be evaluated in context. From my dashboard dictionary:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;documentation&lt;/em&gt;, n.&lt;/p&gt;

  &lt;p&gt;Material that provides official information or evidence or that serves as a record&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I&amp;rsquo;m at a loss to understand how else you would do it. Tracer bullets don&amp;rsquo;t help you a bit if you are just firing randomly. And I think that&amp;rsquo;s what people miss about the process. You really do &lt;em&gt;aim&lt;/em&gt; first. And if you can&amp;rsquo;t remember why you aimed where you did, or if the person who did the aiming  has left by the time feedback is coming in, that feedback may be interesting, but it certainly isn&amp;rsquo;t going to enable you to refine your decisions.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;sup1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Thanks to &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; for providing links to some of these articles&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Agile thought 41 years ago</title>
    <id>http://brixen.io/2006/8/29/agile-thought-41-years-ago</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/29/agile-thought-41-years-ago" />
    <published>2006-08-29T00:00:00-07:00</published>
    <updated>2006-08-29T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Recently, &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; dropped off his copy of &lt;em&gt;The New Utopians&lt;/em&gt; by Robert Boguslaw at my desk with a section marked: &amp;ldquo;For Whom and For What&amp;rdquo;. Here are a couple interesting quotes on page 45:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This, then, is one of the fundamental problems of application: on the one hand, the temptation is almost overpowering to establish the techniques and practices of practitioners as handbook truths available in situations of the sort we have termed established. It is the temptation to speak with the same degree of assurance under all professional circumstances as does the familiar stereotype of the TV repairman or journeyman carpenter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;On the other hand, there may be found equally strong temptation to revert to unbridled intuitionism&amp;ndash;on the part of those who somehow sense the inadequacy of established situation science applied to emergent situation reality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This reminded me of the recent blog exchange between &lt;a href=&quot;http://peat.wordpress.com/2006/08/14/software-and-common-sense-part-ii/&quot;&gt;Peat&lt;/a&gt; and &lt;a href=&quot;http://jooto.com/blog/index.php/2006/08/16/why-do-geeks-hate-common-sense/&quot;&gt;Alex&lt;/a&gt; regarding the role of common sense and intuition in application development.&lt;/p&gt;

&lt;p&gt;It is an attractive and beguiling illusion that attempts to persuade us to think that if we just apply enough analysis from correct principles, we&amp;rsquo;ll produce something &amp;ldquo;correct.&amp;rdquo; And we should do the analysis first. That pretty siren sings so sweetly over the shipwreck mess of many development projects. The allure is so powerful, of course, because sometimes it is correct. The problem is when to do this and at what scale.&lt;/p&gt;

&lt;p&gt;Sometimes it is much better to analyze things first. Some people will say, &amp;ldquo;First make it correct, then optimize it.&amp;rdquo; But when speaking with &lt;a href=&quot;http://railsexpress.de/blog/&quot;&gt;Stefan Kaes&lt;/a&gt; at RailsConf 2006 after his talk, I thanked him for pointing out that some consideration for performance &lt;em&gt;must&lt;/em&gt; be made up front. To paraphrase his reply, &amp;ldquo;Absolutely&amp;rdquo;. Here, the scale is large. Broad decisions are made, not detailed ones. And it is necessary to do it earlier rather than later because this broad decision will dictate the confines under which many small decisions are made that create a structure of significant weight that will resist change.&lt;/p&gt;

&lt;p&gt;I was a bit disturbed to read &lt;a href=&quot;http://martin.ankerl.org/2006/03/03/tracer-bullet-development-versus-extreme-programming/&quot;&gt;this comparison&lt;/a&gt; of Tracer Bullet Development versus eXtreme Programming where it was asserted that TBD uses up-front design while XP does not. Obviously, using XP, you don&amp;rsquo;t just start randomly writing code. &lt;em&gt;Somewhere&lt;/em&gt;, &lt;em&gt;somehow&lt;/em&gt; a bunch of decisions were made that create the context in which you start writing tests. Disregarding appropriate situations at which to make preliminary decisions is as dangerous as deciding too much.&lt;/p&gt;

&lt;p&gt;Even if we know extremely well the technical details of the small bits of test-driven code we are writing, it&amp;rsquo;s probably guaranteed that we have but a faint understanding of how those pieces will make a complete application. As Robert points out summarizing Kurt Lewin in &amp;ldquo;Field Theory and Learning&amp;rdquo;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In short, it is not &amp;hellip; that the whole is &lt;em&gt;more&lt;/em&gt; than the sum of its parts; it is &lt;em&gt;different&lt;/em&gt; from the some of its parts&lt;/p&gt;
&lt;/blockquote&gt;

</content>
  </entry>
  
  <entry>
    <title>assert_no_cookie dammit</title>
    <id>http://brixen.io/2006/8/28/assert_no_cookie-dammit</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/28/assert_no_cookie-dammit" />
    <published>2006-08-28T00:00:00-07:00</published>
    <updated>2006-08-28T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I hate cookies. Or maybe I&amp;#8217;m just feeling schizo today. Actually, I do love cookies, just not testing them with Rails.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve added &lt;code&gt;assert\_no\_cookie&lt;/code&gt; method to the &lt;code&gt;assert\_cookie&lt;/code&gt; plugin. That&amp;#8217;s because in your functional tests, &lt;code&gt;cookies['chocolate']&lt;/code&gt; may be something, nil, or an empty array depending on what you&amp;#8217;ve just done. For example, in this code I had tried &lt;code&gt;assert\_nil cookies['pass']&lt;/code&gt; but that failed because &lt;code&gt;cookies['pass']&lt;/code&gt; was &lt;code&gt;[]&lt;/code&gt; after calling &lt;code&gt;cookies.delete :pass&lt;/code&gt; in the controller:&lt;/p&gt;
&lt;pre&gt;&amp;lt;typo:code lang=&quot;ruby&quot;&amp;gt;
def test_destroy_should_remove_persistent_login_cookie
  post :create, :username =&amp;gt; 'brian.ford', :password =&amp;gt; 'secret', 
      :remember_me =&amp;gt; '1'
  pass = cookies['pass']
  
  @request.cookies['pass'] = cookies['pass']
  post :destroy, :_method =&amp;gt; 'delete'
  
  assert_no_cookie :pass
  user = User.find_by_username 'brian.ford'
  assert_nil user.persistent_logins.find_by_pass(pass)
end
&amp;lt;/typo:code&amp;gt;&lt;/pre&gt;
&lt;p&gt;Anyway, as before, you can get this by &lt;code&gt;script/plugin http://svn.planetargon.org/rails/plugins/assert_cookie&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And thanks yet again to &lt;a href=&quot;http://www.pluitsolutions.com/2006/08/02/rails-functional-test-with-cookie/&quot;&gt;Pluit Solutions&lt;/a&gt; for helping me keep my head straight about how to work with cookies in functional tests. Next stop, a patch for Rails (would a generous soul please donate some time to this so I don&amp;#8217;t have to).&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>assert_cookie for ooey gooey fun</title>
    <id>http://brixen.io/2006/8/27/assert_cookie-for-ooey-gooey-fun</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/27/assert_cookie-for-ooey-gooey-fun" />
    <published>2006-08-27T00:00:00-07:00</published>
    <updated>2006-08-27T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I love cookies. There are, of course, tons of varieties and I&amp;rsquo;m no connoisseur but I love the soft chocolate chip right out of the oven, hot and gooey. But, if you&amp;rsquo;re like me, you don&amp;rsquo;t want your Rails code to be gooey. &lt;/p&gt;

&lt;p&gt;Last Friday, after spending a good frustrating hour trying to figure out why my tests were failing with a nil when a cookie was expected, I finally tried a google search for &amp;ldquo;assert cookies&amp;rdquo;. (A lot of more detailed searches pulled up nothing but Java stuff, a not-so-subtle reminder that Ruby is not yet the dominant language out there.) Seems that &lt;a href=&quot;http://www.pluitsolutions.com/2006/08/02/rails-functional-test-with-cookie/&quot;&gt;Pluit Solutions&lt;/a&gt; ran into the same problem. This got me thinking that a nice custom assertion might be in order. Actually, I just wrote a quick helper because that was faster than trying to figure out why Rails wasn&amp;rsquo;t performing &lt;a href=&quot;http://api.rubyonrails.com/classes/Test/Unit/Assertions.html&quot;&gt;as advertised&lt;/a&gt;. But it kept bugging me, so I wrapped it up as a plugin. It&amp;rsquo;s still rough and tests are coming. Perhaps I&amp;rsquo;m putting too much into a single assertion. Install it with &lt;code&gt;script/plugin install http://svn.planetargon.org/rails/plugins/assert_cookie&lt;/code&gt;. And please send feedback.&lt;/p&gt;

&lt;p&gt;The idea is to allow various assertions about cookies using a hash of arguments. In particular, you can do such things as:&lt;/p&gt;

&lt;pre&gt;&lt;typo:code lang=&quot;ruby&quot;&gt;
assert_cookie :pass, 
    :value =&amp;gt; lambda { |value| UUID.parse(value).valid? }
assert_cookie :yellow, :value =&amp;gt; ['sunny', 'days']
assert_cookie :delight, :value =&amp;gt; 'yum'
assert_cookie :secret, :path =&amp;gt; lambda { |path| path =~ /secret/ }, 
    :secure =&amp;gt; true
&lt;/typo:code&gt;&lt;/pre&gt;
</content>
  </entry>
  
  <entry>
    <title>Patterns of dialogue</title>
    <id>http://brixen.io/2006/8/22/patterns-of-dialogue</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/22/patterns-of-dialogue" />
    <published>2006-08-22T00:00:00-07:00</published>
    <updated>2006-08-22T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Several weeks ago when &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; and I started discussing how to better interact with clients, one of our goals was a simpler, more effective process. From my experiences as a math student, I knew that a few carefully chosen symbols along with adherence to a fairly simple structure enabled folks from the world over, with different native languages and different cultures, to discuss mathematics, learn from each other, and understand the topics.&lt;/p&gt;

&lt;p&gt;The news press is another profession that makes excellent, effective use of a simple structure to interview people and elicit facts to reconstruct an event at which the reporter was not present. We have a rather high degree of confidence (depending on the media outlet) in the accuracy of the method.&lt;/p&gt;

&lt;p&gt;These, among other things, encouraged us to focus on the dialogue we have with our clients. We want to examine the dialogue without any special props or artifacts from a particular methodology. What can we accomplish as knowledgeable people, potentially having different vocabularies and areas of expertise, sitting around a table perhaps with paper and pencil? So far, we&amp;rsquo;ve mostly posted about these ideas. But our aim is to extend these ideas into identifying patterns of dialogue.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s one: You probably noticed that my posts tend to be pretty long. That&amp;rsquo;s because, just like the three paragraphs above, I usually try to take time to lay some groundwork, get on the same page. And this is often what I do when talking with someone as well. Perhaps a good name would be the &lt;em&gt;Misunderstanding Prevention Focused Long Intro&lt;/em&gt; dialogue pattern. The problem is, unless you&amp;rsquo;re pretty dedicated about paying attention, I might lose you before I get done painting the whole picture. A different pattern could focus on one small bit of the relevant topic, frequently check understanding, and build out the background to enhance understanding when necessary. To me, that pattern is much more like BDD and follows the principle of not solving a problem you haven&amp;rsquo;t yet encountered.&lt;/p&gt;

&lt;p&gt;Another thing we frequently observe is that any little feature of the software we&amp;rsquo;re building acts just like a spark in tinder, setting a client off on a runaway course of, &amp;ldquo;Wouldn&amp;rsquo;t it be cool if&amp;hellip;&amp;rdquo;. Attempting to blow out that flame before it derails the discussion, we often use totally irrelevant data that has less provocative affect. For example, in a recent prototype showing tagging features, we used names of food as tags, which have absolutely nothing to do with the application. The intent was to prevent the client from starting to think about the &amp;ldquo;right tags&amp;rdquo; and focus instead on the features of the tagging process.&lt;/p&gt;

&lt;p&gt;We are attempting that sort of process on a bigger scale with clients who seem naturally to obsess on features. We try to structure the dialogue about the user&amp;rsquo;s goals without referring to the software at all. At first glance, that may seem to increase the likelihood that we will misunderstand what the client wants. But, we find the reverse is true. Feature focus is more likely to contribute to misunderstanding what the client needs. And it prevents the client from learning as well.&lt;/p&gt;

&lt;p&gt;What patterns do you observe in your dialogue? When are they appropriate? What are you trying to change about your client interaction?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Ethical Software Needs Dialogue</title>
    <id>http://brixen.io/2006/8/16/ethical-software-needs-dialogue</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/16/ethical-software-needs-dialogue" />
    <published>2006-08-16T00:00:00-07:00</published>
    <updated>2006-08-16T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Growing up in the United States in the late 70&amp;rsquo;s, early 80&amp;rsquo;s, futbol was something I knew very little about. Let&amp;rsquo;s see, we played once in a great while in gym class, my most memorable experience there was taking a hard-kicked ball right in the face. Later in high school, the soccer team was a mere blip on the screen in the shadow of football and baseball. Much later I started playing soccer and, having so much fun, lament that I didn&amp;rsquo;t play as a kid. The interesting thing to me about soccer (and many games, but you&amp;rsquo;ll especially appreciate this if you listen to a soccer game on a hispanic radio station) is that the myriad plays and activities that make up the game are all directed toward scoring a goal (and preventing the opposing team from doing so). In other words, the goal of the game is simple and clear, though not easily achieved.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://jooto.com/blog/&quot;&gt;Alex Bunardzic&lt;/a&gt; is a champion of what he terms &amp;ldquo;ethical software&amp;rdquo;. The idea goes by many names. My favorite is software that doesn&amp;rsquo;t suck. I highly value Alex&amp;rsquo;s ideas, so when I read his recent post, &lt;a href=&quot;http://jooto.com/blog/index.php/2006/08/15/should-driven-development/&quot;&gt;Should-Driven Development&lt;/a&gt;, I couldn&amp;rsquo;t easily dismiss his criticisms of Behavior Driven Development. At the same time, I don&amp;rsquo;t agree that BDD itself is flawed as an approach to creating better software. BDD is a developer&amp;rsquo;s tool. It&amp;rsquo;s about coding. Of course, BDD cannot specify the goals of the software. So, if it is expected to, it will fail to produce software that doesn&amp;rsquo;t suck.&lt;/p&gt;

&lt;p&gt;One of the things about Scrum that I think is tremendously valuable, and yet one of those things that makes you say, &amp;ldquo;Duh!&amp;rdquo;, is the emphasis on empirical process control. There are three components to that: 1) observability, 2) inspection, and 3) adaptation.&lt;/p&gt;

&lt;p&gt;What both Scrum and BDD need to be effective is a clear and accurate statement of the goals. With a goal-directed process you have these components: &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;somewhere you are trying to get to (using a geographic metaphor)&lt;/li&gt;
  &lt;li&gt;some process that accurately compares where you are at with where you want to go&lt;/li&gt;
  &lt;li&gt;a plan to move you incrementally closer to where you want to go&lt;/li&gt;
  &lt;li&gt;a process to evaluate whether your plan got you any closer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or more briefly: goal, assessment, plan, implementation, feedback and around again and again.&lt;/p&gt;

&lt;p&gt;The practice of BDD captures this well. Write the test to capture the expected behavior of the system relative to the goal. The test fails. Write the &lt;em&gt;minimum&lt;/em&gt; code necessary to make the test pass. Refactor. And around. The process alternates between writing new tests to describe expected behavior and the code to make the test pass and then refactoring to make the code better without changing its behavior. The process is powerful.&lt;/p&gt;

&lt;p&gt;But as I said earlier, it is a developer&amp;rsquo;s tool. Developers should never be specifying the goals for the software, just as the client and user should never be specifying the implementation. I&amp;rsquo;m rarely dogmatic, but about that I will be.&lt;/p&gt;

&lt;p&gt;The problem that we face is how we can more accurately capture the goals for the software in our dialogue with the clients and users. Our exploration of that is what we are calling &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/08/08/d3-not-ddd&quot;&gt;d3&lt;/a&gt;. One significant part of that is education. Our experience is that &lt;em&gt;everyone&lt;/em&gt; from clients to developers begins thinking and talking in terms of the software implementation way, way too early. It&amp;rsquo;s like talking to an architect about what finishes to use and what the windows look like long before you have established a vague idea of where the walls will be or if there will even be walls. The process is too often backwards. Talking about the minutiea of text field this and that before we have even established why in the world the user would be doing that in the first place. One approach that we are trying is dialoguing with the client about goals without talking at all about the web site. In other words, for that exploration, the web site doesn&amp;rsquo;t even exist. Talk about thinking outside the tubes.&lt;/p&gt;

&lt;p&gt;Another part of this is fostering a general respect for that fact that software that doesn&amp;rsquo;t suck is constructed according to certain principles. Just because anyone can create an HTML form doesn&amp;rsquo;t mean they should. As long as we collectively persist in thinking that &lt;em&gt;anything&amp;rsquo;s possible&lt;/em&gt; and therefore it all boils down to a matter of opinion about software design, we will continue to create software that sucks.&lt;/p&gt;

&lt;p&gt;So rather than putting down BDD for failing, we need to recognize that right now in the state of our craft there is a huge chasm between client interaction to establish goals for the software and the much lower level development that can excel through application of BDD.&lt;/p&gt;

&lt;p&gt;What we need to develop is how to dialogue to create common understanding. What I am noticing as I try hard to be more aware of how we are communicating with clients is that &amp;ldquo;process&amp;rdquo; and &amp;ldquo;process artifacts&amp;rdquo; can often be counter-productive and obscure issues. If we are just trying to &amp;ldquo;fill in&amp;rdquo; the boxes in our process, are we stopping to really listen? It&amp;rsquo;s like assertiveness training where you are taught to reframe your expressions using &amp;ldquo;I&amp;rdquo; statements. Rather than, &amp;ldquo;you are really pissing me off&amp;rdquo; someone might as an initial stab try &amp;ldquo;I feel like you are really pissing me off&amp;rdquo;. Yeah, not very effective. Try that with your girlfriend if you don&amp;rsquo;t believe me. More effective is, &amp;ldquo;I feel hurt when you say you don&amp;rsquo;t want to play with my new Mephisto blog.&amp;rdquo; One approach attempts to conform to the structure of assertiveness, one effectively conforms to the principles. What are the principles of effective dialogue?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>not Scrum.equal :product_backlog</title>
    <id>http://brixen.io/2006/8/10/not-scrum-equal-product_backlog</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/10/not-scrum-equal-product_backlog" />
    <published>2006-08-10T00:00:00-07:00</published>
    <updated>2006-08-10T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I think it&amp;rsquo;s obvious to everyone that Scrum and the product backlog are not the same thing. Sometimes stating the obvious is useful. Scrum is a structured process of which the product backlog is a part. &lt;a href=&quot;http://mechanismalley.com/blog&quot;&gt;Mechanism Alley&lt;/a&gt; has posted an excellent, thoughtful &lt;a href=&quot;http://mechanismalley.com/blog/2006/08/06/what-is-scrum/&quot;&gt;article&lt;/a&gt; about Scrum with some references to some of what we&amp;rsquo;ve been saying about &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/08/08/d3-not-ddd&quot;&gt;d3&lt;/a&gt;. It&amp;rsquo;s worth a careful read. In fact, I want to personally thank &lt;a href=&quot;http://mechanismalley.com&quot;&gt;MSM&lt;/a&gt; for not perceiving our comments as an invitation to start flaming about this or that pet methodology.&lt;/p&gt;

&lt;p&gt;I certainly don&amp;rsquo;t want our conversations about Scrum to be alienating to any of the excellent folks working hard under the agile umbrella. Further, I don&amp;rsquo;t want Scrum only to be the focus of these conversations. Finally, I&amp;rsquo;m not particularly interested in pumping another meme through the well-oiled Rails machine. Are we restating things said by others? Hell yes! We are standing on the shoulders of giants.&lt;/p&gt;

&lt;p&gt;What I find a bit disturbing is that while I said a &lt;a href=&quot;http://blog.brightredglow.com/articles/2006/08/06/one-cuckoo-flew-over-the-nest&quot;&gt;number of things&lt;/a&gt; about Scrum, only what &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; and I have said about the product backlog is getting attention. Further, the responses seem to fall generally into three categories:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;the literature we read misrepresented the Scrum process&lt;/li&gt;
  &lt;li&gt;we have misunderstood the literature&lt;/li&gt;
  &lt;li&gt;the way the commenter uses the product backlog involves a lot of conversation, not a lot of dictation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Firstly, the book I referred to, &lt;em&gt;Agile Project Management with Scrum&lt;/em&gt; by Ken Schwaber seems to be a good source. It seems consistent with everything knowledgeable people have posted about Scrum. And it clearly advocates agile methods. Consider this quote:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You can get through almost anything if you don&amp;rsquo;t try to impose rigid solutions before problems even arise, instead devising solutions as necessary when problems crop up. (pg 131)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That&amp;rsquo;s from chapter 9, &lt;em&gt;Scaling Projects Using Scrum&lt;/em&gt;, which described application of Scrum to a difficult project and discussed solutions implemented in the spirit of Scrum but rather far outside of a &amp;ldquo;typical&amp;rdquo; Scrum process (if such could be argued to exist).&lt;/p&gt;

&lt;p&gt;Secondly, we are not claiming to be Scrum experts, but that said, I don&amp;rsquo;t think I&amp;rsquo;m misunderstanding the literature. What we are aiming at are things that we think could be better understood and articulated. Just like the agile manifesto doesn&amp;rsquo;t prescribe a &amp;ldquo;right&amp;rdquo; way, it&amp;rsquo;s clear there are many implementations of agile processes. At the same time, the agile manifesto is certainly opinionated about certain processes being preferred for (and I would go as far as saying essential to) effectively creating software.&lt;/p&gt;

&lt;p&gt;Thirdly, commenters that relate, in their experience, how much conversation is required around and facilitated by the product backlog are contributing to our confidence that there is a lot to say and understand about the dialogues we are having. Further, we are really interested in dialogues we are having with clients. We are finding this to be very challenging at best.&lt;/p&gt;

&lt;p&gt;As Robby recently pointed out in a conversation with me, development processes often seem geared toward making the developers look good based on all the items they&amp;rsquo;ve checked off the list of the client&amp;rsquo;s wants. &amp;ldquo;See, we&amp;rsquo;ve delivered everything you&amp;rsquo;ve asked for, and on time even!&amp;rdquo; Yet through these processes, we (collectively) continue to successfully create software that sucks! We think that&amp;rsquo;s because it&amp;rsquo;s extraordinarily challenging to get processes to be goal directed based on &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/08/06/clients-deserve-simplicity&quot;&gt;requirements versus solutions&lt;/a&gt;. The way we get to this is through a lot of dialogue. We want to better understand the process and patterns of this dialogue.&lt;/p&gt;

&lt;p&gt;And, ultimately, whether you are using Scrum or some other process under the agile umbrella, knowledge of how to conduct and facilitate this dialogue will be extremely valuable to you. So, please help us understand how you dialogue. If the product backlog is an artifact in this, please help us understand how?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Rails' future is bright indeed, bright like the sun</title>
    <id>http://brixen.io/2006/8/7/rails-future-is-bright-indeed-bright-like-the-sun</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/7/rails-future-is-bright-indeed-bright-like-the-sun" />
    <published>2006-08-07T00:00:00-07:00</published>
    <updated>2006-08-07T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;If you don&amp;#8217;t get a chance to hang out on our irc channel much (#planetargon on irc.freenode.net), you may have missed some of the innovations on the horizon for Rails: We&amp;#8217;ll let you know when the nuclear-powered Rails beta is up for testing.&lt;/p&gt;
&lt;p&gt;Anyway, Happy Birthday Rails!&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;
&lt;p&gt;.utterance {&lt;br /&gt;
	color: palegoldenrod;&lt;br /&gt;
	font-size: 11pt;&lt;br /&gt;
}&lt;br /&gt;
.time {&lt;br /&gt;
	color: slategray;&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
	font-family: sans-serif;&lt;br /&gt;
	font-size: 10pt;&lt;br /&gt;
}&lt;br /&gt;
.tacodog, .harrisj, .lanaer, .dgibbons, .brixen, .tshine {&lt;br /&gt;
	font-family: sans-serif;&lt;br /&gt;
	font-size: 11pt;&lt;br /&gt;
	width: 7em;&lt;br /&gt;
}&lt;br /&gt;
.tacodog {&lt;br /&gt;
	color: cornflowerblue;&lt;br /&gt;
}&lt;br /&gt;
.harrisj {&lt;br /&gt;
	color: orange;&lt;br /&gt;
}&lt;br /&gt;
.brixen {&lt;br /&gt;
	color: mediumslateblue;&lt;br /&gt;
}&lt;br /&gt;
.lanaer {&lt;br /&gt;
	color: mediumseagreen;&lt;br /&gt;
}&lt;br /&gt;
.tshine {&lt;br /&gt;
	color: yellow;&lt;br /&gt;
}&lt;br /&gt;
.dgibbons {&lt;br /&gt;
	color: lightgreen;&lt;br /&gt;
}&lt;br /&gt;
.block {&lt;br /&gt;
	width: 500px;&lt;br /&gt;
	padding: 8px;&lt;br /&gt;
	background-color: black;&lt;br /&gt;
}&lt;/p&gt;
&lt;/style&gt;
&lt;div class=&quot;block&quot;&gt;
&lt;p&gt;&lt;span class=&quot;time&quot;&gt;12:24&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;hrm. there are 3ppb of uranium in seawater.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:24&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;4.5b estimated tons of uranium in the ocean&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:24&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;even more thorium.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:25&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;the uranium alone could power the world for the next 6500 years.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:26&lt;/span&gt;  &lt;span class=&quot;harrisj&quot;&gt;* harrisj&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;hatches a world-domination scheme&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:41&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;you know how i came across all this? one day i was eating crab with the wife&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;i looked over and saw a pile of crabshells&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;wondered what it could be used for&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;chitin is the second most common organic substance in the world. second only to cellulose&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;and one of the things you can do with chitin is to clean water.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;sewer water&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;harrisj&quot;&gt;harrisj&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;what about keratin?&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:42&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;it absorbs metals&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:43&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;dunno.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:43&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;but chitin is crabs, insects, etc.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:43&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;so, it absorbs metals in water&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:43&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;uranium, titanium adn thorium are dissolved in seawater&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:43&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;so&amp;#8230; i started doing some research&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:44&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;a japanese scientist &amp;#8216;mined&amp;#8217; yellow cake from the ocean&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:44&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;amazing&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:44&lt;/span&gt;   &lt;span class=&quot;harrisj&quot;&gt;harrisj&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;tacodog: wow&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:45&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;more thorium than uranium in seawater&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:45&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;more expensive to use thorium in a reactor, but it&amp;#8217;s possible&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:45&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;and&amp;#8230; pair this with pebble bed reactors&amp;#8230;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:45&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;and you got yourself a bidness&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:46&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;sorry, i&amp;#8217;m a nerd. i admit it. this fascinates me.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:47&lt;/span&gt;   &lt;span class=&quot;lanaer&quot;&gt;lanaer&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;bah, no apologies.&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:47&lt;/span&gt;   &lt;span class=&quot;lanaer&quot;&gt;lanaer&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;just keep adding to the interesting tidbits of info I come across in my day :)&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:47&lt;/span&gt;   &lt;span class=&quot;dgibbons&quot;&gt;dgibbons&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;yeah this is much better then the talk in my other channels&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;12:48&lt;/span&gt;   &lt;span class=&quot;lanaer&quot;&gt;lanaer&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;heh&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:49&lt;/span&gt;   &lt;span class=&quot;brixen&quot;&gt;brixen&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;tacodog: thanks, now #planetargon just bubbled to the top of the list at &lt;span class=&quot;caps&quot;&gt;NSA&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:49&lt;/span&gt;   &lt;span class=&quot;brixen&quot;&gt;brixen&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;they&amp;#8217;re busily researching everybody&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:51&lt;/span&gt;   &lt;span class=&quot;brixen&quot;&gt;brixen&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;but I like the idea: get your own nuclear powered rails app :P&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;   &lt;span class=&quot;brixen&quot;&gt;brixen&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;rails on uranium, or thorium&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;   &lt;span class=&quot;tshine&quot;&gt;tshine&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;nuclear powered rails aparams&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;   &lt;span class=&quot;tshine&quot;&gt;tshine&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;opps&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;   &lt;span class=&quot;tacodog&quot;&gt;tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;hahaha&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;   &lt;span class=&quot;tshine&quot;&gt;tshine&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;nuclear powered rails on a 9-volt budget&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:52&lt;/span&gt;  &lt;span class=&quot;tacodog&quot;&gt;* tacodog&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;is back from lunch&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:53&lt;/span&gt;   &lt;span class=&quot;tshine&quot;&gt;tshine&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;my hotkey proggy inserted that little tidbit :( &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;time&quot;&gt;13:53&lt;/span&gt;   &lt;span class=&quot;dgibbons&quot;&gt;dgibbons&lt;/span&gt; &lt;span class=&quot;utterance&quot;&gt;your rails app generates enough power you can sell it back to the power company&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;</content>
  </entry>
  
  <entry>
    <title>One cuckoo flew over the nest</title>
    <id>http://brixen.io/2006/8/6/one-cuckoo-flew-over-the-nest</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/6/one-cuckoo-flew-over-the-nest" />
    <published>2006-08-06T00:00:00-07:00</published>
    <updated>2006-08-06T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Firstly, a disclaimer in the words of the inimitable Ken Kesey:
&amp;gt;Take what you can use and let the rest go by.&lt;/p&gt;

&lt;p&gt;Interestingly, when I googled this quote to ensure I was recalling it correctly, I found some other &lt;a href=&quot;http://en.wikiquote.org/wiki/Ken_Kesey&quot;&gt;excellent quotes&lt;/a&gt;. Another that seems apropos:
&amp;gt;You don&amp;rsquo;t plow under the corn because the seed was planted with a neighbor&amp;rsquo;s shovel.&lt;/p&gt;

&lt;p&gt;If Dialog Driven Development is merely &lt;a href=&quot;http://mechanismalley.com/blog/2006/08/04/on-product-backlogs/&quot;&gt;rounded corners&lt;/a&gt; to you, please continue to enjoy your square ones. This exploration is not aimed at gathering the true believers. I&amp;rsquo;m not the evangelist type. So, if you&amp;rsquo;re worried I&amp;rsquo;ll show up on your doorstep thumping my bible, rest assured I won&amp;rsquo;t. I&amp;rsquo;m an atheist.&lt;/p&gt;

&lt;p&gt;That said, I think there is value in creating distinctions to better understand the terrain. Agile is a big umbrella. If the processes were formulaic, all we would need to worry about is a good algorithm. &lt;/p&gt;

&lt;p&gt;Recently on a flight to DC to meet with a new client, I delved into a book &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; brought along: &lt;em&gt;Agile Project Management with Scrum&lt;/em&gt; by Ken Schwaber, one of the co-founders of the Scrum method. Below are a few notes I jotted down on my index cards while reading the first 4 chapters and browsing the appendices. Since then I&amp;rsquo;ve browsed some of the other chapters but I haven&amp;rsquo;t finished the book. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;advantages of Scrum&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;emphasis on empirical process control&lt;/li&gt;
  &lt;li&gt;iterations&lt;/li&gt;
  &lt;li&gt;daily team meetings where each member presents what she did in the past 24 hours, what she&amp;rsquo;ll do in the next 24 hours, and any blockers&lt;/li&gt;
  &lt;li&gt;frequent feedback loop&lt;/li&gt;
  &lt;li&gt;clear separation of responsibility using the pigs and chickens metaphor to facilitate more effective decision making and reduce interference by chickens, which can bog down the process&lt;/li&gt;
  &lt;li&gt;The three legs that hold up the implementation of empirical process control: 1) visibility - aspects that affect the outcome must be visible to those controlling the process; 2) inspection - these aspects must be inspected frequently enough to change course if necessary before too much has elapsed; and 3) adaptation - changing course when new information suggests it is necessary&lt;/li&gt;
  &lt;li&gt;emphasis on having a &lt;em&gt;vision&lt;/em&gt;, it must be a vision that is fairly resistant to change in order to guide the project, but able to change when required&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&amp;rdquo;&lt;em&gt;You can get through almost anything if you don&amp;rsquo;t try to impose rigid solutions before problems even arise, instead devising solutions as necessary when problems crop up.&lt;/em&gt;&amp;rdquo; (page 131)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;drawbacks to Scrum&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;specifying the product backlog - this suggests too much &lt;em&gt;dictation&lt;/em&gt; and not enough &lt;em&gt;collaboration&lt;/em&gt;. According to the book, the product owner specifies the backlog and prioritizes the items in it. The team meets to decide which items it can deliver in the next sprint. That process is two monologues not a dialogue.&lt;/li&gt;
  &lt;li&gt;30-day sprint is too long. I don&amp;rsquo;t think the feedback cycle is nearly as effective at this scale because we need feedback long before functionality is &amp;ldquo;deliverable&amp;rdquo;. More frequent testing is needed to refine features. Imagine getting a haircut where you tell the stylist what you want. She then takes you to a room with no mirrors and starts chopping away. When she&amp;rsquo;s done she takes you to another room to demo your new haircut. Fortunately, the difference between a bad haircut and a good one is about 2 weeks. The same is hardly true of software.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process of software development requires a lot of educating of the people involved. The product backlog does not encourage thinking in this way. I dislike the sequential list where the only explicit organizing idea is priority. Where is the context and relation between what is being specified? And how does the process ensure that the product owner doesn&amp;rsquo;t fall back to specifying things like, &amp;ldquo;Dialog X needs a dropdown field to display Y&amp;rdquo;, or &amp;ldquo;Build a screen to display user stats&amp;rdquo;? If you haven&amp;rsquo;t had to deal with this, then I desperately want to come visit your universe. If you don&amp;rsquo;t know why this is the biggest ingredient in a recipe for disaster, just continue building software this way.&lt;/p&gt;

&lt;p&gt;The way to challenge this is with true, effective dialogue. What that looks like varies a lot. But it&amp;rsquo;s not about particular artifacts. If you read &lt;a href=&quot;http://mechanismalley.com/blog/about/&quot;&gt;Manley&amp;rsquo;s&lt;/a&gt; criticism of our &lt;a href=&quot;http://mechanismalley.com/blog/2006/08/04/on-product-backlogs/&quot;&gt;rounded corners&lt;/a&gt;, he relates the necessity of educating product owners. If dialogue is at the center of your process, the product backlog could function as a passable way to document the evolving mutual understanding.&lt;/p&gt;

&lt;p&gt;My favorite idiocy in software development is the crystal ball method. Everyone has a crystal ball on their desks from which they can conjure a precise, detailed, perfectly focused picture of any event at any point in the future. Of course, this is an absolute absurdity. But that doesn&amp;rsquo;t stop people from believing such feats are possible. The product backlog easily falls prey to this delusion.&lt;/p&gt;

&lt;p&gt;A much more useful metaphor is based on the simple fact of vision that any sighted person can appreciate. From where I stand, there are a number of things in crisp focus. Beyond that, things are mostly distinguishable by shape and relationship. I&amp;rsquo;m seeing the forest. Beyond that, only the vaguest, broadest features are distinguishable. I see that mountain, but the dark areas juxtaposing the snow may be forest or exposed rock. I can&amp;rsquo;t tell.&lt;/p&gt;

&lt;p&gt;Attempting to draw on this fact of vision to inform and structure dialogue about a recent project, we set up a wiki with a page to capture descriptions of the software&amp;rsquo;s behavior in terms of goals. We have three sections: 1) near term goals, 2) medium range goals, and 3) long range goals. These follow the rough divisions of visual clarity described above.&lt;/p&gt;

&lt;p&gt;The process of transforming those goals into software features and determining their priority based on architectural constraints is &lt;strong&gt;not&lt;/strong&gt; something a client can dictate. You don&amp;rsquo;t tell your architect how to construct your house, you describe what you want in it. The reason for that is simple: physics dictates what is a viable structure. In software, we have no appreciation for physics. Clients believe they can do anything. All the rusting hulks of failed software littering the desert notwithstanding.&lt;/p&gt;

&lt;p&gt;The essential way to bring the analogue of physics to software development is mutual education mediated by effective dialogue. What that actually looks like needs a great deal of definition. If this is just rounded corners on existing work, please point us in the right direction.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>It's all about the dialogue</title>
    <id>http://brixen.io/2006/8/4/its-all-about-the-dialogue</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/4/its-all-about-the-dialogue" />
    <published>2006-08-04T00:00:00-07:00</published>
    <updated>2006-08-04T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.martinfowler.com&quot;&gt;Martin Fowler&lt;/a&gt; is a paradox. That is, if you accept one of the common connotations of &amp;ldquo;enterprise software&amp;rdquo;: evil. &amp;ldquo;I concentrate on designing enterprise software – looking at what makes a good design and what practices are needed to come up with good design.&amp;rdquo;, says Martin. Yet, he is one of the giants of agile software development. Recently, at the second annual &lt;a href=&quot;http://oscamp.org/FOSCON&quot;&gt;foscon&lt;/a&gt;, I won a raffle for a book. The one I selected from those available was Martin&amp;rsquo;s &lt;em&gt;Patterns of Enterprise Application Architecture&lt;/em&gt;. If you have not yet listened to his &lt;a href=&quot;http://blog.scribestudio.com/articles/2006/07/03/martin-fowler-railsconf-2006-keynote-address&quot;&gt;RailsConf 2006 Keynote&lt;/a&gt;, I strongly urge you to do so.&lt;/p&gt;

&lt;p&gt;A couple days ago, &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; posted about &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/08/02/dialogue-driven-development&quot;&gt;Dialogue Driven Development&lt;/a&gt;. We&amp;rsquo;ll leave it to the art historians to decide if the following artifact proves that while sitting together at Martin&amp;rsquo;s talk during RailsConf 2006, I first wrote the words, or jotted them down after Robby summarized one of Martin&amp;rsquo;s points. Robby often encourages &amp;ldquo;blog early, blog often&amp;rdquo;. So I can hardly complain if he pre-empted me on publishing DDD since RailsConf was over six weeks ago.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.brightredglow.com/assets/2006/10/3/ddd_small.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The important thing is that DDD is not just another marketing term. Although, it could be useful as one, so we want to distinguish between &lt;strong&gt;dialog&lt;/strong&gt;, those artifacts from desktop applications that we on the web infrequently encounter, and &lt;strong&gt;dialogue&lt;/strong&gt;, &lt;em&gt;n. a discussion between two or more people or groups, esp. one directed toward exploration of a particular subject or resolution of a problem&lt;/em&gt; (from my dashboard dictionary).&lt;/p&gt;

&lt;p&gt;For me, the &lt;em&gt;-ue&lt;/em&gt; is all about user experience. And that is the meat and potatoes of application development that we should be targeting. Don&amp;rsquo;t believe me? Think it&amp;rsquo;s more about business logic, fancy technology, web 2.0, &amp;lt;insert favorite CS concept here&amp;gt;? I don&amp;rsquo;t think so. But, don&amp;rsquo;t take my word for it. You too can pre-empt me on a coming post by heading over and reading, if you have not, Alan Cooper, &lt;em&gt;About Face: The Essentials of User Interface Design&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, DDD. What we&amp;rsquo;re trying to do is label a concept that is sorely in need of development. To flesh it out a bit from my perspective, here are a few points from Martin&amp;rsquo;s keynote that I found particularly interesting.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;martin_keynote.points.each do |point|&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
&lt;ul&gt;&lt;li&gt;The interesting thing about Rails is that it tries to do things differently than other software over the last few years. It doesn't try to be the one-size-fits-all solution.&lt;/li&gt;

&lt;li&gt;What we are seeing is a drive toward simplicity. Conventional wisdom once was &quot;quick necessarily means dirty&quot;. Ruby challenges that. As did Smalltalk, which showed that you could be quick and clean.&lt;/li&gt;

&lt;li&gt;What's important about technology is the way it affects the whole conversation between customer and developers. It affects how we go about building software. The essence of XP from Kent Beck is this change in relationship so it is not a one way stream of &quot;this is what I want&quot;: want -&amp;gt; tell -&amp;gt; build -&amp;gt; all is well. People may know what they want, but not what they need. We can build exactly what they want and still fail because it is not what they need.&lt;/li&gt;


&lt;pre&gt;&lt;code&gt;end&lt;/code&gt;&lt;/pre&gt;

It was after jotting down that last note that I wrote &quot;dialog-based develepment&quot; and then &quot;dialog driven development&quot; in my notes (I know, I misspelled it, too). The DDD term was prompted by the recent conversations [Jeremy](http://www.jvoorhis.com) and I had with [Steven Baker](http://blog.lavalamp.ca/) and [David Goodlad](http://david.goodlad.ca/) on the train to Chicago about Behavior Driven Development as they worked a bunch on a next-generation RSpec.

My pie in the sky is a Ruby DSL something like RSpec that could be used with clients to talk about the software. It would allow a spectrum from less specific-more tolerant to more-specific-less tolerant. At the left end is client dialogue about behavior of the software. Something like, &quot;app should require login&quot;. A &quot;failure&quot; at this high level could be something like, _not implemented_. The spectrum continues down to the level of BDD with something like RSpec, where the focus is on behavior of the code.

Also on the train, [Josh Knowles](http://joshknowles.com/) was strongly advocating for much better acceptance testing. Of course, using iterative development, acceptance testing is not something done at the end, months or years into the project, but should be done frequently. The left end of the spectrum could support this _expectation based software behavior dialogue_.

Of course, these are very rough ideas. What I want to do is build out the understanding behind the word &quot;collaboration&quot; in the [Agile Manifesto](http://www.agilemanifesto.org) and identify how &quot;individuals and interactions&quot; work to create excellent software. Join the fun!
&lt;/ul&gt;&lt;/blockquote&gt;
</content>
  </entry>
  
  <entry>
    <title>Is there room for a good Samaritan in the face of the spam deluge</title>
    <id>http://brixen.io/2006/8/3/is-there-room-for-a-good-samaritan-in-the-face-of-the-spam-deluge</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/8/3/is-there-room-for-a-good-samaritan-in-the-face-of-the-spam-deluge" />
    <published>2006-08-03T00:00:00-07:00</published>
    <updated>2006-08-03T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;We all love the spluge (spam deluge), don&amp;rsquo;t we? Usually spam is so abnoxiously and obviously stupid it is easy to ignore. And, gmail does a wonderful job of ensuring I deal with very little of it. However, once in a while something comes through. A trend I&amp;rsquo;ve noticed recently are emails that begin with &amp;ldquo;This is an advertisement&amp;hellip;&amp;rdquo; I&amp;rsquo;ve never read one careful but it&amp;rsquo;s possible, but unlikely, that I somehow asked to receive it.&lt;/p&gt;

&lt;p&gt;Today, I got an odd email. I first thought to dismiss it, but upon reading it I decided it was either the best crafted bit of spam, or an honest mistake. Then I was faced with a decision: round-file it, or be a good Samaritan and let the guy know. Here&amp;rsquo;s the email:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Subject: travel to Missoula&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Thanks for getting the reservation at Downtown Motel.  The fellow I talked to said &amp;ldquo;no available rooms the entire weekend&amp;rdquo;.  I&amp;rsquo;ll put &amp;gt;it on my credit card when I get there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I&amp;rsquo;ve encountered another problem with scheduling.  I ordered my airline tickets through Priceline.Com and now they tell me there is no record of my order.  The airlines now want about $400 more because of the short notice.  Consequently, I&amp;rsquo;m going to drive and will pick up Quincy and your mother.  We will arrive sometime late Friday and stay through Sunday.  See you then.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;code&gt;                                    Love,  Uncle John
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ultimately, I decided to reply:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hi John,&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;I&amp;rsquo;m sorry, but you&amp;rsquo;ve reached the wrong email box.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Forgive my suspicion, but if you do happen to be a spammer and are using this as a ploy to get a response from this email address, rest assured a real person lives here and I&amp;rsquo;ll haunt your sleep forever if you continue to spam me. However, also note that, if you are a spammer, all your future spam will flutter totally un-noticed by me into my big circular bit bucket to live out eternity in utter unacknowledgement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Hope the trip goes well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cheers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What do you think&amp;ndash;was it spam? Would you have replied? The analogy is walking down the city street, only talking to our friends, eyeing with suspicion and from a distance any stranger we happen across. Do we need to recreate this dynamic on the tubes (pipes? I forget) as well, or can we allow for greater friendliness?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Good user experience design is like chicken-sexing</title>
    <id>http://brixen.io/2006/7/23/good-user-experience-design-is-like-chicken-sexing</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/7/23/good-user-experience-design-is-like-chicken-sexing" />
    <published>2006-07-23T00:00:00-07:00</published>
    <updated>2006-07-23T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;To paraphrase &lt;a href=&quot;http://www.webvisionsevent.com/speakers/detail/?spkloc=spool_jared&quot;&gt;Jared Spool&lt;/a&gt;, who gave the closing &lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=jared_spool_keynote&quot;&gt;keynote&lt;/a&gt; at &lt;a href=&quot;http://www.webvisionsevent.com/&quot;&gt;webvisions (2006)&lt;/a&gt;, designing compelling user experience is something that can be learned, but there&amp;rsquo;s no good understanding of how it works. To illustrate this phenomenon, Jared refers to &lt;a href=&quot;http://en.wikipedia.org/wiki/Chicken_sexer&quot;&gt;chicken-sexing&lt;/a&gt;. You can &lt;a href=&quot;http://www2.dpi.qld.gov.au/poultry/15032.html&quot;&gt;read up&lt;/a&gt; on it, but the basic idea is that to run a cost-effective chicken farm, you need to know the gender of the chicks about 2-3 weeks before any known mechanized process can successfully do so. The solution is to rely on professionals that watch the chicks go by and identify them as male or female.&lt;/p&gt;

&lt;p&gt;Consider the ipod and netflix as two examples of compelling user experience despite, according to Jared, the former having inferior technology compared to competitor offerings and the latter not having any brick-and-mortar storefronts or any customer service other than through their website. Even so, the ipod is wildly more popular than any other portable music player, and Netflix membership dwarfs that of Blockbusters recent through-the-mail dvd rental service.&lt;/p&gt;

&lt;p&gt;Obviously, there is great advantage to being able to learn good user experience design. And that was one of Jared&amp;rsquo;s main points. It can be learned. This is supported by current research. Consider an article in the August 2006 issue of &lt;em&gt;Scientific American&lt;/em&gt;, &amp;ldquo;The Expert Mind&amp;rdquo;. Research into chess masters indicates that there is little actual contribution by &amp;ldquo;talent&amp;rdquo;. Rather these folks&amp;rsquo; mastery consists primarily of categorizing a huge amount of knowledge of fruitful moves given the configuration of piece on the board.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Effortful study&lt;/strong&gt; is the key to achieving success in chess, classical music, soccer and many other fields. New research has indicated that motivation is a more important factor than innate ability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One key to effortful study is constantly pushing yourself to reach just beyond your current abilities. This is good news for those of us who have never felt we are natural born chicken-sexers.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Having a blast at webvisions 2006</title>
    <id>http://brixen.io/2006/7/21/having-a-blast-at-webvisions-2006</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/7/21/having-a-blast-at-webvisions-2006" />
    <published>2006-07-21T00:00:00-07:00</published>
    <updated>2006-07-21T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I have had the good fortune of being sent to &lt;a href=&quot;http://www.webvisionsevent.com/&quot;&gt;webvisions (2006)&lt;/a&gt; by &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;. I have it on good authority that this year it is much larger than last year. It&amp;rsquo;s two days long and chock-full of great talks. &lt;/p&gt;

&lt;p&gt;So far, I have attended:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=professional_blogging&quot;&gt;Becoming a Professional Blogger&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=people_business&quot;&gt;People and Business: A Global Perspective&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=blogging_panel&quot;&gt;Practical Business Blogging Panel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=anthrodesign&quot;&gt;Designing for Socal Sharing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=design_patterns&quot;&gt;Design Patterns for the Web&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.webvisionsevent.com/schedule/detail/?evtloc=mobile_development_panel&quot;&gt;Mobile Development Panel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &amp;ldquo;People and Business&amp;rdquo; panel was a very interesting, if Portland-specific, look at government and industry participating to create and promote business. This was a bit unusual, I thought, since folks have come from all over to attend the conference. At the same time, it was intriguing to hear, especially from the Portland Development Commission, some things that may distinguish Portland as a hospitable environment for technology innovation. By coincidence, I think, the Portland City Council had voted just the night before to move forward with plans to build a free, public Wi-Fi blanket in Portland.&lt;/p&gt;

&lt;p&gt;My favorite talk by far was &amp;ldquo;Designing for Social Sharing&amp;rdquo;. I recommend checking out &lt;a href=&quot;http://www.rashmisinha.com/&quot;&gt;Rashmi&amp;rsquo;s site&lt;/a&gt;. She was a vibrant, engaging, knowledgeable speaker. One of the most interesting points is that to create a successful site for social sharing, we need an object around which people can share. Now that we have sites like &lt;a href=&quot;http://www.flickr.com&quot;&gt;Flickr&lt;/a&gt;, this seems like a no-brainer. But when we view how &amp;ldquo;social networking&amp;rdquo; sites have progressed from 1st generation, where the emphasis was only on the social network, we see how important this idea is. To paraphrase her, people don&amp;rsquo;t just connect for the sake of connecting, they connect over &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A big component of a successful site that encourages people to share is providing a way for people to contribute their own creativity or personality. In effect, the design of these sites must facilitate the user&amp;rsquo;s ability to influence the design. Interestingly, I have recently been reading, &lt;em&gt;A Pattern Approach to Interaction Design&lt;/em&gt;, by Jan Borchers. The author goes to some length to present a more full exposition of Alexander&amp;rsquo;s ideas on patterns. There is a lot of use of &amp;ldquo;patterns&amp;rdquo; this-or-that in various domains. To some extent, the word is often just stretched to cover a favorite concept. But the following quote seems particularly relevant in the context of a social sharing site:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every place is given its character by certain patterns of events that keep on happening there. These patterns of events are always interlocked with certain geometric patterns in the space.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Christopher Alexander, &lt;em&gt;The Timeless Way of Building&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this quote is nicely relevant to designers of such sites:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Interestingly, Alexander&amp;rsquo;s ideas were not always received well by his colleagues. One reason for this is that Alexander&amp;rsquo;s concepts empowered the inhabitants, supplying them with more ways to influence the building process, and taking much of that power out of the hands of the professional. Obviously, this idea was not very popular among architects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jan Borchers, &lt;em&gt;A Pattern Approach to Interaction Design&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another excellent talk was &amp;ldquo;Design Patterns for the Web&amp;rdquo; by a guy from eBay and another from Yahoo!. A nice serendipity: I recently have been re-reading, &lt;em&gt;About Face: the essentials of user interface design&lt;/em&gt;, by Alan Cooper. This book was awesome when I first read it years ago, and even today I&amp;rsquo;m amazed it is copyright 1995. Unfortunately, the content seems to be little-known in the web design world. Not at Yahoo! It appears to be very much an inspiration, as I will explain a bit more in a later post.&lt;/p&gt;

&lt;p&gt;Okay, that&amp;rsquo;s it for now. I&amp;rsquo;ll mine my notes for juicy tidbits and snippet to share with you. Admittedly, I&amp;rsquo;m not a good liveblogger. :-/&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The "real world" can eat my shorts</title>
    <id>http://brixen.io/2006/7/20/the-real-world-can-eat-my-shorts</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/7/20/the-real-world-can-eat-my-shorts" />
    <published>2006-07-20T00:00:00-07:00</published>
    <updated>2006-07-20T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Yesterday, &lt;a href=&quot;http://www.robbyonrails.com&quot;&gt;Robby&lt;/a&gt; messaged me that he was invited to be a speaker at Sys-Con Rails Conference. (Sorry, I&amp;rsquo;d have a link for you, but I&amp;rsquo;m getting a 500 page right now.) Right in the title, it mentions Ruby on Rails in the &amp;ldquo;real world&amp;rdquo;. I am unable to suppress a groan every time I hear that quoted phrase &lt;em&gt;&amp;ldquo;real world&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &amp;ldquo;real world&amp;rdquo; label is used to legitimize. If something works in the &amp;ldquo;real world&amp;rdquo;, that basically says it&amp;rsquo;s not a toy, it&amp;rsquo;s for real. But if you look around at what works in the real world, you might ask yourself, &amp;ldquo;Why on earth would I want to imitate that?&amp;rdquo; I certainly do. The &amp;ldquo;real world&amp;rdquo; is filled with lame, difficult, buggy, costly software.&lt;/p&gt;

&lt;p&gt;This relates to a point from DHH&amp;rsquo;s keynote at RailsConf that I&amp;rsquo;ve been meaning to reiterate. DHH essentially said that he lives in a fantasy world. I don&amp;rsquo;t think most of us realize how lucky we are that he does.&lt;/p&gt;

&lt;p&gt;Imagine if he didn&amp;rsquo;t. Imagine DHH working on a nascent ActiveRecord and being closely in touch with the &amp;ldquo;real world&amp;rdquo;. Certainly, he would want it to be legitimate, not merely a toy. To be legit, it should solve &amp;ldquo;real world&amp;rdquo; problems. The &amp;ldquo;real world&amp;rdquo; is full of complex databases. It better support any imaginable scheme for primary keys, even composite ones. Anything less would&amp;hellip; hmm, not work well in the &amp;ldquo;real world&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;The point is, we should be eager to say no to features. But in the &amp;ldquo;real world&amp;rdquo;, it is rare to find someone eager to do so. Sure, I can imagine my super-gizmo-mondo-cool coffee cup that is also a mobile phone, razor, electric toothbrush, talking tire gauge, and bottle opener. But why?! Just because it&amp;rsquo;s possible, does not mean that it&amp;rsquo;s desirable.&lt;/p&gt;

&lt;p&gt;Really, our ability to live in a fantasy world, even briefly, is a terribly two-edged sword. It gives us the ability to imagine a world that does not exist, and execute the steps necessary to manifest it. For example, Rails. At the same time, it gives us the ability to imagine a world that does not exist, and execute the steps necessary to manifest it. For example, J2EE.&lt;/p&gt;

&lt;p&gt;One of those two is thriving in the &amp;ldquo;real world&amp;rdquo;, according to the connotations normally associated with that phrase. I think we&amp;rsquo;re trying too hard in the wrong direction if we are chasing the &amp;ldquo;real world&amp;rdquo;. Rails is a disruptive technology; and that is something to be celebrated.&lt;/p&gt;

&lt;p&gt;Rails does not need to be legitimized.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s my opinion. In fact, I think we do a disservice to the disruptive potential of Rails by trying to legitimize it with the &amp;ldquo;real world&amp;rdquo; label. I may be reading too much into the &amp;ldquo;real world&amp;rdquo; phrase in the Sys-Con event title, but since it is billed as being for CEO&amp;rsquo;s, CTO&amp;rsquo;s, etc., I don&amp;rsquo;t think so.&lt;/p&gt;

&lt;p&gt;I think Rails is highly relevant to creating real world applications, meaning those that assist people to achieve their goals by doing much more with far, far less complexity. That requires us to have a vivid imagination and vibrant fantasy life. In other words, a good, healthy distance from the &amp;ldquo;real world&amp;rdquo;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>There's a short in my NetNewsWire</title>
    <id>http://brixen.io/2006/7/10/there-s-a-short-in-my-netnewswire</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/7/10/there-s-a-short-in-my-netnewswire" />
    <published>2006-07-10T00:00:00-07:00</published>
    <updated>2006-07-10T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;When I started at &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;, I was given a bright new matte black MacBook to use. It&amp;rsquo;s a beauty. This is the first time I&amp;rsquo;ve used a Mac extensively since around &amp;lsquo;89 and I love it. Well, mostly. For the last decade or so I&amp;rsquo;ve used Linux 90% of the time. First RedHat, then Fedora, and most recently Ubuntu, which in my experience is simply excellent.&lt;/p&gt;

&lt;p&gt;What I miss most from Linux is the super responsive Gnome desktop, the wonderful Gnome Terminal, and the oodles of very high quality free software. With the Mac, I am quickly annoyed by the frequent appearance of that damned spinning color wheel, Mac-speak for, &amp;ldquo;uh, hold on, I&amp;rsquo;m having a moment&amp;rdquo;; the typing through molasses feel of iTerm; and paying for so many little pieces of software. Mind you, I&amp;rsquo;m fine trading my money for something of value, but if you are going to force the issue with me, you should probably ensure your process to lighten my wallet doesn&amp;rsquo;t piss me off.&lt;/p&gt;

&lt;p&gt;Enter NetNewsWire. I&amp;rsquo;ve used it through it&amp;rsquo;s evaluation period and it&amp;rsquo;s been passable, nothing spectacular. But today, it wants money from me. So it puts up a friendly dialog, asking nicely. A bit miffed, I go ahead and click the &amp;ldquo;Purchase Software&amp;rdquo; radio button. Hmm, nothing happens. Seems that option is disabled. Oh well, sorry NetNewsWire, now I&amp;rsquo;m evaluating &lt;a href=&quot;http://www.newsfirerss.com/&quot;&gt;NewsFire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.brightredglow.com/assets/2006/10/3/netnewswire.jpg&quot; /&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Dilbert wisdom: CRUD is for idiots</title>
    <id>http://brixen.io/2006/7/5/dilbert-wisdom-crud-is-for-idiots</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/7/5/dilbert-wisdom-crud-is-for-idiots" />
    <published>2006-07-05T00:00:00-07:00</published>
    <updated>2006-07-05T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Last week, my esteemed colleague &lt;a href=&quot;http://www.jvoorhis.com&quot;&gt;Jeremy&lt;/a&gt;, at his characteristic morning unveiling&lt;sup&gt;[1]&lt;/sup&gt;, brought in a couple books on &amp;ldquo;Death March&amp;rdquo; projects. While he tackled the other, he lent me &lt;em&gt;Death March&lt;/em&gt;: second edition, by Edward Yourdon. Edward defines a death march project as &amp;ldquo;one whose &amp;lsquo;project parameters&amp;rsquo; exceed the norm by at least 50 percent&amp;rdquo;. That is, one or more of the following is true: the project has less than half the budget, the staff, the time, or more than double the functionality, features, performance, or technical requirements. He discusses why death march projects are created, why people participate in them, and some things one might do to try to handle such a project (although he&amp;rsquo;s pretty pessimistic about successfully changing a project of this type).  &lt;/p&gt;

&lt;p&gt;Under the heading, &lt;em&gt;Why Do Death March Projects Happen&lt;/em&gt;, Edward starts off with a great quote by the author of the &lt;em&gt;Dilbert&lt;/em&gt; cartoons, Scott Adams:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When I first started hearing these stories [about irrational corporate behavior] I was puzzled, but after careful analysis I have developed a sophisticated theory to explain the existence of this bizarre workplace behavior. People are idiots.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Including me. Everyone is an idiot, not just the people with low SAT scores. The only difference among us is that we&amp;rsquo;re idiots about different things at different times. No matter how smart you are, you spend much of your day being an idiot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hopefully everyone is not totally insulted at this point. As in &lt;em&gt;Dilbert&lt;/em&gt;, this idea can be a great source of inspiration. It&amp;rsquo;s really not as derogatory or as hopeless as it sounds. And for me, it puts some recent events in perspective.&lt;/p&gt;

&lt;p&gt;Since DHH&amp;rsquo;s keynote at RailsConf, there has been noticeable buzz about CRUD. Everything from &lt;a href=&quot;http://jimonwebgames.com/articles/2006/06/26/dont-say-crud-say-fucd&quot;&gt;new acronyms&lt;/a&gt; to &lt;a href=&quot;http://www.jvoorhis.com/articles/2006/06/28/journaled-domain-models-via-the-command-pattern-or-its-all-just-crud-pt-ii&quot;&gt;debates&lt;/a&gt; about &lt;a href=&quot;http://blog.jasonwatkins.net/articles/2006/06/27/are-nouns-better-than-verbs&quot;&gt;nouns versus verbs&lt;/a&gt;. All good stuff, interesting, thought provoking. But for me, probably the greatest benefit of more CRUDful modeling is better managing of complexity. I think this is the raison d&amp;rsquo;être of CRUD.&lt;/p&gt;

&lt;p&gt;Similar to when OOP was capturing hearts and minds, many people waxed poetic about reuse, more faithful domain modeling, etc. But the golden egg of OOP is encapsulation, and encapsulation is another powerful abstraction that helps manage complexity. If there were one thing I would lobby to be added to the agile manifesto, it would be &amp;ldquo;Simplicity over big, amazing, mind-boggling complexity&amp;rdquo;. Certainly, the &amp;ldquo;less software&amp;rdquo; mantra is related to this, but even a tiny piece of software does not necessarily mean simple, not complex.&lt;/p&gt;

&lt;p&gt;So, if you notice your controller method count is ballooning, or your controllers are more cross-wired than your plate of spaghetti, you might see an opportunity for using CRUD to restore sanity. But you can also ruthlessly adopt Einstein&amp;rsquo;s wisdom at every stage of development and use CRUD to make your app as simple as possible, but not simpler.&lt;/p&gt;

&lt;hr style=&quot;width: 10em;&quot; /&gt;

&lt;p&gt;&lt;sup&gt;[1]&lt;/sup&gt; Jeremy often comes to work with an announce if you will. For instance, one day we were discussing something about languages; I mentioned Erlang. The next day Jeremy announces when he arrived, &amp;ldquo;I learned Erlang last night.&amp;rdquo; Sweet!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>I be broke</title>
    <id>http://brixen.io/2006/6/19/i-be-broke</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/6/19/i-be-broke" />
    <published>2006-06-19T00:00:00-07:00</published>
    <updated>2006-06-19T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;So there I am, peacefully logged into my US Bank online account. Everything is going well. We&amp;rsquo;re having a nice dialog. I click, it responds. I click&amp;hellip; now I&amp;rsquo;m looking at a plain, white page with the following scrawled across the top in courier font:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;an exception occurred: Unable to complete your request at this time, ReferenceID = &quot;wl26*2006-71-59-03:21:11:742*XLP3-594861&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Imagine what the scene might be if I were speaking to a human teller and suddenly in our interaction I received a response like this. I imagine the likes of a scene from the Exorcist. The breakdown in the expected flow is extreme.&lt;/p&gt;

&lt;p&gt;On the one hand, US Bank is not a little entity. They have plenty of money for technology solutions. On the other, I understand that exceptions occur. Here&amp;rsquo;s a gentle reminder to degrade gracefully and if you can write something to the screen, make it useful, somewhat reassuring, and perhaps apologetic. There&amp;rsquo;s no good excuse for barfing your undigested exception in my face.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>What I want to be when I grow up</title>
    <id>http://brixen.io/2006/6/16/what-i-want-to-be-when-i-grow-up</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/6/16/what-i-want-to-be-when-i-grow-up" />
    <published>2006-06-16T00:00:00-07:00</published>
    <updated>2006-06-16T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;I have been rescued from mundane obscurity. Yesterday I met with &lt;a href=&quot;http://robbyonrails.com&quot;&gt;Robby&lt;/a&gt; and &lt;a href=&quot;http://www.planetargon.com/about.html&quot;&gt;Allison&lt;/a&gt; and we settled on &lt;strong&gt;Interaction Architect&lt;/strong&gt; as my title. Those are certainly big shoes to fill, boats really, but I&amp;rsquo;m looking forward to it. The title is broad enough to encompass interaction as it applies to humans-computers, humans-humans, and computers-computers. It&amp;rsquo;s both justification and impetus to push my knowledge and understanding. For example, with Project Borat, we&amp;rsquo;re focused on how we can facilitate client interaction throughout the project as well as pushing the envelope with features to support user interaction.&lt;/p&gt;

&lt;p&gt;My interest in languages dates at least as far back as about 6 years old when I discovered Chinese writing. I was fascinated to the point of drawing nonsense characters for kids at school, telling them I could write Chinese. This interest extends to programming languages and mathematics. And since first working with one of the early Macintosh computers almost 20 years ago, human-computer interaction has been a persistent curiosity, if somewhat sidelined. In fact, design interests me more than coding, but unfortunately, I don&amp;rsquo;t possess abundant artistic talent. For me, interaction design allows me to straddle that space between visual design and implementation and I&amp;rsquo;m excited to further develop these skills along side the other highly talented folks at &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>G'day Project Borat</title>
    <id>http://brixen.io/2006/6/9/gday-project-borat</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/6/9/gday-project-borat" />
    <published>2006-06-09T00:00:00-07:00</published>
    <updated>2006-06-09T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Yesterday, Project Borat and I were formally introduced. I&amp;rsquo;ll be the lead developer, picking up the &lt;a href=&quot;http://peat.org/articles/2006/05/03/introducing-project-borat&quot;&gt;thread&lt;/a&gt; and, along with &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/05/03/project-borat-an-introduction&quot;&gt;Robby&lt;/a&gt;, I&amp;rsquo;ll continue to entertain you with insights we gain as we delve deeply into the process, knocking some moss off a few rocks and uncovering ideas that will work well for us and our clients.&lt;/p&gt;

&lt;p&gt;As this project is just getting under way, one of the first things we&amp;rsquo;re facing is&amp;hellip; hmm, I hate to label it because along with that label comes all sorts of assumptions. Sure, we could call it requirements gathering, but that doesn&amp;rsquo;t tell the whole story. Then there are stories, use cases, method XYZ, and better mention PQR for completeness. Before you run off googling those last two, I made them up. Point is, even though there is a lot of material on processes, and I&amp;rsquo;m learning more every day, it&amp;rsquo;s just not that simple.&lt;/p&gt;

&lt;p&gt;So, today &lt;a href=&quot;http://robbyonrails.com&quot;&gt;Robby&lt;/a&gt; and I took a quick jaunt over to one of my favorite places on the planet. How cool to work this &lt;a href=&quot;http://rubyurl.com/jmM&quot;&gt;close&lt;/a&gt; to &lt;a href=&quot;http://www.powells.com/technicalbooks&quot;&gt;Powells Technical Books&lt;/a&gt;. While he&amp;rsquo;s deep into today&amp;rsquo;s &lt;a href=&quot;http://www.robbyonrails.com/articles/2006/06/08/trawling-for-requirements&quot;&gt;acquisition&lt;/a&gt;,  &lt;a href=&quot;http://www.powells.com/biblio/71-0321419499-0&quot;&gt;Mastering the Requirements Process, 2nd Ed&lt;/a&gt;, I had my own &lt;a href=&quot;http://rubyurl.com/uGg&quot;&gt;surprise&lt;/a&gt; waiting on my doorstep this evening.&lt;/p&gt;

&lt;p&gt;That brings me to one point about gathering requirements: the first value listed on the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;agile manifesto&lt;/a&gt;&amp;ndash;&amp;ldquo;Individuals and interactions over processes and tools&amp;rdquo;. I&amp;rsquo;m guessing there&amp;rsquo;s more than a few reasons why that one is listed first.&lt;/p&gt;

&lt;p&gt;Clients are people with varied backgrounds. If we are slaves to a particular methodology, we either 1) talk over the client&amp;rsquo;s head with unintelligible jargon, 2) try to coerce the client into &amp;ldquo;learning&amp;rdquo; our methodology so we can &amp;ldquo;be on the same page&amp;rdquo;, or 3) continually translate, in the back of our heads or on our notes, what the client is saying into our method&amp;rsquo;s jargon. The first two are disrespectful, the last one error prone. (Where&amp;rsquo;s the feedback that must occur for checking understanding?)&lt;/p&gt;

&lt;p&gt;When we, as developers, began focusing on user-centric design and usability, it was a recognition that users deserved respect and need not be rescued, if you will, by our bright ideas. In a big way, we needed to keep our bright ideas out of the user&amp;rsquo;s way. In the same way, I&amp;rsquo;m not convinced I should expect a client to care about stories, use cases, or XYZ artifact. I do believe my role is to facilitate a client&amp;rsquo;s understanding of what they want and capture that as faithfully as possible.&lt;/p&gt;

&lt;p&gt;I think plain ol&amp;rsquo; natural language is probably the most valuable tool for that. &amp;ldquo;Ee gads, but natural language is fraught with ambiguities, imprecision, double meanings, and all things evil,&amp;rdquo; you say. Well, perhaps. But consider this: mathematics is probably the most precise form of &amp;ldquo;language&amp;rdquo; humans have yet devised, and plain ol&amp;rsquo; natural language suffices to convey mathematics given a couple rules of usage. &lt;/p&gt;

&lt;p&gt;First, we do try to eliminate ambiguity and imprecision with definitions. If I&amp;rsquo;m talking about a metric space, I begin with, &amp;ldquo;given a set X and a metric d, (X,d)&amp;rdquo;. There, no more ambiguity. And second, economy; introduce a symbol or name to mean a particularly well-defined concept. Add a dose of discipline, be conscientious about usage, and you can get very far using normal language to discuss very difficult concepts. Trust me, or visit a math class and watch people learning math.&lt;/p&gt;

&lt;p&gt;So, that&amp;rsquo;s the first of my explorations. How far can natural language take me before I start reaching for this or that &amp;ldquo;representation&amp;rdquo;? I&amp;rsquo;ll aim to keep these posts short and pithy in the future, but thanks for ambling along with me on this one.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Where for art thou lighttpd</title>
    <id>http://brixen.io/2006/5/24/where-for-art-thou-lighttpd</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/5/24/where-for-art-thou-lighttpd" />
    <published>2006-05-24T00:00:00-07:00</published>
    <updated>2006-05-24T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;For the second time in a few days, lighttpd went awol on me. All that shows in the logs is &amp;lsquo;graceful shutdown started&amp;rsquo;, then &amp;lsquo;server stopped&amp;rsquo;. The VDS is fine and dandy, showing up-time of 26+ days. And the rails fcgi processes are all fine as well.&lt;/p&gt;

&lt;p&gt;Perhaps this is a good time to give &lt;a href=&quot;http://mongrel.rubyforge.org/&quot;&gt;Mongrel&lt;/a&gt; a whirl. There&amp;rsquo;s been interest expressed around the &lt;a href=&quot;http://www.planetargon.com&quot;&gt;office&lt;/a&gt;, especially after &lt;a href=&quot;http://redhanded.hobix.com/cult/zedGoesOffAboutMongrel.html&quot;&gt;Redhanded&amp;rsquo;s&lt;/a&gt; quote from the interview with Zed Shaw about Mongrel using a parser based on a real grammar and parser generator, &lt;a href=&quot;http://www.cs.queensu.ca/~thurston/ragel/&quot;&gt;Ragel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alas, this bit of sysadmin has eaten the few minutes for my intended post, so I&amp;rsquo;ll leave you with just the teaser of a title for the next post&amp;hellip;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The pursuit of perfection</title>
    <id>http://brixen.io/2006/5/24/the-pursuit-of-perfection</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/5/24/the-pursuit-of-perfection" />
    <published>2006-05-24T00:00:00-07:00</published>
    <updated>2006-05-24T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;The law of diminishing returns: more and more gets you less and less. It&amp;rsquo;s familiar in many domains: economics, martial arts training, propulsion. &lt;a href=&quot;http://www.rushlimbaugh.com/&quot;&gt;Rush Limbaugh&lt;/a&gt; would probably agree it even applies to &lt;a href=&quot;http://en.wikipedia.org/wiki/Rush_Limbaugh&quot;&gt;drug use&lt;/a&gt;. It certainly applies to developing software. There&amp;rsquo;s only a certain value derived from polishing a chunk of code. So, while I&amp;rsquo;ll reserve opinion about whether this is a &amp;lsquo;law&amp;rsquo; of nature, it&amp;rsquo;s definitely something we observe in many contexts.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s interesting to me to note where the law of diminishing returns appears to break down.&lt;/p&gt;

&lt;p&gt;I have always been intrigued by one of the ad lines used by &lt;a href=&quot;http://www.lexus.com.hk/b/b01.html&quot;&gt;Lexus&lt;/a&gt;: the relentless pursuit of perfection. For me, perfection is spelled &lt;a href=&quot;http://www.rsportscars.com/eng/cars/carrera_gt.asp&quot;&gt;Porsche&lt;/a&gt;, but I like that Lexus boldly puts perfection as the aim. The idea of pursuing perfection seems to be thumbing one&amp;rsquo;s nose at the ol&amp;rsquo; law of diminishing returns.&lt;/p&gt;

&lt;p&gt;While we&amp;rsquo;re not all engrossed in engineering the ultimate automobile, I think human artistic endeavor in general doesn&amp;rsquo;t pay much heed to the law of dimishing returns. I imagine an artist relies more on a sense of holistic completeness when deciding to stop working on a piece. Education is another area. Imagine telling your boss, &amp;ldquo;Er, I think learning more about this is just pushing the law of diminishing returns.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;In the end, it may be that the law of dimishing returns governs all our activities, but intriguing to me is how our perception influences our efforts. In the pursuit of perfection, I think we perceive each additional effort as adding value. We don&amp;rsquo;t see that value dimishing or we would likely give up. So, despite the &amp;lsquo;law&amp;rsquo; of diminishing returns, it may be our perception that makes the difference between accomplishing something mediocre and something great.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>PLANET ARGON is my Google</title>
    <id>http://brixen.io/2006/5/3/planet-argon-is-my-google</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/5/3/planet-argon-is-my-google" />
    <published>2006-05-03T00:00:00-07:00</published>
    <updated>2006-05-03T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;Late breaking news (I really need to speak to my publishing staff about getting these out on time): Monday, May 1st was my first day as part of the great team at &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;. Everyone extended themselves to get me up to speed on the working of the company. And, in truly classy fashion, the company treated us to a team welcome lunch on my behalf.&lt;/p&gt;

&lt;p&gt;I am delighted and honored to be working with these dedicated, enthusiastic, highly skilled and intelligent folks. Innovation in web applications in general and Rails in particular is occuring at such a rapid pace and &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt; is committed to being in the thick of it. On the day I started, if you pulled up google search, typed &amp;lsquo;ruby rails development hosting&amp;rsquo;, and hit I&amp;rsquo;m Feeling Lucky, it would send you straight to the &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt; website. I&amp;rsquo;m here to contribute all my expertise to these endeavors, and I expect to learn a tremendous amount along the way.&lt;/p&gt;

&lt;p&gt;So, it may seem odd to compare a small company in Portland, OR to that giant of search engines, etc. but here&amp;rsquo;s the connection: People I know who aspire to work at Google do so because of the company&amp;rsquo;s perceived technological innovation and excellence. And that&amp;rsquo;s the connection for me. The &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt; team is pursuing innovation and excellence in application design, development processes, project management, training and more. I was certain I wanted to be a part of the action.&lt;/p&gt;

&lt;p&gt;Now boarding for &lt;a href=&quot;http://www.planetargon.com&quot;&gt;PLANET ARGON&lt;/a&gt;. Stay tuned and I&amp;rsquo;ll fill you in on the adventures.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The lure of the black diamond</title>
    <id>http://brixen.io/2006/5/2/the-lure-of-the-black-diamond</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/5/2/the-lure-of-the-black-diamond" />
    <published>2006-05-02T00:00:00-07:00</published>
    <updated>2006-05-02T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;One great thing about Portland is the (usually) great snow less than 1.5 hours away. We have season passes this year for &lt;a href=&quot;http://www.skibowl.com/winter/home.cfm&quot;&gt;SkiBowl&lt;/a&gt; and the snow there has been great. But we had free passes for &lt;a href=&quot;http://www.skihood.com/&quot;&gt;Mt Hood Meadows&lt;/a&gt; so we decided to go there this weekend. Turns out April 30th was a free ski and board day at all area ski resorts, so our tickets will be good for another day till the end of the season. Anyway, it was beautiful, sunny weather and a lot of fun.&lt;/p&gt;

&lt;p&gt;Now, this is really my first season snowboarding (I went once last season) and I&amp;rsquo;ve never skied before. In other words, a rank beginner. But in this one season, I&amp;rsquo;ve gone from often sliding down on my backside, to mastering the falling leaf and stopping on my edge rather than my butt, and finally linking turns. I&amp;rsquo;ve also drastically reduced the frequency of sudden, bone-jarring endo&amp;rsquo;s resulting from catching an edge in the wrong direction. Along with the increasing skill, I&amp;rsquo;ve ventured into more difficult terrain. First the green circles, then the blue squares, and finally a couple black diamonds (but no double-black yet).&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s a big difference between a green run and a black one. It takes a lot more effort; there&amp;rsquo;s a much greater chance of wiping out; it&amp;rsquo;s definitely intimidating to stare down that near vertical (it seems) face at the black run ahead. So, what&amp;rsquo;s the lure of the black diamond? If we consider some conventional wisdom about users of software, we may recall ideas like &amp;ldquo;users are lazy&amp;rdquo;, or &amp;ldquo;people take the path of least resistence&amp;rdquo;, or &amp;ldquo;someone will do the minimum to get by&amp;rdquo;, or &amp;ldquo;people are just pleasure seekers&amp;rdquo;. How does that add up? The path of least resistance is definitely not down the black diamond run.&lt;/p&gt;

&lt;p&gt;It seems to me those ideas need refinement. I firmly believe that people are not lazy. Rather, living organisms are experts at balancing costs versus benefits, an expertise refined over hundreds of millions of years of evolution. I think people do what is most rewarding with the least cost. There is a premium on energy, so an organism must conserve it. That doesn&amp;rsquo;t mean always using the least possible, but rather using the least necessary to accomplish a goal. The difference is significant.&lt;/p&gt;

&lt;p&gt;If we conceive of people as being lazy, we&amp;rsquo;re likely to design software that supports or encourages laziness. On the other hand, if we realize people are quite willing to expend the energy to tackle a black diamond run when the payoff in the thrill of the experience is great enough, we may wonder how we can design and construct software that brings out the best in people as they tackle challenges in their work. We may wonder how we can provoke people to be the best they can be. Does that sound too idealistic, too unrealistic? Or are we just too embedded in these silly over-simplifications that people are just lazy?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Xen and the art of noise (management)</title>
    <id>http://brixen.io/2006/5/1/xen-and-the-art-of-noise-management</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/5/1/xen-and-the-art-of-noise-management" />
    <published>2006-05-01T00:00:00-07:00</published>
    <updated>2006-05-01T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;While I definitely appreciate the folks at &lt;a href=&quot;http://www.textdrive.com&quot;&gt;Textdrive&lt;/a&gt; for being early, and continuing, supporters of &lt;a href=&quot;www.rubyonrails.com&quot;&gt;Rails&lt;/a&gt;, I recently decided to switch to a VDS for essentially the same reasons as &lt;a href=&quot;http://outside-thoughts.octopod.info/articles/2006/02/22/why-the-move&quot;&gt;Octopod&lt;/a&gt;. Actually, I have him to thank for that little extra nudge provided by his blog entry. I hadn&amp;rsquo;t given the idea much thought until then because it seemed like overkill for hosting a couple personal sites. Silly me.&lt;/p&gt;

&lt;p&gt;After quite a bit of research, I decided to go with &lt;a href=&quot;http://www.quantact.com&quot;&gt;Quantact&lt;/a&gt; as well. And thanks to Ezra&amp;rsquo;s great &lt;a href=&quot;http://brainspl.at/rails_stack.html&quot;&gt;tutorial&lt;/a&gt;, I&amp;rsquo;m up and enjoying myself a lot. Well, mostly. I decided to use Debian 3.1, which I&amp;rsquo;ve never used before. However, since I&amp;rsquo;ve been using &lt;a href=&quot;www.ubuntu.com&quot;&gt;Ubuntu&lt;/a&gt; for the past several months (which was a pretty big switch after RH and Fedora for years), the process was mostly painless. The one area I&amp;rsquo;m not real comfortable with is the firewall. I&amp;rsquo;m using Bastille, but I haven&amp;rsquo;t closed the book on that yet. Actually, the idea that&amp;rsquo;s pinging around in my head is: I wonder how it would work to use Rake to write the rules for iptables. Has anyone tried something like this? I&amp;rsquo;ll let you know what I discover.&lt;/p&gt;

&lt;p&gt;Okay, you might be wondering how the title fits in here. If you&amp;rsquo;ve checked out &lt;a href=&quot;http://www.quantact.com&quot;&gt;Quantact&lt;/a&gt;, you may have noticed they are using &lt;a href=&quot;http://www.xensource.com/&quot;&gt;Xen&lt;/a&gt; for the VDS. Impressive technology. The rest? Well, when evaluating what I was finding most unsatisfactory about shared hosting, I realized it was the &amp;ldquo;noise&amp;rdquo;. All these processes, all these directories, all this stuff going on that had nothing to do with me. I was spending a lot of time in that noise, especially that webmin interface when I just wanted to type a few lines and be done. Now ps aux fills less than one screen of my xterm. I don&amp;rsquo;t think about special cases or file tickets for a port. Mind you, I&amp;rsquo;m not saying Textdrive has it all wrong. I&amp;rsquo;m just saying, my Xen VDS is nice and quiet.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>My favorite button to push</title>
    <id>http://brixen.io/2006/4/30/my-favorite-button-to-push</id>
    <link rel="alternate" type="text/html" href="http://brixen.io//2006/4/30/my-favorite-button-to-push" />
    <published>2006-04-30T00:00:00-07:00</published>
    <updated>2006-04-30T00:00:00-07:00</updated>
    <author>
      <name>Brian</name>
    </author>
    <content type="html">&lt;p&gt;A long time ago, I remember discovering while using Windows 3.1 a button with a question mark on it. Click on it and you got a cursor with a question mark and pointer. It was the &amp;#8220;what&amp;#8217;s this&amp;#8221; button; click on a control and up popped a blurb to explain something about it. Unfortunately, it seemed that developers saw this as mostly an after thought since I don&amp;#8217;t recall ever getting anything useful. Usually it was something like &amp;#8220;Name field&amp;#8221; when the control was already labeled &amp;#8220;Name:&amp;#8221;. But it was the kernel of a great idea.&lt;/p&gt;
&lt;p&gt;Taken further, the idea that software would have responsive features to assist the user manifests in context sensitive help agents and &amp;#8220;show me&amp;#8221; button activated tutorials. A reasonable argument would be that such features are required by overly complex and difficult software. But even as we strive to construct less software that is easier to use, how do we assess and implement &amp;#8220;helpful&amp;#8221; features.&lt;/p&gt;
&lt;p&gt;The holy grail for me is software that can provide anything from a little to a lot of help, contextually, and with my own data, without intruding terribly on my flow (e.g. opening new windows, obscuring my view, losing my place). Take over the mouse pointer, click here, highlight this, type that. When I move the mouse, the &amp;#8220;tutor&amp;#8221; silently retreats and I continue with my work. Just like asking another person over to show me how to do something.&lt;/p&gt;
&lt;p&gt;That sort of utility would encourage people to be more exploratory and, I think, derive greater satisfaction from using their software tools.&lt;/p&gt;
&lt;p&gt;Oh, and I wish people had a &amp;#8220;show me&amp;#8221; button.&lt;/p&gt;</content>
  </entry>
  

</feed>

