<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;CUMEQX0yfSp7ImA9WhVUFU4.&quot;"><id>tag:blogger.com,1999:blog-69451</id><updated>2012-05-20T12:03:20.395-05:00</updated><category term="arduino" /><category term="cooking" /><category term="Resharper" /><category term="Visual Studio" /><category term="tools" /><category term="refactoring" /><category term="kaizenconf" /><category term="books" /><category term="C" /><category term="collaboration" /><category term="open-source software" /><category term="rhino mocks" /><category term="language" /><category term="conference" /><category term="altnetconf" /><category term="shortcut" /><category term="electronics" /><category term="climbing" /><category term="TDD" /><category term="scrum" /><category term="agile" /><category term="hacks" /><category term="book review" /><category term="agileaustinopenspace" /><category term="unit testing" /><category term="DDD" /><category term="code" /><category term="JavaScript" /><category term="designpatterns" /><title>Girl Writes Code</title><subtitle type="html">Sharon Cichelli: Developer. Analyst. Instigator.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>1592</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/GirlWritesCode" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="girlwritescode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUUGRXk9eip7ImA9WhVUEUk.&quot;"><id>tag:blogger.com,1999:blog-69451.post-7442869190917664926</id><published>2012-05-15T23:34:00.000-05:00</published><updated>2012-05-15T23:40:24.762-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-15T23:40:24.762-05:00</app:edited><title>The Future of Blogging*</title><content type="html">Here's how this is going to work. I have technical blogs on &lt;a href="http://lostechies.com/sharoncichelli/"&gt;Los Techies&lt;/a&gt; and &lt;a href="http://www.headspring.com/author/scichelli/"&gt;Headspring&lt;/a&gt;, but this here blog is the one with the cute domain name. Wondering what to do with Girl Writes Code, I remind myself that I enjoy writing about cooking and climbing and travel as much as I enjoy writing about code.&lt;br /&gt;
&lt;br /&gt;
So I will continue to post technical content to those blogs, and this one will feature posts about the rest of my life, with pointers to the tech posts on the others. You can subscribe to either of those blogs, or to this one for the &lt;a href="http://feeds.feedburner.com/GirlWritesCode"&gt;union of all three&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* on this blog&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-7442869190917664926?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/7442869190917664926/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=7442869190917664926" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7442869190917664926?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7442869190917664926?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2012/05/future-of-blogging.html" title="The Future of Blogging*" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DUYBQXo7cSp7ImA9WhRSFEQ.&quot;"><id>tag:blogger.com,1999:blog-69451.post-954019574581716031</id><published>2011-11-16T20:31:00.001-06:00</published><updated>2011-11-16T20:32:30.409-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-16T20:32:30.409-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="arduino" /><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title>Running JavaScript... With Sneakers!</title><content type="html">&lt;p&gt;Code-review time. I haven't written significant JavaScript in &lt;em&gt;forevs&lt;/em&gt;, but I hit upon a use case well suited to it, had a blast coding it up, and am confident that I'll be completely mystified by it three months from now. That is, unless we refactor it for maintainability (this is where you come in).&lt;/p&gt;

&lt;p&gt;I'll explain the use case. The &lt;a href="http://www.coolrunning.com/engine/2/2_3/181.shtml"&gt;Couch-to-5K&lt;/a&gt; running plan is an excellent exercise regimen for learning to run. I followed it to successfully transform myself from sedentary software developer to 5K finisher. The runners among you know that five kilometers is a beginner-level distance; the sedentary software developers may find it as daunting as I once did. You train in intervals, alternating walking and running, gradually shifting the ratios to more running in successive workouts. If you can walk a moderate distance, following the program is totally doable (or modify it for easy walking/fast walking, if you're not up for jogging). Definitely check it out.&lt;/p&gt;

&lt;p&gt;The thing is, timing the intervals&amp;mdash;especially at the beginning, where you're alternating a minute of running with 90 seconds of walking&amp;mdash;needs a complex timing device (a fancy runners watch), and if you're using a treadmill, it is &lt;em&gt;really annoying&lt;/em&gt; to your fellow gym users, as your watch is beeping every minute or two. Or, well, maybe gym people don't care, but it's really annoying to me, since the dang thing is on my own wrist. For running indoors, I want a C25K timer that is tactile or visual. I've been thinking about an Arduino-powered timer that reads from a dip switch to determine which workout you're running and signals the changes with a vibration motor (like in a cell phone). Thinking, and not so much doing. Finally one Sunday I forced myself to focus on the problem: what do you have, with a visual display, that is really small and runs code?&lt;/p&gt;

&lt;p&gt;My &lt;a href="http://en.wikipedia.org/wiki/Nokia_N810"&gt;Nokia N810 internet tablet&lt;/a&gt; has a web browser that runs JavaScript, can open html files stored locally, and can do this while also playing a podcast. Win!&lt;/p&gt;

&lt;p&gt;Here's what you &lt;em&gt;can't&lt;/em&gt; do with JavaScript, though: Thread.Sleep(walkInterval). Instead, you use setTimeout() to say "execute this function &lt;em&gt;after&lt;/em&gt; this interval," asynchronously. That's the part that currently works but I daren't touch it. In other words, that's the part that needs your code review advice. Remember that the intended scenario is to rest the tablet on the treadmill's magazine lip, so the app flashes the background of the page to catch my eye when I'm not looking directly at it. It's high-contrast because it isn't meant to be &lt;em&gt;watched&lt;/em&gt;, just kept at hand, in my periphery.&lt;/p&gt;

&lt;p&gt;If you choose to use the app (in addition to reviewing it), please only use it on a treadmill. Stay safe; don't try to wrangle something you need to &lt;em&gt;look&lt;/em&gt; at while you're on the trail.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/scichelli/RunningTimer"&gt;Running Timer code&lt;/a&gt; is on github. A representative sample is below. How would you make it better?&lt;/p&gt;

&lt;pre class="code"&gt;&lt;code&gt;var exercise = function(setup) {
 var workout = getWorkout(setup.week, setup.day);
 doExercise(workout, 0);
}

var cooldown = function() {
 walk('Cool Down');
 window.setTimeout(function() { transition(function() { walk('Done!'); })}, 
  minToMilli(RT.cooldownDuration));
}

var doExercise = function(workout, i) {
 workout[i].mode();
 if (i === workout.length - 1) {
  window.setTimeout(function() { transition(cooldown) }, 
   minToMilli(workout[i].minutes));
 } else {
  window.setTimeout(function() { transition(function() { doExercise(workout, i + 1); })}, 
   minToMilli(workout[i].minutes));
 }
}

var getWorkout = function(week, day) {
 return eval('C25K.W' + week + 'D' + day);
}

