<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Interoperability Happens - Scala</title>
    <link>http://blogs.tedneward.com/</link>
    <description>Ted's takes on the enterprise Java, .NET and Web services communities and technologies</description>
    <copyright>Ted Neward</copyright>
    <lastBuildDate>Thu, 09 Sep 2010 03:53:01 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7067.0</generator>
    <managingEditor>tneward@tedneward.com</managingEditor>
    <webMaster>tneward@tedneward.com</webMaster>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=bd7339e6-fdd5-4f2a-b711-de9a38f6c743</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,bd7339e6-fdd5-4f2a-b711-de9a38f6c743.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,bd7339e6-fdd5-4f2a-b711-de9a38f6c743.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=bd7339e6-fdd5-4f2a-b711-de9a38f6c743</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Hey, anybody who’s got significant VMWare mojo, help out a bro?
</p>
        <p>
I’ve got a Win7 VM (one of many) that appears to be exhibiting weird disk behavior—the
vmdk, a growable single-file VMDK, is almost precisely twice the used space. It’s
a 120GB growable disk, and the Win7 guest reports about 35GB used, but the VMDK takes
about 70GB on host disk. CHKDSK inside Windows says everything’s good, and the VMWare
“Disk Cleanup” doesn’t change anything, either. It doesn’t seem to be a Windows7 thing,
because I’ve got a half-dozen other Win7 VMs that operate… well, normally (by which
I mean, 30GB used in the VMDK means 30GB used on disk). It’s a VMWare Fusion host,
if that makes any difference. Any other details that might be relevant, let me know
and I’ll post.
</p>
        <p>
Anybody got any ideas what the heck is going on inside this disk?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bd7339e6-fdd5-4f2a-b711-de9a38f6c743" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>VMWare help</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,bd7339e6-fdd5-4f2a-b711-de9a38f6c743.aspx</guid>
      <link>http://blogs.tedneward.com/2010/09/09/VMWare+Help.aspx</link>
      <pubDate>Thu, 09 Sep 2010 03:53:01 GMT</pubDate>
      <description>&lt;p&gt;
Hey, anybody who’s got significant VMWare mojo, help out a bro?
&lt;/p&gt;
&lt;p&gt;
I’ve got a Win7 VM (one of many) that appears to be exhibiting weird disk behavior—the
vmdk, a growable single-file VMDK, is almost precisely twice the used space. It’s
a 120GB growable disk, and the Win7 guest reports about 35GB used, but the VMDK takes
about 70GB on host disk. CHKDSK inside Windows says everything’s good, and the VMWare
“Disk Cleanup” doesn’t change anything, either. It doesn’t seem to be a Windows7 thing,
because I’ve got a half-dozen other Win7 VMs that operate… well, normally (by which
I mean, 30GB used in the VMDK means 30GB used on disk). It’s a VMWare Fusion host,
if that makes any difference. Any other details that might be relevant, let me know
and I’ll post.
&lt;/p&gt;
&lt;p&gt;
Anybody got any ideas what the heck is going on inside this disk?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bd7339e6-fdd5-4f2a-b711-de9a38f6c743" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,bd7339e6-fdd5-4f2a-b711-de9a38f6c743.aspx</comments>
      <category>.NET</category>
      <category>Android</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>iPhone</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Objective-C</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Security</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
      <category>XNA</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=7e7d1388-4091-49a5-ada5-4d607df5fe9e</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,7e7d1388-4091-49a5-ada5-4d607df5fe9e.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,7e7d1388-4091-49a5-ada5-4d607df5fe9e.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=7e7d1388-4091-49a5-ada5-4d607df5fe9e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The <a href="http://jz10.java.no" target="_blank">JavaZone</a> conference has just
become one of my favorite conferences, EVAH. Check out <a href="http://jz10.java.no/java-4-ever-trailer.html" target="_blank">this
trailer</a> they put together, entitled "Java 4-Ever". Yes, Microsofties,
you should watch, too. Just leave off the evangelism for a moment and enjoy the humor
of it. You've had your own fun over the years, too, or need I remind you of the Matrix
video with Gates and Ballmer and the blue pill/red pill? ;-)
</p>
        <p>
This video brings several things to mind:
</p>
        <ul>
          <li>
Wow, that's well done. And take heed, the "R" rating at the front of the
trailer is actually pretty serious. NSFW.</li>
          <li>
I remember speaking at JavaZone a half-dozen years ago, and remember it fondly. Which
reminds me, I need to get back there before long. I missed NDC this year, and I need
my Oslo on before long.</li>
          <li>
Whatever happened to Microsoft marketing? They used to do things like this on a more
regular basis, but it seems they've been silent over the past few years. C'mon back,
guys! The water's fine!</li>
        </ul>
        <p>
Oh, and by the way, pay absolutely no attention to most of the comments that appeared
on the trailer page—most of them are ridiculous and stupid. (To the .NET advocate
who said that ".NET doesn't use a virtual machine", you're the biggest idiot
of the lot.)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=7e7d1388-4091-49a5-ada5-4d607df5fe9e" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>A well-done &amp;quot;movie trailer&amp;quot;</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,7e7d1388-4091-49a5-ada5-4d607df5fe9e.aspx</guid>
      <link>http://blogs.tedneward.com/2010/07/01/A+Welldone+Quotmovie+Trailerquot.aspx</link>
      <pubDate>Thu, 01 Jul 2010 10:06:35 GMT</pubDate>
      <description>&lt;p&gt;
The &lt;a href="http://jz10.java.no" target="_blank"&gt;JavaZone&lt;/a&gt; conference has just
become one of my favorite conferences, EVAH. Check out &lt;a href="http://jz10.java.no/java-4-ever-trailer.html" target="_blank"&gt;this
trailer&lt;/a&gt; they put together, entitled &amp;quot;Java 4-Ever&amp;quot;. Yes, Microsofties,
you should watch, too. Just leave off the evangelism for a moment and enjoy the humor
of it. You've had your own fun over the years, too, or need I remind you of the Matrix
video with Gates and Ballmer and the blue pill/red pill? ;-)
&lt;/p&gt;
&lt;p&gt;
This video brings several things to mind:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Wow, that's well done. And take heed, the &amp;quot;R&amp;quot; rating at the front of the
trailer is actually pretty serious. NSFW.&lt;/li&gt;
&lt;li&gt;
I remember speaking at JavaZone a half-dozen years ago, and remember it fondly. Which
reminds me, I need to get back there before long. I missed NDC this year, and I need
my Oslo on before long.&lt;/li&gt;
&lt;li&gt;
Whatever happened to Microsoft marketing? They used to do things like this on a more
regular basis, but it seems they've been silent over the past few years. C'mon back,
guys! The water's fine!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Oh, and by the way, pay absolutely no attention to most of the comments that appeared
on the trailer page—most of them are ridiculous and stupid. (To the .NET advocate
who said that &amp;quot;.NET doesn't use a virtual machine&amp;quot;, you're the biggest idiot
of the lot.)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=7e7d1388-4091-49a5-ada5-4d607df5fe9e" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,7e7d1388-4091-49a5-ada5-4d607df5fe9e.aspx</comments>
      <category>.NET</category>
      <category>Android</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Scala</category>
      <category>Social</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
      <category>XNA</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=479e3371-5ecf-4379-b9d4-f7cf070aae82</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,479e3371-5ecf-4379-b9d4-f7cf070aae82.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,479e3371-5ecf-4379-b9d4-f7cf070aae82.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=479e3371-5ecf-4379-b9d4-f7cf070aae82</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
By now, the Twitter messages have spread, and the word is out: at Uberconf this year,
I did a session ("Pragmatic Architecture"), which I've done at other venues
before, but this time we made it into a 180-minute workshop instead of a 90-minute
session, and the workshop included breaking the room up into small (10-ish, which
was still a teensy bit too big) groups and giving each one an "architectural
kata" to work on.
</p>
        <p>
The architectural kata is a take on PragDave's coding kata, except taken to a higher
level: the architectural kata is an exercise in which the group seeks to create an
architecture to solve the problem presented. The inspiration for this came from Frederick
Brooks' latest book, <em>The Design of Design</em>, in which he points out that the
only way to get great designers is to get them to design. The corollary, of course,
is that in order to create great architects, we have to get them to architect. But
few architects get a chance to architect a system more than a half-dozen times or
so over the lifetime of a career, and that's only for those who are fortunate to be
given the opportunity to architect in the first place. Of course, the problem here
is, you have to be an architect in order to get hired as an architect, but if you're
not an architect, then how can you architect in order to become an architect?
</p>
        <p>
Um... hang on, let me make sure I wrote that right.
</p>
        <p>
Anyway, the "rules" around the kata (which makes it more difficult to consume
the kata but makes the scenario more realistic, IMHO):
</p>
        <ul>
          <li>
you may ask the instructor questions about the project</li>
          <li>
you must be prepared to present a rough architectural vision of the project and defend
questions about it</li>
          <li>
you must be prepared to ask questions of other participants' presentations</li>
          <li>
you may safely make assumptions about technologies you don't know well as long as
those assumptions are clearly defined and spelled out</li>
          <li>
you may not assume you have hiring/firing authority over the development team</li>
          <li>
any technology is fair game (but you must justify its use)</li>
          <li>
any other rules, you may ask about</li>
        </ul>
        <p>
The groups were given 30 minutes in which to formulate some ideas, and then three
of them were given a few minutes to present their ideas and defend it against some
questions from the crowd.
</p>
        <p>
An example kata is below:
</p>
        <blockquote>
          <p>
            <strong>Architectural Kata #5: I'll have the BLT</strong>
          </p>
          <p>
a national sandwich shop wants to enable "fax in your order" but over the
Internet instead
</p>
          <p>
users: millions+
</p>
          <p>
requirements: users will place their order, then be given a time to pick up their
sandwich and directions to the shop (which must integrate with Google Maps); if the
shop offers a delivery service, dispatch the driver with the sandwich to the user;
mobile-device accessibility; offer national daily promotionals/specials; offer local
daily promotionals/specials; accept payment online or in person/on delivery
</p>
        </blockquote>
        <p>
As you can tell, it's vague in some ways, and this is somewhat deliberate—as one group
discovered, part of the architect's job is to ask questions of the project champion
(me), and they didn't, and felt like they failed pretty miserably. (In their defense,
the kata they drew—randomly—was pretty much universally thought to be the hardest
of the lot.) But overall, the exercise was well-received, lots of people found it
a great opportunity to try being an architect, and even the team that failed felt
that it was a valuable exercise.
</p>
        <p>
I'm definitely going to do more of these, and refine the whole thing a little. (Thanks
to everyone who participated and gave me great feedback on how to make it better.)
If you're interested in having it done as a practice exercise for your development
team before the start of a big project, ping me. I think this would be a *great* exercise
to do during a user group meeting, too.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=479e3371-5ecf-4379-b9d4-f7cf070aae82" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Architectural Katas</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,479e3371-5ecf-4379-b9d4-f7cf070aae82.aspx</guid>
      <link>http://blogs.tedneward.com/2010/06/17/Architectural+Katas.aspx</link>
      <pubDate>Thu, 17 Jun 2010 08:42:47 GMT</pubDate>
      <description>&lt;p&gt;
By now, the Twitter messages have spread, and the word is out: at Uberconf this year,
I did a session (&amp;quot;Pragmatic Architecture&amp;quot;), which I've done at other venues
before, but this time we made it into a 180-minute workshop instead of a 90-minute
session, and the workshop included breaking the room up into small (10-ish, which
was still a teensy bit too big) groups and giving each one an &amp;quot;architectural
kata&amp;quot; to work on.
&lt;/p&gt;
&lt;p&gt;
The architectural kata is a take on PragDave's coding kata, except taken to a higher
level: the architectural kata is an exercise in which the group seeks to create an
architecture to solve the problem presented. The inspiration for this came from Frederick
Brooks' latest book, &lt;em&gt;The Design of Design&lt;/em&gt;, in which he points out that the
only way to get great designers is to get them to design. The corollary, of course,
is that in order to create great architects, we have to get them to architect. But
few architects get a chance to architect a system more than a half-dozen times or
so over the lifetime of a career, and that's only for those who are fortunate to be
given the opportunity to architect in the first place. Of course, the problem here
is, you have to be an architect in order to get hired as an architect, but if you're
not an architect, then how can you architect in order to become an architect?
&lt;/p&gt;
&lt;p&gt;
Um... hang on, let me make sure I wrote that right.
&lt;/p&gt;
&lt;p&gt;
Anyway, the &amp;quot;rules&amp;quot; around the kata (which makes it more difficult to consume
the kata but makes the scenario more realistic, IMHO):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
you may ask the instructor questions about the project&lt;/li&gt;
&lt;li&gt;
you must be prepared to present a rough architectural vision of the project and defend
questions about it&lt;/li&gt;
&lt;li&gt;
you must be prepared to ask questions of other participants' presentations&lt;/li&gt;
&lt;li&gt;
you may safely make assumptions about technologies you don't know well as long as
those assumptions are clearly defined and spelled out&lt;/li&gt;
&lt;li&gt;
you may not assume you have hiring/firing authority over the development team&lt;/li&gt;
&lt;li&gt;
any technology is fair game (but you must justify its use)&lt;/li&gt;
&lt;li&gt;
any other rules, you may ask about&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The groups were given 30 minutes in which to formulate some ideas, and then three
of them were given a few minutes to present their ideas and defend it against some
questions from the crowd.
&lt;/p&gt;
&lt;p&gt;
An example kata is below:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Architectural Kata #5: I'll have the BLT&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
a national sandwich shop wants to enable &amp;quot;fax in your order&amp;quot; but over the
Internet instead
&lt;/p&gt;
&lt;p&gt;
users: millions+
&lt;/p&gt;
&lt;p&gt;
requirements: users will place their order, then be given a time to pick up their
sandwich and directions to the shop (which must integrate with Google Maps); if the
shop offers a delivery service, dispatch the driver with the sandwich to the user;
mobile-device accessibility; offer national daily promotionals/specials; offer local
daily promotionals/specials; accept payment online or in person/on delivery
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
As you can tell, it's vague in some ways, and this is somewhat deliberate—as one group
discovered, part of the architect's job is to ask questions of the project champion
(me), and they didn't, and felt like they failed pretty miserably. (In their defense,
the kata they drew—randomly—was pretty much universally thought to be the hardest
of the lot.) But overall, the exercise was well-received, lots of people found it
a great opportunity to try being an architect, and even the team that failed felt
that it was a valuable exercise.
&lt;/p&gt;
&lt;p&gt;
I'm definitely going to do more of these, and refine the whole thing a little. (Thanks
to everyone who participated and gave me great feedback on how to make it better.)
If you're interested in having it done as a practice exercise for your development
team before the start of a big project, ping me. I think this would be a *great* exercise
to do during a user group meeting, too.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=479e3371-5ecf-4379-b9d4-f7cf070aae82" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,479e3371-5ecf-4379-b9d4-f7cf070aae82.aspx</comments>
      <category>.NET</category>
      <category>Android</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>iPhone</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Objective-C</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Security</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>WCF</category>
      <category>XML Services</category>
      <category>XNA</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=0e4f9c86-b602-42d7-8729-662d855fd69f</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,0e4f9c86-b602-42d7-8729-662d855fd69f.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,0e4f9c86-b602-42d7-8729-662d855fd69f.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=0e4f9c86-b602-42d7-8729-662d855fd69f</wfw:commentRss>
      <slash:comments>13</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://codekata.pragprog.com/2007/01/code_katahow_it.html" target="_blank">Code
Katas</a> are small, relatively simple exercises designed to give you a problem to
try and solve. I like to use them as a way to get my feet wet and help write something
more interesting than "Hello World" but less complicated than "The
Internet's Next Killer App".
</p>
        <p>
 
</p>
        <p>
          <a href="http://richardminerich.com/2010/04/the-ted-neward-f-folding-challenge/" target="_blank">Rick
Minerich</a> mentioned this one on his blog already, but here is the original "problem"/challenge
as it was presented to me and which I in turn shot to him over a Twitter DM:
</p>
        <p>
 
</p>
        <p>
I have a list, say something like [4, 4, 4, 4, 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 1,
5, 5], which consists of varying repetitions of integers. (We can assume that it's
always numbers, and the use of the term "list" here is generic—it could
be a list, array, or some other collection class, your choice.) The goal is to take
this list of numbers, and "compress" it down into a (theoretically smaller)
list of numbers in pairs, where the first of the pair is the occurrence number of
the value, which is the second number. So, since the list above has four 4's, followed
by three 2's, two 3's, four 2's, three 1's and two 5's, it should compress into [4,
4, 3, 2, 2, 3, 3, 1, 2, 5]. 
</p>
        <blockquote>
          <p>
            <strong>Update:</strong> Typo! It should compress into [4, 4, 3, 2, 2, 3, 4, 2, 3,
1, 2, 5], not [4, 4, 3, 2, 2, 3, 3, 1, 2, 5]. Sorry!
</p>
        </blockquote>
        <p>
Using your functional language of choice, implement a solution. (No looking at Rick's
solution first, by the way—that's cheating!) Feel free to post proposed solutions
here as comments, by the way.
</p>
        <p>
 
</p>
        <p>
This is a pretty easy challenge, but I wanted to try and solve it in a functional
mindset, which the challenger had never seen before. I also thought it made for an
interesting challenge for people who've never programming in functional languages
before, because it requires a very different approach than the imperative solution.
</p>
        <p>
 
</p>
        <p>
Extensions to the kata (a.k.a. "extra credit"):
</p>
        <ul>
          <li>
How does the implementation change (if any) to generalize it to a list of any particular
type? (Assume the list is of homogenous type—always strings, always ints, always whatever.)</li>
          <li>
How does the implementation change (if any) to generalize it to a list of any type?
(In other words, a list of strings, ints, Dates, whatever, mixed together within the
list: [1, 1, "one", "one", "one", ...] .)</li>
          <li>
How does the implementation change (if any) to generate a list of two-item tuples
(the first being the occurence, the second being the value) as the result instead?
Are there significant advantages to this?</li>
          <li>
How does the implementation change (if any) to parallelize/multi-thread it? For your
particular language how many elements have to be in the list before doing so yields
a significant payoff?</li>
        </ul>
        <p>
By the way, some of the extension questions make the Kata somewhat interesting even
for the imperative/O-O developer; have at, and let me know what you think.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=0e4f9c86-b602-42d7-8729-662d855fd69f" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Code Kata: Compressing Lists</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,0e4f9c86-b602-42d7-8729-662d855fd69f.aspx</guid>
      <link>http://blogs.tedneward.com/2010/05/06/Code+Kata+Compressing+Lists.aspx</link>
      <pubDate>Thu, 06 May 2010 21:42:09 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://codekata.pragprog.com/2007/01/code_katahow_it.html" target="_blank"&gt;Code
Katas&lt;/a&gt; are small, relatively simple exercises designed to give you a problem to
try and solve. I like to use them as a way to get my feet wet and help write something
more interesting than &amp;quot;Hello World&amp;quot; but less complicated than &amp;quot;The
Internet's Next Killer App&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://richardminerich.com/2010/04/the-ted-neward-f-folding-challenge/" target="_blank"&gt;Rick
Minerich&lt;/a&gt; mentioned this one on his blog already, but here is the original &amp;quot;problem&amp;quot;/challenge
as it was presented to me and which I in turn shot to him over a Twitter DM:
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
I have a list, say something like [4, 4, 4, 4, 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 1,
5, 5], which consists of varying repetitions of integers. (We can assume that it's
always numbers, and the use of the term &amp;quot;list&amp;quot; here is generic—it could
be a list, array, or some other collection class, your choice.) The goal is to take
this list of numbers, and &amp;quot;compress&amp;quot; it down into a (theoretically smaller)
list of numbers in pairs, where the first of the pair is the occurrence number of
the value, which is the second number. So, since the list above has four 4's, followed
by three 2's, two 3's, four 2's, three 1's and two 5's, it should compress into [4,
4, 3, 2, 2, 3, 3, 1, 2, 5]. 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Typo! It should compress into [4, 4, 3, 2, 2, 3, 4, 2, 3,
1, 2, 5], not [4, 4, 3, 2, 2, 3, 3, 1, 2, 5]. Sorry!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Using your functional language of choice, implement a solution. (No looking at Rick's
solution first, by the way—that's cheating!) Feel free to post proposed solutions
here as comments, by the way.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
This is a pretty easy challenge, but I wanted to try and solve it in a functional
mindset, which the challenger had never seen before. I also thought it made for an
interesting challenge for people who've never programming in functional languages
before, because it requires a very different approach than the imperative solution.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Extensions to the kata (a.k.a. &amp;quot;extra credit&amp;quot;):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
How does the implementation change (if any) to generalize it to a list of any particular
type? (Assume the list is of homogenous type—always strings, always ints, always whatever.)&lt;/li&gt;
&lt;li&gt;
How does the implementation change (if any) to generalize it to a list of any type?
(In other words, a list of strings, ints, Dates, whatever, mixed together within the
list: [1, 1, &amp;quot;one&amp;quot;, &amp;quot;one&amp;quot;, &amp;quot;one&amp;quot;, ...] .)&lt;/li&gt;
&lt;li&gt;
How does the implementation change (if any) to generate a list of two-item tuples
(the first being the occurence, the second being the value) as the result instead?
Are there significant advantages to this?&lt;/li&gt;
&lt;li&gt;
How does the implementation change (if any) to parallelize/multi-thread it? For your
particular language how many elements have to be in the list before doing so yields
a significant payoff?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
By the way, some of the extension questions make the Kata somewhat interesting even
for the imperative/O-O developer; have at, and let me know what you think.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=0e4f9c86-b602-42d7-8729-662d855fd69f" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,0e4f9c86-b602-42d7-8729-662d855fd69f.aspx</comments>
      <category>.NET</category>
      <category>Android</category>
      <category>C#</category>
      <category>C++</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>iPhone</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=6b75f874-1ce8-485b-b0ec-72c0e7f2ad38</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,6b75f874-1ce8-485b-b0ec-72c0e7f2ad38.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,6b75f874-1ce8-485b-b0ec-72c0e7f2ad38.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=6b75f874-1ce8-485b-b0ec-72c0e7f2ad38</wfw:commentRss>
      <slash:comments>14</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
... with my earlier <a href="http://blogs.tedneward.com/2010/03/23/How+To+And+Not+To+Give+A+Talk+On+F.aspx" target="_blank">speaking
about F#</a> post, which I will admit, surprises me, since I would've thought somebody
interested in promoting F# would've been more supportive of the idea of putting some
ideas out to help other speakers get F# more easily adopted by the community. Perhaps
I misunderstood her objections, but I thought a response was required in any event.
</p>
        <p>
Amanda opens with:
</p>
        <blockquote>
          <p>
Let's start with the "Do" category.
</p>
        </blockquote>
        <p>
OK, then, let's. :-)
</p>
        <blockquote>
          <p>
First you say you want the speaker to show inheritance... in a functional-first language.
This is an obvious no-no. Inheritance should be used extremely lightly in any language
and it should be hidden completely in F#. You should NEVER have a student/instructor/employee
inherit from a person. This language isn't used that way. 
</p>
        </blockquote>
        <p>
That's odd.... that's entirely contradictory to what I've heard from the F# team.
I've never heard anyone on the F# team ever call it a "functional-first"
language, nor that inheritance (or any other object-oriented feature) is something
that should be used "extremely lightly" or "hidden completely".
Quite the contrary, in fact; when I did a tag-team presentation on F# with Luke Hoban,
the PM of the F# team, he gently corrected my use of the phrase describing F# as a
"functional-object hybrid" language to suggest instead that it was a "fusion"
of both features.
</p>
        <p>
But even if that's not the case (or perhaps isn't the case anymore), I think it's
critical to give audience members something concrete and familiar to hang onto as
they start the roller-coaster ride of learning not only a new syntax, but new concepts.
To simply say, "Everything you know from objects is wrong" is to do them
a disservice, particularly when the language clearly is intended to expose object-oriented
concepts as a first-class citizen.
</p>
        <blockquote>
          <p>
Second you say to show interop. This will show nothing about the language. You might
as well just say it is a .net language. If you spend your F# session discussing what
it means to be on .net, you fail. Nobody expects that one dll will not be able to
call another. If they do, I assure you that they will not be writing F# anytime soon. 
</p>
        </blockquote>
        <p>
Ah, but here is where my decades of experience teaching languages to audiences all
over the world kicks in: they don't know that. DLLs are not all created equal, as
anyone who's ever tried to get COM components to interop with native C++ DLLs that
in turn want to call into managed code DLLs will tell you. It's important to stress,
again, that what they know is still relevant in this new world. In fact, the goal
of showing them interoperability is to reassure them that, in fact, it's not a new
world at all, but simply a different spin on the world they already know and love.
</p>
        <blockquote>
          <p>
Next you say give concrete examples of where F# is a win. This is a sales pitch. It's
fine for some audiences but if you intend to teach F# to the audience, you likely
are already there. Just make sure your examples are real world and you should be fine.
I challenge you to make your next blog a "Why F#" which contains real world
examples. I've not ever heard you give valuable advice about when to use F#. Also
please post what your real world experience is with F#. Where did you implement a
solution? What was that project like? Why was F# the best choice? 
</p>
        </blockquote>
        <p>
Interesting. Based on the conversations I've had with others, the main reason people
come to technical talks, at least the talks I've been to (both as an audience member
and as a speaker) is to know when and where and how they can use this technology (whatever
it is) to solve the problems they face. That means that they need to see and hear
where a technology fits well as a solution against a given problem domain or case,
and the sooner they get that information, the sooner they can start to evaluate where,
how and when they should use a particular technology. This has been true of almost
every "new" technology I've evaluated—from the more recent presentations
and articles around WCF, Workflow, MongoDB and Axum to the older talks/trainings I've
given for C#, Java (including servlets, JSPs, EJBs, JMS, and so on), C++ and patterns.
Case in point: does F# offer up a great experience in building UIs? Not really—Visual
Studio 2010 doesn't have any of the templates or designer support that C# and Visual
Basic will have, making it awkward at best to build a UI around it. On top of that,
the data-binding architecture present in both WinForms and WPF rely on the idea of
mutable objects, which while something F# allows, isn't something it encourages. So,
it seems pretty reasonable to assume that F# is not great for UI scenarios.
</p>
        <p>
Oh, and your memory is letting you down here—your comment "I've not ever heard
you give valuable advice about when to use F#" is patently false. You were standing
next to me at DevTeach 2008, talking about F# to an audience of about 20 or so when
I said that I thought that functional-object languages were a natural fit for building
services (XML or otherwise).
</p>
        <p>
More importantly, these were tips to speakers interested in F#—where <em>they</em> think
F# is strong and <em>they</em> think F# is weak is a personal judgment, not something
that I should dictate. You used F# to implement an insurance-scoring engine, as I
recall. I've used it (in conjunction with AbsIL, which used to ship with the F# bits
back when they were a MSR technology) to do some IL weaving in the spirit of AOP.
I've used it in a couple of other cases, but alas I cannot divulge the details due
to NDA. But where I've used it and where you've used it isn't the point—it's what
the speaker talking about F# has done that's important. This isn't about us—it's about
the guy or gal on the stage who's giving the talk.
</p>
        <blockquote>
          <p>
Then you say to inform the audience that the language is Turing complete. This seems
like a huge waste as well. If the audience needs to understand that you can accomplish
the same things in C#/VB/F#/Iron*/etc, you are speaking to people who are very young
in the understanding of programming. They won't be using F# anytime soon. 
</p>
        </blockquote>
        <p>
Hmm. I <em>think</em> this is a reaction to the comment "DO stress that F# can
do everything that C# or Visual Basic can do", which is a very different creature
than simply informing the audience that the language is Turing complete. Again, based
on my decade's-plus years of training experience, it's important to let the audience
know that they don't have to throw away everything they already know in order to use
this language. I know that it's fashionable among the functional programming community
to suggest that we should just "toss away all that object stuff", but frankly
I've not found that to be the attitude among the "heavyweights" in that
part of the industry, nor do I find that attitude laced throughout F#. If that were
the case, why would F# go to such great lengths to incorporate object-orientation
as a full part of its linguistic capabilities? It would be far simpler to be a CLI
Consumer (much as managed JScript is/was) and only offer up functional mechanisms,
a la Yeti in the Java space.
</p>
        <p>
I lived through the procedural-to-object transition back in the late 80's/early 90's,
and realized that if you want to bring the previous generation of programmers along
with you into a brave new world, you have to show them that a complete reboot of their
mental processes is not necessary. Otherwise, you're basically calling them idiots
if they can't keep up. Perhaps you're OK with that; I'm not.
</p>
        <blockquote>
          <p>
Finally you say to Tease them for 20 minutes. I am not sure what this means. Can you
post those 35 lines to wow us? I'd love to see your real world demo that is 35 lines.
I'm curious as to why you wouldn't be able to explain the 35 lines as well. I guess
there isn't time because you're busy showing interop examples that prove F# is a Turing
complete, .net language.
</p>
        </blockquote>
        <p>
Alas, I doubt my 35 lines would impress you. However, my 35 lines of F# service code,
or Aaron's 35 lines of F# natural-language parser code might impress the crowd we're
speaking to. I dunno. More importantly, again, this isn't about what *I* want to do
in a talk, it's about helping other F# speakers be able to better reach their audience.
</p>
        <blockquote>
          <p>
Let's get into the Don't category:
</p>
        </blockquote>
        <p>
So soon? But we were just getting comfortable with all the DO's being judged completely
out of order from their corresponding DON'Ts. *shrug* Ah, well.
</p>
        <blockquote>
          <p>
First you say to stay away from mathematical examples because people don't write mathematical
code every day. I think you already mentioned that F# is not meant to be the language
you use for every scenario. Now it seems you want to say it should be the everyday
tool. I'm confused. I agree that some of these simple examples aren't very useful
but then again it's not because they are mathematical. It's because they are simple
and ridiculous. I don't use a web crawler everyday either but I see value in the demo.
I think the examples need to be more real world, period. Have you posted that blog
I requested yet? :) 
</p>
        </blockquote>
        <p>
Ah, the black/white pedagogical argument: if it's not black, it must be white, and
if it's not white, it must be black. Your confusion is clear: if it is not a language
to be used for everything, it must be a niche language solely for creating high-end
mathematical systems, and if it isn't just for creating high-end mathematical systems,
it must be a language used for everything.
</p>
        <p>
My reasoning for avoiding the exponent-hugging example is pretty easy, I think: Mathematical
examples reinforce the idea that F# is solely to be used for high-end mathematical
scenarios. If you're OK with the language only appealing to that crowd, please, by
all means, continue to use those examples. Myself, I think functional concepts are
powerful, and I try to show people the power of extracting behavior by showing them
widely-disparate uses of foldLeft across lists of things to produce concrete yet widely
different results. Simple examples, but without a shred of "derivatives"
found anywhere.
</p>
        <p>
Alas, that blog post will have to wait—I have an F# book I'm finishing up, and I'd
rather put the energy there.
</p>
        <blockquote>
          <p>
Next up you say to not stress FSI or the REPL. I'll start by reminding you that FSI
is the REPL. There aren't two different things here. I think it's great to show a
REPL! This is not just a cool F# thing. It's common to most functional languages,
statically typed or not. The statically typed argument might be a better one to have
than Turing completeness. I'd much rather discuss those benefits for the types of
code that are written in F#. 
</p>
        </blockquote>
        <p>
Wow. I wouldn't have thought I would have to remind you that REPL is a generic phrase
that can apply to both FSI and the Interactive Window inside Visual Studio. And while
I'm certainly happy to hear that you think it's great to show a REPL, the fact remains
that most .NET developers don't know what to do with it. More importantly, demonstrating
a REPL reinforces the idea that this is a shell-scripting language like Python and
Ruby and PowerShell, hence the questions comparing F# to Python or Perl that come
up every time I've seen an F# talk show off FSI or the Interactive Window. Business
developers using .NET build using Visual Studio (with the exception of that small
percentage who've discovered IPy or IRb) and, again, need to be brought gently into
this new approach.
</p>
        <p>
(For those readers still following along, the REPL concept is hardly restricted to
the functional language cadre; in fact, object-oriented developers would be well-advised
to play with one of their own ancient progenitors, Smalltalk, and its environment
that is essentially one giant REPL baked into a GUI image that can be frozen and re-hydrated
at any time. Long-time readers of this blog will know I've talked about this before,
and how incredibly powerful it would be if we could do similar kinds of things to
the JVM or CLR.)
</p>
        <blockquote>
          <p>
You go back into the Why F# question without giving any real reason. Can you post
that blog please? I think many of your readers would appreciate that! PS: The Steelers
are fantastic! :) 
</p>
        </blockquote>
        <p>
If I'm following your point-by-point refutation correctly, you're now saying I'm "going
back" to the "Why F#" question for no real reason; I would've thought
the progression of DON'T followed by DO would've been pretty obvious, but perhaps
I was assuming too much on the part of at least one of the post's readership. The
DO was designed to offer up prescriptive advice about how to accomplish something
I'd said to DON'T previously. And thus is true here: DON'T answer the "Why F#"
question with "Productivity", DO answer it with something more concrete
and tangible than that, either in the form of real-world examples or concrete scenarios.
</p>
        <p>
I think by this point, given all the wheedling for that blog post, the general readership
would probably be very interested in your own rationale blog post, by the way.
</p>
        <p>
Alas, your Steelers barely made it to .500 last year, their franchise quarterback
is now the target of his second (and possibly more, if the rumors are to be believed)
sexual assault charge, and their principal receiver has a reputation around the league
as being a dirty player. So perhaps we will simply have to disagree on how fantastic
they are. Which, you will note, proves my point—as the old saying goes, "there
is no accounting for taste", because I can't understand how you think. Which
then means "It's just how I think" is pretty ridiculous as a justification
for using a language.
</p>
        <blockquote>
          <p>
You say to stay away from the "functional jazz" or the reason why anyone
should be looking at F# to start with. People don't come to these types of talks to
see how F# is just like C#. They want to see what is different. Don't stress the jargon
but if someone asks, let them know there is a name for what they are looking at. I
remember when I was learning F# that everyone hid the meaning of let!. They would
say "Something special happens here" and that would leave me thinking they
were trying to hide the magic. There is no magic! I don't assume people are morons.
They can handle the truth. If they want to learn more I want to give them a term to
google and some potential resources. There isn't time to cover that completely in
most sessions though. It's something to be careful of, not to avoid completely. 
</p>
        </blockquote>
        <p>
Interesting how your anecdotal evidence differs from mine—what I've seen, based on
the quick poll I took of the attendees at the user group meeting last night, and based
on conversations I've had with hundreds of developers from companies all over the
world over the last four years, vastly more attendees come to a talk on a given subject
because they have no clue what this thing is and want to see a general overview of
it. Shy Cohen, one of the attendees last night, whom I first met during my days as
a <em>digerati</em> on the WCF team back when it was still called "Indigo",
admitted as much during a whispered conversation at the back of the room. If Shy,
old Microsoft hand that he is/was, bright guy that he is, and close friend to Lisa
Feigenbaum, who's a Program Manager for Visual Studio, has no clue what F# is and
comes to a talk on it so he can get a quick overview of it, how likely is it that
everybody is coming to an F# talk with a predetermined idea of what the language is
and are thus ready to be given "the truth" complete with all the big dime-store
words?
</p>
        <p>
Yes, people want to know what is different, but to do that, they also have to see
what is the same. Which takes us back to my earlier points about showing them what
is the same between F# and C#.
</p>
        <p>
As for people waving their hands and saying "something special happens here",
well, maybe you just listened to the wrong people. *shrug* Can't help you there. For
as long as I've been giving talks on F#, dating back to SDWest back in 2005 when I
gave a talk on "A Tour of Microsoft Research" during which I talked about
Fugue, Detours, AbsIL and F#, I've shown the language, talked about what's happening
in there, and shown the IL bindings underneath to give people concrete ideas to hold
on to. It's the truth, but without the pretentiousness of big words.
</p>
        <blockquote>
          <p>
The last point is obvious. Nobody can learn F# in 20 (or 30 as it was) minutes. 
</p>
        </blockquote>
        <p>
Unfortunately, that doesn't stop people from trying to teach the entirety of the language
in 20 minutes. Or even in a full day. (From having taught languages for many years,
and knowing that it took most of a week to teach C# back in the 1.0/2.0 timeframe,
I'm finding that it takes about 5 days of full 8-to-5 training to get them competent
and confident in using the language. Less than that, by about a day or so, if they
have a strong background in C#.)
</p>
        <blockquote>
          <p>
Context, context, context.
</p>
        </blockquote>
        <p>
Indeed. But for now, Amanda, if you take such strong issue with my suggested guidelines
for F# speakers, I encourage you to create your own guidelines and post them to your
blog. Let's rise the tide to raise all the ships, and encourage a broad spectrum of
talk styles.
</p>
        <p>
In the meantime, though, I have a lunch with Michael later this week, some OTN and
developerWorks articles to write, an F# book to finish, a Scala book to start, some
client code to wrap up, a slew of Scala recordings to work through, soccer practice
Thursday night, and a Seattle Tech Speakers Workshop meeting next month to prep for,
in addition to a class next week that requires some final polish, so you'll have to
excuse me if I don't respond further down this particular path.
</p>
        <p>
Cheers!
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6b75f874-1ce8-485b-b0ec-72c0e7f2ad38" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Amanda takes umbrage....</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,6b75f874-1ce8-485b-b0ec-72c0e7f2ad38.aspx</guid>
      <link>http://blogs.tedneward.com/2010/03/24/Amanda+Takes+Umbrage.aspx</link>
      <pubDate>Wed, 24 Mar 2010 06:38:17 GMT</pubDate>
      <description>&lt;p&gt;
... with my earlier &lt;a href="http://blogs.tedneward.com/2010/03/23/How+To+And+Not+To+Give+A+Talk+On+F.aspx" target="_blank"&gt;speaking
about F#&lt;/a&gt; post, which I will admit, surprises me, since I would've thought somebody
interested in promoting F# would've been more supportive of the idea of putting some
ideas out to help other speakers get F# more easily adopted by the community. Perhaps
I misunderstood her objections, but I thought a response was required in any event.
&lt;/p&gt;
&lt;p&gt;
Amanda opens with:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Let's start with the &amp;quot;Do&amp;quot; category.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
OK, then, let's. :-)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
First you say you want the speaker to show inheritance... in a functional-first language.
This is an obvious no-no. Inheritance should be used extremely lightly in any language
and it should be hidden completely in F#. You should NEVER have a student/instructor/employee
inherit from a person. This language isn't used that way. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
That's odd.... that's entirely contradictory to what I've heard from the F# team.
I've never heard anyone on the F# team ever call it a &amp;quot;functional-first&amp;quot;
language, nor that inheritance (or any other object-oriented feature) is something
that should be used &amp;quot;extremely lightly&amp;quot; or &amp;quot;hidden completely&amp;quot;.
Quite the contrary, in fact; when I did a tag-team presentation on F# with Luke Hoban,
the PM of the F# team, he gently corrected my use of the phrase describing F# as a
&amp;quot;functional-object hybrid&amp;quot; language to suggest instead that it was a &amp;quot;fusion&amp;quot;
of both features.
&lt;/p&gt;
&lt;p&gt;
But even if that's not the case (or perhaps isn't the case anymore), I think it's
critical to give audience members something concrete and familiar to hang onto as
they start the roller-coaster ride of learning not only a new syntax, but new concepts.
To simply say, &amp;quot;Everything you know from objects is wrong&amp;quot; is to do them
a disservice, particularly when the language clearly is intended to expose object-oriented
concepts as a first-class citizen.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Second you say to show interop. This will show nothing about the language. You might
as well just say it is a .net language. If you spend your F# session discussing what
it means to be on .net, you fail. Nobody expects that one dll will not be able to
call another. If they do, I assure you that they will not be writing F# anytime soon. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ah, but here is where my decades of experience teaching languages to audiences all
over the world kicks in: they don't know that. DLLs are not all created equal, as
anyone who's ever tried to get COM components to interop with native C++ DLLs that
in turn want to call into managed code DLLs will tell you. It's important to stress,
again, that what they know is still relevant in this new world. In fact, the goal
of showing them interoperability is to reassure them that, in fact, it's not a new
world at all, but simply a different spin on the world they already know and love.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Next you say give concrete examples of where F# is a win. This is a sales pitch. It's
fine for some audiences but if you intend to teach F# to the audience, you likely
are already there. Just make sure your examples are real world and you should be fine.
I challenge you to make your next blog a &amp;quot;Why F#&amp;quot; which contains real world
examples. I've not ever heard you give valuable advice about when to use F#. Also
please post what your real world experience is with F#. Where did you implement a
solution? What was that project like? Why was F# the best choice? 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Interesting. Based on the conversations I've had with others, the main reason people
come to technical talks, at least the talks I've been to (both as an audience member
and as a speaker) is to know when and where and how they can use this technology (whatever
it is) to solve the problems they face. That means that they need to see and hear
where a technology fits well as a solution against a given problem domain or case,
and the sooner they get that information, the sooner they can start to evaluate where,
how and when they should use a particular technology. This has been true of almost
every &amp;quot;new&amp;quot; technology I've evaluated—from the more recent presentations
and articles around WCF, Workflow, MongoDB and Axum to the older talks/trainings I've
given for C#, Java (including servlets, JSPs, EJBs, JMS, and so on), C++ and patterns.
Case in point: does F# offer up a great experience in building UIs? Not really—Visual
Studio 2010 doesn't have any of the templates or designer support that C# and Visual
Basic will have, making it awkward at best to build a UI around it. On top of that,
the data-binding architecture present in both WinForms and WPF rely on the idea of
mutable objects, which while something F# allows, isn't something it encourages. So,
it seems pretty reasonable to assume that F# is not great for UI scenarios.
&lt;/p&gt;
&lt;p&gt;
Oh, and your memory is letting you down here—your comment &amp;quot;I've not ever heard
you give valuable advice about when to use F#&amp;quot; is patently false. You were standing
next to me at DevTeach 2008, talking about F# to an audience of about 20 or so when
I said that I thought that functional-object languages were a natural fit for building
services (XML or otherwise).
&lt;/p&gt;
&lt;p&gt;
More importantly, these were tips to speakers interested in F#—where &lt;em&gt;they&lt;/em&gt; think
F# is strong and &lt;em&gt;they&lt;/em&gt; think F# is weak is a personal judgment, not something
that I should dictate. You used F# to implement an insurance-scoring engine, as I
recall. I've used it (in conjunction with AbsIL, which used to ship with the F# bits
back when they were a MSR technology) to do some IL weaving in the spirit of AOP.
I've used it in a couple of other cases, but alas I cannot divulge the details due
to NDA. But where I've used it and where you've used it isn't the point—it's what
the speaker talking about F# has done that's important. This isn't about us—it's about
the guy or gal on the stage who's giving the talk.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Then you say to inform the audience that the language is Turing complete. This seems
like a huge waste as well. If the audience needs to understand that you can accomplish
the same things in C#/VB/F#/Iron*/etc, you are speaking to people who are very young
in the understanding of programming. They won't be using F# anytime soon. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Hmm. I &lt;em&gt;think&lt;/em&gt; this is a reaction to the comment &amp;quot;DO stress that F# can
do everything that C# or Visual Basic can do&amp;quot;, which is a very different creature
than simply informing the audience that the language is Turing complete. Again, based
on my decade's-plus years of training experience, it's important to let the audience
know that they don't have to throw away everything they already know in order to use
this language. I know that it's fashionable among the functional programming community
to suggest that we should just &amp;quot;toss away all that object stuff&amp;quot;, but frankly
I've not found that to be the attitude among the &amp;quot;heavyweights&amp;quot; in that
part of the industry, nor do I find that attitude laced throughout F#. If that were
the case, why would F# go to such great lengths to incorporate object-orientation
as a full part of its linguistic capabilities? It would be far simpler to be a CLI
Consumer (much as managed JScript is/was) and only offer up functional mechanisms,
a la Yeti in the Java space.
&lt;/p&gt;
&lt;p&gt;
I lived through the procedural-to-object transition back in the late 80's/early 90's,
and realized that if you want to bring the previous generation of programmers along
with you into a brave new world, you have to show them that a complete reboot of their
mental processes is not necessary. Otherwise, you're basically calling them idiots
if they can't keep up. Perhaps you're OK with that; I'm not.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Finally you say to Tease them for 20 minutes. I am not sure what this means. Can you
post those 35 lines to wow us? I'd love to see your real world demo that is 35 lines.
I'm curious as to why you wouldn't be able to explain the 35 lines as well. I guess
there isn't time because you're busy showing interop examples that prove F# is a Turing
complete, .net language.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Alas, I doubt my 35 lines would impress you. However, my 35 lines of F# service code,
or Aaron's 35 lines of F# natural-language parser code might impress the crowd we're
speaking to. I dunno. More importantly, again, this isn't about what *I* want to do
in a talk, it's about helping other F# speakers be able to better reach their audience.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Let's get into the Don't category:
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
So soon? But we were just getting comfortable with all the DO's being judged completely
out of order from their corresponding DON'Ts. *shrug* Ah, well.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
First you say to stay away from mathematical examples because people don't write mathematical
code every day. I think you already mentioned that F# is not meant to be the language
you use for every scenario. Now it seems you want to say it should be the everyday
tool. I'm confused. I agree that some of these simple examples aren't very useful
but then again it's not because they are mathematical. It's because they are simple
and ridiculous. I don't use a web crawler everyday either but I see value in the demo.
I think the examples need to be more real world, period. Have you posted that blog
I requested yet? :) 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ah, the black/white pedagogical argument: if it's not black, it must be white, and
if it's not white, it must be black. Your confusion is clear: if it is not a language
to be used for everything, it must be a niche language solely for creating high-end
mathematical systems, and if it isn't just for creating high-end mathematical systems,
it must be a language used for everything.
&lt;/p&gt;
&lt;p&gt;
My reasoning for avoiding the exponent-hugging example is pretty easy, I think: Mathematical
examples reinforce the idea that F# is solely to be used for high-end mathematical
scenarios. If you're OK with the language only appealing to that crowd, please, by
all means, continue to use those examples. Myself, I think functional concepts are
powerful, and I try to show people the power of extracting behavior by showing them
widely-disparate uses of foldLeft across lists of things to produce concrete yet widely
different results. Simple examples, but without a shred of &amp;quot;derivatives&amp;quot;
found anywhere.
&lt;/p&gt;
&lt;p&gt;
Alas, that blog post will have to wait—I have an F# book I'm finishing up, and I'd
rather put the energy there.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Next up you say to not stress FSI or the REPL. I'll start by reminding you that FSI
is the REPL. There aren't two different things here. I think it's great to show a
REPL! This is not just a cool F# thing. It's common to most functional languages,
statically typed or not. The statically typed argument might be a better one to have
than Turing completeness. I'd much rather discuss those benefits for the types of
code that are written in F#. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wow. I wouldn't have thought I would have to remind you that REPL is a generic phrase
that can apply to both FSI and the Interactive Window inside Visual Studio. And while
I'm certainly happy to hear that you think it's great to show a REPL, the fact remains
that most .NET developers don't know what to do with it. More importantly, demonstrating
a REPL reinforces the idea that this is a shell-scripting language like Python and
Ruby and PowerShell, hence the questions comparing F# to Python or Perl that come
up every time I've seen an F# talk show off FSI or the Interactive Window. Business
developers using .NET build using Visual Studio (with the exception of that small
percentage who've discovered IPy or IRb) and, again, need to be brought gently into
this new approach.
&lt;/p&gt;
&lt;p&gt;
(For those readers still following along, the REPL concept is hardly restricted to
the functional language cadre; in fact, object-oriented developers would be well-advised
to play with one of their own ancient progenitors, Smalltalk, and its environment
that is essentially one giant REPL baked into a GUI image that can be frozen and re-hydrated
at any time. Long-time readers of this blog will know I've talked about this before,
and how incredibly powerful it would be if we could do similar kinds of things to
the JVM or CLR.)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
You go back into the Why F# question without giving any real reason. Can you post
that blog please? I think many of your readers would appreciate that! PS: The Steelers
are fantastic! :) 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
If I'm following your point-by-point refutation correctly, you're now saying I'm &amp;quot;going
back&amp;quot; to the &amp;quot;Why F#&amp;quot; question for no real reason; I would've thought
the progression of DON'T followed by DO would've been pretty obvious, but perhaps
I was assuming too much on the part of at least one of the post's readership. The
DO was designed to offer up prescriptive advice about how to accomplish something
I'd said to DON'T previously. And thus is true here: DON'T answer the &amp;quot;Why F#&amp;quot;
question with &amp;quot;Productivity&amp;quot;, DO answer it with something more concrete
and tangible than that, either in the form of real-world examples or concrete scenarios.
&lt;/p&gt;
&lt;p&gt;
I think by this point, given all the wheedling for that blog post, the general readership
would probably be very interested in your own rationale blog post, by the way.
&lt;/p&gt;
&lt;p&gt;
Alas, your Steelers barely made it to .500 last year, their franchise quarterback
is now the target of his second (and possibly more, if the rumors are to be believed)
sexual assault charge, and their principal receiver has a reputation around the league
as being a dirty player. So perhaps we will simply have to disagree on how fantastic
they are. Which, you will note, proves my point—as the old saying goes, &amp;quot;there
is no accounting for taste&amp;quot;, because I can't understand how you think. Which
then means &amp;quot;It's just how I think&amp;quot; is pretty ridiculous as a justification
for using a language.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
You say to stay away from the &amp;quot;functional jazz&amp;quot; or the reason why anyone
should be looking at F# to start with. People don't come to these types of talks to
see how F# is just like C#. They want to see what is different. Don't stress the jargon
but if someone asks, let them know there is a name for what they are looking at. I
remember when I was learning F# that everyone hid the meaning of let!. They would
say &amp;quot;Something special happens here&amp;quot; and that would leave me thinking they
were trying to hide the magic. There is no magic! I don't assume people are morons.
They can handle the truth. If they want to learn more I want to give them a term to
google and some potential resources. There isn't time to cover that completely in
most sessions though. It's something to be careful of, not to avoid completely. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Interesting how your anecdotal evidence differs from mine—what I've seen, based on
the quick poll I took of the attendees at the user group meeting last night, and based
on conversations I've had with hundreds of developers from companies all over the
world over the last four years, vastly more attendees come to a talk on a given subject
because they have no clue what this thing is and want to see a general overview of
it. Shy Cohen, one of the attendees last night, whom I first met during my days as
a &lt;em&gt;digerati&lt;/em&gt; on the WCF team back when it was still called &amp;quot;Indigo&amp;quot;,
admitted as much during a whispered conversation at the back of the room. If Shy,
old Microsoft hand that he is/was, bright guy that he is, and close friend to Lisa
Feigenbaum, who's a Program Manager for Visual Studio, has no clue what F# is and
comes to a talk on it so he can get a quick overview of it, how likely is it that
everybody is coming to an F# talk with a predetermined idea of what the language is
and are thus ready to be given &amp;quot;the truth&amp;quot; complete with all the big dime-store
words?
&lt;/p&gt;
&lt;p&gt;
Yes, people want to know what is different, but to do that, they also have to see
what is the same. Which takes us back to my earlier points about showing them what
is the same between F# and C#.
&lt;/p&gt;
&lt;p&gt;
As for people waving their hands and saying &amp;quot;something special happens here&amp;quot;,
well, maybe you just listened to the wrong people. *shrug* Can't help you there. For
as long as I've been giving talks on F#, dating back to SDWest back in 2005 when I
gave a talk on &amp;quot;A Tour of Microsoft Research&amp;quot; during which I talked about
Fugue, Detours, AbsIL and F#, I've shown the language, talked about what's happening
in there, and shown the IL bindings underneath to give people concrete ideas to hold
on to. It's the truth, but without the pretentiousness of big words.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The last point is obvious. Nobody can learn F# in 20 (or 30 as it was) minutes. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Unfortunately, that doesn't stop people from trying to teach the entirety of the language
in 20 minutes. Or even in a full day. (From having taught languages for many years,
and knowing that it took most of a week to teach C# back in the 1.0/2.0 timeframe,
I'm finding that it takes about 5 days of full 8-to-5 training to get them competent
and confident in using the language. Less than that, by about a day or so, if they
have a strong background in C#.)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Context, context, context.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Indeed. But for now, Amanda, if you take such strong issue with my suggested guidelines
for F# speakers, I encourage you to create your own guidelines and post them to your
blog. Let's rise the tide to raise all the ships, and encourage a broad spectrum of
talk styles.
&lt;/p&gt;
&lt;p&gt;
In the meantime, though, I have a lunch with Michael later this week, some OTN and
developerWorks articles to write, an F# book to finish, a Scala book to start, some
client code to wrap up, a slew of Scala recordings to work through, soccer practice
Thursday night, and a Seattle Tech Speakers Workshop meeting next month to prep for,
in addition to a class next week that requires some final polish, so you'll have to
excuse me if I don't respond further down this particular path.
&lt;/p&gt;
&lt;p&gt;
Cheers!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6b75f874-1ce8-485b-b0ec-72c0e7f2ad38" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,6b75f874-1ce8-485b-b0ec-72c0e7f2ad38.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Scala</category>
      <category>Visual Basic</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=8dd248aa-f023-4739-8f37-0a51ad70c20b</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,8dd248aa-f023-4739-8f37-0a51ad70c20b.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,8dd248aa-f023-4739-8f37-0a51ad70c20b.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8dd248aa-f023-4739-8f37-0a51ad70c20b</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Michael Easter called me out over Twitter tonight, entirely fairly. This blog post
is to attempt to make right.
</p>
        <p>
Context: Tonight was a <a href="http://dotnetda.org/wp/?p=421" target="_blank">.NET
Developer Association meeting in Redmond</a>, during which we had two presentations:
one on Entity Framework, and one on F#. The talk on F#, while well-meaning and delivered
by somebody I've not yet met personally, suffered from several failures that I believe
to be endemic to Microsoft's approach to presenting F#. I don't fault the speaker—I
think Michael was set up to fail from the very beginning. Thus, I decided that it
was time for me to "put up" and describe the structural failures I've seen
in several talks attempting to describe F# to the general .NET computing community.
(I think these could probably be generalized to presenting a new language to any general
computing community, but I'll keep it focused on F# for now.)
</p>
        <p>
In no particular order:
</p>
        <ul>
          <li>
            <strong>
              <em>DON'T</em> use a demo based on a mathematical principle (like Fibonacci,
factorial, or some other exponent-hugging formula).</strong> I ask you, how many developers
find themselves writing that kind of code on a daily basis? If you offer up purely
mathematical examples, you will create the impression that F# is only good for high-scale
numerical and mathematical computing, such as what scientists use, and you will essentially
convince everybody in the room that F# belongs in that class of programming language
that doesn't have anything to do with them.</li>
          <li>
            <strong>
              <em>DO </em>use a demo based on real-world environments or problems.</strong> Use
domain types that could have come from a regular line-of-business scenario; my favorite
is "Person", since that can serve as a base type for other, more domain-specific,
types (like "Student", "Instructor", "Employee", and
whatever).</li>
          <li>
            <strong>
              <em>DON'T</em> stress the F# Interactive environment.</strong> Yes, it's great
that F# has an interactive environment and a REPL. But accept that this is <em>not</em> what
the general development community cares about, or even sees value in. In fact, the
more you stress the REPL/interactive window in F#, the more likely you are to get
a question at the end of the talk asking you to compare F# to Python or Perl. Then
you end up having to argue the benefits of static typing and type inference over dynamic/duck
typing, which really makes no sense in a scripting tool, which is only on the questioners'
mind <em>because you put it there by stressing the REPL.</em></li>
          <li>
            <strong>
              <em>DO </em>show F# code being called by other assemblies, and vice versa.</strong> At
the end of the day, the watchword here should be "interoperability", because
no matter how eloquent your presentation, you're not going to get the audience to
suddenly abandon their C# and Visual Basic and switch over to writing everything in
F#, because there's just too many scenarios where F# is not the right answer (UI "top
of the stack" kinds of things being at the top of my "not great for F#"
list). Stress how an F# type is just a class, with methods that can be invoked from
C# and vice versa.</li>
          <li>
            <strong>
              <em>DON'T</em> answer the inevitable "why should I care?" question
with the word "productivity".</strong> I hate to be the one to point this
out, but <em>every</em> language ever introduced has held this up as a reason to switch
to it, and none of them have ever really <em>felt</em> like they were a productivity
boost, at least not in the long run. And if you answer with, "Because I just
think that way", that's a FAIL on your part, because I can't see how <em>your</em> thinking
changes mine. (You may also like the Pittsburgh Steelers, while I know they can't
hold a candle to the New Orleans Saints—now where are we?)</li>
          <li>
            <strong>
              <em>DO</em> answer the inevitable "why should I care?" question
with tangible real-world scenarios or examples.</strong> Give two or three cases,
abstract or concrete, where F# makes the developers' life easier, and how. And frankly,
I would sprinkle in a few cases where F# <em>isn't</em> a net win, because everybody
knows, deep down, that no one language is perfect for all scenarios. (Only marketing
and sales people seem to think there is.)</li>
          <li>
            <strong>
              <em>DON'T</em> jump straight into all this functional jazz.</strong>
            <em>
            </em>I
hate to tell you this, but most of the developer community is not convinced that functional
programming is "obviously" the right way to program. Attempting to take
them deep into functional mojo is only going to lose them and overwhelm them and quite
likely convince them that functional programming is for math majors. Use of the terms
"catamorphism" or "monad" or "partial application" or
"currying" in your introductory talk is an exercise in stroking your own
ego, not in teaching the audience something useful.</li>
          <li>
            <strong>
              <em>DO</em> stress that F# can do everything C# or Visual Basic can do.</strong> Developers
like to start with the familiar—it's why every programming language starts with the
"Hello World" example, not only because it's simple and straightforward
but because developers have come to expect it. F# can build types just like C# can,
so do that, and use that as a framework from which to build up their understanding
of the syntax and semantics.</li>
          <li>
            <strong>
              <em>DON'T</em> assume you can give an introduction to a programming language
in 20 minutes.</strong> I don't care how good you are as a presenter, it can't be
done. 50 minutes would be pushing it. 90 minutes is maybe just enough to get through
enough syntax to get the audience to the point where they can read a commonplace F#
program. Maybe.</li>
          <li>
            <strong>
              <em>DO </em>tease the hell out of them for 20 minutes.</strong> If you only
have 20 minutes, then create a super-sexy demo (not a math-based or scripting-based
one), show them the demo, then point out that this is written in 35 lines of F#, and
if they want to understand what's going on in that 35 lines, here's some resources
to go learn F#. Leave them wanting more.</li>
        </ul>
        <p>
Again, I'm not faulting Michael (tonight's speaker): I think he bravely attempted
what was likely to be a failure regardless of who was giving the talk. My hope is
that as others start to step up to talk about F# to their coworkers and fellow user
group members, this will help avoid a few more "Oh, so F# is totally irrelevant
to me" reactions.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8dd248aa-f023-4739-8f37-0a51ad70c20b" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>How to (and not to) give a talk on F#</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,8dd248aa-f023-4739-8f37-0a51ad70c20b.aspx</guid>
      <link>http://blogs.tedneward.com/2010/03/23/How+To+And+Not+To+Give+A+Talk+On+F.aspx</link>
      <pubDate>Tue, 23 Mar 2010 06:34:57 GMT</pubDate>
      <description>&lt;p&gt;
Michael Easter called me out over Twitter tonight, entirely fairly. This blog post
is to attempt to make right.
&lt;/p&gt;
&lt;p&gt;
Context: Tonight was a &lt;a href="http://dotnetda.org/wp/?p=421" target="_blank"&gt;.NET
Developer Association meeting in Redmond&lt;/a&gt;, during which we had two presentations:
one on Entity Framework, and one on F#. The talk on F#, while well-meaning and delivered
by somebody I've not yet met personally, suffered from several failures that I believe
to be endemic to Microsoft's approach to presenting F#. I don't fault the speaker—I
think Michael was set up to fail from the very beginning. Thus, I decided that it
was time for me to &amp;quot;put up&amp;quot; and describe the structural failures I've seen
in several talks attempting to describe F# to the general .NET computing community.
(I think these could probably be generalized to presenting a new language to any general
computing community, but I'll keep it focused on F# for now.)
&lt;/p&gt;
&lt;p&gt;
In no particular order:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DON'T&lt;/em&gt; use a demo based on a mathematical principle (like Fibonacci,
factorial, or some other exponent-hugging formula).&lt;/strong&gt; I ask you, how many developers
find themselves writing that kind of code on a daily basis? If you offer up purely
mathematical examples, you will create the impression that F# is only good for high-scale
numerical and mathematical computing, such as what scientists use, and you will essentially
convince everybody in the room that F# belongs in that class of programming language
that doesn't have anything to do with them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DO &lt;/em&gt;use a demo based on real-world environments or problems.&lt;/strong&gt; Use
domain types that could have come from a regular line-of-business scenario; my favorite
is &amp;quot;Person&amp;quot;, since that can serve as a base type for other, more domain-specific,
types (like &amp;quot;Student&amp;quot;, &amp;quot;Instructor&amp;quot;, &amp;quot;Employee&amp;quot;, and
whatever).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DON'T&lt;/em&gt; stress the F# Interactive environment.&lt;/strong&gt; Yes, it's great
that F# has an interactive environment and a REPL. But accept that this is &lt;em&gt;not&lt;/em&gt; what
the general development community cares about, or even sees value in. In fact, the
more you stress the REPL/interactive window in F#, the more likely you are to get
a question at the end of the talk asking you to compare F# to Python or Perl. Then
you end up having to argue the benefits of static typing and type inference over dynamic/duck
typing, which really makes no sense in a scripting tool, which is only on the questioners'
mind &lt;em&gt;because you put it there by stressing the REPL.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DO &lt;/em&gt;show F# code being called by other assemblies, and vice versa.&lt;/strong&gt; At
the end of the day, the watchword here should be &amp;quot;interoperability&amp;quot;, because
no matter how eloquent your presentation, you're not going to get the audience to
suddenly abandon their C# and Visual Basic and switch over to writing everything in
F#, because there's just too many scenarios where F# is not the right answer (UI &amp;quot;top
of the stack&amp;quot; kinds of things being at the top of my &amp;quot;not great for F#&amp;quot;
list). Stress how an F# type is just a class, with methods that can be invoked from
C# and vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DON'T&lt;/em&gt; answer the inevitable &amp;quot;why should I care?&amp;quot; question
with the word &amp;quot;productivity&amp;quot;.&lt;/strong&gt; I hate to be the one to point this
out, but &lt;em&gt;every&lt;/em&gt; language ever introduced has held this up as a reason to switch
to it, and none of them have ever really &lt;em&gt;felt&lt;/em&gt; like they were a productivity
boost, at least not in the long run. And if you answer with, &amp;quot;Because I just
think that way&amp;quot;, that's a FAIL on your part, because I can't see how &lt;em&gt;your&lt;/em&gt; thinking
changes mine. (You may also like the Pittsburgh Steelers, while I know they can't
hold a candle to the New Orleans Saints—now where are we?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DO&lt;/em&gt; answer the inevitable &amp;quot;why should I care?&amp;quot; question
with tangible real-world scenarios or examples.&lt;/strong&gt; Give two or three cases,
abstract or concrete, where F# makes the developers' life easier, and how. And frankly,
I would sprinkle in a few cases where F# &lt;em&gt;isn't&lt;/em&gt; a net win, because everybody
knows, deep down, that no one language is perfect for all scenarios. (Only marketing
and sales people seem to think there is.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DON'T&lt;/em&gt; jump straight into all this functional jazz.&lt;/strong&gt;&lt;em&gt; &lt;/em&gt;I
hate to tell you this, but most of the developer community is not convinced that functional
programming is &amp;quot;obviously&amp;quot; the right way to program. Attempting to take
them deep into functional mojo is only going to lose them and overwhelm them and quite
likely convince them that functional programming is for math majors. Use of the terms
&amp;quot;catamorphism&amp;quot; or &amp;quot;monad&amp;quot; or &amp;quot;partial application&amp;quot; or
&amp;quot;currying&amp;quot; in your introductory talk is an exercise in stroking your own
ego, not in teaching the audience something useful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DO&lt;/em&gt; stress that F# can do everything C# or Visual Basic can do.&lt;/strong&gt; Developers
like to start with the familiar—it's why every programming language starts with the
&amp;quot;Hello World&amp;quot; example, not only because it's simple and straightforward
but because developers have come to expect it. F# can build types just like C# can,
so do that, and use that as a framework from which to build up their understanding
of the syntax and semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DON'T&lt;/em&gt; assume you can give an introduction to a programming language
in 20 minutes.&lt;/strong&gt; I don't care how good you are as a presenter, it can't be
done. 50 minutes would be pushing it. 90 minutes is maybe just enough to get through
enough syntax to get the audience to the point where they can read a commonplace F#
program. Maybe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;DO &lt;/em&gt;tease the hell out of them for 20 minutes.&lt;/strong&gt; If you only
have 20 minutes, then create a super-sexy demo (not a math-based or scripting-based
one), show them the demo, then point out that this is written in 35 lines of F#, and
if they want to understand what's going on in that 35 lines, here's some resources
to go learn F#. Leave them wanting more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Again, I'm not faulting Michael (tonight's speaker): I think he bravely attempted
what was likely to be a failure regardless of who was giving the talk. My hope is
that as others start to step up to talk about F# to their coworkers and fellow user
group members, this will help avoid a few more &amp;quot;Oh, so F# is totally irrelevant
to me&amp;quot; reactions.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8dd248aa-f023-4739-8f37-0a51ad70c20b" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,8dd248aa-f023-4739-8f37-0a51ad70c20b.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Python</category>
      <category>Scala</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=e04221b4-bd81-4aa6-9867-4b8d6010a7a5</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,e04221b4-bd81-4aa6-9867-4b8d6010a7a5.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,e04221b4-bd81-4aa6-9867-4b8d6010a7a5.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=e04221b4-bd81-4aa6-9867-4b8d6010a7a5</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A couple of days ago, a buddy of mine, Scott Hanselman, wrote <a href="http://www.hanselman.com/blog/BackToBasicsC4MethodOverloadingAndDynamicTypes.aspx" target="_blank">a
nice little intro to the "dynamic" type in C# 4.0</a>. In particular, I
like (though don't necessarily 100% agree with) his one-sentence summation of dynamic
as <em>"There's no way for you or I to know the type of this now, compiler, so
let's hope that the runtime figures it out."</em> It's an interesting characterization,
but my disagreement with his characterization is not the point here, at least not
of this particular blog entry.
</p>
        <p>
I've been waiting for it for a while, ever since C# 4 was announced, and sure enough,
here we go: Scott's blog is the victim of the <em>Static-Typing Fundamentalist</em>,
the bearded and grizzled veteran of the Static/Dynamic Code Wars, come out to proclaim
the sins of dynamic programming, the evils of those who use(d) it, and why C#/C++/Java
was so much better than Visual Basic/Ruby/Python/whatever. Be careful of these creatures.
They rival Al-Qaeda in their ferocity and zeal, Fox News in their attention to detail
and evidence, and George Bush in their pronouncements of gloom and doom for the future
if we don't <em>act now and eliminate this evil</em>.
</p>
        <p>
Allow me to quote (liberally) from <a href="http://robert-seder.myopenid.com/" target="_blank">Rob</a>'s <a href="http://www.hanselman.com/blog/CommentView.aspx?guid=FC406BB6-2218-4481-A6BA-CD1E12994D74" target="_blank">comment
on Scott's blog</a>, and comment in turn as we go:
</p>
        <blockquote>
          <p>
It's such a shame that you promote this stuff. You should've seen the horrific devastation
that "Variant" caused in the old VB days. Variant single-handedly create
job security for so many people since the late 90's, because of the horrible, horrible,
horrible things that developers did with that ridiculous, 12-byte data type!
</p>
        </blockquote>
        <p>
I just love it when people make comments like "horrific devastation". Nothing
like a little hyperbole to liven things up! I mean, it didn't cause exceptions, it
didn't make code hard to read, it didn't make it tricky for developers to modify and
refactor safely, it leveled cities! burned forests! slaughtered kittens! and even
worse, it was <em>12 bytes in size!</em></p>
        <p>
Never mind the fact that Visual Basic developers frequently churned out apps twice,
three, five times faster than their C++ cousins did. (I know this—I was one of those
C++ developers, and routinely mocked the VB guys across the hall for their crappy
language and code.... until they built an app in a few days that I tried to build
at home in C++ and gave up after two weeks. And all the damn thing did was basic dialogs-and-data
kinds of stuff, too.)
</p>
        <blockquote>
          <p>
This weak-typing with late-binding is just such a bad idea. I know you'll say "But
wait, these are powerful tools that skilled developers can leverage!" - and maybe
so, but 98% of the people that truly use these sorts of techniques out in the real
world, are unskilled developers making a mess of software all across this great land,
because the compiler is so forgiving. 
</p>
        </blockquote>
        <p>
Ah, the "All Developers (Except Me) Are Idiots" argument. I love this one—the
hubris involved here is just too precious for words. I have no doubt that the author
of this post, being (of course) the classically-trained object-oriented developer
and therefore too smart/disciplined/experienced/whatever to fall into such a ridiculous
temptation as to use dynamic typing, would never use this feature except in the Most
Dire of Emergencies, but his fellow programmers, all of them being <em>much</em> less
disciplined/smart/trained/whatever than he is, will fall for the temptation and write
code that levels cities! burns forests! kills kittens! and worse, uses 12 bytes! (Oh,
wait, it's only 3 bytes, because dynamic is just a placeholder for an object reference,
and all object references are 3 bytes in the CLR. Or at least they used to be—I admit,
I haven't checked in CLR 4.) Those poor souls, they won't have any hope! There they'll
be, staring at Visual Studio, wanting <em>desperately</em> to do the Right Thing,
and that evil little programmer devil on their shoulder (probably wearing a T-shirt
that says, "P3rl is l33t" or something equally blasphemous) will whisper,
"You know, if you just make it a dynamic, you can get the compiler to shut up
and you can go home early...."
</p>
        <p>
Oh, right—sorry, I forgot. That devil will whisper, "You know, if you write this
code in Visual Basic .NET, you can make the entire codebase Option Strict Off and
Option Explicit Off, make the compiler shut up and you can go home early...."
Hell, they've been whispering <em>that</em> bit of subversion since 2001. And ye Gods!
The leveled cities! burned forests! cute little kitten bodies! all over the place!
It's fortunate that we C# developers have kept all those Visual Basic developers on
the straight-and-narrow path of <strike>true salvation</strike> static typing.
</p>
        <blockquote>
          <p>
This is a huge step backwards for C#, in my opinion - and creates the same scenario
VB always did - where it is so forgiving, that it allows developers to write horrible
code and you won't so much as see a compiler warning!! I've always tauted that C#
was better, simply because it gave the developer "tough love", and forced
him/her to be better coder and to "make good choices"! :-)
</p>
        </blockquote>
        <p>
Ah, yes, the C# compiler and its "tough love". The "prefer compile
errors over runtime errors" argument, vis-a-vis Scott Meyers' "Effective
C++" circa 1994 or so. It's vastly preferable to see errors early, before the
big demo in front of the VP/President/potential customer. (Anybody who disagrees with
this obviously hasn't had a demo fail in front of a VP/President/potential customer.)
How fortunate that the C# compiler catches all these ugly errors at compile-time,
like
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> DoSomething()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span> List&lt;<span style="color: #0000ff">object</span>&gt;
intList = <span style="color: #0000ff">new</span> List&lt;<span style="color: #0000ff">object</span>&gt;();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span> intList.Add(5);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span>
              <span style="color: #0000ff">string</span> s
= (<span style="color: #0000ff">string</span>) intList[0];</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span> Console.WriteLine(s);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
... because boy, that would be <em>embarrassing</em> if it didn't. I mean, can you
imagine the horror other disciplined/smart/experienced developers would feel if a
lenient compiler actually allowed code like this:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">class</span> Point</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">internal</span>
              <span style="color: #0000ff">int</span> x;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span>
              <span style="color: #0000ff">internal</span>
              <span style="color: #0000ff">int</span> y;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span>
              <span style="color: #0000ff">public</span> Point(<span style="color: #0000ff">int</span> x, <span style="color: #0000ff">int</span> y)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> x
= x;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span> y
= y;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
or this:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">class</span> Point</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">internal</span>
              <span style="color: #0000ff">int</span> x;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span>
              <span style="color: #0000ff">internal</span>
              <span style="color: #0000ff">int</span> y;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span>
              <span style="color: #0000ff">public</span> Point(<span style="color: #0000ff">int</span> x, <span style="color: #0000ff">int</span> y)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span>
              <span style="color: #0000ff">this</span>.x
= x;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span>
              <span style="color: #0000ff">this</span>.y
= y;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">override</span>
              <span style="color: #0000ff">string</span> ToString()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum11"> 11:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum12"> 12:</span>
              <span style="color: #0000ff">return</span> String.Format(<span style="color: #006080">"({0},{1})"</span>,
x, y);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum13"> 13:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum14"> 14:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum15"> 15:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> DoSomething()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum16"> 16:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum17"> 17:</span> Point
pt = <span style="color: #0000ff">new</span> Point(12, 12);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum18"> 18:</span> pt.GetType()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum19"> 19:</span> .GetField(<span style="color: #006080">"x"</span>,
BindingFlags.Instance | </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum20"> 20:</span> BindingFlags.NonPublic)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum21"> 21:</span> .SetValue(pt,
24);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum22"> 22:</span> Console.WriteLine(pt);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum23"> 23:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
to compile? Cities! Forests! Kittens! Thank <em>God</em> C# isn't that kind of lustfully
promiscuous... I mean, "lenient"... compiler!
</p>
        <p>
(Now if only we could tout blog comment engines with spellcheck....)
</p>
        <blockquote>
          <p>
Specific to this blog post, if you are doing somewhere where you can't even quantify
what the data type that is coming back? Guess waht, you've got yourself a bad design. 
</p>
        </blockquote>
        <p>
Wow. There's just no arguing with that one. I mean, knowing the actual type on which
the method is being dispatched is such a <em>huge</em> part of the C# development
experience:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> DoSomething()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span> List&lt;Point&gt;
ptList = <span style="color: #0000ff">new</span> List&lt;Point&gt;();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span> ptList.Add(<span style="color: #0000ff">new</span> Point(12,
12));</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span>
              <span style="color: #0000ff">object</span> o
= ptList[0];</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span> Console.WriteLine(o.ToString());</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Gah. Just the <em>thought</em> of not knowing the concrete type on which the method
is being dispatched gives me the heebie-jeebies.
</p>
        <blockquote>
          <p>
Just because the framework allows you use weak-typing and late-binding, doesn't mean
you should - nor should you endorse it's use, in my opinion. 
</p>
        </blockquote>
        <p>
Somebody better tell all those users of NHibernate, NUnit, Spring.NET, MEF and all
those other Reflection-based tools... including WinForms, ASP.NET, WPF, Workflow and
WCF, come to think about it... that they're using frameworks that clearly were designed
by idiots. (The <em>gall</em> of those people.)
</p>
        <blockquote>
          <p>
I'm just saying, it's a shame that popular "nerd celebrities" like you (and
I mean zero offense by that!) - endorse all this loosey-goosey typing. I say that
becuase I've never seen a single case where weak typing or late binding: A) made a
design better or B) where it didn't make the component or application worse, because
it was a looser design.
</p>
        </blockquote>
        <p>
I'm so glad you were here to set Scott and me straight, Rob. Because otherwise, we
might actually get something done. God <em>forbid</em>.
</p>
        <p>
Little tidbits of thought for those who are still thinking about this one.
</p>
        <ul>
          <li>
            <a href="http://olabini.com/blog/2008/06/fractal-programming/" target="_blank">Ola
Bini describes the application of the right language at the right level of the stack</a> as
a three-layer pyramid.</li>
          <li>
Any C# or Java developer who's not writing unit tests to test their code "because
the compiler will catch all those errors" and provide "tough love"
needs to be fired. <em>Immediately.</em> I cannot conceive of a situation where unit
tests can be passed over in favor of static typing in a professionally-responsible
development project. (Oh, don't mis-read that, I can see lots of situations where
unit tests aren't necessary. But not on code that's going to reach Production.)</li>
          <li>
The argument for the degree of static typing in C# or Java is completely indefensible
compared to what statically-typed type-inferenced languages like Haskell, F# or Scala
provide. And their syntax frequently looks like "let x = [ 1; 2; 3; 4; ]",
which isn't all that far off from what a dynamically-typed language looks like, despite
very very different things happening under the compiler's hood. Until you, the Statically-Typed
Fundamentalist, have written code in a Haskell/ML-derived language, you have no right
arguing the merits of static typing. (In fact, that's probably also true if you've
never written code in Ruby, Python, or PowerShell, either.)</li>
          <li>
There's lots more arguments the Static-Typing Fundamentalist can throw, by the way.
I'm disappointed Rob never mentioned performance, for one—that's a classic line of
attack, too. Never mind the fact that most of those guys are still looping down and
doing other silly micro-optimizations because that's way C++ taught them to do it....</li>
          <li>
Oh, and <em>never ever</em> show the Static Typing Fundamentalist an XML document
and using something like XPath to extract data from it. They inevitably fall into
XML Schema and the "if we just write the schema flexibly enough" and....
The last time I did that.... I still visit his gravesite, all these years later, and
it still hurts, losing him that way.</li>
          <li>
Java guys argued against dynamic typing for years, too... until they tried Groovy
and JRuby and Clojure. Now.... not so much.</li>
        </ul>
        <p>
Peace out.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=e04221b4-bd81-4aa6-9867-4b8d6010a7a5" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Don't Fear the dynamic/VARIANT/Reaper....</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,e04221b4-bd81-4aa6-9867-4b8d6010a7a5.aspx</guid>
      <link>http://blogs.tedneward.com/2010/02/14/Dont+Fear+The+DynamicVARIANTReaper.aspx</link>
      <pubDate>Sun, 14 Feb 2010 11:41:34 GMT</pubDate>
      <description>&lt;p&gt;
A couple of days ago, a buddy of mine, Scott Hanselman, wrote &lt;a href="http://www.hanselman.com/blog/BackToBasicsC4MethodOverloadingAndDynamicTypes.aspx" target="_blank"&gt;a
nice little intro to the &amp;quot;dynamic&amp;quot; type in C# 4.0&lt;/a&gt;. In particular, I
like (though don't necessarily 100% agree with) his one-sentence summation of dynamic
as &lt;em&gt;&amp;quot;There's no way for you or I to know the type of this now, compiler, so
let's hope that the runtime figures it out.&amp;quot;&lt;/em&gt; It's an interesting characterization,
but my disagreement with his characterization is not the point here, at least not
of this particular blog entry.
&lt;/p&gt;
&lt;p&gt;
I've been waiting for it for a while, ever since C# 4 was announced, and sure enough,
here we go: Scott's blog is the victim of the &lt;em&gt;Static-Typing Fundamentalist&lt;/em&gt;,
the bearded and grizzled veteran of the Static/Dynamic Code Wars, come out to proclaim
the sins of dynamic programming, the evils of those who use(d) it, and why C#/C++/Java
was so much better than Visual Basic/Ruby/Python/whatever. Be careful of these creatures.
They rival Al-Qaeda in their ferocity and zeal, Fox News in their attention to detail
and evidence, and George Bush in their pronouncements of gloom and doom for the future
if we don't &lt;em&gt;act now and eliminate this evil&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Allow me to quote (liberally) from &lt;a href="http://robert-seder.myopenid.com/" target="_blank"&gt;Rob&lt;/a&gt;'s &lt;a href="http://www.hanselman.com/blog/CommentView.aspx?guid=FC406BB6-2218-4481-A6BA-CD1E12994D74" target="_blank"&gt;comment
on Scott's blog&lt;/a&gt;, and comment in turn as we go:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
It's such a shame that you promote this stuff. You should've seen the horrific devastation
that &amp;quot;Variant&amp;quot; caused in the old VB days. Variant single-handedly create
job security for so many people since the late 90's, because of the horrible, horrible,
horrible things that developers did with that ridiculous, 12-byte data type!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I just love it when people make comments like &amp;quot;horrific devastation&amp;quot;. Nothing
like a little hyperbole to liven things up! I mean, it didn't cause exceptions, it
didn't make code hard to read, it didn't make it tricky for developers to modify and
refactor safely, it leveled cities! burned forests! slaughtered kittens! and even
worse, it was &lt;em&gt;12 bytes in size!&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Never mind the fact that Visual Basic developers frequently churned out apps twice,
three, five times faster than their C++ cousins did. (I know this—I was one of those
C++ developers, and routinely mocked the VB guys across the hall for their crappy
language and code.... until they built an app in a few days that I tried to build
at home in C++ and gave up after two weeks. And all the damn thing did was basic dialogs-and-data
kinds of stuff, too.)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
This weak-typing with late-binding is just such a bad idea. I know you'll say &amp;quot;But
wait, these are powerful tools that skilled developers can leverage!&amp;quot; - and maybe
so, but 98% of the people that truly use these sorts of techniques out in the real
world, are unskilled developers making a mess of software all across this great land,
because the compiler is so forgiving. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ah, the &amp;quot;All Developers (Except Me) Are Idiots&amp;quot; argument. I love this one—the
hubris involved here is just too precious for words. I have no doubt that the author
of this post, being (of course) the classically-trained object-oriented developer
and therefore too smart/disciplined/experienced/whatever to fall into such a ridiculous
temptation as to use dynamic typing, would never use this feature except in the Most
Dire of Emergencies, but his fellow programmers, all of them being &lt;em&gt;much&lt;/em&gt; less
disciplined/smart/trained/whatever than he is, will fall for the temptation and write
code that levels cities! burns forests! kills kittens! and worse, uses 12 bytes! (Oh,
wait, it's only 3 bytes, because dynamic is just a placeholder for an object reference,
and all object references are 3 bytes in the CLR. Or at least they used to be—I admit,
I haven't checked in CLR 4.) Those poor souls, they won't have any hope! There they'll
be, staring at Visual Studio, wanting &lt;em&gt;desperately&lt;/em&gt; to do the Right Thing,
and that evil little programmer devil on their shoulder (probably wearing a T-shirt
that says, &amp;quot;P3rl is l33t&amp;quot; or something equally blasphemous) will whisper,
&amp;quot;You know, if you just make it a dynamic, you can get the compiler to shut up
and you can go home early....&amp;quot;
&lt;/p&gt;
&lt;p&gt;
Oh, right—sorry, I forgot. That devil will whisper, &amp;quot;You know, if you write this
code in Visual Basic .NET, you can make the entire codebase Option Strict Off and
Option Explicit Off, make the compiler shut up and you can go home early....&amp;quot;
Hell, they've been whispering &lt;em&gt;that&lt;/em&gt; bit of subversion since 2001. And ye Gods!
The leveled cities! burned forests! cute little kitten bodies! all over the place!
It's fortunate that we C# developers have kept all those Visual Basic developers on
the straight-and-narrow path of &lt;strike&gt;true salvation&lt;/strike&gt; static typing.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
This is a huge step backwards for C#, in my opinion - and creates the same scenario
VB always did - where it is so forgiving, that it allows developers to write horrible
code and you won't so much as see a compiler warning!! I've always tauted that C#
was better, simply because it gave the developer &amp;quot;tough love&amp;quot;, and forced
him/her to be better coder and to &amp;quot;make good choices&amp;quot;! :-)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ah, yes, the C# compiler and its &amp;quot;tough love&amp;quot;. The &amp;quot;prefer compile
errors over runtime errors&amp;quot; argument, vis-a-vis Scott Meyers' &amp;quot;Effective
C++&amp;quot; circa 1994 or so. It's vastly preferable to see errors early, before the
big demo in front of the VP/President/potential customer. (Anybody who disagrees with
this obviously hasn't had a demo fail in front of a VP/President/potential customer.)
How fortunate that the C# compiler catches all these ugly errors at compile-time,
like
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;
intList = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; intList.Add(5);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; s
= (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;) intList[0];&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; Console.WriteLine(s);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
... because boy, that would be &lt;em&gt;embarrassing&lt;/em&gt; if it didn't. I mean, can you
imagine the horror other disciplined/smart/experienced developers would feel if a
lenient compiler actually allowed code like this:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Point&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Point(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; x
= x;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt; y
= y;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
or this:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Point&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Point(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; x, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; y)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.x
= x;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.y
= y;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ToString()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt; 11:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt; 12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; String.Format(&lt;span style="color: #006080"&gt;&amp;quot;({0},{1})&amp;quot;&lt;/span&gt;,
x, y);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt; 13:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt; 14:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt; 15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt; 16:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt; 17:&lt;/span&gt; Point
pt = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Point(12, 12);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt; 18:&lt;/span&gt; pt.GetType()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt; 19:&lt;/span&gt; .GetField(&lt;span style="color: #006080"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;,
BindingFlags.Instance | &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt; 20:&lt;/span&gt; BindingFlags.NonPublic)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt; 21:&lt;/span&gt; .SetValue(pt,
24);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt; 22:&lt;/span&gt; Console.WriteLine(pt);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt; 23:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
to compile? Cities! Forests! Kittens! Thank &lt;em&gt;God&lt;/em&gt; C# isn't that kind of lustfully
promiscuous... I mean, &amp;quot;lenient&amp;quot;... compiler!
&lt;/p&gt;
&lt;p&gt;
(Now if only we could tout blog comment engines with spellcheck....)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Specific to this blog post, if you are doing somewhere where you can't even quantify
what the data type that is coming back? Guess waht, you've got yourself a bad design. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wow. There's just no arguing with that one. I mean, knowing the actual type on which
the method is being dispatched is such a &lt;em&gt;huge&lt;/em&gt; part of the C# development
experience:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; List&amp;lt;Point&amp;gt;
ptList = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;Point&amp;gt;();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; ptList.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Point(12,
12));&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; o
= ptList[0];&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; Console.WriteLine(o.ToString());&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Gah. Just the &lt;em&gt;thought&lt;/em&gt; of not knowing the concrete type on which the method
is being dispatched gives me the heebie-jeebies.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Just because the framework allows you use weak-typing and late-binding, doesn't mean
you should - nor should you endorse it's use, in my opinion. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Somebody better tell all those users of NHibernate, NUnit, Spring.NET, MEF and all
those other Reflection-based tools... including WinForms, ASP.NET, WPF, Workflow and
WCF, come to think about it... that they're using frameworks that clearly were designed
by idiots. (The &lt;em&gt;gall&lt;/em&gt; of those people.)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I'm just saying, it's a shame that popular &amp;quot;nerd celebrities&amp;quot; like you (and
I mean zero offense by that!) - endorse all this loosey-goosey typing. I say that
becuase I've never seen a single case where weak typing or late binding: A) made a
design better or B) where it didn't make the component or application worse, because
it was a looser design.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I'm so glad you were here to set Scott and me straight, Rob. Because otherwise, we
might actually get something done. God &lt;em&gt;forbid&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Little tidbits of thought for those who are still thinking about this one.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://olabini.com/blog/2008/06/fractal-programming/" target="_blank"&gt;Ola
Bini describes the application of the right language at the right level of the stack&lt;/a&gt; as
a three-layer pyramid.&lt;/li&gt;
&lt;li&gt;
Any C# or Java developer who's not writing unit tests to test their code &amp;quot;because
the compiler will catch all those errors&amp;quot; and provide &amp;quot;tough love&amp;quot;
needs to be fired. &lt;em&gt;Immediately.&lt;/em&gt; I cannot conceive of a situation where unit
tests can be passed over in favor of static typing in a professionally-responsible
development project. (Oh, don't mis-read that, I can see lots of situations where
unit tests aren't necessary. But not on code that's going to reach Production.)&lt;/li&gt;
&lt;li&gt;
The argument for the degree of static typing in C# or Java is completely indefensible
compared to what statically-typed type-inferenced languages like Haskell, F# or Scala
provide. And their syntax frequently looks like &amp;quot;let x = [ 1; 2; 3; 4; ]&amp;quot;,
which isn't all that far off from what a dynamically-typed language looks like, despite
very very different things happening under the compiler's hood. Until you, the Statically-Typed
Fundamentalist, have written code in a Haskell/ML-derived language, you have no right
arguing the merits of static typing. (In fact, that's probably also true if you've
never written code in Ruby, Python, or PowerShell, either.)&lt;/li&gt;
&lt;li&gt;
There's lots more arguments the Static-Typing Fundamentalist can throw, by the way.
I'm disappointed Rob never mentioned performance, for one—that's a classic line of
attack, too. Never mind the fact that most of those guys are still looping down and
doing other silly micro-optimizations because that's way C++ taught them to do it....&lt;/li&gt;
&lt;li&gt;
Oh, and &lt;em&gt;never ever&lt;/em&gt; show the Static Typing Fundamentalist an XML document
and using something like XPath to extract data from it. They inevitably fall into
XML Schema and the &amp;quot;if we just write the schema flexibly enough&amp;quot; and....
The last time I did that.... I still visit his gravesite, all these years later, and
it still hurts, losing him that way.&lt;/li&gt;
&lt;li&gt;
Java guys argued against dynamic typing for years, too... until they tried Groovy
and JRuby and Clojure. Now.... not so much.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Peace out.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=e04221b4-bd81-4aa6-9867-4b8d6010a7a5" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,e04221b4-bd81-4aa6-9867-4b8d6010a7a5.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
      <category>WCF</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=4b2137dd-11cc-4ad5-8771-5906f2759273</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,4b2137dd-11cc-4ad5-8771-5906f2759273.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,4b2137dd-11cc-4ad5-8771-5906f2759273.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4b2137dd-11cc-4ad5-8771-5906f2759273</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Cruising the Web late last night, I ran across <a href="http://blogs.techrepublic.com.com/10things/?p=1297" target="_blank">"10
things you can do to advance your career as a developer"</a>, summarized below:
</p>
        <ol>
          <li>
Build a PC 
</li>
          <li>
Participate in an online forum and help others 
</li>
          <li>
Man the help desk 
</li>
          <li>
Perform field service 
</li>
          <li>
Perform DBA functions 
</li>
          <li>
Perform all phases of the project lifecycle 
</li>
          <li>
Recognize and learn the latest technologies 
</li>
          <li>
Be an independent contractor 
</li>
          <li>
Lead a project, supervise, or manage 
</li>
          <li>
Seek additional education 
</li>
        </ol>
        <p>
I agreed with some of them, I disagreed with others, and in general felt like they
were a little too high-level to be of real use. For example, "Seek additional
education" seems entirely too vague: In what? How much? How often? And "Recognize
and learn the latest technologies" is something like offering advice to the Olympic
fencing silver medalist and saying, "You should have tried harder".
</p>
        <p>
So, in the great spirit of "Not Invented Here", I present my own list; as
usual, I welcome comment and argument. And, also as usual, caveats apply, since not
everybody will be in precisely the same place and be looking for the same things.
In general, though, whether you're looking to kick-start your career or just "kick
it up a notch", I believe this list will help, because these ideas have been
of help to me at some point or another in my own career.
</p>
        <h3>
          <strong>
            <em>10: Build a PC.</em>
          </strong>
        </h3>
        <p>
Yes, even developers have to know about hardware. More importantly, a developer at
a small organization or team will find himself in a position where he has to take
on some system administrator roles, and sometimes that means grabbing a screwdriver,
getting a little dusty and dirty, and swapping hardware around. Having said this,
though, once you've done it once or twice, leave it alone—the hardware game is an
ever-shifting and ever-changing game (much like software is, surprise surprise), and
it's been my experience that most of us only really have the time to pursue one or
the other.
</p>
        <p>
By the way, "PC" there is something of a generic term—build a Linux box,
build a Windows box, or "build" a Mac OS box (meaning, buy a Mac Pro and
trick it out a little—add more memory, add another hard drive, and so on), they all
get you comfortable with snapping parts together, and discovering just how ridiculously
simple the whole thing really is.
</p>
        <p>
And for the record, once you've done it, go ahead and go back to buying pre-built
systems or laptops—I've never found building a PC to be any cheaper than buying one
pre-built. Particularly for PC systems, I prefer to use smaller local vendors where
I can customize and trick out the box. If you're a Mac, that's not really an option
unless you're into the "Hackintosh" thing, which is quite possibly the logical
equivalent to "Build a PC". Having never done it myself, though, I can't
say how useful that is as an educational action.
</p>
        <h3>
        </h3>
        <h3>
        </h3>
        <h3>
        </h3>
        <h3>
          <strong>
            <em>9: Pick a destination</em>
          </strong>
        </h3>
        <p>
Do you want to run a team of your own? Become an independent contractor? Teach programming
classes? Speak at conferences? Move up into higher management and get out of the programming
game altogether? Everybody's got a different idea of what they consider to be the
"ideal" career, but it's amazing how many people don't really think about
what they want their career path to be.
</p>
        <p>
A wise man once said, "The journey of a thousand miles begins with a single step."
I disagree: The journey of a thousand miles begins with the damn map. You have to
know where you want to go, and a rough idea of how to get there, before you can really
start with that single step. Otherwise, you're just wandering, which in itself isn't
a bad thing, but isn't going to get you to a destination except by random chance.
(Sometimes that's not a bad result, but at least then you're openly admitting that
you're leaving your career in the hands of chance. If you're OK with that, skip to
the next item. If you're not, read on.)
</p>
        <p>
Lay out explicitly (as in, write it down someplace) what kind of job you're wanting
to grow into, and then lay out a couple of scenarios that move you closer towards
that goal. Can you grow within the company you're in? (Have others been able to?)
Do you need to quit and strike out on your own? Do you want to lead a team of your
own? (Are there new projects coming in to the company that you could put yourself
forward as a potential tech lead?) And so on.
</p>
        <p>
Once you've identified the destination, now you can start thinking about steps to
get there. 
</p>
        <p>
If you want to become a speaker, put your name forward to give some presentations
at the local technology user group, or volunteer to hold a "brown bag" session
at the company. Sign up with Toastmasters to hone your speaking technique. Watch other
speakers give technical talks, and see what they do that you don't, and vice versa. 
</p>
        <p>
If you want to be a tech lead, start by quietly assisting other members of the team
get their work done. Help them debug thorny problems. Answer questions they have.
Offer yourself up as a resource for dealing with hard problems.
</p>
        <p>
If you want to slowly move up the management chain, look to get into the project management
side of things. Offer to be a point of contact for the users. Learn the business better.
Sit down next to one of your users and watch their interaction with the existing software,
and try to see the system from their point of view.
</p>
        <p>
And so on.
</p>
        <h3>
          <strong>
            <em>8: Be a bell curve</em>
          </strong>
        </h3>
        <p>
Frequently, at conferences, attendees ask me how I got to know so much on so many
things. In some ways, I'm reminded of the story of a world-famous concert pianist
giving a concert at Carnegie Hall—when a gushing fan said, "I'd give my life
to be able to play like that", the pianist responded quietly, "I did".
But as much as I'd like to leave you with the impression that I've dedicated my entire
life to knowing everything I could about this industry, that would be something of
a lie. The truth is, I don't know anywhere near as much as I'd like, and I'm always
poking my head into new areas. Thank God for my ADD, that's all I can say on that
one.
</p>
        <p>
For the rest of you, though, that's not feasible, and not really practical, particularly
since I have an advantage that the "working" programmer doesn't—I have set
aside weeks or months in which to do nothing more than study a new technology or language.
</p>
        <p>
Back in the early days of my career, though, when I was holding down the 9-to-5, I
was a Windows/C++ programmer. I was working with the Borland C++ compiler and its
associated framework, the ObjectWindows Library (OWL), extending and maintaining applications
written in it. One contracting client wanted me to work with Microsoft MFC instead
of OWL. Another one was storing data into a relational database using ODBC. And so
on. Slowly, over time, I built up a "bell curve"-looking collection of skills
that sort of "hovered" around the central position of C++/Windows.
</p>
        <p>
Then, one day, a buddy of mine mentioned the team on which he was a project manager
was looking for new blood. They were doing web applications, something with which
I had zero experience—this was completely outside of my bell curve. HTML, HTTP, Cold
Fusion, NetDynamics (an early Java app server), this was way out of my range, though
at least NetDynamics was a <em>little</em> similar, since it was basically a server-side
application framework, and I had some experience with app frameworks from my C++ days.
So, resting on my C++ experience, I started flirting with Java, and so on.
</p>
        <p>
Before long, my "bell curve" had been readjusted to have Java more or less
at its center, and I found that experience in C++ still worked out here—what I knew
about ODBC turned out to be incredibly useful in understanding JDBC, what I knew about
DLLs from Windows turned out to be helpful in understanding Java's dynamic loading
model, and of course syntactically Java looked a lot like C++ even though it behaved
a little bit differently under the hood. (One article author suggested that Java was
closer to Smalltalk than C++, and that prompted me to briefly flirt with Smalltalk
before I concluded said author was out of his frakking mind.)
</p>
        <p>
All of this happened over roughly a three-year period, by the way.
</p>
        <p>
The point here is that you won't be able to assimilate the entire industry in a single
sitting, so pick something that's relatively close to what you already know, and use
your experience as a springboard to learn something that's new, yet possibly-if-not-probably
useful to your current job. You don't have to be a deep expert in it, and the further
away it is from what you do, the less you really need to know about it (hence the
bell curve metaphor), but you're still exposing yourself to new ideas and new concepts
and new tools/technologies that still could be applicable to what you do on a daily
basis. Over time the "center" of your bell curve may drift away from what
you've done to include new things, and that's OK.
</p>
        <h3>
          <strong>
            <em>7: Learn one new thing every year</em>
          </strong>
        </h3>
        <p>
In the last tip, I told you to branch out slowly from what you know. In this tip,
I'm telling you to go throw a dart at something entirely unfamiliar to you and learn
it. Yes, I realize this sounds contradictory. It's because those who stick to only
what they know end up missing the radical shifts of direction that the industry hits
every half-decade or so until it's mainstream and commonplace and "everybody's
doing it".
</p>
        <p>
In their amazing book "The Pragmatic Programmer", Dave Thomas and Andy Hunt
suggest that you learn one new programming language every year. I'm going to amend
that somewhat—not because there aren't enough languages in the world to keep you on
that pace for the rest of your life—far from it, if that's what you want, go learn
Ruby, F#, Scala, Groovy, Clojure, Icon, Io, Erlang, Haskell and Smalltalk, then come
back to me for the list for 2020—but because languages aren't the only thing that
we as developers need to explore. There's a lot of movement going on in areas beyond
languages, and you don't want to be the last kid on the block to know they're happening.
</p>
        <p>
Consider this list: object databases (<a href="http://www.db4o.com" target="_blank">db4o</a>)
and/or the "NoSQL" movement (<a href="http://www.mongodb.org/display/DOCS/Tutorial" target="_blank">MongoDB</a>).
Dependency injection and composable architectures (<a href="http://www.springframework.org" target="_blank">Spring</a>, <a href="http://mef.codeplex.com" target="_blank">MEF</a>).
A dynamic language (<a href="http://www.rubyforge.org" target="_blank">Ruby</a>, <a href="http://www.python.org" target="_blank">Python</a>, <a href="http://www.ecmascript.org" target="_blank">ECMAScript</a>).
A functional language (<a href="http://msdn.microsoft.com/en-us/fsharp/default.aspx" target="_blank">F#</a>, <a href="http://www.scala-lang.org" target="_blank">Scala</a>, <a href="http://www.haskell.org" target="_blank">Haskell</a>).
A Lisp (Common Lisp, <a href="http://clojure.org" target="_blank">Clojure</a>, Scheme,
Nu). A mobile platform (iPhone, Android). "Space"-based architecture (<a href="http://www.gigaspaces.com" target="_blank">Gigaspaces</a>,
Terracotta). Rich UI platforms (Flash/Flex, Silverlight). Browser enhancements (AJAX,
jQuery, HTML 5) and how they're different from the rich UI platforms. And this is
without adding any of the "obvious" stuff, like Cloud, to the list.
</p>
        <p>
(I'm not convinced Cloud is something worth learning this year, anyway.)
</p>
        <p>
You get through that list, you're operating outside of your comfort zone, and chances
are, your boss' comfort zone, which puts you into the enviable position of being somebody
who can advise him around those technologies. <em>DO NOT TAKE THIS TO MEAN YOU MUST
KNOW THEM DEEPLY.</em> Just having a passing familiarity with them can be enough. <em>DO
NOT TAKE THIS TO MEAN YOU SHOULD PROPOSE USING THEM ON THE NEXT PROJECT.</em> In fact,
sometimes the most compelling evidence that you really know where and when they should
be used is when you suggest stealing ideas from the thing, rather than trying to force-fit
the thing onto the project as a whole.
</p>
        <h3>
          <strong>
            <em>6: Practice, practice, practice</em>
          </strong>
        </h3>
        <p>
Speaking of the concert pianist, somebody once asked him how to get to Carnegie Hall.
HIs answer: "Practice, my boy, practice."
</p>
        <p>
The same is true here. You're not going to get to be a better developer without practice.
Volunteer some time—even if it's just an hour a week—on an open-source project, or
start one of your own. Heck, it doesn't even have to be an "open source"
project—just create some requirements of your own, solve a problem that a family member
is having, or rewrite the project you're on as an interesting side-project. Do the
Nike thing and "Just do it". Write some Scala code. Write some F# code.
Once you're past "hello world", write the Scala code to use db4o as a persistent
storage. Wire it up behind Tapestry. Or write straight servlets in Scala. And so on.
</p>
        <h3>
          <strong>
            <em>5: Turn off the TV</em>
          </strong>
        </h3>
        <p>
Speaking of marketing slogans, if you're like most Americans, surveys have shown that
you watch about four hours of TV a day, or 28 hours of TV a week. In that same amount
of time (28 hours over 1 week), you could read the entire set of poems by Maya Angelou,
one F. Scott Fitzgerald novel, all poems by T.S.Eliot, 2 plays by Thornton Wilder,
or all 150 Psalms of the Bible. An average reader, reading just one hour a day, can
finish an "average-sized" book (let's assume about the size of a novel)
in a week, which translates to 52 books a year.
</p>
        <p>
Let's assume a technical book is going to take slightly longer, since it's a bit deeper
in concept and requires you to spend some time experimenting and typing in code; let's
assume that reading and going through the exercises of an average technical book will
require 4 weeks (a month) instead of just one week. That's 12 new tools/languages/frameworks/ideas
you'd be learning per year.
</p>
        <p>
All because you stopped watching David Caruso turn to the camera, whip his sunglasses
off and say something stupid. (I guess it's not his fault; <em>CSI:Miami</em> is a
crap show. The other two are actually not bad, but <em>Miami</em> just makes me retch.) 
</p>
        <p>
After all, when's the last time that David Caruso or the rest of that show did anything
that was even remotely realistic from a computer perspective? (I always laugh out
loud every time they run a database search against some national database on a completely
non-indexable criteria—like a partial license plate number—and it comes back in seconds.
What the hell database are THEY using? I want it!) Soon as you hear The Who break
into that riff, flip off the TV (or set it to mute) and pick up the book on the nightstand
and boost your career. (And hopefully sink Caruso's.)
</p>
        <p>
Or, if you just can't give up your weekly dose of Caruso, then put the book in the
bathroom. Think about it—how much time do you spend in there a week?
</p>
        <p>
And this gets even better when you get a Kindle or other e-reader that accepts PDFs,
or the book you're interested in is natively supported in the e-readers' format. Now
you have it with you for lunch, waiting at dinner for your food to arrive, or while
you're sitting guard on your 10-year-old so he doesn't sneak out of his room after
his bedtime to play more XBox.
</p>
        <h3>
          <strong>
            <em>4: Have a life</em>
          </strong>
        </h3>
        <p>
Speaking of XBox, don't slave your life to work. Pursue other things. Scientists have
repeatedly discovered that exercise helps keep the mind in shape, so take a couple
of hours a week (buh-bye, <em>American Idol</em>) and go get some exercise. Pick up
a new sport you've never played before, or just go work out at the gym. (This year
I'm doing Hopkido and fencing.) Read some nontechnical books. (I recommend anything
by Malcolm Gladwell as a starting point.) Spend time with your family, if you have
one—mine spends at least six or seven hours a week playing "family games"
like <a href="http://www.realitycheckgames.com/Products/127-the-settlers-of-catan.aspx" target="_blank">Settlers
of Catan</a>, <a href="http://www.realitycheckgames.com/Products/113-dominion.aspx" target="_blank">Dominion</a>, <a href="http://www.realitycheckgames.com/Products/88-to-court-the-king.aspx" target="_blank">To
Court The King</a>, <a href="http://www.realitycheckgames.com/Products/98-munchkin.aspx" target="_blank">Munchkin</a>,
and other non-traditional games, usually over lunch or dinner. I also belong to an
informal "Game Night club" in Redmond consisting of several Microsoft employees
and their families, as well as outsiders. And so on. Heck, go to a local bar and watch
the game, and you'll meet some really interesting people. And some boring people,
too, but you don't have to talk to them during the next game if you don't want.
</p>
        <p>
This isn't just about maintaining a healthy work-life balance—it's also about having
interests that other people can latch on to, qualities that will make you more "human"
and more interesting as a person, and make you more attractive and "connectable"
and stand out better in their mind when they hear that somebody they know is looking
for a software developer. This will also help you connect better with your users,
because like it or not, they do <em>not</em> get your puns involving Klingon. (Besides,
the geek stereotype is SO 90's, and it's time we let the world know that.)
</p>
        <p>
Besides, you never know when having some depth in other areas—philosophy, music, art,
physics, sports, whatever—will help you create an analogy that will explain some thorny
computer science concept to a non-technical person and get past a communication roadblock.
</p>
        <h3>
          <strong>
            <em>3: Practice on a cadaver</em>
          </strong>
        </h3>
        <p>
Long before they scrub up for their first surgery on a human, medical students practice
on dead bodies. It's grisly, it's not something we really want to think about, but
when you're the one going under the general anesthesia, would you rather see the surgeon
flipping through the "How-To" manual, "just to refresh himself"?
</p>
        <p>
Diagnosing and debugging a software system can be a hugely puzzling trial, largely
because there are so many possible "moving parts" that are creating the
problem. Compound that with certain bugs that only appear when multiple users are
interacting at the same time, and you've got a recipe for disaster when a production
bug suddenly threatens to jeopardize the company's online revenue stream. Do you really
want to be sitting in the production center, flipping through "How-To"'s
and FAQs online while your boss looks on and your CEO is counting every minute by
the thousands of dollars?
</p>
        <p>
Take a tip from the med student: long before the thing goes into production, introduce
a bug, deploy the code into a virtual machine, then hand it over to a buddy and let
him try to track it down. Have him do the same for you. Or if you can't find a buddy
to help you, do it to yourself (but try not to cheat or let your knowledge of where
the bug is color your reactions). How do you know the bug is there? Once you know
it's there, how do you determine what kind of bug it is? Where do you start looking
for it? How would you track it down without attaching a debugger or otherwise disrupting
the system's operations? (Remember, we can't always just attach an IDE and step through
the code on a production server.) How do you patch the running system? And so on.
</p>
        <p>
Remember, you can either learn these things under controlled circumstances, learn
them while you're in the "hot seat", so to speak, or not learn them at all
and see how long the company keeps you around.
</p>
        <h3>
          <strong>
            <em>2: Administer the system</em>
          </strong>
        </h3>
        <p>
Take off your developer hat for a while—a week, a month, a quarter, whatever—and be
one of those thankless folks who have to keep the system running. Wear the pager that
goes off at 3AM when a server goes down. Stay all night doing one of those "server
upgrades" that have to be done in the middle of the night because the system
can't be upgraded while users are using it. Answer the phones or chat requests of
those hapless users who can't figure out why they can't find the record they just
entered into the system, and after a half-hour of thinking it must be a bug, ask them
if they remembered to check the "Save this record" checkbox on the UI (which
had to be there because the developers were told it had to be there) before submitting
the form. Try adding a user. Try removing a user. Try changing the user's password.
Learn what a real joy having seven different properties/XML/configuration files scattered
all over the system really is.
</p>
        <p>
Once you've done that, particularly on a system that you built and tossed over the
fence into production and thought that was the end of it, you'll understand just why
it's so important to keep the system administrators in mind when you're building a
system for production. And why it's critical to be able to have a system that tells
you when it's down, instead of having to go hunting up the answer when a VP tells
you it is (usually because he's just gotten an outage message from a customer or client).
</p>
        <h3>
          <strong>
            <em>1: Cultivate a peer group</em>
          </strong>
        </h3>
        <p>
Yes, you can join an online forum, ask questions, answer questions, and learn that
way, but that's a poor substitute for physical human contact once in a while. Like
it or not, various sociological and psychological studies confirm that a "connection"
is really still best made when eyeballs meet flesh. (The "disassociative"
nature of email is what makes it so easy to be rude or flamboyant or downright violent
in email when we would never say such things in person.) Go to conferences, join a
user group, even start one of your own if you can't find one. Yes, the online avenues
are still open to you—read blogs, join mailing lists or newsgroups—but don't lose
sight of human-to-human contact.
</p>
        <p>
While we're at it, don't create a peer group of people that all look to you for answers—as
flattering as that feels, and as much as we do learn by providing answers, frequently
we rise (or fall) to the level of our peers—have at least one peer group that's overwhelmingly
smarter than you, and as scary as it might be, venture to offer an answer or two to
that group when a question comes up. You don't have to be right—in fact, it's often
vastly more educational to be wrong. Just maintain an attitude that says "I have
no ego wrapped up in being right or wrong", and take the entire experience as
a learning opportunity.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=4b2137dd-11cc-4ad5-8771-5906f2759273" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>10 Things To Improve Your Development Career</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,4b2137dd-11cc-4ad5-8771-5906f2759273.aspx</guid>
      <link>http://blogs.tedneward.com/2010/01/19/10+Things+To+Improve+Your+Development+Career.aspx</link>
      <pubDate>Tue, 19 Jan 2010 10:02:01 GMT</pubDate>
      <description>&lt;p&gt;
Cruising the Web late last night, I ran across &lt;a href="http://blogs.techrepublic.com.com/10things/?p=1297" target="_blank"&gt;&amp;quot;10
things you can do to advance your career as a developer&amp;quot;&lt;/a&gt;, summarized below:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Build a PC 
&lt;/li&gt;
&lt;li&gt;
Participate in an online forum and help others 
&lt;/li&gt;
&lt;li&gt;
Man the help desk 
&lt;/li&gt;
&lt;li&gt;
Perform field service 
&lt;/li&gt;
&lt;li&gt;
Perform DBA functions 
&lt;/li&gt;
&lt;li&gt;
Perform all phases of the project lifecycle 
&lt;/li&gt;
&lt;li&gt;
Recognize and learn the latest technologies 
&lt;/li&gt;
&lt;li&gt;
Be an independent contractor 
&lt;/li&gt;
&lt;li&gt;
Lead a project, supervise, or manage 
&lt;/li&gt;
&lt;li&gt;
Seek additional education 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
I agreed with some of them, I disagreed with others, and in general felt like they
were a little too high-level to be of real use. For example, &amp;quot;Seek additional
education&amp;quot; seems entirely too vague: In what? How much? How often? And &amp;quot;Recognize
and learn the latest technologies&amp;quot; is something like offering advice to the Olympic
fencing silver medalist and saying, &amp;quot;You should have tried harder&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
So, in the great spirit of &amp;quot;Not Invented Here&amp;quot;, I present my own list; as
usual, I welcome comment and argument. And, also as usual, caveats apply, since not
everybody will be in precisely the same place and be looking for the same things.
In general, though, whether you're looking to kick-start your career or just &amp;quot;kick
it up a notch&amp;quot;, I believe this list will help, because these ideas have been
of help to me at some point or another in my own career.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;10: Build a PC.&lt;/em&gt;&lt;/strong&gt; 
&lt;/h3&gt;
&lt;p&gt;
Yes, even developers have to know about hardware. More importantly, a developer at
a small organization or team will find himself in a position where he has to take
on some system administrator roles, and sometimes that means grabbing a screwdriver,
getting a little dusty and dirty, and swapping hardware around. Having said this,
though, once you've done it once or twice, leave it alone—the hardware game is an
ever-shifting and ever-changing game (much like software is, surprise surprise), and
it's been my experience that most of us only really have the time to pursue one or
the other.
&lt;/p&gt;
&lt;p&gt;
By the way, &amp;quot;PC&amp;quot; there is something of a generic term—build a Linux box,
build a Windows box, or &amp;quot;build&amp;quot; a Mac OS box (meaning, buy a Mac Pro and
trick it out a little—add more memory, add another hard drive, and so on), they all
get you comfortable with snapping parts together, and discovering just how ridiculously
simple the whole thing really is.
&lt;/p&gt;
&lt;p&gt;
And for the record, once you've done it, go ahead and go back to buying pre-built
systems or laptops—I've never found building a PC to be any cheaper than buying one
pre-built. Particularly for PC systems, I prefer to use smaller local vendors where
I can customize and trick out the box. If you're a Mac, that's not really an option
unless you're into the &amp;quot;Hackintosh&amp;quot; thing, which is quite possibly the logical
equivalent to &amp;quot;Build a PC&amp;quot;. Having never done it myself, though, I can't
say how useful that is as an educational action.
&lt;/p&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;9: Pick a destination&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Do you want to run a team of your own? Become an independent contractor? Teach programming
classes? Speak at conferences? Move up into higher management and get out of the programming
game altogether? Everybody's got a different idea of what they consider to be the
&amp;quot;ideal&amp;quot; career, but it's amazing how many people don't really think about
what they want their career path to be.
&lt;/p&gt;
&lt;p&gt;
A wise man once said, &amp;quot;The journey of a thousand miles begins with a single step.&amp;quot;
I disagree: The journey of a thousand miles begins with the damn map. You have to
know where you want to go, and a rough idea of how to get there, before you can really
start with that single step. Otherwise, you're just wandering, which in itself isn't
a bad thing, but isn't going to get you to a destination except by random chance.
(Sometimes that's not a bad result, but at least then you're openly admitting that
you're leaving your career in the hands of chance. If you're OK with that, skip to
the next item. If you're not, read on.)
&lt;/p&gt;
&lt;p&gt;
Lay out explicitly (as in, write it down someplace) what kind of job you're wanting
to grow into, and then lay out a couple of scenarios that move you closer towards
that goal. Can you grow within the company you're in? (Have others been able to?)
Do you need to quit and strike out on your own? Do you want to lead a team of your
own? (Are there new projects coming in to the company that you could put yourself
forward as a potential tech lead?) And so on.
&lt;/p&gt;
&lt;p&gt;
Once you've identified the destination, now you can start thinking about steps to
get there. 
&lt;/p&gt;
&lt;p&gt;
If you want to become a speaker, put your name forward to give some presentations
at the local technology user group, or volunteer to hold a &amp;quot;brown bag&amp;quot; session
at the company. Sign up with Toastmasters to hone your speaking technique. Watch other
speakers give technical talks, and see what they do that you don't, and vice versa. 
&lt;/p&gt;
&lt;p&gt;
If you want to be a tech lead, start by quietly assisting other members of the team
get their work done. Help them debug thorny problems. Answer questions they have.
Offer yourself up as a resource for dealing with hard problems.
&lt;/p&gt;
&lt;p&gt;
If you want to slowly move up the management chain, look to get into the project management
side of things. Offer to be a point of contact for the users. Learn the business better.
Sit down next to one of your users and watch their interaction with the existing software,
and try to see the system from their point of view.
&lt;/p&gt;
&lt;p&gt;
And so on.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;8: Be a bell curve&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Frequently, at conferences, attendees ask me how I got to know so much on so many
things. In some ways, I'm reminded of the story of a world-famous concert pianist
giving a concert at Carnegie Hall—when a gushing fan said, &amp;quot;I'd give my life
to be able to play like that&amp;quot;, the pianist responded quietly, &amp;quot;I did&amp;quot;.
But as much as I'd like to leave you with the impression that I've dedicated my entire
life to knowing everything I could about this industry, that would be something of
a lie. The truth is, I don't know anywhere near as much as I'd like, and I'm always
poking my head into new areas. Thank God for my ADD, that's all I can say on that
one.
&lt;/p&gt;
&lt;p&gt;
For the rest of you, though, that's not feasible, and not really practical, particularly
since I have an advantage that the &amp;quot;working&amp;quot; programmer doesn't—I have set
aside weeks or months in which to do nothing more than study a new technology or language.
&lt;/p&gt;
&lt;p&gt;
Back in the early days of my career, though, when I was holding down the 9-to-5, I
was a Windows/C++ programmer. I was working with the Borland C++ compiler and its
associated framework, the ObjectWindows Library (OWL), extending and maintaining applications
written in it. One contracting client wanted me to work with Microsoft MFC instead
of OWL. Another one was storing data into a relational database using ODBC. And so
on. Slowly, over time, I built up a &amp;quot;bell curve&amp;quot;-looking collection of skills
that sort of &amp;quot;hovered&amp;quot; around the central position of C++/Windows.
&lt;/p&gt;
&lt;p&gt;
Then, one day, a buddy of mine mentioned the team on which he was a project manager
was looking for new blood. They were doing web applications, something with which
I had zero experience—this was completely outside of my bell curve. HTML, HTTP, Cold
Fusion, NetDynamics (an early Java app server), this was way out of my range, though
at least NetDynamics was a &lt;em&gt;little&lt;/em&gt; similar, since it was basically a server-side
application framework, and I had some experience with app frameworks from my C++ days.
So, resting on my C++ experience, I started flirting with Java, and so on.
&lt;/p&gt;
&lt;p&gt;
Before long, my &amp;quot;bell curve&amp;quot; had been readjusted to have Java more or less
at its center, and I found that experience in C++ still worked out here—what I knew
about ODBC turned out to be incredibly useful in understanding JDBC, what I knew about
DLLs from Windows turned out to be helpful in understanding Java's dynamic loading
model, and of course syntactically Java looked a lot like C++ even though it behaved
a little bit differently under the hood. (One article author suggested that Java was
closer to Smalltalk than C++, and that prompted me to briefly flirt with Smalltalk
before I concluded said author was out of his frakking mind.)
&lt;/p&gt;
&lt;p&gt;
All of this happened over roughly a three-year period, by the way.
&lt;/p&gt;
&lt;p&gt;
The point here is that you won't be able to assimilate the entire industry in a single
sitting, so pick something that's relatively close to what you already know, and use
your experience as a springboard to learn something that's new, yet possibly-if-not-probably
useful to your current job. You don't have to be a deep expert in it, and the further
away it is from what you do, the less you really need to know about it (hence the
bell curve metaphor), but you're still exposing yourself to new ideas and new concepts
and new tools/technologies that still could be applicable to what you do on a daily
basis. Over time the &amp;quot;center&amp;quot; of your bell curve may drift away from what
you've done to include new things, and that's OK.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;7: Learn one new thing every year&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
In the last tip, I told you to branch out slowly from what you know. In this tip,
I'm telling you to go throw a dart at something entirely unfamiliar to you and learn
it. Yes, I realize this sounds contradictory. It's because those who stick to only
what they know end up missing the radical shifts of direction that the industry hits
every half-decade or so until it's mainstream and commonplace and &amp;quot;everybody's
doing it&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
In their amazing book &amp;quot;The Pragmatic Programmer&amp;quot;, Dave Thomas and Andy Hunt
suggest that you learn one new programming language every year. I'm going to amend
that somewhat—not because there aren't enough languages in the world to keep you on
that pace for the rest of your life—far from it, if that's what you want, go learn
Ruby, F#, Scala, Groovy, Clojure, Icon, Io, Erlang, Haskell and Smalltalk, then come
back to me for the list for 2020—but because languages aren't the only thing that
we as developers need to explore. There's a lot of movement going on in areas beyond
languages, and you don't want to be the last kid on the block to know they're happening.
&lt;/p&gt;
&lt;p&gt;
Consider this list: object databases (&lt;a href="http://www.db4o.com" target="_blank"&gt;db4o&lt;/a&gt;)
and/or the &amp;quot;NoSQL&amp;quot; movement (&lt;a href="http://www.mongodb.org/display/DOCS/Tutorial" target="_blank"&gt;MongoDB&lt;/a&gt;).
Dependency injection and composable architectures (&lt;a href="http://www.springframework.org" target="_blank"&gt;Spring&lt;/a&gt;, &lt;a href="http://mef.codeplex.com" target="_blank"&gt;MEF&lt;/a&gt;).
A dynamic language (&lt;a href="http://www.rubyforge.org" target="_blank"&gt;Ruby&lt;/a&gt;, &lt;a href="http://www.python.org" target="_blank"&gt;Python&lt;/a&gt;, &lt;a href="http://www.ecmascript.org" target="_blank"&gt;ECMAScript&lt;/a&gt;).
A functional language (&lt;a href="http://msdn.microsoft.com/en-us/fsharp/default.aspx" target="_blank"&gt;F#&lt;/a&gt;, &lt;a href="http://www.scala-lang.org" target="_blank"&gt;Scala&lt;/a&gt;, &lt;a href="http://www.haskell.org" target="_blank"&gt;Haskell&lt;/a&gt;).
A Lisp (Common Lisp, &lt;a href="http://clojure.org" target="_blank"&gt;Clojure&lt;/a&gt;, Scheme,
Nu). A mobile platform (iPhone, Android). &amp;quot;Space&amp;quot;-based architecture (&lt;a href="http://www.gigaspaces.com" target="_blank"&gt;Gigaspaces&lt;/a&gt;,
Terracotta). Rich UI platforms (Flash/Flex, Silverlight). Browser enhancements (AJAX,
jQuery, HTML 5) and how they're different from the rich UI platforms. And this is
without adding any of the &amp;quot;obvious&amp;quot; stuff, like Cloud, to the list.
&lt;/p&gt;
&lt;p&gt;
(I'm not convinced Cloud is something worth learning this year, anyway.)
&lt;/p&gt;
&lt;p&gt;
You get through that list, you're operating outside of your comfort zone, and chances
are, your boss' comfort zone, which puts you into the enviable position of being somebody
who can advise him around those technologies. &lt;em&gt;DO NOT TAKE THIS TO MEAN YOU MUST
KNOW THEM DEEPLY.&lt;/em&gt; Just having a passing familiarity with them can be enough. &lt;em&gt;DO
NOT TAKE THIS TO MEAN YOU SHOULD PROPOSE USING THEM ON THE NEXT PROJECT.&lt;/em&gt; In fact,
sometimes the most compelling evidence that you really know where and when they should
be used is when you suggest stealing ideas from the thing, rather than trying to force-fit
the thing onto the project as a whole.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;6: Practice, practice, practice&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Speaking of the concert pianist, somebody once asked him how to get to Carnegie Hall.
HIs answer: &amp;quot;Practice, my boy, practice.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
The same is true here. You're not going to get to be a better developer without practice.
Volunteer some time—even if it's just an hour a week—on an open-source project, or
start one of your own. Heck, it doesn't even have to be an &amp;quot;open source&amp;quot;
project—just create some requirements of your own, solve a problem that a family member
is having, or rewrite the project you're on as an interesting side-project. Do the
Nike thing and &amp;quot;Just do it&amp;quot;. Write some Scala code. Write some F# code.
Once you're past &amp;quot;hello world&amp;quot;, write the Scala code to use db4o as a persistent
storage. Wire it up behind Tapestry. Or write straight servlets in Scala. And so on.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;5: Turn off the TV&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Speaking of marketing slogans, if you're like most Americans, surveys have shown that
you watch about four hours of TV a day, or 28 hours of TV a week. In that same amount
of time (28 hours over 1 week), you could read the entire set of poems by Maya Angelou,
one F. Scott Fitzgerald novel, all poems by T.S.Eliot, 2 plays by Thornton Wilder,
or all 150 Psalms of the Bible. An average reader, reading just one hour a day, can
finish an &amp;quot;average-sized&amp;quot; book (let's assume about the size of a novel)
in a week, which translates to 52 books a year.
&lt;/p&gt;
&lt;p&gt;
Let's assume a technical book is going to take slightly longer, since it's a bit deeper
in concept and requires you to spend some time experimenting and typing in code; let's
assume that reading and going through the exercises of an average technical book will
require 4 weeks (a month) instead of just one week. That's 12 new tools/languages/frameworks/ideas
you'd be learning per year.
&lt;/p&gt;
&lt;p&gt;
All because you stopped watching David Caruso turn to the camera, whip his sunglasses
off and say something stupid. (I guess it's not his fault; &lt;em&gt;CSI:Miami&lt;/em&gt; is a
crap show. The other two are actually not bad, but &lt;em&gt;Miami&lt;/em&gt; just makes me retch.) 
&lt;/p&gt;
&lt;p&gt;
After all, when's the last time that David Caruso or the rest of that show did anything
that was even remotely realistic from a computer perspective? (I always laugh out
loud every time they run a database search against some national database on a completely
non-indexable criteria—like a partial license plate number—and it comes back in seconds.
What the hell database are THEY using? I want it!) Soon as you hear The Who break
into that riff, flip off the TV (or set it to mute) and pick up the book on the nightstand
and boost your career. (And hopefully sink Caruso's.)
&lt;/p&gt;
&lt;p&gt;
Or, if you just can't give up your weekly dose of Caruso, then put the book in the
bathroom. Think about it—how much time do you spend in there a week?
&lt;/p&gt;
&lt;p&gt;
And this gets even better when you get a Kindle or other e-reader that accepts PDFs,
or the book you're interested in is natively supported in the e-readers' format. Now
you have it with you for lunch, waiting at dinner for your food to arrive, or while
you're sitting guard on your 10-year-old so he doesn't sneak out of his room after
his bedtime to play more XBox.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;4: Have a life&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Speaking of XBox, don't slave your life to work. Pursue other things. Scientists have
repeatedly discovered that exercise helps keep the mind in shape, so take a couple
of hours a week (buh-bye, &lt;em&gt;American Idol&lt;/em&gt;) and go get some exercise. Pick up
a new sport you've never played before, or just go work out at the gym. (This year
I'm doing Hopkido and fencing.) Read some nontechnical books. (I recommend anything
by Malcolm Gladwell as a starting point.) Spend time with your family, if you have
one—mine spends at least six or seven hours a week playing &amp;quot;family games&amp;quot;
like &lt;a href="http://www.realitycheckgames.com/Products/127-the-settlers-of-catan.aspx" target="_blank"&gt;Settlers
of Catan&lt;/a&gt;, &lt;a href="http://www.realitycheckgames.com/Products/113-dominion.aspx" target="_blank"&gt;Dominion&lt;/a&gt;, &lt;a href="http://www.realitycheckgames.com/Products/88-to-court-the-king.aspx" target="_blank"&gt;To
Court The King&lt;/a&gt;, &lt;a href="http://www.realitycheckgames.com/Products/98-munchkin.aspx" target="_blank"&gt;Munchkin&lt;/a&gt;,
and other non-traditional games, usually over lunch or dinner. I also belong to an
informal &amp;quot;Game Night club&amp;quot; in Redmond consisting of several Microsoft employees
and their families, as well as outsiders. And so on. Heck, go to a local bar and watch
the game, and you'll meet some really interesting people. And some boring people,
too, but you don't have to talk to them during the next game if you don't want.
&lt;/p&gt;
&lt;p&gt;
This isn't just about maintaining a healthy work-life balance—it's also about having
interests that other people can latch on to, qualities that will make you more &amp;quot;human&amp;quot;
and more interesting as a person, and make you more attractive and &amp;quot;connectable&amp;quot;
and stand out better in their mind when they hear that somebody they know is looking
for a software developer. This will also help you connect better with your users,
because like it or not, they do &lt;em&gt;not&lt;/em&gt; get your puns involving Klingon. (Besides,
the geek stereotype is SO 90's, and it's time we let the world know that.)
&lt;/p&gt;
&lt;p&gt;
Besides, you never know when having some depth in other areas—philosophy, music, art,
physics, sports, whatever—will help you create an analogy that will explain some thorny
computer science concept to a non-technical person and get past a communication roadblock.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;3: Practice on a cadaver&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Long before they scrub up for their first surgery on a human, medical students practice
on dead bodies. It's grisly, it's not something we really want to think about, but
when you're the one going under the general anesthesia, would you rather see the surgeon
flipping through the &amp;quot;How-To&amp;quot; manual, &amp;quot;just to refresh himself&amp;quot;?
&lt;/p&gt;
&lt;p&gt;
Diagnosing and debugging a software system can be a hugely puzzling trial, largely
because there are so many possible &amp;quot;moving parts&amp;quot; that are creating the
problem. Compound that with certain bugs that only appear when multiple users are
interacting at the same time, and you've got a recipe for disaster when a production
bug suddenly threatens to jeopardize the company's online revenue stream. Do you really
want to be sitting in the production center, flipping through &amp;quot;How-To&amp;quot;'s
and FAQs online while your boss looks on and your CEO is counting every minute by
the thousands of dollars?
&lt;/p&gt;
&lt;p&gt;
Take a tip from the med student: long before the thing goes into production, introduce
a bug, deploy the code into a virtual machine, then hand it over to a buddy and let
him try to track it down. Have him do the same for you. Or if you can't find a buddy
to help you, do it to yourself (but try not to cheat or let your knowledge of where
the bug is color your reactions). How do you know the bug is there? Once you know
it's there, how do you determine what kind of bug it is? Where do you start looking
for it? How would you track it down without attaching a debugger or otherwise disrupting
the system's operations? (Remember, we can't always just attach an IDE and step through
the code on a production server.) How do you patch the running system? And so on.
&lt;/p&gt;
&lt;p&gt;
Remember, you can either learn these things under controlled circumstances, learn
them while you're in the &amp;quot;hot seat&amp;quot;, so to speak, or not learn them at all
and see how long the company keeps you around.
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;2: Administer the system&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Take off your developer hat for a while—a week, a month, a quarter, whatever—and be
one of those thankless folks who have to keep the system running. Wear the pager that
goes off at 3AM when a server goes down. Stay all night doing one of those &amp;quot;server
upgrades&amp;quot; that have to be done in the middle of the night because the system
can't be upgraded while users are using it. Answer the phones or chat requests of
those hapless users who can't figure out why they can't find the record they just
entered into the system, and after a half-hour of thinking it must be a bug, ask them
if they remembered to check the &amp;quot;Save this record&amp;quot; checkbox on the UI (which
had to be there because the developers were told it had to be there) before submitting
the form. Try adding a user. Try removing a user. Try changing the user's password.
Learn what a real joy having seven different properties/XML/configuration files scattered
all over the system really is.
&lt;/p&gt;
&lt;p&gt;
Once you've done that, particularly on a system that you built and tossed over the
fence into production and thought that was the end of it, you'll understand just why
it's so important to keep the system administrators in mind when you're building a
system for production. And why it's critical to be able to have a system that tells
you when it's down, instead of having to go hunting up the answer when a VP tells
you it is (usually because he's just gotten an outage message from a customer or client).
&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;&lt;em&gt;1: Cultivate a peer group&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;
&lt;p&gt;
Yes, you can join an online forum, ask questions, answer questions, and learn that
way, but that's a poor substitute for physical human contact once in a while. Like
it or not, various sociological and psychological studies confirm that a &amp;quot;connection&amp;quot;
is really still best made when eyeballs meet flesh. (The &amp;quot;disassociative&amp;quot;
nature of email is what makes it so easy to be rude or flamboyant or downright violent
in email when we would never say such things in person.) Go to conferences, join a
user group, even start one of your own if you can't find one. Yes, the online avenues
are still open to you—read blogs, join mailing lists or newsgroups—but don't lose
sight of human-to-human contact.
&lt;/p&gt;
&lt;p&gt;
While we're at it, don't create a peer group of people that all look to you for answers—as
flattering as that feels, and as much as we do learn by providing answers, frequently
we rise (or fall) to the level of our peers—have at least one peer group that's overwhelmingly
smarter than you, and as scary as it might be, venture to offer an answer or two to
that group when a question comes up. You don't have to be right—in fact, it's often
vastly more educational to be wrong. Just maintain an attitude that says &amp;quot;I have
no ego wrapped up in being right or wrong&amp;quot;, and take the entire experience as
a learning opportunity.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=4b2137dd-11cc-4ad5-8771-5906f2759273" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,4b2137dd-11cc-4ad5-8771-5906f2759273.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Security</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=b60b096c-5148-4a72-9aa4-b2a317990f4b</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,b60b096c-5148-4a72-9aa4-b2a317990f4b.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,b60b096c-5148-4a72-9aa4-b2a317990f4b.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=b60b096c-5148-4a72-9aa4-b2a317990f4b</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
But too impatient to read a whole book on it? Try the 6-panel <a href="http://refcardz.dzone.com/refcardz/essential-f?oid=ban00021-0" target="_blank">RefCard</a> that <a href="http://leibnizdream.wordpress.com/" target="_blank">Chance
Coble</a> and I put together for <a href="http://refcardz.dzone.com/" target="_blank">DZone</a>.
Free download.
</p>
        <p>
Or, for the more patient type, wait for the books that Chance and I (<a href="http://www.wiley.com/WileyCDA/WileyTitle/productCd-047052801X.html" target="_blank">Professional
F#</a>) are each writing; they're remarkably complementary, at least from what Chance
has told me about his.
</p>
        <p>
Which reminds me.... if you've not already noticed, <a href="http://www.amazon.com/Professional-F-1-0-Ted-Neward/dp/047052801X" target="_blank">Pro
F# is now up in Amazon</a>. Call me a romantic fool, but I get just a little thrill
run down my spine every time a new book of mine shows up on Amazon, and just a slightly
bigger one when it shows up on a shelf (which will happen shortly after VS 2010 hits
the streets). Nothing like that little surge of energy to give you the boost you need
to cross the finish line. :-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=b60b096c-5148-4a72-9aa4-b2a317990f4b" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Interested in F#?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,b60b096c-5148-4a72-9aa4-b2a317990f4b.aspx</guid>
      <link>http://blogs.tedneward.com/2010/01/07/Interested+In+F.aspx</link>
      <pubDate>Thu, 07 Jan 2010 23:28:13 GMT</pubDate>
      <description>&lt;p&gt;
But too impatient to read a whole book on it? Try the 6-panel &lt;a href="http://refcardz.dzone.com/refcardz/essential-f?oid=ban00021-0" target="_blank"&gt;RefCard&lt;/a&gt; that &lt;a href="http://leibnizdream.wordpress.com/" target="_blank"&gt;Chance
Coble&lt;/a&gt; and I put together for &lt;a href="http://refcardz.dzone.com/" target="_blank"&gt;DZone&lt;/a&gt;.
Free download.
&lt;/p&gt;
&lt;p&gt;
Or, for the more patient type, wait for the books that Chance and I (&lt;a href="http://www.wiley.com/WileyCDA/WileyTitle/productCd-047052801X.html" target="_blank"&gt;Professional
F#&lt;/a&gt;) are each writing; they're remarkably complementary, at least from what Chance
has told me about his.
&lt;/p&gt;
&lt;p&gt;
Which reminds me.... if you've not already noticed, &lt;a href="http://www.amazon.com/Professional-F-1-0-Ted-Neward/dp/047052801X" target="_blank"&gt;Pro
F# is now up in Amazon&lt;/a&gt;. Call me a romantic fool, but I get just a little thrill
run down my spine every time a new book of mine shows up on Amazon, and just a slightly
bigger one when it shows up on a shelf (which will happen shortly after VS 2010 hits
the streets). Nothing like that little surge of energy to give you the boost you need
to cross the finish line. :-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=b60b096c-5148-4a72-9aa4-b2a317990f4b" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,b60b096c-5148-4a72-9aa4-b2a317990f4b.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>F#</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=680b8296-ba07-4230-b067-edceaf04e84b</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,680b8296-ba07-4230-b067-edceaf04e84b.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,680b8296-ba07-4230-b067-edceaf04e84b.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=680b8296-ba07-4230-b067-edceaf04e84b</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Here we go again—another year, another set of predictions revisited and offered up
for the next 12 months. And maybe, if I'm feeling really ambitious, I'll take that
shot I thought about last year and try predicting for the decade. Without further
ado, I'll go back and revisit, unedited, my predictions for 2009 ("<strong>THEN</strong>"),
and pontificate on those subjects for 2010 before adding any new material/topics.
Just for convenience, <a href="http://blogs.tedneward.com/2009/01/01/2009+Predictions+2008+Predictions+Revisited.aspx" target="_blank">here's
a link back to last years' predictions</a>.
</p>
        <p>
Last year's predictions went something like this (complete with basketball-scoring):
</p>
        <ul>
          <li>
            <strong>THEN: </strong>"Cloud" will become the next "ESB" or "SOA",
in that it will be something that everybody will talk about, but few will understand
and even fewer will do anything with. (Considering the widespread disparity in the
definition of the term, this seems like a no-brainer.) <strong>NOW:</strong> Oh, yeah.
Straight up. I get two points for this one. Does <em>anyone</em> have a working definition
of "cloud" that applies to all of the major vendors' implementations? <em>Ted,
2; Wrongness, 0</em>.</li>
          <li>
            <strong>THEN: </strong>Interest in Scala will continue to rise, as will the number
of detractors who point out that Scala is too hard to learn. <strong>NOW:</strong> Two
points for this one, too. Not a hard one, mind you, but one of those "pass-and-shoot"
jumpers from twelve feet out. James Strachan even tweeted about this earlier today,
pointing out this comparison. As more Java developers who think of themselves as smart
people try to pick up Scala and fail, the numbers of sour grapes responses like "Scala's
too complex, and who needs that functional stuff anyway?" will continue to rise
in 2010. <em>Ted, 4; Wrongness, 0</em>.</li>
          <li>
            <strong>THEN</strong>: Interest in F# will continue to rise, as will the number of
detractors who point out that F# is too hard to learn. (Hey, the two really are cousins,
and the fortunes of one will serve as a pretty good indication of the fortunes of
the other, and both really seem to be on the same arc right now.) <strong>NOW:</strong> Interestingly
enough, I haven't heard as many F# detractors as Scala detractors, possibly because
I think F# hasn't really reached the masses of .NET developers the way that Scala
has managed to find its way in front of Java developers. I think that'll change mighty
quickly in 2010, though, once VS 2010 hits the streets. <em>Ted, 4; Wrongness 2</em>.</li>
          <li>
            <strong>THEN</strong>
            <em>:</em> Interest in all kinds of functional languages will
continue to rise, and more than one person will take a hint from Bob "crazybob"
Lee and liken functional programming to AOP, for good and for ill. People who took
classes on Haskell in college will find themselves reaching for their old college
textbooks again. <strong>NOW:</strong> Yep, I'm claiming two points on this one, if
only because a bunch of Haskell books shipped this year, and they'll be the last to
do so for about five years after this. (By the way, does anybody still remember aspects?)
But I'm going the opposite way with this one now; yes, there's Haskell, and yes, there's
Erlang, and yes, there's a lot of other functional languages out there, but who cares?
They're hard to learn, they don't always translate well to other languages, and developers
want languages that work on the platform they use on a daily basis, and that means
F# and Scala or Clojure, or its simply not an option. <em>Ted 6; Wrongness 2</em>.</li>
          <li>
            <strong>THEN</strong>
            <em>:</em> The iPhone is going to be hailed as "the enterprise
development platform of the future", and companies will be rolling out apps to
it. Look for Quicken iPhone edition, PowerPoint and/or Keynote iPhone edition, along
with connectors to hook the iPhone up to a presentation device, and (I'll bet) a World
of Warcraft iPhone client (legit or otherwise). iPhone is the new hotness in the mobile
space, and people will flock to it madly. <strong>NOW:</strong> Two more points, but
let's be honest—this was a fast-break layup, no work required on my part. <em>Ted
8; Wrongness 2.</em></li>
          <li>
            <strong>THEN</strong>: Another Oslo CTP will come out, and it will bear only a superficial
resemblance to the one that came out in October at PDC. Betting on Oslo right now
is a fools' bet, not because of any inherent weakness in the technology, but just
because it's way too early in the cycle to be thinking about for anything vaguely
resembling production code. <strong>NOW:</strong> If you've worked at all with Oslo,
you might argue with me, but I'm still taking my two points. The two CTPs were pretty
different in a number of ways. <em>Ted 10; Wrongness 2.</em></li>
          <li>
            <strong>THEN</strong>: The IronPython and IronRuby teams will find some serious versioning
issues as they try to manage the DLR versioning story between themselves and the CLR
as a whole. An initial hack will result, which will be codified into a standard practice
when .NET 4.0 ships. Then the next release of IPy or IRb will have to try and slip
around its restrictions in 2010/2011. By 2012, IPy and IRb will have to be shipping
as part of Visual Studio just to put the releases back into lockstep with one another
(and the rest of the .NET universe). <strong>NOW:</strong> Pressure is still building.
Let's see what happens by the time VS 2010 ships, and then see what the IPy/IRb teams
start to do to adjust to the versioning issues that arise. <em>Ted 8; Wrongness 2.</em></li>
          <li>
            <strong>THEN</strong>: The death of JSR-277 will spark an uprising among the two leading
groups hoping to foist it off on the Java community--OSGi and Maven--while the rest
of the Java world will breathe a huge sigh of relief and look to see what "modularity"
means in Java 7. Some of the alpha geeks in Java will start using--if not building--JDK
7 builds just to get a heads-up on its impact, and be quietly surprised and, I dare
say, perhaps even pleased. <strong>NOW:</strong> Ah, Ted, you really should never
underestimate the community's willingness to take a bad idea, strip all the goodness
out of it, and then cycle it back into the mix as something completely different yet
somehow just as dangerous and crazy. I give you Project Jigsaw. <em>Ted 10; Wrongness
2;</em></li>
          <li>
            <strong>THEN</strong>: The invokedynamic JSR will leapfrog in importance to the top
of the list. <strong>NOW:</strong> The invokedynamic JSR begat interest in other languages
on the JVM. The interest in other languages on the JVM begat the need to start thinking
about how to support them in the Java libraries. The need to start thinking about
supporting those languages begat a "Holy sh*t moment" somewhere inside Sun
and led them to (re-)propose closures for JDK 7. And in local sports news, Ted notched
up two more points on the scoreboard. <em>Ted 12; Wrongness 2.</em></li>
          <li>
            <strong>THEN</strong>: Another Windows 7 CTP will come out, and it will spawn huge
media interest that will eventually be remembered as Microsoft promises, that will
eventually be remembered as Microsoft guarantees, that will eventually be remembered
as Microsoft FUD and "promising much, delivering little". Microsoft ain't
always at fault for the inflated expectations people have--sometimes, yes, perhaps
even a lot of times, but not always. <strong>NOW:</strong> And then, just when the
game started to turn into a runaway, airballs started to fly. The Windows7 release
shipped, and contrary to what I expected, the general response to it was pretty warm.
Yes, there were a few issues that emerged, but overall the media liked it, the masses
liked it, and Microsoft seemed to have dodged a bullet. <em>Ted 12; Wrongness 5.</em></li>
          <li>
            <strong>THEN</strong>: Apple will begin to legally threaten the clone market again,
except this time somebody's going to get the DOJ involved. (Yes, this is the iPhone/iTunes
prediction from last year, carrying over. I still expect this to happen.) <strong>NOW:</strong> What
clones? The only people trying to clone Macs are those who are building Hackintosh
machines, and Apple can't sue them so long as they're using licensed copies of Mac
OS X (as far as I know). Which has never stopped them from trying, mind you, and I
still think Steve has some part of his brain whispering to him at night, calculating
all the hardware sales lost to Hackintosh netbooks out there. But in any event, that's
another shot missed. <em>Ted 12; Wrongness 7.</em></li>
          <li>
            <strong>THEN</strong>: Alpha-geek developers will start creating their own languages
(even if they're obscure or bizarre ones like Shakespeare or Ook#) just to have that
listed on their resume as the DSL/custom language buzz continues to build. <strong>NOW:</strong> I
give you Ioke. If I'd extended this to include outdated CPU interpreters, I'd have
made that three-pointer from half-court instead of just the top of the key. <em>Ted
14; Wrongness 7.</em></li>
          <li>
            <strong>THEN</strong>: Roy Fielding will officially disown most of the "REST"ful
authors and software packages available. Nobody will care--or worse, somebody looking
to make a name for themselves will proclaim that Roy "doesn't really understand
REST". And they'll be right--Roy doesn't understand what <em>they</em> consider
to be REST, and the fact that he created the term will be of no importance anymore.
Being "REST"ful will equate to "I did it myself!", complete with
expectations of a gold star and a lollipop. <strong>NOW:</strong> Does anybody in
the REST community care what Roy Fielding wrote way back when? I keep seeing "REST"ful
systems that seem to have designers who've never heard of Roy, or his thesis. Roy
hasn't officially disowned them, but damn if he doesn't seem close to it. Still....
No points. <em>Ted 14; Wrongness 9.</em></li>
          <li>
            <strong>THEN</strong>: The Parrot guys will make at least one more minor point release.
Nobody will notice or care, except for a few doggedly stubborn Perl hackers. They
will find themselves having nightmares of previous lives carrying around OS/2 books
and Amiga paraphernalia. Perl 6 will celebrate it's seventh... or is it eighth?...
anniversary of being announced, and nobody will notice. <strong>NOW:</strong> Does
anybody still follow Perl 6 development? Has the spec even been written yet? Google
on "Perl 6 release", and you get varying reports: "It'll ship 'when
it's ready'", "There are no such dates because this isn't a commericially-backed
effort", and "Spring 2010". Swish—nothin' but net. <em>Ted 16; Wrongness
9.</em></li>
          <li>
            <strong>THEN</strong>: The debate around "Scrum Certification" will rise
to a fever pitch as short-sighted money-tight companies start looking for reasons
to cut costs and either buy into agile at a superficial level and watch it fail, or
start looking to cut the agilists from their company in order to replace them with
cheaper labor. <strong>NOW:</strong> Agile has become another adjective meaning "best
practices", and as such, has essentially lost its meaning. Just ask Scott Bellware. <em>Ted
18; Wrongness 9.</em></li>
          <li>
            <strong>THEN</strong>: Adobe will continue to make Flex and AIR look more like C#
and the CLR even as Microsoft tries to make Silverlight look more like Flash and AIR.
Web designers will now get to experience the same fun that back-end web developers
have enjoyed for near-on a decade, as shops begin to artificially partition themselves
up as either "Flash" shops or "Silverlight" shops. <strong>NOW:</strong> Not
sure how to score this one—I haven't seen the explicit partitioning happen yet, but
the two environments definitely still seem to be looking to start tromping on each
others' turf, particularly when we look at the rapid releases coming from the Silverlight
team. <em>Ted 16; Wrongness 11.</em></li>
          <li>
            <strong>THEN</strong>: Gartner will still come knocking, looking to hire me for outrageous
sums of money to do nothing but blog and wax prophetic. <strong>NOW:</strong> Still
no job offers. Damn. Ah, well. <em>Ted 16; Wrongness 13.</em></li>
        </ul>
        <p>
A close game. Could've gone either way. *shrug* Ah, well. It was silly to try and
score it in basketball metaphor, anyway—that's the last time I watch ESPN before writing
this.
</p>
        <p>
For 2010, I predict....
</p>
        <ul>
          <li>
            <em>... I will offer 3- and 4-day training classes on F# and Scala, among other things.</em> OK,
that's not fair—yes, I have the materials, I just need to work out locations and times.
Contact me if you're interested in a private class, by the way.</li>
          <li>
            <em>... I will publish two books, one on F# and one on Scala.</em> OK, OK, another
plug. Or, rather, more of a resolution. One will be the "Professional F#"
I'm doing for Wiley/Wrox, the other isn't yet finalized. But it'll either be published
through a publisher, or self-published, by JavaOne 2010.</li>
          <li>
            <em>... DSLs will either "succeed" this year, or begin the short slide into
the dustbin of obscure programming ideas.</em> Domain-specific language advocates
have to put up some kind of strawman for developers to learn from and poke at, or
the whole concept will just fade away. Martin's book will help, if it ships this year,
but even that might not be enough to generate interest if it doesn't have some kind
of large-scale applicability in it. Patterns and refactoring and enterprise containers
all had a huge advantage in that developers could see pretty easily what the problem
was they solved; DSLs haven't made that clear yet.</li>
          <li>
            <em>... functional languages will start to see a backlash.</em> I hate to say it,
but "getting" the functional mindset is hard, and there's precious few resources
that are making it easy for mainstream (read: O-O) developers make that adjustment,
far fewer than there was during the procedural-to-object shift. If the functional
community doesn't want to become mainstream, then mainstream developers will find
ways to take functional's most compelling gateway use-case (parallel/concurrent programming)
and find a way to "git 'er done" in the traditional O-O approach, probably
through software transactional memory, and functional languages like Haskell and Erlang
will be relegated to the "What Might Have Been" of computer science history.
Not sure what I mean? Try this: walk into a functional language forum, and ask what
a monad is. Nobody yet has been able to produce an answer that doesn't involve math
theory, or that does involve a practical domain-object-based example. In fact, nobody
has really said why (or if) monads are even still useful. Or catamorphisms. Or any
of the other dime-store words that the functional community likes to toss around.</li>
          <li>
            <em>... Visual Studio 2010 will ship on time, and be one of the buggiest and/or slowest
releases in its history.</em> I hate to make this prediction, because I really don't
want to be right, but there's just so much happening in the Visual Studio refactoring
effort that it makes me incredibly nervous. Widespread adoption of VS2010 will wait
until SP1 at the earliest. In fact....</li>
          <li>
            <em>... Visual Studio 2010 SP 1 will ship within three months of the final product.</em> Microsoft
knows that people wait until SP 1 to think about upgrading, so they'll just plan for
an eager SP 1 release, and hope that managers will be too hung over from the New Year
(still) to notice that the necessary shakeout time hasn't happened.</li>
          <li>
            <em>... Apple will ship a tablet with multi-touch on it, and it will flop horribly.</em> Not
sure why I think this, but I just don't think the multi-touch paradigm that Apple
has cooked up for the iPhone will carry over to a tablet/laptop device. That won't
stop them from shipping it, and it won't stop Apple fan-boiz from buying it, but that's
about where the interest will end.</li>
          <li>
            <em>... JDK 7 closures will be debated for a few weeks, then become a fait accompli
as the Java community shrugs its collective shoulders.</em> Frankly, I think the Java
community has exhausted its interest in debating new language features for Java. Recent
college grads and open-source groups with an axe to grind will continue to try and
make an issue out of this, but I think the overall Java community just... doesn't...
care. They just want to see JDK 7 ship someday.</li>
          <li>
            <em>... Scala either "pops" in 2010, or begins to fall apart.</em> By "pops",
I mean reaches a critical mass of developers interested in using it, enough to convince
somebody to create a company around it, a la G2One.</li>
          <li>
            <em>... Oracle is going to make a serious "cloud" play, probably by offering
an Oracle-hosted version of Azure or AppEngine.</em> Oracle loves the enterprise space
too much, and derives too much money from it, to not at least appear to have some
kind of offering here. Now that they own Java, they'll marry it up against OpenSolaris,
the Oracle database, and throw the whole thing into a series of server centers all
over the continent, and call it "Oracle 12c" (c for Cloud, of course) or
something.</li>
          <li>
            <em>... Spring development will slow to a crawl and start to take a left turn toward
cloud ideas.</em> VMWare bought SpringSource for a reason, and I believe it's entirely
centered around VMWare's movement into the cloud space—they want to be more than "just"
a virtualization tool. Spring + Groovy makes a compelling development stack, particularly
if VMWare does some interesting hooks-n-hacks to make Spring a virtualization environment
in its own right somehow. But from a practical perspective, any community-driven development
against Spring is all but basically dead. The source may be downloadable later, like
the VMWare Player code is, but making contributions back? Fuhgeddabowdit.</li>
          <li>
            <em>... the explosion of e-book readers brings the Kindle 2009 edition way down to
size.</em> The era of the e-book reader is here, and honestly, while I'm glad I have
a Kindle, I'm expecting that I'll be dusting it off a shelf in a few years. Kinda
like I do with my iPods from a few years ago.</li>
          <li>
            <em>... "social networking" becomes the "Web 2.0" of 2010.</em> In
other words, using the term will basically identify you as a tech wannabe and clearly
out of touch with the bleeding edge.</li>
          <li>
            <em>... Facebook becomes a developer platform requirement.</em> I don't pretend to
know anything about Facebook—I'm not even on it, which amazes my family to no end—but
clearly Facebook is one of those mechanisms by which people reach each other, and
before long, it'll start showing up as a developer requirement for companies looking
to hire. If you're looking to build out your resume to make yourself attractive to
companies in 2010, mad Facebook skillz might not be a bad investment.</li>
          <li>
            <em>... Nintendo releases an open SDK for building games for its next-gen DS-based
device.</em> With the spectacular success of games on the iPhone, Nintendo clearly
must see that they're missing a huge opportunity every day developers can't write
games for the Nintendo DS that are easily downloadable to the device for playing.
Nintendo is not stupid—if they don't open up the SDK and promote "casual"
games like those on the iPhone and those that can now be downloaded to the Zune or
the XBox, they risk being marginalized out of existence.</li>
        </ul>
        <p>
And for the next decade, I predict....
</p>
        <ul>
          <li>
            <em>... colleges and unversities will begin issuing e-book reader devices to students.</em> It's
a helluvalot cheaper than issuing laptops or netbooks, and besides....</li>
          <li>
            <em>... netbooks and e-book readers will merge before the decade is out.</em> Let's
be honest—if the e-book reader could do email and browse the web, you have almost
the perfect paperback-sized mobile device. As for the credit-card sized mobile device....</li>
          <li>
            <em>... mobile phones will all but disappear as they turn into what PDAs tried to
be.</em> "The iPhone makes calls? Really? You mean Voice-over-IP, right? No,
wait, over cell signal? It can <em>do </em>that? Wow, there's really an app for everything,
isn't there?"</li>
          <li>
            <em>... wireless formats will skyrocket in importance all around the office and home.</em> Combine
the iPhone's Bluetooth (or something similar yet lower-power-consuming) with an equally-capable
(Bluetooth or otherwise) projector, and suddenly many executives can leave their netbook
or laptop at home for a business presentation. Throw in the Whispersync-aware e-book
reader/netbook-thing, and now most executives have absolutely zero reason to carry
anything but their e-book/netbook and their phone/PDA. The day somebody figures out
an easy way to combine Bluetooth with PayPal on the iPhone or Android phone, we will
have more or less made pocket change irrelevant. And believe me, that day will happen
before the end of the decade.</li>
          <li>
            <em>... either Android or Windows Mobile will gain some serious market share against
the iPhone the day they figure out how to support an open and unrestricted AppStore-like
app acquisition model.</em> Let's be honest, the attraction of iTunes and AppStore
is that I can see an "Oh, cool!" app on a buddy's iPhone, and have it on
mine less than 30 seconds later. If Android or WinMo can figure out how to offer that
same kind of experience without the draconian AppStore policies to go with it, they'll
start making up lost ground on iPhone in a hurry.</li>
          <li>
            <em>... Apple becomes the DOJ target of the decade.</em> Microsoft was it in the 2000's,
and Apple's stunning rising success is going to put it squarely in the sights of monopolist
accusations before long. Coupled with the unfortunate health distractions that Steve
Jobs has to deal with, Apple's going to get hammered pretty hard by the end of the
decade, but it will have mastered enough market share and mindshare to weather it
as Microsoft has.</li>
          <li>
            <em>... Google becomes the next Microsoft.</em> It won't be anything the founders
do, but Google will do "something evil", and it will be loudly and screechingly
pointed out by all of Google's corporate opponents, and the star will have fallen.</li>
          <li>
... <em>Microsoft finds its way again.</em> Microsoft, as a company, has lost its
way. This is a company that's not used to losing, and like Bill Belichick's Patriots,
they will find ways to adapt and adjust to the changed circumstances of their position
to find a way to win again. What that'll be, I have no idea, but historically, the
last decade notwithstanding, betting against Microsoft has historically been a bad
idea. My gut tells me they'll figure something new to get that mojo back.</li>
          <li>
            <em>... a politician will make himself or herself famous by standing up to the TSA.</em> The
scene will play out like this: during a Congressional hearing on airline security,
after some nut/terrorist tries to blow up another plane through nitroglycerine-soaked
underwear, the TSA director will suggest all passengers should fly naked in order
to preserve safety, the congressman/woman will stare open-mouthed at this suggestion,
proclaim, "Have you no sense of decency, sir?" and immediately get a standing
ovation and never have to worry about re-election again. Folks, if we want to prevent
any chance of loss of life from a terrorist act on an airplane, we have to prevent
passengers from getting on them. Otherwise, just accept that it might happen, do a
reasonable job of preventing it from happening, and let private insurance start offering
flight insurance against the possibility to reassure the paranoid.</li>
        </ul>
        <p>
See you all next year.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=680b8296-ba07-4230-b067-edceaf04e84b" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>2010 Predictions, 2009 Predictions Revisited</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,680b8296-ba07-4230-b067-edceaf04e84b.aspx</guid>
      <link>http://blogs.tedneward.com/2010/01/05/2010+Predictions+2009+Predictions+Revisited.aspx</link>
      <pubDate>Tue, 05 Jan 2010 09:45:59 GMT</pubDate>
      <description>&lt;p&gt;
Here we go again—another year, another set of predictions revisited and offered up
for the next 12 months. And maybe, if I'm feeling really ambitious, I'll take that
shot I thought about last year and try predicting for the decade. Without further
ado, I'll go back and revisit, unedited, my predictions for 2009 (&amp;quot;&lt;strong&gt;THEN&lt;/strong&gt;&amp;quot;),
and pontificate on those subjects for 2010 before adding any new material/topics.
Just for convenience, &lt;a href="http://blogs.tedneward.com/2009/01/01/2009+Predictions+2008+Predictions+Revisited.aspx" target="_blank"&gt;here's
a link back to last years' predictions&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Last year's predictions went something like this (complete with basketball-scoring):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&amp;quot;Cloud&amp;quot; will become the next &amp;quot;ESB&amp;quot; or &amp;quot;SOA&amp;quot;,
in that it will be something that everybody will talk about, but few will understand
and even fewer will do anything with. (Considering the widespread disparity in the
definition of the term, this seems like a no-brainer.) &lt;strong&gt;NOW:&lt;/strong&gt; Oh, yeah.
Straight up. I get two points for this one. Does &lt;em&gt;anyone&lt;/em&gt; have a working definition
of &amp;quot;cloud&amp;quot; that applies to all of the major vendors' implementations? &lt;em&gt;Ted,
2; Wrongness, 0&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;Interest in Scala will continue to rise, as will the number
of detractors who point out that Scala is too hard to learn. &lt;strong&gt;NOW:&lt;/strong&gt; Two
points for this one, too. Not a hard one, mind you, but one of those &amp;quot;pass-and-shoot&amp;quot;
jumpers from twelve feet out. James Strachan even tweeted about this earlier today,
pointing out this comparison. As more Java developers who think of themselves as smart
people try to pick up Scala and fail, the numbers of sour grapes responses like &amp;quot;Scala's
too complex, and who needs that functional stuff anyway?&amp;quot; will continue to rise
in 2010. &lt;em&gt;Ted, 4; Wrongness, 0&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Interest in F# will continue to rise, as will the number of
detractors who point out that F# is too hard to learn. (Hey, the two really are cousins,
and the fortunes of one will serve as a pretty good indication of the fortunes of
the other, and both really seem to be on the same arc right now.) &lt;strong&gt;NOW:&lt;/strong&gt; Interestingly
enough, I haven't heard as many F# detractors as Scala detractors, possibly because
I think F# hasn't really reached the masses of .NET developers the way that Scala
has managed to find its way in front of Java developers. I think that'll change mighty
quickly in 2010, though, once VS 2010 hits the streets. &lt;em&gt;Ted, 4; Wrongness 2&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;&lt;em&gt;:&lt;/em&gt; Interest in all kinds of functional languages will
continue to rise, and more than one person will take a hint from Bob &amp;quot;crazybob&amp;quot;
Lee and liken functional programming to AOP, for good and for ill. People who took
classes on Haskell in college will find themselves reaching for their old college
textbooks again. &lt;strong&gt;NOW:&lt;/strong&gt; Yep, I'm claiming two points on this one, if
only because a bunch of Haskell books shipped this year, and they'll be the last to
do so for about five years after this. (By the way, does anybody still remember aspects?)
But I'm going the opposite way with this one now; yes, there's Haskell, and yes, there's
Erlang, and yes, there's a lot of other functional languages out there, but who cares?
They're hard to learn, they don't always translate well to other languages, and developers
want languages that work on the platform they use on a daily basis, and that means
F# and Scala or Clojure, or its simply not an option. &lt;em&gt;Ted 6; Wrongness 2&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;&lt;em&gt;:&lt;/em&gt; The iPhone is going to be hailed as &amp;quot;the enterprise
development platform of the future&amp;quot;, and companies will be rolling out apps to
it. Look for Quicken iPhone edition, PowerPoint and/or Keynote iPhone edition, along
with connectors to hook the iPhone up to a presentation device, and (I'll bet) a World
of Warcraft iPhone client (legit or otherwise). iPhone is the new hotness in the mobile
space, and people will flock to it madly. &lt;strong&gt;NOW:&lt;/strong&gt; Two more points, but
let's be honest—this was a fast-break layup, no work required on my part. &lt;em&gt;Ted
8; Wrongness 2.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Another Oslo CTP will come out, and it will bear only a superficial
resemblance to the one that came out in October at PDC. Betting on Oslo right now
is a fools' bet, not because of any inherent weakness in the technology, but just
because it's way too early in the cycle to be thinking about for anything vaguely
resembling production code. &lt;strong&gt;NOW:&lt;/strong&gt; If you've worked at all with Oslo,
you might argue with me, but I'm still taking my two points. The two CTPs were pretty
different in a number of ways. &lt;em&gt;Ted 10; Wrongness 2.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: The IronPython and IronRuby teams will find some serious versioning
issues as they try to manage the DLR versioning story between themselves and the CLR
as a whole. An initial hack will result, which will be codified into a standard practice
when .NET 4.0 ships. Then the next release of IPy or IRb will have to try and slip
around its restrictions in 2010/2011. By 2012, IPy and IRb will have to be shipping
as part of Visual Studio just to put the releases back into lockstep with one another
(and the rest of the .NET universe). &lt;strong&gt;NOW:&lt;/strong&gt; Pressure is still building.
Let's see what happens by the time VS 2010 ships, and then see what the IPy/IRb teams
start to do to adjust to the versioning issues that arise. &lt;em&gt;Ted 8; Wrongness 2.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: The death of JSR-277 will spark an uprising among the two leading
groups hoping to foist it off on the Java community--OSGi and Maven--while the rest
of the Java world will breathe a huge sigh of relief and look to see what &amp;quot;modularity&amp;quot;
means in Java 7. Some of the alpha geeks in Java will start using--if not building--JDK
7 builds just to get a heads-up on its impact, and be quietly surprised and, I dare
say, perhaps even pleased. &lt;strong&gt;NOW:&lt;/strong&gt; Ah, Ted, you really should never
underestimate the community's willingness to take a bad idea, strip all the goodness
out of it, and then cycle it back into the mix as something completely different yet
somehow just as dangerous and crazy. I give you Project Jigsaw. &lt;em&gt;Ted 10; Wrongness
2;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: The invokedynamic JSR will leapfrog in importance to the top
of the list. &lt;strong&gt;NOW:&lt;/strong&gt; The invokedynamic JSR begat interest in other languages
on the JVM. The interest in other languages on the JVM begat the need to start thinking
about how to support them in the Java libraries. The need to start thinking about
supporting those languages begat a &amp;quot;Holy sh*t moment&amp;quot; somewhere inside Sun
and led them to (re-)propose closures for JDK 7. And in local sports news, Ted notched
up two more points on the scoreboard. &lt;em&gt;Ted 12; Wrongness 2.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Another Windows 7 CTP will come out, and it will spawn huge
media interest that will eventually be remembered as Microsoft promises, that will
eventually be remembered as Microsoft guarantees, that will eventually be remembered
as Microsoft FUD and &amp;quot;promising much, delivering little&amp;quot;. Microsoft ain't
always at fault for the inflated expectations people have--sometimes, yes, perhaps
even a lot of times, but not always. &lt;strong&gt;NOW:&lt;/strong&gt; And then, just when the
game started to turn into a runaway, airballs started to fly. The Windows7 release
shipped, and contrary to what I expected, the general response to it was pretty warm.
Yes, there were a few issues that emerged, but overall the media liked it, the masses
liked it, and Microsoft seemed to have dodged a bullet. &lt;em&gt;Ted 12; Wrongness 5.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Apple will begin to legally threaten the clone market again,
except this time somebody's going to get the DOJ involved. (Yes, this is the iPhone/iTunes
prediction from last year, carrying over. I still expect this to happen.) &lt;strong&gt;NOW:&lt;/strong&gt; What
clones? The only people trying to clone Macs are those who are building Hackintosh
machines, and Apple can't sue them so long as they're using licensed copies of Mac
OS X (as far as I know). Which has never stopped them from trying, mind you, and I
still think Steve has some part of his brain whispering to him at night, calculating
all the hardware sales lost to Hackintosh netbooks out there. But in any event, that's
another shot missed. &lt;em&gt;Ted 12; Wrongness 7.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Alpha-geek developers will start creating their own languages
(even if they're obscure or bizarre ones like Shakespeare or Ook#) just to have that
listed on their resume as the DSL/custom language buzz continues to build. &lt;strong&gt;NOW:&lt;/strong&gt; I
give you Ioke. If I'd extended this to include outdated CPU interpreters, I'd have
made that three-pointer from half-court instead of just the top of the key. &lt;em&gt;Ted
14; Wrongness 7.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Roy Fielding will officially disown most of the &amp;quot;REST&amp;quot;ful
authors and software packages available. Nobody will care--or worse, somebody looking
to make a name for themselves will proclaim that Roy &amp;quot;doesn't really understand
REST&amp;quot;. And they'll be right--Roy doesn't understand what &lt;em&gt;they&lt;/em&gt; consider
to be REST, and the fact that he created the term will be of no importance anymore.
Being &amp;quot;REST&amp;quot;ful will equate to &amp;quot;I did it myself!&amp;quot;, complete with
expectations of a gold star and a lollipop. &lt;strong&gt;NOW:&lt;/strong&gt; Does anybody in
the REST community care what Roy Fielding wrote way back when? I keep seeing &amp;quot;REST&amp;quot;ful
systems that seem to have designers who've never heard of Roy, or his thesis. Roy
hasn't officially disowned them, but damn if he doesn't seem close to it. Still....
No points. &lt;em&gt;Ted 14; Wrongness 9.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: The Parrot guys will make at least one more minor point release.
Nobody will notice or care, except for a few doggedly stubborn Perl hackers. They
will find themselves having nightmares of previous lives carrying around OS/2 books
and Amiga paraphernalia. Perl 6 will celebrate it's seventh... or is it eighth?...
anniversary of being announced, and nobody will notice. &lt;strong&gt;NOW:&lt;/strong&gt; Does
anybody still follow Perl 6 development? Has the spec even been written yet? Google
on &amp;quot;Perl 6 release&amp;quot;, and you get varying reports: &amp;quot;It'll ship 'when
it's ready'&amp;quot;, &amp;quot;There are no such dates because this isn't a commericially-backed
effort&amp;quot;, and &amp;quot;Spring 2010&amp;quot;. Swish—nothin' but net. &lt;em&gt;Ted 16; Wrongness
9.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: The debate around &amp;quot;Scrum Certification&amp;quot; will rise
to a fever pitch as short-sighted money-tight companies start looking for reasons
to cut costs and either buy into agile at a superficial level and watch it fail, or
start looking to cut the agilists from their company in order to replace them with
cheaper labor. &lt;strong&gt;NOW:&lt;/strong&gt; Agile has become another adjective meaning &amp;quot;best
practices&amp;quot;, and as such, has essentially lost its meaning. Just ask Scott Bellware. &lt;em&gt;Ted
18; Wrongness 9.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Adobe will continue to make Flex and AIR look more like C#
and the CLR even as Microsoft tries to make Silverlight look more like Flash and AIR.
Web designers will now get to experience the same fun that back-end web developers
have enjoyed for near-on a decade, as shops begin to artificially partition themselves
up as either &amp;quot;Flash&amp;quot; shops or &amp;quot;Silverlight&amp;quot; shops. &lt;strong&gt;NOW:&lt;/strong&gt; Not
sure how to score this one—I haven't seen the explicit partitioning happen yet, but
the two environments definitely still seem to be looking to start tromping on each
others' turf, particularly when we look at the rapid releases coming from the Silverlight
team. &lt;em&gt;Ted 16; Wrongness 11.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN&lt;/strong&gt;: Gartner will still come knocking, looking to hire me for outrageous
sums of money to do nothing but blog and wax prophetic. &lt;strong&gt;NOW:&lt;/strong&gt; Still
no job offers. Damn. Ah, well. &lt;em&gt;Ted 16; Wrongness 13.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
A close game. Could've gone either way. *shrug* Ah, well. It was silly to try and
score it in basketball metaphor, anyway—that's the last time I watch ESPN before writing
this.
&lt;/p&gt;
&lt;p&gt;
For 2010, I predict....
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;... I will offer 3- and 4-day training classes on F# and Scala, among other things.&lt;/em&gt; OK,
that's not fair—yes, I have the materials, I just need to work out locations and times.
Contact me if you're interested in a private class, by the way.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... I will publish two books, one on F# and one on Scala.&lt;/em&gt; OK, OK, another
plug. Or, rather, more of a resolution. One will be the &amp;quot;Professional F#&amp;quot;
I'm doing for Wiley/Wrox, the other isn't yet finalized. But it'll either be published
through a publisher, or self-published, by JavaOne 2010.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... DSLs will either &amp;quot;succeed&amp;quot; this year, or begin the short slide into
the dustbin of obscure programming ideas.&lt;/em&gt; Domain-specific language advocates
have to put up some kind of strawman for developers to learn from and poke at, or
the whole concept will just fade away. Martin's book will help, if it ships this year,
but even that might not be enough to generate interest if it doesn't have some kind
of large-scale applicability in it. Patterns and refactoring and enterprise containers
all had a huge advantage in that developers could see pretty easily what the problem
was they solved; DSLs haven't made that clear yet.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... functional languages will start to see a backlash.&lt;/em&gt; I hate to say it,
but &amp;quot;getting&amp;quot; the functional mindset is hard, and there's precious few resources
that are making it easy for mainstream (read: O-O) developers make that adjustment,
far fewer than there was during the procedural-to-object shift. If the functional
community doesn't want to become mainstream, then mainstream developers will find
ways to take functional's most compelling gateway use-case (parallel/concurrent programming)
and find a way to &amp;quot;git 'er done&amp;quot; in the traditional O-O approach, probably
through software transactional memory, and functional languages like Haskell and Erlang
will be relegated to the &amp;quot;What Might Have Been&amp;quot; of computer science history.
Not sure what I mean? Try this: walk into a functional language forum, and ask what
a monad is. Nobody yet has been able to produce an answer that doesn't involve math
theory, or that does involve a practical domain-object-based example. In fact, nobody
has really said why (or if) monads are even still useful. Or catamorphisms. Or any
of the other dime-store words that the functional community likes to toss around.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Visual Studio 2010 will ship on time, and be one of the buggiest and/or slowest
releases in its history.&lt;/em&gt; I hate to make this prediction, because I really don't
want to be right, but there's just so much happening in the Visual Studio refactoring
effort that it makes me incredibly nervous. Widespread adoption of VS2010 will wait
until SP1 at the earliest. In fact....&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Visual Studio 2010 SP 1 will ship within three months of the final product.&lt;/em&gt; Microsoft
knows that people wait until SP 1 to think about upgrading, so they'll just plan for
an eager SP 1 release, and hope that managers will be too hung over from the New Year
(still) to notice that the necessary shakeout time hasn't happened.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Apple will ship a tablet with multi-touch on it, and it will flop horribly.&lt;/em&gt; Not
sure why I think this, but I just don't think the multi-touch paradigm that Apple
has cooked up for the iPhone will carry over to a tablet/laptop device. That won't
stop them from shipping it, and it won't stop Apple fan-boiz from buying it, but that's
about where the interest will end.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... JDK 7 closures will be debated for a few weeks, then become a fait accompli
as the Java community shrugs its collective shoulders.&lt;/em&gt; Frankly, I think the Java
community has exhausted its interest in debating new language features for Java. Recent
college grads and open-source groups with an axe to grind will continue to try and
make an issue out of this, but I think the overall Java community just... doesn't...
care. They just want to see JDK 7 ship someday.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Scala either &amp;quot;pops&amp;quot; in 2010, or begins to fall apart.&lt;/em&gt; By &amp;quot;pops&amp;quot;,
I mean reaches a critical mass of developers interested in using it, enough to convince
somebody to create a company around it, a la G2One.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Oracle is going to make a serious &amp;quot;cloud&amp;quot; play, probably by offering
an Oracle-hosted version of Azure or AppEngine.&lt;/em&gt; Oracle loves the enterprise space
too much, and derives too much money from it, to not at least appear to have some
kind of offering here. Now that they own Java, they'll marry it up against OpenSolaris,
the Oracle database, and throw the whole thing into a series of server centers all
over the continent, and call it &amp;quot;Oracle 12c&amp;quot; (c for Cloud, of course) or
something.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Spring development will slow to a crawl and start to take a left turn toward
cloud ideas.&lt;/em&gt; VMWare bought SpringSource for a reason, and I believe it's entirely
centered around VMWare's movement into the cloud space—they want to be more than &amp;quot;just&amp;quot;
a virtualization tool. Spring + Groovy makes a compelling development stack, particularly
if VMWare does some interesting hooks-n-hacks to make Spring a virtualization environment
in its own right somehow. But from a practical perspective, any community-driven development
against Spring is all but basically dead. The source may be downloadable later, like
the VMWare Player code is, but making contributions back? Fuhgeddabowdit.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... the explosion of e-book readers brings the Kindle 2009 edition way down to
size.&lt;/em&gt; The era of the e-book reader is here, and honestly, while I'm glad I have
a Kindle, I'm expecting that I'll be dusting it off a shelf in a few years. Kinda
like I do with my iPods from a few years ago.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... &amp;quot;social networking&amp;quot; becomes the &amp;quot;Web 2.0&amp;quot; of 2010.&lt;/em&gt; In
other words, using the term will basically identify you as a tech wannabe and clearly
out of touch with the bleeding edge.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Facebook becomes a developer platform requirement.&lt;/em&gt; I don't pretend to
know anything about Facebook—I'm not even on it, which amazes my family to no end—but
clearly Facebook is one of those mechanisms by which people reach each other, and
before long, it'll start showing up as a developer requirement for companies looking
to hire. If you're looking to build out your resume to make yourself attractive to
companies in 2010, mad Facebook skillz might not be a bad investment.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Nintendo releases an open SDK for building games for its next-gen DS-based
device.&lt;/em&gt; With the spectacular success of games on the iPhone, Nintendo clearly
must see that they're missing a huge opportunity every day developers can't write
games for the Nintendo DS that are easily downloadable to the device for playing.
Nintendo is not stupid—if they don't open up the SDK and promote &amp;quot;casual&amp;quot;
games like those on the iPhone and those that can now be downloaded to the Zune or
the XBox, they risk being marginalized out of existence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And for the next decade, I predict....
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;... colleges and unversities will begin issuing e-book reader devices to students.&lt;/em&gt; It's
a helluvalot cheaper than issuing laptops or netbooks, and besides....&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... netbooks and e-book readers will merge before the decade is out.&lt;/em&gt; Let's
be honest—if the e-book reader could do email and browse the web, you have almost
the perfect paperback-sized mobile device. As for the credit-card sized mobile device....&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... mobile phones will all but disappear as they turn into what PDAs tried to
be.&lt;/em&gt; &amp;quot;The iPhone makes calls? Really? You mean Voice-over-IP, right? No,
wait, over cell signal? It can &lt;em&gt;do &lt;/em&gt;that? Wow, there's really an app for everything,
isn't there?&amp;quot;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... wireless formats will skyrocket in importance all around the office and home.&lt;/em&gt; Combine
the iPhone's Bluetooth (or something similar yet lower-power-consuming) with an equally-capable
(Bluetooth or otherwise) projector, and suddenly many executives can leave their netbook
or laptop at home for a business presentation. Throw in the Whispersync-aware e-book
reader/netbook-thing, and now most executives have absolutely zero reason to carry
anything but their e-book/netbook and their phone/PDA. The day somebody figures out
an easy way to combine Bluetooth with PayPal on the iPhone or Android phone, we will
have more or less made pocket change irrelevant. And believe me, that day will happen
before the end of the decade.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... either Android or Windows Mobile will gain some serious market share against
the iPhone the day they figure out how to support an open and unrestricted AppStore-like
app acquisition model.&lt;/em&gt; Let's be honest, the attraction of iTunes and AppStore
is that I can see an &amp;quot;Oh, cool!&amp;quot; app on a buddy's iPhone, and have it on
mine less than 30 seconds later. If Android or WinMo can figure out how to offer that
same kind of experience without the draconian AppStore policies to go with it, they'll
start making up lost ground on iPhone in a hurry.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Apple becomes the DOJ target of the decade.&lt;/em&gt; Microsoft was it in the 2000's,
and Apple's stunning rising success is going to put it squarely in the sights of monopolist
accusations before long. Coupled with the unfortunate health distractions that Steve
Jobs has to deal with, Apple's going to get hammered pretty hard by the end of the
decade, but it will have mastered enough market share and mindshare to weather it
as Microsoft has.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... Google becomes the next Microsoft.&lt;/em&gt; It won't be anything the founders
do, but Google will do &amp;quot;something evil&amp;quot;, and it will be loudly and screechingly
pointed out by all of Google's corporate opponents, and the star will have fallen.&lt;/li&gt;
&lt;li&gt;
... &lt;em&gt;Microsoft finds its way again.&lt;/em&gt; Microsoft, as a company, has lost its
way. This is a company that's not used to losing, and like Bill Belichick's Patriots,
they will find ways to adapt and adjust to the changed circumstances of their position
to find a way to win again. What that'll be, I have no idea, but historically, the
last decade notwithstanding, betting against Microsoft has historically been a bad
idea. My gut tells me they'll figure something new to get that mojo back.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;... a politician will make himself or herself famous by standing up to the TSA.&lt;/em&gt; The
scene will play out like this: during a Congressional hearing on airline security,
after some nut/terrorist tries to blow up another plane through nitroglycerine-soaked
underwear, the TSA director will suggest all passengers should fly naked in order
to preserve safety, the congressman/woman will stare open-mouthed at this suggestion,
proclaim, &amp;quot;Have you no sense of decency, sir?&amp;quot; and immediately get a standing
ovation and never have to worry about re-election again. Folks, if we want to prevent
any chance of loss of life from a terrorist act on an airplane, we have to prevent
passengers from getting on them. Otherwise, just accept that it might happen, do a
reasonable job of preventing it from happening, and let private insurance start offering
flight insurance against the possibility to reassure the paranoid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
See you all next year.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=680b8296-ba07-4230-b067-edceaf04e84b" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,680b8296-ba07-4230-b067-edceaf04e84b.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Security</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=bc8ecefa-a434-4688-875c-3da855b8b28c</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,bc8ecefa-a434-4688-875c-3da855b8b28c.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,bc8ecefa-a434-4688-875c-3da855b8b28c.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=bc8ecefa-a434-4688-875c-3da855b8b28c</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Why study new and different programming languages? To change your programming mindset.
Not sure what I mean by that? Check this out.
</p>
        <p>
Ever done one of these?
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">interface</span> IService</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span> DateTime
GetDate();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span>
              <span style="color: #0000ff">int</span> CalculateSomethingInteresting(<span style="color: #0000ff">int</span> lhs, <span style="color: #0000ff">int</span> rhs);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> OneServiceImpl
: IService</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span>
              <span style="color: #0000ff">public</span> DateTime
GetDate()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span> { <span style="color: #0000ff">return</span> DateTime.Now;
}</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum11"> 11:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">int</span> CalculateSomethingInteresting(<span style="color: #0000ff">int</span> lhs, <span style="color: #0000ff">int</span> rhs)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum12"> 12:</span> { <span style="color: #0000ff">return</span> lhs
+ rhs; }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum13"> 13:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum14"> 14:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum15"> 15:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> AnotherServiceImpl
: IService</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum16"> 16:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum17"> 17:</span>
              <span style="color: #0000ff">public</span> DateTime
GetDate()</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum18"> 18:</span> { <span style="color: #0000ff">return</span><span style="color: #0000ff">new</span> DateTime();
}</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum19"> 19:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">int</span> CalculateSomethingInteresting(<span style="color: #0000ff">int</span> lhs, <span style="color: #0000ff">int</span> rhs)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum20"> 20:</span> { <span style="color: #0000ff">return</span> lhs
* rhs; }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum21"> 21:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum22"> 22:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum23"> 23:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> ServiceFactory</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum24"> 24:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum25"> 25:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span> IService
GetInstance(<span style="color: #0000ff">string</span> which)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum26"> 26:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum27"> 27:</span>
              <span style="color: #0000ff">if</span> (which
== <span style="color: #006080">"One"</span>) <span style="color: #0000ff">return</span><span style="color: #0000ff">new</span> OneServiceImpl();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum28"> 28:</span>
              <span style="color: #0000ff">else</span>
              <span style="color: #0000ff">if</span> (which
== <span style="color: #006080">"Another"</span>) <span style="color: #0000ff">return</span><span style="color: #0000ff">new</span> AnotherServiceImpl();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum29"> 29:</span>
              <span style="color: #0000ff">else</span>
              <span style="color: #0000ff">throw</span>
              <span style="color: #0000ff">new</span> ArgumentException();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum30"> 30:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum31"> 31:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum32"> 32:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum33"> 33:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> App</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum34"> 34:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum35"> 35:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[]
args)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum36"> 36:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum37"> 37:</span>
              <span style="color: #0000ff">foreach</span> (<span style="color: #0000ff">string</span> s <span style="color: #0000ff">in</span> args)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum38"> 38:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum39"> 39:</span> IService
serv = ServiceFactory.GetInstance(s);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum40"> 40:</span> Console.WriteLine(<span style="color: #006080">"serv
calc = {0}"</span>, serv.CalculateSomethingInteresting(3, 3));</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum41"> 41:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum42"> 42:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum43"> 43:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
So has my client this week. In fact, it's fair to say that they're infatuated with
them—they've got services all over the place, including at their communication layer,
where they use configuration files to decide which of the two service implementations
to use, either a "native" .NET implementation or the "real" Web
services implementation that they're supposed to be using. (They end up going back
to the native implementation because sometimes—which is to say, apparently a lot of
times—the Web services implementation is broken in some fundamental way. Go figure.)
</p>
        <p>
The problem is, very bluntly, that the interfaces they're defining (the IService definition
above) are ever-so-slightly different from the communications-based proxy interfaces
that they use to communicate outside of this process, so some poor schmuck ends up
having to write the service implementation (OneServiceImpl) that simply takes the
parameters passed in, translates them into a call through the communications-based
interface, then takes the response and hands it back. Tedious, mind-numbing coding,
particularly painful when there are dozens of interfaces with (in some cases) hundreds
of methods per interface. Ouch.
</p>
        <p>
There <em>had</em> to be a better way.
</p>
        <p>
Based on some of the work/research/play I've been doing with both dynamic and functional
programming languages, it occurred to me that what they really wanted was some kind
of "forwarding" or "delegating" behavior that certain languages
have baked in as a feature. In those languages, it's possible to nominate a "delegate"
object to which method calls are automatically forwarded if no such method is implemented
on this object; in this particular case, what I'd do to replace all of the above is
simply create an IService object instance that has either a OneServiceImpl or a AnotherServiceImpl
instance (depending on the value in the configuration file) set up as the "delegate"
object. That way the method calls remain statically type-checked, but none of this
service interface/service implementation/service factory nonsense has to be created
just to switch between the two.
</p>
        <p>
(By the way, all of this pain goes away completely in a language that supports deferred
checking of signatures until runtime. In other words, if the client had been programming
in IronPython or IronRuby or even Visual Basic, we could get away with not having
to do any of the above, and just use Reflection to access the appropriate method on
whichever of the two service implementations they want to use at the time. <a href="http://www.fantom.org" target="_blank">Fan</a> would
let us do it if we used "-&gt;" instead of "." to invoke the method; <a href="http://cobra-language.com/" target="_blank">Cobra</a> would
switch between the two automatically; and so on.)
</p>
        <p>
Now, this is C# 2.0 that they're using, and they're pretty entrenched on that point,
so I can't simply suggest that they use a new language, but if we take the basic idea
and adapt it to C#, we can get pretty much the same behavior without having to force
the poor schmuck on the bottom of the totem pole to write all those service implementations
by hand.
</p>
        <p>
We start by transforming the IService interface into an IService "interface"
(meaning it's not really an interface anymore, but it'll sure look like one to anybody
who's not paying attention):
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> IService</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">public</span> Func0&lt;DateTime&gt;
GetDate;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span>
              <span style="color: #0000ff">public</span> Func2&lt;<span style="color: #0000ff">int</span>, <span style="color: #0000ff">int</span>, <span style="color: #0000ff">int</span>&gt;
CalculateSomethingInteresting;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
IService is now a class with fields (not properties, though I suppose if you really
wanted them to be properties you could make them such, not that I see much value to
doing so), where each field corresponds in name to the method of the interface it
wants to replace, and the type is a delegate type parameterized to match the return
type and parameter types of that same method of the original interface. Func0 and
Func2 are delegate types I had to create, since nothing like them existed until C#
3.0; their definitions are pretty simple:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">delegate</span> R
Func0&lt;R&gt;();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">delegate</span> R
Func1&lt;R, P1&gt;(P1 p1);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">delegate</span> R
Func2&lt;R, P1, P2&gt;(P1 p1, P2 p2);</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Now, assuming we have the implementation classes from before, we have two choices;
one is to write a by-hand factory that fills out the fields to point to the appropriate
method on the implementation class, like so:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">if</span> (which
== <span style="color: #006080">"One"</span>)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span> servInstance.GetDate
= <span style="color: #0000ff">delegate</span>() { <span style="color: #0000ff">return</span> DateTime.Now;
};</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span> servInstance.CalculateSomethingInteresting
= <span style="color: #0000ff">delegate</span> (<span style="color: #0000ff">int</span> lhs, <span style="color: #0000ff">int</span> rhs)
{ <span style="color: #0000ff">return</span> lhs + rhs; };</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span>
              <span style="color: #0000ff">else</span>
              <span style="color: #0000ff">if</span> (which
== <span style="color: #006080">"Another"</span>)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span> servInstance.GetDate
= <span style="color: #0000ff">delegate</span>() { <span style="color: #0000ff">return</span><span style="color: #0000ff">new</span> DateTime();
};</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span> servInstance.CalculateSomethingInteresting
= <span style="color: #0000ff">delegate</span> (<span style="color: #0000ff">int</span> lhs, <span style="color: #0000ff">int</span> rhs)
{ <span style="color: #0000ff">return</span> lhs * rhs; };</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum11"> 11:</span>
              <span style="color: #0000ff">else</span>
            </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum12"> 12:</span>
              <span style="color: #0000ff">throw</span>
              <span style="color: #0000ff">new</span> ArgumentException();</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
But, quite frankly, this defeats the point—the point was to <em>avoid</em> writing
all this stuff by hand, not simply repeat it in a different form. So instead, we leverage
Reflection, which depends on the basic assumption that the field name in the IService
"interface" matches the method name on the implementation class we wish
to invoke. Assuming that holds (which it does, in my client's case, anyway), we can
reflect on the IService field, find the matching method name in the implementation,
then construct a delegate instance around that method and assign the delegate instance
to the field. Once complete, we hand back the completed service instance, and the
client literally doesn't know that anything's different:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> ServiceFactory</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span> IService
GetInstance(<span style="color: #0000ff">string</span> which)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span> IService
servInstance = <span style="color: #0000ff">new</span> IService();</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> Type
targetType = Assembly.GetExecutingAssembly().GetType(which + <span style="color: #006080">"ServiceImpl"</span>);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span>
              <span style="color: #0000ff">foreach</span> (FieldInfo
fi <span style="color: #0000ff">in</span> servInstance.GetType().GetFields())</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum11"> 11:</span> MethodInfo
targetMethod = targetType.GetMethod(fi.Name);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum12"> 12:</span>
              <span style="color: #008000">//Console.WriteLine("Wiring
up {0} against {1} with {2}", fi.Name, targetType, targetMethod);</span>
            </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum13"> 13:</span> Delegate
d = Delegate.CreateDelegate(fi.FieldType, <span style="color: #0000ff">null</span>,
targetMethod);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum14"> 14:</span>
              <span style="color: #008000">//Console.WriteLine(d);</span>
            </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum15"> 15:</span> fi.SetValue(servInstance,
d);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum16"> 16:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum17"> 17:</span>  </pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum18"> 18:</span>
              <span style="color: #0000ff">return</span> servInstance;</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum19"> 19:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum20"> 20:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Remember, the client code still looks the same...
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum1"> 1:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> App</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum2"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum3"> 3:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[]
args)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum4"> 4:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum5"> 5:</span>
              <span style="color: #0000ff">foreach</span> (<span style="color: #0000ff">string</span> s <span style="color: #0000ff">in</span> args)</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum6"> 6:</span> {</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum7"> 7:</span> IService
serv = ServiceFactory.GetInstance(s);</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum8"> 8:</span> Console.WriteLine(<span style="color: #006080">"serv
calc = {0}"</span>, serv.CalculateSomethingInteresting(3, 3));</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum9"> 9:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum10"> 10:</span> }</pre>
            <!--CRLF-->
            <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
              <span style="color: #606060" id="lnum11"> 11:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
... because what the client doesn't know is that he's accessing a field, then invoking
the delegate that's being returned from that field dereference.
</p>
        <p>
What this permits, aside from the automated wiring up of the IService "interface",
is a greater degree of flexibility—rather than having to choose which implementation
to use on an interface-by-interface basis, we can now configure to use different implementations
on a method-by-method basis. But considering how many interfaces and implementations
my client was looking at having to write by hand, the real win is in the automated
ServiceFactory wiring.
</p>
        <p>
By the way, the only reason we can get away with this sleight-of-hand is because delegates
are deliberately designed to act like method calls; no explicit .Invoke() call is
required, it's implied with the () after the delegate instance's name. If Java7 closures
and/or method handles end up with support for that kind of syntax, then we can do
the same thing in Java7 (more or less).
</p>
        <p>
Make sense?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bc8ecefa-a434-4688-875c-3da855b8b28c" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>A New Kind of Service</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,bc8ecefa-a434-4688-875c-3da855b8b28c.aspx</guid>
      <link>http://blogs.tedneward.com/2009/12/08/A+New+Kind+Of+Service.aspx</link>
      <pubDate>Tue, 08 Dec 2009 19:25:18 GMT</pubDate>
      <description>&lt;p&gt;
Why study new and different programming languages? To change your programming mindset.
Not sure what I mean by that? Check this out.
&lt;/p&gt;
&lt;p&gt;
Ever done one of these?
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IService&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; DateTime
GetDate();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CalculateSomethingInteresting(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; lhs, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rhs);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; OneServiceImpl
: IService&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DateTime
GetDate()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; DateTime.Now;
}&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt; 11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CalculateSomethingInteresting(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; lhs, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rhs)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt; 12:&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; lhs
+ rhs; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt; 13:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt; 14:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt; 15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AnotherServiceImpl
: IService&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt; 16:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt; 17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DateTime
GetDate()&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt; 18:&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DateTime();
}&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt; 19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CalculateSomethingInteresting(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; lhs, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rhs)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt; 20:&lt;/span&gt; { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; lhs
* rhs; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum21"&gt; 21:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum22"&gt; 22:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum23"&gt; 23:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ServiceFactory&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum24"&gt; 24:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum25"&gt; 25:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IService
GetInstance(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; which)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum26"&gt; 26:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum27"&gt; 27:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (which
== &lt;span style="color: #006080"&gt;&amp;quot;One&amp;quot;&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; OneServiceImpl();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum28"&gt; 28:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (which
== &lt;span style="color: #006080"&gt;&amp;quot;Another&amp;quot;&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; AnotherServiceImpl();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum29"&gt; 29:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentException();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum30"&gt; 30:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum31"&gt; 31:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum32"&gt; 32:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum33"&gt; 33:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; App&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum34"&gt; 34:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum35"&gt; 35:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[]
args)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum36"&gt; 36:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum37"&gt; 37:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; s &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; args)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum38"&gt; 38:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum39"&gt; 39:&lt;/span&gt; IService
serv = ServiceFactory.GetInstance(s);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum40"&gt; 40:&lt;/span&gt; Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;serv
calc = {0}&amp;quot;&lt;/span&gt;, serv.CalculateSomethingInteresting(3, 3));&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum41"&gt; 41:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum42"&gt; 42:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum43"&gt; 43:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
So has my client this week. In fact, it's fair to say that they're infatuated with
them—they've got services all over the place, including at their communication layer,
where they use configuration files to decide which of the two service implementations
to use, either a &amp;quot;native&amp;quot; .NET implementation or the &amp;quot;real&amp;quot; Web
services implementation that they're supposed to be using. (They end up going back
to the native implementation because sometimes—which is to say, apparently a lot of
times—the Web services implementation is broken in some fundamental way. Go figure.)
&lt;/p&gt;
&lt;p&gt;
The problem is, very bluntly, that the interfaces they're defining (the IService definition
above) are ever-so-slightly different from the communications-based proxy interfaces
that they use to communicate outside of this process, so some poor schmuck ends up
having to write the service implementation (OneServiceImpl) that simply takes the
parameters passed in, translates them into a call through the communications-based
interface, then takes the response and hands it back. Tedious, mind-numbing coding,
particularly painful when there are dozens of interfaces with (in some cases) hundreds
of methods per interface. Ouch.
&lt;/p&gt;
&lt;p&gt;
There &lt;em&gt;had&lt;/em&gt; to be a better way.
&lt;/p&gt;
&lt;p&gt;
Based on some of the work/research/play I've been doing with both dynamic and functional
programming languages, it occurred to me that what they really wanted was some kind
of &amp;quot;forwarding&amp;quot; or &amp;quot;delegating&amp;quot; behavior that certain languages
have baked in as a feature. In those languages, it's possible to nominate a &amp;quot;delegate&amp;quot;
object to which method calls are automatically forwarded if no such method is implemented
on this object; in this particular case, what I'd do to replace all of the above is
simply create an IService object instance that has either a OneServiceImpl or a AnotherServiceImpl
instance (depending on the value in the configuration file) set up as the &amp;quot;delegate&amp;quot;
object. That way the method calls remain statically type-checked, but none of this
service interface/service implementation/service factory nonsense has to be created
just to switch between the two.
&lt;/p&gt;
&lt;p&gt;
(By the way, all of this pain goes away completely in a language that supports deferred
checking of signatures until runtime. In other words, if the client had been programming
in IronPython or IronRuby or even Visual Basic, we could get away with not having
to do any of the above, and just use Reflection to access the appropriate method on
whichever of the two service implementations they want to use at the time. &lt;a href="http://www.fantom.org" target="_blank"&gt;Fan&lt;/a&gt; would
let us do it if we used &amp;quot;-&amp;gt;&amp;quot; instead of &amp;quot;.&amp;quot; to invoke the method; &lt;a href="http://cobra-language.com/" target="_blank"&gt;Cobra&lt;/a&gt; would
switch between the two automatically; and so on.)
&lt;/p&gt;
&lt;p&gt;
Now, this is C# 2.0 that they're using, and they're pretty entrenched on that point,
so I can't simply suggest that they use a new language, but if we take the basic idea
and adapt it to C#, we can get pretty much the same behavior without having to force
the poor schmuck on the bottom of the totem pole to write all those service implementations
by hand.
&lt;/p&gt;
&lt;p&gt;
We start by transforming the IService interface into an IService &amp;quot;interface&amp;quot;
(meaning it's not really an interface anymore, but it'll sure look like one to anybody
who's not paying attention):
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; IService&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Func0&amp;lt;DateTime&amp;gt;
GetDate;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Func2&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;
CalculateSomethingInteresting;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
IService is now a class with fields (not properties, though I suppose if you really
wanted them to be properties you could make them such, not that I see much value to
doing so), where each field corresponds in name to the method of the interface it
wants to replace, and the type is a delegate type parameterized to match the return
type and parameter types of that same method of the original interface. Func0 and
Func2 are delegate types I had to create, since nothing like them existed until C#
3.0; their definitions are pretty simple:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; R
Func0&amp;lt;R&amp;gt;();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; R
Func1&amp;lt;R, P1&amp;gt;(P1 p1);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; R
Func2&amp;lt;R, P1, P2&amp;gt;(P1 p1, P2 p2);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Now, assuming we have the implementation classes from before, we have two choices;
one is to write a by-hand factory that fills out the fields to point to the appropriate
method on the implementation class, like so:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (which
== &lt;span style="color: #006080"&gt;&amp;quot;One&amp;quot;&lt;/span&gt;)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; servInstance.GetDate
= &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; DateTime.Now;
};&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; servInstance.CalculateSomethingInteresting
= &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; lhs, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rhs)
{ &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; lhs + rhs; };&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (which
== &lt;span style="color: #006080"&gt;&amp;quot;Another&amp;quot;&lt;/span&gt;)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt; servInstance.GetDate
= &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;() { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DateTime();
};&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; servInstance.CalculateSomethingInteresting
= &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; lhs, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; rhs)
{ &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; lhs * rhs; };&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt; 11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt; 12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentException();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
But, quite frankly, this defeats the point—the point was to &lt;em&gt;avoid&lt;/em&gt; writing
all this stuff by hand, not simply repeat it in a different form. So instead, we leverage
Reflection, which depends on the basic assumption that the field name in the IService
&amp;quot;interface&amp;quot; matches the method name on the implementation class we wish
to invoke. Assuming that holds (which it does, in my client's case, anyway), we can
reflect on the IService field, find the matching method name in the implementation,
then construct a delegate instance around that method and assign the delegate instance
to the field. Once complete, we hand back the completed service instance, and the
client literally doesn't know that anything's different:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ServiceFactory&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IService
GetInstance(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; which)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; IService
servInstance = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; IService();&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; Type
targetType = Assembly.GetExecutingAssembly().GetType(which + &lt;span style="color: #006080"&gt;&amp;quot;ServiceImpl&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (FieldInfo
fi &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; servInstance.GetType().GetFields())&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt; 11:&lt;/span&gt; MethodInfo
targetMethod = targetType.GetMethod(fi.Name);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt; 12:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Console.WriteLine(&amp;quot;Wiring
up {0} against {1} with {2}&amp;quot;, fi.Name, targetType, targetMethod);&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt; 13:&lt;/span&gt; Delegate
d = Delegate.CreateDelegate(fi.FieldType, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,
targetMethod);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum14"&gt; 14:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Console.WriteLine(d);&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum15"&gt; 15:&lt;/span&gt; fi.SetValue(servInstance,
d);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum16"&gt; 16:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum17"&gt; 17:&lt;/span&gt;&amp;#160; &lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum18"&gt; 18:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; servInstance;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum19"&gt; 19:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum20"&gt; 20:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Remember, the client code still looks the same...
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; App&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[]
args)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt; 4:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; s &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; args)&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt; 6:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt; 7:&lt;/span&gt; IService
serv = ServiceFactory.GetInstance(s);&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt; 8:&lt;/span&gt; Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;serv
calc = {0}&amp;quot;&lt;/span&gt;, serv.CalculateSomethingInteresting(3, 3));&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt; 9:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt; 10:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt; 11:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
... because what the client doesn't know is that he's accessing a field, then invoking
the delegate that's being returned from that field dereference.
&lt;/p&gt;
&lt;p&gt;
What this permits, aside from the automated wiring up of the IService &amp;quot;interface&amp;quot;,
is a greater degree of flexibility—rather than having to choose which implementation
to use on an interface-by-interface basis, we can now configure to use different implementations
on a method-by-method basis. But considering how many interfaces and implementations
my client was looking at having to write by hand, the real win is in the automated
ServiceFactory wiring.
&lt;/p&gt;
&lt;p&gt;
By the way, the only reason we can get away with this sleight-of-hand is because delegates
are deliberately designed to act like method calls; no explicit .Invoke() call is
required, it's implied with the () after the delegate instance's name. If Java7 closures
and/or method handles end up with support for that kind of syntax, then we can do
the same thing in Java7 (more or less).
&lt;/p&gt;
&lt;p&gt;
Make sense?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bc8ecefa-a434-4688-875c-3da855b8b28c" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,bc8ecefa-a434-4688-875c-3da855b8b28c.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=d3b4c5aa-2964-492c-9af3-523cb403b444</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,d3b4c5aa-2964-492c-9af3-523cb403b444.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,d3b4c5aa-2964-492c-9af3-523cb403b444.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=d3b4c5aa-2964-492c-9af3-523cb403b444</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Paul asked me to review this, his first book, and my comment to him was that he had
a pretty high bar to match; being of the same "series" as <em>Release It!</em>,
Mike Nygard's take on building software ready for production (and, in my repeatedly
stated opinion, the most important-to-read book of the decade), <em>Debug It!</em> had
some pretty impressive shoes to fill. Paul's comment was pretty predictable: "Thanks
for keeping the pressure to a minimum."
</p>
        <p>
My copy arrived in the mail while I was at the NFJS show in Denver this past weekend,
and with a certain amount of dread and excitement, I opened the envelope and sat down
to read for a few minutes. I managed to get halfway through it before deciding I had
to post a review before I get too caught up in my next trip and forget.
</p>
        <h4>
          <em>Short version</em>
        </h4>
        <p>
          <em>Debug It!</em> is a great resource for anyone looking to learn the science of
good debugging. It is entirely language- and platform-agnostic, preferring to focus
entirely on the <em>process</em> and <em>mindset</em> of debugging, rather than on
edge cases or command-line switches in a tool or language. Overall, the writing is
clear and straightforward without being preachy or judgmental, and is liberally annotated
with real-life case stories from both the authors' and the Pragmatic Programmers'
own history, which keeps the tone lighter and yet still proving the point of the text.
Highly recommended for the junior developers on the team; senior developers will likely
find some good tidbits in here as well. 
</p>
        <h4>
          <em>Long version</em>
        </h4>
        <p>
          <em>Debug It!</em> is an excellently-written and to-the-point description of the process
of not only identifying and fixing defects in software, but also of the attitudes
required to keep software from failing. Rather than simply tossing off old maxims
or warming them over with new terminology ("You should always verify the parameters
to your procedure calls" replaced with "You should always verify the parameters
entering a method and ensure the fields follow the invariants established in the specification"),
Paul ensures that when making a point, his prose is clear, the rationale carefully
explained, and the consequences of not following this advice are clearly spelled out.
His advice is pragmatic, and takes into account that developers can't always follow
the absolute rules we'd like to—he talks about some of his experiences with "bug
priorities" and how users pretty quickly figured out to always set the bug's
priority at the highest level in order to get developer attention, for example, and
some ways to try and address that all-too-human failing of bug-tracking systems.
</p>
        <p>
It needs to be said, right from the beginning, that <em>Debug It!</em> will not teach
you how to use the debugging features of your favorite IDE, however. This is because
Paul (deliberately, it seems) takes a platform- and language-agnostic approach to
the book—there are no examples of how to set breakpoints in gdb, or how to attach
the Visual Studio IDE to a running Windows service, for example. This will likely
weed out those readers who are looking for "Google-able" answers to their
common debugging problems, and that's a shame, because those are probably the very
readers that need to read this book. Having said that, however, I like this agnostic
approach, because these ideas and thought processes, the ones that are entirely independent
of the language or platform, are exactly the kinds of things that senior developers
carry over with them from one platform to the next. Still, the junior developer who
picks this book up is going to still need a reference manual or the user manual for
their IDE or toolchain, and will need to practice some with both books in hand if
they want to maximize the effectiveness of what's in here.
</p>
        <p>
One of the things I like most about this book is that it is liberally adorned with
real-life discussions of various scenarios the author team has experienced; the reason
I say "author team" here is because although the stories (for the most part)
remain unattributed, there are obvious references to "Dave" and "Andy",
which I assume pretty obviously refer to Dave Thomas and Andy Hunt, the Pragmatic
Programmers and the owners of Pragmatic Bookshelf. Some of the stories are humorous,
and some of them probably would be humorous if they didn't strike so close to my own
bitterly-remembered experiences. All of them do a good job of reinforcing the point,
however, thus rendering the prose more effective in communicating the idea without
getting to be too preachy or bombastic.
</p>
        <p>
The book obviously intends to target a junior developer audience, because most senior
developers have already intuitively (or experientially) figured out many of the processes
described in here. But, quite frankly, I think it would be a shame for senior developers
to pass on this one; though the temptation will be to simply toss it aside and say,
"I already do all this stuff", senior developers should resist that urge
and read it through cover to cover. If nothing else, it'll help reinforce certain
ideas, bring some of the intuitive process more to light and allow us to analyze what
we do right and what we do wrong, and perhaps most importantly, give us a common backdrop
against which we can mentor junior developers in the science of debugging.
</p>
        <p>
One of the chapters I like in particular, "Chapter 7: Pragmatic Zero Tolerance",
is particularly good reading for those shops that currently suffer from a deficit
of management support for writing good software. In it, Paul talks specifically about
some of the triage process about bugs ("When to fix bugs"), the mental approach
developers should have to fixing bugs ("The debugging mind-set") and how
to get started on creating good software out of bad ("How to dig yourself out
of a quality hole"). These are techniques that a senior developer can bring to
the team and implement at a grass-roots level, in many cases without management even
being aware of what's going on. (It's a sad state of affairs that we sometimes have
to work behind management's back to write good-quality code, but I know that some
developers out there are in exactly that situation, and simply saying, "Quit
and find a new job", although pithy and good for a laugh on a panel, doesn't
really offer much in the way of help. Paul doesn't take that route here, and that
alone makes this book worth reading.)
</p>
        <p>
Another of the chapters that resonates well with me is the first one in Part III ("Debug
Fu"), Chapter 8, entitled "Special Cases", in which he tackles a number
of "advanced" debugging topics, such as "Patching Existing Releases"
and "Hesenbugs" (Concurrency-related bugs). I won't spoil the punchline
for you, but suffice it to say that I wish I'd had that chapter on hand to give out
to teammates on a few projects I've worked on in the past.
</p>
        <p>
Overall, this book is going to be a huge win, and I think it's a worthy successor
to the <em>Release It!</em> reputation. Development managers and team leads should
get a copy for the junior developers on their team as a Christmas gift, but only after
the senior developers have read through it as well. (Senior devs, don't despair—at
190 pages, you can rip through this in a single night, and I can almost guarantee
that you'll learn a few ideas you can put into practice the next morning to boot.)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=d3b4c5aa-2964-492c-9af3-523cb403b444" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Book Review: Debug It! (Paul Butcher, Pragmatic Bookshelf)</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,d3b4c5aa-2964-492c-9af3-523cb403b444.aspx</guid>
      <link>http://blogs.tedneward.com/2009/11/23/Book+Review+Debug+It+Paul+Butcher+Pragmatic+Bookshelf.aspx</link>
      <pubDate>Mon, 23 Nov 2009 07:24:41 GMT</pubDate>
      <description>&lt;p&gt;
Paul asked me to review this, his first book, and my comment to him was that he had
a pretty high bar to match; being of the same &amp;quot;series&amp;quot; as &lt;em&gt;Release It!&lt;/em&gt;,
Mike Nygard's take on building software ready for production (and, in my repeatedly
stated opinion, the most important-to-read book of the decade), &lt;em&gt;Debug It!&lt;/em&gt; had
some pretty impressive shoes to fill. Paul's comment was pretty predictable: &amp;quot;Thanks
for keeping the pressure to a minimum.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
My copy arrived in the mail while I was at the NFJS show in Denver this past weekend,
and with a certain amount of dread and excitement, I opened the envelope and sat down
to read for a few minutes. I managed to get halfway through it before deciding I had
to post a review before I get too caught up in my next trip and forget.
&lt;/p&gt;
&lt;h4&gt;&lt;em&gt;Short version&lt;/em&gt;
&lt;/h4&gt;
&lt;p&gt;
&lt;em&gt;Debug It!&lt;/em&gt; is a great resource for anyone looking to learn the science of
good debugging. It is entirely language- and platform-agnostic, preferring to focus
entirely on the &lt;em&gt;process&lt;/em&gt; and &lt;em&gt;mindset&lt;/em&gt; of debugging, rather than on
edge cases or command-line switches in a tool or language. Overall, the writing is
clear and straightforward without being preachy or judgmental, and is liberally annotated
with real-life case stories from both the authors' and the Pragmatic Programmers'
own history, which keeps the tone lighter and yet still proving the point of the text.
Highly recommended for the junior developers on the team; senior developers will likely
find some good tidbits in here as well. 
&lt;/p&gt;
&lt;h4&gt;&lt;em&gt;Long version&lt;/em&gt;
&lt;/h4&gt;
&lt;p&gt;
&lt;em&gt;Debug It!&lt;/em&gt; is an excellently-written and to-the-point description of the process
of not only identifying and fixing defects in software, but also of the attitudes
required to keep software from failing. Rather than simply tossing off old maxims
or warming them over with new terminology (&amp;quot;You should always verify the parameters
to your procedure calls&amp;quot; replaced with &amp;quot;You should always verify the parameters
entering a method and ensure the fields follow the invariants established in the specification&amp;quot;),
Paul ensures that when making a point, his prose is clear, the rationale carefully
explained, and the consequences of not following this advice are clearly spelled out.
His advice is pragmatic, and takes into account that developers can't always follow
the absolute rules we'd like to—he talks about some of his experiences with &amp;quot;bug
priorities&amp;quot; and how users pretty quickly figured out to always set the bug's
priority at the highest level in order to get developer attention, for example, and
some ways to try and address that all-too-human failing of bug-tracking systems.
&lt;/p&gt;
&lt;p&gt;
It needs to be said, right from the beginning, that &lt;em&gt;Debug It!&lt;/em&gt; will not teach
you how to use the debugging features of your favorite IDE, however. This is because
Paul (deliberately, it seems) takes a platform- and language-agnostic approach to
the book—there are no examples of how to set breakpoints in gdb, or how to attach
the Visual Studio IDE to a running Windows service, for example. This will likely
weed out those readers who are looking for &amp;quot;Google-able&amp;quot; answers to their
common debugging problems, and that's a shame, because those are probably the very
readers that need to read this book. Having said that, however, I like this agnostic
approach, because these ideas and thought processes, the ones that are entirely independent
of the language or platform, are exactly the kinds of things that senior developers
carry over with them from one platform to the next. Still, the junior developer who
picks this book up is going to still need a reference manual or the user manual for
their IDE or toolchain, and will need to practice some with both books in hand if
they want to maximize the effectiveness of what's in here.
&lt;/p&gt;
&lt;p&gt;
One of the things I like most about this book is that it is liberally adorned with
real-life discussions of various scenarios the author team has experienced; the reason
I say &amp;quot;author team&amp;quot; here is because although the stories (for the most part)
remain unattributed, there are obvious references to &amp;quot;Dave&amp;quot; and &amp;quot;Andy&amp;quot;,
which I assume pretty obviously refer to Dave Thomas and Andy Hunt, the Pragmatic
Programmers and the owners of Pragmatic Bookshelf. Some of the stories are humorous,
and some of them probably would be humorous if they didn't strike so close to my own
bitterly-remembered experiences. All of them do a good job of reinforcing the point,
however, thus rendering the prose more effective in communicating the idea without
getting to be too preachy or bombastic.
&lt;/p&gt;
&lt;p&gt;
The book obviously intends to target a junior developer audience, because most senior
developers have already intuitively (or experientially) figured out many of the processes
described in here. But, quite frankly, I think it would be a shame for senior developers
to pass on this one; though the temptation will be to simply toss it aside and say,
&amp;quot;I already do all this stuff&amp;quot;, senior developers should resist that urge
and read it through cover to cover. If nothing else, it'll help reinforce certain
ideas, bring some of the intuitive process more to light and allow us to analyze what
we do right and what we do wrong, and perhaps most importantly, give us a common backdrop
against which we can mentor junior developers in the science of debugging.
&lt;/p&gt;
&lt;p&gt;
One of the chapters I like in particular, &amp;quot;Chapter 7: Pragmatic Zero Tolerance&amp;quot;,
is particularly good reading for those shops that currently suffer from a deficit
of management support for writing good software. In it, Paul talks specifically about
some of the triage process about bugs (&amp;quot;When to fix bugs&amp;quot;), the mental approach
developers should have to fixing bugs (&amp;quot;The debugging mind-set&amp;quot;) and how
to get started on creating good software out of bad (&amp;quot;How to dig yourself out
of a quality hole&amp;quot;). These are techniques that a senior developer can bring to
the team and implement at a grass-roots level, in many cases without management even
being aware of what's going on. (It's a sad state of affairs that we sometimes have
to work behind management's back to write good-quality code, but I know that some
developers out there are in exactly that situation, and simply saying, &amp;quot;Quit
and find a new job&amp;quot;, although pithy and good for a laugh on a panel, doesn't
really offer much in the way of help. Paul doesn't take that route here, and that
alone makes this book worth reading.)
&lt;/p&gt;
&lt;p&gt;
Another of the chapters that resonates well with me is the first one in Part III (&amp;quot;Debug
Fu&amp;quot;), Chapter 8, entitled &amp;quot;Special Cases&amp;quot;, in which he tackles a number
of &amp;quot;advanced&amp;quot; debugging topics, such as &amp;quot;Patching Existing Releases&amp;quot;
and &amp;quot;Hesenbugs&amp;quot; (Concurrency-related bugs). I won't spoil the punchline
for you, but suffice it to say that I wish I'd had that chapter on hand to give out
to teammates on a few projects I've worked on in the past.
&lt;/p&gt;
&lt;p&gt;
Overall, this book is going to be a huge win, and I think it's a worthy successor
to the &lt;em&gt;Release It!&lt;/em&gt; reputation. Development managers and team leads should
get a copy for the junior developers on their team as a Christmas gift, but only after
the senior developers have read through it as well. (Senior devs, don't despair—at
190 pages, you can rip through this in a single night, and I can almost guarantee
that you'll learn a few ideas you can put into practice the next morning to boot.)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=d3b4c5aa-2964-492c-9af3-523cb403b444" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,d3b4c5aa-2964-492c-9af3-523cb403b444.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=9eb4738e-4c53-4fbb-bf8e-e8712050c5ec</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,9eb4738e-4c53-4fbb-bf8e-e8712050c5ec.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,9eb4738e-4c53-4fbb-bf8e-e8712050c5ec.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=9eb4738e-4c53-4fbb-bf8e-e8712050c5ec</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Those of you who've seen me speak on Java 7 at various conferences have heard me lament
(in a small way) the fact that Sun decided last year (Dec 2008) to forgo the idea
of including closures in the Java language. Imagine my surprise, then, to check my
Twitter feed and discover that, to everyone's surprise, closures <a href="http://puredanger.com/tech/2009/11/18/closures-after-all/" target="_blank">are
back in as a consideration for the Java7 release</a>.
</p>
        <p>
Several thoughts come to mind:
</p>
        <ul>
          <li>
            <strong>
              <em>"WTF?!?!? This is a community effort?"</em>
            </strong> Originally,
when Sun created the Java Community Process, the tradeoff for a committee-based development
process was against the open and fair inclusion of ideas from outside of Sun. But
with the Java7 release still lacking a JSR (as of a few weeks ago, anyway; I haven't
checked today to see if it was opened), and both the Modules facility and language
extensions deferred to "Projects" (not JSRs), it seems Sun is now abandoning
the JCP in favor of a Sun-dominant process that is certainly solicitous of the community
at large, but not constrained or defined by it. And for the life of me, I can't tell
if this is a good thing or a bad thing. It's good in that now we don't have to garner
a critical mass of community momentum to get something included into the platform
or language, but it's bad in that Sun has historically been the bigger drag on innovation
there, not the community. 
</li>
          <li>
            <strong>
              <em>"Can we please stop calling them closures?"</em>
            </strong> This
is a nit, but technically what we're talking about adding here are either lambda expressions
or anonymous methods, depending on whose glossary you're using when you're talking.
A true closure is one that will compute all referenced variables from the enclosing
scope and automatically include them in the generated code, which (so far as I can
tell) none of the Java anonymous method or lambda expression proposals currently include.
But it's a nit, so I'll say it this once and then drop it. 
</li>
          <li>
            <strong>
              <em>"Will Groovy, Scala, Clojure and all other JVM languages please report
to the refactoring room?"</em>
            </strong> People look at me quizzically when I
say I'd like to see Java have closures in the language, because in general my take
on language features in Java is that the Java language is more or less dead, and I
could care less what happens to it; I'd vastly prefer to code in Groovy or Scala or
Clojure or JRuby before writing something in Java. My rationale for wanting closures
in Java, however, is this: by defining a common <em>implementation</em> for closures
in Java, all of the above languages can refactor their implementations of anonymous
methods/lambda expressions/etc into something that uses Java's closure implementation,
and that'll make calling Groovy anonymous methods from Scala much much easier. 
</li>
          <li>
            <strong>
              <em>"Why there, now?"</em>
            </strong> Devoxx is apparently turning
into JavaOne Winter, because Sun's been making a lot of pretty big announcements at
that show, including last year's "no closures, no built-in XML support, ..."
announcement about Java7, and now this year's "well, we lied, we're thinking
about closures again". Fortunately I think the Devoxx folks have much better
skills at keeping their conference relevant to the Java community than JavaOne's organizers
did. And I say that <em>despite</em> the fact (or perhaps because of the fact) that
I didn't speak there this year. ;-) 
</li>
          <li>
            <strong>
              <em>"When is this all supposed to ship again?"</em>
            </strong> Originally,
my understanding was that JDK7 was slated to ship in the early part of 2010, but now
rumor has it slipping to this time next year (2010). That is a huge postponement,
and gives Microsoft a bit of an edge, since Visual Studio 2010 and .NET 4.0 are (again,
according to rumor) supposed to ship somewhere around the end of 1Q2010. If Sun/Oracle
keeps this up, we could very well be seeing a 2-.NET-releases-to-1-Java-release pattern,
and that's disturbing in its own right. (Anybody else remember the days when Sun withdrew
Java from ECMA, ISO and ANSI standardization consideration because they wanted to
"innovate on the platform faster"?) 
</li>
          <li>
            <strong>
              <em>"We really have no clue what we're talking about."</em>
            </strong> Aside
from rumors and hearsay (including the one that says that Mark Reinhold, who made
the announcement, made up the syntax on the flight from the US to Belgium), we really
don't have much by way of Sun-blessed <em>official</em> discussions of what this will
look like or act like, at least none so far as I've been able to find, so any sort
of supposition on whether it will be good or suck like an inverted hurricane is a
tad premature. Trust me, I want to see where this goes, too, so I'll be keeping an
eye out. 
</li>
        </ul>
        <p>
In the meantime, if you want to keep on top of the Java space, maybe it's time to <a href="http://www.devoxx.com" target="_blank">consider
a trip to Antwerp</a> this time next year, since, if the new ship date rumors are
to be believed,  it looks like Sun (once again) is planning to use Devoxx as
the platform from which to make a large announcement, this time the release Java7
itself.
</p>
        <hr />
        <p>
          <strong>Update:</strong>
          <a href="http://olabini.com" target="_blank">Ola Bini</a> noted
that...
</p>
        <blockquote>
          <p>
Two things:
</p>
          <ul>
            <li>
They are <u>definitely</u> closures. Calling them anonymous functions are incorrect,
since they aren't really functions. Lambda expression is an OK name, but it has connotations
that aren't really correct for a language like Java. A closure is defined as an anonymous
piece of code that closes over at least one free variable, which in the case of this
proposal will definitely happen. In fact, all of these will be closures, since they
will be closing over the this at least. 
</li>
            <li>
This is mostly on the level of compiler, syntax and type checking, and will NOT have
any real implications for runtime. This means there will be no real sharing of implementation
- at most JRuby, Groovy and Scala blocks will implement another interface (but all
of them already implement Runnable and Callable so it's a limited win). 
</li>
          </ul>
        </blockquote>
        <p>
which prompted me to respond thusly:
</p>
        <p>
First off, I actually never used the term "anonymous function"; instead,
I said "anonymous method", which, as I understand it, is how the underlying
implementation of these proposals will work: the syntax "#() return 42"
will create an anonymous inner class instance of an interface defined by the library
(in its "SimpleClosure" example, the BGGA compiler uses the interface "javax.lang.function.I",
which has one method on it, "invoke()"), which, thus, makes this an anonymous
method. We can't call them "anonymous functions" because Java has no function
type, and probably never will. (And yes, it may seem like we're splitting hairs somewhat
to differentiate between functions and methods,but once you've explored ML, Haskell,
Scala, or F#, you really begin to see a huge difference in those terms, so it's important
to be precise with our terminology, or else the conversation becomes almost entirely
meaningless.)
</p>
        <p>
Neal Gafter uses the definition "A closure is a function that captures the bindings
of free variables in its lexical context." (<a href="http://gafter.blogspot.com/2007/01/definition-of-closures.html)">http://gafter.blogspot.com/2007/01/definition-of-closures.html)</a> Given
that said same post also claims that Java has no function type (and therefore, by
his definition, can't really have a closure), I suppose we could split the hairs even
further and suggest that Java will never have closures until it has true function
types. Personally, I'm happy to say that we can swap in "methods" for "functions"
in this particular discussion, but my understanding is that capturing free variables
also implies capturing variables referenced in the enclosing lexical context, which
the current "closures" proposal (as reported by Alex Miller's closures page)
will not do. (Non-final enclosing parameters will not be accessible, only those passed
in formally as parameters. <a href="http://www.jroller.com/scolebourne/entry/closures_in_jdk_7" target="_blank">Stephen
Colebourne</a> reports as much: "[Mark Reinhold] also indicated that access to
non-final variables was unlikely.")
</p>
        <p>
Given that the current proposal suggests the new #() syntax will essentially generate
an anonymous inner class with a method of the appropriate signature (though I do believe
that method handles are targeted for use at some point, based on what I've been hearing
through the rumor mill), to me it feels like the "closures" implementation
is generating an anonymous method of an anonymous class with a few other restrictions
included--hence my commentary above.
</p>
        <p>
(Having said all that, the <a href="http://docs.google.com/View?docid=ddhp95vd_6hg3qhc" target="_blank">FCM
proposal</a> does provide complete capture of all referenced variables in enclosing
scope, but Mark's keynote hasn't officially endorsed either the BGGA proposal or the
FCM proposal, and if Sun keeps to their habits, they won't. They'll build something
that's an amalgamation of all of them. Right now the current consensus seems to be
to adopt the BGGA implementation behind the FCM syntax, which jives with Neal's 0.6a
specification proposal.)
</p>
        <p>
On top of that, the comment "all of these will be closures, since they will be
closing over the this at least" is not, I don't think, entirely true. The details
of the closures proposal aren't clear, but the "outer this" (which I believe
is the "this" Ola refers to above) hasn't been explicitly mentioned in any
of the closures proposals I've seen, nor have I seen any text suggesting that they
will honor it, so I don't know that this is true. Of course, in absence of a specification
or real working bits, all we can do is just speculate. However, having said that,
playing around a bit with the BGGA prototype compiler (which, admittedly, is still
one minor rev back from Neal's revised proposal), I saw no generated "outer this"
in the generated code for the generated inner class implementation of the closure.
If the comment above is meant to refer to the "this" of the inner class
instance, then that would make all methods of an object-oriented language that provided
an implicit "this" a closure, and somehow I doubt that's what Ola means,
though I could, as always, be wrong.
</p>
        <p>
As for the runtime implementation, as I said earlier I believe the plan is to use
method handles (already on the table for JDK 7), which do have some runtime implications
(generally good ones, from what I can tell so far), but not beyond what was already
on the table for 7.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=9eb4738e-4c53-4fbb-bf8e-e8712050c5ec" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Closures are back again!</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,9eb4738e-4c53-4fbb-bf8e-e8712050c5ec.aspx</guid>
      <link>http://blogs.tedneward.com/2009/11/19/Closures+Are+Back+Again.aspx</link>
      <pubDate>Thu, 19 Nov 2009 08:10:11 GMT</pubDate>
      <description>&lt;p&gt;
Those of you who've seen me speak on Java 7 at various conferences have heard me lament
(in a small way) the fact that Sun decided last year (Dec 2008) to forgo the idea
of including closures in the Java language. Imagine my surprise, then, to check my
Twitter feed and discover that, to everyone's surprise, closures &lt;a href="http://puredanger.com/tech/2009/11/18/closures-after-all/" target="_blank"&gt;are
back in as a consideration for the Java7 release&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Several thoughts come to mind:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;WTF?!?!? This is a community effort?&amp;quot;&lt;/em&gt;&lt;/strong&gt; Originally,
when Sun created the Java Community Process, the tradeoff for a committee-based development
process was against the open and fair inclusion of ideas from outside of Sun. But
with the Java7 release still lacking a JSR (as of a few weeks ago, anyway; I haven't
checked today to see if it was opened), and both the Modules facility and language
extensions deferred to &amp;quot;Projects&amp;quot; (not JSRs), it seems Sun is now abandoning
the JCP in favor of a Sun-dominant process that is certainly solicitous of the community
at large, but not constrained or defined by it. And for the life of me, I can't tell
if this is a good thing or a bad thing. It's good in that now we don't have to garner
a critical mass of community momentum to get something included into the platform
or language, but it's bad in that Sun has historically been the bigger drag on innovation
there, not the community. 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;Can we please stop calling them closures?&amp;quot;&lt;/em&gt;&lt;/strong&gt; This
is a nit, but technically what we're talking about adding here are either lambda expressions
or anonymous methods, depending on whose glossary you're using when you're talking.
A true closure is one that will compute all referenced variables from the enclosing
scope and automatically include them in the generated code, which (so far as I can
tell) none of the Java anonymous method or lambda expression proposals currently include.
But it's a nit, so I'll say it this once and then drop it. 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;Will Groovy, Scala, Clojure and all other JVM languages please report
to the refactoring room?&amp;quot;&lt;/em&gt;&lt;/strong&gt; People look at me quizzically when I
say I'd like to see Java have closures in the language, because in general my take
on language features in Java is that the Java language is more or less dead, and I
could care less what happens to it; I'd vastly prefer to code in Groovy or Scala or
Clojure or JRuby before writing something in Java. My rationale for wanting closures
in Java, however, is this: by defining a common &lt;em&gt;implementation&lt;/em&gt; for closures
in Java, all of the above languages can refactor their implementations of anonymous
methods/lambda expressions/etc into something that uses Java's closure implementation,
and that'll make calling Groovy anonymous methods from Scala much much easier. 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;Why there, now?&amp;quot;&lt;/em&gt;&lt;/strong&gt; Devoxx is apparently turning
into JavaOne Winter, because Sun's been making a lot of pretty big announcements at
that show, including last year's &amp;quot;no closures, no built-in XML support, ...&amp;quot;
announcement about Java7, and now this year's &amp;quot;well, we lied, we're thinking
about closures again&amp;quot;. Fortunately I think the Devoxx folks have much better
skills at keeping their conference relevant to the Java community than JavaOne's organizers
did. And I say that &lt;em&gt;despite&lt;/em&gt; the fact (or perhaps because of the fact) that
I didn't speak there this year. ;-) 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;When is this all supposed to ship again?&amp;quot;&lt;/em&gt;&lt;/strong&gt; Originally,
my understanding was that JDK7 was slated to ship in the early part of 2010, but now
rumor has it slipping to this time next year (2010). That is a huge postponement,
and gives Microsoft a bit of an edge, since Visual Studio 2010 and .NET 4.0 are (again,
according to rumor) supposed to ship somewhere around the end of 1Q2010. If Sun/Oracle
keeps this up, we could very well be seeing a 2-.NET-releases-to-1-Java-release pattern,
and that's disturbing in its own right. (Anybody else remember the days when Sun withdrew
Java from ECMA, ISO and ANSI standardization consideration because they wanted to
&amp;quot;innovate on the platform faster&amp;quot;?) 
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&amp;quot;We really have no clue what we're talking about.&amp;quot;&lt;/em&gt;&lt;/strong&gt; Aside
from rumors and hearsay (including the one that says that Mark Reinhold, who made
the announcement, made up the syntax on the flight from the US to Belgium), we really
don't have much by way of Sun-blessed &lt;em&gt;official&lt;/em&gt; discussions of what this will
look like or act like, at least none so far as I've been able to find, so any sort
of supposition on whether it will be good or suck like an inverted hurricane is a
tad premature. Trust me, I want to see where this goes, too, so I'll be keeping an
eye out. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
In the meantime, if you want to keep on top of the Java space, maybe it's time to &lt;a href="http://www.devoxx.com" target="_blank"&gt;consider
a trip to Antwerp&lt;/a&gt; this time next year, since, if the new ship date rumors are
to be believed,&amp;#160; it looks like Sun (once again) is planning to use Devoxx as
the platform from which to make a large announcement, this time the release Java7
itself.
&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://olabini.com" target="_blank"&gt;Ola Bini&lt;/a&gt; noted
that...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Two things:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
They are &lt;u&gt;definitely&lt;/u&gt; closures. Calling them anonymous functions are incorrect,
since they aren't really functions. Lambda expression is an OK name, but it has connotations
that aren't really correct for a language like Java. A closure is defined as an anonymous
piece of code that closes over at least one free variable, which in the case of this
proposal will definitely happen. In fact, all of these will be closures, since they
will be closing over the this at least. 
&lt;/li&gt;
&lt;li&gt;
This is mostly on the level of compiler, syntax and type checking, and will NOT have
any real implications for runtime. This means there will be no real sharing of implementation
- at most JRuby, Groovy and Scala blocks will implement another interface (but all
of them already implement Runnable and Callable so it's a limited win). 
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
which prompted me to respond thusly:
&lt;/p&gt;
&lt;p&gt;
First off, I actually never used the term &amp;quot;anonymous function&amp;quot;; instead,
I said &amp;quot;anonymous method&amp;quot;, which, as I understand it, is how the underlying
implementation of these proposals will work: the syntax &amp;quot;#() return 42&amp;quot;
will create an anonymous inner class instance of an interface defined by the library
(in its &amp;quot;SimpleClosure&amp;quot; example, the BGGA compiler uses the interface &amp;quot;javax.lang.function.I&amp;quot;,
which has one method on it, &amp;quot;invoke()&amp;quot;), which, thus, makes this an anonymous
method. We can't call them &amp;quot;anonymous functions&amp;quot; because Java has no function
type, and probably never will. (And yes, it may seem like we're splitting hairs somewhat
to differentiate between functions and methods,but once you've explored ML, Haskell,
Scala, or F#, you really begin to see a huge difference in those terms, so it's important
to be precise with our terminology, or else the conversation becomes almost entirely
meaningless.)
&lt;/p&gt;
&lt;p&gt;
Neal Gafter uses the definition &amp;quot;A closure is a function that captures the bindings
of free variables in its lexical context.&amp;quot; (&lt;a href="http://gafter.blogspot.com/2007/01/definition-of-closures.html)"&gt;http://gafter.blogspot.com/2007/01/definition-of-closures.html)&lt;/a&gt; Given
that said same post also claims that Java has no function type (and therefore, by
his definition, can't really have a closure), I suppose we could split the hairs even
further and suggest that Java will never have closures until it has true function
types. Personally, I'm happy to say that we can swap in &amp;quot;methods&amp;quot; for &amp;quot;functions&amp;quot;
in this particular discussion, but my understanding is that capturing free variables
also implies capturing variables referenced in the enclosing lexical context, which
the current &amp;quot;closures&amp;quot; proposal (as reported by Alex Miller's closures page)
will not do. (Non-final enclosing parameters will not be accessible, only those passed
in formally as parameters. &lt;a href="http://www.jroller.com/scolebourne/entry/closures_in_jdk_7" target="_blank"&gt;Stephen
Colebourne&lt;/a&gt; reports as much: &amp;quot;[Mark Reinhold] also indicated that access to
non-final variables was unlikely.&amp;quot;)
&lt;/p&gt;
&lt;p&gt;
Given that the current proposal suggests the new #() syntax will essentially generate
an anonymous inner class with a method of the appropriate signature (though I do believe
that method handles are targeted for use at some point, based on what I've been hearing
through the rumor mill), to me it feels like the &amp;quot;closures&amp;quot; implementation
is generating an anonymous method of an anonymous class with a few other restrictions
included--hence my commentary above.
&lt;/p&gt;
&lt;p&gt;
(Having said all that, the &lt;a href="http://docs.google.com/View?docid=ddhp95vd_6hg3qhc" target="_blank"&gt;FCM
proposal&lt;/a&gt; does provide complete capture of all referenced variables in enclosing
scope, but Mark's keynote hasn't officially endorsed either the BGGA proposal or the
FCM proposal, and if Sun keeps to their habits, they won't. They'll build something
that's an amalgamation of all of them. Right now the current consensus seems to be
to adopt the BGGA implementation behind the FCM syntax, which jives with Neal's 0.6a
specification proposal.)
&lt;/p&gt;
&lt;p&gt;
On top of that, the comment &amp;quot;all of these will be closures, since they will be
closing over the this at least&amp;quot; is not, I don't think, entirely true. The details
of the closures proposal aren't clear, but the &amp;quot;outer this&amp;quot; (which I believe
is the &amp;quot;this&amp;quot; Ola refers to above) hasn't been explicitly mentioned in any
of the closures proposals I've seen, nor have I seen any text suggesting that they
will honor it, so I don't know that this is true. Of course, in absence of a specification
or real working bits, all we can do is just speculate. However, having said that,
playing around a bit with the BGGA prototype compiler (which, admittedly, is still
one minor rev back from Neal's revised proposal), I saw no generated &amp;quot;outer this&amp;quot;
in the generated code for the generated inner class implementation of the closure.
If the comment above is meant to refer to the &amp;quot;this&amp;quot; of the inner class
instance, then that would make all methods of an object-oriented language that provided
an implicit &amp;quot;this&amp;quot; a closure, and somehow I doubt that's what Ola means,
though I could, as always, be wrong.
&lt;/p&gt;
&lt;p&gt;
As for the runtime implementation, as I said earlier I believe the plan is to use
method handles (already on the table for JDK 7), which do have some runtime implications
(generally good ones, from what I can tell so far), but not beyond what was already
on the table for 7.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=9eb4738e-4c53-4fbb-bf8e-e8712050c5ec" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,9eb4738e-4c53-4fbb-bf8e-e8712050c5ec.aspx</comments>
      <category>Conferences</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Scala</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da</wfw:commentRss>
      <slash:comments>12</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Phil Haack wrote <a href="http://haacked.com/archive/2009/10/13/software-externalities.aspx" target="_blank">a
thoughtful, insightful and absolutely correct response</a> to <a href="http://blogs.tedneward.com/2009/10/12/quotAgile+Is+Treating+The+Symptoms+Not+The+Diseasequot.aspx" target="_blank">my
earlier blog post</a>. But he's still missing the point.
</p>
        <p>
The short version: Phil's right when he says, "<strong>Agile is less about managing
the complexity of an application itself and more about managing the complexity of
building an application</strong>." Agile is by far the best approach to take
when building complex software. 
</p>
        <p>
But that's not where I'm going with this. 
</p>
        <p>
As a starting point in the discussion, I'd like to call attention to one of Phil's
sidebars: I find it curious (and indicative of the larger point) his earlier comment
about "<em>I have to wonder, why is that little school district in western Pennsylvania
engaging in custom software development in the first place?</em>" At what point
does standing a small Access database up qualify as "custom software development"?
And I take <em>huge</em> issue with Phil's comment immediately thereafter: ""
That's totally untrue, Phil—you are, in fact, creating custom educational curricula,
for your children at home. Not for popular usage, not for commercial use, but clearly
you're educating your children at home, because you'd be a pretty crappy parent if
you didn't. You also practice an informal form of medicine ("Let me kiss the
boo-boo"), psychology ("Now, come on, share the truck"), culinary arts
("Would you like mac and cheese tonight?"), acting ("Aaar! I'm the
Tickle Monster!") and a vastly larger array of "professional" skills
that any of the "professionals" will do vastly better than you.
</p>
        <p>
In other words, you're not a professional actor/chef/shrink/doctor, you're an amateur
one, and you want tools that let you practice your amateur "professions"
as you wish, without requiring the skills and trappings (and overhead) of a professional
in the same arena.
</p>
        <p>
Consider this, Phil: your child decides it's time to have a puppy. (We all know the
kids are the ones who make these choices, not us, right?) So, being the conscientious
parent that you are, you decide to build a doghouse for the new puppy to use to sleep
outdoors (forgetting, as all parents do, that the puppy will actually end up sleeping
in the bed with your child, but that's another discussion for another day). So immediately
you head on down to Home Depot, grab some lumber, some nails, maybe a hammer and a
screwdriver, some paint, and head on home.
</p>
        <p>
Whoa, there, turbo. Aren't you forgetting a few things? For starters, you need to
get the concrete for the foundation, rebar to support the concrete in the event of
a bad earthquake, drywall, fire extinguishers, sirens for the emergency exit doors...
And of course, you'll need a foreman to coordinate all the work, to make sure the
foundation is poured before the carpenters show up to put up the trusses, which in
turn has to happen before the drywall can go up...
</p>
        <p>
We in this industry have a jealous and irrational attitude towards the amateur software
developer. This was even apparent in the Twitter comments that accompanied the conversation
around my blog post: "@<a href="http://twitter.com/tedneward">tedneward</a> treating
the disease would mean... have the client have all their ideas correct from the start"
(from <a href="http://twitter.com/kelps/statuses/4839762645" target="_blank">@kelps</a>).
In other words, "bad client! No biscuit!"?
</p>
        <p>
Why is it that we, IT professionals, consider anything that involves doing something
other than simply putting content into an application to be "custom software
development"? Why can't end-users create tools of their own to solve their own
problems at a scale appropriate to their local problem?
</p>
        <p>
Phil offers a few examples of why end-users creating their own tools is a Bad Idea:
</p>
        <blockquote>
          <p>
I remember one rescue operation for a company drowning in the complexity of a “simple”
Access application they used to run their business. It was simple until they started
adding new business processes they needed to track. It was simple until they started <em>emailing
copies around </em>and were unsure which was the “master copy”. Not to mention all
the data integrity issues and difficulty in changing the monolithic procedural application
code.
</p>
        </blockquote>
        <blockquote>
          <p>
I also remember helping a teachers union who started off with a simple attendance
tracker style app (to use an example Ted mentions) and just scaled it up to an atrociously
complex Access database with stranded data and manual processes where they printed
excel spreadsheets to paper, then manually entered it into another application.
</p>
        </blockquote>
        <p>
And you know what? 
</p>
        <p>
This is not a bad state of affairs. 
</p>
        <p>
Oh, of course, we, the IT professionals, will immediately pounce on all the things
wrong with their attempts to extend the once-simple application/solution in ways beyond
its capabilities, and we will scoff at their solutions, but you know what? That just
speaks to our insecurities, not the effort expended. You think Wolfgang Puck isn't
going to throw back his head and roar at my lame attempts at culinary experimentation?
You think Frank Lloyd Wright wouldn't cringe in horror at my cobbled-together doghouse?
And I'll bet Maya Angelou will be so shocked at the ugliness of my poetry that she'll
post it somewhere on the "So You Think You're A Poet" website.
</p>
        <p>
Does that mean I need to abandon my efforts to all of these things?
</p>
        <p>
The agilists' community reaction to my post would seem to imply so. "If you aren't
a professional, don't even attempt this?" Really? Is that the message we're preaching
these days?
</p>
        <p>
End users have just as much a desire and right to be amateur software developers as
we do at being amateur cooks, photographers, poets, construction foremen, and musicians.
And what do you do when you want to add an addition to your house instead of just
building a doghouse? Or when you want to cook for several hundred people instead of
just your family?
</p>
        <p>
You hire a professional, and let them do the project professionally.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Haacked, but not content; agile still treats the disease</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da.aspx</guid>
      <link>http://blogs.tedneward.com/2009/10/13/Haacked+But+Not+Content+Agile+Still+Treats+The+Disease.aspx</link>
      <pubDate>Tue, 13 Oct 2009 20:42:22 GMT</pubDate>
      <description>&lt;p&gt;
Phil Haack wrote &lt;a href="http://haacked.com/archive/2009/10/13/software-externalities.aspx" target="_blank"&gt;a
thoughtful, insightful and absolutely correct response&lt;/a&gt; to &lt;a href="http://blogs.tedneward.com/2009/10/12/quotAgile+Is+Treating+The+Symptoms+Not+The+Diseasequot.aspx" target="_blank"&gt;my
earlier blog post&lt;/a&gt;. But he's still missing the point.
&lt;/p&gt;
&lt;p&gt;
The short version: Phil's right when he says, &amp;quot;&lt;strong&gt;Agile is less about managing
the complexity of an application itself and more about managing the complexity of
building an application&lt;/strong&gt;.&amp;quot; Agile is by far the best approach to take
when building complex software. 
&lt;/p&gt;
&lt;p&gt;
But that's not where I'm going with this. 
&lt;/p&gt;
&lt;p&gt;
As a starting point in the discussion, I'd like to call attention to one of Phil's
sidebars: I find it curious (and indicative of the larger point) his earlier comment
about &amp;quot;&lt;em&gt;I have to wonder, why is that little school district in western Pennsylvania
engaging in custom software development in the first place?&lt;/em&gt;&amp;quot; At what point
does standing a small Access database up qualify as &amp;quot;custom software development&amp;quot;?
And I take &lt;em&gt;huge&lt;/em&gt; issue with Phil's comment immediately thereafter: &amp;quot;&amp;quot;
That's totally untrue, Phil—you are, in fact, creating custom educational curricula,
for your children at home. Not for popular usage, not for commercial use, but clearly
you're educating your children at home, because you'd be a pretty crappy parent if
you didn't. You also practice an informal form of medicine (&amp;quot;Let me kiss the
boo-boo&amp;quot;), psychology (&amp;quot;Now, come on, share the truck&amp;quot;), culinary arts
(&amp;quot;Would you like mac and cheese tonight?&amp;quot;), acting (&amp;quot;Aaar! I'm the
Tickle Monster!&amp;quot;) and a vastly larger array of &amp;quot;professional&amp;quot; skills
that any of the &amp;quot;professionals&amp;quot; will do vastly better than you.
&lt;/p&gt;
&lt;p&gt;
In other words, you're not a professional actor/chef/shrink/doctor, you're an amateur
one, and you want tools that let you practice your amateur &amp;quot;professions&amp;quot;
as you wish, without requiring the skills and trappings (and overhead) of a professional
in the same arena.
&lt;/p&gt;
&lt;p&gt;
Consider this, Phil: your child decides it's time to have a puppy. (We all know the
kids are the ones who make these choices, not us, right?) So, being the conscientious
parent that you are, you decide to build a doghouse for the new puppy to use to sleep
outdoors (forgetting, as all parents do, that the puppy will actually end up sleeping
in the bed with your child, but that's another discussion for another day). So immediately
you head on down to Home Depot, grab some lumber, some nails, maybe a hammer and a
screwdriver, some paint, and head on home.
&lt;/p&gt;
&lt;p&gt;
Whoa, there, turbo. Aren't you forgetting a few things? For starters, you need to
get the concrete for the foundation, rebar to support the concrete in the event of
a bad earthquake, drywall, fire extinguishers, sirens for the emergency exit doors...
And of course, you'll need a foreman to coordinate all the work, to make sure the
foundation is poured before the carpenters show up to put up the trusses, which in
turn has to happen before the drywall can go up...
&lt;/p&gt;
&lt;p&gt;
We in this industry have a jealous and irrational attitude towards the amateur software
developer. This was even apparent in the Twitter comments that accompanied the conversation
around my blog post: &amp;quot;@&lt;a href="http://twitter.com/tedneward"&gt;tedneward&lt;/a&gt; treating
the disease would mean... have the client have all their ideas correct from the start&amp;quot;
(from &lt;a href="http://twitter.com/kelps/statuses/4839762645" target="_blank"&gt;@kelps&lt;/a&gt;).
In other words, &amp;quot;bad client! No biscuit!&amp;quot;?
&lt;/p&gt;
&lt;p&gt;
Why is it that we, IT professionals, consider anything that involves doing something
other than simply putting content into an application to be &amp;quot;custom software
development&amp;quot;? Why can't end-users create tools of their own to solve their own
problems at a scale appropriate to their local problem?
&lt;/p&gt;
&lt;p&gt;
Phil offers a few examples of why end-users creating their own tools is a Bad Idea:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I remember one rescue operation for a company drowning in the complexity of a “simple”
Access application they used to run their business. It was simple until they started
adding new business processes they needed to track. It was simple until they started &lt;em&gt;emailing
copies around &lt;/em&gt;and were unsure which was the “master copy”. Not to mention all
the data integrity issues and difficulty in changing the monolithic procedural application
code.
&lt;/p&gt;
&lt;/blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
I also remember helping a teachers union who started off with a simple attendance
tracker style app (to use an example Ted mentions) and just scaled it up to an atrociously
complex Access database with stranded data and manual processes where they printed
excel spreadsheets to paper, then manually entered it into another application.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
And you know what? 
&lt;/p&gt;
&lt;p&gt;
This is not a bad state of affairs. 
&lt;/p&gt;
&lt;p&gt;
Oh, of course, we, the IT professionals, will immediately pounce on all the things
wrong with their attempts to extend the once-simple application/solution in ways beyond
its capabilities, and we will scoff at their solutions, but you know what? That just
speaks to our insecurities, not the effort expended. You think Wolfgang Puck isn't
going to throw back his head and roar at my lame attempts at culinary experimentation?
You think Frank Lloyd Wright wouldn't cringe in horror at my cobbled-together doghouse?
And I'll bet Maya Angelou will be so shocked at the ugliness of my poetry that she'll
post it somewhere on the &amp;quot;So You Think You're A Poet&amp;quot; website.
&lt;/p&gt;
&lt;p&gt;
Does that mean I need to abandon my efforts to all of these things?
&lt;/p&gt;
&lt;p&gt;
The agilists' community reaction to my post would seem to imply so. &amp;quot;If you aren't
a professional, don't even attempt this?&amp;quot; Really? Is that the message we're preaching
these days?
&lt;/p&gt;
&lt;p&gt;
End users have just as much a desire and right to be amateur software developers as
we do at being amateur cooks, photographers, poets, construction foremen, and musicians.
And what do you do when you want to add an addition to your house instead of just
building a doghouse? Or when you want to cook for several hundred people instead of
just your family?
&lt;/p&gt;
&lt;p&gt;
You hire a professional, and let them do the project professionally.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,f9d4f3dc-bf96-4f4b-8794-6a053ab2d7da.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=53f9b658-3b27-4f1a-b93e-14d3a57a8ec1</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,53f9b658-3b27-4f1a-b93e-14d3a57a8ec1.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,53f9b658-3b27-4f1a-b93e-14d3a57a8ec1.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=53f9b658-3b27-4f1a-b93e-14d3a57a8ec1</wfw:commentRss>
      <slash:comments>35</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The above quote was tossed off by Billy Hollis at the patterns&amp;practices Summit
this week in Redmond. I passed the quote out to the Twitter masses, along with my
+1, and predictably, the comments started coming in shortly thereafter. Rather than
limit the thoughts to the 120 or so characters that Twitter limits us to, I thought
this subject deserved some greater expansion.
</p>
        <p>
But before I do, let me try (badly) to paraphrase the lightning talk that Billy gave
here, which sets context for the discussion:
</p>
        <ul>
          <li>
Keeping track of all the stuff Microsoft is releasing is hard work: LINQ, EF, Silverlight,
ASP.NET MVC, Enterprise Library, Azure, Prism, Sparkle, MEF, WCF, WF, WPF, InfoCard,
CardSpace, the list goes on and on, and frankly, nobody (and I mean nobody) can track
it all.</li>
          <li>
Microsoft released all this stuff because they were chasing the "enterprise"
part of the developer/business curve, as opposed to the "long tail" part
of the curve that they used to chase down. They did this because they believed that
this was good business practice—like banks, "enterprises are where the money
is". (If you're not familiar with this curve, imagine a graph with a single curve
asymptotically reaching for both axes, where Y is the number of developers on the
project, and X is the number of projects. What you get is a curve of a few high-developer-population
projects on the left, to a large number of projects with just 1 or 2 developers. This
right-hand portion of the curve is known as "the long tail" of the software
industry.)</li>
          <li>
A lot of software written back in the 90's was written by 1 or 2 guys working for
just a few months to slam something out and see if it was useful. What chances do
those kinds of projects have today? What tools would you use to build them?</li>
          <li>
The problem is the complexity of the tools we have available to us today preclude
that kind of software development.</li>
          <li>
Agile doesn't solve this problem—the agile movement suggests that we have to create
story cards, we have to build unit tests, we have to have a continuous integration
server, we have to have standup meetings every day, .... In short, particularly among
the agile evangelists (by which we really mean <em>zealots</em>), if you aren't doing
a full agile process, you are simply failing. <em>(If this is true, how on earth did
all those thousands of applications written in FoxPro or Access ever manage to succeed?
–-Me)</em> At one point, an agilist said point-blank, "If you don't do agile,
what happens when your project reaches a thousand users?" As Billy put it, "Think
about that for a second: This agile guy is <em>threatening</em> us with success."</li>
          <li>
Agile is for managing complexity. What we need is to recognize that there is a place
for outright simplicity instead.</li>
        </ul>
        <p>
By the way, let me say this out loud: if you have not heard Billy Hollis speak, you
should. Even if you're a Java or Ruby developer, you should listen to what he has
to say. He's been developing software for a long time, has seen a lot of these technology-industry
trends come and go, and even if you disagree with him, you need to listen to him.
</p>
        <p>
Let me rephrase Billy's talk this way:
</p>
        <blockquote>
          <p>
            <em>Where is this decade's Access?</em>
          </p>
        </blockquote>
        <p>
It may seem like a snarky and trolling question, but think about it for a moment:
for a decade or so, I was brought into project after project that was designed to
essentially rebuild/rearchitect the Access database created by one of the department's
more tech-savvy employees into something that could scale beyond just the department. 
</p>
        <blockquote>
          <p>
            <em>(Actually, in about half of them, the goal wasn't even to scale it up, it was
just to put it on the web. It was only in the subsequent meetings and discussions
that the issues of scale came up, and if my memory is accurate, I was the one who
raised those issues, not the customer. I wonder now, looking back at it, if that was
pure gold-plating on my part.)</em>
          </p>
        </blockquote>
        <p>
Others, including many people I care about (Rod Paddock, Markus Eggers, Ken Levy,
Cathi Gero, for starters) made a healthy living off of building "line of business"
applications in FoxPro, which Microsoft has now officially shut down. For those who
did Office applications, Visual Basic for Applications has now been officially deprecated
in favor of VSTO (Visual Studio Tools for Office), a set of libraries that are available
for use by any .NET application language, and of course classic Visual Basic itself
has been "brought into the fold" by making it a fully-fledged object-oriented
language complete with XML literals and LINQ query capabilities.
</p>
        <p>
Which means, if somebody working for a small school district in western Pennsylvania
wants to build a simple application for tracking students' attendance (rather than
tracking it on paper anymore), what do they do?
</p>
        <p>
Bruce Tate alluded to this in his <em>Beyond Java</em>, based on the realization that
the Java space was no better—to bring a college/university student up to speed on
all the necessary technologies required of a "productive" Java developer,
he calculated at least five or six weeks of training was required. And that's not
a bad estimate, and might even be a bit on the shortened side. You can maybe get away
with less if they're joining a team which collectively has these skills distributed
across the entire team, but if we're talking about a standalone developer who's going
to be building software by himself, it's a pretty impressive list. Here's my back-of-the-envelope
calculations:
</p>
        <ul>
          <li>
Week one: Java language. (Nobody ever comes out of college knowing all the Java language
they need.)</li>
          <li>
Week two: Java virtual machine: threading/concurrency, ClassLoaders, Serialization,
RMI, XML parsing, reference types (weak, soft, phantom).</li>
          <li>
Week three: Infrastructure: Ant, JUnit, continuous integration, Spring.</li>
          <li>
Week four: Data access: JDBC, Hibernate. (Yes, I think you need a full week on Hibernate
to be able to use it effectively.)</li>
          <li>
Week five: Web: HTTP, HTML, servlets, filters, servlet context and listeners, JSP,
model-view-controller, and probably some Ajax to boot.</li>
        </ul>
        <p>
I could go on (seriously! no JMS? no REST? no Web services?), but you get the point.
And lest the .NET community start feeling complacent, put together a similar list
for the standalone .NET developer, and you'll come out to something pretty equivalent.
(Just look at the <a href="http://www.pluralsight.com/main/ilt/Courses.aspx" target="_blank">Pluralsight
list of courses</a>—name the <em>one</em> course you would give that college kid to
bring him up to speed. Stumped? Don't feel bad—I can't, either. And it's not them—pick
on any of the training companies.)
</p>
        <p>
Now throw agile into that mix: <em>how does an agile process reduce the complexity
load?</em> And the answer, of course, is that it doesn't—it simply tries to muddle
through as best it can, by doing all of the things that developers need to be doing:
gathering as much feedback from every corner of their world as they can, through tests,
customer interaction, and frequent releases. <em>All of which is good</em>. I'm <em>not</em> here
to suggest that we should all give up agile and immediately go back to waterfall and
Big Design Up Front. Anybody who uses Billy's quote as a sound bite to suggest that
is a subversive and a terrorist and should have their arguments refuted with <em>extreme
prejudice</em>.
</p>
        <p>
But agile is not going to reduce the technology complexity load, which is the root
cause of the problem.
</p>
        <p>
Or, perhaps, let me ask it this way: your 16-year-old wants to build a system to track
the cards in his Magic deck. What language do you teach him?
</p>
        <p>
We are in <em>desperate</em> need of simplicity in this industry. Whoever gets that,
and gets it right, defines the "Next Big Thing".
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=53f9b658-3b27-4f1a-b93e-14d3a57a8ec1" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>&amp;quot;Agile is treating the symptoms, not the disease&amp;quot;</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,53f9b658-3b27-4f1a-b93e-14d3a57a8ec1.aspx</guid>
      <link>http://blogs.tedneward.com/2009/10/12/quotAgile+Is+Treating+The+Symptoms+Not+The+Diseasequot.aspx</link>
      <pubDate>Mon, 12 Oct 2009 23:51:39 GMT</pubDate>
      <description>&lt;p&gt;
The above quote was tossed off by Billy Hollis at the patterns&amp;amp;practices Summit
this week in Redmond. I passed the quote out to the Twitter masses, along with my
+1, and predictably, the comments started coming in shortly thereafter. Rather than
limit the thoughts to the 120 or so characters that Twitter limits us to, I thought
this subject deserved some greater expansion.
&lt;/p&gt;
&lt;p&gt;
But before I do, let me try (badly) to paraphrase the lightning talk that Billy gave
here, which sets context for the discussion:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Keeping track of all the stuff Microsoft is releasing is hard work: LINQ, EF, Silverlight,
ASP.NET MVC, Enterprise Library, Azure, Prism, Sparkle, MEF, WCF, WF, WPF, InfoCard,
CardSpace, the list goes on and on, and frankly, nobody (and I mean nobody) can track
it all.&lt;/li&gt;
&lt;li&gt;
Microsoft released all this stuff because they were chasing the &amp;quot;enterprise&amp;quot;
part of the developer/business curve, as opposed to the &amp;quot;long tail&amp;quot; part
of the curve that they used to chase down. They did this because they believed that
this was good business practice—like banks, &amp;quot;enterprises are where the money
is&amp;quot;. (If you're not familiar with this curve, imagine a graph with a single curve
asymptotically reaching for both axes, where Y is the number of developers on the
project, and X is the number of projects. What you get is a curve of a few high-developer-population
projects on the left, to a large number of projects with just 1 or 2 developers. This
right-hand portion of the curve is known as &amp;quot;the long tail&amp;quot; of the software
industry.)&lt;/li&gt;
&lt;li&gt;
A lot of software written back in the 90's was written by 1 or 2 guys working for
just a few months to slam something out and see if it was useful. What chances do
those kinds of projects have today? What tools would you use to build them?&lt;/li&gt;
&lt;li&gt;
The problem is the complexity of the tools we have available to us today preclude
that kind of software development.&lt;/li&gt;
&lt;li&gt;
Agile doesn't solve this problem—the agile movement suggests that we have to create
story cards, we have to build unit tests, we have to have a continuous integration
server, we have to have standup meetings every day, .... In short, particularly among
the agile evangelists (by which we really mean &lt;em&gt;zealots&lt;/em&gt;), if you aren't doing
a full agile process, you are simply failing. &lt;em&gt;(If this is true, how on earth did
all those thousands of applications written in FoxPro or Access ever manage to succeed?
–-Me)&lt;/em&gt; At one point, an agilist said point-blank, &amp;quot;If you don't do agile,
what happens when your project reaches a thousand users?&amp;quot; As Billy put it, &amp;quot;Think
about that for a second: This agile guy is &lt;em&gt;threatening&lt;/em&gt; us with success.&amp;quot;&lt;/li&gt;
&lt;li&gt;
Agile is for managing complexity. What we need is to recognize that there is a place
for outright simplicity instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
By the way, let me say this out loud: if you have not heard Billy Hollis speak, you
should. Even if you're a Java or Ruby developer, you should listen to what he has
to say. He's been developing software for a long time, has seen a lot of these technology-industry
trends come and go, and even if you disagree with him, you need to listen to him.
&lt;/p&gt;
&lt;p&gt;
Let me rephrase Billy's talk this way:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Where is this decade's Access?&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
It may seem like a snarky and trolling question, but think about it for a moment:
for a decade or so, I was brought into project after project that was designed to
essentially rebuild/rearchitect the Access database created by one of the department's
more tech-savvy employees into something that could scale beyond just the department. 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;(Actually, in about half of them, the goal wasn't even to scale it up, it was
just to put it on the web. It was only in the subsequent meetings and discussions
that the issues of scale came up, and if my memory is accurate, I was the one who
raised those issues, not the customer. I wonder now, looking back at it, if that was
pure gold-plating on my part.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Others, including many people I care about (Rod Paddock, Markus Eggers, Ken Levy,
Cathi Gero, for starters) made a healthy living off of building &amp;quot;line of business&amp;quot;
applications in FoxPro, which Microsoft has now officially shut down. For those who
did Office applications, Visual Basic for Applications has now been officially deprecated
in favor of VSTO (Visual Studio Tools for Office), a set of libraries that are available
for use by any .NET application language, and of course classic Visual Basic itself
has been &amp;quot;brought into the fold&amp;quot; by making it a fully-fledged object-oriented
language complete with XML literals and LINQ query capabilities.
&lt;/p&gt;
&lt;p&gt;
Which means, if somebody working for a small school district in western Pennsylvania
wants to build a simple application for tracking students' attendance (rather than
tracking it on paper anymore), what do they do?
&lt;/p&gt;
&lt;p&gt;
Bruce Tate alluded to this in his &lt;em&gt;Beyond Java&lt;/em&gt;, based on the realization that
the Java space was no better—to bring a college/university student up to speed on
all the necessary technologies required of a &amp;quot;productive&amp;quot; Java developer,
he calculated at least five or six weeks of training was required. And that's not
a bad estimate, and might even be a bit on the shortened side. You can maybe get away
with less if they're joining a team which collectively has these skills distributed
across the entire team, but if we're talking about a standalone developer who's going
to be building software by himself, it's a pretty impressive list. Here's my back-of-the-envelope
calculations:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Week one: Java language. (Nobody ever comes out of college knowing all the Java language
they need.)&lt;/li&gt;
&lt;li&gt;
Week two: Java virtual machine: threading/concurrency, ClassLoaders, Serialization,
RMI, XML parsing, reference types (weak, soft, phantom).&lt;/li&gt;
&lt;li&gt;
Week three: Infrastructure: Ant, JUnit, continuous integration, Spring.&lt;/li&gt;
&lt;li&gt;
Week four: Data access: JDBC, Hibernate. (Yes, I think you need a full week on Hibernate
to be able to use it effectively.)&lt;/li&gt;
&lt;li&gt;
Week five: Web: HTTP, HTML, servlets, filters, servlet context and listeners, JSP,
model-view-controller, and probably some Ajax to boot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I could go on (seriously! no JMS? no REST? no Web services?), but you get the point.
And lest the .NET community start feeling complacent, put together a similar list
for the standalone .NET developer, and you'll come out to something pretty equivalent.
(Just look at the &lt;a href="http://www.pluralsight.com/main/ilt/Courses.aspx" target="_blank"&gt;Pluralsight
list of courses&lt;/a&gt;—name the &lt;em&gt;one&lt;/em&gt; course you would give that college kid to
bring him up to speed. Stumped? Don't feel bad—I can't, either. And it's not them—pick
on any of the training companies.)
&lt;/p&gt;
&lt;p&gt;
Now throw agile into that mix: &lt;em&gt;how does an agile process reduce the complexity
load?&lt;/em&gt; And the answer, of course, is that it doesn't—it simply tries to muddle
through as best it can, by doing all of the things that developers need to be doing:
gathering as much feedback from every corner of their world as they can, through tests,
customer interaction, and frequent releases. &lt;em&gt;All of which is good&lt;/em&gt;. I'm &lt;em&gt;not&lt;/em&gt; here
to suggest that we should all give up agile and immediately go back to waterfall and
Big Design Up Front. Anybody who uses Billy's quote as a sound bite to suggest that
is a subversive and a terrorist and should have their arguments refuted with &lt;em&gt;extreme
prejudice&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
But agile is not going to reduce the technology complexity load, which is the root
cause of the problem.
&lt;/p&gt;
&lt;p&gt;
Or, perhaps, let me ask it this way: your 16-year-old wants to build a system to track
the cards in his Magic deck. What language do you teach him?
&lt;/p&gt;
&lt;p&gt;
We are in &lt;em&gt;desperate&lt;/em&gt; need of simplicity in this industry. Whoever gets that,
and gets it right, defines the &amp;quot;Next Big Thing&amp;quot;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=53f9b658-3b27-4f1a-b93e-14d3a57a8ec1" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,53f9b658-3b27-4f1a-b93e-14d3a57a8ec1.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Social</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>WCF</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=6b0686be-7311-4856-9fc9-6fd1c7040b37</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,6b0686be-7311-4856-9fc9-6fd1c7040b37.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,6b0686be-7311-4856-9fc9-6fd1c7040b37.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=6b0686be-7311-4856-9fc9-6fd1c7040b37</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently I've had the pleasure to make the acquaintance of <a href="http://www.walterbright.com/" target="_blank">Walter
Bright</a>, one of the heavyweights of compiler construction, and the creator of the
D language (among other things), and he's been great in giving me some hand-holding
on some compiler-related topics and ideas.
</p>
        <p>
Thus, it seems appropriate to point out that Walter's willing to give lots of other
people the same kind of attention and focus, <a href="http://www.astoriaseminar.com/" target="_blank">in
exchange for your presence in gorgeous Astoria, OR</a>. The Astoria Compiler Construction
Seminar is Walter teaching you about the nuts and bolts of building a compiler, from
start to finish:
</p>
        <ul>
          <li>
Introduction to Compilers</li>
          <li>
Lexing and Parsing</li>
          <li>
Semantic Analysis</li>
          <li>
Intermediate Representation</li>
          <li>
Interpreters</li>
          <li>
Optimization</li>
          <li>
Code Generation</li>
          <li>
Special Topics (thread-local storage, exception-handling, and so on)</li>
          <li>
Building a Compiler for .NET</li>
        </ul>
        <p>
If you've got any interest whatsoever in building a language, but you're not sure
how or where to get started, this seems like a great chance to sit down with one of
the "big boys" and find out how to do it. And it doesn't hurt that Walter's
an extremely pleasant guy to hang out with, either. :-) (It doesn't hurt that he was
the one who created the original Empire game, either. So at least you know you'll
have something to play during the breaks.)
</p>
        <p>
Go. Sign up. You'll thank me later.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6b0686be-7311-4856-9fc9-6fd1c7040b37" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Are you a language wonk? Do you want to be?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,6b0686be-7311-4856-9fc9-6fd1c7040b37.aspx</guid>
      <link>http://blogs.tedneward.com/2009/08/15/Are+You+A+Language+Wonk+Do+You+Want+To+Be.aspx</link>
      <pubDate>Sat, 15 Aug 2009 17:44:30 GMT</pubDate>
      <description>&lt;p&gt;
Recently I've had the pleasure to make the acquaintance of &lt;a href="http://www.walterbright.com/" target="_blank"&gt;Walter
Bright&lt;/a&gt;, one of the heavyweights of compiler construction, and the creator of the
D language (among other things), and he's been great in giving me some hand-holding
on some compiler-related topics and ideas.
&lt;/p&gt;
&lt;p&gt;
Thus, it seems appropriate to point out that Walter's willing to give lots of other
people the same kind of attention and focus, &lt;a href="http://www.astoriaseminar.com/" target="_blank"&gt;in
exchange for your presence in gorgeous Astoria, OR&lt;/a&gt;. The Astoria Compiler Construction
Seminar is Walter teaching you about the nuts and bolts of building a compiler, from
start to finish:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Introduction to Compilers&lt;/li&gt;
&lt;li&gt;
Lexing and Parsing&lt;/li&gt;
&lt;li&gt;
Semantic Analysis&lt;/li&gt;
&lt;li&gt;
Intermediate Representation&lt;/li&gt;
&lt;li&gt;
Interpreters&lt;/li&gt;
&lt;li&gt;
Optimization&lt;/li&gt;
&lt;li&gt;
Code Generation&lt;/li&gt;
&lt;li&gt;
Special Topics (thread-local storage, exception-handling, and so on)&lt;/li&gt;
&lt;li&gt;
Building a Compiler for .NET&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
If you've got any interest whatsoever in building a language, but you're not sure
how or where to get started, this seems like a great chance to sit down with one of
the &amp;quot;big boys&amp;quot; and find out how to do it. And it doesn't hurt that Walter's
an extremely pleasant guy to hang out with, either. :-) (It doesn't hurt that he was
the one who created the original Empire game, either. So at least you know you'll
have something to play during the breaks.)
&lt;/p&gt;
&lt;p&gt;
Go. Sign up. You'll thank me later.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6b0686be-7311-4856-9fc9-6fd1c7040b37" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,6b0686be-7311-4856-9fc9-6fd1c7040b37.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=bfd09520-fc73-4358-9a87-14f433f40095</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,bfd09520-fc73-4358-9a87-14f433f40095.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,bfd09520-fc73-4358-9a87-14f433f40095.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=bfd09520-fc73-4358-9a87-14f433f40095</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <blockquote>
          <p>
            <em>
              <strong>(Disclaimer:</strong> In the spirit of full disclosure, Stu is a friend,
fellow NFJS speaker, and former co-worker of mine from DevelopMentor.)</em>
          </p>
        </blockquote>
        <p>
I present this review to you in two parts.
</p>
        <p>
          <strong>Short version:</strong> If you want to learn Clojure, and you're familiar
with at least one programming language, you'll find this a great resource. If you
don't already know a programming language, or if you already know Clojure, or if you're
looking for "best practices" to cut-and-paste, you're going to be disappointed.
</p>
        <p>
          <strong>Long version:</strong> Recently, fellow NFJS speaker Stu Halloway decided
to take up a new language, and came to Clojure. He found the language interesting
enough to write a book on it, something he hasn't done since his Java days, and the
result is a nice walk through the language and its environment for experienced Java
developers who want to understand Clojure's language, concurrency concepts, and programming
model.
</p>
        <p>
Now, let's be 100% honest about this: if you're coming at this book expecting it to
be a language reference, you will probably be disappointed (as <a href="http://www.amazon.com/review/R3NM9CKFWYFKAE/ref=cm_cr_rdp_perm" target="_blank">this
guy</a> obviously is). Stu's not like that—he's not going to re-create material that's
available elsewhere, or that can be found with an easy Google search. Stu will not
waste your time that way—he wants to tell you a story, one that takes you from "I'm
a Java guy, but clueless about Lisp, dynamic languages, functional programming, concurrency,
or macros" to "Wow. I know kung-fu." in the shortest path possible,
but without trying to lobotomize you. He wants—no, <em>expects</em>—the readers of
his book to be propping the text open with a cell phone on one side and the dinner
plate on the other, craning your neck over to scan the pages and type in the examples
into the REPL shell to try them out, see them work, then spend a few minutes experimenting
with them before moving on to the next paragraph or page. 
</p>
        <p>
(Oh, I suppose you could just cut and paste them from the PDF version of the book,
but where's the fun in that?)
</p>
        <p>
The fact is, the <em>concepts</em> behind Clojure make up what's important to learn
here, and readers of this book will come away like the panda from the movie, realizing
that "There is no Secret Ingredient", that the power of Clojure comes not
from its super-secret language sauce or special libraries, but in the way Clojure
programmers approach problems and think about programming. And for that reason, if
you're a programmer—even if you don't program on the JVM—you really want to take a
look at what Stu's talking about (and Rich Hickey is creating).
</p>
        <p>
Just remember, cellphone and dinner plate. Otherwise you'll be missing out on so much.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bfd09520-fc73-4358-9a87-14f433f40095" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Review: &amp;quot;Programming Clojure&amp;quot;, by Stu Halloway</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,bfd09520-fc73-4358-9a87-14f433f40095.aspx</guid>
      <link>http://blogs.tedneward.com/2009/06/28/Review+QuotProgramming+Clojurequot+By+Stu+Halloway.aspx</link>
      <pubDate>Sun, 28 Jun 2009 05:34:56 GMT</pubDate>
      <description>&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;&lt;strong&gt;(Disclaimer:&lt;/strong&gt; In the spirit of full disclosure, Stu is a friend,
fellow NFJS speaker, and former co-worker of mine from DevelopMentor.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I present this review to you in two parts.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Short version:&lt;/strong&gt; If you want to learn Clojure, and you're familiar
with at least one programming language, you'll find this a great resource. If you
don't already know a programming language, or if you already know Clojure, or if you're
looking for &amp;quot;best practices&amp;quot; to cut-and-paste, you're going to be disappointed.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Long version:&lt;/strong&gt; Recently, fellow NFJS speaker Stu Halloway decided
to take up a new language, and came to Clojure. He found the language interesting
enough to write a book on it, something he hasn't done since his Java days, and the
result is a nice walk through the language and its environment for experienced Java
developers who want to understand Clojure's language, concurrency concepts, and programming
model.
&lt;/p&gt;
&lt;p&gt;
Now, let's be 100% honest about this: if you're coming at this book expecting it to
be a language reference, you will probably be disappointed (as &lt;a href="http://www.amazon.com/review/R3NM9CKFWYFKAE/ref=cm_cr_rdp_perm" target="_blank"&gt;this
guy&lt;/a&gt; obviously is). Stu's not like that—he's not going to re-create material that's
available elsewhere, or that can be found with an easy Google search. Stu will not
waste your time that way—he wants to tell you a story, one that takes you from &amp;quot;I'm
a Java guy, but clueless about Lisp, dynamic languages, functional programming, concurrency,
or macros&amp;quot; to &amp;quot;Wow. I know kung-fu.&amp;quot; in the shortest path possible,
but without trying to lobotomize you. He wants—no, &lt;em&gt;expects&lt;/em&gt;—the readers of
his book to be propping the text open with a cell phone on one side and the dinner
plate on the other, craning your neck over to scan the pages and type in the examples
into the REPL shell to try them out, see them work, then spend a few minutes experimenting
with them before moving on to the next paragraph or page. 
&lt;/p&gt;
&lt;p&gt;
(Oh, I suppose you could just cut and paste them from the PDF version of the book,
but where's the fun in that?)
&lt;/p&gt;
&lt;p&gt;
The fact is, the &lt;em&gt;concepts&lt;/em&gt; behind Clojure make up what's important to learn
here, and readers of this book will come away like the panda from the movie, realizing
that &amp;quot;There is no Secret Ingredient&amp;quot;, that the power of Clojure comes not
from its super-secret language sauce or special libraries, but in the way Clojure
programmers approach problems and think about programming. And for that reason, if
you're a programmer—even if you don't program on the JVM—you really want to take a
look at what Stu's talking about (and Rich Hickey is creating).
&lt;/p&gt;
&lt;p&gt;
Just remember, cellphone and dinner plate. Otherwise you'll be missing out on so much.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bfd09520-fc73-4358-9a87-14f433f40095" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,bfd09520-fc73-4358-9a87-14f433f40095.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=be86b355-6dfb-4395-bfa9-d09783f21428</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,be86b355-6dfb-4395-bfa9-d09783f21428.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,be86b355-6dfb-4395-bfa9-d09783f21428.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=be86b355-6dfb-4395-bfa9-d09783f21428</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Well, OK, the title is trolling ever so slightly, but there is an interesting trend
at work, and I'm genuinely concerned about its ultimate expression if the trend continues
to its logical conclusion. <a href="http://channel9.msdn.com/posts/Glucose/Hanselminutes-on-9-The-Death-of-the-Professional-Conference-Speaker/" target="_blank">Have
a look</a> and tell me if you agree or disagree.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=be86b355-6dfb-4395-bfa9-d09783f21428" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Interview with Scott Bellware and Scott Hanselman on the Death of the Professional Speaker</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,be86b355-6dfb-4395-bfa9-d09783f21428.aspx</guid>
      <link>http://blogs.tedneward.com/2009/06/18/Interview+With+Scott+Bellware+And+Scott+Hanselman+On+The+Death+Of+The+Professional+Speaker.aspx</link>
      <pubDate>Thu, 18 Jun 2009 13:40:28 GMT</pubDate>
      <description>&lt;p&gt;
Well, OK, the title is trolling ever so slightly, but there is an interesting trend
at work, and I'm genuinely concerned about its ultimate expression if the trend continues
to its logical conclusion. &lt;a href="http://channel9.msdn.com/posts/Glucose/Hanselminutes-on-9-The-Death-of-the-Professional-Conference-Speaker/" target="_blank"&gt;Have
a look&lt;/a&gt; and tell me if you agree or disagree.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=be86b355-6dfb-4395-bfa9-d09783f21428" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,be86b355-6dfb-4395-bfa9-d09783f21428.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Social</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=49e7a9d3-c222-45d7-a049-29b5a4b25cd3</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,49e7a9d3-c222-45d7-a049-29b5a4b25cd3.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,49e7a9d3-c222-45d7-a049-29b5a4b25cd3.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=49e7a9d3-c222-45d7-a049-29b5a4b25cd3</wfw:commentRss>
      <slash:comments>22</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Apparently the Rails community isn't the only one pursuing that ephemeral goal of
"edginess"—another blatantly sexist presentation came off without a hitch,
this time at a Flash conference, and if anything, it was worse than the Rails/CouchDB
presentation. I excerpt a few choice tidbits <a href="http://www.geekgirlsguide.com/blog/2009/06/11/98/prude_or_professional_by_courtney_remes" target="_blank">from
an eyewitness</a> here, but be warned—if you're not comfortable with language, skip
the next block paragraph.
</p>
        <blockquote>
          <p>
Yesterday's afternoon keynote is this guy named <a href="http://flashbelt.com/#/speakers/hoss_gifford/">Hoss
Gifford</a> — I believe his major claim to fame is that viral "spank the monkey"
thing that went around a few years back.  Highlights of his talk:
</p>
          <ul>
            <li>
He opens his keynote with one of those <a href="http://www.ignitempls.org/">"Ignite"-esque
presentations</a> — where you have 5-minutes and 20 slides to tell a story — and the
first and last are a close-up of a woman's lower half, her legs spread (wearing stilettos,
of course) and her shaved vagina visible through some see-thru panties that say "drink
me," with Hoss's Photoshopped, upward-looking face placed below it. 
</li>
            <li>
He later demos a drawing tool he has created (admittedly with someone else's code)
and invites a woman to come up to try it.  After she sits back down, he points
out that in her doodles she's drawn a "cock." 
</li>
            <li>
Then he decides he wants to give a try at using the tool to draw a "cock"
(he loves this word) — and draws a face, then a giant dick (he redraws it three times)
that ultimately cums all over the face. 
</li>
            <li>
A multitude of references to penises and lots of swearing — and also "If you
are easily offended, fuck you!" 
</li>
            <li>
And then, to top it off, a self-made flash movie of an animated woman's face, positioned
as if she's having sex with you, who gradually orgasms based on the speed of your
mouse movement on the page. 
</li>
          </ul>
        </blockquote>
        <p>
Wow. Just... wow. To call this unprofessional smacks of calling Hitler a "socially
awkward individual"... or using a euphemism like "mild medical condition"
to refer to death. This is so far "over the line" that it's unbelievable.
Even Mr. Aimonetti's "CouchDB" presentation, as bad as it was, at least
tried to tie the analogy together in a meaningful, if offensive, way. This is just
male posturing at its worst. (I'm shocked Hoss didn't whip off his pants and demand
the women in the room bow down in worship to his obviously superior manhood.) 
</p>
        <p>
Fortunately, according to the source, the conference organizer seems to be pretty
responsive, so kudos to the one adult in the room, but....
</p>
        <p>
What's worse, apparently the presenter and more than a few of his pals are (in the
best traditions of assholery) blatantly unrepentant about the whole thing, claiming
the moral high ground in much the same way that the Rails idiots did—it's all in good
fun, if you don't find it funny you're a prude, and so on:
</p>
        <blockquote>
          <p>
I checked Twitter (hashtag <a href="http://search.twitter.com/search?q=%23flashbelt">#flashbelt</a>)
to see what the responses were.  Here are some notable remarks:
</p>
          <ul>
            <li>
              <a href="http://twitter.com/Fonx/status/2096740346">Fonx</a> is reading the #flashbelt
rants on Hoss offending the ladies w/ a few swear words &amp; a penis drawing - r
u really that prudish &amp; sexist? 
</li>
            <li>
nthitz lol @hoss69 "If you are easily offended, fuck you" #flashbelt 
</li>
            <li>
              <a href="http://twitter.com/livenootrac/status/2096075802">livenootrac</a> Ladies
of #flashbelt , I am sorry for the Hoss preso, but in the flash community he gets
a pass, kinda like Don Rickles - that's just Hoss. 
</li>
            <li>
              <a href="http://twitter.com/CujoJpn/status/2096658483">CujoJpn</a> @livenootrac And
there were many ladies at #flashbelt who were offended by Hoss' Preso some were thick
skinned and took it as is. 
</li>
          </ul>
          <p>
So, if you didn't like it then 
<br />
a) you are a prude - and sexist (?) 
<br />
b) fuck you 
<br />
c) suck it because Hoss gets a pass here in the boy's club known as "the flash
community" and 
<br />
d) you are a wimpy girl who isn't strong enough / man enough / "thick-skinned"
enough  to deal with it.
</p>
        </blockquote>
        <p>
Even more... wow. Talk about justification and marginalization. Amazing.
</p>
        <p>
Before I figuratively smack this Hoss guy around the blog for a while, let's take
a brief moment for reflection—what's going on here? Why all the misogynistic presentations
recently? Is this reflective of a general trend in the programming industry? Of society
in general? Is the world coming to an end?
</p>
        <p>
A few possibilities present themselves:
</p>
        <ul>
          <li>
            <strong>The lack of women in the IT industry means there's nobody around to act as
a "gender filter" to keep things on an even keel.</strong> In other words,
the genders constantly filter themselves based on the company they keep, and because
the boys who put these presentations together don't have female input, they simply
don't know where to draw the line for mixed company. This theory also presumes that
an industry that's made up primarily of women will also lack such a filter and "girls
will be girls" as a result. Unfortunately I have no good counterexamples at hand
to examine—anybody know of an industry populated primarily by women, and can weigh
in with experience there? The closest I get is my brief experience working in a restaurant
with an almost-all-woman serving staff, and from that brief experience, yep, the theory
holds. Solution? Easy: get more women in IT, and things will re-balance themselves
naturally.</li>
          <li>
            <strong>Programmers are principally males who have no redeeming social skills.</strong> In
other words, the industry gathers up exactly the kind of men who find objectifying
women and reveling in late-acquired testosterone overdoses to be gratifying, and this
kind of behavior is the result. If true, it leads to the conclusion that programmers
are no more evolved than the Navy sailors involved in the Tailhook scandal of a few
years ago. So go ahead, smack your wives and girlfriends around a little if they get
a little "uppity", it's OK, 'cuz u r a l33t d00d. Personally? I find the
idea ludicrous—there is definitely a strong antisocial streak that runs through the
IT ecosystem (how many of you met your friends via World of Warcraft again?), but
like all stereotypes, there's some elements of truth to it, and a lot of exaggeration.
And frankly, anybody who believes in this theory is welcome to come with me to dinner
at a No Fluff Just Stuff show and meet the other speakers, and listen in on our "boys
club" conversations, including questions like, "Which movie best represents
the book it was made after?" and "If given a mandate to create a programming
language, what language would your language most resemble?". Oh, and the odd
fart joke. We are boys, after all.</li>
          <li>
            <strong>We're hypersensitive to the subject right now.</strong> In other words, these
kind of presentations have always been going on, and it's just that we notice them
now, in the same way that you notice a particular brand of car on the road a lot more
when you're thinking about buying that brand and model of car. Frankly, I don't buy
this argument—I've been to a lot of presentations over the past decade, and I've never
seen any that were anything like this.</li>
          <li>
            <strong>This is the YouTube generation, with access to everything the Internet has
to offer, and this is "just how they do things".</strong> After all, how
much maturity, sexual discretion and adult behavior can we expect of the generation
that gave us "Girls Gone Wild" and its ilk? It's just a "generation
gap" thing, and we old fogies who didn't grow up with Internet porn just a browser-click
away just don't "get it". Hmm.... somehow, I just don't buy it. Sure, there
may be some elements of this involved here (I'm <em>really</em> curious to see what
all these "Girls Gone Wild" girls are going to say to their own daughters
in a decade or so...), but I think that's too easy an answer, and an eminently unhelpful
one.</li>
          <li>
            <strong>We have copycatters out there trying to follow the path of people they respect.</strong> If
you're looking up at this Hoss character and thinking, "I want to be just like
him!", you really should see a therapist and develop a sense of self, before
you find yourself without friends. Hoss gets a pass because of your misguided fan-boi
hero-worship. So does Paris Hilton. You want to be the Paris Hilton of your social
circle? Go for it. After all, she's highly respected and loved, right? Take a clue
from the next car wreck you drive past—everybody's slowing to look not because they
wish they were in the body bag, folks, but because we have a ghoulish fascination
with it. In the case of Ms. Hilton, that ghoulish fascination is with those who self-destruct
in spectacular fashion. (Me, I'd <em>love</em> to be the fly on the wall at the Hoss
residence when he tries to explain this whole thing to his daughter or his date/girlfriend/wife,
if he ever finds one.)</li>
          <li>
            <strong>The presenters taking this tack are looking for an easy path to fame.</strong> In
the grand traditions of Andrew Dice Clay ("Oh!"), the easiest way for a
presenter to "stand out" from the rest of the crowd of presenters is to
do something outrageous and call it "edgy", and stake out a claim on the
edge of the civilization, rather than try to integrate with the rest of the crowd
and build something up slowly. Don Box has already claimed "HTTP is dead",
I made the analogy between a technology and a military conflict, and Matt Aimonetti
claimed a data storage framework "performs like a pr0n star", so what's
left but to stake out ground even further out on the fringe and just be misogynistic?
Fortunately, history suggests that people with content-free/shock-heavy presentations
(or even content-heavy/shock-heavy ones) don't go the distance, so to speak, and that
once there's nowhere more shocking left to go, the audience comes back to the content-heavy/shock-light
discussions and stays there for a while. Unfortunately, this means we're going to
have to suffer through somebody's "Live YouPorn filming" talk first, which
I'm <em>not</em> looking forward to.</li>
        </ul>
        <p>
And now for the smacking around... but you know, I suddenly realize that the volume
of comments on the original post leave with nothing to do or say that's not already
being said, so to just "pile on" would only serve to let me vent, and I
have other outlets for that. But it would be inappropriate to just "walk away",
so to speak, so with that in mind....
</p>
        <p>
Hoss, you're an idiot. Like any sprinter, you're going to head up the pack for a bit,
but soon enough, your "shtick" is going to flame out and you'll be left
behind with all the other "shock jocks" of the 80's who found their material
unwelcome after a while. So enjoy the spotlight (such as it is) while you can. In
the meantime, I'm off to revise a few presentations, and stick with solid ideas and
analogies, and maybe dropping the odd F-bomb when I want to make a point, just for
emphasis, because I know something you apparently don't:
</p>
        <p>
Shock makes a point because of the <em>contrast</em> to the rest of the talk, not
because of its inherent "edginess".
</p>
        <p>
Meanwhile, by all means, continue to be an idiot. You just make me look better by
comparison, for which I thank you.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=49e7a9d3-c222-45d7-a049-29b5a4b25cd3" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>The &amp;quot;controversy&amp;quot; continues</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,49e7a9d3-c222-45d7-a049-29b5a4b25cd3.aspx</guid>
      <link>http://blogs.tedneward.com/2009/06/14/The+Quotcontroversyquot+Continues.aspx</link>
      <pubDate>Sun, 14 Jun 2009 22:17:44 GMT</pubDate>
      <description>&lt;p&gt;
Apparently the Rails community isn't the only one pursuing that ephemeral goal of
&amp;quot;edginess&amp;quot;—another blatantly sexist presentation came off without a hitch,
this time at a Flash conference, and if anything, it was worse than the Rails/CouchDB
presentation. I excerpt a few choice tidbits &lt;a href="http://www.geekgirlsguide.com/blog/2009/06/11/98/prude_or_professional_by_courtney_remes" target="_blank"&gt;from
an eyewitness&lt;/a&gt; here, but be warned—if you're not comfortable with language, skip
the next block paragraph.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Yesterday's afternoon keynote is this guy named &lt;a href="http://flashbelt.com/#/speakers/hoss_gifford/"&gt;Hoss
Gifford&lt;/a&gt; — I believe his major claim to fame is that viral &amp;quot;spank the monkey&amp;quot;
thing that went around a few years back.&amp;#160; Highlights of his talk:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
He opens his keynote with one of those &lt;a href="http://www.ignitempls.org/"&gt;&amp;quot;Ignite&amp;quot;-esque
presentations&lt;/a&gt; — where you have 5-minutes and 20 slides to tell a story — and the
first and last are a close-up of a woman's lower half, her legs spread (wearing stilettos,
of course) and her shaved vagina visible through some see-thru panties that say &amp;quot;drink
me,&amp;quot; with Hoss's Photoshopped, upward-looking face placed below it. 
&lt;/li&gt;
&lt;li&gt;
He later demos a drawing tool he has created (admittedly with someone else's code)
and invites a woman to come up to try it.&amp;#160; After she sits back down, he points
out that in her doodles she's drawn a &amp;quot;cock.&amp;quot; 
&lt;/li&gt;
&lt;li&gt;
Then he decides he wants to give a try at using the tool to draw a &amp;quot;cock&amp;quot;
(he loves this word) — and draws a face, then a giant dick (he redraws it three times)
that ultimately cums all over the face. 
&lt;/li&gt;
&lt;li&gt;
A multitude of references to penises and lots of swearing — and also &amp;quot;If you
are easily offended, fuck you!&amp;quot; 
&lt;/li&gt;
&lt;li&gt;
And then, to top it off, a self-made flash movie of an animated woman's face, positioned
as if she's having sex with you, who gradually orgasms based on the speed of your
mouse movement on the page. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wow. Just... wow. To call this unprofessional smacks of calling Hitler a &amp;quot;socially
awkward individual&amp;quot;... or using a euphemism like &amp;quot;mild medical condition&amp;quot;
to refer to death. This is so far &amp;quot;over the line&amp;quot; that it's unbelievable.
Even Mr. Aimonetti's &amp;quot;CouchDB&amp;quot; presentation, as bad as it was, at least
tried to tie the analogy together in a meaningful, if offensive, way. This is just
male posturing at its worst. (I'm shocked Hoss didn't whip off his pants and demand
the women in the room bow down in worship to his obviously superior manhood.) 
&lt;/p&gt;
&lt;p&gt;
Fortunately, according to the source, the conference organizer seems to be pretty
responsive, so kudos to the one adult in the room, but....
&lt;/p&gt;
&lt;p&gt;
What's worse, apparently the presenter and more than a few of his pals are (in the
best traditions of assholery) blatantly unrepentant about the whole thing, claiming
the moral high ground in much the same way that the Rails idiots did—it's all in good
fun, if you don't find it funny you're a prude, and so on:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I checked Twitter (hashtag &lt;a href="http://search.twitter.com/search?q=%23flashbelt"&gt;#flashbelt&lt;/a&gt;)
to see what the responses were.&amp;#160; Here are some notable remarks:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://twitter.com/Fonx/status/2096740346"&gt;Fonx&lt;/a&gt; is reading the #flashbelt
rants on Hoss offending the ladies w/ a few swear words &amp;amp; a penis drawing - r
u really that prudish &amp;amp; sexist? 
&lt;/li&gt;
&lt;li&gt;
nthitz lol @hoss69 &amp;quot;If you are easily offended, fuck you&amp;quot; #flashbelt 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://twitter.com/livenootrac/status/2096075802"&gt;livenootrac&lt;/a&gt; Ladies
of #flashbelt , I am sorry for the Hoss preso, but in the flash community he gets
a pass, kinda like Don Rickles - that's just Hoss. 
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://twitter.com/CujoJpn/status/2096658483"&gt;CujoJpn&lt;/a&gt; @livenootrac And
there were many ladies at #flashbelt who were offended by Hoss' Preso some were thick
skinned and took it as is. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So, if you didn't like it then 
&lt;br /&gt;
a) you are a prude - and sexist (?) 
&lt;br /&gt;
b) fuck you 
&lt;br /&gt;
c) suck it because Hoss gets a pass here in the boy's club known as &amp;quot;the flash
community&amp;quot; and 
&lt;br /&gt;
d) you are a wimpy girl who isn't strong enough / man enough / &amp;quot;thick-skinned&amp;quot;
enough&amp;#160; to deal with it.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Even more... wow. Talk about justification and marginalization. Amazing.
&lt;/p&gt;
&lt;p&gt;
Before I figuratively smack this Hoss guy around the blog for a while, let's take
a brief moment for reflection—what's going on here? Why all the misogynistic presentations
recently? Is this reflective of a general trend in the programming industry? Of society
in general? Is the world coming to an end?
&lt;/p&gt;
&lt;p&gt;
A few possibilities present themselves:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The lack of women in the IT industry means there's nobody around to act as
a &amp;quot;gender filter&amp;quot; to keep things on an even keel.&lt;/strong&gt; In other words,
the genders constantly filter themselves based on the company they keep, and because
the boys who put these presentations together don't have female input, they simply
don't know where to draw the line for mixed company. This theory also presumes that
an industry that's made up primarily of women will also lack such a filter and &amp;quot;girls
will be girls&amp;quot; as a result. Unfortunately I have no good counterexamples at hand
to examine—anybody know of an industry populated primarily by women, and can weigh
in with experience there? The closest I get is my brief experience working in a restaurant
with an almost-all-woman serving staff, and from that brief experience, yep, the theory
holds. Solution? Easy: get more women in IT, and things will re-balance themselves
naturally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programmers are principally males who have no redeeming social skills.&lt;/strong&gt; In
other words, the industry gathers up exactly the kind of men who find objectifying
women and reveling in late-acquired testosterone overdoses to be gratifying, and this
kind of behavior is the result. If true, it leads to the conclusion that programmers
are no more evolved than the Navy sailors involved in the Tailhook scandal of a few
years ago. So go ahead, smack your wives and girlfriends around a little if they get
a little &amp;quot;uppity&amp;quot;, it's OK, 'cuz u r a l33t d00d. Personally? I find the
idea ludicrous—there is definitely a strong antisocial streak that runs through the
IT ecosystem (how many of you met your friends via World of Warcraft again?), but
like all stereotypes, there's some elements of truth to it, and a lot of exaggeration.
And frankly, anybody who believes in this theory is welcome to come with me to dinner
at a No Fluff Just Stuff show and meet the other speakers, and listen in on our &amp;quot;boys
club&amp;quot; conversations, including questions like, &amp;quot;Which movie best represents
the book it was made after?&amp;quot; and &amp;quot;If given a mandate to create a programming
language, what language would your language most resemble?&amp;quot;. Oh, and the odd
fart joke. We are boys, after all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We're hypersensitive to the subject right now.&lt;/strong&gt; In other words, these
kind of presentations have always been going on, and it's just that we notice them
now, in the same way that you notice a particular brand of car on the road a lot more
when you're thinking about buying that brand and model of car. Frankly, I don't buy
this argument—I've been to a lot of presentations over the past decade, and I've never
seen any that were anything like this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;This is the YouTube generation, with access to everything the Internet has
to offer, and this is &amp;quot;just how they do things&amp;quot;.&lt;/strong&gt; After all, how
much maturity, sexual discretion and adult behavior can we expect of the generation
that gave us &amp;quot;Girls Gone Wild&amp;quot; and its ilk? It's just a &amp;quot;generation
gap&amp;quot; thing, and we old fogies who didn't grow up with Internet porn just a browser-click
away just don't &amp;quot;get it&amp;quot;. Hmm.... somehow, I just don't buy it. Sure, there
may be some elements of this involved here (I'm &lt;em&gt;really&lt;/em&gt; curious to see what
all these &amp;quot;Girls Gone Wild&amp;quot; girls are going to say to their own daughters
in a decade or so...), but I think that's too easy an answer, and an eminently unhelpful
one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We have copycatters out there trying to follow the path of people they respect.&lt;/strong&gt; If
you're looking up at this Hoss character and thinking, &amp;quot;I want to be just like
him!&amp;quot;, you really should see a therapist and develop a sense of self, before
you find yourself without friends. Hoss gets a pass because of your misguided fan-boi
hero-worship. So does Paris Hilton. You want to be the Paris Hilton of your social
circle? Go for it. After all, she's highly respected and loved, right? Take a clue
from the next car wreck you drive past—everybody's slowing to look not because they
wish they were in the body bag, folks, but because we have a ghoulish fascination
with it. In the case of Ms. Hilton, that ghoulish fascination is with those who self-destruct
in spectacular fashion. (Me, I'd &lt;em&gt;love&lt;/em&gt; to be the fly on the wall at the Hoss
residence when he tries to explain this whole thing to his daughter or his date/girlfriend/wife,
if he ever finds one.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The presenters taking this tack are looking for an easy path to fame.&lt;/strong&gt; In
the grand traditions of Andrew Dice Clay (&amp;quot;Oh!&amp;quot;), the easiest way for a
presenter to &amp;quot;stand out&amp;quot; from the rest of the crowd of presenters is to
do something outrageous and call it &amp;quot;edgy&amp;quot;, and stake out a claim on the
edge of the civilization, rather than try to integrate with the rest of the crowd
and build something up slowly. Don Box has already claimed &amp;quot;HTTP is dead&amp;quot;,
I made the analogy between a technology and a military conflict, and Matt Aimonetti
claimed a data storage framework &amp;quot;performs like a pr0n star&amp;quot;, so what's
left but to stake out ground even further out on the fringe and just be misogynistic?
Fortunately, history suggests that people with content-free/shock-heavy presentations
(or even content-heavy/shock-heavy ones) don't go the distance, so to speak, and that
once there's nowhere more shocking left to go, the audience comes back to the content-heavy/shock-light
discussions and stays there for a while. Unfortunately, this means we're going to
have to suffer through somebody's &amp;quot;Live YouPorn filming&amp;quot; talk first, which
I'm &lt;em&gt;not&lt;/em&gt; looking forward to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And now for the smacking around... but you know, I suddenly realize that the volume
of comments on the original post leave with nothing to do or say that's not already
being said, so to just &amp;quot;pile on&amp;quot; would only serve to let me vent, and I
have other outlets for that. But it would be inappropriate to just &amp;quot;walk away&amp;quot;,
so to speak, so with that in mind....
&lt;/p&gt;
&lt;p&gt;
Hoss, you're an idiot. Like any sprinter, you're going to head up the pack for a bit,
but soon enough, your &amp;quot;shtick&amp;quot; is going to flame out and you'll be left
behind with all the other &amp;quot;shock jocks&amp;quot; of the 80's who found their material
unwelcome after a while. So enjoy the spotlight (such as it is) while you can. In
the meantime, I'm off to revise a few presentations, and stick with solid ideas and
analogies, and maybe dropping the odd F-bomb when I want to make a point, just for
emphasis, because I know something you apparently don't:
&lt;/p&gt;
&lt;p&gt;
Shock makes a point because of the &lt;em&gt;contrast&lt;/em&gt; to the rest of the talk, not
because of its inherent &amp;quot;edginess&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
Meanwhile, by all means, continue to be an idiot. You just make me look better by
comparison, for which I thank you.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=49e7a9d3-c222-45d7-a049-29b5a4b25cd3" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,49e7a9d3-c222-45d7-a049-29b5a4b25cd3.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Mac OS</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Social</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=dd85708f-48d8-47dc-a9c6-cc4a1287ad31</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,dd85708f-48d8-47dc-a9c6-cc4a1287ad31.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,dd85708f-48d8-47dc-a9c6-cc4a1287ad31.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=dd85708f-48d8-47dc-a9c6-cc4a1287ad31</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <blockquote>
          <p>
            <strong>Update:</strong> See below, but I wanted to include the text Mike Abercrombie
(DM's owner) posted as a comment to this post, in the body of the blog post itself. <em>"Ted
- All of us at DevelopMentor greatly appreciate your admiration. We're also grateful
for your contributions to DevelopMentor when you were part of our staff. However,
all of us that work here, especially our technical staff that write and delivery our
courses today, would appreciate it if you would check your sources before writing
our eulogy. DevelopMentor is open for business and delivering courses this week and
we intend to remain doing so."</em> Duly noted, Mike. Apology offered (and hopefully
accepted).
</p>
        </blockquote>
        <p>
An email crossed my desk today, announcing that DevelopMentor, home to so many good
people and fond memories, has (at least temporarily) closed its doors.
</p>
        <p>
I admit to a small, carefully-cushioned place in my heart where I mourn over this.
</p>
        <p>
DevelopMentor was such a transcendent place for me. Much, if not most or all, of the
acceleration that came in my career came not only while I was there, but <em>because</em> I
was there.
</p>
        <p>
          <em>So</em> much of my speaking persona and skill I owe to Ron Sumida, who took a
half-baked neophyte of intermediate speaking skill, and in an eight-hour marathon
session still referred to in my mental memoirs as my "Night with Scary Ron",
shaped me and taught me tricks about speaking that I continue to use to this day.
That I got to know him as a friend and confidant later still to this day ranks as
one of my greatest blessings.
</p>
        <p>
I remember my first DM Instructor Retreat, where I met so many of the names I'd read
about or heard about, and feeling "Oh, my God" fanboy-ish. I remember Tim
Ewald giving a talk on transactions at that retreat that left me agape—I seriously
didn't understand half of what he was saying, and rather than feeling overwhelmed
or ashamed, I remember distinctly thinking, "Wow—I have found a home where I
can learn SO much more." It was like waking up one morning to find that your
writing workshop group suddenly included Neal Stephenson, Stephen Pinker, C.S. Lewis
and Ernest Hemingway. (Yes, I know those last two are dead. Work with me here.)
</p>
        <p>
I remember the day that Lorie (the ops manager at the time) called me to say that
Don Box wanted me to work with him on the C# course. I was convinced that she'd called
the wrong Ted, meaning instead to reach for Ted Pattison in her Rolodex and coming
up a few letters shy. She tartly informed me, "No, I know exactly who I'm talking
to, and are you interested or not?" How could I refuse? Help the Diety of COM
write DM's flagship course on Microsoft's flagship technology for the next decade?
"Hmm...", I say out loud, not because I needed time to think about it, but
because a thread in the back of my head says, "Is there <em>any</em> scenario
here where I say no?"
</p>
        <p>
I still fondly recall doing a Guerilla .NET at the Torrance Hilton shortly after the
.NET 1.0 release, and having a conversation with Don in my hotel room later that night;
that was when he told me "Microsoft is working on an open-source version of the
CLR". I was stunned—I had no idea that said version would factor pretty largely
in my life later. But it opened my eyes, in a very practical way, to how deeply-connected
DevelopMentor was to Microsoft, and how that could play out in a direct fashion.
</p>
        <p>
When Peter Drayton joined, he asked me to do a quick review pass on the reference
section of his <em>C# in a Nutshell</em>, and I agreed because Peter was a good guy
(and somebody I'd hoped would become a friend), and wanted to see the book do well.
That went from informal review to formal review to "well, could you maybe make
it an editing pass?" to "Would you like to write a few chapters?" to
"Well, let's sign you up as a co-author...". That project is what introduced
me to John Osborn, which in turn led him to call me one day and say, "Some guys
at Microsoft are working on an open-source version of the CLR, and would like to have
a 'professional writer' help them write a book on it. Interested?" That led to <em>SSCLI
Internals</em>, working with David Stutz, and wow, did I learn a helluvalot from <em>that</em> project,
too.
</p>
        <p>
          <em>Effective Enterprise Java</em> came through DevelopMentor, thanks again to Don
Box, who introduced me to the folks at Addison-Wesley that put the contract (and Scott
Meyers, another blessing) in front of me.
</p>
        <p>
DM got me my start in the conference circuit, as well. In 2002, John Lam pinged me
over email—he'd recently become track chair for Connections down in Orlando, and was
I interested in speaking there? I was such a newbie to the whole idea, but having
taught classes roughly twice every month, I wasn't worried about the speaking part,
but the rest of the process. John walked me through the process, and in doing so,
set me down a path that would almost completely redefine my career within a year or
so.
</p>
        <p>
Even my Java chops got built up—the head of our Java curriculum was Stu Halloway (recently
of Clojure fame), and between him, Kevin Jones, Si Horrell, Brian Maso and Owen Tallman,
man, did I feel simultaneously like a small child among giants and like a kid in a
candy store. Every time I turned around, they'd discovered something new about the
Java platform that floored me. Bob Beauchemin has forgotten more about databases in
general than I will ever learn, and he had some insights on the intersection of Java
+ databases that still hang with me today.
</p>
        <p>
And my start with No Fluff Just Stuff came through DevelopMentor, too. Jason Whittington
heard through a mutual friend (Erik Hatcher, of Ant fame) about this cool little conference
being held in Denver, and maybe I should look into it. That led to an email intro
to Jay Zimmerman, a dinner together while I was teaching in Denver a few weeks later,
and before I knew it, I was on the Denver NFJS schedule, including the speaker panel,
where I uttered the then-infamous line, "Swing sucks. Get over it."
</p>
        <p>
DevelopMentor, you shaped my career—and my life—in so many ways, you will always be
a source of pleasant memories and a group of friends and acquaintances that I would
never have had otherwise. Thank you <em>so</em> much.
</p>
        <p>
Rest in peace.
</p>
        <p>
          <strong>Update:</strong> Well, as it turns out, I have to rescind at least part of
my eulogy, as the post itself generated quite a stir—the folks at DevelopMentor were
pretty quick to email me, pointing out that they're still alive and well. In fact,
as one of them (a friend of mine still working there) put it, "We were all kinda
surprised when we came to work this morning and discovered that we could go home."
Fortunately, the DevelopMentor folks were pretty gracious about what could've been
a <em>very</em> ugly situation, and I apologize for to them for the misunderstanding—all
I can say is that my "source" must've also been mistaken, and I'm glad that
we're all still good. And lest it need to be said out loud, I <em>heartily</em> want
nothing but the best for DM, and hope that I never have to write this message again.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=dd85708f-48d8-47dc-a9c6-cc4a1287ad31" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>A eulogy: DevelopMentor, RIP</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,dd85708f-48d8-47dc-a9c6-cc4a1287ad31.aspx</guid>
      <link>http://blogs.tedneward.com/2009/06/01/A+Eulogy+DevelopMentor+RIP.aspx</link>
      <pubDate>Mon, 01 Jun 2009 06:32:07 GMT</pubDate>
      <description>&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; See below, but I wanted to include the text Mike Abercrombie
(DM's owner) posted as a comment to this post, in the body of the blog post itself. &lt;em&gt;&amp;quot;Ted
- All of us at DevelopMentor greatly appreciate your admiration. We're also grateful
for your contributions to DevelopMentor when you were part of our staff. However,
all of us that work here, especially our technical staff that write and delivery our
courses today, would appreciate it if you would check your sources before writing
our eulogy. DevelopMentor is open for business and delivering courses this week and
we intend to remain doing so.&amp;quot;&lt;/em&gt; Duly noted, Mike. Apology offered (and hopefully
accepted).
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
An email crossed my desk today, announcing that DevelopMentor, home to so many good
people and fond memories, has (at least temporarily) closed its doors.
&lt;/p&gt;
&lt;p&gt;
I admit to a small, carefully-cushioned place in my heart where I mourn over this.
&lt;/p&gt;
&lt;p&gt;
DevelopMentor was such a transcendent place for me. Much, if not most or all, of the
acceleration that came in my career came not only while I was there, but &lt;em&gt;because&lt;/em&gt; I
was there.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;So&lt;/em&gt; much of my speaking persona and skill I owe to Ron Sumida, who took a
half-baked neophyte of intermediate speaking skill, and in an eight-hour marathon
session still referred to in my mental memoirs as my &amp;quot;Night with Scary Ron&amp;quot;,
shaped me and taught me tricks about speaking that I continue to use to this day.
That I got to know him as a friend and confidant later still to this day ranks as
one of my greatest blessings.
&lt;/p&gt;
&lt;p&gt;
I remember my first DM Instructor Retreat, where I met so many of the names I'd read
about or heard about, and feeling &amp;quot;Oh, my God&amp;quot; fanboy-ish. I remember Tim
Ewald giving a talk on transactions at that retreat that left me agape—I seriously
didn't understand half of what he was saying, and rather than feeling overwhelmed
or ashamed, I remember distinctly thinking, &amp;quot;Wow—I have found a home where I
can learn SO much more.&amp;quot; It was like waking up one morning to find that your
writing workshop group suddenly included Neal Stephenson, Stephen Pinker, C.S. Lewis
and Ernest Hemingway. (Yes, I know those last two are dead. Work with me here.)
&lt;/p&gt;
&lt;p&gt;
I remember the day that Lorie (the ops manager at the time) called me to say that
Don Box wanted me to work with him on the C# course. I was convinced that she'd called
the wrong Ted, meaning instead to reach for Ted Pattison in her Rolodex and coming
up a few letters shy. She tartly informed me, &amp;quot;No, I know exactly who I'm talking
to, and are you interested or not?&amp;quot; How could I refuse? Help the Diety of COM
write DM's flagship course on Microsoft's flagship technology for the next decade?
&amp;quot;Hmm...&amp;quot;, I say out loud, not because I needed time to think about it, but
because a thread in the back of my head says, &amp;quot;Is there &lt;em&gt;any&lt;/em&gt; scenario
here where I say no?&amp;quot;
&lt;/p&gt;
&lt;p&gt;
I still fondly recall doing a Guerilla .NET at the Torrance Hilton shortly after the
.NET 1.0 release, and having a conversation with Don in my hotel room later that night;
that was when he told me &amp;quot;Microsoft is working on an open-source version of the
CLR&amp;quot;. I was stunned—I had no idea that said version would factor pretty largely
in my life later. But it opened my eyes, in a very practical way, to how deeply-connected
DevelopMentor was to Microsoft, and how that could play out in a direct fashion.
&lt;/p&gt;
&lt;p&gt;
When Peter Drayton joined, he asked me to do a quick review pass on the reference
section of his &lt;em&gt;C# in a Nutshell&lt;/em&gt;, and I agreed because Peter was a good guy
(and somebody I'd hoped would become a friend), and wanted to see the book do well.
That went from informal review to formal review to &amp;quot;well, could you maybe make
it an editing pass?&amp;quot; to &amp;quot;Would you like to write a few chapters?&amp;quot; to
&amp;quot;Well, let's sign you up as a co-author...&amp;quot;. That project is what introduced
me to John Osborn, which in turn led him to call me one day and say, &amp;quot;Some guys
at Microsoft are working on an open-source version of the CLR, and would like to have
a 'professional writer' help them write a book on it. Interested?&amp;quot; That led to &lt;em&gt;SSCLI
Internals&lt;/em&gt;, working with David Stutz, and wow, did I learn a helluvalot from &lt;em&gt;that&lt;/em&gt; project,
too.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Effective Enterprise Java&lt;/em&gt; came through DevelopMentor, thanks again to Don
Box, who introduced me to the folks at Addison-Wesley that put the contract (and Scott
Meyers, another blessing) in front of me.
&lt;/p&gt;
&lt;p&gt;
DM got me my start in the conference circuit, as well. In 2002, John Lam pinged me
over email—he'd recently become track chair for Connections down in Orlando, and was
I interested in speaking there? I was such a newbie to the whole idea, but having
taught classes roughly twice every month, I wasn't worried about the speaking part,
but the rest of the process. John walked me through the process, and in doing so,
set me down a path that would almost completely redefine my career within a year or
so.
&lt;/p&gt;
&lt;p&gt;
Even my Java chops got built up—the head of our Java curriculum was Stu Halloway (recently
of Clojure fame), and between him, Kevin Jones, Si Horrell, Brian Maso and Owen Tallman,
man, did I feel simultaneously like a small child among giants and like a kid in a
candy store. Every time I turned around, they'd discovered something new about the
Java platform that floored me. Bob Beauchemin has forgotten more about databases in
general than I will ever learn, and he had some insights on the intersection of Java
+ databases that still hang with me today.
&lt;/p&gt;
&lt;p&gt;
And my start with No Fluff Just Stuff came through DevelopMentor, too. Jason Whittington
heard through a mutual friend (Erik Hatcher, of Ant fame) about this cool little conference
being held in Denver, and maybe I should look into it. That led to an email intro
to Jay Zimmerman, a dinner together while I was teaching in Denver a few weeks later,
and before I knew it, I was on the Denver NFJS schedule, including the speaker panel,
where I uttered the then-infamous line, &amp;quot;Swing sucks. Get over it.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
DevelopMentor, you shaped my career—and my life—in so many ways, you will always be
a source of pleasant memories and a group of friends and acquaintances that I would
never have had otherwise. Thank you &lt;em&gt;so&lt;/em&gt; much.
&lt;/p&gt;
&lt;p&gt;
Rest in peace.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Well, as it turns out, I have to rescind at least part of
my eulogy, as the post itself generated quite a stir—the folks at DevelopMentor were
pretty quick to email me, pointing out that they're still alive and well. In fact,
as one of them (a friend of mine still working there) put it, &amp;quot;We were all kinda
surprised when we came to work this morning and discovered that we could go home.&amp;quot;
Fortunately, the DevelopMentor folks were pretty gracious about what could've been
a &lt;em&gt;very&lt;/em&gt; ugly situation, and I apologize for to them for the misunderstanding—all
I can say is that my &amp;quot;source&amp;quot; must've also been mistaken, and I'm glad that
we're all still good. And lest it need to be said out loud, I &lt;em&gt;heartily&lt;/em&gt; want
nothing but the best for DM, and hope that I never have to write this message again.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=dd85708f-48d8-47dc-a9c6-cc4a1287ad31" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,dd85708f-48d8-47dc-a9c6-cc4a1287ad31.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Reading</category>
      <category>Scala</category>
      <category>Security</category>
      <category>Visual Basic</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=425494e3-309e-49a7-b96c-45178dd4165b</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,425494e3-309e-49a7-b96c-45178dd4165b.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,425494e3-309e-49a7-b96c-45178dd4165b.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=425494e3-309e-49a7-b96c-45178dd4165b</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, NFJS alum and buddy Dion Almaer <a href="http://almaer.com/blog/browser-storage-do-we-need-sql-or-would-a-json-approach-be-better">questioned</a> the
widespread, almost default, usage of a relational database for all things storage
related:
</p>
        <blockquote>
          <blockquote>
            <p>
Ian Hickson: “I expect I’ll be reverse-engineering SQLite and speccing that, if nothing
better is picked first. As it is, people are starting to use the database feature
in actual Web apps (e.g. mobile GMail, iirc).” 
</p>
          </blockquote>
          <p>
When I read that comment to Vlad’s <a href="http://blog.vlad1.com/2009/04/06/html5-web-storage-and-sql/">post
on HTML 5 Web Storage</a> I gulped. This would basically make SQLite the HTML 5 for
storage in the browser. You would have to be a little crazy to re-write the exact
semantics (including bugs) of SQLite and its dialect. What if you couldn’t use the
public domain code?
</p>
          <p>
Gears lead out strong with making a relational database part of the toolbox for developers.
It embedded its own SQLite, in fact one that was customized to have the very cool <a href="http://code.google.com/apis/gears/api_database.html">full
text search</a> ability. However, this brings up the point of “which SQLite do you
standardize on?”
</p>
          <p>
The beauty of using SQL and SQLite is that many developers already know it. RDBMS
has been mainstream for donkey’s years; we have tools to manage SQL, to view the model,
and to tweak for performance. It has gone through the test of time.
</p>
          <p>
However, SQL has always been at odds with many developers. Ted Neward brought up ORM
as the <a href="http://stackoverflow.com/questions/404083/is-orm-still-the-vietnam-of-computer-science">vietnam
of computer science</a> (which is going a touch far ;). I was just lamenting with
a friend at Microsoft on how developers spend 90% of their time munging data. Our
life is one of transformations, and that is why I am interested in a world of JavaScript
on client and server AND database. We aren’t there yet, but hopefully we can <a href="https://wiki.mozilla.org/ServerJS">make
progress</a>.
</p>
          <p>
One of Vlad’s main questions is “Is SQL the right API for Web developers?” and it
is a valid one. I quickly found that for most of my tasks with the DB I just wanted
to deal with JSON and hence created a wrapper <a href="http://almaer.com/blog/gearsdb-a-simple-abstraction-for-the-google-gears-database">GearsDB</a> to
let me insert/update/select/delete the database with a JSON view of the world. You
probably wouldn’t want to do this on large production applications for performance
reasons, but it works well for me.
</p>
          <p>
Now a days, we have interesting APIs such as <a href="http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/">JSONQuery</a> which <a href="http://sitepen.com/labs/persevere.php">Persevere</a> (and
other databases) use. I would love to see Firefox and other browsers support something
like this and let us live in JSON throughout the stack. It feels so much more Webby,
and also, some of the reasons that made us stay with SQL don’t matter as much in the
client side world. For example, when OODBMS took off in some Enterprises, I remember
having all of these Versant to Oracle exports just so people could report on the darn
data. On the client the database is used for a very different reason (local storage)
so lets use JSON!
</p>
          <p>
That being said, at this point there are applications such as Gmail, MySpace search,
Zoho, and many iPhone Web applications that use the SQL storage in browsers. In fact,
if we had the API in Firefox I would have Bespin using it right now! We had a version
of this that abstracted on top of stores, but it was a pain. I would love to just
use HTML 5 storage and be done.
</p>
          <p>
So, I think that Firefox should actually support this for practical reasons (and we
have SQLite right there!) but should push JSON APIs and let developers decide. I hope
that JSON wins, you? I also hope that Hixie doesn’t have to spec SQLite :/
</p>
        </blockquote>
        <p>
Dion's right when he says "developers spend 90% of their time munging data"
and that "Our life is one of transformations", but I think he's being short-sighted
and entirely narrow-minded when he says, "I am interested in a world of JavaScript
on client and server AND database." Dion, I love you, man, but you're falling
prey to the Fallacy of the One True Language. JavaScript (or ECMAScript, as its official
name is given) is an interesting and powerful language, but why do you want to force
your biases and perceptions on the rest of the world, man? You're being just as bad
as the C++ or Java guys were in their heyday—remember when Java stored procedures
were all the rage because "everybody knows that Java is the wave of the future"?
</p>
        <p>
The fact is, from where I stand, there is no one storage solution or language solution
or user-interface solution that is the Right Thing To Do in all situations. Not even
inside the browser. There will be situations where a SQLite is the Right Thing, and
other situations where a document-oriented JSON-like or CouchDB-like thing will be
the Right Thing, and trying to force-feed one into a situation that's best solved
by the other is a bad idea.
</p>
        <p>
Dion alludes to my article about the Vietnam of Computer Science, but in fact, his
suggestion charges right into another quagmire—how long before somebody starts trying
to create a JSON-to-RDBMS adaption layer? Or JSON-to-CouchDB? Or things equally ridiculous?
The fact is, data has three fundamentally different "shapes" to it, and
trying to pound data from one shape into the other has all the efficacy and elegance
to it just as much as pounding round pegs into square holes does. Dion even alludes
to this with this paragraph:
</p>
        <blockquote>
          <p>
One of Vlad’s main questions is “Is SQL the right API for Web developers?” and it
is a valid one. I quickly found that for most of my tasks with the DB I just wanted
to deal with JSON and hence created a wrapper <a href="http://almaer.com/blog/gearsdb-a-simple-abstraction-for-the-google-gears-database">GearsDB</a> to
let me insert/update/select/delete the database with a JSON view of the world. You
probably wouldn’t want to do this on large production applications for performance
reasons, but it works well for me.
</p>
        </blockquote>
        <p>
JSON is certainly an attractive representation format for ECMAScript objects, thanks
to its fundamental roots in ECMAScript's object literal syntax, and the powerful/dangerous
eval() functionality offered by ECMAScript environments, but JSON also lacks a number
of things a SQL-based dialect has, including a powerful query syntax for selecting
individual and subsets of entities from the whole, which only becomes more and more
necessary as the data base itself gets larger and larger. (Anybody who suggests that
a local browser store would only remain within a certain size is clearly not thinking
further ahead than the current day. Look at how cookies are outrageously abused as
local storage for a lot of sites, or how Viewstate was abused in early ASP.NET apps—if
you give the HTML/front-end developer a local storage mechanism, they will use it,
and use it as far and as long and as hard as they can.) On top of which, JSON simply
doesn't have the years of solid backing behind it than a SQL-based storage format
does. And so on, and so on, and so on.
</p>
        <p>
Ironically, just as JSON is a scheme for representing native objects in some kind
of data format (in this case, a plain-text one), developers casually ignore the idea
of storing objects in a native data format with all of the other bells-and-whistles
that a database provides. Naturally, I'm referring to the idea of an object database—if
JSON is appropriate for storing certain kinds of data in certain scenarios, then why
isn't it appropriate to consider a native object database for some of those same certain
kinds of scenarios? Not that I have anything against a JSON-based database scenario—in
fact, I can easily imagine a JSON database that indexes the properties of the stored
objects and takes ECMAScript functions as "native queries" in the same way
that db4o doe. But let's stop with the repeated attempts at "one size fits all",
and just accept that the world is a polyglot world, and that no one language—or data
storage format, or data access API—will be the Right Thing To Do for all scenarios.
Each language, format, API or tool has a reason to exist, a particular way it looks
at the world, and optimizes itself to work best when used in that particular style.
Trying to force one into the terms of the other is the road to another Computer Science
quagmire.
</p>
        <p>
Viva la Polyglot!
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=425494e3-309e-49a7-b96c-45178dd4165b" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>&amp;quot;From each, according to its abilities....&amp;quot;</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,425494e3-309e-49a7-b96c-45178dd4165b.aspx</guid>
      <link>http://blogs.tedneward.com/2009/04/20/quotFrom+Each+According+To+Its+Abilitiesquot.aspx</link>
      <pubDate>Mon, 20 Apr 2009 19:56:20 GMT</pubDate>
      <description>&lt;p&gt;
Recently, NFJS alum and buddy Dion Almaer &lt;a href="http://almaer.com/blog/browser-storage-do-we-need-sql-or-would-a-json-approach-be-better"&gt;questioned&lt;/a&gt; the
widespread, almost default, usage of a relational database for all things storage
related:
&lt;/p&gt;
&lt;blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
Ian Hickson: “I expect I’ll be reverse-engineering SQLite and speccing that, if nothing
better is picked first. As it is, people are starting to use the database feature
in actual Web apps (e.g. mobile GMail, iirc).” 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
When I read that comment to Vlad’s &lt;a href="http://blog.vlad1.com/2009/04/06/html5-web-storage-and-sql/"&gt;post
on HTML 5 Web Storage&lt;/a&gt; I gulped. This would basically make SQLite the HTML 5 for
storage in the browser. You would have to be a little crazy to re-write the exact
semantics (including bugs) of SQLite and its dialect. What if you couldn’t use the
public domain code?
&lt;/p&gt;
&lt;p&gt;
Gears lead out strong with making a relational database part of the toolbox for developers.
It embedded its own SQLite, in fact one that was customized to have the very cool &lt;a href="http://code.google.com/apis/gears/api_database.html"&gt;full
text search&lt;/a&gt; ability. However, this brings up the point of “which SQLite do you
standardize on?”
&lt;/p&gt;
&lt;p&gt;
The beauty of using SQL and SQLite is that many developers already know it. RDBMS
has been mainstream for donkey’s years; we have tools to manage SQL, to view the model,
and to tweak for performance. It has gone through the test of time.
&lt;/p&gt;
&lt;p&gt;
However, SQL has always been at odds with many developers. Ted Neward brought up ORM
as the &lt;a href="http://stackoverflow.com/questions/404083/is-orm-still-the-vietnam-of-computer-science"&gt;vietnam
of computer science&lt;/a&gt; (which is going a touch far ;). I was just lamenting with
a friend at Microsoft on how developers spend 90% of their time munging data. Our
life is one of transformations, and that is why I am interested in a world of JavaScript
on client and server AND database. We aren’t there yet, but hopefully we can &lt;a href="https://wiki.mozilla.org/ServerJS"&gt;make
progress&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
One of Vlad’s main questions is “Is SQL the right API for Web developers?” and it
is a valid one. I quickly found that for most of my tasks with the DB I just wanted
to deal with JSON and hence created a wrapper &lt;a href="http://almaer.com/blog/gearsdb-a-simple-abstraction-for-the-google-gears-database"&gt;GearsDB&lt;/a&gt; to
let me insert/update/select/delete the database with a JSON view of the world. You
probably wouldn’t want to do this on large production applications for performance
reasons, but it works well for me.
&lt;/p&gt;
&lt;p&gt;
Now a days, we have interesting APIs such as &lt;a href="http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/"&gt;JSONQuery&lt;/a&gt; which &lt;a href="http://sitepen.com/labs/persevere.php"&gt;Persevere&lt;/a&gt; (and
other databases) use. I would love to see Firefox and other browsers support something
like this and let us live in JSON throughout the stack. It feels so much more Webby,
and also, some of the reasons that made us stay with SQL don’t matter as much in the
client side world. For example, when OODBMS took off in some Enterprises, I remember
having all of these Versant to Oracle exports just so people could report on the darn
data. On the client the database is used for a very different reason (local storage)
so lets use JSON!
&lt;/p&gt;
&lt;p&gt;
That being said, at this point there are applications such as Gmail, MySpace search,
Zoho, and many iPhone Web applications that use the SQL storage in browsers. In fact,
if we had the API in Firefox I would have Bespin using it right now! We had a version
of this that abstracted on top of stores, but it was a pain. I would love to just
use HTML 5 storage and be done.
&lt;/p&gt;
&lt;p&gt;
So, I think that Firefox should actually support this for practical reasons (and we
have SQLite right there!) but should push JSON APIs and let developers decide. I hope
that JSON wins, you? I also hope that Hixie doesn’t have to spec SQLite :/
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Dion's right when he says &amp;quot;developers spend 90% of their time munging data&amp;quot;
and that &amp;quot;Our life is one of transformations&amp;quot;, but I think he's being short-sighted
and entirely narrow-minded when he says, &amp;quot;I am interested in a world of JavaScript
on client and server AND database.&amp;quot; Dion, I love you, man, but you're falling
prey to the Fallacy of the One True Language. JavaScript (or ECMAScript, as its official
name is given) is an interesting and powerful language, but why do you want to force
your biases and perceptions on the rest of the world, man? You're being just as bad
as the C++ or Java guys were in their heyday—remember when Java stored procedures
were all the rage because &amp;quot;everybody knows that Java is the wave of the future&amp;quot;?
&lt;/p&gt;
&lt;p&gt;
The fact is, from where I stand, there is no one storage solution or language solution
or user-interface solution that is the Right Thing To Do in all situations. Not even
inside the browser. There will be situations where a SQLite is the Right Thing, and
other situations where a document-oriented JSON-like or CouchDB-like thing will be
the Right Thing, and trying to force-feed one into a situation that's best solved
by the other is a bad idea.
&lt;/p&gt;
&lt;p&gt;
Dion alludes to my article about the Vietnam of Computer Science, but in fact, his
suggestion charges right into another quagmire—how long before somebody starts trying
to create a JSON-to-RDBMS adaption layer? Or JSON-to-CouchDB? Or things equally ridiculous?
The fact is, data has three fundamentally different &amp;quot;shapes&amp;quot; to it, and
trying to pound data from one shape into the other has all the efficacy and elegance
to it just as much as pounding round pegs into square holes does. Dion even alludes
to this with this paragraph:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
One of Vlad’s main questions is “Is SQL the right API for Web developers?” and it
is a valid one. I quickly found that for most of my tasks with the DB I just wanted
to deal with JSON and hence created a wrapper &lt;a href="http://almaer.com/blog/gearsdb-a-simple-abstraction-for-the-google-gears-database"&gt;GearsDB&lt;/a&gt; to
let me insert/update/select/delete the database with a JSON view of the world. You
probably wouldn’t want to do this on large production applications for performance
reasons, but it works well for me.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
JSON is certainly an attractive representation format for ECMAScript objects, thanks
to its fundamental roots in ECMAScript's object literal syntax, and the powerful/dangerous
eval() functionality offered by ECMAScript environments, but JSON also lacks a number
of things a SQL-based dialect has, including a powerful query syntax for selecting
individual and subsets of entities from the whole, which only becomes more and more
necessary as the data base itself gets larger and larger. (Anybody who suggests that
a local browser store would only remain within a certain size is clearly not thinking
further ahead than the current day. Look at how cookies are outrageously abused as
local storage for a lot of sites, or how Viewstate was abused in early ASP.NET apps—if
you give the HTML/front-end developer a local storage mechanism, they will use it,
and use it as far and as long and as hard as they can.) On top of which, JSON simply
doesn't have the years of solid backing behind it than a SQL-based storage format
does. And so on, and so on, and so on.
&lt;/p&gt;
&lt;p&gt;
Ironically, just as JSON is a scheme for representing native objects in some kind
of data format (in this case, a plain-text one), developers casually ignore the idea
of storing objects in a native data format with all of the other bells-and-whistles
that a database provides. Naturally, I'm referring to the idea of an object database—if
JSON is appropriate for storing certain kinds of data in certain scenarios, then why
isn't it appropriate to consider a native object database for some of those same certain
kinds of scenarios? Not that I have anything against a JSON-based database scenario—in
fact, I can easily imagine a JSON database that indexes the properties of the stored
objects and takes ECMAScript functions as &amp;quot;native queries&amp;quot; in the same way
that db4o doe. But let's stop with the repeated attempts at &amp;quot;one size fits all&amp;quot;,
and just accept that the world is a polyglot world, and that no one language—or data
storage format, or data access API—will be the Right Thing To Do for all scenarios.
Each language, format, API or tool has a reason to exist, a particular way it looks
at the world, and optimizes itself to work best when used in that particular style.
Trying to force one into the terms of the other is the road to another Computer Science
quagmire.
&lt;/p&gt;
&lt;p&gt;
Viva la Polyglot!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=425494e3-309e-49a7-b96c-45178dd4165b" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,425494e3-309e-49a7-b96c-45178dd4165b.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Scala</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=f3062e21-fcf4-40f0-ac1f-8e212c931667</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,f3062e21-fcf4-40f0-ac1f-8e212c931667.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,f3062e21-fcf4-40f0-ac1f-8e212c931667.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=f3062e21-fcf4-40f0-ac1f-8e212c931667</wfw:commentRss>
      <slash:comments>7</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The <a href="http://www.simple-talk.com/newsletter-archive/">Simple-Talk newsletter</a> is
a monthly e-zine that the folks over at Red Gate Software (makers of some pretty cool
toys, including their ANTS Profiler, and recent inheritors of the Reflector utility
legacy) produce, usually to good effect.
</p>
        <p>
But <a href="http://www.simple-talk.com/newsletter/v.aspx?n=144">this month</a> carried
with it an interesting editorial piece, which I reproduce in its entirety here:
</p>
        <blockquote>
          <p>
When the market is slack, nothing succeeds better at tightening it up than promoting
serial group-panic within the community. As an example of this, a wave of multi-core
panic spread across the Internet about 18 months ago. IT organizations, it was said,
urgently had to improve application performance by an order of magnitude in order
to cope with rising demand. We wouldn't be able to meet that need because we were
at the "end of the road" with regard to step changes in processor power
and clock speed. Multi-core technology was the only sure route to improving the speed
of applications but, unfortunately, our current "serial" programming techniques,
and the limited multithreading capabilities of our programming languages and programmers,
left us ill-equipped to exploit it. Multi-core mania gripped the industry.
</p>
          <p>
However, the fever was surprisingly short-lived. Intel's "largest open-source
effort ever" to provide a standard tool for writing multi-threaded code, caused
little more than a ripple of interest. Various books, rushed out while the temperature
soared, advocated the urgent need for new "multi-core-friendly" programming
models, involving such things as "software pipelines". Interesting as they
undoubtedly are, they sit stolidly on bookshelves, unread.
</p>
          <p>
The truth is that it's simply not a big issue for the majority of people. Writing
truly "concurrent" applications in languages such as C# is difficult, as
you get very little help from the language. It means getting involved with low-level
concurrency primitives, such as lock statements and so on.
</p>
          <p>
Many programmers lack the skills to do this, but more pertinently lack the need. Increasingly,
programmers work in a web environment. As long as these web applications are deployed
to a load-balanced web farm, then page requests can be handled in parallel so all
available cores will be used efficiently without the need for the programmer to be
concerned with fine-grained parallelism.
</p>
          <p>
Furthermore, the SQL Server engine behind these web applications is intrinsically
"parallel", and can handle and use effectively about as many cores as you
care to throw at it. SQL itself is a declarative rather than procedural language,
so it is fundamentally concurrent.
</p>
          <p>
A minority of programmers, for example games programmers or those who deal with "embarrassingly
parallel" desktop applications such as Photoshop, do need to start working with
the current tools and 'low-level' coding techniques that will allow them to exploit
multi-core technology. Although currently perceived to be more of "academic"
interest, concurrent languages such as Erlang, and concurrency techniques such as
"software transactional memory", may yet prove to be significant.
</p>
          <p>
For most programmers and for most web applications, however, the multi-core furore
is a storm in a teacup; it's just not relevant. The web and database platforms already
cope with concurrency requirements. We are already doing it.
</p>
        </blockquote>
        <p>
My <em>hope</em> is that this newsletter, sent on April 1st, was intended to be a
joke. Having said that, I can’t find any verbage in the email that suggests that it
is, in which case, I have to treat it as a legitimate editorial. 
</p>
        <p>
And frankly, I think it’s all crap. 
</p>
        <p>
It's dangerously ostrichian in nature—it encourages developers to simply bury their
heads in the sand and ignore the freight train that's coming their way. Permit me,
if you will, a few minutes of your time, that I may be allowed to go through and demonstrate
the reasons why I say this.
</p>
        <p>
To begin ...
</p>
        <blockquote>
          <p>
When the market is slack, nothing succeeds better at tightening it up than promoting
serial group-panic within the community. As an example of this, a wave of multi-core
panic spread across the Internet about 18 months ago. IT organizations, it was said,
urgently had to improve application performance by an order of magnitude in order
to cope with rising demand. [...] Multi-core mania gripped the industry.
</p>
        </blockquote>
        <p>
Point of fact: The “panic” cited here didn’t start about 18 months ago, it started
with Herb Sutter’s most excellent (and not only highly recommended but highly required)
article, “The Free Lunch is Over: A Fundamental Turn Toward Concurrency in Software”,
appeared in the pages of Dr. Dobb’s Journal in March of 2005. (Herb’s website notes
that “a much briefer version under the title “The Concurrency Revolution” appeared
in C/C++ User’s Journal” the previous month.) And the panic itself wasn’t rooted in
the idea that we weren’t going to be able to cope with rising demand, but that multi-core
CPUs, back then a rarity and reserved only for hardware systems in highly-specialized
roles, were in fact becoming commonplace in servers, and worse, as they migrated into
desktops, they would quickly a fact of life that every developer would need to face.
Herb demonstrated this by pointing out that CPU speeds had taken an interesting change
of pace in early 2003:
</p>
        <blockquote>
          <p>
Around the beginning of 2003, <em>[looking at the website Figure 1 graph] </em>you’ll
note a disturbing sharp turn in the previous trend toward ever-faster CPU clock speeds.
I’ve added lines to show the limit trends in maximum clock speed; instead of continuing
on the previous path, as indicated by the thin dotted line, there is a sharp flattening.
It has become harder and harder to exploit higher clock speeds due to not just one
but several physical issues, notably heat (too much of it and too hard to dissipate),
power consumption (too high), and current leakage problems.
</p>
        </blockquote>
        <p>
Joe Armstrong, creator of Erlang, noted in a presentation at QCon London 2007 that
another of those physical limitations was the speed of light—that for the first time,
CPU signal couldn't get from one end of the chip to the other in a single clock cycle.
</p>
        <blockquote>
          <p>
Quick: What’s the clock speed on the CPU(s) in your current workstation? Are you running
at 10GHz? On Intel chips, we reached 2GHz a long time ago (August 2001), and according
to CPU trends before 2003, now in early 2005 we should have the first 10GHz Pentium-family
chips.
</p>
        </blockquote>
        <p>
Just to (re-)emphasize the point, here, now, in early 200<strong>9</strong>, we should
be seeing the first 20 or 40 GHz processors, and clearly we’re still plodding along
in the 2 – 3 GHz range. The "Quake Rule" (when asked about perf problems,
tell your boss you'll need eighteen months to get a 2X improvement, then bury yourselves
in a closet for 18 months playing Quake until the next gen of Intel hardware comes
out) no longer works.
</p>
        <blockquote>
          <p>
For the near-term future, meaning for the next few years, the performance gains in
new chips will be fueled by three main approaches, only one of which is the same as
in the past. The near-term future performance growth drivers are:
</p>
          <ul>
            <li>
hyperthreading</li>
            <li>
multicore</li>
            <li>
cache</li>
          </ul>
          <p>
Hyperthreading is about running two or more threads in parallel inside a single CPU.
Hyperthreaded CPUs are already available today, and they do allow some instructions
to run in parallel. A limiting factor, however, is that although a hyper-threaded
CPU has some extra hardware including extra registers, it still has just one cache,
one integer math unit, one FPU, and in general just one each of most basic CPU features.
Hyperthreading is sometimes cited as offering a 5% to 15% performance boost for reasonably
well-written multi-threaded applications, or even as much as 40% under ideal conditions
for carefully written multi-threaded applications. That’s good, but it’s hardly double,
and it doesn’t help single-threaded applications.
</p>
          <p>
Multicore is about running two or more actual CPUs on one chip. Some chips, including
Sparc and PowerPC, have multicore versions available already. The initial Intel and
AMD designs, both due in 2005, vary in their level of integration but are functionally
similar. AMD’s seems to have some initial performance design advantages, such as better
integration of support functions on the same die, whereas Intel’s initial entry basically
just glues together two Xeons on a single die. The performance gains should initially
be about the same as having a true dual-CPU system (only the system will be cheaper
because the motherboard doesn’t have to have two sockets and associated “glue” chippery),
which means something less than double the speed even in the ideal case, and just
like today it will boost reasonably well-written multi-threaded applications. Not
single-threaded ones.
</p>
          <p>
Finally, on-die cache sizes can be expected to continue to grow, at least in the near
term. Of these three areas, only this one will broadly benefit most existing applications.
The continuing growth in on-die cache sizes is an incredibly important and highly
applicable benefit for many applications, simply because space is speed. Accessing
main memory is expensive, and you really don’t want to touch RAM if you can help it.
On today’s systems, a cache miss that goes out to main memory often costs 10 to 50
times as much getting the information from the cache; this, incidentally, continues
to surprise people because we all think of memory as fast, and it is fast compared
to disks and networks, but not compared to on-board cache which runs at faster speeds.
If an application’s working set fits into cache, we’re golden, and if it doesn’t,
we’re not. That is why increased cache sizes will save some existing applications
and breathe life into them for a few more years without requiring significant redesign:
As existing applications manipulate more and more data, and as they are incrementally
updated to include more code for new features, performance-sensitive operations need
to continue to fit into cache. As the Depression-era old-timers will be quick to remind
you, “Cache is king.”
</p>
        </blockquote>
        <p>
Herb’s article was a pretty serious wake-up call to programmers who hadn’t noticed
the trend themselves. (Being one of those who hadn’t noticed, I remember reading his
piece, looking at that graph, glancing at the open ad from Fry’s Electronics sitting
on the dining room table next to me, and saying to myself, “Holy sh*t, he’s right!”.)
Does that qualify it as a “mania”? Perhaps if you’re trying to pooh-pooh the concern,
sure. But if you’re a developer who’s wondering where you’re going to get the processing
power to address the ever-expanding list of features your users want, something Herb
points out as a basic fact of life in the software development world ...
</p>
        <blockquote>
          <p>
There’s an interesting phenomenon that’s known as “Andy giveth, and Bill taketh away.”
No matter how fast processors get, software consistently finds new ways to eat up
the extra speed. Make a CPU ten times as fast, and software will usually find ten
times as much to do (or, in some cases, will feel at liberty to do it ten times less
efficiently).
</p>
        </blockquote>
        <p>
...  then eking out the best performance from an application is going to remain
at the top of the priority list. Users are classic consumers: they will always want
more and more for the same money as before. Ignore this truth of software (actually,
of basic microeconomics) at your peril.
</p>
        <p>
To get back to the editorial, we next come to ...
</p>
        <blockquote>
          <p>
However, the fever was surprisingly short-lived. Intel's "largest open-source
effort ever" to provide a standard tool for writing multi-threaded code, caused
little more than a ripple of interest. Various books, rushed out while the temperature
soared, advocated the urgent need for new "multi-core-friendly" programming
models, involving such things as "software pipelines". Interesting as they
undoubtedly are, they sit stolidly on bookshelves, unread.
</p>
        </blockquote>
        <p>
Wow. Talk about your pretty aggressive accusation without any supporting evidence
or citation whatsoever.
</p>
        <p>
Intel's not big into the open-source space, so it doesn't take much for an open-source
project from them to be their "largest open-source effort ever". (What,
they're going to open-source the schematics for the Intel chipline? Who could read
them even if they did? Who would offer up a patch? What good would it do?) The fact
that Intel made the software available in the first place meant that they knew the
hurdle that had yet to be overcome, and wanted to aid developers in overcoming it.
They're members of the OpenMP group for the same reason.
</p>
        <p>
Rogue Wave's software pipelines programming model is another case where real benefits
have accrued, backed by case studies. (Disclaimer: I know this because I ghost-wrote
an article for them on their Software Pipelines implementation.) Let's not knock something
that's actually delivered value. Pipelines aren't going to be the solution to every
problem, granted, but they're a useful way of structuring a design, one that's curiously
similar to what I see in functional programming languages.
</p>
        <p>
But simply defending Intel's generosity or the validity of an alternative programming
model doesn't support the idea that concurrency is still a hot topic. No, for that,
I need real evidence, something with actual concrete numbers and verifiable fact to
it. 
</p>
        <p>
Thus, I point to Brian Goetz’s <em>Java Concurrency in Practice</em>, one of those
“books, rushed out while the temperature soared”, which also turned out to be the
best-selling book at Java One 2007, <em>and</em> the second-best-selling book (behind
only Joshua Bloch’s unbelievably good <em>Effective Java (2nd Ed) </em>) at Java One
2008. Clearly, yes, bestselling concurrency books are just a myth, alongside the magical
device that will receive messages from all over the world and play them into your
brain (by way of your ears) on demand, or the magical silver bird that can wing its
way through the air with no visible means of support as it does so. Myths, clearly,
all of them.
</p>
        <p>
To continue...
</p>
        <blockquote>
          <p>
The truth is that it's simply not a big issue for the majority of people. Writing
truly "concurrent" applications in languages such as C# is difficult, as
you get very little help from the language. It means getting involved with low-level
concurrency primitives, such as lock statements and so on. 
</p>
          <p>
Many programmers lack the skills to do this, but more pertinently lack the need. Increasingly,
programmers work in a web environment. As long as these web applications are deployed
to a load-balanced web farm, then page requests can be handled in parallel so all
available cores will be used efficiently without the need for the programmer to be
concerned with fine-grained parallelism.
</p>
        </blockquote>
        <p>
He’s right when he says you get very little help from the language, be it C# or Java
or C++. And getting involved with low-level concurrency primitives is clearly not
in anybody’s best interests, particularly if you’re not a concurrency guru like Brian.
(And let’s be honest, even low-level concurrency gurus like Brian, or Joe Duffy, who
wrote <em>Concurrent Programming on Windows</em>, or Mike Woodring, who co-authored <em>Win32
Multithreaded Programming</em>, have better things to do.) But to say that they “pertinently
lack the need” is a rather impertinent statement. “As long as these web applications
are deployed to a load-balanced web farm", which is very likely to continue to
happen, “then page requests can be handled in parallel so all available cores will
be used …”
</p>
        <p>
Um... excuse me?
</p>
        <p>
Didn’t you <em>just</em> say that programmers <em>didn’t</em> need to learn concurrency
constructs? It would strike me that if their page requests are being handled <em>in
parallel</em> that they have to learn how to write code that won’t break when it’s
accessed <em>in parallel</em> or lead to data-corruption problems or race conditions
when their pages are accessed <em>in parallel.</em> If parallelism is a fundamental
part of the Web, don’t you think it’s important for them to learn how to write programs
that can behave correctly <em>in parallel</em>?
</p>
        <p>
Look for just a moment at the average web application: if data is stored in a per-user
collection, and two simultaneous requests come in from a given user (perhaps because
the page has AJAX requests being generated by the user on the page, or perhaps because
there’s a frameset that’s generating requests for each sub-frame, or ...), what happens
if the code is written to read a value from the session, increment it, and store it
back? ASP.NET can save you here, a little, in that it used to establish a per-user
lock on the entirety of the page request (I don’t know if it still does this—I really
have lost any desire to build web apps ever again), but that essentially puts an artificial
throttle on the scalability of your system, and makes the end-users’ experience that
much slower. Load-balancer going to spray the request all over the farm? So long as
the user session state is stored on every machine in the farm, that’ll work... But
of course if you store the user’s state in the SQL instance behind each of those machines
on the farm, then you take the performance hit of an <em>extra</em> network round-trip
(at which point we’re back to concurrency in the database) ...
</p>
        <p>
... all because the programmer couldn’t figure out how to make “lock” work? This is
progress?
</p>
        <p>
The Java Servlet specification specifically backed away from this "lock on every
request" approach because of the performance implications. I heard a fair amount
of wailing and gnashing during the early ASP.NET days over this. I heard the ASP.NET
dev team say they made their decision because the average developer can't figure out
concurrency correctly anyway.
</p>
        <p>
And, by the way folks, this editorial completely ignores XML services. I guess "real"
applications don't write services much, either.
</p>
        <p>
The next part is even better:
</p>
        <blockquote>
          <p>
Furthermore, the SQL Server engine behind these web applications is intrinsically
"parallel", and can handle and use effectively about as many cores as you
care to throw at it. SQL itself is a declarative rather than procedural language,
so it is fundamentally concurrent.
</p>
        </blockquote>
        <p>
True… and false. SQL is fundamentally “parallel” (largely because SQL is a non-strict
functional language, not just a “declarative” one), but T-SQL isn’t. And how many
developers actually know where the line is drawn between SQL and T-SQL? More importantly,
though, how many <em>effective</em> applications can be written with a complete ignorance
of the underlying locking model? Why do DBAs spend hours tuning the database’s physical
constructs, establishing where isolation levels can be turned down, establishing where
the scope of a transaction is too large, putting in indexed columns where necessary,
and figuring out where page, row, or table locking will be most efficient? Because
despite the view that a relational database presents, these queries are being executed<em> in
parallel</em>, and if a developer wants to avoid writing an application that requires
a new server for each and every new user added to the system, they need to learn how
to maximize their use of the database’s parallelism. So even if the <em>language</em> is
"fundamentally concurrent" and can thus be relied upon to do the right thing
on behalf of the developer, the <em>implementation</em> isn't, and needs to be understood
in order to be implemented efficiently.
</p>
        <p>
He finishes:
</p>
        <blockquote>
          <p>
For most programmers and for most web applications, however, the multi-core furore
is a storm in a teacup; it's just not relevant. The web and database platforms already
cope with concurrency requirements. We are already doing it.
</p>
        </blockquote>
        <p>
This is one of those times I wish I had a time machine handy—I'd love to step forward
five years, have a look around, then come back and report the findings. I'm tempted
to close with the challenge to just let’s come back in five years and see what the
programming language landscape and hardware landscape looks like. But that's too easy
an "out", and frankly, doesn't do much to really instill confidence, in
my opinion.
</p>
        <p>
To ignore the developers building "rich" applications (be they being done
in Flex/Flash, Cocoa/iPhone, WinForms, Swing, WPF, or what-have-you) is to also ignore
a relatively large segment of the market. Not every application is being built on
the web and is backed by a relational database—to simply brush those off and not even
consider them as part of the editorial reveals a dangerous bias on the editor's part.
And those applications aren't hosted in an "intrinsically 'parallel'" container
that developers can just bury their head inside.
</p>
        <p>
Like it or not, folks, the path forward isn't one that you get to choose. Intel, AMD,
and other chip manufacturers have already made that clear. They're <em>not</em> going
to abandon the multicore approach now, not when doing so would mean trying to wrestle
with so many problems (including trying to change the speed of light) that simply
aren't there when using a multicore foundation. That isn't up for debate anymore.
Multicore has won for the forseeable future. And, as a result, multicore is going
to be a fact of the developer's life for the forseeable future. Concurrency is thus
also a fact of the developer's life for the forseeable future. 
</p>
        <p>
The web and database platforms “cope” with concurrency requirements by either making
"one-size-fits-all" decisions that almost always end up being the wrong
decision for high-scale systems (but I'm sure your new startup-based idea, like a
system that allows people to push "micro-entries" of no more than 140 characters
in length to a publicly-trackable feed would never actually take off and start carrying
millions and millions of messages every day, right?), or by punting entirely and forcing
developers to dig deeper beneath the covers to see the concurrency there. So if you're
happy with your applications running no faster than 2GHz for the rest of the forseeable
future, then sure, you don't need to worry about learning concurrency-friendly kinds
of programming techniques. Bear in mind, by the way, that this essentially locks you
in to small-scale, web-plus-database systems for the forseeable future, and clearly
nothing with any sort of CPU intensiveness to it whatsoever. Be happy in your niche,
and wave to the other COBOL programmers who made the same decision.
</p>
        <p>
This is a leaky abstraction, full stop, end of story. Anyone who tells you otherwise
is either trolling for hits, trying to sell you something, or striving to persuade
developers that ignorance isn't such a bad place to be.
</p>
        <p>
All you ignorant developers, this is the phrase you will be forced to learn before
you start your next job: "Would you like fries with that?"
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=f3062e21-fcf4-40f0-ac1f-8e212c931667" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>&amp;quot;Multi-core Mania&amp;quot;: A Rebuttal</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,f3062e21-fcf4-40f0-ac1f-8e212c931667.aspx</guid>
      <link>http://blogs.tedneward.com/2009/04/01/quotMulticore+Maniaquot+A+Rebuttal.aspx</link>
      <pubDate>Wed, 01 Apr 2009 08:44:35 GMT</pubDate>
      <description>&lt;p&gt;
The &lt;a href="http://www.simple-talk.com/newsletter-archive/"&gt;Simple-Talk newsletter&lt;/a&gt; is
a monthly e-zine that the folks over at Red Gate Software (makers of some pretty cool
toys, including their ANTS Profiler, and recent inheritors of the Reflector utility
legacy) produce, usually to good effect.
&lt;/p&gt;
&lt;p&gt;
But &lt;a href="http://www.simple-talk.com/newsletter/v.aspx?n=144"&gt;this month&lt;/a&gt; carried
with it an interesting editorial piece, which I reproduce in its entirety here:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
When the market is slack, nothing succeeds better at tightening it up than promoting
serial group-panic within the community. As an example of this, a wave of multi-core
panic spread across the Internet about 18 months ago. IT organizations, it was said,
urgently had to improve application performance by an order of magnitude in order
to cope with rising demand. We wouldn't be able to meet that need because we were
at the &amp;quot;end of the road&amp;quot; with regard to step changes in processor power
and clock speed. Multi-core technology was the only sure route to improving the speed
of applications but, unfortunately, our current &amp;quot;serial&amp;quot; programming techniques,
and the limited multithreading capabilities of our programming languages and programmers,
left us ill-equipped to exploit it. Multi-core mania gripped the industry.
&lt;/p&gt;
&lt;p&gt;
However, the fever was surprisingly short-lived. Intel's &amp;quot;largest open-source
effort ever&amp;quot; to provide a standard tool for writing multi-threaded code, caused
little more than a ripple of interest. Various books, rushed out while the temperature
soared, advocated the urgent need for new &amp;quot;multi-core-friendly&amp;quot; programming
models, involving such things as &amp;quot;software pipelines&amp;quot;. Interesting as they
undoubtedly are, they sit stolidly on bookshelves, unread.
&lt;/p&gt;
&lt;p&gt;
The truth is that it's simply not a big issue for the majority of people. Writing
truly &amp;quot;concurrent&amp;quot; applications in languages such as C# is difficult, as
you get very little help from the language. It means getting involved with low-level
concurrency primitives, such as lock statements and so on.
&lt;/p&gt;
&lt;p&gt;
Many programmers lack the skills to do this, but more pertinently lack the need. Increasingly,
programmers work in a web environment. As long as these web applications are deployed
to a load-balanced web farm, then page requests can be handled in parallel so all
available cores will be used efficiently without the need for the programmer to be
concerned with fine-grained parallelism.
&lt;/p&gt;
&lt;p&gt;
Furthermore, the SQL Server engine behind these web applications is intrinsically
&amp;quot;parallel&amp;quot;, and can handle and use effectively about as many cores as you
care to throw at it. SQL itself is a declarative rather than procedural language,
so it is fundamentally concurrent.
&lt;/p&gt;
&lt;p&gt;
A minority of programmers, for example games programmers or those who deal with &amp;quot;embarrassingly
parallel&amp;quot; desktop applications such as Photoshop, do need to start working with
the current tools and 'low-level' coding techniques that will allow them to exploit
multi-core technology. Although currently perceived to be more of &amp;quot;academic&amp;quot;
interest, concurrent languages such as Erlang, and concurrency techniques such as
&amp;quot;software transactional memory&amp;quot;, may yet prove to be significant.
&lt;/p&gt;
&lt;p&gt;
For most programmers and for most web applications, however, the multi-core furore
is a storm in a teacup; it's just not relevant. The web and database platforms already
cope with concurrency requirements. We are already doing it.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
My &lt;em&gt;hope&lt;/em&gt; is that this newsletter, sent on April 1st, was intended to be a
joke. Having said that, I can’t find any verbage in the email that suggests that it
is, in which case, I have to treat it as a legitimate editorial. 
&lt;/p&gt;
&lt;p&gt;
And frankly, I think it’s all crap. 
&lt;/p&gt;
&lt;p&gt;
It's dangerously ostrichian in nature—it encourages developers to simply bury their
heads in the sand and ignore the freight train that's coming their way. Permit me,
if you will, a few minutes of your time, that I may be allowed to go through and demonstrate
the reasons why I say this.
&lt;/p&gt;
&lt;p&gt;
To begin ...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
When the market is slack, nothing succeeds better at tightening it up than promoting
serial group-panic within the community. As an example of this, a wave of multi-core
panic spread across the Internet about 18 months ago. IT organizations, it was said,
urgently had to improve application performance by an order of magnitude in order
to cope with rising demand. [...] Multi-core mania gripped the industry.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Point of fact: The “panic” cited here didn’t start about 18 months ago, it started
with Herb Sutter’s most excellent (and not only highly recommended but highly required)
article, “The Free Lunch is Over: A Fundamental Turn Toward Concurrency in Software”,
appeared in the pages of Dr. Dobb’s Journal in March of 2005. (Herb’s website notes
that “a much briefer version under the title “The Concurrency Revolution” appeared
in C/C++ User’s Journal” the previous month.) And the panic itself wasn’t rooted in
the idea that we weren’t going to be able to cope with rising demand, but that multi-core
CPUs, back then a rarity and reserved only for hardware systems in highly-specialized
roles, were in fact becoming commonplace in servers, and worse, as they migrated into
desktops, they would quickly a fact of life that every developer would need to face.
Herb demonstrated this by pointing out that CPU speeds had taken an interesting change
of pace in early 2003:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Around the beginning of 2003, &lt;em&gt;[looking at the website Figure 1 graph] &lt;/em&gt;you’ll
note a disturbing sharp turn in the previous trend toward ever-faster CPU clock speeds.
I’ve added lines to show the limit trends in maximum clock speed; instead of continuing
on the previous path, as indicated by the thin dotted line, there is a sharp flattening.
It has become harder and harder to exploit higher clock speeds due to not just one
but several physical issues, notably heat (too much of it and too hard to dissipate),
power consumption (too high), and current leakage problems.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Joe Armstrong, creator of Erlang, noted in a presentation at QCon London 2007 that
another of those physical limitations was the speed of light—that for the first time,
CPU signal couldn't get from one end of the chip to the other in a single clock cycle.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Quick: What’s the clock speed on the CPU(s) in your current workstation? Are you running
at 10GHz? On Intel chips, we reached 2GHz a long time ago (August 2001), and according
to CPU trends before 2003, now in early 2005 we should have the first 10GHz Pentium-family
chips.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Just to (re-)emphasize the point, here, now, in early 200&lt;strong&gt;9&lt;/strong&gt;, we should
be seeing the first 20 or 40 GHz processors, and clearly we’re still plodding along
in the 2 – 3 GHz range. The &amp;quot;Quake Rule&amp;quot; (when asked about perf problems,
tell your boss you'll need eighteen months to get a 2X improvement, then bury yourselves
in a closet for 18 months playing Quake until the next gen of Intel hardware comes
out) no longer works.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
For the near-term future, meaning for the next few years, the performance gains in
new chips will be fueled by three main approaches, only one of which is the same as
in the past. The near-term future performance growth drivers are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
hyperthreading&lt;/li&gt;
&lt;li&gt;
multicore&lt;/li&gt;
&lt;li&gt;
cache&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Hyperthreading is about running two or more threads in parallel inside a single CPU.
Hyperthreaded CPUs are already available today, and they do allow some instructions
to run in parallel. A limiting factor, however, is that although a hyper-threaded
CPU has some extra hardware including extra registers, it still has just one cache,
one integer math unit, one FPU, and in general just one each of most basic CPU features.
Hyperthreading is sometimes cited as offering a 5% to 15% performance boost for reasonably
well-written multi-threaded applications, or even as much as 40% under ideal conditions
for carefully written multi-threaded applications. That’s good, but it’s hardly double,
and it doesn’t help single-threaded applications.
&lt;/p&gt;
&lt;p&gt;
Multicore is about running two or more actual CPUs on one chip. Some chips, including
Sparc and PowerPC, have multicore versions available already. The initial Intel and
AMD designs, both due in 2005, vary in their level of integration but are functionally
similar. AMD’s seems to have some initial performance design advantages, such as better
integration of support functions on the same die, whereas Intel’s initial entry basically
just glues together two Xeons on a single die. The performance gains should initially
be about the same as having a true dual-CPU system (only the system will be cheaper
because the motherboard doesn’t have to have two sockets and associated “glue” chippery),
which means something less than double the speed even in the ideal case, and just
like today it will boost reasonably well-written multi-threaded applications. Not
single-threaded ones.
&lt;/p&gt;
&lt;p&gt;
Finally, on-die cache sizes can be expected to continue to grow, at least in the near
term. Of these three areas, only this one will broadly benefit most existing applications.
The continuing growth in on-die cache sizes is an incredibly important and highly
applicable benefit for many applications, simply because space is speed. Accessing
main memory is expensive, and you really don’t want to touch RAM if you can help it.
On today’s systems, a cache miss that goes out to main memory often costs 10 to 50
times as much getting the information from the cache; this, incidentally, continues
to surprise people because we all think of memory as fast, and it is fast compared
to disks and networks, but not compared to on-board cache which runs at faster speeds.
If an application’s working set fits into cache, we’re golden, and if it doesn’t,
we’re not. That is why increased cache sizes will save some existing applications
and breathe life into them for a few more years without requiring significant redesign:
As existing applications manipulate more and more data, and as they are incrementally
updated to include more code for new features, performance-sensitive operations need
to continue to fit into cache. As the Depression-era old-timers will be quick to remind
you, “Cache is king.”
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Herb’s article was a pretty serious wake-up call to programmers who hadn’t noticed
the trend themselves. (Being one of those who hadn’t noticed, I remember reading his
piece, looking at that graph, glancing at the open ad from Fry’s Electronics sitting
on the dining room table next to me, and saying to myself, “Holy sh*t, he’s right!”.)
Does that qualify it as a “mania”? Perhaps if you’re trying to pooh-pooh the concern,
sure. But if you’re a developer who’s wondering where you’re going to get the processing
power to address the ever-expanding list of features your users want, something Herb
points out as a basic fact of life in the software development world ...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
There’s an interesting phenomenon that’s known as “Andy giveth, and Bill taketh away.”
No matter how fast processors get, software consistently finds new ways to eat up
the extra speed. Make a CPU ten times as fast, and software will usually find ten
times as much to do (or, in some cases, will feel at liberty to do it ten times less
efficiently).
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
...&amp;#160; then eking out the best performance from an application is going to remain
at the top of the priority list. Users are classic consumers: they will always want
more and more for the same money as before. Ignore this truth of software (actually,
of basic microeconomics) at your peril.
&lt;/p&gt;
&lt;p&gt;
To get back to the editorial, we next come to ...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
However, the fever was surprisingly short-lived. Intel's &amp;quot;largest open-source
effort ever&amp;quot; to provide a standard tool for writing multi-threaded code, caused
little more than a ripple of interest. Various books, rushed out while the temperature
soared, advocated the urgent need for new &amp;quot;multi-core-friendly&amp;quot; programming
models, involving such things as &amp;quot;software pipelines&amp;quot;. Interesting as they
undoubtedly are, they sit stolidly on bookshelves, unread.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wow. Talk about your pretty aggressive accusation without any supporting evidence
or citation whatsoever.
&lt;/p&gt;
&lt;p&gt;
Intel's not big into the open-source space, so it doesn't take much for an open-source
project from them to be their &amp;quot;largest open-source effort ever&amp;quot;. (What,
they're going to open-source the schematics for the Intel chipline? Who could read
them even if they did? Who would offer up a patch? What good would it do?) The fact
that Intel made the software available in the first place meant that they knew the
hurdle that had yet to be overcome, and wanted to aid developers in overcoming it.
They're members of the OpenMP group for the same reason.
&lt;/p&gt;
&lt;p&gt;
Rogue Wave's software pipelines programming model is another case where real benefits
have accrued, backed by case studies. (Disclaimer: I know this because I ghost-wrote
an article for them on their Software Pipelines implementation.) Let's not knock something
that's actually delivered value. Pipelines aren't going to be the solution to every
problem, granted, but they're a useful way of structuring a design, one that's curiously
similar to what I see in functional programming languages.
&lt;/p&gt;
&lt;p&gt;
But simply defending Intel's generosity or the validity of an alternative programming
model doesn't support the idea that concurrency is still a hot topic. No, for that,
I need real evidence, something with actual concrete numbers and verifiable fact to
it. 
&lt;/p&gt;
&lt;p&gt;
Thus, I point to Brian Goetz’s &lt;em&gt;Java Concurrency in Practice&lt;/em&gt;, one of those
“books, rushed out while the temperature soared”, which also turned out to be the
best-selling book at Java One 2007, &lt;em&gt;and&lt;/em&gt; the second-best-selling book (behind
only Joshua Bloch’s unbelievably good &lt;em&gt;Effective Java (2nd Ed) &lt;/em&gt;) at Java One
2008. Clearly, yes, bestselling concurrency books are just a myth, alongside the magical
device that will receive messages from all over the world and play them into your
brain (by way of your ears) on demand, or the magical silver bird that can wing its
way through the air with no visible means of support as it does so. Myths, clearly,
all of them.
&lt;/p&gt;
&lt;p&gt;
To continue...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The truth is that it's simply not a big issue for the majority of people. Writing
truly &amp;quot;concurrent&amp;quot; applications in languages such as C# is difficult, as
you get very little help from the language. It means getting involved with low-level
concurrency primitives, such as lock statements and so on. 
&lt;/p&gt;
&lt;p&gt;
Many programmers lack the skills to do this, but more pertinently lack the need. Increasingly,
programmers work in a web environment. As long as these web applications are deployed
to a load-balanced web farm, then page requests can be handled in parallel so all
available cores will be used efficiently without the need for the programmer to be
concerned with fine-grained parallelism.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
He’s right when he says you get very little help from the language, be it C# or Java
or C++. And getting involved with low-level concurrency primitives is clearly not
in anybody’s best interests, particularly if you’re not a concurrency guru like Brian.
(And let’s be honest, even low-level concurrency gurus like Brian, or Joe Duffy, who
wrote &lt;em&gt;Concurrent Programming on Windows&lt;/em&gt;, or Mike Woodring, who co-authored &lt;em&gt;Win32
Multithreaded Programming&lt;/em&gt;, have better things to do.) But to say that they “pertinently
lack the need” is a rather impertinent statement. “As long as these web applications
are deployed to a load-balanced web farm&amp;quot;, which is very likely to continue to
happen, “then page requests can be handled in parallel so all available cores will
be used …”
&lt;/p&gt;
&lt;p&gt;
Um... excuse me?
&lt;/p&gt;
&lt;p&gt;
Didn’t you &lt;em&gt;just&lt;/em&gt; say that programmers &lt;em&gt;didn’t&lt;/em&gt; need to learn concurrency
constructs? It would strike me that if their page requests are being handled &lt;em&gt;in
parallel&lt;/em&gt; that they have to learn how to write code that won’t break when it’s
accessed &lt;em&gt;in parallel&lt;/em&gt; or lead to data-corruption problems or race conditions
when their pages are accessed &lt;em&gt;in parallel.&lt;/em&gt; If parallelism is a fundamental
part of the Web, don’t you think it’s important for them to learn how to write programs
that can behave correctly &lt;em&gt;in parallel&lt;/em&gt;?
&lt;/p&gt;
&lt;p&gt;
Look for just a moment at the average web application: if data is stored in a per-user
collection, and two simultaneous requests come in from a given user (perhaps because
the page has AJAX requests being generated by the user on the page, or perhaps because
there’s a frameset that’s generating requests for each sub-frame, or ...), what happens
if the code is written to read a value from the session, increment it, and store it
back? ASP.NET can save you here, a little, in that it used to establish a per-user
lock on the entirety of the page request (I don’t know if it still does this—I really
have lost any desire to build web apps ever again), but that essentially puts an artificial
throttle on the scalability of your system, and makes the end-users’ experience that
much slower. Load-balancer going to spray the request all over the farm? So long as
the user session state is stored on every machine in the farm, that’ll work... But
of course if you store the user’s state in the SQL instance behind each of those machines
on the farm, then you take the performance hit of an &lt;em&gt;extra&lt;/em&gt; network round-trip
(at which point we’re back to concurrency in the database) ...
&lt;/p&gt;
&lt;p&gt;
... all because the programmer couldn’t figure out how to make “lock” work? This is
progress?
&lt;/p&gt;
&lt;p&gt;
The Java Servlet specification specifically backed away from this &amp;quot;lock on every
request&amp;quot; approach because of the performance implications. I heard a fair amount
of wailing and gnashing during the early ASP.NET days over this. I heard the ASP.NET
dev team say they made their decision because the average developer can't figure out
concurrency correctly anyway.
&lt;/p&gt;
&lt;p&gt;
And, by the way folks, this editorial completely ignores XML services. I guess &amp;quot;real&amp;quot;
applications don't write services much, either.
&lt;/p&gt;
&lt;p&gt;
The next part is even better:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Furthermore, the SQL Server engine behind these web applications is intrinsically
&amp;quot;parallel&amp;quot;, and can handle and use effectively about as many cores as you
care to throw at it. SQL itself is a declarative rather than procedural language,
so it is fundamentally concurrent.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
True… and false. SQL is fundamentally “parallel” (largely because SQL is a non-strict
functional language, not just a “declarative” one), but T-SQL isn’t. And how many
developers actually know where the line is drawn between SQL and T-SQL? More importantly,
though, how many &lt;em&gt;effective&lt;/em&gt; applications can be written with a complete ignorance
of the underlying locking model? Why do DBAs spend hours tuning the database’s physical
constructs, establishing where isolation levels can be turned down, establishing where
the scope of a transaction is too large, putting in indexed columns where necessary,
and figuring out where page, row, or table locking will be most efficient? Because
despite the view that a relational database presents, these queries are being executed&lt;em&gt; in
parallel&lt;/em&gt;, and if a developer wants to avoid writing an application that requires
a new server for each and every new user added to the system, they need to learn how
to maximize their use of the database’s parallelism. So even if the &lt;em&gt;language&lt;/em&gt; is
&amp;quot;fundamentally concurrent&amp;quot; and can thus be relied upon to do the right thing
on behalf of the developer, the &lt;em&gt;implementation&lt;/em&gt; isn't, and needs to be understood
in order to be implemented efficiently.
&lt;/p&gt;
&lt;p&gt;
He finishes:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
For most programmers and for most web applications, however, the multi-core furore
is a storm in a teacup; it's just not relevant. The web and database platforms already
cope with concurrency requirements. We are already doing it.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This is one of those times I wish I had a time machine handy—I'd love to step forward
five years, have a look around, then come back and report the findings. I'm tempted
to close with the challenge to just let’s come back in five years and see what the
programming language landscape and hardware landscape looks like. But that's too easy
an &amp;quot;out&amp;quot;, and frankly, doesn't do much to really instill confidence, in
my opinion.
&lt;/p&gt;
&lt;p&gt;
To ignore the developers building &amp;quot;rich&amp;quot; applications (be they being done
in Flex/Flash, Cocoa/iPhone, WinForms, Swing, WPF, or what-have-you) is to also ignore
a relatively large segment of the market. Not every application is being built on
the web and is backed by a relational database—to simply brush those off and not even
consider them as part of the editorial reveals a dangerous bias on the editor's part.
And those applications aren't hosted in an &amp;quot;intrinsically 'parallel'&amp;quot; container
that developers can just bury their head inside.
&lt;/p&gt;
&lt;p&gt;
Like it or not, folks, the path forward isn't one that you get to choose. Intel, AMD,
and other chip manufacturers have already made that clear. They're &lt;em&gt;not&lt;/em&gt; going
to abandon the multicore approach now, not when doing so would mean trying to wrestle
with so many problems (including trying to change the speed of light) that simply
aren't there when using a multicore foundation. That isn't up for debate anymore.
Multicore has won for the forseeable future. And, as a result, multicore is going
to be a fact of the developer's life for the forseeable future. Concurrency is thus
also a fact of the developer's life for the forseeable future. 
&lt;/p&gt;
&lt;p&gt;
The web and database platforms “cope” with concurrency requirements by either making
&amp;quot;one-size-fits-all&amp;quot; decisions that almost always end up being the wrong
decision for high-scale systems (but I'm sure your new startup-based idea, like a
system that allows people to push &amp;quot;micro-entries&amp;quot; of no more than 140 characters
in length to a publicly-trackable feed would never actually take off and start carrying
millions and millions of messages every day, right?), or by punting entirely and forcing
developers to dig deeper beneath the covers to see the concurrency there. So if you're
happy with your applications running no faster than 2GHz for the rest of the forseeable
future, then sure, you don't need to worry about learning concurrency-friendly kinds
of programming techniques. Bear in mind, by the way, that this essentially locks you
in to small-scale, web-plus-database systems for the forseeable future, and clearly
nothing with any sort of CPU intensiveness to it whatsoever. Be happy in your niche,
and wave to the other COBOL programmers who made the same decision.
&lt;/p&gt;
&lt;p&gt;
This is a leaky abstraction, full stop, end of story. Anyone who tells you otherwise
is either trolling for hits, trying to sell you something, or striving to persuade
developers that ignorance isn't such a bad place to be.
&lt;/p&gt;
&lt;p&gt;
All you ignorant developers, this is the phrase you will be forced to learn before
you start your next job: &amp;quot;Would you like fries with that?&amp;quot;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=f3062e21-fcf4-40f0-ac1f-8e212c931667" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,f3062e21-fcf4-40f0-ac1f-8e212c931667.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Scala</category>
      <category>Visual Basic</category>
      <category>WCF</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=dbf7aba3-e02b-4d88-961d-3e4e6ff97771</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,dbf7aba3-e02b-4d88-961d-3e4e6ff97771.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,dbf7aba3-e02b-4d88-961d-3e4e6ff97771.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=dbf7aba3-e02b-4d88-961d-3e4e6ff97771</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
While playing around with a recent research-oriented project for myself (more on that
later), I discovered something that I haven't seen mentioned anywhere in the Scala
universe before. (OK, not really--as you'll see towards the end of this piece, it
really is documented, but allow me my brief delusions of grandeur as I write this.
They'll get deflated quickly enough.) 
</p>
        <p>
So the core of the thing was a stack-oriented execution engine; essentially I'm processing
commands delivered in a postfix manner. Since some of these commands are relational
operators, it's important that there be two things to relationally operate on the
execution stack, after which I want to evaluate the relational operation and push
its result (1 if true, 0 if false) back on the stack; this is pretty easily done via
the following: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">def compareOp(op : (Int, Int) =&gt; Boolean) =<br />
{<br />
checkStack(2)<br />
val v1 = (execStack.pop()).asInstanceOf[Int]<br />
val v2 = (execStack.pop()).asInstanceOf[Int]<br />
val vr = op(v1, v2)<br />
execStack.push(<span style="color: #0000ff">if</span> (vr) 1 <span style="color: #0000ff">else</span> 0)<br />
} 
<br /></pre>
          <br />
        </div>
        <p>
where "execStack" is a mutable.Stack[Any] held in an enclosing function. 
</p>
        <p>
Interestingly enough, however, when I wrote this the first time, I wrote it like this,
which is a very different sequence of operations: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">def compareOp(op : (Int, Int) =&gt; Boolean) =<br />
{<br />
checkStack(2)<br />
def v1 = (execStack.pop()).asInstanceOf[Int]<br />
def v2 = (execStack.pop()).asInstanceOf[Int]<br />
def vr = op(v1, v2)<br />
execStack.push(<span style="color: #0000ff">if</span> (vr) 1 <span style="color: #0000ff">else</span> 0)<br />
}</pre>
          <br />
        </div>
        <p>
See the difference? Subtle, is it not? But the actual code is significantly different,
something that's more easily seen with a much simpler (and standalone) example: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
def v1 = (stack.pop()).asInstanceOf[Int]<br />
def v2 = (stack.pop()).asInstanceOf[Int]<br />
def vr = v1 + v2<br />
System.<span style="color: #0000ff">out</span>.println(vr)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
When run, the console prints out "36", as we'd well expect. 
</p>
        <p>
But suppose we want to look at those values of v1 and v2 along the way, perhaps as
part of a logging operation, or perhaps because you're just screwing around with some
ideas in your head and you don't want to bother to fire up an IDE with Scala support
in it. So you decide to spit those values to a console: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
def v1 = (stack.pop()).asInstanceOf[Int]<br />
def v2 = (stack.pop()).asInstanceOf[Int]<br />
System.<span style="color: #0000ff">out</span>.println(v1)<br />
System.<span style="color: #0000ff">out</span>.println(v2)<br />
def vr = v1 + v2<br />
System.<span style="color: #0000ff">out</span>.println(vr)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
And then something *very* different happens; you get "24", "12",
and then a NoSuchElementException. 
</p>
        <p>
If you're like me the first time I ran into this, your first reaction is, "Eh?".
Actually, if you're like me, when you're programming, your profanity filters are probaby
at an ebb, so your first reaction is "WTF?!?", said with great gusto and
emphasis. Which has a tendency to get some strange looks when you're at a Denny's
doing your research, I will admit. Particularly when it's at 3 AM in the morning.
And the bar crowd is in full alcoholic haze and slightly nervous about the long-haired,
goatee-sporting guy in his headphones, wearing his black leather jacket and swearing
like a drunken sailor at his laptop. But I digress. 
</p>
        <p>
What is Scala doing here? 
</p>
        <p>
Turns out this is exactly as the language designers intended, but it's subtle. (Or
maybe it's just subtle to me at 3AM when I'm pumped full of caffeine.) 
</p>
        <p>
Let's take this a different way: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
def v1 = (stack.pop()).asInstanceOf[Int]<br />
def v2 = (stack.pop()).asInstanceOf[Int]<br />
System.<span style="color: #0000ff">out</span>.println(stack)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
When run, the console prints "Stack(12, 24)", which *really* starts to play
with your mind when you're a little short on sleep and a little high on Diet Coke.
At first glance, it looks like Scala is broken somehow--after all, those "pop"
operations are supposed to modify the Stack against which they're operating, just
as the push()es do. So why is the stack convinced that it still holds the values of
12 and 24? 
</p>
        <p>
Because Scala hasn't actually executed those pop()s yet. 
</p>
        <p>
The "def" keyword, it turns out, isn't what I wanted here--what I wanted
(and in retrospect it’s painfully obvious) was a "val", instead, in order
to force the execution of those statements and capture the value into a local value
(an immutable local variable). The "def" keyword, instead, creates a function
binding that waits for formal execution before evaluating. So that when I previously
said 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
def v1 = (stack.pop()).asInstanceOf[Int]<br />
def v2 = (stack.pop()).asInstanceOf[Int]<br />
def vr = v1 + v2<br />
System.<span style="color: #0000ff">out</span>.println(vr)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
… what in fact I was saying was this: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
def v1 = (stack.pop()).asInstanceOf[Int]<br />
def v2 = (stack.pop()).asInstanceOf[Int]<br />
System.<span style="color: #0000ff">out</span>.println(v1 + v2)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
… which is the same as: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
System.<span style="color: #0000ff">out</span>.println((stack.pop()).asInstanceOf[Int]
+ (stack.pop()).asInstanceOf[Int])<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
… which, when we look back at my most recent "debugging" version of the
code, substituting the "def"ed versions of v1 and v2 (and vr) where they're
used, makes the reason for the NoSuchElementException become entirely more clear: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
System.<span style="color: #0000ff">out</span>.println((stack.pop()).asInstanceOf[Int])<br />
System.<span style="color: #0000ff">out</span>.println((stack.pop()).asInstanceOf[Int])<br />
System.<span style="color: #0000ff">out</span>.println((stack.pop()).asInstanceOf[Int]
+ (stack.pop()).asInstanceOf[Int])<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
Now, normally, this would probably set off all kinds of alarm bells in your head,
but the reaction that went off in mine was "COOL!", the reasons for which
revolve around the concept of "laziness"; in a functional language, we frequently
don't want to evaluate the results right away, instead preferring to defer their execution
until actually requiring it. In fact, many functional languages—such as Haskell—take
laziness to new heights, baking it directly into the language definition and assuming
laziness everywhere, so much so that you have to take special steps to avoid it. There’s
a variety of reasons why this is advantageous, but I’ll leave those discussions to
the Haskellians of the world, like Matt Podwysocki and Simon Peyton-Jones.
</p>
        <p>
From a Scalist’s perspective, laziness is still a useful tool to have in your toolbox.
Suppose you have a really powerful function that calculates PI to a ridiculous number
of decimal places. In Java, you might be tempted to do something like this: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">class</span> MyMath<br />
{<br /><span style="color: #0000ff">public</span><span style="color: #0000ff">static</span> final <span style="color: #0000ff">double</span> PI
= calculatePiToARidiculousNumberOfPlaces();<br /><span style="color: #0000ff">private</span><span style="color: #0000ff">static</span><span style="color: #0000ff">double</span> calculatePiToARidiculousNumberOfPlaces()<br />
{<br /><span style="color: #008000">// implementation left to the reader's imagination</span><br /><span style="color: #008000">// imagine it being "really cool"</span><br />
}<br />
} </pre>
          <br />
        </div>
        <p>
The problem with this is that if that method takes any length of time to execute,
it's being done during class initialization during its ClassLoading phase, and aside
from introducing a window of time where the class *could* be used before that initialization
is finished (it's subtle, it's not going to happen very often, but it can, according
to older versions of the JVM Spec), the problem is that the time required to do that
initialization is paid for *regardless of whether you use PI*. In other words, the
classic Stroustrup-ian "Don't pay for it if you don't use it" principle
is being completely tossed aside.
</p>
        <p>
In Scala, using the "def" keyword here, aside from avoiding the need for
the additional decorators, completely eliminates this cost--people won't need the
value of PI until it becomes used: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def PI = calculatePiToARidiculousNumberOfPlaces()<br />
def calculatePiToARidiculousNumberOfPlaces() =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Calculating
PI"</span>)<br />
3 + 0.14<br />
}<br />
def main(args : Array[String]) =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Entering
main"</span>)<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"PI
= "</span> + PI)<br />
}<br />
} </pre>
          <br />
        </div>
        <p>
(In fact, you'd probably just write it without the calculating method definition,
since it's easier that way, but bear with me.) 
</p>
        <p>
When you run this, of course, we see PI being calculated after main()'s been entered,
thus proving that PI is being calculated only on demand, not ahead of time, as a public-static-final-constant
would be. 
</p>
        <p>
The problem with this approach is, you end up calculating PI on <em>each</em> access: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
def PI = calculatePiToARidiculousNumberOfPlaces()<br />
def calculatePiToARidiculousNumberOfPlaces() =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Calculating
PI"</span>)<br />
3 + 0.14<br />
}<br />
def main(args : Array[String]) =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Entering
main"</span>)<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"PI
= "</span> + PI)<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"PI
= "</span> + PI)<br /><span style="color: #008000">// prints twice! Not good!</span><br />
}<br />
} </pre>
          <br />
        </div>
        <p>
Which sort of defeats the advantage of lazy evaluation. 
</p>
        <p>
This got me wondering--in F#, we have lazy as a baked-in concept (sort of), such that
when I write 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">#light<br />
let sixty = lazy (30 + 30)<br />
System.Console.WriteLine(sixty) </pre>
          <br />
        </div>
        <p>
What I see on the console is not 60, but a Lazy&lt;T&gt; type instance, which effectively
defers execution until it's Force() method is invoked (among other scenarios). This
means I can write things like 
</p>
        <p>
let reallyBigList = lazy ([1..1000000000000] |&gt; complexCalculation |&gt; anotherComplexCalcuation) 
</p>
        <p>
without fear of blowing the stack or heap apart, since laziness means the list won't
actually be calculated until it's forced; we can see this from the following (from
the F# interactive console): 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">&gt; let sixtyWithSideEffect = lazy (printfn <span style="color: #006080">"Hello
world"</span>; 30+30);;<br />
val sixtyWithSideEffect: Lazy&lt;<span style="color: #0000ff">int</span>&gt;<br />
&gt; sixtyWithSideEffect.Force();;<br />
Hello world<br />
val it : <span style="color: #0000ff">int</span> = 60<br />
&gt; sixtyWithSideEffect.Force();;<br />
val it : <span style="color: #0000ff">int</span> = 60 </pre>
          <br />
        </div>
        <p>
(Examples taken from the excellent <em>Expert F#</em> by Syme/Granicz/Cisternino;
highly recommended, if a touch out-of-date to the current language definition. I expect
Chris Smith’s <em>Programming F#</em>, from O’Reilly, to correct that before too long.)
</p>
        <p>
It would be nice if something similar were doable in Scala. Of course, once I start
looking for it, it makes itself visible, in the wonderful Venners/Odersky/Spoon book, <em>Programming
In Scala</em>, p. 444: 
</p>
        <blockquote>
          <p>
You can use pre-initialized fields to simulate precisely the initialization behavior 
<br />
of class constructor arguments. Sometimes, however, you might prefer 
<br />
to let the system itself sort out how things should be initialized. This can 
<br />
be achieved by making your val definitions lazy. If you prefix a val definition 
<br />
with a lazy modifier, the initializing expression on the right-hand side 
<br />
will only be evaluated the first time the val is used. 
</p>
          <p>
[...] 
</p>
          <p>
This is similar to the situation where x is defined as a parameterless 
<br />
method, using a def. However, unlike a def a lazy val is never evaluated 
<br />
more than once. In fact, after the first evaluation of a lazy val the result of the 
<br />
evaluation is stored, to be reused when the same val is used subsequently. 
</p>
        </blockquote>
        <p>
Perfect! The key, then, is to define PI like so: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">object</span> App<br />
{<br />
lazy val PI = calculatePiToARidiculousNumberOfPlaces()<br />
def calculatePiToARidiculousNumberOfPlaces() =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Calculating
PI"</span>)<br />
3 + 0.14<br />
}<br />
def main(args : Array[String]) =<br />
{<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"Entering
main"</span>)<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"PI
= "</span> + PI)<br />
System.<span style="color: #0000ff">out</span>.println(<span style="color: #006080">"PI
= "</span> + PI)<br /><span style="color: #008000">// prints once! Awesome!</span><br />
}<br />
} </pre>
          <br />
        </div>
        <p>
That means, if I apply it to my Stack example from before, I should get the same deferred-execution
properties of the "def"-based version ... 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
lazy val v1 = (stack.pop()).asInstanceOf[Int]<br />
lazy val v2 = (stack.pop()).asInstanceOf[Int]<br />
System.<span style="color: #0000ff">out</span>.println(stack)<br /><span style="color: #008000">// prints out "Stack(12,24)</span><br />
} </pre>
          <br />
        </div>
        <p>
... but if I go back to the version that blows up because the stack is empty, using
lazy val works exactly the way I would want it to: 
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">def main(args : Array[String]) =<br />
{<br />
import scala.collection.mutable.Stack<br />
var stack : Stack[Any] = <span style="color: #0000ff">new</span> Stack()<br />
stack.push(12)<br />
stack.push(24)<br />
lazy val v1 = (stack.pop()).asInstanceOf[Int]<br />
lazy val v2 = (stack.pop()).asInstanceOf[Int]<br />
System.<span style="color: #0000ff">out</span>.println(v1)<br />
System.<span style="color: #0000ff">out</span>.println(v2)<br />
lazy val vr = v1 + v2<br />
System.<span style="color: #0000ff">out</span>.println(vr)<br /><span style="color: #008000">// prints 12, 24, then 36</span><br /><span style="color: #008000">// and no exception!</span><br />
} </pre>
          <br />
        </div>
        <p>
Nice. 
</p>
        <p>
So, it turns out that my accidental use of "def" inside the compareOp function
behaves exactly the way the language designers wanted it to, which is not surprising,
and that Scala provides nifty abilities to defer processing or extraction of values
until called for.
</p>
        <p>
Curiously, the two languages differ in how laziness is implemented; in F#, the lazy
modifier defines the type to be a Lazy&lt;T&gt; instance, an ordinary type that we
can pass around from F# to C# and back again as necessary (in much the same way that
C# defined nullable types to be instances of Nullable&lt;T&gt; under the hood). We
can see that from the interactive console output above, and from the fact that we
call Force() on the instance to evaluate its value. 
</p>
        <p>
In Scala, however, there is no corresponding Lazy[T] type; instead, the PI() method
is defined to determine whether or not the value has already been evaluated:
</p>
        <div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
          <pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
            <span style="color: #0000ff">public</span>
            <span style="color: #0000ff">double</span> PI();<br />
Code:<br />
0: aload_0<br />
1: getfield #135; <span style="color: #008000">//Field bitmap$0:I</span><br />
4: iconst_1<br />
5: iand<br />
6: iconst_0<br />
7: if_icmpne 48<br />
10: aload_0<br />
11: dup<br />
12: astore_1<br />
13: monitorenter<br />
14: aload_0<br />
15: getfield #135; <span style="color: #008000">//Field bitmap$0:I</span><br />
18: iconst_1<br />
19: iand<br />
20: iconst_0<br />
21: if_icmpne 42<br />
24: aload_0<br />
25: aload_0<br />
26: invokevirtual #137; <span style="color: #008000">//Method calculatePiToARidiculousNumberOfPlaces:()D</span><br />
29: putfield #139; <span style="color: #008000">//Field PI:D</span><br />
32: aload_0<br />
33: aload_0<br />
34: getfield #135; <span style="color: #008000">//Field bitmap$0:I</span><br />
37: iconst_1<br />
38: ior<br />
39: putfield #135; <span style="color: #008000">//Field bitmap$0:I</span><br />
42: getstatic #145; <span style="color: #008000">//Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;</span><br />
45: pop<br />
46: aload_1<br />
47: monitorexit<br />
48: aload_0<br />
49: getfield #139; <span style="color: #008000">//Field PI:D</span><br />
52: dreturn<br />
53: aload_1<br />
54: monitorexit<br />
55: athrow<br />
Exception table:<br />
from to target type<br />
14 48 53 any</pre>
          <br />
        </div>
        <p>
If you look carefully at the bytecode, the implementation of PI is checking a bitmask
field (!) to determine if the first bit is flipped (!) to know whether or not the
value is held in the local field PI, and if not, calculate it and store it there.
This means that Java developers will just need to call PI() over and over again, rather
than have to know that the instance is actually a Lazy[T] on which they need to call
Value or Force (such as one would from C# in the F# case). Frankly, I don’t know at
this point which approach I prefer, but I’m slightly leaning towards the Scala version
for now. (If only Java supported properties, then the syntax “MyMath.PI” would look
like a constant, act lazily, and everything would be great.)
</p>
        <p>
(It strikes me that the F# developer looking to write something C#-accessible need
only tuck the Lazy&lt;T&gt; instance behind a property accessor and the problem goes
away, by the way; it would just be nicer to not have to do anything special on either
side, to have my laziness and Force() it, too. Pipe dream, perhaps.)
</p>
        <p>
In retrospect, I could wish that Scala weren't *quite* so subtle in its treatment
of "def" vs "val", but now that I'm aware of it, it'll (hopefully)
not bite me quite so subtly in the sensitive spots of my anatomy again.
</p>
        <p>
And any experience in which you learn something is a good one, right?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=dbf7aba3-e02b-4d88-961d-3e4e6ff97771" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>Laziness in Scala</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,dbf7aba3-e02b-4d88-961d-3e4e6ff97771.aspx</guid>
      <link>http://blogs.tedneward.com/2009/03/29/Laziness+In+Scala.aspx</link>
      <pubDate>Sun, 29 Mar 2009 12:18:12 GMT</pubDate>
      <description>&lt;p&gt;
While playing around with a recent research-oriented project for myself (more on that
later), I discovered something that I haven't seen mentioned anywhere in the Scala
universe before. (OK, not really--as you'll see towards the end of this piece, it
really is documented, but allow me my brief delusions of grandeur as I write this.
They'll get deflated quickly enough.) 
&lt;/p&gt;
&lt;p&gt;
So the core of the thing was a stack-oriented execution engine; essentially I'm processing
commands delivered in a postfix manner. Since some of these commands are relational
operators, it's important that there be two things to relationally operate on the
execution stack, after which I want to evaluate the relational operation and push
its result (1 if true, 0 if false) back on the stack; this is pretty easily done via
the following: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;def compareOp(op : (Int, Int) =&amp;gt; Boolean) =&lt;br /&gt;
{&lt;br /&gt;
checkStack(2)&lt;br /&gt;
val v1 = (execStack.pop()).asInstanceOf[Int]&lt;br /&gt;
val v2 = (execStack.pop()).asInstanceOf[Int]&lt;br /&gt;
val vr = op(v1, v2)&lt;br /&gt;
execStack.push(&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (vr) 1 &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; 0)&lt;br /&gt;
} 
&lt;br /&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
where &amp;quot;execStack&amp;quot; is a mutable.Stack[Any] held in an enclosing function. 
&lt;/p&gt;
&lt;p&gt;
Interestingly enough, however, when I wrote this the first time, I wrote it like this,
which is a very different sequence of operations: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;def compareOp(op : (Int, Int) =&amp;gt; Boolean) =&lt;br /&gt;
{&lt;br /&gt;
checkStack(2)&lt;br /&gt;
def v1 = (execStack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (execStack.pop()).asInstanceOf[Int]&lt;br /&gt;
def vr = op(v1, v2)&lt;br /&gt;
execStack.push(&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (vr) 1 &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; 0)&lt;br /&gt;
}&lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
See the difference? Subtle, is it not? But the actual code is significantly different,
something that's more easily seen with a much simpler (and standalone) example: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
def v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def vr = v1 + v2&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(vr)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
When run, the console prints out &amp;quot;36&amp;quot;, as we'd well expect. 
&lt;/p&gt;
&lt;p&gt;
But suppose we want to look at those values of v1 and v2 along the way, perhaps as
part of a logging operation, or perhaps because you're just screwing around with some
ideas in your head and you don't want to bother to fire up an IDE with Scala support
in it. So you decide to spit those values to a console: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
def v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(v1)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(v2)&lt;br /&gt;
def vr = v1 + v2&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(vr)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
And then something *very* different happens; you get &amp;quot;24&amp;quot;, &amp;quot;12&amp;quot;,
and then a NoSuchElementException. 
&lt;/p&gt;
&lt;p&gt;
If you're like me the first time I ran into this, your first reaction is, &amp;quot;Eh?&amp;quot;.
Actually, if you're like me, when you're programming, your profanity filters are probaby
at an ebb, so your first reaction is &amp;quot;WTF?!?&amp;quot;, said with great gusto and
emphasis. Which has a tendency to get some strange looks when you're at a Denny's
doing your research, I will admit. Particularly when it's at 3 AM in the morning.
And the bar crowd is in full alcoholic haze and slightly nervous about the long-haired,
goatee-sporting guy in his headphones, wearing his black leather jacket and swearing
like a drunken sailor at his laptop. But I digress. 
&lt;/p&gt;
&lt;p&gt;
What is Scala doing here? 
&lt;/p&gt;
&lt;p&gt;
Turns out this is exactly as the language designers intended, but it's subtle. (Or
maybe it's just subtle to me at 3AM when I'm pumped full of caffeine.) 
&lt;/p&gt;
&lt;p&gt;
Let's take this a different way: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
def v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(stack)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
When run, the console prints &amp;quot;Stack(12, 24)&amp;quot;, which *really* starts to play
with your mind when you're a little short on sleep and a little high on Diet Coke.
At first glance, it looks like Scala is broken somehow--after all, those &amp;quot;pop&amp;quot;
operations are supposed to modify the Stack against which they're operating, just
as the push()es do. So why is the stack convinced that it still holds the values of
12 and 24? 
&lt;/p&gt;
&lt;p&gt;
Because Scala hasn't actually executed those pop()s yet. 
&lt;/p&gt;
&lt;p&gt;
The &amp;quot;def&amp;quot; keyword, it turns out, isn't what I wanted here--what I wanted
(and in retrospect it’s painfully obvious) was a &amp;quot;val&amp;quot;, instead, in order
to force the execution of those statements and capture the value into a local value
(an immutable local variable). The &amp;quot;def&amp;quot; keyword, instead, creates a function
binding that waits for formal execution before evaluating. So that when I previously
said 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
def v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def vr = v1 + v2&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(vr)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
… what in fact I was saying was this: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
def v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
def v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(v1 + v2)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
… which is the same as: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println((stack.pop()).asInstanceOf[Int]
+ (stack.pop()).asInstanceOf[Int])&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
… which, when we look back at my most recent &amp;quot;debugging&amp;quot; version of the
code, substituting the &amp;quot;def&amp;quot;ed versions of v1 and v2 (and vr) where they're
used, makes the reason for the NoSuchElementException become entirely more clear: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println((stack.pop()).asInstanceOf[Int])&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println((stack.pop()).asInstanceOf[Int])&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println((stack.pop()).asInstanceOf[Int]
+ (stack.pop()).asInstanceOf[Int])&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
Now, normally, this would probably set off all kinds of alarm bells in your head,
but the reaction that went off in mine was &amp;quot;COOL!&amp;quot;, the reasons for which
revolve around the concept of &amp;quot;laziness&amp;quot;; in a functional language, we frequently
don't want to evaluate the results right away, instead preferring to defer their execution
until actually requiring it. In fact, many functional languages—such as Haskell—take
laziness to new heights, baking it directly into the language definition and assuming
laziness everywhere, so much so that you have to take special steps to avoid it. There’s
a variety of reasons why this is advantageous, but I’ll leave those discussions to
the Haskellians of the world, like Matt Podwysocki and Simon Peyton-Jones.
&lt;/p&gt;
&lt;p&gt;
From a Scalist’s perspective, laziness is still a useful tool to have in your toolbox.
Suppose you have a really powerful function that calculates PI to a ridiculous number
of decimal places. In Java, you might be tempted to do something like this: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MyMath&lt;br /&gt;
{&lt;br /&gt;
&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; final &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; PI
= calculatePiToARidiculousNumberOfPlaces();&lt;br /&gt;
&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; calculatePiToARidiculousNumberOfPlaces()&lt;br /&gt;
{&lt;br /&gt;
&lt;span style="color: #008000"&gt;// implementation left to the reader's imagination&lt;/span&gt;
&lt;br /&gt;
&lt;span style="color: #008000"&gt;// imagine it being &amp;quot;really cool&amp;quot;&lt;/span&gt;
&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
The problem with this is that if that method takes any length of time to execute,
it's being done during class initialization during its ClassLoading phase, and aside
from introducing a window of time where the class *could* be used before that initialization
is finished (it's subtle, it's not going to happen very often, but it can, according
to older versions of the JVM Spec), the problem is that the time required to do that
initialization is paid for *regardless of whether you use PI*. In other words, the
classic Stroustrup-ian &amp;quot;Don't pay for it if you don't use it&amp;quot; principle
is being completely tossed aside.
&lt;/p&gt;
&lt;p&gt;
In Scala, using the &amp;quot;def&amp;quot; keyword here, aside from avoiding the need for
the additional decorators, completely eliminates this cost--people won't need the
value of PI until it becomes used: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def PI = calculatePiToARidiculousNumberOfPlaces()&lt;br /&gt;
def calculatePiToARidiculousNumberOfPlaces() =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Calculating
PI&amp;quot;&lt;/span&gt;)&lt;br /&gt;
3 + 0.14&lt;br /&gt;
}&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Entering
main&amp;quot;&lt;/span&gt;)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;PI
= &amp;quot;&lt;/span&gt; + PI)&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
(In fact, you'd probably just write it without the calculating method definition,
since it's easier that way, but bear with me.) 
&lt;/p&gt;
&lt;p&gt;
When you run this, of course, we see PI being calculated after main()'s been entered,
thus proving that PI is being calculated only on demand, not ahead of time, as a public-static-final-constant
would be. 
&lt;/p&gt;
&lt;p&gt;
The problem with this approach is, you end up calculating PI on &lt;em&gt;each&lt;/em&gt; access: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
def PI = calculatePiToARidiculousNumberOfPlaces()&lt;br /&gt;
def calculatePiToARidiculousNumberOfPlaces() =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Calculating
PI&amp;quot;&lt;/span&gt;)&lt;br /&gt;
3 + 0.14&lt;br /&gt;
}&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Entering
main&amp;quot;&lt;/span&gt;)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;PI
= &amp;quot;&lt;/span&gt; + PI)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;PI
= &amp;quot;&lt;/span&gt; + PI)&lt;br /&gt;
&lt;span style="color: #008000"&gt;// prints twice! Not good!&lt;/span&gt;
&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
Which sort of defeats the advantage of lazy evaluation. 
&lt;/p&gt;
&lt;p&gt;
This got me wondering--in F#, we have lazy as a baked-in concept (sort of), such that
when I write 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;#light&lt;br /&gt;
let sixty = lazy (30 + 30)&lt;br /&gt;
System.Console.WriteLine(sixty) &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
What I see on the console is not 60, but a Lazy&amp;lt;T&amp;gt; type instance, which effectively
defers execution until it's Force() method is invoked (among other scenarios). This
means I can write things like 
&lt;/p&gt;
&lt;p&gt;
let reallyBigList = lazy ([1..1000000000000] |&amp;gt; complexCalculation |&amp;gt; anotherComplexCalcuation) 
&lt;/p&gt;
&lt;p&gt;
without fear of blowing the stack or heap apart, since laziness means the list won't
actually be calculated until it's forced; we can see this from the following (from
the F# interactive console): 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&amp;gt; let sixtyWithSideEffect = lazy (printfn &lt;span style="color: #006080"&gt;&amp;quot;Hello
world&amp;quot;&lt;/span&gt;; 30+30);;&lt;br /&gt;
val sixtyWithSideEffect: Lazy&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;&lt;br /&gt;
&amp;gt; sixtyWithSideEffect.Force();;&lt;br /&gt;
Hello world&lt;br /&gt;
val it : &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; = 60&lt;br /&gt;
&amp;gt; sixtyWithSideEffect.Force();;&lt;br /&gt;
val it : &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; = 60 &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
(Examples taken from the excellent &lt;em&gt;Expert F#&lt;/em&gt; by Syme/Granicz/Cisternino;
highly recommended, if a touch out-of-date to the current language definition. I expect
Chris Smith’s &lt;em&gt;Programming F#&lt;/em&gt;, from O’Reilly, to correct that before too long.)
&lt;/p&gt;
&lt;p&gt;
It would be nice if something similar were doable in Scala. Of course, once I start
looking for it, it makes itself visible, in the wonderful Venners/Odersky/Spoon book, &lt;em&gt;Programming
In Scala&lt;/em&gt;, p. 444: 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
You can use pre-initialized fields to simulate precisely the initialization behavior 
&lt;br /&gt;
of class constructor arguments. Sometimes, however, you might prefer 
&lt;br /&gt;
to let the system itself sort out how things should be initialized. This can 
&lt;br /&gt;
be achieved by making your val definitions lazy. If you prefix a val definition 
&lt;br /&gt;
with a lazy modifier, the initializing expression on the right-hand side 
&lt;br /&gt;
will only be evaluated the first time the val is used. 
&lt;/p&gt;
&lt;p&gt;
[...] 
&lt;/p&gt;
&lt;p&gt;
This is similar to the situation where x is defined as a parameterless 
&lt;br /&gt;
method, using a def. However, unlike a def a lazy val is never evaluated 
&lt;br /&gt;
more than once. In fact, after the first evaluation of a lazy val the result of the 
&lt;br /&gt;
evaluation is stored, to be reused when the same val is used subsequently. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Perfect! The key, then, is to define PI like so: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; App&lt;br /&gt;
{&lt;br /&gt;
lazy val PI = calculatePiToARidiculousNumberOfPlaces()&lt;br /&gt;
def calculatePiToARidiculousNumberOfPlaces() =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Calculating
PI&amp;quot;&lt;/span&gt;)&lt;br /&gt;
3 + 0.14&lt;br /&gt;
}&lt;br /&gt;
def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;Entering
main&amp;quot;&lt;/span&gt;)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;PI
= &amp;quot;&lt;/span&gt; + PI)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(&lt;span style="color: #006080"&gt;&amp;quot;PI
= &amp;quot;&lt;/span&gt; + PI)&lt;br /&gt;
&lt;span style="color: #008000"&gt;// prints once! Awesome!&lt;/span&gt;
&lt;br /&gt;
}&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
That means, if I apply it to my Stack example from before, I should get the same deferred-execution
properties of the &amp;quot;def&amp;quot;-based version ... 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
lazy val v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
lazy val v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(stack)&lt;br /&gt;
&lt;span style="color: #008000"&gt;// prints out &amp;quot;Stack(12,24)&lt;/span&gt;
&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
... but if I go back to the version that blows up because the stack is empty, using
lazy val works exactly the way I would want it to: 
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;def main(args : Array[String]) =&lt;br /&gt;
{&lt;br /&gt;
import scala.collection.mutable.Stack&lt;br /&gt;
var stack : Stack[Any] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Stack()&lt;br /&gt;
stack.push(12)&lt;br /&gt;
stack.push(24)&lt;br /&gt;
lazy val v1 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
lazy val v2 = (stack.pop()).asInstanceOf[Int]&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(v1)&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(v2)&lt;br /&gt;
lazy val vr = v1 + v2&lt;br /&gt;
System.&lt;span style="color: #0000ff"&gt;out&lt;/span&gt;.println(vr)&lt;br /&gt;
&lt;span style="color: #008000"&gt;// prints 12, 24, then 36&lt;/span&gt;
&lt;br /&gt;
&lt;span style="color: #008000"&gt;// and no exception!&lt;/span&gt;
&lt;br /&gt;
} &lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
Nice. 
&lt;/p&gt;
&lt;p&gt;
So, it turns out that my accidental use of &amp;quot;def&amp;quot; inside the compareOp function
behaves exactly the way the language designers wanted it to, which is not surprising,
and that Scala provides nifty abilities to defer processing or extraction of values
until called for.
&lt;/p&gt;
&lt;p&gt;
Curiously, the two languages differ in how laziness is implemented; in F#, the lazy
modifier defines the type to be a Lazy&amp;lt;T&amp;gt; instance, an ordinary type that we
can pass around from F# to C# and back again as necessary (in much the same way that
C# defined nullable types to be instances of Nullable&amp;lt;T&amp;gt; under the hood). We
can see that from the interactive console output above, and from the fact that we
call Force() on the instance to evaluate its value. 
&lt;/p&gt;
&lt;p&gt;
In Scala, however, there is no corresponding Lazy[T] type; instead, the PI() method
is defined to determine whether or not the value has already been evaluated:
&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;
&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; PI();&lt;br /&gt;
Code:&lt;br /&gt;
0: aload_0&lt;br /&gt;
1: getfield #135; &lt;span style="color: #008000"&gt;//Field bitmap$0:I&lt;/span&gt;
&lt;br /&gt;
4: iconst_1&lt;br /&gt;
5: iand&lt;br /&gt;
6: iconst_0&lt;br /&gt;
7: if_icmpne 48&lt;br /&gt;
10: aload_0&lt;br /&gt;
11: dup&lt;br /&gt;
12: astore_1&lt;br /&gt;
13: monitorenter&lt;br /&gt;
14: aload_0&lt;br /&gt;
15: getfield #135; &lt;span style="color: #008000"&gt;//Field bitmap$0:I&lt;/span&gt;
&lt;br /&gt;
18: iconst_1&lt;br /&gt;
19: iand&lt;br /&gt;
20: iconst_0&lt;br /&gt;
21: if_icmpne 42&lt;br /&gt;
24: aload_0&lt;br /&gt;
25: aload_0&lt;br /&gt;
26: invokevirtual #137; &lt;span style="color: #008000"&gt;//Method calculatePiToARidiculousNumberOfPlaces:()D&lt;/span&gt;
&lt;br /&gt;
29: putfield #139; &lt;span style="color: #008000"&gt;//Field PI:D&lt;/span&gt;
&lt;br /&gt;
32: aload_0&lt;br /&gt;
33: aload_0&lt;br /&gt;
34: getfield #135; &lt;span style="color: #008000"&gt;//Field bitmap$0:I&lt;/span&gt;
&lt;br /&gt;
37: iconst_1&lt;br /&gt;
38: ior&lt;br /&gt;
39: putfield #135; &lt;span style="color: #008000"&gt;//Field bitmap$0:I&lt;/span&gt;
&lt;br /&gt;
42: getstatic #145; &lt;span style="color: #008000"&gt;//Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;&lt;/span&gt;
&lt;br /&gt;
45: pop&lt;br /&gt;
46: aload_1&lt;br /&gt;
47: monitorexit&lt;br /&gt;
48: aload_0&lt;br /&gt;
49: getfield #139; &lt;span style="color: #008000"&gt;//Field PI:D&lt;/span&gt;
&lt;br /&gt;
52: dreturn&lt;br /&gt;
53: aload_1&lt;br /&gt;
54: monitorexit&lt;br /&gt;
55: athrow&lt;br /&gt;
Exception table:&lt;br /&gt;
from to target type&lt;br /&gt;
14 48 53 any&lt;/pre&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;p&gt;
If you look carefully at the bytecode, the implementation of PI is checking a bitmask
field (!) to determine if the first bit is flipped (!) to know whether or not the
value is held in the local field PI, and if not, calculate it and store it there.
This means that Java developers will just need to call PI() over and over again, rather
than have to know that the instance is actually a Lazy[T] on which they need to call
Value or Force (such as one would from C# in the F# case). Frankly, I don’t know at
this point which approach I prefer, but I’m slightly leaning towards the Scala version
for now. (If only Java supported properties, then the syntax “MyMath.PI” would look
like a constant, act lazily, and everything would be great.)
&lt;/p&gt;
&lt;p&gt;
(It strikes me that the F# developer looking to write something C#-accessible need
only tuck the Lazy&amp;lt;T&amp;gt; instance behind a property accessor and the problem goes
away, by the way; it would just be nicer to not have to do anything special on either
side, to have my laziness and Force() it, too. Pipe dream, perhaps.)
&lt;/p&gt;
&lt;p&gt;
In retrospect, I could wish that Scala weren't *quite* so subtle in its treatment
of &amp;quot;def&amp;quot; vs &amp;quot;val&amp;quot;, but now that I'm aware of it, it'll (hopefully)
not bite me quite so subtly in the sensitive spots of my anatomy again.
&lt;/p&gt;
&lt;p&gt;
And any experience in which you learn something is a good one, right?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=dbf7aba3-e02b-4d88-961d-3e4e6ff97771" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,dbf7aba3-e02b-4d88-961d-3e4e6ff97771.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Scala</category>
      <category>Visual Basic</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=3decc34a-7e83-4f37-aed6-d968f88fcf32</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,3decc34a-7e83-4f37-aed6-d968f88fcf32.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,3decc34a-7e83-4f37-aed6-d968f88fcf32.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=3decc34a-7e83-4f37-aed6-d968f88fcf32</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
An <a href="http://thegreylensmansview.blogspot.com/2009/02/book-of-josh.html">interesting
blog post</a> was forwarded to me by another of my fellow ThoughtWorkers, which suggests
a new software stack for building an enterprise system, acronymized as “JOSH”:
</p>
        <blockquote>
          <p>
The Book Of JOSH
</p>
          <p>
            <br />
Through a marvelous, even devious, set of circumstances, I'm presented with the opportunity
to address my little problem without proscribed constraints, a true green field opportunity. 
<br /></p>
          <p>
            <strong>J</strong>son <strong>O</strong>SGi <strong>S</strong>cala <strong>H</strong>TTP 
<br /></p>
          <p>
            <strong>Json</strong> delivers on what XML promised. Simple to understand, effective
data markup accessible and usable by human and computer alike. Serialization/Deserialization
is on par with or faster then XML, Thrift and Protocol Buffers. Sure I'm losing XSD
Schema type checking, SOAP and WS-* standardization. I'm taking that trade. 
<br /></p>
          <p>
            <strong>OSGi</strong> a standardized dynamic, modular framework for versioned components
and services. Pick a logger component, a HTTP server component, a ??? component, add
your own internal components and you have a dedicated application solution. Micro
deployment with true replacement. What am I giving up? The monolithic J2EE application
servlet loaded with 25 frameworks, SCA and XML configuration hell. Taking the trade. 
<br /></p>
          <p>
            <strong>HTTP</strong> is simple, effective, fast enough, and widely supported. I'm
tired of needlessly complex and endless proprietary protocols to move simple data
from A to B with all the accompanying firewall port insanity. Yes, HTTP is not perfect.
But I'm taking this trade where I can as well. 
<br /></p>
          <p>
All interfaces will be simple REST inspired APIs based on HTTP+JSON. This is an immediate
consequence of the JOSH stack. 
<br /></p>
          <p>
            <strong>Scala</strong> is by far the toughest, yet the easiest selection in the JOSH
stack. I wrestled far more with the JSON or XML or Thrift or Protocol Buffers decision.
</p>
        </blockquote>
        <p>
And, let’s be honest, the stack sounds a lot better than what he was working with
before....
</p>
        <blockquote>
          <p>
[...] Yes, you see, I have a small problem.
</p>
          <p>
            <br />
So whats the issue, you say? I write a whole blog about nothing, you say? We all know
the right answer, you're pointing out? Yea, I know, its intuitively obvious to the
casual observer.
</p>
          <p>
            <br />
We'll rewrite it from scratch.
</p>
          <p>
            <br />
Course we'll need a cluster of WebSphere Application Servers, and an Oracle RAC cluster
for all that data. Don't forget the middleware needed to transition over from the
legacy systems, so toss in an ESB cluster, and what heck a couple of BPEL servers
too.
</p>
          <p>
            <br />
Need a SOA Center of Excellence of course too. Can't integrate without some common
XML Business Object Schemas. Also need to roll the Rational RUP suite and some beefy
IDE environments and for that shiny look, sprinkle the works with lots of WS-* sparkly
dust. Bake 3-5 years or until done, whenever.
</p>
          <p>
            <br />
My presentation slides for all this will be killer. I can sell this stuff. I'm good
at it. I'll look like a bloody genius. I'll have Vendors fawning all over me. And
the best part is the bubble on this mess won't pop for YEARS, when I'll have plenty
of plausible deniability. "Hey the plan was perfect, the business, IT managers
and their people were incapable of executing it."
</p>
          <p>
            <br />
I feel like the enterprise IT equivalent of an AIG trader pocketing ill gotten gains
from writing Credit Default Swaps that we can't pay off.
</p>
        </blockquote>
        <p>
Ewww... even thinking about all that makes me want to go upstairs, step into the shower,
turn the water as hot as it will go, and wash. Scrub my skin raw with soap and sponge
until the top five layers of epidermis are gone, and <em>still</em> not feel clean.
</p>
        <p>
On the surface of things, the stack sounds pretty good. OSGi is a pretty solid spec
for managing versioning and modularity within a running Java system, and more importantly,
it’s well-known, relatively reliable, and pretty well-proven to handle the classic
problems well. And of course, anybody who knows me knows that I’m a fan of the Scala
language as a potential complement or supplement to the Java programming language,
so that’s hardly in debate.
</p>
        <p>
But there are a few concerns. JSON is a simple wire protocol, granted, but that is
both a good thing and a bad thing (it’s object-centric, for one, and will run into
some of the same issues as objects do with certain relationships), and it lacks the
ubiquity that XML provides. Granted, XML clearly suffered from an overabundance of
adoption, but it still doesn’t take away the fact that ubiquity is really necessary
if you’re building a baseline for something that will talk to a variety of different
systems. Which, I admit, may not be in his list of requirements, I don’t know. And
HTTP is great for long-haul, client-initiated communication, but it definitely has
its limitations (which he acknowledges, openly, to his credit), at least to internal-facing
consumers. There is no peer for external-facing consumers, that’s a given.
</p>
        <p>
And the stack is clearly also missing something else...
</p>
        <blockquote>
          <p>
The JOSH stack is lacking a letter, because a solution for persisted data is missing
in the stack.
</p>
          <p>
            <br />
A great deal of what needs to be done does not require a ACID RDB cluster. Some of
it does and I'm kicking that can down the road.
</p>
          <p>
            <br />
For the rest, either the data is ReadOnly and loaded a 1-3 times a day or is best
persisted by a distributed Key-Value storage system. A number of these are now available
as open source solutions and at the right moment I'll need to pick one and add that
letter to the JOSH stack.
</p>
        </blockquote>
        <p>
As a commenter suggested, CouchDB might be a solution here, or I’ll even throw db4o
into the ring for discussion as an option. Again, it’ll depend on how far-and-wide
the data will be seen by other systems—the more other systems need to see it, the
less further away from a “regular” RDBMS we can go.
</p>
        <p>
Certainly, it’s a great start for discussion, even if the acronym is likely to give
those named Joshua an unhealthy ego boost. :-)
</p>
        <p>
Part of me wonders, though... what would the equivalent on .NET look like? JSON +
Assemblies + F# + HTTP = JAFH?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=3decc34a-7e83-4f37-aed6-d968f88fcf32" />
        <br />
        <hr />
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. <a href="mailto:ted@tedneward.com">Contact
me for details</a>.</body>
      <title>A new stack: JOSH</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,3decc34a-7e83-4f37-aed6-d968f88fcf32.aspx</guid>
      <link>http://blogs.tedneward.com/2009/03/24/A+New+Stack+JOSH.aspx</link>
      <pubDate>Tue, 24 Mar 2009 09:25:43 GMT</pubDate>
      <description>&lt;p&gt;
An &lt;a href="http://thegreylensmansview.blogspot.com/2009/02/book-of-josh.html"&gt;interesting
blog post&lt;/a&gt; was forwarded to me by another of my fellow ThoughtWorkers, which suggests
a new software stack for building an enterprise system, acronymized as “JOSH”:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The Book Of JOSH
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
Through a marvelous, even devious, set of circumstances, I'm presented with the opportunity
to address my little problem without proscribed constraints, a true green field opportunity. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;J&lt;/strong&gt;son &lt;strong&gt;O&lt;/strong&gt;SGi &lt;strong&gt;S&lt;/strong&gt;cala &lt;strong&gt;H&lt;/strong&gt;TTP 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Json&lt;/strong&gt; delivers on what XML promised. Simple to understand, effective
data markup accessible and usable by human and computer alike. Serialization/Deserialization
is on par with or faster then XML, Thrift and Protocol Buffers. Sure I'm losing XSD
Schema type checking, SOAP and WS-* standardization. I'm taking that trade. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;OSGi&lt;/strong&gt; a standardized dynamic, modular framework for versioned components
and services. Pick a logger component, a HTTP server component, a ??? component, add
your own internal components and you have a dedicated application solution. Micro
deployment with true replacement. What am I giving up? The monolithic J2EE application
servlet loaded with 25 frameworks, SCA and XML configuration hell. Taking the trade. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;HTTP&lt;/strong&gt; is simple, effective, fast enough, and widely supported. I'm
tired of needlessly complex and endless proprietary protocols to move simple data
from A to B with all the accompanying firewall port insanity. Yes, HTTP is not perfect.
But I'm taking this trade where I can as well. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
All interfaces will be simple REST inspired APIs based on HTTP+JSON. This is an immediate
consequence of the JOSH stack. 
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Scala&lt;/strong&gt; is by far the toughest, yet the easiest selection in the JOSH
stack. I wrestled far more with the JSON or XML or Thrift or Protocol Buffers decision.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
And, let’s be honest, the stack sounds a lot better than what he was working with
before....
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
[...] Yes, you see, I have a small problem.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
So whats the issue, you say? I write a whole blog about nothing, you say? We all know
the right answer, you're pointing out? Yea, I know, its intuitively obvious to the
casual observer.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
We'll rewrite it from scratch.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
Course we'll need a cluster of WebSphere Application Servers, and an Oracle RAC cluster
for all that data. Don't forget the middleware needed to transition over from the
legacy systems, so toss in an ESB cluster, and what heck a couple of BPEL servers
too.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
Need a SOA Center of Excellence of course too. Can't integrate without some common
XML Business Object Schemas. Also need to roll the Rational RUP suite and some beefy
IDE environments and for that shiny look, sprinkle the works with lots of WS-* sparkly
dust. Bake 3-5 years or until done, whenever.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
My presentation slides for all this will be killer. I can sell this stuff. I'm good
at it. I'll look like a bloody genius. I'll have Vendors fawning all over me. And
the best part is the bubble on this mess won't pop for YEARS, when I'll have plenty
of plausible deniability. &amp;quot;Hey the plan was perfect, the business, IT managers
and their people were incapable of executing it.&amp;quot;
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
I feel like the enterprise IT equivalent of an AIG trader pocketing ill gotten gains
from writing Credit Default Swaps that we can't pay off.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ewww... even thinking about all that makes me want to go upstairs, step into the shower,
turn the water as hot as it will go, and wash. Scrub my skin raw with soap and sponge
until the top five layers of epidermis are gone, and &lt;em&gt;still&lt;/em&gt; not feel clean.
&lt;/p&gt;
&lt;p&gt;
On the surface of things, the stack sounds pretty good. OSGi is a pretty solid spec
for managing versioning and modularity within a running Java system, and more importantly,
it’s well-known, relatively reliable, and pretty well-proven to handle the classic
problems well. And of course, anybody who knows me knows that I’m a fan of the Scala
language as a potential complement or supplement to the Java programming language,
so that’s hardly in debate.
&lt;/p&gt;
&lt;p&gt;
But there are a few concerns. JSON is a simple wire protocol, granted, but that is
both a good thing and a bad thing (it’s object-centric, for one, and will run into
some of the same issues as objects do with certain relationships), and it lacks the
ubiquity that XML provides. Granted, XML clearly suffered from an overabundance of
adoption, but it still doesn’t take away the fact that ubiquity is really necessary
if you’re building a baseline for something that will talk to a variety of different
systems. Which, I admit, may not be in his list of requirements, I don’t know. And
HTTP is great for long-haul, client-initiated communication, but it definitely has
its limitations (which he acknowledges, openly, to his credit), at least to internal-facing
consumers. There is no peer for external-facing consumers, that’s a given.
&lt;/p&gt;
&lt;p&gt;
And the stack is clearly also missing something else...
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The JOSH stack is lacking a letter, because a solution for persisted data is missing
in the stack.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
A great deal of what needs to be done does not require a ACID RDB cluster. Some of
it does and I'm kicking that can down the road.
&lt;/p&gt;
&lt;p&gt;
&lt;br /&gt;
For the rest, either the data is ReadOnly and loaded a 1-3 times a day or is best
persisted by a distributed Key-Value storage system. A number of these are now available
as open source solutions and at the right moment I'll need to pick one and add that
letter to the JOSH stack.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
As a commenter suggested, CouchDB might be a solution here, or I’ll even throw db4o
into the ring for discussion as an option. Again, it’ll depend on how far-and-wide
the data will be seen by other systems—the more other systems need to see it, the
less further away from a “regular” RDBMS we can go.
&lt;/p&gt;
&lt;p&gt;
Certainly, it’s a great start for discussion, even if the acronym is likely to give
those named Joshua an unhealthy ego boost. :-)
&lt;/p&gt;
&lt;p&gt;
Part of me wonders, though... what would the equivalent on .NET look like? JSON +
Assemblies + F# + HTTP = JAFH?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=3decc34a-7e83-4f37-aed6-d968f88fcf32" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <comments>http://blogs.tedneward.com/CommentView,guid,3decc34a-7e83-4f37-aed6-d968f88fcf32.aspx</comments>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Scala</category>
      <category>XML Services</category>
    </item>
  </channel>
</rss>