var transition = function(callback) {
 var indicatorDiv = $('.runCountdown');
 var body = $(document.body);
 transitionBlink(6, indicatorDiv, body, callback);
}&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-954019574581716031?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/954019574581716031?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/954019574581716031?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2011/11/running-javascript-with-sneakers.html" title="Running JavaScript... With Sneakers!" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author></entry><entry gd:etag="W/&quot;CE4MQHkycCp7ImA9WhdaEU4.&quot;"><id>tag:blogger.com,1999:blog-69451.post-5619214847656106044</id><published>2011-08-22T09:34:00.010-05:00</published><updated>2011-10-20T12:49:41.798-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T12:49:41.798-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="open-source software" /><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title>An Object Lesson in Binary Compatibility</title><content type="html">A riddle for you, friends: When is changing a method from &lt;code&gt;return void&lt;/code&gt; to &lt;code&gt;return Something&lt;/code&gt; a breaking change?&lt;br /&gt;
&lt;br /&gt;
If you already know the answer, then why hadn't you told me? Could've saved me a fair bit of embarrassment. Ah well, maybe I missed your call.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
First, a story&lt;/h2&gt;
&lt;br /&gt;
I had the opportunity to contribute to the &lt;a href="https://github.com/DarthFubuMVC/htmltags"&gt;HtmlTags&lt;/a&gt; open-source project&lt;super&gt;&lt;a href="http://www.blogger.com/blogger.g?blogID=69451#footnote1"&gt;1&lt;/a&gt;&lt;/super&gt;. They needed some unit test coverage, and I &amp;lt;3 unit testing and wanted to try my hand at contributing to open-source software. As I got my bearings, I got more confident and started to reach beyond the unit test project into refactoring the application code.&lt;br /&gt;
&lt;br /&gt;
That's when I &lt;a href="https://github.com/scichelli/htmltags/commit/f8103728490297bec21d8ccc0e27d890ad39ec98"&gt;found the AddStyle and AddJavaScript methods&lt;/a&gt;. Their friends returned an HtmlTag, but they returned void. They would be easier to test if they returned an HtmlTag, but that's not a good justification for changing a method. But they would be more &lt;em&gt;consistent&lt;/em&gt; if they behaved like their neighbors, and that is a sufficient justification to consider it.&lt;br /&gt;
&lt;br /&gt;
HtmlTags is a library meant to be consumed by other applications. It was already in use in the wild. Therefore, it was important not to change its API. It had to work like it always had, else we'd cause considerable grief to the developers using our code. I've been the consumer of a service that made breaking changes to its API, and I have choice things to say about the team that saddled me with that noise.&lt;br /&gt;
&lt;br /&gt;
I thought really carefully. I was contemplating changing the return type of a public method in an in-use API. But all those uses would be calling it as if it returned nothing, and you can invoke a method without using its return value. This would be just like that. I asked a coder-buddy for advice. We convinced each other:  What harm could it do?&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
What about the riddle?&lt;/h2&gt;
&lt;br /&gt;
Here we come to the answer to the riddle. If you're changing a library that will be called by other applications, then there are &lt;a href="http://stackoverflow.com/questions/1456785/a-definite-guide-to-api-breaking-changes-in-net"&gt;&lt;em&gt;many&lt;/em&gt; seemingly harmless changes that are actually breaking changes&lt;/a&gt;, including &lt;a href="http://stackoverflow.com/questions/1456785/a-definite-guide-to-api-breaking-changes-in-net/1472967#1472967"&gt;changing a method's return type&lt;/a&gt;. When the consuming assembly is compiled, it is built with instructions to find a method named &lt;code&gt;Whatever&lt;/code&gt; that returns void, but the changed &lt;a href="http://www.akadia.com/services/dotnet_assemblies.html#Assemblies"&gt;assembly's manifest&lt;/a&gt; contains only a method named &lt;code&gt;Whatever&lt;/code&gt; that returns string. No match.&lt;br /&gt;
&lt;br /&gt;
Computers. They're so literal.&lt;br /&gt;
&lt;br /&gt;
To fix it, you merely need to recompile the consuming application, but you don't discover the problem until assemblies are loaded at run-time, an annoying time to discover exceptions. I coded up a simple example that illustrates the problem. Feel free to follow along at home.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
See the problem in action&lt;/h2&gt;
&lt;br /&gt;
Make two separate solutions, a class library called MessageOutputter and a console application called ConsoleMessager that references MessageOutputter. First, build MessageOutputter with a &lt;code&gt;return void&lt;/code&gt; method.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;namespace MessageOutputter
{
  public class Outputter
  {
    private string _message = "This is the outputter, version 1.";

    public string Emit()
    {
      return _message;
    }

    public void UpdateVersion(string versionNumber)
    {
      _message = string.Format("I've been altered by the UpdateVersion method. I am version {0}.", versionNumber);
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
UpdateVersion modifies a private field but does not return a value. Compile that solution and put its dll into a lib folder from which you will reference it in ConsoleMessager. Open the ConsoleMessager solution and add a reference to the MessageOutputter.dll. Write a method that uses the MessageOutputter.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;namespace ConsoleMessager
{
  class Program
  {
    static void Main(string[] args)
    {
      var outputter = new MessageOutputter.Outputter();
      Console.WriteLine("Calling the outputter:");
      Console.WriteLine(outputter.Emit());
      Console.WriteLine("Asking the outputter to update, then calling it again.");
      outputter.UpdateVersion("Updated 1");
      Console.WriteLine(outputter.Emit());
      Console.Read();
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
The UpdateVersion method is called, not expecting a return value. Build and run the ConsoleMessager.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://4.bp.blogspot.com/--A7Dqr3hnRM/TlJqJnFJ33I/AAAAAAAAAB4/Amb6boyxcJM/s1600/RunWithVersion1.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5643689996390621042" src="http://4.bp.blogspot.com/--A7Dqr3hnRM/TlJqJnFJ33I/AAAAAAAAAB4/Amb6boyxcJM/s320/RunWithVersion1.png" style="cursor: hand; cursor: pointer; height: 72px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Return to the MessageOutputter solution and modify the UpdateVersion method to return the message after it modifies it.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;namespace MessageOutputter
{
  public class Outputter
  {
    private string _message = "This is the outputter, version 2.";

    public string Emit()
    {
      return _message;
    }

    public string UpdateVersion(string versionNumber)
    {
      _message = string.Format("I've been altered by the UpdateVersion method. I am version {0}.", versionNumber);
      return _message;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Now UpdateVersion returns a string. Build the solution and copy its new dll back into the lib folder, and into the Debug or Release folder under ConsoleMessager/bin, so that the ConsoleMessager will run with your new version of the dll. Run ConsoleMessager and you will encounter the error:&lt;br /&gt;
&lt;div style="margin-bottom: 1em; margin-left: 3em;"&gt;
Unhandled Exception: System.MissingMethodException: Method not found: 'Void MessageOutputter.Outputter.UpdateVersion(System.String)' at ConsoleMessager.Program.Main(String[] args)&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://1.bp.blogspot.com/-5sGPCq73v_Y/TlJqcD2MTQI/AAAAAAAAACA/1zqqDH1Lgkk/s1600/ErrorWithVersion2.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5643690313350139138" src="http://1.bp.blogspot.com/-5sGPCq73v_Y/TlJqcD2MTQI/AAAAAAAAACA/1zqqDH1Lgkk/s320/ErrorWithVersion2.png" style="cursor: hand; cursor: pointer; height: 87px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The MissingMethodException indicates that ConsoleMessager, when looking within the MessageOutputter library, could not find an UpdateVersion method that returns void. Reopen the ConsoleMessager solution. Before you even build, IntelliSense will tell you that UpdateVersion returns a string now. Build ConsoleMessager and run it again, to see that it works successfully.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/-EvLuSX7jtn0/TlJqmU5oT2I/AAAAAAAAACI/8BEN82CHFrE/s1600/RunWithVersion2.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5643690489726652258" src="http://2.bp.blogspot.com/-EvLuSX7jtn0/TlJqmU5oT2I/AAAAAAAAACI/8BEN82CHFrE/s320/RunWithVersion2.png" style="cursor: hand; cursor: pointer; height: 64px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Wiser now&lt;/h2&gt;
&lt;br /&gt;
No one raked me over the coals—in fact, my intro-to-OSS experience was thoroughly positive, and I can't wait to do more—but I know I caused some time-consuming inconvenience to my fellow devs. I have now learned that &lt;a href="http://blogs.msdn.com/b/jmstall/archive/2008/03/10/binary-vs-source-compatibility.aspx"&gt;Binary Compatibility is not the same as Source Compatibility&lt;/a&gt;. Conflating the two is like saying, "Works on &lt;em&gt;my&lt;/em&gt; machine." I hope this write-up can help you avoid a similar goof.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="border-top: 1px solid #ccc; font-size: .8em;"&gt;
&lt;a href="" name="footnote1"&gt;&lt;/a&gt;&lt;super&gt;1&lt;/super&gt; The nice thing about open-source projects is that everyone has the opportunity to contribute. But I had the especially good fortune to have willing help from &lt;a href="http://lostechies.com/joshuaflanagan/"&gt;Josh Flanagan&lt;/a&gt; in finding my way through my first OSS pull request.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-5619214847656106044?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5619214847656106044?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5619214847656106044?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2011/08/object-lesson-in-binary-compatibility.html" title="An Object Lesson in Binary Compatibility" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/--A7Dqr3hnRM/TlJqJnFJ33I/AAAAAAAAAB4/Amb6boyxcJM/s72-c/RunWithVersion1.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;CUcAQXY_cSp7ImA9WhdaEU4.&quot;"><id>tag:blogger.com,1999:blog-69451.post-8574976263564780089</id><published>2011-06-20T18:25:00.010-05:00</published><updated>2011-10-20T12:50:40.849-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T12:50:40.849-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DDD" /><title>Using Syntax to Model the Domain</title><content type="html">I'm fascinated by the small syntactic decisions that bring code closer to representing the business domain. Never mind the class inheritance examples from text books ("Dog IS-A Pet," which has nearly never been relevant), I mean using properties, methods, and constructors to let the compiler ensure your objects stay in a valid state. Linguistically, I think this is neat.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Not everything deserves a setter&lt;/h2&gt;
&lt;br /&gt;
Consider my Bacon class with an IsCooked property:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;public class Bacon
{
  public bool IsCooked { get; set; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
To cook some bacon, I set IsCooked to true. Sure. But what if I set it to false? I just defied physics and the space-time continuum. Shucks.&lt;br /&gt;
&lt;br /&gt;
IsCooked should be read-only, and I need a different way to change it in a one-way transition: I need a method. Bacon comes into my domain uncooked, so I'll set that property in its constructor.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;public class Bacon
{
  public bool IsCooked { get; private set; }

  public Bacon()
  {
    IsCooked = false;
  }

  public void Cook()
  {
    IsCooked = true;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
The sanctity of thermodynamics is preserved. When the transitions get more interesting than a simple Boolean, you're looking at a &lt;a href="http://en.wikipedia.org/wiki/Finite-state_machine"&gt;state machine&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Polywhatism?&lt;/h2&gt;
&lt;br /&gt;
I encountered this example in the wild, but I've changed the domain to protect the innocent.&lt;br /&gt;
&lt;br /&gt;
We're exploring a dungeon, and in our inventory we have items that affect our health:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;amulets add a small amount to our health each day;&lt;/li&gt;
&lt;li&gt;granola bars give us a lump-sum boost to our health the moment we eat them; and&lt;/li&gt;
&lt;li&gt;cursed rings sap away our health each day until the curse runs out. (Why keep a cursed ring? How else would you command your army of winged monkeys?)&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Here's a display of our inventory:&lt;br /&gt;
&lt;br /&gt;
&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Item&lt;/th&gt;&lt;th&gt;Daily Boost&lt;/th&gt;&lt;th&gt;Total Remaining&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Obsidian amulet&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Luck ring&lt;/td&gt;&lt;td&gt;(25)&lt;/td&gt;&lt;td&gt;375&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Jasper amulet&lt;/td&gt;&lt;td&gt;253&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Granola of righteousness&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;400&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
This was implemented as a collection of IHealthItem objects. Here's what I found:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;public class Amulet : IHealthItem
{
  public int? DailyBoost { get; set; }

  public int? Total
  {
    get
    {
      return null;
    }
    set
    {
      throw new NotSupportedException(
           "Amulets do not have a total");
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
As if the cursed rings weren't bad enough, now there are properties we're not allowed to call, lurking, waiting to pounce on us with a run-time exception. The calling code, when working with an IHealthItem instance, is forced to make an "Is" check to determine the type, in order to know which properties are safe to use. Half the properties aren't relevant half the time. The DailyBoost property on CursedRing has an additional problem: Should you set it to a negative number, or assume it should be stored as an absolute value and multiplied by -1 when being used and displayed? The IHealthItem interface does not provide any abstraction.&lt;br /&gt;
&lt;br /&gt;
In fact, these are &lt;em&gt;not&lt;/em&gt; three variations of the same thing. The only quality they have in common is the user's desire to see them displayed in a table. (Further proof that they weren't related, in the real application, that table was labeled "Amulets/Granola Bars/Cursed Rings.") These concepts should have been modeled as three independent entities, keeping it unambiguous in the business layer how to use them to increment and decrement the adventurer's health. Only at the presentation (UI) layer, they could be projected into a display-only DTO (Data Transfer Object) or &lt;a href="http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/"&gt;view model&lt;/a&gt;, using strings for all three properties.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Don't let me be uninitialized&lt;/h2&gt;
&lt;br /&gt;
If a property must be set for an object to be in a valid state, the class's constructor should require that value as an argument instead. That way, it's impossible to construct the object without also putting it into a valid state.&lt;br /&gt;
&lt;br /&gt;
If a method, MethodB(), uses a private field and relies on another method, MethodA(), to be called first to set it, MethodB should take that value as a parameter instead. That way, MethodB can be called only after the result of MethodA has been determined; the correct order in which to call them is unambiguous.&lt;br /&gt;
&lt;br /&gt;
These types of temporal coupling are illustrated nicely with examples and remedies on Mark Seemann's blog in "&lt;a href="http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling.aspx"&gt;Design Smell: Temporal Coupling&lt;/a&gt;." (He has a whole &lt;a href="http://blog.ploeh.dk/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx"&gt;series on encapsulation&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Too, meaning drives syntax&lt;/h2&gt;
&lt;br /&gt;
When I find myself compelled to &lt;em&gt;explain&lt;/em&gt; in comments, to write instructions ("make sure you set this before you call that") in the xml summary, to incorporate usage notes into method names, I pounce on that as a candidate for refactoring. Finicky methods and classes that require secret knowledge to use correctly are invitations for bugs. It's like when I'm editing the rules for one of Jon's games: every instance of the word "except" must justify its existence. Every special-case exception immediately draws my attention as a spot where the rules could be improved and streamlined. Similarly, when coding, certain behaviors draw my attention as opportunities for improvement. Hyper-explainy documentation is a big one.&lt;br /&gt;
&lt;br /&gt;
Semantics is the study of meaning, and syntax is the study of structure. That distinction makes them sound like separate domains, but the two interpretations of "foreign car mechanic" stem from &lt;em&gt;syntactic&lt;/em&gt; ambiguity. Each word still carries the same meaning, but in one case "foreign" modifies "car," and in the other, "foreign" modifies "mechanic." Syntax in natural languages certainly influences meaning, so why not in code, as well?&lt;br /&gt;
&lt;script type="text/javascript"&gt;
custom_slug='http://lostechies.com/sharoncichelli/2011/06/20/using-syntax-to-model-the-domain/#comments';
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-8574976263564780089?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/8574976263564780089?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/8574976263564780089?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2011/06/using-syntax-to-model-domain.html" title="Using Syntax to Model the Domain" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author></entry><entry gd:etag="W/&quot;CEACR34-eSp7ImA9WhZWFko.&quot;"><id>tag:blogger.com,1999:blog-69451.post-3035937166107619979</id><published>2011-05-17T17:51:00.000-05:00</published><updated>2011-05-17T17:52:46.051-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-17T17:52:46.051-05:00</app:edited><title>Diffing Files to Avoid Easy Goofs</title><content type="html">A good habit learned at my last job has saved me a lot of embarrassment and bugs (same thing): Before committing a set of changes to source control, I look at the diff of each file. &lt;em&gt;Look&lt;/em&gt; at the changes, read 'em over, look for misspellings and placeholder notes-to-self and files I hadn't intended to change; then make fixes and revert as needed. It's like proofreading. Polishing the fingerprints off a product before sending it into the world. &lt;a href="http://www.supertopo.com/climbers-forum/1359870/Check-Your-Knot-More-Accidents"&gt;Checking your knot&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Shortcuts for diffing files:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In TFS, Shift&amp;ndash;double-click a file name in the Pending Changes window. (You can &lt;a href="http://blogs.msdn.com/b/jmanning/archive/2006/02/20/diff-merge-configuration-in-team-foundation-common-command-and-argument-values.aspx"&gt;configure TFS's diff tool&lt;/a&gt;.)&lt;/li&gt;&lt;li&gt;In TortoiseSvn, double-click a file name in the "Changes made" panel of the Commit window.&lt;/li&gt;&lt;li&gt;In git and Hg... help me out here. I'm too used to a visual side-by-side. Recommend a nice explanation of getting the most from those in-line diff reports?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If that seems daunting because there are so many files to review, check in more often. I appreciate the mentors who have drilled into me: small, focused, atomic changes. It keeps me focused on what I'm doing. Make this one change, and every other stray thought that leaps to mind ("Ooh, I need to do &lt;em&gt;this&lt;/em&gt;, too!") gets tossed in a running text file, to be addressed later. How small is small enough? When it no longer feels onerous to diff all your files before checking in. ;-) In addition to keeping my thought process on-track, this habit makes it easy to review, fix, unwind, and selectively pick certain changes when I need to.&lt;br /&gt;&lt;br /&gt;Small check-ins are like the &lt;a href="http://www.refactoring.com/catalog/extractMethod.html"&gt;extract-method refactoring&lt;/a&gt;. In code, when you have a collection of statements that &lt;em&gt;do&lt;/em&gt; something, you'd extract them into a method so that you can &lt;em&gt;name&lt;/em&gt; the something. Similarly, a focused check-in can have a descriptive and useful check-in comment.&lt;br /&gt;&lt;br /&gt;The three habits fit together: small check-ins targeting a focused goal, with a useful commit message, reviewing the changes before checking them in. Reduces the number of times I have to think "Who the heck did&amp;mdash;?! Oh, me. Heh."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-3035937166107619979?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/3035937166107619979/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=3035937166107619979" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3035937166107619979?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3035937166107619979?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2011/05/diffing-files-to-avoid-easy-goofs.html" title="Diffing Files to Avoid Easy Goofs" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEAHQHwzeSp7ImA9Wx9aF08.&quot;"><id>tag:blogger.com,1999:blog-69451.post-5361914762396925550</id><published>2011-03-09T21:10:00.000-06:00</published><updated>2011-03-09T21:12:11.281-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-09T21:12:11.281-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="electronics" /><category scheme="http://www.blogger.com/atom/ns#" term="arduino" /><title>Microcontroller Projects and Source Code</title><content type="html">Welcome, &lt;a href="http://dorkbot.org/dorkbotaustin/2011/03/dorkbot-28-sxsw-2011-science-fair-pesenters/"&gt;Ignite/Dorkbot Science Fair&lt;/a&gt; Party Goers. Here are details on the two projects I had with me at the Science Fair.&lt;br /&gt;&lt;br /&gt;I used the open-source &lt;a href="http://arduino.cc/"&gt;Arduino microcontroller&lt;/a&gt;. Arduino programs are called "sketches." I keep my Arduino sketches on the collaborative source-code repository &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;, in my &lt;a href="https://github.com/scichelli/Arduino-Sketches"&gt;Arduino-Sketches repository&lt;/a&gt;. You can browse the code in a web browser without installing Git, so go check it out. And then learn Git and post your own sketches.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/spyderella/3924009165/"&gt;&lt;img src="http://farm4.static.flickr.com/3516/3924009165_7e1bb7167f_m.jpg" width="240" height="180" alt="Ambient Clock" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Ambient Clock is an information radiator for the passage of time. It was written up on the &lt;a href="http://blog.makezine.com/archive/2009/10/ambient-led-flowerpot-clock.html"&gt;Makezine blog&lt;/a&gt;. (&lt;a href="http://www.flickr.com/photos/spyderella/sets/72157622382205116/"&gt;pictures&lt;/a&gt; | &lt;a href="https://github.com/scichelli/Arduino-Sketches/tree/master/AmbientClock"&gt;program&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/spyderella/4085499113/"&gt;&lt;img src="http://farm3.static.flickr.com/2737/4085499113_a04fefc4d7_m.jpg" width="240" height="180" alt="Blinky Eyeball Halloween Costume" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Blinky Eyeball Halloween Nightmare is, um, pretty self-describing. (&lt;a href="http://www.girlwritescode.com/2009/11/happy-hack-o-ween-electronics-and.html"&gt;write-up&lt;/a&gt; | &lt;a href="http://www.flickr.com/photos/spyderella/sets/72157622735987434/"&gt;pictures&lt;/a&gt; | &lt;a href="https://github.com/scichelli/Arduino-Sketches/tree/master/HalloweenEyeballs"&gt;program&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-5361914762396925550?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/5361914762396925550/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=5361914762396925550" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5361914762396925550?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5361914762396925550?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2011/03/microcontroller-projects-and-source.html" title="Microcontroller Projects and Source Code" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm4.static.flickr.com/3516/3924009165_7e1bb7167f_t.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcBR3o8eyp7ImA9WhZaFU8.&quot;"><id>tag:blogger.com,1999:blog-69451.post-4028601229978357555</id><published>2010-12-29T15:24:00.001-06:00</published><updated>2011-07-01T08:47:36.473-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-01T08:47:36.473-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C" /><title>Hello World in C, Dev Setup</title><content type="html">As mentioned, &lt;a href="http://www.girlwritescode.com/2010/12/dipping-into-c.html"&gt;I'm learning C&lt;/a&gt;, and I've achieved hello-world, plus recursive calculations of factorials and some data structures. Whee. :) For those playing along at home, I'll describe my dev setup.&lt;br /&gt;&lt;br /&gt;But first, an unexpected discovery: Counter to my intuition, there's a beneficial synergy between learning a new editor and learning a new language at the same time. I had thought it would be too many new things to take on at once. I've wanted to learn &lt;a href="http://www.vim.org/"&gt;Vim&lt;/a&gt; for its beautiful efficiency, but its formidable learning curve repels all comers. I couldn't gain traction. When writing in a language with which I am comfortable (C#, English), my thoughts would run too fast, too far ahead of my rudimentary editor skills, ideas slipping out of my grasp as I stumbled around the text with j, k, h, and l (and never the one I meant). But in C, where I am carefully picking my way over unfamiliar terrain, my lines of code have slowed down to match my fingers. Because I am trying to hang onto only one edit at a time, I can spare a second to check that A will switch me to insert mode at the end of the current line. I recommend it: learning a new language is a good time to learn a new text editor.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Sandbox&lt;/h2&gt;&lt;br /&gt;I use &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; to run virtual machines. VMs are excellent for experiment-based learning; think of it: a nice clean server that you can start up, poke and abuse, throw away and start again. If you start with the right VM image&amp;mdash;for example, one &lt;a href="http://www.turnkeylinux.org/rails"&gt;configured for Ruby on Rails&lt;/a&gt;&amp;mdash;you can jump right into the experimentation without all the installation hoop-jumping.&lt;br /&gt;&lt;br /&gt;For this endeavor I chose &lt;a href="http://www.turnkeylinux.org/core"&gt;TurnKey Linux's Core appliance&lt;/a&gt; because it's just Linux and not much else, following their &lt;a href="http://www.turnkeylinux.org/docs/installation-appliances-virtualbox"&gt;instructions for installing a TurnKey appliance&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To install a compiler (later), I needed my VM to connect to the internet. In VirtualBox Settings &amp;gt; Network, I set "Attached to" to "Bridged Adapter," meaning the VM could use my laptop's connection, and the adapter's "Name" to my wireless card. (The other choice in the dropdown list is a PCI-E Fast Ethernet Controller, and that... didn't work.) With that set, I powered up the VM, which starts the webmin console. I let it automatically configure DHCP, and I was internet-ready.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Editor&lt;/h2&gt;&lt;br /&gt;Vim is already installed on the Core VM image, so I just needed to type "vim helloworld.c" to start stumbling around my new code file. I'm relying on the TuXfiles &lt;a href="http://www.tuxfiles.org/linuxhelp/vimcheat.html"&gt;Vim cheat sheet&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Compiler&lt;/h2&gt;&lt;br /&gt;I chose &lt;a href="http://gcc.gnu.org/"&gt;GCC, the GNU Compiler Collection&lt;/a&gt; for my C compiler, and I needed to download and install it. Following TurnKey's &lt;a href="http://www.turnkeylinux.org/docs/apt-howto"&gt;apt-get instructions&lt;/a&gt;:&lt;ul type="none"&gt;&lt;li&gt;apt-get update (to update apt's list of modules)&lt;/li&gt;&lt;li&gt;apt-cache search gcc (to find modules for the gcc compiler - gcc-4.1 looked right.)&lt;/li&gt;&lt;li&gt;apt-cache show gcc-4.1 (to get info about it)&lt;/li&gt;&lt;li&gt;apt-get install gcc-4.1 (to install it)&lt;/li&gt;&lt;li&gt;gcc-4.1 myfile.c -o myexename (to compile and generate myexename executable)&lt;/li&gt;&lt;li&gt;./myexename (to run my program)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Hello World&lt;/h2&gt;&lt;br /&gt;I followed a &lt;a href="http://www.youtube.com/watch?v=_0_4yiD8_hk"&gt;video that creates and compiles a C program using the GCC compiler&lt;/a&gt;. "Hello, World!" A simple phrase, profoundly satisfying.&lt;br /&gt;&lt;script language='text/javascript'&gt;custom_slug='17 /blogs/sharoncichelli/archive/2010/12/29/hello-world-in-c-dev-setup.aspx';&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-4028601229978357555?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/4028601229978357555/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=4028601229978357555" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4028601229978357555?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4028601229978357555?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/12/hello-world-in-c-dev-setup.html" title="Hello World in C, Dev Setup" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;D0IDR34_eSp7ImA9Wx9SE0U.&quot;"><id>tag:blogger.com,1999:blog-69451.post-3057690064759816368</id><published>2010-12-03T08:11:00.001-06:00</published><updated>2010-12-03T08:12:56.041-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-03T08:12:56.041-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><title>Dipping into C</title><content type="html">I decided on Monday that I should learn C. Cultivate a nodding acquaintance, at any rate. &lt;a href="http://www.lostechies.com/blogs/louissalin/"&gt;Louis&lt;/a&gt; is always prodding me to become a better craftsman, to become more proficient with my tools. So I figured I should understand my roots.&lt;br /&gt;&lt;br /&gt;I picked up O'Reilly's &lt;i&gt;&lt;a href="http://oreilly.com/catalog/9781565924536"&gt;Mastering Algorithms with C&lt;/a&gt;&lt;/i&gt; at the library, and I'm already having fun. It will get into recursion, Big O notation, linked lists, quicksorts, encryption, and all that jazz, but right off the bat, it starts with pointers. &lt;br /&gt;&lt;br /&gt;Immediately some aspects of C# become more clear, by understanding their precursors from C: the ideas behind reference types and passing parameters by reference, and the joys of automatic garbage collection and abstracted memory allocation.&lt;br /&gt;&lt;br /&gt;The syntax of pointers in C involves a lot of punctuation&amp;mdash;a subtle and nuanced application of asterisks and ampersands&amp;mdash;which the book assumes I would already know. My favorite search engine (code-named Sweetie, as in, "Hey, Sweetie, can you find...") turned up an online edition of &lt;i&gt;&lt;a href="http://publications.gbdirect.co.uk/c_book/"&gt;The C Book&lt;/a&gt;&lt;/i&gt;, containing this &lt;a href="http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html"&gt;excellent explanation of pointers&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's my understanding so far. Please suggest corrections if I've gotten it sideways.&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td style="border: 1px solid gray;"&gt;int *mypointer;&lt;/td&gt;&lt;td style="padding-left:1em;"&gt;mypointer's type is "pointer that can point to an integer"&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="border: 1px solid gray;"&gt;mypointer = &amp;amp;myint;&lt;/td&gt;&lt;td style="padding-left:1em;"&gt;mypointer is pointing to the location where myint is stored&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="border: 1px solid gray;"&gt;*mypointer = 7;&lt;/td&gt;&lt;td style="padding-left:1em;"&gt;the place where mypointer is pointing now contains a 7, so myint now equals 7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="border: 1px solid gray;"&gt;myotherint = myint;&lt;/td&gt;&lt;td style="padding-left:1em;"&gt;myotherint also equals 7 (but just a copy of 7, so changes to myint won't affect myotherint)&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;So what? So now I'm clearer about reference types in C#. In C, I can pass a &lt;em&gt;pointer&lt;/em&gt; as a parameter to a function, instead of passing a value. That means I'm passing the function a reference to a location in memory. If the function uses the pointer to change the stuff in that location, when someone else accesses that location, they will receive the changed stuff. Contrast this with passing a value, such as an integer, to a function, which actually passes a copy of the value. Any changes to the value are scoped within the function and are not detectable from outside. It's something I've known for a while, but now I know &lt;em&gt;why&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;If you no longer need the piece of memory that a pointer points to but you fail to de-allocate that memory, it will stay held in reserve forever&amp;mdash;voil&amp;agrave;, a memory leak. Different data types take up different amounts of memory, so writing a data type into a pointer of a differently sized data type will overwrite other pieces of memory in unpredictable ways. I feel like I've been making peanut-butter sandwiches with a butter knife and just noticed that other people are wielding samurai swords: looks really powerful and flexible, but I'm scared I'd cut off a finger. Now I get what the big deal is about the CLR's garbage collector (and how in some contexts it would be too restrictive).&lt;br /&gt;&lt;br /&gt;I'm having fun getting "closer to the metal" and realizing the reasons behind some things I've taken for granted. I can't wait to get into the chapters on algorithms.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-3057690064759816368?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/3057690064759816368/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=3057690064759816368" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3057690064759816368?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3057690064759816368?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/12/dipping-into-c.html" title="Dipping into C" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;Ak8MRnkzfSp7ImA9Wx5QEUU.&quot;"><id>tag:blogger.com,1999:blog-69451.post-6329402014043200956</id><published>2010-08-30T12:16:00.001-05:00</published><updated>2010-08-30T12:21:27.785-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-30T12:21:27.785-05:00</app:edited><title>Three Simple Steps to Improve Your Writing</title><content type="html">Technical books are longer than they ought to be. Most software books could be improved by shedding a tenth of their heft. It's a product of market pressures, of course: Tech books need to get to market &lt;em&gt;fast&lt;/em&gt;, which does not allow for the time-consuming labor of honing and refining a text until it is lean and tight. I have a few simple strategies, though&amp;mdash;simple tips that provide a disproportionately beneficial return on a trivial time investment. You can use the following tips to improve your blog posts, books, and presentations.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Replace "basically" with nothing.&lt;/h2&gt;&lt;br /&gt;This word never adds value. It is usually a manifestation of the author's or speaker's unconscious concern that what he is explaining is too complex. If time allows, revise the material until your readers don't need extra convincing that it is basic. At least get rid of the useless word.&lt;br /&gt;&lt;br /&gt;You could have some fun writing a regular expression to correct all instances with a global search-and-replace. If you're amused by the challenge, please feel free to post your regex in the comments. You'd be helping all of us.&lt;br /&gt;&lt;br /&gt;Here are the replacements your regex would need to catch:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Find&lt;/th&gt;&lt;th&gt;Result&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="background-color:#cccccc;"&gt;Basically, i&lt;/span&gt;t can start a sentence.&lt;/td&gt;&lt;td&gt;It can start a sentence.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="background-color:#cccccc;"&gt;Basically p&lt;/span&gt;eople leave off the comma, too.&lt;/td&gt;&lt;td&gt;People leave off the comma, too.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;It can &lt;span style="background-color:#cccccc;"&gt;basically&amp;nbsp;&lt;/span&gt;appear in the middle.&lt;/td&gt;&lt;td&gt;It can appear in the middle.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;It can&lt;span style="background-color:#cccccc;"&gt;, basically,&lt;/span&gt; be set off with commas.&lt;/td&gt;&lt;td&gt;It can be set off with commas.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;It can end a sentence&lt;span style="background-color:#cccccc;"&gt;, basically&lt;/span&gt;.&lt;/td&gt;&lt;td&gt;It can end a sentence.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;It might end without a comma&lt;span style="background-color:#cccccc;"&gt;&amp;nbsp;basically&lt;/span&gt;.&lt;/td&gt;&lt;td&gt;It might end without a comma.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;h2&gt;Replace "essentially" with nothing.&lt;/h2&gt;&lt;br /&gt;As above.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Replace "is nothing more than" with "is."&lt;/h2&gt;&lt;br /&gt;The "is nothing more than" construction falls in the category of noisy hedge words. It's a large category. Folks add words to forestall arguments. Even though it sounds romantically brash&amp;mdash;X is &lt;em&gt;nothing&lt;/em&gt; but Y, #wristforehead&amp;mdash;it actually weakens the association between the subject and its predicate nominative. Be clear; be bold. If you're trying to define X by saying that it is Y, say that X is Y.&lt;br /&gt;&lt;br /&gt;I wish the industry allowed more time for editing. I wish I were able to help more people express their ideas. Good editing is liberating, plucking the brambles and cruft off a passage until its central theme floats to the fore&amp;mdash;getting the &lt;em&gt;text&lt;/em&gt; out of the way of the &lt;em&gt;writing&lt;/em&gt;. &lt;br /&gt;&lt;br /&gt;I hope you find these tips helpful and easy to implement. Ruthlessly delete useless clutter like "basically," "essentially," and "nothing more than." Let your ideas stand tall.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-6329402014043200956?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/6329402014043200956/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=6329402014043200956" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/6329402014043200956?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/6329402014043200956?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/08/three-simple-steps-to-improve-your.html" title="Three Simple Steps to Improve Your Writing" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkIMRXY7eip7ImA9WxFVGUQ.&quot;"><id>tag:blogger.com,1999:blog-69451.post-5440015536542040910</id><published>2010-06-19T20:40:00.007-05:00</published><updated>2010-06-19T20:49:44.802-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-19T20:49:44.802-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Resharper" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="shortcut" /><title>ReSharper Shortcut for Context-Sensitive Unit-Test Running</title><content type="html">For a keyboard shortcut to the context-sensitive ReSharper unit test runner (otherwise available via right-click &amp;gt; Run Unit Tests), map:&lt;br /&gt;&lt;br /&gt;&lt;span style="padding-left: 30px;"&gt;ReSharper.ReSharper_UnitTest_ContextRun&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(Thanks to &lt;a href="http://handcraftsman.wordpress.com/"&gt;Clinton&lt;/a&gt; for mentioning it.)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What This Solves&lt;/h2&gt;&lt;br /&gt;The slowest way to select and run unit tests is to click the green-yellow bubbles in the left margin and pick "Run" (or "Append to Session" to collect a bunch of them to run).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_2t4fAGyHQn0/TB1zXfBRJXI/AAAAAAAAAAs/GKCjY0Zkxpw/s1600/ResharperTestRunner.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 239px; height: 157px;" src="http://2.bp.blogspot.com/_2t4fAGyHQn0/TB1zXfBRJXI/AAAAAAAAAAs/GKCjY0Zkxpw/s320/ResharperTestRunner.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484666768508134770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the right-click menu, the "Run Unit Tests" option will run a test if your cursor is in a test, all tests in a fixture if your cursor is outside a test but within the fixture, or all tests in a file if you're outside any fixtures.&lt;br /&gt;&lt;br /&gt;Mapping the ReSharper.ReSharper_UnitTest_ContextRun to a keyboard shortcut achieves the context-sensitive behavior, mouse free. I chose Alt-T for mine, since that wasn't in use for anything else. (Have a nice strategy for picking unique keyboard shortcuts and remembering them? Please share in the comments.)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;To Map the Shortcut&lt;/h2&gt;&lt;br /&gt;Tools &amp;gt; Options &amp;gt; Environment &amp;gt; Keyboard. In the "Show commands containing" textbox, enter some or all of the command, and select the command.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_2t4fAGyHQn0/TB1zlwnjyGI/AAAAAAAAAA0/ECpb1a7xuBg/s1600/MapResharperShortcut.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 186px;" src="http://2.bp.blogspot.com/_2t4fAGyHQn0/TB1zlwnjyGI/AAAAAAAAAA0/ECpb1a7xuBg/s320/MapResharperShortcut.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484667013750311010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Set your focus to the "Press shortcut keys" textbox and type your shortcut just as if you were invoking it. If a command shows up in the "Shortcut currently used by" list, life will be simpler if you pick a different shortcut. When you have one you like, click "Assign" and "OK." Good to go!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-5440015536542040910?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/5440015536542040910/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=5440015536542040910" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5440015536542040910?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5440015536542040910?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/06/resharper-shortcut-for-context.html" title="ReSharper Shortcut for Context-Sensitive Unit-Test Running" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_2t4fAGyHQn0/TB1zXfBRJXI/AAAAAAAAAAs/GKCjY0Zkxpw/s72-c/ResharperTestRunner.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0YESH0-fCp7ImA9WxBbGUs.&quot;"><id>tag:blogger.com,1999:blog-69451.post-7087268201502074166</id><published>2010-03-18T22:17:00.002-05:00</published><updated>2010-03-18T22:25:09.354-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-18T22:25:09.354-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="rhino mocks" /><title>Rhino Mocks Examples, with a fix</title><content type="html">Jon Kruger created an excellent &lt;a href="http://jonkruger.com/blog/2010/03/12/how-to-use-rhino-mocks-documented-through-tests/"&gt;explanation of Rhino Mocks, using unit tests&lt;/a&gt; to demonstrate and illuminate the syntax and capabilities. (Found via &lt;a href="http://twitter.com/gar3t"&gt;@gar3t&lt;/a&gt;.) It needs one small correction, which I'd like to write about here so that I can link to and support Jon's work, and because it gives the opportunity to clarify a subtle distinction between mocks and stubs and verified expectations.&lt;br /&gt;&lt;br /&gt;First, go check out &lt;a href="http://github.com/JonKruger/RhinoMocksExamples/raw/master/src/RhinoMocksExamples/RhinoMocksExamples/RhinoMocksTests.cs"&gt;Jon's code&lt;/a&gt;, then come back here.&lt;br /&gt;&lt;br /&gt;The problem lies in the following test. I can comment out the part that looks like it is satisfying the assertions, yet the test still passes&amp;mdash;a false positive.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:550px;"&gt;&lt;pre style="margin: 0px;"&gt;[&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Another_way_to_verify_expectations_instead_of_AssertWasCalled()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; stub = &lt;span style="color: #2b91af;"&gt;MockRepository&lt;/span&gt;.GenerateStub&amp;lt;&lt;span style="color: #2b91af;"&gt;ISampleClass&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Here I'm setting up an expectation that a method will be called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.Expect(s =&amp;gt; s.MethodThatReturnsInteger(&lt;span style="color: #a31515;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;)).Return(5);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;//Sneaky Sharon comments out the &amp;quot;Act&amp;quot; part of the test:&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;//var output = stub.MethodThatReturnsInteger(&amp;quot;foo&amp;quot;);&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;//Assert.AreEqual(5, output);&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// ... and now I'm verifying that the method was called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.VerifyAllExpectations();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;In translation, that test says: Create a fake ISampleClass; set up an expectation that a method will be called; &lt;s&gt;call that method&lt;/s&gt; do nothing; verify that your expectations were met (and flag the test as a failure if they weren't). Shoot. Worse than not having my expectations met is not realizing they're not being met. Reminds me of my college boyfriend.&lt;br /&gt;&lt;br /&gt;There are two things to fix here. The first is that this test is a little solipsistic. If you create a mock, tell the mock to act, and verify things about the mock... all you're testing are mocks. Instead, you want your tests to exercise &lt;em&gt;real&lt;/em&gt; code. The "system under test," i.e., the class being tested, should be part of your production code. Its dependencies are what get mocked, so that you can verify proper interactions with those dependencies. Let's fix the solipsism before going on to the second issue.&lt;br /&gt;&lt;br /&gt;As originally written, the expectation would be satisfied by the "Act" (as in Arrange-Act-Assert) part of the test. It says, "Call this method. Did I just call this method? Oh, good." Instead, you want to ensure the system under test correctly interacts with its friends, using Rhino Mocks' AssertWasCalled and Expect methods. We need a real class that takes the stubbed class and calls a method on the stubbed class, and we'll write unit tests around the real class.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:550px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MyRealClass&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ActOnTheSampleClass(&lt;span style="color: #2b91af;"&gt;ISampleClass&lt;/span&gt; sampleClass)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here's the re-written test, verifying how my real class interacts with the ISampleClass interface.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:550px;"&gt;&lt;pre style="margin: 0px;"&gt;[&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Another_way_to_verify_expectations_instead_of_AssertWasCalled()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; stub = &lt;span style="color: #2b91af;"&gt;MockRepository&lt;/span&gt;.GenerateStub&amp;lt;&lt;span style="color: #2b91af;"&gt;ISampleClass&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; systemUnderTest = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MyRealClass&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Here I'm setting up an expectation that a method will be called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.Expect(s =&amp;gt; s.MethodThatReturnsInteger(&lt;span style="color: #a31515;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;)).Return(5);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Tell the system to act (which, if it is working correctly, &lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// will call a method on the ISampleClass.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; systemUnderTest.ActOnTheSampleClass(stub);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// ... and now I'm verifying that the method was called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.VerifyAllExpectations();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This test will still pass, despite the fact that my real class does not currently call any methods on the ISampleClass interface. This points to the second issue to fix. In Rhino Mocks, expectations on stubs are not verified; only mocks are verified. If an object is created with GenerateStub instead of GenerateMock, then its VerifyAllExpectations method doesn't do anything. This is non-obvious because the AssertWasCalled and AssertWasNotCalled methods on a stub &lt;em&gt;will&lt;/em&gt; behave the way you want them to.&lt;br /&gt;&lt;br /&gt;In Rhino Mocks, a stub can keep track of its interactions and assert that they happened, but it cannot record expectations and verify they were met. A mock can do both these things. &lt;br /&gt;&lt;br /&gt;That is how they are implemented in Rhino Mocks. If you were holding firm to the ideas in Fowler's &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;Mocks Aren't Stubs&lt;/a&gt; article, I think stubs would implement neither VerifyAll nor AssertWasCalled. Semantically, verifying expectations and asserting interactions are synonymous, if you ask me; therefore, stubs shouldn't do either one.&lt;br /&gt;&lt;br /&gt;Back to Jon Kruger's tests. If we call GenerateMock instead of GenerateStub, the test will fail properly with an ExpectationViolationException.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:550px;"&gt;&lt;pre style="margin: 0px;"&gt;[&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Another_way_to_verify_expectations_instead_of_AssertWasCalled()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; stub = &lt;span style="color: #2b91af;"&gt;MockRepository&lt;/span&gt;.GenerateMock&amp;lt;&lt;span style="color: #2b91af;"&gt;ISampleClass&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; systemUnderTest = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MyRealClass&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Here I'm setting up an expectation that a method will be called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.Expect(s =&amp;gt; s.MethodThatReturnsInteger(&lt;span style="color: #a31515;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;)).Return(5);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Tell the system to act (which, if it is working correctly, &lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// will call a method on the ISampleClass.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; systemUnderTest.ActOnTheSampleClass(stub);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// ... and now I'm verifying that the method was called&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; stub.VerifyAllExpectations();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Now that we're red, let's get to green. Change the system under test so that it does its job as expected.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:550px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MyRealClass&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ActOnTheSampleClass(&lt;span style="color: #2b91af;"&gt;ISampleClass&lt;/span&gt; sampleClass)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; &amp;nbsp; sampleClass.MethodThatReturnsInteger(&lt;span style="color: #a31515;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Wahoo, a passing test that we can rely on.&lt;br /&gt;&lt;br /&gt;The two key points from this exercise are:&lt;ol&gt;&lt;li&gt;&lt;a href="http://jonkruger.com/blog/2010/03/12/how-to-use-rhino-mocks-documented-through-tests/"&gt;Describing Rhino Mocks with unit tests&lt;/a&gt; is a cool way to explain a topic. Let's have more executable documentation, eh?&lt;/li&gt;&lt;li&gt;Expectations on stubs aren't verified, so beware of falsely passing tests.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-7087268201502074166?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/7087268201502074166/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=7087268201502074166" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7087268201502074166?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7087268201502074166?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/03/rhino-mocks-examples-with-fix.html" title="Rhino Mocks Examples, with a fix" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkUNQXY7cCp7ImA9WxBbGUs.&quot;"><id>tag:blogger.com,1999:blog-69451.post-1487814733975264725</id><published>2010-03-18T22:10:00.001-05:00</published><updated>2010-03-18T22:11:30.808-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-18T22:11:30.808-05:00</app:edited><title>New home for RSS feed</title><content type="html">A friend recommended FeedBurner, so the RSS feed for Girl Writes Code will be served from &lt;a href="http://feeds.feedburner.com/GirlWritesCode"&gt;http://feeds.feedburner.com/GirlWritesCode&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-1487814733975264725?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/1487814733975264725/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=1487814733975264725" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/1487814733975264725?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/1487814733975264725?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/03/new-home-for-rss-feed.html" title="New home for RSS feed" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkMGQn44eSp7ImA9WxBUFU4.&quot;"><id>tag:blogger.com,1999:blog-69451.post-5005224017860174252</id><published>2010-02-28T07:12:00.006-06:00</published><updated>2010-03-02T06:53:43.031-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T06:53:43.031-06:00</app:edited><title>GirlWritesCode is moving to new digs; please join us.</title><content type="html">I use Blogger's FTP model, where my posts are published out to my webhost on Invisible City. Blogger is discontinuing that service, due to lack of use and to enable bigger and better things in their architecture. So I need to shuffle things around, and I hope that you will follow this blog to its new home.&lt;br /&gt;&lt;br /&gt;I'll update &lt;a href="http://www.girlwritescode.com/"&gt;GirlWritesCode.com&lt;/a&gt; to redirect to the new location, so if that's the url you've bookmarked, you're good to go.&lt;br /&gt;&lt;br /&gt;I'll continue to cross-post at &lt;a href="http://www.lostechies.com/blogs/sharoncichelli/default.aspx"&gt;Los Techies&lt;/a&gt;. If that's your main means of keeping up with me, then... how are you reading this? ;-)&lt;br /&gt;&lt;br /&gt;I'll have an RSS feed from the new location, but the url is going to change. It will be &lt;s&gt;http://girlwritescode.blogspot.com/atom.xml&lt;/s&gt;, I'm pretty sure. [Correction: &lt;a href="http://www.girlwritescode.com/feeds/posts/default"&gt;http://www.girlwritescode.com/feeds/posts/default&lt;/a&gt;] I'll post a "we've landed" post from the new location, so you'll know when I've got it sorted.&lt;br /&gt;&lt;br /&gt;I appreciate your readership. Everything I write, I write with you in mind. I hope you will follow this blog to its new location.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-5005224017860174252?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5005224017860174252?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/5005224017860174252?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/02/girlwritescode-is-moving-to-new-digs.html" title="GirlWritesCode is moving to new digs; please join us." /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author></entry><entry gd:etag="W/&quot;C04NSHY6fyp7ImA9WxBWFUU.&quot;"><id>tag:blogger.com,1999:blog-69451.post-13049191294412866</id><published>2010-02-07T16:32:00.000-06:00</published><updated>2010-02-07T16:33:19.817-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-07T16:33:19.817-06:00</app:edited><title>More Dogs and Bears and Chickens and Things: Invite your colleagues to Pablo's Fiesta</title><content type="html">If you work with developers who are women, please tell them about the &lt;a href="http://fiesta.lostechies.com/"&gt;Los Techies Open Space conference&lt;/a&gt;, coming up at the end of February. If you've attended an event like this in the past, you're already aware of some facts:&lt;ul&gt;&lt;li&gt;The Austin developer community is vibrant, engaged, and constantly striving to improve our craft. We've got a good thing going here.&lt;/li&gt;&lt;li&gt;The quality of the conversations and the value of the event far outstrip the price of admission; it would be a bargain at twice the price.&lt;/li&gt;&lt;li&gt;Women are way under-represented.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Early in my career, I wasn't tapped into the information channels that announce events like this. I didn't go because I just didn't know about them. My friend and colleague &lt;a href="http://www.lostechies.com/blogs/joshuaflanagan/"&gt;Josh Flanagan&lt;/a&gt; made a point of letting me know, and encouraging me to go, and showing that it was not only okay but right to ask my employer to send me to such things.&lt;br /&gt;&lt;br /&gt;Attending conferences has made a huge difference in my growth as a developer and in my career. It brought me into the on-going conversation in the developer community. It exposed me to new practices and new technologies, which I brought back to the team. Please do the same favor for your women co-workers that Josh did for me: Tell them about Pablo's Fiesta and encourage them to sign up.&lt;br /&gt;&lt;br /&gt;Bringing women into the mix brings new, diverse ideas into the conversation, new skillsets to the community, more role models for our kids. The conference will be improved by spicing up the guest list. Although I'm focusing on women here, reach out to any of your colleagues who "don't usually go to these things." New voices mean new synergy, which means more learning and more fun.&lt;br /&gt;&lt;br /&gt;And you. &lt;a href="http://fiesta.lostechies.com/"&gt;Sign up&lt;/a&gt;, your own self. It'll be great.&lt;br /&gt;&lt;br /&gt;If you have any questions about Pablo's Fiesta, or about whether you'd enjoy it, please feel free to post them &lt;a href="http://www.lostechies.com/blogs/sharoncichelli/archive/2010/02/07/more-dogs-and-bears-and-chickens-and-things-invite-your-colleagues-to-pablo-s-fiesta.aspx"&gt;here&lt;/a&gt;, and I'll get the answers for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-13049191294412866?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/13049191294412866/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=13049191294412866" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/13049191294412866?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/13049191294412866?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/02/more-dogs-and-bears-and-chickens-and.html" title="More Dogs and Bears and Chickens and Things: Invite your colleagues to Pablo's Fiesta" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YHR389cSp7ImA9WxBQF0g.&quot;"><id>tag:blogger.com,1999:blog-69451.post-4993678437861948074</id><published>2010-01-17T13:04:00.000-06:00</published><updated>2010-01-17T13:05:36.169-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-17T13:05:36.169-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="book review" /><title>Interface-Oriented Design - Book Review</title><content type="html">Ken Pugh's &lt;i&gt;&lt;a href="http://www.pragprog.com/titles/kpiod/interface-oriented-design"&gt;Interface-Oriented Design&lt;/a&gt;&lt;/i&gt; (Pragmatic Programmers) presents an approach to designing applications that focuses first on the interfaces, the places where pieces of the application interact. The interfaces here are not primarily user interfaces, but module-to-module interfaces and service interfaces, and the applications are not exclusively object-oriented. Pugh's proposed process is to identify use cases and test cases, determine the interfaces that will enable those use cases, then create tests and implementations for the interfaces.&lt;br /&gt;&lt;br /&gt;The book is divided into three parts. The first explains the concepts and theory underlying an interface-focused approach to design. These concepts include real-world analogies which quickly provide context to the discussion; types of interfaces, such as stateless versus stateful, and procedural versus document; design concerns such as contracts, cohesiveness, and polymorphism; and the Asimov-inspired "three laws of interfaces," which specify the qualities of a well behaved implementation. Part two is brief and describes where interface-oriented design fits into the project lifecycle. Part three walks through three examples, from concept to design to implementation, and highlights the design patterns exhibited in those examples. The book concludes with a grab-bag appendix of topics that could have been better served by integration into the main text.&lt;br /&gt;&lt;br /&gt;If your learning style is learn-by-doing, you might get more out of the book by reading Part Three before Part One. Part Three provides the "yeah, but what are we &lt;em&gt;doin'&lt;/em&gt; here" skeleton onto which you can hang the theory that is explained in Part One. I find theory easier to digest and retain if I know which of my real-world, day-to-day experiences it applies to. You'll get that context if you flip the order in which you read it.&lt;br /&gt;&lt;br /&gt;I picked up this book looking for best practices on providing and consuming remote interfaces, and it isn't that. Have you ever taken a sip of something you like, but because you were expecting a completely different flavor, it tasted off? I bumped into that dissonance here, so it was hard for me to get into the book. To appropriately prepare your palate, the flavor to anticipate from &lt;i&gt;Interface-Oriented Design&lt;/i&gt; is a technique for thinking about a problem domain and its software solution by thinking about the places where responsibilities interact, analogous to the way that &lt;a href="http://en.wikipedia.org/wiki/Service-oriented_architecture"&gt;service-oriented architecture&lt;/a&gt; is a technique for thinking about software design.&lt;br /&gt;&lt;br /&gt;An area where this book really shines is Pugh's deft use of real-world examples. In the first  chapter, he introduces the process of ordering a pizza as a series of exchanges through a PizzaOrdering interface. The example is familiar, relatable, and practically identical across the United States (&lt;a href="http://www.austinspizza.com/"&gt;implementations vary&lt;/a&gt;, of course). Pugh then uses that example and expands upon it throughout the rest of the book, allowing us to fit new concepts into the model as it is refined. This worked better than if each new concept had been presented with a new example; the book gained a pedagogical momentum.&lt;br /&gt;&lt;br /&gt;Many times during my reading, I asked myself whether the ideas were so fundamental and distilled as to shift my way of thinking, or so fundamental as to be mundane and trivial. Was this book raising the level of abstraction, like climbing a mountain to get a better view of the landscape, or just telling me no-duh stuff I already knew? Is its audience experienced developers looking to put terms and practices around habits they do instinctively, or is its audience beginners who need an introduction to methodical design? I still haven't decided. Will it affect my thinking? Probably. Not in ways that I can articulate and enumerate for you, but likely in subtle and profound ways that I may or may not notice as they occur. For yourself, I recommend checking out the table of contents (available from the &lt;a href="http://www.pragprog.com/titles/kpiod/interface-oriented-design"&gt;Pragmatic Bookshelf&lt;/a&gt;) and see if it suits you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-4993678437861948074?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/4993678437861948074/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=4993678437861948074" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4993678437861948074?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4993678437861948074?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2010/01/interface-oriented-design-book-review.html" title="Interface-Oriented Design - Book Review" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkYMSH87cCp7ImA9WxNUFkQ.&quot;"><id>tag:blogger.com,1999:blog-69451.post-4590327380219080543</id><published>2009-11-08T10:35:00.000-06:00</published><updated>2009-11-08T10:36:29.108-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-08T10:36:29.108-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="electronics" /><category scheme="http://www.blogger.com/atom/ns#" term="arduino" /><title>Happy Hack-o-ween: Electronics and a microcontroller spice up the haunt</title><content type="html">Ah, Halloween, when a young woman's fancy turns to love. And zombies.&lt;br /&gt;&lt;br /&gt;I had two personal requirements for the costume I would build this year:&lt;ol&gt;&lt;li&gt;It shall be spooky.&lt;/li&gt;&lt;li&gt;It shall blink.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;I'll tell you about the final result, the electronics and the software that went into it, plus the techniques I used to achieve wearable electronics. I'll introduce you to the &lt;a href="http://www.arduino.cc/"&gt;Arduino&lt;/a&gt;, an open-source microcontroller prototyping platform, which is an exhilarating tool/toy for making your software skills manifest in the physical world.&lt;br /&gt;&lt;br /&gt;My husband and I have been teaching ourselves electronics. A few months ago, Dad taught me to solder. I recently read Syuzi Pakhchyan's excellent primer on wearable electronics and smart materials, &lt;a href="http://www.librarything.com/work/5874825/book/47829579"&gt;&lt;i&gt;Fashioning Technology&lt;/i&gt;&lt;/a&gt;. And I've been &lt;a href="http://blog.makezine.com/archive/2009/10/ambient_led_flowerpot_clock.html"&gt;making things&lt;/a&gt; with my Arduino. All these ideas were swirling and combining in my head to inspire this year's Halloween project. Er, &lt;em&gt;costume&lt;/em&gt;. Same difference.&lt;br /&gt;&lt;br /&gt;What was I? I was a nightmare... the thing under your bed... the reason for your well developed sense of paranoia...&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/spyderella/sets/72157622735987434/"&gt;&lt;img src="http://farm3.static.flickr.com/2609/4076005063_851a85338f_m.jpg" width="161" height="240" alt="The thing under your bed" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I sported a crop of writhing eyeballs erupting from my head. Each eyeball has an LED inside it, and they blink randomly and independently, until I trigger a hidden switch, which causes the blinky ones to go dark and two red eyes to pulse menacingly. In the &lt;a href="http://www.flickr.com/photos/spyderella/sets/72157622735987434/"&gt;Flickr photoset&lt;/a&gt;, you can see the construction process. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Arduino Sketch&lt;/h2&gt;&lt;br /&gt;The term "Arduino" is overloaded to mean:&lt;ol&gt;&lt;li&gt;a particular chip and circuit board which you can buy or build;&lt;/li&gt;&lt;li&gt;the IDE in which you write programs for the chip;&lt;/li&gt;&lt;li&gt;the language, which is C-flavored;&lt;/li&gt;&lt;li&gt;fun.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Arduino programs are called sketches. Every sketch must contain two functions: setup (runs once) and loop (runs continuously). Here's my sketch, with extra explanatory comments, that blinks the six regular eyeballs and responds to the switch by pulsing the red eyeballs.&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:600px; height: 400px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;#define&lt;/span&gt; SWITCH 8&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;int&lt;/span&gt; ledPins[] = {2, 3, 4, 5, 6, 7};&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;int&lt;/span&gt; ledPinsCount = 6;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;int&lt;/span&gt; redEyePins[] = {10, 11};&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;int&lt;/span&gt; redEyePinsCount = 2;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;long&lt;/span&gt; durations[ledPinsCount];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;int&lt;/span&gt; ledStates[ledPinsCount];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;long&lt;/span&gt; previousTimes[ledPinsCount];&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;int&lt;/span&gt; i;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; setup()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; pinMode(SWITCH, INPUT); &lt;span style="color: green;"&gt;//Specify the switch pin as an input.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; redEyePinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; pinMode(redEyePins[i], OUTPUT); &lt;span style="color: green;"&gt;//Specify each red-eye LED pin as an output.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; ledPinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; pinMode(ledPins[i], OUTPUT); &lt;span style="color: green;"&gt;//Specify each regular LED pin as an output.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; ledStates[i] = random(1); &lt;span style="color: green;"&gt;//Randomly set the LEDs to on or off (1 or 0).&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; durations[i] = GetRandomDuration(); &lt;span style="color: green;"&gt;//Define a random duration for each LED to stay in that state.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; previousTimes[i] = 0; &lt;span style="color: green;"&gt;//At time of setup, the &amp;quot;last time we changed&amp;quot; is at 0 milliseconds, the start of time.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; loop()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (digitalRead(SWITCH) == HIGH)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; TurnOffLeds();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; PulseRedEyes();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; redEyePinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; digitalWrite(redEyePins[i], LOW); &lt;span style="color: green;"&gt;//Turn the red eyes all the way off.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; ledPinsCount; i++) &lt;span style="color: green;"&gt;//For each LED:&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (millis() - previousTimes[i] &amp;gt; durations[i])&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ChangeLed(i); &lt;span style="color: green;"&gt;//If this one's duration is up, then flip it.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; TurnOffLeds()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; ledPinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; digitalWrite(ledPins[i], LOW);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; PulseRedEyes()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;//Fade on, then off.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;int&lt;/span&gt; j;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(j = 0; j &amp;lt; 255; j+=5)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; redEyePinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;68&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;69&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; analogWrite(redEyePins[i], j);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;70&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; delay(10);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;71&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;72&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;73&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(j = 255; j &amp;gt; 0; j-=5)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;74&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;75&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt;(i = 0; i &amp;lt; redEyePinsCount; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;76&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;77&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; analogWrite(redEyePins[i], j);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;78&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; delay(10);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;79&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;80&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;81&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;82&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;83&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; ChangeLed(&lt;span style="color: blue;"&gt;int&lt;/span&gt; ledPin)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;84&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;85&lt;/span&gt;&amp;nbsp;&amp;nbsp; previousTimes[ledPin] = millis(); &lt;span style="color: green;"&gt;//Update the &amp;quot;last time we changed&amp;quot; to now.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;86&lt;/span&gt;&amp;nbsp;&amp;nbsp; durations[ledPin] = GetRandomDuration(); &lt;span style="color: green;"&gt;//Give it a new random duration.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;87&lt;/span&gt;&amp;nbsp;&amp;nbsp; ledStates[ledPin] = 1 - ledStates[ledPin]; &lt;span style="color: green;"&gt;//Flip the state between on and off.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;88&lt;/span&gt;&amp;nbsp;&amp;nbsp; digitalWrite(ledPins[ledPin], ledStates[ledPin]); &lt;span style="color: green;"&gt;//Set the LED to that state.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;89&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;90&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;91&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;long&lt;/span&gt; GetRandomDuration()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;92&lt;/span&gt;&amp;nbsp;{&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;93&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;//Random number between 1 and 10, then multiplied by 400 to give it a detectable duration.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;94&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; random(1, 10) * 400;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;95&lt;/span&gt;&amp;nbsp;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I like the way the eyes blink independently. If they all flashed in unison, they would look like Christmas lights, and you would notice that two were "special" because they weren't flashing. Instead, the duration that any given eyeball is lit or dark constantly changes. &lt;br /&gt;&lt;br /&gt;The blinking is managed by a collection of arrays. One array represents each of my LED pins, so that I can address them in a for loop. The three other arrays hold: the state (on/off) of each LED; the duration each LED should stay in that state; the reading from the millisecond counter when the LED last flipped its state. Each time the loop function executes, if the switch is not connected, then I look at each LED; if the difference between the current time and the time when it previously changed is greater than its duration, flip its state (from off to on, or from on to off), randomly assign it a new duration, and record "now" as the new "previously changed" time. If the switch &lt;em&gt;is&lt;/em&gt; connected, then I make the red eyes fade on and fade off.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Fading with PWM&lt;/h2&gt;&lt;br /&gt;PWM (Pulse-Width Modulation) is a technique for making a digital component (one that turns on or off) simulate analog behavior (be a little bit on, and then a little bit more on). If you turn an LED off and on really quickly, you won't perceive the flickering, but it will look half as bright, because it is actually off for half the time. If you let it spend a little more time off than on, it will appear even dimmer. So by varying the width of the pulses, you can control how bright the LED looks. &lt;br /&gt;&lt;br /&gt;The Arduino comes with built-in PWM functions; some pins are already set up to be PWM pins. If you plug an LED into one of the PWM pins, then you can write to it as if it were an analog component. That's why, in my sketch above, I set the brightness of the red eyes using &lt;em&gt;analogWrite()&lt;/em&gt;, instead of digitalWrite(). My for loop increments the counter j from 0 to 255, and sets the brightness of both red eyes to the value of j. The Arduino takes care of (imperceptibly) flickering the LEDs with the right ratio of on-time and off-time to achieve a j amount of brightness. So the eyes get gradually brighter, then gradually dimmer. (Then control returns to the main loop function, but if my switch is still connected, the red eyes will throb again.)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Snaps: Wearable Plugs&lt;/h2&gt;&lt;br /&gt;A metal sewable snap is like a plug for your clothing, an interface between the world of textiles and the world of wires. This is handy when you need the electronics to be separate while you are getting into the clothing, or if you want to wash the clothing. My Arduino hung out at the base of my neck, to be near the LEDs on my head but hidden underneath my wig, but my control switch was near my hip. I could have run a wire down to the switch, but conductive thread was more subtle and more comfortable.&lt;br /&gt;&lt;br /&gt;To complete the connection, I soldered a short wire to one side of the snap. That wire plugged into a pin on the Arduino. The conductive thread ran from the switch at my hip up to the back of my dress near the Arduino, and I sewed that conductive thread to the other half of the snap. When the two halves are snapped together, the wire and the thread make a complete connection, as if they were one continuous wire. &lt;br /&gt;&lt;a href="http://www.flickr.com/photos/spyderella/4085497865/" title="Soldered snaps / Sewn snaps by Spyderella, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2584/4085497865_a50e4e45d1_m.jpg" width="240" height="180" alt="Soldered snaps / Sewn snaps" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I had two threads (going out to the switch and back), so I encased them each in a bias tape tube, to prevent them from touching each other and shorting out.&lt;br /&gt;&lt;br /&gt;I've been saying "switch," but actually, I simplified at the 11th hour. I tied each thread around a safety pin, and stuck the pins to my dress. When the safety pins touched each other, they completed the circuit, which the Arduino sketch interpreted as triggering the switch&amp;mdash;cue red-eye glare.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What's Next&lt;/h2&gt;&lt;br /&gt;Soldering and sewing are both liberating skills to possess&amp;mdash;they free up your creativity to make wilder and more integrated stuff. If you are currently proficient with only one, ask around and see if you can find a buddy who's good at the other, and teach each other.&lt;br /&gt;&lt;br /&gt;The Arduino comes with a great community of hackers and makers, lots of people to learn from and collaborate with. Definitely check it out. There is lots of fun to be had, and blinking LEDs is the barest beginning of what it can do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-4590327380219080543?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/4590327380219080543/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=4590327380219080543" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4590327380219080543?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4590327380219080543?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/11/happy-hack-o-ween-electronics-and.html" title="Happy Hack-o-ween: Electronics and a microcontroller spice up the haunt" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm3.static.flickr.com/2609/4076005063_851a85338f_t.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUUGRXw4eip7ImA9WxNWFEU.&quot;"><id>tag:blogger.com,1999:blog-69451.post-4118341339839165433</id><published>2009-10-13T21:24:00.002-05:00</published><updated>2009-10-13T21:27:04.232-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-13T21:27:04.232-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title>Refactoring Dinner: Interfaces instead of Inheritance</title><content type="html">Last time, in &lt;a href="http://www.invisible-city.com/sharon/2009/08/cooking-up-good-template-method.html"&gt;Cooking Up a Good Template Method&lt;/a&gt;, I had a template method cooking our dinner. An abstract base class defined the template&amp;mdash;the high level steps for preparing a one-skillet dinner&amp;mdash;and a derived class provided the implementation for those steps. I'm currently reading &lt;a href="http://www.pragprog.com/titles/kpiod/interface-oriented-design"&gt;Ken Pugh's &lt;i&gt;Interface Oriented Design&lt;/i&gt;&lt;/a&gt; (more on that after I finish the book), and it got me thinking of a way to change the design to use interfaces instead of inheritance. &lt;br /&gt;&lt;br /&gt;I think there's value in this refactoring because it allows future flexibility and testability. Let's stroll through it, and I welcome your thoughts about how (and whether) this improves the code.&lt;br /&gt;&lt;br /&gt;Previously, we had a base class SkilletDinner, which was extended by variants on that theme, such as chicken with onions and bell peppers or the FancyBaconPankoDinner. (If I've learned one thing from my readership, it is that blog posts should mention bacon. Mm, crispy bacon.) As the first step in the refactoring, I'll create an interface, ISkilletCookable that provides the same methods that were previously abstract methods in SkilletDinner. By naming convention, the interface is prefixed with 'I' and is an adjective describing how it can be used (-able).&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ISkilletCookable&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddSauceAndGarnish();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Next, I'll create a SkilletDinner constructor that accepts an ISkilletCookable, and change the SkilletDinner's Cook() method to ask that cookable to do the work. SkilletDinner no longer needs to be abstract.&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ISkilletCookable&lt;/span&gt; cookable;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; SkilletDinner(&lt;span style="color: #2b91af;"&gt;ISkilletCookable&lt;/span&gt; cookable)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.cookable = cookable;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Cook()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.HeatFat();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteSavoryRoot();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteProtein();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteVegetables();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.AddSauceAndGarnish();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Then, FancyBaconPankoDinner implements ISkilletCookable and provides implementations for each of the methods that will be called by the Cook() method. &lt;br /&gt;&lt;br /&gt;The first benefit from this refactoring is flexibility. While FancyBaconPankoDinner could not have inherited multiple classes (no multiple inheritance in C#), it &lt;em&gt;can&lt;/em&gt; implement multiple interfaces. For example, it could also implement the IShoppable interface, thereby providing a ListIngredients() method that would let me include it in my grocery list.&lt;br /&gt;&lt;br /&gt;This refactoring also makes it easier for me to test the quality and completeness of my template method. I can verify&amp;mdash;does it cover all of the requisite steps for cooking a skillet dinner?&amp;mdash;by creating &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html#ChoosingBetweenTheDifferences"&gt;behavior-verifying tests&lt;/a&gt; that assess the SkilletDinner's interactions with the ISkilletCookable interface. When I'm writing unit tests for the SkilletDinner class, I want to test its behavior because &lt;em&gt;the behavior is what's important&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;To forestall objections, I tried writing a test around the old version, creating my own mock class that extends the old abstract SkilletDinner. It got pretty lengthy.&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; height: 300px; width:500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinnerSpecs&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [TestFixture]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;When_told_to_cook&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; heatFatMethod = &lt;span style="color: #a31515;"&gt;&amp;quot;HeatFat&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; sauteSavoryRootMethod = &lt;span style="color: #a31515;"&gt;&amp;quot;SauteSavoryRoot&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; sauteProteinMethod = &lt;span style="color: #a31515;"&gt;&amp;quot;SauteProtein&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; sauteVegetablesMethod = &lt;span style="color: #a31515;"&gt;&amp;quot;SauteVegetables&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; addFinishingTouchesMethod = &lt;span style="color: #a31515;"&gt;&amp;quot;AddFinishingTouches&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Should_follow_dinner_preparation_steps_in_order()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; systemUnderTest = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MockSkilletDinner&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; expectedMethodCalls = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expectedMethodCalls.Add(heatFatMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expectedMethodCalls.Add(sauteSavoryRootMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expectedMethodCalls.Add(sauteProteinMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expectedMethodCalls.Add(sauteVegetablesMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expectedMethodCalls.Add(addFinishingTouchesMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; systemUnderTest.Cook();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(expectedMethodCalls.Count, systemUnderTest.CalledMethods.Count, &lt;span style="color: #a31515;"&gt;&amp;quot;Expected number of called methods did not equal actual.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; expectedMethodCalls.Count; i++)&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(expectedMethodCalls[i], systemUnderTest.CalledMethods[i]);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MockSkilletDinner&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt; CalledMethods = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CalledMethods.Add(heatFatMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CalledMethods.Add(sauteSavoryRootMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CalledMethods.Add(sauteProteinMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CalledMethods.Add(sauteVegetablesMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;59&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;60&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;61&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddFinishingTouches()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;62&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;63&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CalledMethods.Add(addFinishingTouchesMethod);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;64&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;65&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;66&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;67&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;In the new design, I can mock the ISkilletCookable interface with a mocking framework like Rhino.Mocks. The interface is easy to mock because interfaces, being the epitome of abstractions, readily lend themselves to being replaced by faked implementations. Rhino.Mocks takes care of recording and verifying which methods were called.&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; border: 1px solid #ccc; overflow: auto; width:500px;"&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinnerSpecs&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;TestFixture&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;When_told_to_cook&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;span style="color: #2b91af;"&gt;Test&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Should_follow_dinner_preparation_steps_in_order()&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; mocks = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MockRepository&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; cookable = mocks.StrictMock&amp;lt;&lt;span style="color: #2b91af;"&gt;ISkilletCookable&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; systemUnderTest = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;(cookable);&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; (mocks.Record())&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; (mocks.Ordered())&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.HeatFat();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteSavoryRoot();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteProtein();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.SauteVegetables();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cookable.AddSauceAndGarnish();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;using&lt;/span&gt; (mocks.Playback())&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; systemUnderTest.Cook();&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The test relies on Rhino.Mocks to create a mock implementation of ISkilletCookable, and then verifies that the system under test, the SkilletDinner, interacts correctly with ISkilletCookable by telling it what steps to do in what order. &lt;br /&gt;&lt;br /&gt;That test is quite cognizant of the inner workings of the SkilletDinner.Cook() method, but that's specifically what I'm unit testing: Does the template method do the right steps? I don't mind how the steps are done, but you have to start the onions before you add the meat, or else the onions won't caramelize and flavor the oil.&lt;br /&gt;&lt;br /&gt;By the way, if you had previously found the learning curve for Rhino.Mocks' record/playback model too steep a hill to climb (or to convince your teammates to climb), check out &lt;a href="http://www.ayende.com/Wiki/Rhino%20Mocks%203.5.ashx"&gt;Rhino.Mocks 3.5's arrange-act-assert style&lt;/a&gt;. It creates more readable tests, putting statements in a more intuitive order. I really like it. I could not, however, use it here because I have not found a way to enforce ordering of the expectations (i.e., to assert that method A was called before B, and to fail if B was called before A) in A-A-A-style. So we have a record/playback test, instead.&lt;br /&gt;&lt;br /&gt;Here's a summary of the refactoring. I extracted an interface, ISkilletCookable, and composed SkilletDinner with an instance of that interface, liberating us from class inheritance. Because SkilletDinner is now given the worker it depends on (via dependency injection), I can give it a fake worker in my tests, so that my unit tests don't need to perform the time- and resource-consuming operation of firing up the stove. And I managed to write another blog post that mentions bacon. Mm, bacon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-4118341339839165433?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/4118341339839165433/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=4118341339839165433" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4118341339839165433?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/4118341339839165433?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/10/refactoring-dinner-interfaces-instead.html" title="Refactoring Dinner: Interfaces instead of Inheritance" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE4NSHs4cCp7ImA9WxNSFUs.&quot;"><id>tag:blogger.com,1999:blog-69451.post-937580397471093833</id><published>2009-08-29T12:18:00.004-05:00</published><updated>2009-08-29T12:29:59.538-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-29T12:29:59.538-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="designpatterns" /><title>Cooking Up a Good Template Method</title><content type="html">The software concept of "raising the level of abstraction" has improved my skill and creativity in cooking, by teaching me to think about recipe components in terms of their properties and functions. Practicing abstraction-raising in cooking feeds back to help me with coding; for example, keeping me from going astray the other day with the &lt;a href="http://en.wikipedia.org/wiki/Template_method_pattern"&gt;Template Method pattern&lt;/a&gt;. This post is more about coding than cooking. The cooking's a metaphor. (The cake is a lie.)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Abstract Cooking&lt;/strong&gt;&lt;br /&gt;My skill with cooking grew from rote recipe following to intuitive creation when I started to think of it in terms borrowed from software: raising the level of abstraction.&lt;br /&gt;&lt;br /&gt;Consider a week-night skillet dinner. If I told you to heat canola oil in a cast-iron skillet, saute slices of onion and chunks of chicken seasoned with salt and pepper, and toss in bell peppers cut into strips, you could probably follow along and make exactly that. But that's pretty limiting. If instead I described the process as using a fat to conduct heat for sauteing a savory root, a seasoned protein, and some vegetables, then you could use that as a template, and make a week of dinners without repeating yourself.&lt;br /&gt;&lt;br /&gt;Let's dive into that step of using a fat for conduction, because it is a cool and useful bit of food science. To cook, you need to get heat onto food. The medium can be air, liquid, or fat. Each creates different results, hence the terms baking, boiling, and frying. When you toss cut-up bits of food in a skillet with oil and repeatedly jostle them, you're sauteing ("saute" means "to jump"), and that oil is playing the role of the fat, which is conducting the heat. If you'll pardon the metaphor, CanolaOil implements the IFat interface.&lt;br /&gt;&lt;br /&gt;It's useful to think of cooking this way, because if you know the properties of the various cooking fats, you can choose the right IFat implementation for the job. Canola oil is heart-healthy and stands up well to stove-top heat. Olive oil has wonderful health benefits, a bold flavor, and an intriguing green color, but those attributes are pretty much obliterated by heat, so save your expensive EVOO for raw applications like salads and dips. Butter makes everything taste better, browns up beautifully, but is harder on the heart and will burn at a low temperature; temper it with an oil like canola to keep it from burning. Peanut oil stands up to heat like a champ, so it's popular for deep frying. Armed with this kind of knowledge, I don't need to check a recipe when I'm cooking; I just think about what I'm trying to accomplish, and choose the right implementation.&lt;br /&gt;&lt;br /&gt;Pam Anderson's &lt;a href="http://www.librarything.com/work/67701"&gt;&lt;i&gt;How to Cook Without a Book&lt;/i&gt;&lt;/a&gt; got me thinking about food this way, and Harold McGee's &lt;a href="http://www.librarything.com/work/44636"&gt;&lt;i&gt;On Food and Cooking&lt;/i&gt;&lt;/a&gt; provides a feast of food geekery to fill in all the particulars.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Template Coding&lt;/strong&gt;&lt;br /&gt;Thinking about food this way, raising the level of abstraction, guides my thinking about code. My meal preparation follows the Template Method pattern, as does a class my teammate and I needed to modify recently.&lt;br /&gt;&lt;br /&gt;In this example, our application sends instructions to various external systems. The specifics of how those systems like to hold their conversations vary between systems. However, the series of steps, when phrased in our core business terms, remain the same. You do A, then you do B, then you do C, in whatever way a particular instance likes to do A, B, and C.&lt;br /&gt;&lt;br /&gt;Here's my class with its template method, translated back to the dinner metaphor:&lt;br /&gt;&lt;div style="border: 1px solid #ccc; font-family: Courier New; font-size: 8pt; color: black; background: white;  width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Cook()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;But lo, I encountered an external system that needed to do one extra little thing. I needed a special step, just for that one instance. Like dinner the other night, where the vegetable was asparagus, the fat was bacon (oh ho!), and the final step was to toss some panko breadcrumbs into the pan to brown and toast and soak up the bacony love.&lt;br /&gt;&lt;br /&gt;How do I extend my template method to accommodate an instance-specific step?&lt;br /&gt;&lt;br /&gt;One idea that floated by was to make the method virtual, so that we could override it in our special instance. But we still wanted the rest of the steps, so we'd have to copy the whole method into the new instance, just to add a few lines. Also, anybody else could override that template, too, so that when they were told to do A, B, and C, they could totally fib and do nothing of the sort.&lt;br /&gt;&lt;div style="border: 1px solid #ccc; font-family: Courier New; font-size: 8pt; color: black; background: white; overflow: auto; height: 300px; width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;virtual&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Cook()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Note: The Cook template method is now virtual,&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//and can be overridden in deriving classes. &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//That's not good.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;LazyDinner&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Cook()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; OrderPizza();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//We're overriding the template and *cheating*!&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Although, if it's Austin's Pizza, &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//maybe that's okay...&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OrderPizza()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//With extra garlic!&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat() { }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot() { }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein() { }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables() { }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;That LazyDinner class isn't really a SkilletDinner at all; its behavior is completely different. No, that option flouts the whole point of the Template Method pattern.&lt;br /&gt;&lt;br /&gt;Our better idea was to make one small change to the template method, adding an extension point. That is, a call to a virtual method which in the base implementation does nothing, and can be overridden and told to do stuff in specific cases.&lt;br /&gt;&lt;br /&gt;Back to dinner:&lt;br /&gt;&lt;div style="border: 1px solid #ccc; font-family: Courier New; font-size: 8pt; color: black; background: white; overflow: auto; height: 300px; width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Cook()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;11&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AddFinishingTouches(); &lt;span style="color: green;"&gt;//Here's the hook.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;virtual&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddFinishingTouches()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//By default, do nothing.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;abstract&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;FancyBaconPankoDinner&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;SkilletDinner&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;27&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddFinishingTouches()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;28&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;29&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//In this case, override this extensibility hook:&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;30&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ToastBreadcrumbs();&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;31&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;32&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;33&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ToastBreadcrumbs()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;34&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;35&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Toss in the bacon fat; keep 'em moving.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;36&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;37&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;38&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HeatFat()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;39&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;40&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Cook bacon, set aside, drain off some fat.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;41&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;42&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;43&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteSavoryRoot()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;44&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;45&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Minced garlic, until soft but before browning&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;46&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;47&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;48&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteProtein()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;49&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;50&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//How about... tofu that tastes like bacon?&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;51&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;52&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;53&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SauteVegetables()&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;54&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;55&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Asparagus, cut into sections. &lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;56&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//Make it bright green and a little crispy.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;57&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;58&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;This maintains the contract of the template method, while allowing for special cases. With the right extensibility hooks in place, my dinner preparation happily follows the &lt;a href="http://www.blogger.com/blogs/joe_ocampo/archive/2008/03/21/ptom-the-open-closed-principle.aspx"&gt;Open-Closed Principle&lt;/a&gt;—open for extension, but closed for modification.&lt;br /&gt;&lt;br /&gt;I enjoy the way my various hobbies feed into and reflect upon each other. I hope this post has given you some useful insight into the Template Method pattern, or dinner preparation, or both. Look for synergies amongst your own varied interests; it can be the springboard for some truly breakthrough ideas.&lt;br /&gt;&lt;br /&gt;Mmm, bacon...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-937580397471093833?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/937580397471093833/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=937580397471093833" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/937580397471093833?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/937580397471093833?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/08/cooking-up-good-template-method.html" title="Cooking Up a Good Template Method" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;CkMCR3o_cCp7ImA9WxJWFU0.&quot;"><id>tag:blogger.com,1999:blog-69451.post-2479474745694306033</id><published>2009-06-20T07:19:00.000-05:00</published><updated>2009-06-20T07:21:06.448-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-20T07:21:06.448-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="DDD" /><category scheme="http://www.blogger.com/atom/ns#" term="collaboration" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>Inconvenient Accessibility Makes Self-Documenting Code</title><content type="html">Intentional use of &lt;a href="http://msdn.microsoft.com/en-us/library/ms173121.aspx"&gt;access modifiers&lt;/a&gt; (public, private, etc.) is like a clear memo to your team. This came up during &lt;a href="http://unhandled-exceptions.com/blog/"&gt;Steve Bohlen&lt;/a&gt;'s &lt;a href="http://www.virtualaltnet.com/"&gt;Virtual Alt.Net&lt;/a&gt; talk on &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;domain-driven design&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Steve explained the distinction between Entity objects, which have a unique identity independent of their properties (Even when I change my name, I'm still me.), and Value objects, which are defined by their properties (If you change the house number in an address, you have a new address.). When dealing with Entities, code should not be able to change the unique id&amp;mdash;that would be like someone claiming your social security number and thereby &lt;em&gt;becoming&lt;/em&gt; you. Therefore, Entity classes should have &lt;em&gt;private&lt;/em&gt; setters for their unique identifiers.&lt;br /&gt;&lt;br /&gt;A meeting attendee asked why, since this gets inconvenient when you're creating an object based on a record fetched from the persistence repository. It's a big pain; why bother? The analogy I would offer is this. When you're defining a class to represent an Entity in your business domain, you know it's an Entity. You intend for it to behave and be treated like an Entity. You don't want any of your teammates setting its unique id in their code. So you send them an email: "Don't set Person.UniqueId, okay?" Uh hunh. How well is &lt;em&gt;that&lt;/em&gt; going to work over time?&lt;br /&gt;&lt;br /&gt;Instead, if you simply don't provide a public accessor to the UniqueId property, your teammates will get the message loud and clear. Granted, someone could edit the code and change the accessibility, but the fact that he or she needs to is a flashing neon sign saying "Stop. Think. Are you barking up the wrong tree?" You've made your code communicative. Its structure conveys your intent. No need for comments; this is an example of self-documenting code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-2479474745694306033?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/2479474745694306033/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=2479474745694306033" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/2479474745694306033?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/2479474745694306033?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/06/inconvenient-accessibility-makes-self.html" title="Inconvenient Accessibility Makes Self-Documenting Code" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUYAQXs4fyp7ImA9WxJQGE0.&quot;"><id>tag:blogger.com,1999:blog-69451.post-3309192540867741942</id><published>2009-05-31T15:37:00.004-05:00</published><updated>2009-05-31T15:52:20.537-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-31T15:52:20.537-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tools" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>Giving Mono to my Husband</title><content type="html">Holy crossed-platforms, Batman! How did I not know about &lt;a href="http://www.mono-project.com/Main_Page"&gt;Mono&lt;/a&gt;, the free, open-source framework that will run .NET applications on Linux and Mac OS X?&lt;br /&gt;&lt;br /&gt;Not to get too personal, but I'm part of a mixed marriage: I run Windows and develop primarily in C#; my husband runs OS X and is not (actively) a programmer. Through love and mutual respect, we make it work. But what we have so far &lt;em&gt;not&lt;/em&gt; been able to make work is my writing handy utilities and toys that he can use on his laptop.&lt;br /&gt;&lt;br /&gt;I learned about Mono in &lt;a href="http://codebetter.com/blogs/rodpaddock/default.aspx"&gt;Rod Paddock's&lt;/a&gt; intro to the May/June issue of &lt;a href="http://www.code-magazine.com/"&gt;CoDe Magazine&lt;/a&gt;. Then I came home, had Jon install Mono on his Mac, and gave him a quick little console app I'd written in C#. It ran like a charm. A WinForms app with one button and a popup message also ran, looking distinctly X11-y. &lt;br /&gt;&lt;br /&gt;This is super exciting for us. We've been talking about a card-game playtest simulator, to help with his creation of &lt;a href="http://www.invisible-city.com/"&gt;card games&lt;/a&gt;. (Jon posts one free board game a month and has a few upcoming commercial releases.) That process usually involves a significant investment in card stock and time with the paper cutter, just to see how hands of cards come together and move through the game. A simulator would help him to vet the first and maybe second drafts of the cards without printing them out. Now that I know I can build something he'll be easily able to run, it's time to start designing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-3309192540867741942?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/3309192540867741942/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=3309192540867741942" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3309192540867741942?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3309192540867741942?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/05/giving-mono-to-my-husband.html" title="Giving Mono to my Husband" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEcAQXg_cCp7ImA9WxJTFko.&quot;"><id>tag:blogger.com,1999:blog-69451.post-904452077080661170</id><published>2009-04-25T11:08:00.001-05:00</published><updated>2009-04-25T11:14:00.648-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-25T11:14:00.648-05:00</app:edited><title>Got the 0000FFs</title><content type="html">Given up on attaching meaning to those three- or six-character codes that define colors in HTML and CSS? Sure, you can use an online color picker, but let me give you a nuts-and-bolts explanation of what they mean. This info is worth having because:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's a time-saver. If you want to make a color a little more blue, or a little less saturated, you can do the math in your head and take care of it right there in your editor.&lt;/li&gt;&lt;li&gt;It gives you more options. If you find a cracking color combo in the &lt;a href="http://www.librarything.com/work/12738"&gt;Color Index&lt;/a&gt;, but it's given only in RGB values, you can convert it to HTML-ready values using just &lt;em&gt;math.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;It's satisfying. Don't you prefer knowing how something works, instead of just how to work with it?&lt;/li&gt;&lt;li&gt;It will be diverting. There will be stories, you know me.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Two experiences in my childhood laid the foundation for my understanding of hex color codes, so I will share them with you. (See? Stories.)&lt;br /&gt;&lt;br /&gt;When I was very young, I learned that the three primary colors are red, yellow, and blue, and when you mixed them together you got, well, mud, but theoretically black. That's true for pigments (paint and ink; think magazines and newspapers), and if you're going to be pedantic, those pigment primary colors are properly called magenta, yellow, and cyan. (Add blacK and you have CMYK, the other color scheme you'll see mentioned in design books.) But it's a whole 'nother ball game when you are mixing &lt;em&gt;light&lt;/em&gt; instead of pigment, and computer monitors are big light bulbs.&lt;br /&gt;&lt;br /&gt;My seventh-grade science teacher, Mr. Saeger, created an excellent demonstration that I still think of when I'm mixing up hex color codes. He set up the overhead projector. He placed a square of red cellophane on the projector, and it threw a red square of color up on the wall. Sure. Then he added a piece of green cellophane, and the area where they overlapped was... yellow? That's curious. Last he added a piece of blue, and the intersection of all three was &lt;em&gt;white&lt;/em&gt;. It blew my mind.&lt;br /&gt;&lt;br /&gt;If you can replicate this effect (shine a light through overlapping colored plastics), it's a great science experiment to share with your kids. It will help you remember the mixing of light colors with the same intuition you have for mixing pigments. And it's cool.&lt;br /&gt;&lt;br /&gt;The second formative experience from my youth was working the stage lights in my high school theater. Hanging above the stage were three rows of lights; the lights alternated amongst white, yellow, red, and blue, and were controlled by a huge wall of levers backstage. Big, creaky, ancient things, that really let you know you were &lt;em&gt;working the lights.&lt;/em&gt; I had to crouch and get my shoulder under them to move the big ones.&lt;br /&gt;&lt;br /&gt;Picture them: Four rows of colored levers, corresponding to each color of light out over the stage. Each lever controlled a light. Down was off, and as you pushed the lever up, the light would gradually brighten. A big handle at the end of a row would move all the levers of that color, so you could, for example, bring up all the whites in unison. You could slowly turn down the yellows over the course of a scene while a teammate pushed up the reds, and make a sunset. You could push all the colors up to make the light full and cheery (and make the stage hotter than a tanning booth), or pull them all down to plunge the stage into darkness at the dramatic conclusion of Act I.&lt;br /&gt;&lt;br /&gt;Levers... lights... hex codes, here we go.&lt;br /&gt;&lt;br /&gt;Light is mixed from red, green, and blue. (Remember the order: RGB, RGB, RGB.) Computers like to count not from 1 to 100, but from 0 to 255. Think of 0 as off, with the lever all the way down, and 255 as on, with the lever all the way up. To make yellow, you need a lot of red and a lot of green, and no blue, so R = 255, G = 255, and B = 0. To make a paler yellow, you want to bring it closer to white. White is all three on at maximum; therefore you need to turn up the blue. Maybe R = 255, G = 255, and B = 153. To make it more orangey, you'd back off the green. And so forth.&lt;br /&gt;&lt;br /&gt;So we have three levers. A hex color code has three pairs of characters. That yellow would be #FFFF00. Put another way: FF, FF, 00. It's the same three RGB values, but in base 16 instead of base 10. 255 in base 10 becomes FF in base 16. Counting in base 16 is like counting in base 10, if you had 6 extra fingers. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10. &lt;br /&gt;&lt;br /&gt;The Math Bits site gives a visual explanation of &lt;a href="http://mathbits.com/mathbits/compsci/Introduction/frombase10.htm"&gt;how to convert from base 10 to other bases&lt;/a&gt;. Also, you can use the calculator on your computer. In Windows, set the calculator to Scientific mode in the View menu, make sure the "Dec" radio button is marked, type in your base-10 number, then switch to the "Hex" radio button and read the converted value. But usually when I'm writing HTML, I just need to nudge a color a little, not do a whole decimal-to-hexadecimal conversion. So it is sufficient to know that all zeroes is all black, all Fs is all white, CC is more "on" than 99, and EE is just a teeny bit less than full on.&lt;br /&gt;&lt;br /&gt;CSS also permits three-character color codes. The same color-mixing is happening there, it's just a shortcut that doubles each character for you. So #ca9 is equivalent to #CCAA99.&lt;br /&gt;&lt;br /&gt;Putting this into practice...&lt;table class="tabular"&gt;&lt;tr&gt;&lt;td style="background-color:#FFFFFF; color:black"&gt;#FFFFFF&lt;/td&gt;&lt;td&gt;Turning all three levers full on makes white.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#CCCCCC; color:black"&gt;#CCCCCC&lt;/td&gt;&lt;td&gt;Backing them off a little, but keeping them all equal, makes gray.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#000000; color:white"&gt;#000000&lt;/td&gt;&lt;td&gt;Turning them all off: Black.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#FF0000; color:white"&gt;#FF0000&lt;/td&gt;&lt;td&gt;Red on and the rest off makes red.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#990000; color:white"&gt;#990000&lt;/td&gt;&lt;td&gt;Turning down the red, so that it moves closer to black, makes a darker red.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#FF6666; color:white"&gt;#FF6666&lt;/td&gt;&lt;td&gt;Turning up the others, so that the whole mix moves closer to white but has more red than anything else, makes pink ("&lt;a href="http://www.archive.org/details/RvsB_E16"&gt;Lightish red!&lt;/a&gt;").&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#FFFF00; color:black"&gt;#FFFF00&lt;/td&gt;&lt;td&gt;Red plus green (when mixing light) make yellow.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#FF9900; color:black"&gt;#FF9900&lt;/td&gt;&lt;td&gt;Keep the red, but reduce the green, to make orange.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#00FFFF; color:black"&gt;#00FFFF&lt;/td&gt;&lt;td&gt;Green and blue make teal.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="background-color:#FF00FF; color:black"&gt;#FF00FF&lt;/td&gt;&lt;td&gt;Red and blue make purple.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;So there you have it: An explanation of hex color codes by way of my seventh-grade science class and my high school drama&amp;mdash;er, drama &lt;em&gt;department&lt;/em&gt;. Right.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-904452077080661170?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/904452077080661170/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=904452077080661170" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/904452077080661170?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/904452077080661170?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/04/got-0000ffs.html" title="Got the 0000FFs" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C04MSXs5eip7ImA9WxVVEEk.&quot;"><id>tag:blogger.com,1999:blog-69451.post-1065191511471058806</id><published>2009-03-02T18:35:00.005-06:00</published><updated>2009-03-02T18:59:48.522-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-02T18:59:48.522-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="designpatterns" /><category scheme="http://www.blogger.com/atom/ns#" term="code" /><title>The Null Object Pattern: When a slacker is just what you need</title><content type="html">I had a challenge that was neatly solved by the &lt;a href="http://en.wikipedia.org/wiki/Null_Object_pattern"&gt;Null Object pattern&lt;/a&gt;. I'd like to share it with you, so that I can explore the idea and provide a practical example.&lt;br /&gt;&lt;br /&gt;Simplifying a bit, I have a Person object, and I need to fill it with details retrieved from an external system. When I started looking at the code, the call to look up the Person attributes took a Person as a passed-in parameter and modified it. That struck me as bad behavior ("Hey! I gave you that so you could use it, but I didn't expect you to &lt;em&gt;change&lt;/em&gt; it. Sheesh."). I thought it would be more honest for the method to return information, which the controlling class could use to update the Person object if it chose to.&lt;br /&gt;&lt;br /&gt;Let me name the players, to make this easier to follow. I have a class coordinating activities that, in our business context, is called a Translator. I created a Client that makes the actual calls to the external system. Before the refactoring, the Translator would call Client.Lookup(Person). The Client would create a message to the external system, get back a response, and use it to set attributes in the Person.&lt;br /&gt;&lt;br /&gt;I changed Client.Lookup so that it does not change the Person, and instead returns a Response that contains the needed attributes. But if the external system did not have any info to return, should Lookup return null, throw an exception, ...?&lt;br /&gt;&lt;br /&gt;Usually the most appropriate answer to this question is to throw an exception. If no info means you're in an invalid state or an unknown state, then it is not safe to continue, and the code should throw. In this case, though, we &lt;em&gt;could&lt;/em&gt; continue. We didn't require the info coming back from the external system; it was just handy if available. &lt;br /&gt;&lt;br /&gt;So I return null? But that means every time I call Client.Lookup, I have to check whether the Response is null before I use it. And so does anyone else who might be calling it in the future. It seems disingenuous for a method to say, "I'll give you a Response, but I might actually give you an empty bag. I hope you've guessed I might do that and planned accordingly."&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; overflow: auto; width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; DoFancyBusinessSteps(&lt;span style="color: #2b91af;"&gt;Person&lt;/span&gt; person)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;Response&lt;/span&gt; response = client.Lookup(person);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (response != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; person.Address = response.Address;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; person.ExternalSystemId = response.ExternalSystemId;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;19&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;20&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//More stuff based on the Person...&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;I'd rather return an object that is safe to use, regardless of what answer we got from the external system, and is helpful if we received useful info. This is the Null Object pattern.&lt;br /&gt;&lt;br /&gt;I created an IResponse interface that exposes one method, Update(Person). Next I created two implementations of that interface, a Response and a NoDataResponse. &lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; overflow: auto; width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; DoFancyBusinessSteps(&lt;span style="color: #2b91af;"&gt;Person&lt;/span&gt; person)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;13&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;14&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: #2b91af;"&gt;IResponse&lt;/span&gt; response = client.Lookup(person);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;15&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; response.Update(person);&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;16&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;17&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: green;"&gt;//More stuff based on the Person...&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;18&lt;/span&gt;&amp;nbsp;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Response.Update uses its fields to set properties on the Person (with a method name that clearly states it is doing so). NoDataResponse.Update quietly does nothing. This allows the Translator to ask the Client to look up info about the Person, and ask the resulting Response to update the Person.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Courier New; font-size: 8pt; color: black; background: white; overflow: auto; width:500px;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;NoDataResponse&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IResponse&lt;/span&gt;&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;22&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;23&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Update(&lt;span style="color: #2b91af;"&gt;Person&lt;/span&gt; person)&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;24&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;25&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;26&lt;/span&gt;&amp;nbsp;}&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;I like it. As with all good tools, it's prudent not to over-use it. If quietly doing nothing would leave the Person object in a bad state, so that it blew up or corrupted data when you tried to use it later, then don't use the Null Object pattern. Throw an exception instead. The Null Object pattern is handy when you want to return an object that can do stuff in some conditions and will be harmless in other conditions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-1065191511471058806?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/1065191511471058806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=1065191511471058806" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/1065191511471058806?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/1065191511471058806?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/03/null-object-pattern-when-slacker-is.html" title="The Null Object Pattern: When a slacker is just what you need" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEIHRHo7eyp7ImA9WxVWFUw.&quot;"><id>tag:blogger.com,1999:blog-69451.post-7620026207558061040</id><published>2009-02-24T16:59:00.004-06:00</published><updated>2009-02-24T17:02:15.403-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-24T17:02:15.403-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="collaboration" /><title>Follow-up to the Retrospectives Workshop</title><content type="html">My co-facilitator Suzy wrote up &lt;a href="http://suzywbates.blogspot.com/2009/02/retrospective-workshop.html"&gt;her reflections from the AgileAustin retrospectives workshop&lt;/a&gt;, where she shares more of the great insights that came from the participants.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-7620026207558061040?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/7620026207558061040/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=7620026207558061040" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7620026207558061040?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/7620026207558061040?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/02/follow-up-to-retrospectives-workshop.html" title="Follow-up to the Retrospectives Workshop" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE4EQHc_eCp7ImA9WxVWFEw.&quot;"><id>tag:blogger.com,1999:blog-69451.post-2288874975133510304</id><published>2009-02-21T17:08:00.003-06:00</published><updated>2009-02-23T12:15:01.940-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-23T12:15:01.940-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="collaboration" /><title>Retrospectives: Collaborative Improvement</title><content type="html">Suzy Bates and I facilitated an &lt;a href="http://agileaustin.org/"&gt;AgileAustin&lt;/a&gt; workshop this morning called "Cheaper Than an Off-Site: How to hold effective retrospectives that improve team collaboration and performance." It was absolutely a blast, from planning through delivery. A benefit I didn't anticipate (but should have) is that I learned a lot, myself. I'll share some of those epiphanies here.&lt;br /&gt;&lt;br /&gt;If you were to ask me what &lt;i&gt;one thing&lt;/i&gt; a team could do to improve its delivery of great software on a predictable schedule, I would say: hold effective retrospectives. A retrospective is a regularly recurring discussion where the team reflects on how they work together, and what they will change in order to get better. The end of a sprint, right after the demo, is a good time for this.&lt;br /&gt;&lt;br /&gt;We presented the following as the key ideas:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Safety&lt;/li&gt;&lt;li&gt;Diversity of viewpoints&lt;/li&gt;&lt;li&gt;Collective ownership&lt;/li&gt;&lt;li&gt;Structured discussion&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Being a facilitator for the workshop was a bunch of fun. Collaborating with Suzy was excellent&amp;mdash;meshing our two approaches really enhanced the content, as I brought the philosophy and she brought the practical hands-on exercises, and we kept each other moving and making progress on our preparations. If you're tempted to lead a workshop but daunted, find a teammate.&lt;br /&gt;&lt;br /&gt;The audience participation was even richer than I'd hoped. People enthusiastically contributed, leapt into the exercises with gusto, and shared some striking insights. I learned neat stuff. Here are some highlights:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Rotate who holds the role of retrospective leader (or sponsor). That brings fresh ideas and spreads the sense of shared ownership.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;When a team member expresses dissatisfaction (for example, through a team satisfaction histogram), sometimes it is appropriate to acknowledge it &lt;i&gt;without&lt;/i&gt; delving into why and root cause and solutions. If team safety means I can say how I feel and that's okay, then I should be able to say how I feel without getting interrogated about &lt;i&gt;why&lt;/i&gt; I feel that way.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A bunch of "went well" items without any "needs fixing" items might indicate a lack of team safety. In today's exercise, our sprint teams barely knew each other, so they wanted to be polite, and so they were very positive in their reflections. When you're comfortable with your team and trust them, it becomes easier to talk about areas for improvement. I'd view a series of "everything was great" sessions as indicative of a lurking problem.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.ayeconference.com/appreciativeretrospective/"&gt;Affirmative Inquiry&lt;/a&gt; is a philosophy/strategy worth looking into. It replaces, for example, the negative "why is this broken" by changing it into a positive "what was successful in the past that we could apply here."&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Book recommendation for Jim Highsmith's work (probably &lt;i&gt;&lt;a href="http://www.librarything.com/work/317704"&gt;Agile Project Management&lt;/a&gt;&lt;/i&gt;?).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;If you attended the workshop: Thanks! It rocked. If you weren't able to, keep an eye out for future AgileAustin workshops. They're announced on the &lt;a href="http://tech.groups.yahoo.com/group/agileaustin/join"&gt;AgileAustin email list&lt;/a&gt;, so sign up for that. If you don't live in Austin, well... nanny nanny boo boo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-2288874975133510304?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/2288874975133510304/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=2288874975133510304" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/2288874975133510304?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/2288874975133510304?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/02/retrospectives-collaborative.html" title="Retrospectives: Collaborative Improvement" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;C04CQns6fCp7ImA9WxVSF00.&quot;"><id>tag:blogger.com,1999:blog-69451.post-3650298064955452347</id><published>2009-01-11T13:05:00.003-06:00</published><updated>2009-01-11T13:26:03.514-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-11T13:26:03.514-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><title>Quantifying Benefits on Refactoring Work</title><content type="html">When last we talked about &lt;a href="http://www.invisible-city.com/sharon/2008/11/trouble-with-technical-debt.html"&gt;estimating and prioritizing code maintenance&lt;/a&gt;, we'd left it as an exercise for the reader to devise a method to compare the relative size of the benefit from two different refactorings. In other words, you can work on A or B; which one is likely to give a greater benefit? I've had an idea for how to do this. It even includes some satisfying math.&lt;br /&gt;&lt;br /&gt;Start with the premise that, when estimating the size of &lt;i&gt;effort&lt;/i&gt;, it is sufficient&amp;mdash;nay, preferable&amp;mdash;to compare values in an abstract unit ("story points") that does not map directly to any real-world concept (such as "hours"). When you try to estimate effort in a real-world unit, people get distracted by (hung up on) the wrong details. Better to use an abstract unit that lets you compare the relative sizes of two efforts. Then you can prioritize them ("Let's do the smaller one."), and over time you develop a predictive measure of how many units your team can deliver. Can we create a similarly abstract yet useful unit for comparing &lt;i&gt;benefits&lt;/i&gt;?&lt;br /&gt;&lt;br /&gt;You undertake a refactoring because you want to make the code better. The benefit from this work comprises two pieces: how much you're going to improve an area of the codebase, and how important that area is. Your impact will be made up of how much "betterness" you can impart, and how much the betterness will matter.&lt;br /&gt;&lt;br /&gt;You've probably had a similar experience: You find an area of the code that makes you frankly &lt;i&gt;itch&lt;/i&gt; to improve it. You could dramatically increase its beauty. But it's not really used in very many places, and business needs hardly ever drive you to change it, so its beauty or lack thereof is actually rather insignificant. On the other hand, there's a class that makes you queasy every time you have to interact with it, but it's used everywhere, so changing it would be a huge, risky undertaking. It stays ugly, despite being so important.&lt;br /&gt;&lt;br /&gt;There are a number of intuitive and emotional influences in those decisions, and they interact with each other in additive and multiplicative ways. This is a good place to apply some rigor, to get the emotions out of the way and compare options more objectively. You apply a similar rigor when you tackle a difficult decision by actually &lt;i&gt;writing down&lt;/i&gt; the pros and cons in two columns on a piece of paper, so that you can &lt;i&gt;see&lt;/i&gt; how the two sides stack up. So let's apply that to comparing the possible benefits from two refactorings. We only have time to do one, so we're trying to decide which one to do.&lt;br /&gt;&lt;br /&gt;Consider a questionnaire, with pairs of questions, asking about what the code might be like after you're done.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Future proofing:&lt;/li&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;br /&gt;&lt;li&gt;How much easier will it be to change it the next time?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How often do we get asked to change this area?&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;li&gt;Regression proofing:&lt;/li&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;br /&gt;&lt;li&gt;How much better will our test suite be able to prevent defects in this area?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How business-critical is it that we don't introduce defects in this area?&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;li&gt;Avoiding risk:&lt;/li&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;br /&gt;&lt;li&gt;How likely are we to succeed without creating problems?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How tolerant is our business of risk in this area?&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;li&gt;Improving satisfaction and increasing velocity:&lt;/li&gt;&lt;br /&gt;&lt;ol type="a"&gt;&lt;br /&gt;&lt;li&gt;How likely are we to reduce tech support incidents by this work?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How many of our tech support incidents can be attributed to this area?&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;br /&gt;And so on, with questions that are specific to your own team. Collaborate with your team to create the questions, so that they represent the team's decisions. Note how a pair of questions covers how much improvement and how much that improvement will matter. Also see that for each question, a more emphatic answer is a good thing. For example, the avoiding-risk question asks how likely we are to succeed, not how risky the task is. Questions are phrased so that, the more you say "Yes, a lot," the more that's an endorsement in favor.&lt;br /&gt;&lt;br /&gt;Now, depending on your bent, this next bit will remind you either of a prioritization matrix or a Cosmo quiz. Nevertheless, for each question in your questionnaire, answer a 1, 3, or 5, to represent "barely," "some," "a lot." Then multiply the coordinated a's and b's and add those up: (1a * 1b) + (2a * 2b) + (3a * 3b)... In this way, you represent the multiplicative relationship between How Much Better and How Much Does It Matter.&lt;br /&gt;&lt;br /&gt;We need a unit for these scores. I'm thinking "bunits" (BYOO-nits) because they are a unit of benefit and of beauty. So if you have two refactoring tasks on the table during your sprint planning, and Refactoring A has an effort of 13 story points and a benefit of 17 bunits, while Refactoring B has an effort of 8 story points and 23 bunits, you can lean towards choosing Refactoring B. As with all matrices of this type, if that decision completely flouts your intuition, then discuss it with your team&amp;mdash;maybe your intuition can be calmed, or maybe the questionnaire is failing to cover an important aspect of your work and needs some additional questions.&lt;br /&gt;&lt;br /&gt;The real benefit of refactoring is proven only over time. Keep previous bunit estimates in mind and use those in your comparisons and trade-offs when selecting refactorings to undertake. Add this technique as another tool to help you understand the parameters of your decision, but never to override your own good sense.&lt;br /&gt;&lt;br /&gt;This is a technique for quantifying the benefit of work that does not have a direct dollar ROI. Why quantify benefit, especially in a unit that has no analog in the real world? Two reasons. First, if you're going to prioritize your to-do list, every item needs some sense of effort and some sense of reward. It just makes sense to do easy things with lots of benefit before hard things that barely matter. Second, asking yourself questions like the above imparts rigor to your decision-making process. We are seekers of beauty, and want desperately to clean up whatever icky thing we looked at most recently. Surveying the choices and comparing relative benefits prods us to make sound business decisions, instead of scratching an itch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/69451-3650298064955452347?l=www.girlwritescode.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.girlwritescode.com/feeds/3650298064955452347/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=69451&amp;postID=3650298064955452347" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3650298064955452347?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/69451/posts/default/3650298064955452347?v=2" /><link rel="alternate" type="text/html" href="http://www.girlwritescode.com/2009/01/quantifying-benefits-on-refactoring.html" title="Quantifying Benefits on Refactoring Work" /><author><name>Sharon</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total></entry></feed>

