<?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 - Ruby</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=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=0e5b971c-8dd4-48ef-b47c-b9b0611607dd</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,0e5b971c-8dd4-48ef-b47c-b9b0611607dd.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,0e5b971c-8dd4-48ef-b47c-b9b0611607dd.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=0e5b971c-8dd4-48ef-b47c-b9b0611607dd</wfw:commentRss>
      <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>
This one is from the <a href="http://uva.onlinejudge.org/index.php?option=com_onlinejudge&amp;Itemid=8&amp;category=3&amp;page=show_problem&amp;problem=37" target="_blank">UVa
online programming contest judge system</a>, which I discovered after picking up the
book <em>Programming Challenges</em>, which is highly recommended as a source of code
katas, by the way. Much of the advice parts of the book can be skimmed or ignored
by the long-time professional developer, but it's still worth a read, since it can
be an interesting source of ideas and approaches when solving real-world scenarios.
</p>
        <p>
 
</p>
        <p>
          <strong>Problem:</strong> You work for a manufacturing company, and they have just
received their newest piece of super-modern hardware, a highly efficient assembly-line
mechanized pneumatic item manipulator, also known in some circles as a "robotic
arm". It is driven by a series of commands, and your job is to write the software
to drive the arm. The initial test will be to have the arm move a series of blocks
around.
</p>
        <p>
 
</p>
        <p>
          <strong>Context:</strong> The test begins with <em>n</em> number of blocks, laid out
sequentially next to each other, each block with a number on it. (You may safely assume
that <em>n</em> never exceeds 25.) So, if <em>n</em> is 4, then the blocks are laid
out (starting from 0) as:
</p>
        <blockquote>
          <p>
0: 0
</p>
          <p>
1: 1
</p>
          <p>
2: 2
</p>
          <p>
3: 3
</p>
        </blockquote>
        <p>
The display output here is the block-numbered "slot", then a colon, then
the block(s) that are stacked in that slot, lowest to highest in left to right order.
Thus, in the following display:
</p>
        <blockquote>
          <p>
0:
</p>
          <p>
1:
</p>
          <p>
2: 0 1 2 3
</p>
          <p>
3:
</p>
        </blockquote>
        <p>
The 3 block is stacked on top of the 2 block is stacked on top of the 1 block is stacked
on top of the 0 block, all in slot 2. This can be shortened to the representation
[0:, 1:, 2: 0 1 2 3, 3:] for conciseness.
</p>
        <p>
 
</p>
        <p>
The arm understands a number of different commands, as well as an optic sensor. (Yeah,
the guys who created the arm were good enough to write code that knows how to read
the number off a block, but not to actually drive the arm. Go figure.) The commands
are as follows, where <em>a</em> and <em>b</em> are valid block numbers (meaning they
are between 0 and <em>n</em>-1):
</p>
        <ul>
          <li>
"move <em>a</em> onto <em>b</em>" This command orders the arm to find block <em>a</em>,
and return any blocks stacked on top of it to their original position. Do the same
for block <em>b</em>, then stack block <em>a</em> on top of <em>b</em>.</li>
          <li>
"move <em>a</em> over <em>b</em>" This command orders the arm to find block <em>a</em>,
and return any blocks stacked on top of it to their original position. Then stack
block <em>a</em> on top of the stack of blocks containing <em>b</em>.</li>
          <li>
"pile <em>a</em> onto <em>b</em>" This command orders the arm to find the
stack of blocks containing block <em>b</em>, and return any blocks stacked on top
of it to their original position. Then the arm must find the stack of blocks containing
block <em>a</em>, and take the stack of blocks starting from <em>a</em> on upwards
(in other words, don't do anything with any blocks on top of <em>a</em>) and put that
stack on top of block <em>b</em>.</li>
          <li>
"pile <em>a</em> over <em>b</em>" This command orders the arm to find the
stack of blocks containing block <em>a</em> and take the stack of blocks starting
from <em>a</em> on upwards (in other words, don't do anything with any blocks on top
of <em>a</em>) and put that stack on top of the stack of blocks containing block <em>b</em> (in
other words, don't do anything with the stack of blocks containing <em>b</em>, either).</li>
          <li>
"quit" This command tells the arm to shut down (and thus terminates the
simulation).</li>
        </ul>
        <p>
Note that if the input command sequence accidentally offers a command where <em>a</em> and <em>b</em> are
the same value, that command is illegal and should be ignored.
</p>
        <p>
 
</p>
        <p>
As an example, then, if we have 4 blocks in the state [0: 0, 1: 1, 2: 2, 3: 3], and
run a "move 2 onto 3", we get [0: 0, 1: 1, 2:, 3: 3 2]. If we then run a
"pile 3 over 1", we should end up with [0: 0, 1: 1 3 2, 2:, 3:]. And so
on.
</p>
        <p>
 
</p>
        <p>
          <strong>Input:</strong> n = 10. Run these commands:
</p>
        <ol>
          <li>
move 9 onto 1</li>
          <li>
move 8 over 1</li>
          <li>
move 7 over 1</li>
          <li>
move 6 over 1</li>
          <li>
pile 8 over 6</li>
          <li>
pile 8 over 5</li>
          <li>
move 2 over 1</li>
          <li>
move 4 over 9</li>
          <li>
quit</li>
        </ol>
        <p>
The result should be [0: 0, 1: 1 9 2 4, 2:, 3: 3, 4:, 5: 5 8 7 6, 6:, 7:, 8:, 9:]
</p>
        <p>
 
</p>
        <p>
          <strong>Challenges:</strong>
        </p>
        <ul>
          <li>
Implement the Towers of Hanoi (or as close to it as you can get) using this system.</li>
          <li>
Add an optimizer to the arm, in essence reading in the entire program (up to "quit"),
finding shorter paths and/or different commands to achieve the same result.</li>
          <li>
Add a visual component to the simulation, displaying the arm as it moves over each
block and moves blocks around.</li>
          <li>
Add another robotic arm, and allow commands to be given simultaneously. This will
require some thought—does each arm execute a complete command before allowing the
other arm to execute (which reduces the performance having two arms might offer),
or can each arm act entirely independently? The two (or more) arms will probably need
separate command streams, but you might try running them with one command stream just
for grins. Note that deciding how to synchronized the arms so they don't conflict
with one another will probably require adding some kind of synchronization instructions
into the stream as well.</li>
        </ul>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=0e5b971c-8dd4-48ef-b47c-b9b0611607dd" />
        <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: RoboStack</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,0e5b971c-8dd4-48ef-b47c-b9b0611607dd.aspx</guid>
      <link>http://blogs.tedneward.com/2010/05/10/Code+Kata+RoboStack.aspx</link>
      <pubDate>Mon, 10 May 2010 07:01:36 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;
This one is from the &lt;a href="http://uva.onlinejudge.org/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;category=3&amp;amp;page=show_problem&amp;amp;problem=37" target="_blank"&gt;UVa
online programming contest judge system&lt;/a&gt;, which I discovered after picking up the
book &lt;em&gt;Programming Challenges&lt;/em&gt;, which is highly recommended as a source of code
katas, by the way. Much of the advice parts of the book can be skimmed or ignored
by the long-time professional developer, but it's still worth a read, since it can
be an interesting source of ideas and approaches when solving real-world scenarios.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Problem:&lt;/strong&gt; You work for a manufacturing company, and they have just
received their newest piece of super-modern hardware, a highly efficient assembly-line
mechanized pneumatic item manipulator, also known in some circles as a &amp;quot;robotic
arm&amp;quot;. It is driven by a series of commands, and your job is to write the software
to drive the arm. The initial test will be to have the arm move a series of blocks
around.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Context:&lt;/strong&gt; The test begins with &lt;em&gt;n&lt;/em&gt; number of blocks, laid out
sequentially next to each other, each block with a number on it. (You may safely assume
that &lt;em&gt;n&lt;/em&gt; never exceeds 25.) So, if &lt;em&gt;n&lt;/em&gt; is 4, then the blocks are laid
out (starting from 0) as:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
0: 0
&lt;/p&gt;
&lt;p&gt;
1: 1
&lt;/p&gt;
&lt;p&gt;
2: 2
&lt;/p&gt;
&lt;p&gt;
3: 3
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The display output here is the block-numbered &amp;quot;slot&amp;quot;, then a colon, then
the block(s) that are stacked in that slot, lowest to highest in left to right order.
Thus, in the following display:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
0:
&lt;/p&gt;
&lt;p&gt;
1:
&lt;/p&gt;
&lt;p&gt;
2: 0 1 2 3
&lt;/p&gt;
&lt;p&gt;
3:
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The 3 block is stacked on top of the 2 block is stacked on top of the 1 block is stacked
on top of the 0 block, all in slot 2. This can be shortened to the representation
[0:, 1:, 2: 0 1 2 3, 3:] for conciseness.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
The arm understands a number of different commands, as well as an optic sensor. (Yeah,
the guys who created the arm were good enough to write code that knows how to read
the number off a block, but not to actually drive the arm. Go figure.) The commands
are as follows, where &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; are valid block numbers (meaning they
are between 0 and &lt;em&gt;n&lt;/em&gt;-1):
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&amp;quot;move &lt;em&gt;a&lt;/em&gt; onto &lt;em&gt;b&lt;/em&gt;&amp;quot; This command orders the arm to find block &lt;em&gt;a&lt;/em&gt;,
and return any blocks stacked on top of it to their original position. Do the same
for block &lt;em&gt;b&lt;/em&gt;, then stack block &lt;em&gt;a&lt;/em&gt; on top of &lt;em&gt;b&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&amp;quot;move &lt;em&gt;a&lt;/em&gt; over &lt;em&gt;b&lt;/em&gt;&amp;quot; This command orders the arm to find block &lt;em&gt;a&lt;/em&gt;,
and return any blocks stacked on top of it to their original position. Then stack
block &lt;em&gt;a&lt;/em&gt; on top of the stack of blocks containing &lt;em&gt;b&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&amp;quot;pile &lt;em&gt;a&lt;/em&gt; onto &lt;em&gt;b&lt;/em&gt;&amp;quot; This command orders the arm to find the
stack of blocks containing block &lt;em&gt;b&lt;/em&gt;, and return any blocks stacked on top
of it to their original position. Then the arm must find the stack of blocks containing
block &lt;em&gt;a&lt;/em&gt;, and take the stack of blocks starting from &lt;em&gt;a&lt;/em&gt; on upwards
(in other words, don't do anything with any blocks on top of &lt;em&gt;a&lt;/em&gt;) and put that
stack on top of block &lt;em&gt;b&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&amp;quot;pile &lt;em&gt;a&lt;/em&gt; over &lt;em&gt;b&lt;/em&gt;&amp;quot; This command orders the arm to find the
stack of blocks containing block &lt;em&gt;a&lt;/em&gt; and take the stack of blocks starting
from &lt;em&gt;a&lt;/em&gt; on upwards (in other words, don't do anything with any blocks on top
of &lt;em&gt;a&lt;/em&gt;) and put that stack on top of the stack of blocks containing block &lt;em&gt;b&lt;/em&gt; (in
other words, don't do anything with the stack of blocks containing &lt;em&gt;b&lt;/em&gt;, either).&lt;/li&gt;
&lt;li&gt;
&amp;quot;quit&amp;quot; This command tells the arm to shut down (and thus terminates the
simulation).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Note that if the input command sequence accidentally offers a command where &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; are
the same value, that command is illegal and should be ignored.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
As an example, then, if we have 4 blocks in the state [0: 0, 1: 1, 2: 2, 3: 3], and
run a &amp;quot;move 2 onto 3&amp;quot;, we get [0: 0, 1: 1, 2:, 3: 3 2]. If we then run a
&amp;quot;pile 3 over 1&amp;quot;, we should end up with [0: 0, 1: 1 3 2, 2:, 3:]. And so
on.
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Input:&lt;/strong&gt; n = 10. Run these commands:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
move 9 onto 1&lt;/li&gt;
&lt;li&gt;
move 8 over 1&lt;/li&gt;
&lt;li&gt;
move 7 over 1&lt;/li&gt;
&lt;li&gt;
move 6 over 1&lt;/li&gt;
&lt;li&gt;
pile 8 over 6&lt;/li&gt;
&lt;li&gt;
pile 8 over 5&lt;/li&gt;
&lt;li&gt;
move 2 over 1&lt;/li&gt;
&lt;li&gt;
move 4 over 9&lt;/li&gt;
&lt;li&gt;
quit&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
The result should be [0: 0, 1: 1 9 2 4, 2:, 3: 3, 4:, 5: 5 8 7 6, 6:, 7:, 8:, 9:]
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Challenges:&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Implement the Towers of Hanoi (or as close to it as you can get) using this system.&lt;/li&gt;
&lt;li&gt;
Add an optimizer to the arm, in essence reading in the entire program (up to &amp;quot;quit&amp;quot;),
finding shorter paths and/or different commands to achieve the same result.&lt;/li&gt;
&lt;li&gt;
Add a visual component to the simulation, displaying the arm as it moves over each
block and moves blocks around.&lt;/li&gt;
&lt;li&gt;
Add another robotic arm, and allow commands to be given simultaneously. This will
require some thought—does each arm execute a complete command before allowing the
other arm to execute (which reduces the performance having two arms might offer),
or can each arm act entirely independently? The two (or more) arms will probably need
separate command streams, but you might try running them with one command stream just
for grins. Note that deciding how to synchronized the arms so they don't conflict
with one another will probably require adding some kind of synchronization instructions
into the stream as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=0e5b971c-8dd4-48ef-b47c-b9b0611607dd" /&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,0e5b971c-8dd4-48ef-b47c-b9b0611607dd.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>Mac OS</category>
      <category>Objective-C</category>
      <category>Parrot</category>
      <category>Python</category>
      <category>Ruby</category>
      <category>Security</category>
      <category>Visual Basic</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=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=c95a7acd-a467-4c8e-a72a-2b8d3acee495</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,c95a7acd-a467-4c8e-a72a-2b8d3acee495.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,c95a7acd-a467-4c8e-a72a-2b8d3acee495.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c95a7acd-a467-4c8e-a72a-2b8d3acee495</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I'm excited to say that TechEd has accepted my pre-conference proposal, <em>Multiparadigmatic
C#</em>, where the abstract reads:
</p>
        <blockquote>
          <p>
C# has grown from “just” an object-oriented language into a language that is capable
of expressing several different paradigms of software development: object-oriented,
functional, and dynamic. In this session, developers will learn how to approach programming
in C# to use each of these approaches, and when.
</p>
        </blockquote>
        <p>
If you're interested in seeing C# used in a variety of different ways, come on out.
</p>
        <p>
And if you're not going to <a href="http://northamerica.msteched.com/?CR_CC=100280254&amp;WT.srch=1&amp;CR_SCC=100280254&amp;fbid=xvt_cg-ExsG" target="_blank">TechEd</a>....
why not? It's in New Orleans, folks!
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c95a7acd-a467-4c8e-a72a-2b8d3acee495" />
        <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 TechEd PreCon: Multiparadigmatic C#</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,c95a7acd-a467-4c8e-a72a-2b8d3acee495.aspx</guid>
      <link>http://blogs.tedneward.com/2010/01/15/2010+TechEd+PreCon+Multiparadigmatic+C.aspx</link>
      <pubDate>Fri, 15 Jan 2010 07:49:53 GMT</pubDate>
      <description>&lt;p&gt;
I'm excited to say that TechEd has accepted my pre-conference proposal, &lt;em&gt;Multiparadigmatic
C#&lt;/em&gt;, where the abstract reads:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
C# has grown from “just” an object-oriented language into a language that is capable
of expressing several different paradigms of software development: object-oriented,
functional, and dynamic. In this session, developers will learn how to approach programming
in C# to use each of these approaches, and when.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
If you're interested in seeing C# used in a variety of different ways, come on out.
&lt;/p&gt;
&lt;p&gt;
And if you're not going to &lt;a href="http://northamerica.msteched.com/?CR_CC=100280254&amp;amp;WT.srch=1&amp;amp;CR_SCC=100280254&amp;amp;fbid=xvt_cg-ExsG" target="_blank"&gt;TechEd&lt;/a&gt;....
why not? It's in New Orleans, folks!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c95a7acd-a467-4c8e-a72a-2b8d3acee495" /&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,c95a7acd-a467-4c8e-a72a-2b8d3acee495.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Languages</category>
      <category>Python</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</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=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=3026e434-b1c8-4525-816a-2efcd5d2a6e6</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,3026e434-b1c8-4525-816a-2efcd5d2a6e6.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,3026e434-b1c8-4525-816a-2efcd5d2a6e6.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=3026e434-b1c8-4525-816a-2efcd5d2a6e6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, an email crossed my Inbox from a friend who was concerned about some questionable
practices involving my content (as well as a few others'); apparently, I have been
listed as an "author" for SysCon, I have a "domain" with them,
and that I've been writing for them since 10 January, 2003, including two articles,
"Effective Enterprise Java" and "Java/.NET Interoperability".
</p>
        <p>
Given that both of those "articles" are summaries from <em>presentations</em> I've
done at conferences past, I'm a touch skeptical. In fact, it feels like those summaries
were scraped from conferences I've done in the past, and I <em>certainly</em> don't
remember ever giving Sys-Con (or any other conference) the right to reprint my presentation
as an article.
</p>
        <p>
Then it turns out that apparently <a href="http://aralbalkan.com/2284" target="_blank">I'm
not the only one suffering this problem</a>. Go. Read that article, then come back.
I promise, I'll wait.
</p>
        <p>
(Seriously, go read it.)
</p>
        <p>
Wow. Just... wow. If even <em>half</em> of what Aral's story is true (and I'm inclined
to believe at least part of it, given that he's done some pretty meticulous documentation
of at least his side of the story), then this is beyond outrageous, and squarely into
"completely unethical".
</p>
        <p>
Now, I'll be the first to admit, I've not heard back from Sys-Con about any of this,
so if I get any sort of response I'll be sure to update this blog post. But...
</p>
        <p>
          <em>Calling anyone a "homosexual son of a bitch", "terrorist"
or "fag" is so unbelievably offensive it staggers the mind.</em> Normally,
I'd be a bit hesitant to just give either party the benefit of the doubt on that one,
given just how ludicrous the accusation sounds, but Aral includes screen shots of
the articles, which in of itself lends an air of credibility to the accusation—either
Aral is the world's worst Turkish translator, or Sys-Con's translation into Turkish
is a bit on the "edgy" side, or Sys-Con really did call him that. Which
implies that whichever way this goes, doesn't look good for one of the two parties.
But even if we leave that to one side....
</p>
        <p>
          <em>Sys-Con is playing with fire by collecting my content and claiming me as an author.</em> Sys-Con
never contacted me about becoming a part of their "Ulitzer" website. They
never asked me for permission to reprint my articles, though, I'll admit, I can't
find where the articles actually exist, nor links to the articles, so maybe they didn't,
actually, reprint the article, but just link to them... except I can't find the links
to the articles or the presentations, either. They never asked me for an updated bio
or photo, and in fact, they pretty clearly grabbed both bio, photo and "summaries"
from an old location, because that bio lists me as a DevelopMentor instructor (which
I haven't been for two years or so), and as living in Sacramento, CA (which I haven't
been for about three years or so). Let me be very clear about this: <strong>I do not
write for Sys-Con Media. I never have. They have never asked permission to reuse any
of the content I have produced. I am appalled at being included in such a fashion.</strong></p>
        <p>
Note that I'm not opposed to being linked to, mind you—if I put material on my blog,
I generally expect (and hope) that people will link to it, and I don't demand permission
or even notification when it happens. But to claim that I've written material for
an entity <em>does</em> mean I expect to at least be asked if it's OK to use my likeness,
name, or material. No such request was ever made of me, so far as I can remember or
find (through my own email archives, which stretch back to 2001).
</p>
        <p>
And I can say that I've thought about this issue before, from the other side of the
story—back when I was editor at TheServerSide.NET, we began a "blogger's program"
that would take interesting blog posts from around the Internet and "collect"
them in some fashion for TSS.NET readers. Originally, the thought was to simply reproduce
the content directly on our site, and I hated that idea, for the same reasons as I
dislike it when somebody does it to me. Regardless of the licensing model the blog
entries are published under, to me, a publication or media firm owes the author at
least the right of refusal, and a chance to be notified when their material is reused.
(In the end, we chose to ask authors if we could reproduce their material in the program,
and we never (to my knowledge) had an author refuse.) It doesn't take a real rocket
scientist's brain to figure out that asking permission is never a bad thing to do
if you want to maintain good will with your sources of material.
</p>
        <p>
This is an open and public request to Sys-Con media: either contact me about using
my name, likeness and material on your website, or remove it. (I have emailed their
editorial and asked them to acknowledge receipt of my request.)
</p>
        <p>
In the meantime, I will be making every effort to make sure that other content-producers
I know are aware of Sys-Con's practices, so they can act as they see fit.
</p>
        <p>
If you are a reader, and find this distasteful as well, then I suggest you follow
some of the suggestions mentioned in Aral's blog post:
</p>
        <ul>
          <ul>
            <li>
Tell everyone you know about what Sys-Con is doing (but don't link to them so as not
to give them Google Juice). If tweeting, leave out the http:// bit so that your URL
is not automatically made into a link. 
</li>
            <li>
Sys-Con feeds upon the work of authors and speakers to live. If all authors had their
content removed from Sys-Con and Ulitzer, they would not have pages to put ads on.
So go through their list of authors and notify the ones you know. If they are unaware
that they're listed there, they will most likely want themselves removed. <strong>Update:</strong> I've
created a single list of all Sys-Con's Ulitzer authors. <a href="http://aralbalkan.com/2303">More
information and the full list are in this post</a>. The original list of authors is
at http://www.ulitzer.com/?q=authors. You can ask for your Ulitzer/Sys-Con author
page to be removed by emailing <a href="mailto:editorial@sys-con.com">editorial@sys-con.com</a>. 
</li>
            <li>
Contact their advertisers and tell them what you think of their association with Sys-Con. 
</li>
            <li>
If you know any speakers speaking at Sys-Con events, make sure they know the kind
of company they are associating themselves with. Do the same with anyone you know
who is thinking of attending one of their events. Raise awareness about their events
at your place of work. 
</li>
            <li>
Make sure Google knows that Sys-Con/Ulitzer is spamming Google with tons of duplicate
content. <a href="http://www.google.com/contact/spamreport.html">Report them on Google's
spam page for posting duplicate content</a>. According to their terms and conditions,
Google should stop indexing Sys-Con/Ulitzer. <a href="http://aralbalkan.com/2284#comment-256711">See
this comment for a template you can use when reporting them.</a></li>
            <li>
Make sure Google News knows that they are syndicating libelous articles from Sys-Con.
Use the <a href="http://www.google.com/support/news_pub/bin/request.py?contact_type=report_an_issue">Google
News Report an Issue form</a> to report the following articles: http://internetvideo.sys-con.com/node/1017038,
http://internetvideo.sys-con.com/node/1028923, http://www.sys-con.com/node/1035252,
http://air.ulitzer.com/node/1038383, http://openwebdeveloper.sys-con.com/node/1039556,
and http://cloudcomputing.sys-con.com/node/1047589 
</li>
          </ul>
        </ul>
        <p>
Meanwhile, I'm going to be talking about this to everybody I know at Microsoft, desperately
seeking to find out which department engaged the advertising with Sys-Con, and looking
to convince them that they don't need this kind of press or association. Ditto for
the contacts (far fewer in number) I have with IBM, and any other Sys-Con advertiser
I find.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=3026e434-b1c8-4525-816a-2efcd5d2a6e6" />
        <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>More on journalistic integrity: Sys-Con, Ulitzer, theft and libel</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,3026e434-b1c8-4525-816a-2efcd5d2a6e6.aspx</guid>
      <link>http://blogs.tedneward.com/2009/07/29/More+On+Journalistic+Integrity+SysCon+Ulitzer+Theft+And+Libel.aspx</link>
      <pubDate>Wed, 29 Jul 2009 01:58:00 GMT</pubDate>
      <description>&lt;p&gt;
Recently, an email crossed my Inbox from a friend who was concerned about some questionable
practices involving my content (as well as a few others'); apparently, I have been
listed as an &amp;quot;author&amp;quot; for SysCon, I have a &amp;quot;domain&amp;quot; with them,
and that I've been writing for them since 10 January, 2003, including two articles,
&amp;quot;Effective Enterprise Java&amp;quot; and &amp;quot;Java/.NET Interoperability&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
Given that both of those &amp;quot;articles&amp;quot; are summaries from &lt;em&gt;presentations&lt;/em&gt; I've
done at conferences past, I'm a touch skeptical. In fact, it feels like those summaries
were scraped from conferences I've done in the past, and I &lt;em&gt;certainly&lt;/em&gt; don't
remember ever giving Sys-Con (or any other conference) the right to reprint my presentation
as an article.
&lt;/p&gt;
&lt;p&gt;
Then it turns out that apparently &lt;a href="http://aralbalkan.com/2284" target="_blank"&gt;I'm
not the only one suffering this problem&lt;/a&gt;. Go. Read that article, then come back.
I promise, I'll wait.
&lt;/p&gt;
&lt;p&gt;
(Seriously, go read it.)
&lt;/p&gt;
&lt;p&gt;
Wow. Just... wow. If even &lt;em&gt;half&lt;/em&gt; of what Aral's story is true (and I'm inclined
to believe at least part of it, given that he's done some pretty meticulous documentation
of at least his side of the story), then this is beyond outrageous, and squarely into
&amp;quot;completely unethical&amp;quot;.
&lt;/p&gt;
&lt;p&gt;
Now, I'll be the first to admit, I've not heard back from Sys-Con about any of this,
so if I get any sort of response I'll be sure to update this blog post. But...
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Calling anyone a &amp;quot;homosexual son of a bitch&amp;quot;, &amp;quot;terrorist&amp;quot;
or &amp;quot;fag&amp;quot; is so unbelievably offensive it staggers the mind.&lt;/em&gt; Normally,
I'd be a bit hesitant to just give either party the benefit of the doubt on that one,
given just how ludicrous the accusation sounds, but Aral includes screen shots of
the articles, which in of itself lends an air of credibility to the accusation—either
Aral is the world's worst Turkish translator, or Sys-Con's translation into Turkish
is a bit on the &amp;quot;edgy&amp;quot; side, or Sys-Con really did call him that. Which
implies that whichever way this goes, doesn't look good for one of the two parties.
But even if we leave that to one side....
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Sys-Con is playing with fire by collecting my content and claiming me as an author.&lt;/em&gt; Sys-Con
never contacted me about becoming a part of their &amp;quot;Ulitzer&amp;quot; website. They
never asked me for permission to reprint my articles, though, I'll admit, I can't
find where the articles actually exist, nor links to the articles, so maybe they didn't,
actually, reprint the article, but just link to them... except I can't find the links
to the articles or the presentations, either. They never asked me for an updated bio
or photo, and in fact, they pretty clearly grabbed both bio, photo and &amp;quot;summaries&amp;quot;
from an old location, because that bio lists me as a DevelopMentor instructor (which
I haven't been for two years or so), and as living in Sacramento, CA (which I haven't
been for about three years or so). Let me be very clear about this: &lt;strong&gt;I do not
write for Sys-Con Media. I never have. They have never asked permission to reuse any
of the content I have produced. I am appalled at being included in such a fashion.&lt;/strong&gt; 
&lt;/p&gt;
&lt;p&gt;
Note that I'm not opposed to being linked to, mind you—if I put material on my blog,
I generally expect (and hope) that people will link to it, and I don't demand permission
or even notification when it happens. But to claim that I've written material for
an entity &lt;em&gt;does&lt;/em&gt; mean I expect to at least be asked if it's OK to use my likeness,
name, or material. No such request was ever made of me, so far as I can remember or
find (through my own email archives, which stretch back to 2001).
&lt;/p&gt;
&lt;p&gt;
And I can say that I've thought about this issue before, from the other side of the
story—back when I was editor at TheServerSide.NET, we began a &amp;quot;blogger's program&amp;quot;
that would take interesting blog posts from around the Internet and &amp;quot;collect&amp;quot;
them in some fashion for TSS.NET readers. Originally, the thought was to simply reproduce
the content directly on our site, and I hated that idea, for the same reasons as I
dislike it when somebody does it to me. Regardless of the licensing model the blog
entries are published under, to me, a publication or media firm owes the author at
least the right of refusal, and a chance to be notified when their material is reused.
(In the end, we chose to ask authors if we could reproduce their material in the program,
and we never (to my knowledge) had an author refuse.) It doesn't take a real rocket
scientist's brain to figure out that asking permission is never a bad thing to do
if you want to maintain good will with your sources of material.
&lt;/p&gt;
&lt;p&gt;
This is an open and public request to Sys-Con media: either contact me about using
my name, likeness and material on your website, or remove it. (I have emailed their
editorial and asked them to acknowledge receipt of my request.)
&lt;/p&gt;
&lt;p&gt;
In the meantime, I will be making every effort to make sure that other content-producers
I know are aware of Sys-Con's practices, so they can act as they see fit.
&lt;/p&gt;
&lt;p&gt;
If you are a reader, and find this distasteful as well, then I suggest you follow
some of the suggestions mentioned in Aral's blog post:
&lt;/p&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;
Tell everyone you know about what Sys-Con is doing (but don't link to them so as not
to give them Google Juice). If tweeting, leave out the http:// bit so that your URL
is not automatically made into a link. 
&lt;/li&gt;
&lt;li&gt;
Sys-Con feeds upon the work of authors and speakers to live. If all authors had their
content removed from Sys-Con and Ulitzer, they would not have pages to put ads on.
So go through their list of authors and notify the ones you know. If they are unaware
that they're listed there, they will most likely want themselves removed. &lt;strong&gt;Update:&lt;/strong&gt; I've
created a single list of all Sys-Con's Ulitzer authors. &lt;a href="http://aralbalkan.com/2303"&gt;More
information and the full list are in this post&lt;/a&gt;. The original list of authors is
at http://www.ulitzer.com/?q=authors. You can ask for your Ulitzer/Sys-Con author
page to be removed by emailing &lt;a href="mailto:editorial@sys-con.com"&gt;editorial@sys-con.com&lt;/a&gt;. 
&lt;/li&gt;
&lt;li&gt;
Contact their advertisers and tell them what you think of their association with Sys-Con. 
&lt;/li&gt;
&lt;li&gt;
If you know any speakers speaking at Sys-Con events, make sure they know the kind
of company they are associating themselves with. Do the same with anyone you know
who is thinking of attending one of their events. Raise awareness about their events
at your place of work. 
&lt;/li&gt;
&lt;li&gt;
Make sure Google knows that Sys-Con/Ulitzer is spamming Google with tons of duplicate
content. &lt;a href="http://www.google.com/contact/spamreport.html"&gt;Report them on Google's
spam page for posting duplicate content&lt;/a&gt;. According to their terms and conditions,
Google should stop indexing Sys-Con/Ulitzer. &lt;a href="http://aralbalkan.com/2284#comment-256711"&gt;See
this comment for a template you can use when reporting them.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Make sure Google News knows that they are syndicating libelous articles from Sys-Con.
Use the &lt;a href="http://www.google.com/support/news_pub/bin/request.py?contact_type=report_an_issue"&gt;Google
News Report an Issue form&lt;/a&gt; to report the following articles: http://internetvideo.sys-con.com/node/1017038,
http://internetvideo.sys-con.com/node/1028923, http://www.sys-con.com/node/1035252,
http://air.ulitzer.com/node/1038383, http://openwebdeveloper.sys-con.com/node/1039556,
and http://cloudcomputing.sys-con.com/node/1047589 
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;
Meanwhile, I'm going to be talking about this to everybody I know at Microsoft, desperately
seeking to find out which department engaged the advertising with Sys-Con, and looking
to convince them that they don't need this kind of press or association. Ditto for
the contacts (far fewer in number) I have with IBM, and any other Sys-Con advertiser
I find.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=3026e434-b1c8-4525-816a-2efcd5d2a6e6" /&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,3026e434-b1c8-4525-816a-2efcd5d2a6e6.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Industry</category>
      <category>Java/J2EE</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Security</category>
      <category>Social</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=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=8da33b92-cb5f-466a-b2d1-a20f4355ed73</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,8da33b92-cb5f-466a-b2d1-a20f4355ed73.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,8da33b92-cb5f-466a-b2d1-a20f4355ed73.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8da33b92-cb5f-466a-b2d1-a20f4355ed73</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
It's been going around in developer circles now for a few days, this whole controversy
about the "Perform like a pr0n star" <a href="http://www.slideshare.net/mattetti/couchdb-perform-like-a-pr0n-star">presentation</a> from
the <a href="http://gogaruco.com/">Golden Gate Ruby Conference</a> and the related
accusations of misogyny and sexism and overblown accusations and double-standardisms
and what-all else, and I've deliberately waited to let opinions in my head settle
out before blogging on the whole thing. <a href="http://girldeveloper.com/intar-social-commentary/c-mon-you-guys-we-can-do-better-than-this/">Sara
J Chipps reacts on her blog</a>, and the comments to her comments are also somewhat...
interesting... to note.
</p>
        <p>
Without any particular implied importance or order:
</p>
        <ul>
          <li>
            <strong>Matt Aimonetti, you are an idiot.</strong> You had to know that this was going
to generate more than a few strong reactions. I'll admit, it's a funny title, and
it definitely generated a ton of buzz around your name, but for the rest of your life,
you're going to be "the porno Rails guy", and in about a year or so, it's
not going to be funny anymore. You've touched off a firestorm, and you can't very
well hide from it, and frankly, I think the short-term boost to your public recognizance
is going to be more than outweighed by the long-term judgments that will be levied
against you. "Wait, <em>this</em> is the guy who did that talk? Wow. I bet he's
a good developer, but can I risk him pulling the same kind of stunt at a meeting with
our VP or clients? Nah, I'll go for this other guy...."</li>
          <li>
            <strong>Clearly we have a lot of issues to work out in the programming industry.</strong> I'm
not going to go into the rights or wrongs of putting those images into his talk. I'm
talking about the discussion that followed (one comment here says, "Matt Aimonetti
is obviously an antisocial twerp still living in his mothers basement at the age of
35 who has never even been able to muster up the courage to actually talk to a real-life
woman, let alone respect one.", and a follow-up comment says, "Great presentation,
nevermind the jackasses, keep up the good work!"), and the fact that at no point
in the time leading up to this presentation did anybody pull Mr. Aimonetti off to
one side and say, "Dude, it was funny when we thought of it, sure, but it's time
to stop." If ever we wanted to convince the rest of the world that the programming
industry wasn't populated by a bunch of 13-year-olds giggling over the fact that somebody
said, "Boobies".... well, maybe next year.</li>
          <li>
            <strong>Ruby community, you have a long way to go if you want to convince people to
spend money on you.</strong> Maybe you don't mind that corporations think that you
guys are clearly unstable and immature. If/when you want to gain some degree of corporate
acceptance, and maybe make it out of your parents' basement someday, you're going
to have to learn that how you handle yourself in public goes a long way towards establishing
peoples' attitudes towards you as professionals, and right now, you all collectively
look like a bunch of 13-year-olds, what between this and DHH's famous "FUCK YOU"
presentation of a few years ago. If you're OK with not being taken seriously, then
cool, more power to you. But personally, I like the idea of making money at things
I like to do and have fun doing, and you're not helping yourselves.</li>
          <li>
            <strong>Why are we such prudes?</strong> Whether you agree or not with the rightness
of the "porn" metaphor, you have to admit that there is factual basis in
the bones of this particular comment: "This is probably the least offensive thing
I've seen in 3 weeks." Glance at the billboards in the airport next time you're
walking to the gate. Glance at the racks of magazines in the grocery store as you
prepare to check out. Glance at the beer commercials on TV during prime-time. In every
case, sexy, young, attractive, scantily-clad men and women seek to create an instinctive
emotional reaction inside your head to subconsciously create a feel-good link between
whatever product is being hawked and your id. Honestly, the photos in the presentation
are hardly all that titillating—and a very long ways from the kind of commercials
you can see on TV in Europe—so why are we getting up in arms over this?</li>
          <li>
            <strong>Matt Aimonetti, you are an idiot.</strong> Notice how nobody's talking about
the actual subject of your presentation? A good presenter knows that the message should
never outstrip the delivery mechanism, just like a sauce should never overpower the
flavor of the dish it accompanies. For all that the <em>content</em> of your presentation
might have been spot-on, the lessons that might have been learned from the presentation
have drowned in the "He's a pig!" "No he's not!" that has followed.
Great job there, mate. Way to get your message across.</li>
          <li>
            <strong>To the commenter on the presentation page who said, "ps [sic] feminism
is dead", get a clue.</strong> Women still, on average, get paid less than men
do for an equivalently-skilled employee in the same job. Maybe it's not $.50 to every
$1 as it used to be, but so long as it's even measurable, there's work to be done.
This industry in particular has absolutely no reason for gender discrimination in
any form, since there's absolutely nothing "physical" about what we do.
(Ditto for medicine and law, for that matter.)</li>
          <li>
            <strong>Presentations reach far beyond just the attendees.</strong> One commenter
on Sara's blog notes, "What an over reaction, there was nothing wrong with that
presentation, i wouldn't show it to a board room but as far as showing it to a ruby
developers conference then no probs." Frankly, that's a short-sighted attitude,
making the presumption that someone of the suit-and-tie set (those supposedly inhabiting
the "board room" where this kind of presentation isn't appropriate) wouldn't
actually be in the audience at a ruby developers conference. Oh, granted, when in
Rome, one has to expect Romans to act like Romans, but that just means that the Ruby
community isn't welcome inside the board room, right? (Somehow I doubt this is what
the numerous people who are trying to make money off of Ruby really want.) Fact is,
that presentation is now captured by the Internet for all time, and it will forever
be known as "The Ruby Porno Presentation", and it's an even money bet that
somebody in that board room has seen the presentation (and the video, and the play-by-play
from the people who had friends who had friends that were there....).</li>
          <li>
            <strong>To the commenters who say, "You asked for it", get a clue.</strong> Commenters
have suggested that the title should have clued people into what was coming: "I'm
totally flabbergasted no one has stated the obvious here: if you see a presentation
labeled "CouchDB: Perform like a pr0n star" and you choose to go to it,
don't act all surprised when R-rated images are used as props." Sorry, no biscuit.
Presenters use analogies and imagery all the time in their titles in order to "sell"
their talks. Recently I was part of a talk that was labeled as a "smackdown"—did
that mean the audience should have expected to see images of physical violence? If
I title my next talk as something that's "hard-core", should you expect
to see images of ball gags and snuff film clips? This is what happens when we co-opt
terms like "smackdown" and "hard-core"—you can't fall back to
the original meanings and then claim ignorance when people misunderstand how you're
going to use them. (God only knows what Mr. Aimonetti would have done for a presentation
on "Naked Objects". *shudder*)</li>
          <li>
            <strong>Matt Aimonetti, you are an idiot. </strong>You could have had your joke and
keep it tasteful too. You do, in fact, from time to time in the early part of the
presentation: the photo of the "little blue pills" was perfect, offering
a hint as to what you meant while keeping the <em>double-entendre</em> alive. Every
single "objectionable" photo in that presentation could have been replaced
by a more subtle one that kept everybody's mind on the subject and still got the point
across. The fact that you resorted to the heavy-handed imagery only proves that you
wanted to beat the audience's head with it.</li>
          <li>
            <strong>Please, let the one-ups-manship stop.</strong> Can we please agree that moving
and powerful presentations can be done without having to resort to cheap tricks? They
almost always come off badly, particularly when you have to keep the gag running for
a full hour or so. Anybody remember Marc Fleury's "Joker" retinue at TheServerSide
a half-decade ago? Can you tell me what his presentation was about? Now, consider
Dave Thomas' "Cargo Cults" talk from NFJS around the same time—what was
he covering? If you were there for both talks, chances are you remember Dave's talk
far better than you remember the Fleury keynote beyond the fact that he wore Joker
face paint the entire time. Good presentations are about using humor to underscore
and support the message, and not making humor the central point of the message. Think
about that before you start reaching for the bad innuendo.</li>
          <li>
            <strong>Is this really the kind of industry we want?</strong> Granted, it may seem
like all of this is way overblown if you're a 25-year-old guy recently graduated from
college and hacking on your first or second Rails project. "What do these grumpy
idiots not understand about 'it's a joke'? My God, is everybody nuts? Are they trying
to say that we can't have fun at work or with what we do?" To which all I can
say is two things: one, check in with yourself five or ten years from now, when your
daughters are learning about body images by staring at pictures of women who are entirely
artificial (and yes, guys, those pictures you see are entirely artificial, having
been touched up and enhanced in many ways), and two, you're more than welcome to have
whatever jokes you like at whomever's expense you like, in private. This wasn't in
private. A developer conference is not a private locale. More importantly, though,
think about it—when you bring your girlfriend to work, do you want her hearing those
same jokes that buddies toss off back and forth? What seems like "harmless fun"
now, may have a very different feel to it for you a few years from now.</li>
        </ul>
        <p>
I'll freely admit, I drop profanity from time to time in my presentations. And to
everyone who comes up afterwords (figuratively and literally) saying I shouldn't use
such offensive language, I apologize, and point out that I did so in order to underscore
the point, knowing that I'm taking that risk, and knowing that I may be required to
offer up apologies after the fact for having offended them. (To date, those apologies
still number in the single digits.) So perhaps I am no better than Mr. Aimonetti in
the final accounting of things.
</p>
        <p>
But all of this loses sight of a core principle. Regardless of the efficacy of his
presentation, regardless of your feelings about the subject matter, regardless of
your thoughts around the overblown-or-not nature of this discussion, a deeper principle
is at stake here, that of professional presentation etiquette: Mr. Aimonetti, you
owe an apology to anyone and everyone that was offended by your presentation (for
whatever reason). Failure to deliver that, in my mind, equates to a personal and professional
FAIL on your part. 
</p>
        <p>
When you stand up on stage, and you say something that somebody finds offensive, you
owe that person an apology, even if you think their reasoning or rationale is bogus.
</p>
        <p>
It's simple common courtesy.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8da33b92-cb5f-466a-b2d1-a20f4355ed73" />
        <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>On speaking, trolling, inciting and growing</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,8da33b92-cb5f-466a-b2d1-a20f4355ed73.aspx</guid>
      <link>http://blogs.tedneward.com/2009/05/01/On+Speaking+Trolling+Inciting+And+Growing.aspx</link>
      <pubDate>Fri, 01 May 2009 06:03:32 GMT</pubDate>
      <description>&lt;p&gt;
It's been going around in developer circles now for a few days, this whole controversy
about the &amp;quot;Perform like a pr0n star&amp;quot; &lt;a href="http://www.slideshare.net/mattetti/couchdb-perform-like-a-pr0n-star"&gt;presentation&lt;/a&gt; from
the &lt;a href="http://gogaruco.com/"&gt;Golden Gate Ruby Conference&lt;/a&gt; and the related
accusations of misogyny and sexism and overblown accusations and double-standardisms
and what-all else, and I've deliberately waited to let opinions in my head settle
out before blogging on the whole thing. &lt;a href="http://girldeveloper.com/intar-social-commentary/c-mon-you-guys-we-can-do-better-than-this/"&gt;Sara
J Chipps reacts on her blog&lt;/a&gt;, and the comments to her comments are also somewhat...
interesting... to note.
&lt;/p&gt;
&lt;p&gt;
Without any particular implied importance or order:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Matt Aimonetti, you are an idiot.&lt;/strong&gt; You had to know that this was going
to generate more than a few strong reactions. I'll admit, it's a funny title, and
it definitely generated a ton of buzz around your name, but for the rest of your life,
you're going to be &amp;quot;the porno Rails guy&amp;quot;, and in about a year or so, it's
not going to be funny anymore. You've touched off a firestorm, and you can't very
well hide from it, and frankly, I think the short-term boost to your public recognizance
is going to be more than outweighed by the long-term judgments that will be levied
against you. &amp;quot;Wait, &lt;em&gt;this&lt;/em&gt; is the guy who did that talk? Wow. I bet he's
a good developer, but can I risk him pulling the same kind of stunt at a meeting with
our VP or clients? Nah, I'll go for this other guy....&amp;quot;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clearly we have a lot of issues to work out in the programming industry.&lt;/strong&gt; I'm
not going to go into the rights or wrongs of putting those images into his talk. I'm
talking about the discussion that followed (one comment here says, &amp;quot;Matt Aimonetti
is obviously an antisocial twerp still living in his mothers basement at the age of
35 who has never even been able to muster up the courage to actually talk to a real-life
woman, let alone respect one.&amp;quot;, and a follow-up comment says, &amp;quot;Great presentation,
nevermind the jackasses, keep up the good work!&amp;quot;), and the fact that at no point
in the time leading up to this presentation did anybody pull Mr. Aimonetti off to
one side and say, &amp;quot;Dude, it was funny when we thought of it, sure, but it's time
to stop.&amp;quot; If ever we wanted to convince the rest of the world that the programming
industry wasn't populated by a bunch of 13-year-olds giggling over the fact that somebody
said, &amp;quot;Boobies&amp;quot;.... well, maybe next year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby community, you have a long way to go if you want to convince people to
spend money on you.&lt;/strong&gt; Maybe you don't mind that corporations think that you
guys are clearly unstable and immature. If/when you want to gain some degree of corporate
acceptance, and maybe make it out of your parents' basement someday, you're going
to have to learn that how you handle yourself in public goes a long way towards establishing
peoples' attitudes towards you as professionals, and right now, you all collectively
look like a bunch of 13-year-olds, what between this and DHH's famous &amp;quot;FUCK YOU&amp;quot;
presentation of a few years ago. If you're OK with not being taken seriously, then
cool, more power to you. But personally, I like the idea of making money at things
I like to do and have fun doing, and you're not helping yourselves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why are we such prudes?&lt;/strong&gt; Whether you agree or not with the rightness
of the &amp;quot;porn&amp;quot; metaphor, you have to admit that there is factual basis in
the bones of this particular comment: &amp;quot;This is probably the least offensive thing
I've seen in 3 weeks.&amp;quot; Glance at the billboards in the airport next time you're
walking to the gate. Glance at the racks of magazines in the grocery store as you
prepare to check out. Glance at the beer commercials on TV during prime-time. In every
case, sexy, young, attractive, scantily-clad men and women seek to create an instinctive
emotional reaction inside your head to subconsciously create a feel-good link between
whatever product is being hawked and your id. Honestly, the photos in the presentation
are hardly all that titillating—and a very long ways from the kind of commercials
you can see on TV in Europe—so why are we getting up in arms over this?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Matt Aimonetti, you are an idiot.&lt;/strong&gt; Notice how nobody's talking about
the actual subject of your presentation? A good presenter knows that the message should
never outstrip the delivery mechanism, just like a sauce should never overpower the
flavor of the dish it accompanies. For all that the &lt;em&gt;content&lt;/em&gt; of your presentation
might have been spot-on, the lessons that might have been learned from the presentation
have drowned in the &amp;quot;He's a pig!&amp;quot; &amp;quot;No he's not!&amp;quot; that has followed.
Great job there, mate. Way to get your message across.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To the commenter on the presentation page who said, &amp;quot;ps [sic] feminism
is dead&amp;quot;, get a clue.&lt;/strong&gt; Women still, on average, get paid less than men
do for an equivalently-skilled employee in the same job. Maybe it's not $.50 to every
$1 as it used to be, but so long as it's even measurable, there's work to be done.
This industry in particular has absolutely no reason for gender discrimination in
any form, since there's absolutely nothing &amp;quot;physical&amp;quot; about what we do.
(Ditto for medicine and law, for that matter.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presentations reach far beyond just the attendees.&lt;/strong&gt; One commenter
on Sara's blog notes, &amp;quot;What an over reaction, there was nothing wrong with that
presentation, i wouldn't show it to a board room but as far as showing it to a ruby
developers conference then no probs.&amp;quot; Frankly, that's a short-sighted attitude,
making the presumption that someone of the suit-and-tie set (those supposedly inhabiting
the &amp;quot;board room&amp;quot; where this kind of presentation isn't appropriate) wouldn't
actually be in the audience at a ruby developers conference. Oh, granted, when in
Rome, one has to expect Romans to act like Romans, but that just means that the Ruby
community isn't welcome inside the board room, right? (Somehow I doubt this is what
the numerous people who are trying to make money off of Ruby really want.) Fact is,
that presentation is now captured by the Internet for all time, and it will forever
be known as &amp;quot;The Ruby Porno Presentation&amp;quot;, and it's an even money bet that
somebody in that board room has seen the presentation (and the video, and the play-by-play
from the people who had friends who had friends that were there....).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To the commenters who say, &amp;quot;You asked for it&amp;quot;, get a clue.&lt;/strong&gt; Commenters
have suggested that the title should have clued people into what was coming: &amp;quot;I'm
totally flabbergasted no one has stated the obvious here: if you see a presentation
labeled &amp;quot;CouchDB: Perform like a pr0n star&amp;quot; and you choose to go to it,
don't act all surprised when R-rated images are used as props.&amp;quot; Sorry, no biscuit.
Presenters use analogies and imagery all the time in their titles in order to &amp;quot;sell&amp;quot;
their talks. Recently I was part of a talk that was labeled as a &amp;quot;smackdown&amp;quot;—did
that mean the audience should have expected to see images of physical violence? If
I title my next talk as something that's &amp;quot;hard-core&amp;quot;, should you expect
to see images of ball gags and snuff film clips? This is what happens when we co-opt
terms like &amp;quot;smackdown&amp;quot; and &amp;quot;hard-core&amp;quot;—you can't fall back to
the original meanings and then claim ignorance when people misunderstand how you're
going to use them. (God only knows what Mr. Aimonetti would have done for a presentation
on &amp;quot;Naked Objects&amp;quot;. *shudder*)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Matt Aimonetti, you are an idiot. &lt;/strong&gt;You could have had your joke and
keep it tasteful too. You do, in fact, from time to time in the early part of the
presentation: the photo of the &amp;quot;little blue pills&amp;quot; was perfect, offering
a hint as to what you meant while keeping the &lt;em&gt;double-entendre&lt;/em&gt; alive. Every
single &amp;quot;objectionable&amp;quot; photo in that presentation could have been replaced
by a more subtle one that kept everybody's mind on the subject and still got the point
across. The fact that you resorted to the heavy-handed imagery only proves that you
wanted to beat the audience's head with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Please, let the one-ups-manship stop.&lt;/strong&gt; Can we please agree that moving
and powerful presentations can be done without having to resort to cheap tricks? They
almost always come off badly, particularly when you have to keep the gag running for
a full hour or so. Anybody remember Marc Fleury's &amp;quot;Joker&amp;quot; retinue at TheServerSide
a half-decade ago? Can you tell me what his presentation was about? Now, consider
Dave Thomas' &amp;quot;Cargo Cults&amp;quot; talk from NFJS around the same time—what was
he covering? If you were there for both talks, chances are you remember Dave's talk
far better than you remember the Fleury keynote beyond the fact that he wore Joker
face paint the entire time. Good presentations are about using humor to underscore
and support the message, and not making humor the central point of the message. Think
about that before you start reaching for the bad innuendo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is this really the kind of industry we want?&lt;/strong&gt; Granted, it may seem
like all of this is way overblown if you're a 25-year-old guy recently graduated from
college and hacking on your first or second Rails project. &amp;quot;What do these grumpy
idiots not understand about 'it's a joke'? My God, is everybody nuts? Are they trying
to say that we can't have fun at work or with what we do?&amp;quot; To which all I can
say is two things: one, check in with yourself five or ten years from now, when your
daughters are learning about body images by staring at pictures of women who are entirely
artificial (and yes, guys, those pictures you see are entirely artificial, having
been touched up and enhanced in many ways), and two, you're more than welcome to have
whatever jokes you like at whomever's expense you like, in private. This wasn't in
private. A developer conference is not a private locale. More importantly, though,
think about it—when you bring your girlfriend to work, do you want her hearing those
same jokes that buddies toss off back and forth? What seems like &amp;quot;harmless fun&amp;quot;
now, may have a very different feel to it for you a few years from now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I'll freely admit, I drop profanity from time to time in my presentations. And to
everyone who comes up afterwords (figuratively and literally) saying I shouldn't use
such offensive language, I apologize, and point out that I did so in order to underscore
the point, knowing that I'm taking that risk, and knowing that I may be required to
offer up apologies after the fact for having offended them. (To date, those apologies
still number in the single digits.) So perhaps I am no better than Mr. Aimonetti in
the final accounting of things.
&lt;/p&gt;
&lt;p&gt;
But all of this loses sight of a core principle. Regardless of the efficacy of his
presentation, regardless of your feelings about the subject matter, regardless of
your thoughts around the overblown-or-not nature of this discussion, a deeper principle
is at stake here, that of professional presentation etiquette: Mr. Aimonetti, you
owe an apology to anyone and everyone that was offended by your presentation (for
whatever reason). Failure to deliver that, in my mind, equates to a personal and professional
FAIL on your part. 
&lt;/p&gt;
&lt;p&gt;
When you stand up on stage, and you say something that somebody finds offensive, you
owe that person an apology, even if you think their reasoning or rationale is bogus.
&lt;/p&gt;
&lt;p&gt;
It's simple common courtesy.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8da33b92-cb5f-466a-b2d1-a20f4355ed73" /&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,8da33b92-cb5f-466a-b2d1-a20f4355ed73.aspx</comments>
      <category>Conferences</category>
      <category>Industry</category>
      <category>Ruby</category>
      <category>Social</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=429e21f9-875c-4b10-815c-0d98e97a2605</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,429e21f9-875c-4b10-815c-0d98e97a2605.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,429e21f9-875c-4b10-815c-0d98e97a2605.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=429e21f9-875c-4b10-815c-0d98e97a2605</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This crossed my Inbox:
</p>
        <blockquote>
          <p>
I read your article entitled: The Polyglot Programmer. How about the thought that
rather than becoming a polyglot-software engineer; pick a polyglot-language. For example,
C# is borrowing techniques from functional and dynamic languages. Let the compiler
designer worry about mixing features and software engineers worry about keep up with
the mixture. Is this a good approach? <em>[From Phil, at <a href="http://greensoftwareengineer.spaces.live.com/">http://greensoftwareengineer.spaces.live.com/</a>]</em></p>
        </blockquote>
        <p>
Phil, it’s an interesting thought you’ve raised—which is the better/easier approach
to take, that of incorporating the language features we want into a single language,
rather than needing to learn all those different languages (and their own unique syntaxes)
in order to take advantage of those features we want?
</p>
        <p>
After all, we’re starting to see this taking place within a certain number of languages
already, particularly C#; first, in 3.0, they introduced a number of features in support
of LINQ that make C# a useful starting point for working with a functional language.
Extension methods, for example, allow us to add a number of different methods to the
collection classes that provide some functional capabilities (Select&lt;&gt;, GroupBy&lt;&gt;,
and so on), as Matt Podwysocki demonstrates, generics contribute the type-safety that
most functional languages embrace, anonymous methods and delegates provide better
functions-as-first-class-constructs (including lambdas), and anonymous types make
it vastly easier to return and pass tuples. And now, in 4.0, we’re getting the “dynamic”
keyword, which will add support for invoking methods and properties dynamically, in
the grand tradition of most dynamic languages (like Python and Ruby), and 3.0’s local
variable type inference allows us to write “var x = ...”, which feels pretty dynamic
(even if it’s not, under the hood).
</p>
        <p>
Unfortunately, I think for the most part, the answer’s going to be, “Yes, it would
be nice, if it weren’t for the fact that there are very few languages that won’t collapse
underneath their own weight if they did so.”
</p>
        <p>
Consider, for example, the C# language. Already, with the C# 3.0 definition, the language
specification weighs in at close to a thousand pages. The additional features in 4.0
could easily push it over a thousand and possibly, with all the places where “dynamic”
behavior will need to be factored into the existing specification, could push that
well into the 1200 to 1300 page range. What’s the upper limit on a language’s complexity
to maintain and enhance, much less for its programmers to comprehend?
</p>
        <p>
(By comparison, the C++ specification, as I can best remember, didn’t weigh in at
more than a thousand pages, but given that the current working draft is under password
protection, and I can’t find the prior spec as a freely-available download, I can’t
see if memory is correct or not.)
</p>
        <p>
Or, consider the various edge cases that came up around the introduction of nullable
types in C# 2.0. What started out as a fairly simple suggestion—“let’s let T? represent
the idea that this instance of T could be nullable, and at runtime it’ll be a Nullable&lt;T&gt;
instance behind the scenes”—turned into a pretty ugly morass of edge cases at the
language level that resulted in some serious bug-fixing right up until the final ship
date.
</p>
        <p>
Thing is, languages that aren’t written deliberately to allow their own modification
and evolution tend to fail over time. C++ was one such example, and I think both Java
and C# will stand as successor examples before long.
</p>
        <p>
Right now, in C# 3.0, type inference is limited entirely to local variables because
the language isn’t syntactically set up to leave out type names wherever possible—the
“var” token is a type placeholder, largely because the parser has to have a type first.
(This is the same purpose the “dynamic” keyword seems to be playing for 4.0, though
I can’t say so for certain.) In F# and Scala, this syntax is deliberately written
Pascal-style, with the name first, optionally followed by a colon and the type, because
the parser can see the colon and realize the type is already specified, or see no
colon and realize the type should be inferred. That syntax is used consistently throughout
the F# and Scala languages, and that means it’s pretty easy, lexically speaking, for
the languages to recognize when type inference should kick in.
</p>
        <p>
What’s more, both F# and Scala don’t really support the O-O notion of method overloading,
because again, it gets confusing when trying to kick in type inference—something about
too many possibilities confusing the type-inferencer. (I’m not entirely positive of
this point, by the way, it’s based on some conversations I’ve had with language designers
over the last few years. I could be wrong, and would love to see a language that supports
both.) Instead, they force developers to be more explicit about parameters being passed—F#
won’t even do implicit widening conversions, in fact, such as automatically widening
ints to longs.
</p>
        <p>
But both F# and Scala have a <em>very</em> interesting facility to allow definitions
of methods/functions using very flexible syntactic rules, such that they look like
operators or keywords built into the language; F# defines its pipeline operator (
|&gt; ) in its library definitions, for example. Scala defines numerous “keywords”,
like synchronized or transient, as classes in the Scala package extending “StaticAnnotation”—in
other words, their syntax and behavior is defined as an annotation, rather than as
a built-in part of the language. Ditto for Scala’s XML support.
</p>
        <p>
Lisp, of course, was one of the first (if not <em>the</em> first) language to do this,
and it’s my understanding that this has been one of the principal reasons it has survived
all these years as a language—because it’s an abstraction built on top of an abstraction
built on top of an abstraction, <em>et al</em>, it makes it easier to change those
underlying abstractions when the context changes.
</p>
        <p>
This doesn’t mean those “polyactivist” languages like C# are bad things, it just means
that there’s a danger that they’ll eventually collapse from too many moving parts
all trying to talk to each other at the same time. As an exercise, open the C# 3.0
spec, and start checking off all the sections that will need to be touched by the
introduction of the “dynamic” keyword as a new type.
</p>
        <p>
Or, to put it analagously, yes, for a lot of work, a single multifunction tool can
be useful, but for a lot of other work, you want tools that are specialized to the
task at hand. Let’s not minimize the usefulness of that multifunction tool, but let’s
not try to use a Swiss Army knife where a jeweler’s screwdriver is really needed.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=429e21f9-875c-4b10-815c-0d98e97a2605" />
        <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>From the Mailbag: Polyglot Programmer vs. Polyactivist Language</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,429e21f9-875c-4b10-815c-0d98e97a2605.aspx</guid>
      <link>http://blogs.tedneward.com/2009/03/24/From+The+Mailbag+Polyglot+Programmer+Vs+Polyactivist+Language.aspx</link>
      <pubDate>Tue, 24 Mar 2009 07:22:00 GMT</pubDate>
      <description>&lt;p&gt;
This crossed my Inbox:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I read your article entitled: The Polyglot Programmer. How about the thought that
rather than becoming a polyglot-software engineer; pick a polyglot-language. For example,
C# is borrowing techniques from functional and dynamic languages. Let the compiler
designer worry about mixing features and software engineers worry about keep up with
the mixture. Is this a good approach? &lt;em&gt;[From Phil, at &lt;a href="http://greensoftwareengineer.spaces.live.com/"&gt;http://greensoftwareengineer.spaces.live.com/&lt;/a&gt;]&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Phil, it’s an interesting thought you’ve raised—which is the better/easier approach
to take, that of incorporating the language features we want into a single language,
rather than needing to learn all those different languages (and their own unique syntaxes)
in order to take advantage of those features we want?
&lt;/p&gt;
&lt;p&gt;
After all, we’re starting to see this taking place within a certain number of languages
already, particularly C#; first, in 3.0, they introduced a number of features in support
of LINQ that make C# a useful starting point for working with a functional language.
Extension methods, for example, allow us to add a number of different methods to the
collection classes that provide some functional capabilities (Select&amp;lt;&amp;gt;, GroupBy&amp;lt;&amp;gt;,
and so on), as Matt Podwysocki demonstrates, generics contribute the type-safety that
most functional languages embrace, anonymous methods and delegates provide better
functions-as-first-class-constructs (including lambdas), and anonymous types make
it vastly easier to return and pass tuples. And now, in 4.0, we’re getting the “dynamic”
keyword, which will add support for invoking methods and properties dynamically, in
the grand tradition of most dynamic languages (like Python and Ruby), and 3.0’s local
variable type inference allows us to write “var x = ...”, which feels pretty dynamic
(even if it’s not, under the hood).
&lt;/p&gt;
&lt;p&gt;
Unfortunately, I think for the most part, the answer’s going to be, “Yes, it would
be nice, if it weren’t for the fact that there are very few languages that won’t collapse
underneath their own weight if they did so.”
&lt;/p&gt;
&lt;p&gt;
Consider, for example, the C# language. Already, with the C# 3.0 definition, the language
specification weighs in at close to a thousand pages. The additional features in 4.0
could easily push it over a thousand and possibly, with all the places where “dynamic”
behavior will need to be factored into the existing specification, could push that
well into the 1200 to 1300 page range. What’s the upper limit on a language’s complexity
to maintain and enhance, much less for its programmers to comprehend?
&lt;/p&gt;
&lt;p&gt;
(By comparison, the C++ specification, as I can best remember, didn’t weigh in at
more than a thousand pages, but given that the current working draft is under password
protection, and I can’t find the prior spec as a freely-available download, I can’t
see if memory is correct or not.)
&lt;/p&gt;
&lt;p&gt;
Or, consider the various edge cases that came up around the introduction of nullable
types in C# 2.0. What started out as a fairly simple suggestion—“let’s let T? represent
the idea that this instance of T could be nullable, and at runtime it’ll be a Nullable&amp;lt;T&amp;gt;
instance behind the scenes”—turned into a pretty ugly morass of edge cases at the
language level that resulted in some serious bug-fixing right up until the final ship
date.
&lt;/p&gt;
&lt;p&gt;
Thing is, languages that aren’t written deliberately to allow their own modification
and evolution tend to fail over time. C++ was one such example, and I think both Java
and C# will stand as successor examples before long.
&lt;/p&gt;
&lt;p&gt;
Right now, in C# 3.0, type inference is limited entirely to local variables because
the language isn’t syntactically set up to leave out type names wherever possible—the
“var” token is a type placeholder, largely because the parser has to have a type first.
(This is the same purpose the “dynamic” keyword seems to be playing for 4.0, though
I can’t say so for certain.) In F# and Scala, this syntax is deliberately written
Pascal-style, with the name first, optionally followed by a colon and the type, because
the parser can see the colon and realize the type is already specified, or see no
colon and realize the type should be inferred. That syntax is used consistently throughout
the F# and Scala languages, and that means it’s pretty easy, lexically speaking, for
the languages to recognize when type inference should kick in.
&lt;/p&gt;
&lt;p&gt;
What’s more, both F# and Scala don’t really support the O-O notion of method overloading,
because again, it gets confusing when trying to kick in type inference—something about
too many possibilities confusing the type-inferencer. (I’m not entirely positive of
this point, by the way, it’s based on some conversations I’ve had with language designers
over the last few years. I could be wrong, and would love to see a language that supports
both.) Instead, they force developers to be more explicit about parameters being passed—F#
won’t even do implicit widening conversions, in fact, such as automatically widening
ints to longs.
&lt;/p&gt;
&lt;p&gt;
But both F# and Scala have a &lt;em&gt;very&lt;/em&gt; interesting facility to allow definitions
of methods/functions using very flexible syntactic rules, such that they look like
operators or keywords built into the language; F# defines its pipeline operator (
|&amp;gt; ) in its library definitions, for example. Scala defines numerous “keywords”,
like synchronized or transient, as classes in the Scala package extending “StaticAnnotation”—in
other words, their syntax and behavior is defined as an annotation, rather than as
a built-in part of the language. Ditto for Scala’s XML support.
&lt;/p&gt;
&lt;p&gt;
Lisp, of course, was one of the first (if not &lt;em&gt;the&lt;/em&gt; first) language to do this,
and it’s my understanding that this has been one of the principal reasons it has survived
all these years as a language—because it’s an abstraction built on top of an abstraction
built on top of an abstraction, &lt;em&gt;et al&lt;/em&gt;, it makes it easier to change those
underlying abstractions when the context changes.
&lt;/p&gt;
&lt;p&gt;
This doesn’t mean those “polyactivist” languages like C# are bad things, it just means
that there’s a danger that they’ll eventually collapse from too many moving parts
all trying to talk to each other at the same time. As an exercise, open the C# 3.0
spec, and start checking off all the sections that will need to be touched by the
introduction of the “dynamic” keyword as a new type.
&lt;/p&gt;
&lt;p&gt;
Or, to put it analagously, yes, for a lot of work, a single multifunction tool can
be useful, but for a lot of other work, you want tools that are specialized to the
task at hand. Let’s not minimize the usefulness of that multifunction tool, but let’s
not try to use a Swiss Army knife where a jeweler’s screwdriver is really needed.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=429e21f9-875c-4b10-815c-0d98e97a2605" /&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,429e21f9-875c-4b10-815c-0d98e97a2605.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>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=236aa3a3-83db-4c81-bb14-3085d551dad3</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,236aa3a3-83db-4c81-bb14-3085d551dad3.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,236aa3a3-83db-4c81-bb14-3085d551dad3.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=236aa3a3-83db-4c81-bb14-3085d551dad3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This email crossed my Inbox last week while I was on the road:
</p>
        <blockquote>
          <p>
Due to the current economic situation, TechWeb has made the difficult decision to
discontinue the Software Development events, including SD West, SD Best Practices
and Architecture &amp; Design World. We are grateful for your support during SD's
twenty-four year history and are disappointed to see the events end.
</p>
        </blockquote>
        <p>
This really bums me out, because the SD shows were some of the best shows I’ve been
to, particularly SD West, which always had a great cross-cutting collection of experts
from all across the industry’s big technical areas: C++, Java, .NET, security, agile,
and more. It was also where I got to meet and interview Bjarne Stroustrup, a personal
hero of mine from back in my days as a C++ developer, where I got to hang out each
year with Scott Meyers, another personal hero (and now a good friend) as well as editor
on <em>Effective Enterprise Java</em>, and Mike Cohn, another good friend as well
as a great guy to work for. It was where I first met Gary McGraw, in a rather embarrassing
fashion—in the middle of his presentation on security, my cell phone went off with
a klaxon alarm ring tone loud enough to be heard throughout the entire room, and as
every head turned to look at me, he commented dryly, “That’s the buffer overrun alarm—somewhere
in the world, a buffer overrun attack is taking place.”
</p>
        <p>
On a positive note, however, the email goes on to say that “<a href="http://TIG.cmptechnetwork.com/cgi-bin4/DM/y/nBP5n0JjIlP0ZFX0HEjd0Eu">Cloud
Connect</a> [will] take over SD West's dates in March 2010 at the Santa Clara Convention
Center”, which is good news, since it means (hopefully) that I’ll still get a chance
to make my yearly pilgrimage to In-N-Out....
</p>
        <p>
Rest in peace, SD. You will be missed.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=236aa3a3-83db-4c81-bb14-3085d551dad3" />
        <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>SDWest, SDBestPractices, SDArch&amp;amp;Design: RIP, 1975 - 2009</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,236aa3a3-83db-4c81-bb14-3085d551dad3.aspx</guid>
      <link>http://blogs.tedneward.com/2009/03/24/SDWest+SDBestPractices+SDArchampDesign+RIP+1975+2009.aspx</link>
      <pubDate>Tue, 24 Mar 2009 00:22:43 GMT</pubDate>
      <description>&lt;p&gt;
This email crossed my Inbox last week while I was on the road:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Due to the current economic situation, TechWeb has made the difficult decision to
discontinue the Software Development events, including SD West, SD Best Practices
and Architecture &amp;amp; Design World. We are grateful for your support during SD's
twenty-four year history and are disappointed to see the events end.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This really bums me out, because the SD shows were some of the best shows I’ve been
to, particularly SD West, which always had a great cross-cutting collection of experts
from all across the industry’s big technical areas: C++, Java, .NET, security, agile,
and more. It was also where I got to meet and interview Bjarne Stroustrup, a personal
hero of mine from back in my days as a C++ developer, where I got to hang out each
year with Scott Meyers, another personal hero (and now a good friend) as well as editor
on &lt;em&gt;Effective Enterprise Java&lt;/em&gt;, and Mike Cohn, another good friend as well
as a great guy to work for. It was where I first met Gary McGraw, in a rather embarrassing
fashion—in the middle of his presentation on security, my cell phone went off with
a klaxon alarm ring tone loud enough to be heard throughout the entire room, and as
every head turned to look at me, he commented dryly, “That’s the buffer overrun alarm—somewhere
in the world, a buffer overrun attack is taking place.”
&lt;/p&gt;
&lt;p&gt;
On a positive note, however, the email goes on to say that “&lt;a href="http://TIG.cmptechnetwork.com/cgi-bin4/DM/y/nBP5n0JjIlP0ZFX0HEjd0Eu"&gt;Cloud
Connect&lt;/a&gt; [will] take over SD West's dates in March 2010 at the Santa Clara Convention
Center”, which is good news, since it means (hopefully) that I’ll still get a chance
to make my yearly pilgrimage to In-N-Out....
&lt;/p&gt;
&lt;p&gt;
Rest in peace, SD. You will be missed.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=236aa3a3-83db-4c81-bb14-3085d551dad3" /&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,236aa3a3-83db-4c81-bb14-3085d551dad3.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>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</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=97cfa0a6-2f42-4fe1-b756-222ff3350b12</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,97cfa0a6-2f42-4fe1-b756-222ff3350b12.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,97cfa0a6-2f42-4fe1-b756-222ff3350b12.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=97cfa0a6-2f42-4fe1-b756-222ff3350b12</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Just got this email from Chris Sells:
</p>
        <blockquote>
          <p>
For twelve 45-minute slots at this year’s <a href="http://www.sellsbrothers.com/conference/">DSL
DevCon</a> (April 16-17 in Redmond, WA), we had 49 proposals. You have been selected
as speakers for the following talks. Please confirm that you’ll be there for both
days so that I can put together the schedule and post it on the conference site. This
DevCon should rock. Thanks! 
</p>
          <p>
Martin Fowler - Keynote 
</p>
          <p>
Paul Vick + Gio - Mgrammar Deep Dive 
</p>
          <p>
Tom Rodgers - Domain Specific Languages for automated testing of equity order management
systems and trading machines 
</p>
          <p>
Paul Cowan - DSLs in the Horn Package Manager 
</p>
          <p>
Guillaume Laforge - How to implement DSLs with Groovy 
</p>
          <p>
Markus Voelter - Eclipse tooling for Model-Driven stuff 
</p>
          <p>
Dionysios G. Synodinos - JavaScript DSLs for the Client Side 
</p>
          <p>
Ted Neward, Bradford Cross - Functional vs. Dynamic DSLs: The Smackdown 
</p>
          <p>
Gilad Bracha - embedding EBNF in a general purpose language 
</p>
          <p>
Umit Yalcinalp, Tilman Giese - RUMBA: RUby Managed Business data for Applications 
</p>
          <p>
Bob Archer - A DSL for Cool Effects in Adobe Pixel Blender 
</p>
          <p>
Chance Coble - Language Oriented Programming in F#
</p>
        </blockquote>
        <p>
As my 15-year-old son Michael has grown fond of saying... w00t! The list of topics
is fascinating, and I'm really looking forward to most, if not all, of them. Chance's
talk on LOP in F# should be good, I'm really curious to see Gilad's discussion of
EBNF (and wondering if this is Newspeak we'll be seeing), and Guillaume is always
fun to watch when he's going on about Groovy. Of course, I'm also excited to be paired
up with Brad, who's an insanely smart guy--I have a feeling I'll learn a lot just
by standing next to him. (Sort of a speakers' osmosis.)
</p>
        <p>
If you're not planning to be here for this (and the <a href="http://www.langnetsymposium.com/">Lang.NET
Symposium</a>), either you have life-saving surgery scheduled that can't be pushed
back, or you're clearly not interested in DSLs. For your own sake, I hope it's the
latter. ;-)
</p>
        <p>
Seriously, come for the full week. The Lang.NET Symposium last year was an amazing
event, for a number of reasons, not the least of which is that it saw Sun celebrities
John Rose, Charlie Nutter and Brian Goetz step on to the Microsoft campus, deliver
a great presentation on the JVM, MLVM/invokedynamic, and JRuby, and get good feedback
and discussion from Microsoft engineers and other notables. You don't get to see <em>that</em> every
day. :-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=97cfa0a6-2f42-4fe1-b756-222ff3350b12" />
        <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>Woo-hoo! Speaking at DSL DevCon 2009!</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,97cfa0a6-2f42-4fe1-b756-222ff3350b12.aspx</guid>
      <link>http://blogs.tedneward.com/2009/02/19/Woohoo+Speaking+At+DSL+DevCon+2009.aspx</link>
      <pubDate>Thu, 19 Feb 2009 00:29:25 GMT</pubDate>
      <description>&lt;p&gt;
Just got this email from Chris Sells:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
For twelve 45-minute slots at this year’s &lt;a href="http://www.sellsbrothers.com/conference/"&gt;DSL
DevCon&lt;/a&gt; (April 16-17 in Redmond, WA), we had 49 proposals. You have been selected
as speakers for the following talks. Please confirm that you’ll be there for both
days so that I can put together the schedule and post it on the conference site. This
DevCon should rock. Thanks! 
&lt;p&gt;
Martin Fowler - Keynote 
&lt;p&gt;
Paul Vick + Gio - Mgrammar Deep Dive 
&lt;p&gt;
Tom Rodgers - Domain Specific Languages for automated testing of equity order management
systems and trading machines 
&lt;p&gt;
Paul Cowan - DSLs in the Horn Package Manager 
&lt;p&gt;
Guillaume Laforge - How to implement DSLs with Groovy 
&lt;p&gt;
Markus Voelter - Eclipse tooling for Model-Driven stuff 
&lt;p&gt;
Dionysios G. Synodinos - JavaScript DSLs for the Client Side 
&lt;p&gt;
Ted Neward, Bradford Cross - Functional vs. Dynamic DSLs: The Smackdown 
&lt;p&gt;
Gilad Bracha - embedding EBNF in a general purpose language 
&lt;p&gt;
Umit Yalcinalp, Tilman Giese - RUMBA: RUby Managed Business data for Applications 
&lt;p&gt;
Bob Archer - A DSL for Cool Effects in Adobe Pixel Blender 
&lt;p&gt;
Chance Coble - Language Oriented Programming in F#
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
As my 15-year-old son Michael has grown fond of saying... w00t! The list of topics
is fascinating, and I'm really looking forward to most, if not all, of them. Chance's
talk on LOP in F# should be good, I'm really curious to see Gilad's discussion of
EBNF (and wondering if this is Newspeak we'll be seeing), and Guillaume is always
fun to watch when he's going on about Groovy. Of course, I'm also excited to be paired
up with Brad, who's an insanely smart guy--I have a feeling I'll learn a lot just
by standing next to him. (Sort of a speakers' osmosis.)
&lt;/p&gt;
&lt;p&gt;
If you're not planning to be here for this (and the &lt;a href="http://www.langnetsymposium.com/"&gt;Lang.NET
Symposium&lt;/a&gt;), either you have life-saving surgery scheduled that can't be pushed
back, or you're clearly not interested in DSLs. For your own sake, I hope it's the
latter. ;-)
&lt;/p&gt;
&lt;p&gt;
Seriously, come for the full week. The Lang.NET Symposium last year was an amazing
event, for a number of reasons, not the least of which is that it saw Sun celebrities
John Rose, Charlie Nutter and Brian Goetz step on to the Microsoft campus, deliver
a great presentation on the JVM, MLVM/invokedynamic, and JRuby, and get good feedback
and discussion from Microsoft engineers and other notables. You don't get to see &lt;em&gt;that&lt;/em&gt; every
day. :-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=97cfa0a6-2f42-4fe1-b756-222ff3350b12" /&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,97cfa0a6-2f42-4fe1-b756-222ff3350b12.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=1788b4cc-fc8f-4f79-bef6-6dcb784819ee</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,1788b4cc-fc8f-4f79-bef6-6dcb784819ee.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,1788b4cc-fc8f-4f79-bef6-6dcb784819ee.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=1788b4cc-fc8f-4f79-bef6-6dcb784819ee</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Last year I had the opportunity to return to the land of my roots, Poland, and speak
at Java Developer Days (JDD). Just today, the organizers from JDD sent me a link with <a href="http://www.youtube.com/watch?v=AJy8NrkmEko">a
nice little photo montage from the conference</a>. (I did notice a few photos from
the after-party were selectively left out of the montage, however, which is probably
a good thing because that was the first time I'd ever met a Polish Mad Dog, and boy
did they all go down easy...)
</p>
        <p>
If you're anywhere in the area around Krakow in March, you definitely should swing
by for their follow-up conference, <a href="http://4developers.org.pl/">4Developers</a>--it
sounds like it's going to be another fun event, and this time it's going to reach
out to more than just the Java folks, but also the .NET crowd (and a few others),
as well.
</p>
        <p>
(I don't really expect any of the readers of this blog living outside Poland to really
pack up and head over to Krakow for a weekend, mind you, but if you're a technology
speaker and you're interested in hanging with an extremely good group of people, the
people who put these shows on--ProIdea--are top-notch, take great care of the speakers,
and overall make the entire experience well worth the trip.)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=1788b4cc-fc8f-4f79-bef6-6dcb784819ee" />
        <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>Nice little montage from JDD08</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,1788b4cc-fc8f-4f79-bef6-6dcb784819ee.aspx</guid>
      <link>http://blogs.tedneward.com/2009/02/06/Nice+Little+Montage+From+JDD08.aspx</link>
      <pubDate>Fri, 06 Feb 2009 10:17:15 GMT</pubDate>
      <description>&lt;p&gt;
Last year I had the opportunity to return to the land of my roots, Poland, and speak
at Java Developer Days (JDD). Just today, the organizers from JDD sent me a link with &lt;a href="http://www.youtube.com/watch?v=AJy8NrkmEko"&gt;a
nice little photo montage from the conference&lt;/a&gt;. (I did notice a few photos from
the after-party were selectively left out of the montage, however, which is probably
a good thing because that was the first time I'd ever met a Polish Mad Dog, and boy
did they all go down easy...)
&lt;/p&gt;
&lt;p&gt;
If you're anywhere in the area around Krakow in March, you definitely should swing
by for their follow-up conference, &lt;a href="http://4developers.org.pl/"&gt;4Developers&lt;/a&gt;--it
sounds like it's going to be another fun event, and this time it's going to reach
out to more than just the Java folks, but also the .NET crowd (and a few others),
as well.
&lt;/p&gt;
&lt;p&gt;
(I don't really expect any of the readers of this blog living outside Poland to really
pack up and head over to Krakow for a weekend, mind you, but if you're a technology
speaker and you're interested in hanging with an extremely good group of people, the
people who put these shows on--ProIdea--are top-notch, take great care of the speakers,
and overall make the entire experience well worth the trip.)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=1788b4cc-fc8f-4f79-bef6-6dcb784819ee" /&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,1788b4cc-fc8f-4f79-bef6-6dcb784819ee.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>WCF</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=c8fbfc22-056a-41c9-a756-fe520994abb6</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,c8fbfc22-056a-41c9-a756-fe520994abb6.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,c8fbfc22-056a-41c9-a756-fe520994abb6.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c8fbfc22-056a-41c9-a756-fe520994abb6</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
From <a href="http://www.hanselman.com/blog/SeattleRedmondBellevueNerdDinnerJan192009.aspx">Scott
Hanselman's blog</a>:
</p>
        <blockquote>
          <p>
Are you in King County/Seattle/Redmond/Bellevue Washington and surrounding areas?
Are you a huge nerd? Perhaps a geek? No? Maybe a dork, dweeb or wonk. Maybe you're
in town for an SDR (Software Design Review) visiting BillG. Quite possibly you're
just a normal person. 
</p>
          <p>
Regardless, why not join us for some Mall Food at the Crossroads Bellevue Mall Food
Court on Monday, January 19th around 6:30pm? 
</p>
          <p>
... 
</p>
          <p>
NOTE: RSVP by leaving a comment <a href="http://www.hanselman.com/blog/SeattleRedmondBellevueNerdDinnerJan192009.aspx">here</a> and
show up on January 19th at 6:30pm! Feel free to bring friends, kids or family. Bring
a Ruby or Java person!
</p>
        </blockquote>
        <p>
Any of the SeaJUG want to attend? (Anybody know of a Ruby JUG in the Eastside area,
by the way?) I'm game....
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c8fbfc22-056a-41c9-a756-fe520994abb6" />
        <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>Seattle/Redmond/Bellevue Nerd Dinner</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,c8fbfc22-056a-41c9-a756-fe520994abb6.aspx</guid>
      <link>http://blogs.tedneward.com/2009/01/18/SeattleRedmondBellevue+Nerd+Dinner.aspx</link>
      <pubDate>Sun, 18 Jan 2009 09:01:19 GMT</pubDate>
      <description>&lt;p&gt;
From &lt;a href="http://www.hanselman.com/blog/SeattleRedmondBellevueNerdDinnerJan192009.aspx"&gt;Scott
Hanselman's blog&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Are you in King County/Seattle/Redmond/Bellevue Washington and surrounding areas?
Are you a huge nerd? Perhaps a geek? No? Maybe a dork, dweeb or wonk. Maybe you're
in town for an SDR (Software Design Review) visiting BillG. Quite possibly you're
just a normal person. 
&lt;p&gt;
Regardless, why not join us for some Mall Food at the Crossroads Bellevue Mall Food
Court on Monday, January 19th around 6:30pm? 
&lt;p&gt;
... 
&lt;p&gt;
NOTE: RSVP by leaving a comment &lt;a href="http://www.hanselman.com/blog/SeattleRedmondBellevueNerdDinnerJan192009.aspx"&gt;here&lt;/a&gt; and
show up on January 19th at 6:30pm! Feel free to bring friends, kids or family. Bring
a Ruby or Java person!
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Any of the SeaJUG want to attend? (Anybody know of a Ruby JUG in the Eastside area,
by the way?) I'm game....
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c8fbfc22-056a-41c9-a756-fe520994abb6" /&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,c8fbfc22-056a-41c9-a756-fe520994abb6.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</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=c68b5a0f-0ea5-4272-b555-3eef96f1ceab</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,c68b5a0f-0ea5-4272-b555-3eef96f1ceab.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,c68b5a0f-0ea5-4272-b555-3eef96f1ceab.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c68b5a0f-0ea5-4272-b555-3eef96f1ceab</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Chris Sells, an acquaintance (and perhaps friend, when he's not picking on me for
my Java leanings) of mine from my DevelopMentor days, has a habit of putting on a
"DevCon" whenever a technology seems to have reached a certain maturity level. He
did it with XML a few years ago, and ATL before that, both of which were pretty amazing
events, filled with the sharpest guys in the subject, gathered into a single room
to share ideas and shoot each others' pet theories full of holes.
</p>
        <p>
He's at it again, this time with DSLs; from <a href="http://www.sellsbrothers.com/news/showTopic.aspx?ixTopic=2232">the
announcement on his blog</a>:
</p>
        <blockquote>
          <p>
Are you interested in presenting a 45-minute talk on some Domain Specific Language
(DSL) related topic? It doesn't matter which platform or OS you're targeting. It also
doesn't matter whether you're an author, a vendor, a professional speaker or a developer
in the trenches (in fact, I tend to be biased toward the latter). We're after interesting
and unique applications of DSL technology and if you're doing good work in that area,
then I need you to <a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission">send
me a session topic and 2-4 sentence abstract along with a little bit about yourself</a>. 
</p>
          <p>
I'll be taking submissions 'til February 9th, 2009, but <a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission">don't
delay</a>. Passion and a burning story to tell count twice as much as anything else. 
</p>
          <p>
And don't be shy about spreading this announcement around! I've got good coverage
in the .NET and Windows communities, but don't know very many folks in the Java or
Unix or hardcore modeling worlds, so if you're in that world, let those guys know!
Thanks. 
</p>
          <p>
The <a href="http://sellsbrothers.com/conference/">DSL DevCon</a> itself will be in
Redmond, WA on the Microsoft campus April 16-17, 2009, right after <a href="http://www.langnetsymposium.com/">the
Lang.NET conference</a>. Lang.NET will be focused on general-purpose languages, whereas
the DSL DevCon will focus on domain-specific languages. The idea is that if you want
to attend one or the other or both, that's totally fine. We'll have 2.5 days of Lang.NET
on April 14-16 and then 1.5 days of DSL DevCon content. 
</p>
          <p>
Oh, and the cost for both conferences is the same: $0. 
</p>
          <p>
We're only accepting 150 attendees to either conference. Every one of the five previous
DevCons have sold out, so when we open registration, you'll want to be quick about
getting your name on the list. 
</p>
          <p>
            <a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission">Submit
your DSL-related talk idea!</a>
          </p>
        </blockquote>
        <p>
For those of you who are deep in the Java or Ruby space, I really urge you to take
a chance here and come to the event--just because it's being held on the Microsoft
campus doesn't mean you're going to be forcibly plugged into the Matrix; the same
goes for the Lang.NET event in the earlier part of the week, too. Don't believe me?
I have proof: Brian Goetz, John Rose, and Charlie Nutter, Sun employees all, attended
last years Lang.NET event, talked about the JVM and JRuby, and not only did they <em>not</em> have
to give up their "sun.com" email addresses, but they came away with some new appreciations
for the CLR, the ecosystem there, and even a few insights about their own platform
in comparison to the JVM. (I won't say this as an absolute fact, but I think a lot
of John's work on method handles for Java7 came out of conversations he'd had with
some of the CLR guys that week.)
</p>
        <p>
This is a DevCon, not a MarCon or a SaleCon. If you're a dev, you're welcome to come
here. Frankly, I'd love to see the Java and Ruby (and LLVM and Parrot and ...) guys
storm the castle, so to speak, if for no other reason than so Chris will stop teasing
me about being a Java guy. ;-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c68b5a0f-0ea5-4272-b555-3eef96f1ceab" />
        <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>DSLs: Ready for Prime-Time?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,c68b5a0f-0ea5-4272-b555-3eef96f1ceab.aspx</guid>
      <link>http://blogs.tedneward.com/2009/01/14/DSLs+Ready+For+PrimeTime.aspx</link>
      <pubDate>Wed, 14 Jan 2009 06:33:42 GMT</pubDate>
      <description>&lt;p&gt;
Chris Sells, an acquaintance (and perhaps friend, when he's not picking on me for
my Java leanings) of mine from my DevelopMentor days, has a habit of putting on a
"DevCon" whenever a technology seems to have reached a certain maturity level. He
did it with XML a few years ago, and ATL before that, both of which were pretty amazing
events, filled with the sharpest guys in the subject, gathered into a single room
to share ideas and shoot each others' pet theories full of holes.
&lt;/p&gt;
&lt;p&gt;
He's at it again, this time with DSLs; from &lt;a href="http://www.sellsbrothers.com/news/showTopic.aspx?ixTopic=2232"&gt;the
announcement on his blog&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Are you interested in presenting a 45-minute talk on some Domain Specific Language
(DSL) related topic? It doesn't matter which platform or OS you're targeting. It also
doesn't matter whether you're an author, a vendor, a professional speaker or a developer
in the trenches (in fact, I tend to be biased toward the latter). We're after interesting
and unique applications of DSL technology and if you're doing good work in that area,
then I need you to &lt;a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission"&gt;send
me a session topic and 2-4 sentence abstract along with a little bit about yourself&lt;/a&gt;. 
&lt;p&gt;
I'll be taking submissions 'til February 9th, 2009, but &lt;a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission"&gt;don't
delay&lt;/a&gt;. Passion and a burning story to tell count twice as much as anything else. 
&lt;p&gt;
And don't be shy about spreading this announcement around! I've got good coverage
in the .NET and Windows communities, but don't know very many folks in the Java or
Unix or hardcore modeling worlds, so if you're in that world, let those guys know!
Thanks. 
&lt;p&gt;
The &lt;a href="http://sellsbrothers.com/conference/"&gt;DSL DevCon&lt;/a&gt; itself will be in
Redmond, WA on the Microsoft campus April 16-17, 2009, right after &lt;a href="http://www.langnetsymposium.com/"&gt;the
Lang.NET conference&lt;/a&gt;. Lang.NET will be focused on general-purpose languages, whereas
the DSL DevCon will focus on domain-specific languages. The idea is that if you want
to attend one or the other or both, that's totally fine. We'll have 2.5 days of Lang.NET
on April 14-16 and then 1.5 days of DSL DevCon content. 
&lt;p&gt;
Oh, and the cost for both conferences is the same: $0. 
&lt;p&gt;
We're only accepting 150 attendees to either conference. Every one of the five previous
DevCons have sold out, so when we open registration, you'll want to be quick about
getting your name on the list. 
&lt;p&gt;
&lt;a href="mailto:csells@microsoft.com?subject=DSL%20DevCon%20Abstract%20Submission"&gt;Submit
your DSL-related talk idea!&lt;/a&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
For those of you who are deep in the Java or Ruby space, I really urge you to take
a chance here and come to the event--just because it's being held on the Microsoft
campus doesn't mean you're going to be forcibly plugged into the Matrix; the same
goes for the Lang.NET event in the earlier part of the week, too. Don't believe me?
I have proof: Brian Goetz, John Rose, and Charlie Nutter, Sun employees all, attended
last years Lang.NET event, talked about the JVM and JRuby, and not only did they &lt;em&gt;not&lt;/em&gt; have
to give up their "sun.com" email addresses, but they came away with some new appreciations
for the CLR, the ecosystem there, and even a few insights about their own platform
in comparison to the JVM. (I won't say this as an absolute fact, but I think a lot
of John's work on method handles for Java7 came out of conversations he'd had with
some of the CLR guys that week.)
&lt;/p&gt;
&lt;p&gt;
This is a DevCon, not a MarCon or a SaleCon. If you're a dev, you're welcome to come
here. Frankly, I'd love to see the Java and Ruby (and LLVM and Parrot and ...) guys
storm the castle, so to speak, if for no other reason than so Chris will stop teasing
me about being a Java guy. ;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c68b5a0f-0ea5-4272-b555-3eef96f1ceab" /&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,c68b5a0f-0ea5-4272-b555-3eef96f1ceab.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=89bed821-27ee-4770-bb38-065b40cea3d7</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,89bed821-27ee-4770-bb38-065b40cea3d7.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,89bed821-27ee-4770-bb38-065b40cea3d7.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=89bed821-27ee-4770-bb38-065b40cea3d7</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
For a couple of years now, I've been going around the world and giving a talk entitled
"Pragmatic Architecture", talking both about what architecture is (and what architects
really do), and ending the talk with my own "catalog" of architectural elements and
ideas, in an attempt to take some of the mystery and "cloud" nature of architecture
out of the discussion. If you've read <em>Effective Enterprise Java</em>, then you've
read the first version of that discussion, where Pragmatic Architecture was a second-generation
thought process.
</p>
        <p>
Recently, the patterns &amp; practices group at Microsoft went back and refined their <a href="http://www.codeplex.com/AppArchGuide">Application
Architecture Guide</a>, and while there's a lot about it that I wish they'd done differently
(less of a Microsoft-centric focus, for one), I think it's a great book for Microsoft-centric
architects to pick up and have nearby. In a lot of ways, this is something similar
to what I had in mind when I thought about the architectural catalog, though I'll
admit that I'd prefer to go one level "deeper" and find more of the "atoms" that make
up an architecture.
</p>
        <p>
Nevertheless, I think this is a good PDF to pull down and put somewhere on your reference
list.
</p>
        <p>
Notes and caveats: Firstly, this is a book for solution architects; if you're the
VP or CTO, don't bother with it, just hand it to somebody further on down the food
chain. Secondly, if you're not an architect, this is <em>not</em> the book to pick
up to learn how to be one. It's more in the way of a reference guide for existing
architects. In fact, my vision is that an architect faced with a new project (that
is, a new architecture to create) will think about the problem, sketch out a rough
solution in his head, then look at the book to find both potential alternatives (to
see if they fit better or worse than the one s/he has in her/his head), and potential
consequences (to the one s/he has in her/his head). Thirdly, even if you're a Java
or Ruby architect, <em>most</em> of the book is pretty technology-neutral. Just take
a black Sharpie to the parts that have the Microsoft trademark around them, and you'll
find it a pretty decent reference, too. Fourthly, in the spirit of full disclosure,
the p&amp;p guys brought me in for a day of discussion on the Guide, so I can't say
that I'm completely unbiased, but I can honestly say that I didn't write any of it,
just offered critique (in case that matters to any potential readers).
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=89bed821-27ee-4770-bb38-065b40cea3d7" />
        <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;Pragmatic Architecture&amp;quot;, in book form</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,89bed821-27ee-4770-bb38-065b40cea3d7.aspx</guid>
      <link>http://blogs.tedneward.com/2009/01/05/quotPragmatic+Architecturequot+In+Book+Form.aspx</link>
      <pubDate>Mon, 05 Jan 2009 02:30:53 GMT</pubDate>
      <description>&lt;p&gt;
For a couple of years now, I've been going around the world and giving a talk entitled
"Pragmatic Architecture", talking both about what architecture is (and what architects
really do), and ending the talk with my own "catalog" of architectural elements and
ideas, in an attempt to take some of the mystery and "cloud" nature of architecture
out of the discussion. If you've read &lt;em&gt;Effective Enterprise Java&lt;/em&gt;, then you've
read the first version of that discussion, where Pragmatic Architecture was a second-generation
thought process.
&lt;/p&gt;
&lt;p&gt;
Recently, the patterns &amp;amp; practices group at Microsoft went back and refined their &lt;a href="http://www.codeplex.com/AppArchGuide"&gt;Application
Architecture Guide&lt;/a&gt;, and while there's a lot about it that I wish they'd done differently
(less of a Microsoft-centric focus, for one), I think it's a great book for Microsoft-centric
architects to pick up and have nearby. In a lot of ways, this is something similar
to what I had in mind when I thought about the architectural catalog, though I'll
admit that I'd prefer to go one level "deeper" and find more of the "atoms" that make
up an architecture.
&lt;/p&gt;
&lt;p&gt;
Nevertheless, I think this is a good PDF to pull down and put somewhere on your reference
list.
&lt;/p&gt;
&lt;p&gt;
Notes and caveats: Firstly, this is a book for solution architects; if you're the
VP or CTO, don't bother with it, just hand it to somebody further on down the food
chain. Secondly, if you're not an architect, this is &lt;em&gt;not&lt;/em&gt; the book to pick
up to learn how to be one. It's more in the way of a reference guide for existing
architects. In fact, my vision is that an architect faced with a new project (that
is, a new architecture to create) will think about the problem, sketch out a rough
solution in his head, then look at the book to find both potential alternatives (to
see if they fit better or worse than the one s/he has in her/his head), and potential
consequences (to the one s/he has in her/his head). Thirdly, even if you're a Java
or Ruby architect, &lt;em&gt;most&lt;/em&gt; of the book is pretty technology-neutral. Just take
a black Sharpie to the parts that have the Microsoft trademark around them, and you'll
find it a pretty decent reference, too. Fourthly, in the spirit of full disclosure,
the p&amp;amp;p guys brought me in for a day of discussion on the Guide, so I can't say
that I'm completely unbiased, but I can honestly say that I didn't write any of it,
just offered critique (in case that matters to any potential readers).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=89bed821-27ee-4770-bb38-065b40cea3d7" /&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,89bed821-27ee-4770-bb38-065b40cea3d7.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>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=5394a334-8042-40ca-b80b-748b50ce9253</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,5394a334-8042-40ca-b80b-748b50ce9253.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,5394a334-8042-40ca-b80b-748b50ce9253.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=5394a334-8042-40ca-b80b-748b50ce9253</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
It's once again that time of year, and in keeping with my tradition, I'll revisit
the 2008 predictions to see how close I came before I start waxing prophetic on the
coming year. (I'm thinking that maybe the next year--2010's edition--I should actually
take a shot at predicting the next decade, but I'm not sure if I'd remember to go
back and revisit it in 2020 to see how I did. Anybody want to set a calendar reminder
for Dec 31 2019 and remind me, complete with URL? ;-) )
</p>
        <p>
Without further preamble, here's what I said for 2008:
</p>
        <ul>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: The buzz around building custom languages
will only continue to build. More and more tools are emerging to support the creation
of custom programming languages, like Microsoft's Phoenix, Scala's parser combinators,
the Microsoft DLR, SOOT, Javassist, JParsec/NParsec, and so on. Suddenly, the whole
"write your own lexer and parser and AST from scratch" idea seems about as outmoded
as the idea of building your own String class. Granted, there are cases where a from-hand
scanner/lexer/parser/AST/etc is the Right Thing To Do, but there are times when building
your own String class is the Right Thing To Do, too. Between the rich ecosystem of
dynamic languages that could be ported to the JVM/CLR, and the interesting strides
being made on both platforms (JVM and CLR) to make them more "dynamic-friendly" (such
as being able to reify classes or access the call stack directly), the probability
that your company will find a need that is best answered by building a custom language
are only going to rise. <strong>NOW: </strong>The buzz has definitely continued to
build, but buzz can only take us so far. There's been some scattershot use of custom
languages in a few scattershot situations, but it's certainly not "taken the world
by storm" in any meaningful way yet.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: The hype surrounding "domain-specific languages"
will peak in 2008, and start to generate a backlash. Let's be honest: when somebody
looks you straight in the eye and suggests that "scattered, smothered and covered"
is a domain-specific language, the term has lost all meaning. A lexicon unique to
an industry is not a domain-specific language; it's a lexicon. Period. If you can
incorporate said lexicon into your software, thus making it accessible to non-technical
professionals, that's a good thing. But simply using the lexicon doesn't make it a
domain-specific language. Or, alternatively, if you like, every single API designed
for a particular purpose is itself a domain-specific language. This means that Spring
configuration files are a DSL. Deployment descriptors are a DSL. The Java language
is a DSL (since the domain is that of programmers familiar with the Java language).
See how nonsensical this can get? Until somebody comes up with a workable definition
of the term "domain" in "domain-specific language", it's a nonsensical term. The idea
is a powerful one, mind you--creating something that's more "in tune" with what users
understand and can use easily is a technique that's been proven for decades now. Anybody
who's ever watched an accountant rip an entirely new set of predictions for the new
fiscal outlook based entirely on a few seed numbers and a deeply-nested set of Excel
macros knows this already. Whether you call them domain-specific languages or "little
languages" or "user-centric languages" or "macro language" is really up to you. <strong>NOW:</strong> The
backlash hasn't begun, but only because the DSL buzz hasn't materialized in much way
yet--see previous note. It generally takes a year or two of deployments (and hard-earned
experience) before a backlash begins, and we haven't hit that "deployments" stage
yet in anything yet resembling "critical mass" yet. But the DSL/custom language buzz
continues to grow, and the more the buzz grows, the more the backlash is likey.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: Functional languages will begin to make their
presence felt. Between Microsoft's productization plans for F# and the growing community
of Scala programmers, not to mention the inherently functional concepts buried inside
of LINQ and the concurrency-friendly capabilities of side-effect-free programming,
the world is going to find itself working its way into functional thinking either
directly or indirectly. And when programmers start to see the inherent capabilities
inside of Scala (such as Actors) and/or F# (such as asynchronous workflows), they're
going to embrace the strange new world of functional/object hybrid and never look
back. <strong>NOW:</strong> Several books on F# and Scala (and even one or two on
Haskell!) were published in 2008, and several more (including one of my own) are on
the way. The functional buzz is building, and lots of disparate groups are each evaluating
it (functional programming) independently.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: MacOS is going to start posting some serious
market share numbers, leading lots of analysts to predict that Microsoft Windows has
peaked and is due to collapse sometime within the remainder of the decade. Mac's not
only a wonderful OS, but it's some of the best hardware to run Vista on. That will
lead not a few customers to buy Mac hardware, wipe the machine, and install Vista,
as many of the uber-geeks in the Windows world are already doing. This will in turn
lead Gartner (always on the lookout for an established trend they can "predict" on)
to suggest that Mac is going to end up with 115% market share by 2012 (.8 probability),
then sell you this wisdom for a mere price of $1.5 million (per copy). <strong>NOW:</strong> Can't
speak to the Gartner report--I didn't have $1.5 million handy--but certainly the MacOS
is growing in popularity. More on that later.</li>
          <li>
            <strong>THEN:</strong>
            <em>General</em>: Ted will be hired by Gartner... if only to
keep him from smacking them around so much. .0001 probability, with probability going
up exponentially as my salary offer goes up exponentially. (Hey, I've got kids headed
for college in a few years.) <strong>NOW:</strong> Well, Gartner appears to have lost
my email address and phone number, but I'm sure they were planning to make me that
offer.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: MacOS is going to start creaking in a few
places. The Mac OS is a wonderful OS, but it's got its own creaky parts, and the more
users that come to Mac OS, the more that software packages are going to exploit some
of those creaky parts, leading to some instability in the Mac OS. It won't be widespread,
but for those who are interested in finding it, they're there. Assuming current trends
(of customers adopting Mac OS) hold, the Mac OS 10.6 upgrade is going to be a very
interesting process, indeed. <strong>NOW:</strong> Shhh. Don't tell anybody, but I've
been seeing it starting to happen. Don't get me wrong, Apple still does a pretty good
job with the OS, but the law of numbers has started to create some bad upgrade scenarios
for some people.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: Somebody is going to realize that iTunes
is the world's biggest monopoly on music, and Apple will be forced to defend itself
in the court of law, the court of public opinion, or both. Let's be frank: if this
were Microsoft, offering music that can only be played on Microsoft music players,
the world would be through the roof. All UI goodness to one side, the iPod represents
just as much of a monopoly in the music player business as Internet Explorer did in
the operating system business, and if the world doesn't start taking Apple to task
over this, then "justice" is a word that only applies when losers in an industry want
to drag down the market leader (which I firmly believe to be the case--nobody likes
more than to pile on the successful guy). <strong>NOW:</strong> Nothing this year.</li>
          <li>
            <strong>THEN: </strong>
            <em>General</em>: Somebody is going to realize that the iPhone's
"nothing we didn't write will survive the next upgrade process" policy is nothing
short of draconian. As my father, who gets it right every once in a while, says, "If
I put a third-party stereo in my car, the dealer doesn't get to rip it out and replace
it with one of their own (or nothing at all!) the next time I take it in for an oil
change". Fact is, if I buy the phone, I own the phone, and I own what's on it. Unfortunately,
this takes us squarely into the realm of DRM and IP ownership, and we all know how
clear-cut that is... But once the general public starts to understand some of these
issues--and I think the iPhone and iTunes may just be the vehicle that will teach
them--look out, folks, because the backlash will be huge. As in, "Move over, Mr. Gates,
you're about to be joined in infamy by your other buddy Steve...." <strong>NOW:</strong> Apple
released iPhone 2.0, and with it, the iPhone SDK, so at least Apple has opened the
dashboard to third-party stereos. But the deployment model (AppStore) is still a bit
draconian, and Apple still jealously holds the reins over which apps can be deployed
there and which ones can't, so maybe they haven't learned their lesson yet, after
all....</li>
          <li>
            <strong>THEN: </strong>
            <em>Java</em>: The OpenJDK in Mercurial will slowly start to
see some external contributions. The whole point of Mercurial is to allow for deeper
control over which changes you incorporate into your build tree, so once people figure
out how to build the JDK and how to hack on it, the local modifications will start
to seep across the Internet.... <strong>NOW:</strong> OpenJDK has started to collect
contributions from external (to Sun) sources, but still in relatively small doses,
it seems. None of the local modifications I envisioned creeping across the 'Net have
begun, that I can see, so maybe it's still waiting to happen. Or maybe the OpenJDK
is too complicated to really allow for that kind of customization, and it never will.</li>
          <li>
            <strong>THEN:</strong>
            <em>Java</em>: SpringSource will soon be seen as a vendor like
BEA or IBM or Sun. Perhaps with a bit better reputation to begin, but a vendor all
the same. <strong>NOW:</strong> SpringSource's acquisition of G2One (the company behind
Groovy just as SpringSource backs Spring) only reinforced this image, but it seems
it's still something that some fail to realize or acknowledge due to Spring's open-source
(?) nature. (I'm not a Spring expert by any means, but apparently Spring 3 was pulled
back inside the SpringSource borders, leading some people to wonder what SpringSource
is up to, and whether or not Spring will continue to be open source after all.)</li>
          <li>
            <strong>THEN:</strong>
            <em>.NET</em>: Interest in OpenJDK will bootstrap similar interest
in Rotor/SSCLI. After all, they're both VMs, with lots of interesting ideas and information
about how the managed platforms work. <strong>NOW:</strong> Nope, hasn't really happened
yet, that I can see. Not even the 2nd edition of the SSCLI book (by Joel Pobar and
yours truly, yes that was a plug) seemed to foster the kind of attention or interest
that I'd expected, or at least, not on the scale I'd thought might happen.</li>
          <li>
            <strong>THEN: </strong>
            <em>C++/Native</em>: If you've not heard of LLVM before this,
you will. It's a compiler and bytecode toolchain aimed at the native platforms, complete
with JIT and GC. <strong>NOW:</strong> Apple sank a lot of investment into LLVM, including
hosting an LLVM conference at the corporate headquarters.</li>
          <li>
            <strong>THEN:</strong>
            <em>Java</em>: Somebody will create Yet Another Rails-Killer
Web Framework. 'Nuff said. <strong>NOW:</strong> You know what? I honestly can't say
whether this happened or not; I was completely not paying attention.</li>
          <li>
            <strong>THEN:</strong>
            <em>Native</em>: Developers looking for a native programming
language will discover D, and be happy. Considering D is from the same mind that was
the core behind the Zortech C++ compiler suite, and that D has great native platform
integration (building DLLs, calling into DLLs easily, and so on), not to mention automatic
memory management (except for those areas where you want manual memory management),
it's definitely worth looking into. <a href="http://www.digitalmars.com">www.digitalmars.com</a><strong>NOW:</strong> D
had its own get-together as well, and appears to still be going strong, among the
group of developers who still work on native apps (and aren't simply maintaining legacy
C/C++ apps).</li>
        </ul>
        <p>
Now, for the 2009 predictions. The last set was a little verbose, so let me see if
I can trim the list down a little and keep it short and sweet:
</p>
        <ul>
          <li>
            <em>General:</em> "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.)</li>
          <li>
            <em>Java</em>: Interest in Scala will continue to rise, as will the number of detractors
who point out that Scala is too hard to learn.</li>
          <li>
            <em>.NET</em>: 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.)</li>
          <li>
            <em>General:</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.</li>
          <li>
            <em>General:</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.</li>
          <li>
            <em>.NET</em>: 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.</li>
          <li>
            <em>.NET</em>: 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).</li>
          <li>
            <em>Java</em>: 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.</li>
          <li>
            <em>Java</em>: The invokedynamic JSR will leapfrog in importance to the top of the
list.</li>
          <li>
            <em>Windows</em>: 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.</li>
          <li>
            <em>Mac OS</em>: 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.)</li>
          <li>
            <em>Languages</em>: 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.</li>
          <li>
            <em>XML Services</em>: 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.</li>
          <li>
            <em>Parrot</em>: 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.</li>
          <li>
            <em>Agile</em>: 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.</li>
          <li>
            <em>Flash</em>: 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.</li>
          <li>
            <em>Personal</em>: Gartner will still come knocking, looking to hire me for outrageous
sums of money to do nothing but blog and wax prophetic.</li>
        </ul>
        <p>
Well, so much for brief or short. See you all again next year....
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=5394a334-8042-40ca-b80b-748b50ce9253" />
        <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>2009 Predictions, 2008 Predictions Revisited</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,5394a334-8042-40ca-b80b-748b50ce9253.aspx</guid>
      <link>http://blogs.tedneward.com/2009/01/01/2009+Predictions+2008+Predictions+Revisited.aspx</link>
      <pubDate>Thu, 01 Jan 2009 07:54:29 GMT</pubDate>
      <description>&lt;p&gt;
It's once again that time of year, and in keeping with my tradition, I'll revisit
the 2008 predictions to see how close I came before I start waxing prophetic on the
coming year. (I'm thinking that maybe the next year--2010's edition--I should actually
take a shot at predicting the next decade, but I'm not sure if I'd remember to go
back and revisit it in 2020 to see how I did. Anybody want to set a calendar reminder
for Dec 31 2019 and remind me, complete with URL? ;-) )
&lt;/p&gt;
&lt;p&gt;
Without further preamble, here's what I said for 2008:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: The buzz around building custom languages
will only continue to build. More and more tools are emerging to support the creation
of custom programming languages, like Microsoft's Phoenix, Scala's parser combinators,
the Microsoft DLR, SOOT, Javassist, JParsec/NParsec, and so on. Suddenly, the whole
"write your own lexer and parser and AST from scratch" idea seems about as outmoded
as the idea of building your own String class. Granted, there are cases where a from-hand
scanner/lexer/parser/AST/etc is the Right Thing To Do, but there are times when building
your own String class is the Right Thing To Do, too. Between the rich ecosystem of
dynamic languages that could be ported to the JVM/CLR, and the interesting strides
being made on both platforms (JVM and CLR) to make them more "dynamic-friendly" (such
as being able to reify classes or access the call stack directly), the probability
that your company will find a need that is best answered by building a custom language
are only going to rise. &lt;strong&gt;NOW: &lt;/strong&gt;The buzz has definitely continued to
build, but buzz can only take us so far. There's been some scattershot use of custom
languages in a few scattershot situations, but it's certainly not "taken the world
by storm" in any meaningful way yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: The hype surrounding "domain-specific languages"
will peak in 2008, and start to generate a backlash. Let's be honest: when somebody
looks you straight in the eye and suggests that "scattered, smothered and covered"
is a domain-specific language, the term has lost all meaning. A lexicon unique to
an industry is not a domain-specific language; it's a lexicon. Period. If you can
incorporate said lexicon into your software, thus making it accessible to non-technical
professionals, that's a good thing. But simply using the lexicon doesn't make it a
domain-specific language. Or, alternatively, if you like, every single API designed
for a particular purpose is itself a domain-specific language. This means that Spring
configuration files are a DSL. Deployment descriptors are a DSL. The Java language
is a DSL (since the domain is that of programmers familiar with the Java language).
See how nonsensical this can get? Until somebody comes up with a workable definition
of the term "domain" in "domain-specific language", it's a nonsensical term. The idea
is a powerful one, mind you--creating something that's more "in tune" with what users
understand and can use easily is a technique that's been proven for decades now. Anybody
who's ever watched an accountant rip an entirely new set of predictions for the new
fiscal outlook based entirely on a few seed numbers and a deeply-nested set of Excel
macros knows this already. Whether you call them domain-specific languages or "little
languages" or "user-centric languages" or "macro language" is really up to you. &lt;strong&gt;NOW:&lt;/strong&gt; The
backlash hasn't begun, but only because the DSL buzz hasn't materialized in much way
yet--see previous note. It generally takes a year or two of deployments (and hard-earned
experience) before a backlash begins, and we haven't hit that "deployments" stage
yet in anything yet resembling "critical mass" yet. But the DSL/custom language buzz
continues to grow, and the more the buzz grows, the more the backlash is likey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: Functional languages will begin to make their
presence felt. Between Microsoft's productization plans for F# and the growing community
of Scala programmers, not to mention the inherently functional concepts buried inside
of LINQ and the concurrency-friendly capabilities of side-effect-free programming,
the world is going to find itself working its way into functional thinking either
directly or indirectly. And when programmers start to see the inherent capabilities
inside of Scala (such as Actors) and/or F# (such as asynchronous workflows), they're
going to embrace the strange new world of functional/object hybrid and never look
back. &lt;strong&gt;NOW:&lt;/strong&gt; Several books on F# and Scala (and even one or two on
Haskell!) were published in 2008, and several more (including one of my own) are on
the way. The functional buzz is building, and lots of disparate groups are each evaluating
it (functional programming) independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: MacOS is going to start posting some serious
market share numbers, leading lots of analysts to predict that Microsoft Windows has
peaked and is due to collapse sometime within the remainder of the decade. Mac's not
only a wonderful OS, but it's some of the best hardware to run Vista on. That will
lead not a few customers to buy Mac hardware, wipe the machine, and install Vista,
as many of the uber-geeks in the Windows world are already doing. This will in turn
lead Gartner (always on the lookout for an established trend they can "predict" on)
to suggest that Mac is going to end up with 115% market share by 2012 (.8 probability),
then sell you this wisdom for a mere price of $1.5 million (per copy). &lt;strong&gt;NOW:&lt;/strong&gt; Can't
speak to the Gartner report--I didn't have $1.5 million handy--but certainly the MacOS
is growing in popularity. More on that later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN:&lt;/strong&gt; &lt;em&gt;General&lt;/em&gt;: Ted will be hired by Gartner... if only to
keep him from smacking them around so much. .0001 probability, with probability going
up exponentially as my salary offer goes up exponentially. (Hey, I've got kids headed
for college in a few years.) &lt;strong&gt;NOW:&lt;/strong&gt; Well, Gartner appears to have lost
my email address and phone number, but I'm sure they were planning to make me that
offer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: MacOS is going to start creaking in a few
places. The Mac OS is a wonderful OS, but it's got its own creaky parts, and the more
users that come to Mac OS, the more that software packages are going to exploit some
of those creaky parts, leading to some instability in the Mac OS. It won't be widespread,
but for those who are interested in finding it, they're there. Assuming current trends
(of customers adopting Mac OS) hold, the Mac OS 10.6 upgrade is going to be a very
interesting process, indeed. &lt;strong&gt;NOW:&lt;/strong&gt; Shhh. Don't tell anybody, but I've
been seeing it starting to happen. Don't get me wrong, Apple still does a pretty good
job with the OS, but the law of numbers has started to create some bad upgrade scenarios
for some people.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: Somebody is going to realize that iTunes
is the world's biggest monopoly on music, and Apple will be forced to defend itself
in the court of law, the court of public opinion, or both. Let's be frank: if this
were Microsoft, offering music that can only be played on Microsoft music players,
the world would be through the roof. All UI goodness to one side, the iPod represents
just as much of a monopoly in the music player business as Internet Explorer did in
the operating system business, and if the world doesn't start taking Apple to task
over this, then "justice" is a word that only applies when losers in an industry want
to drag down the market leader (which I firmly believe to be the case--nobody likes
more than to pile on the successful guy). &lt;strong&gt;NOW:&lt;/strong&gt; Nothing this year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;General&lt;/em&gt;: Somebody is going to realize that the iPhone's
"nothing we didn't write will survive the next upgrade process" policy is nothing
short of draconian. As my father, who gets it right every once in a while, says, "If
I put a third-party stereo in my car, the dealer doesn't get to rip it out and replace
it with one of their own (or nothing at all!) the next time I take it in for an oil
change". Fact is, if I buy the phone, I own the phone, and I own what's on it. Unfortunately,
this takes us squarely into the realm of DRM and IP ownership, and we all know how
clear-cut that is... But once the general public starts to understand some of these
issues--and I think the iPhone and iTunes may just be the vehicle that will teach
them--look out, folks, because the backlash will be huge. As in, "Move over, Mr. Gates,
you're about to be joined in infamy by your other buddy Steve...." &lt;strong&gt;NOW:&lt;/strong&gt; Apple
released iPhone 2.0, and with it, the iPhone SDK, so at least Apple has opened the
dashboard to third-party stereos. But the deployment model (AppStore) is still a bit
draconian, and Apple still jealously holds the reins over which apps can be deployed
there and which ones can't, so maybe they haven't learned their lesson yet, after
all....&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;Java&lt;/em&gt;: The OpenJDK in Mercurial will slowly start to
see some external contributions. The whole point of Mercurial is to allow for deeper
control over which changes you incorporate into your build tree, so once people figure
out how to build the JDK and how to hack on it, the local modifications will start
to seep across the Internet.... &lt;strong&gt;NOW:&lt;/strong&gt; OpenJDK has started to collect
contributions from external (to Sun) sources, but still in relatively small doses,
it seems. None of the local modifications I envisioned creeping across the 'Net have
begun, that I can see, so maybe it's still waiting to happen. Or maybe the OpenJDK
is too complicated to really allow for that kind of customization, and it never will.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN:&lt;/strong&gt; &lt;em&gt;Java&lt;/em&gt;: SpringSource will soon be seen as a vendor like
BEA or IBM or Sun. Perhaps with a bit better reputation to begin, but a vendor all
the same. &lt;strong&gt;NOW:&lt;/strong&gt; SpringSource's acquisition of G2One (the company behind
Groovy just as SpringSource backs Spring) only reinforced this image, but it seems
it's still something that some fail to realize or acknowledge due to Spring's open-source
(?) nature. (I'm not a Spring expert by any means, but apparently Spring 3 was pulled
back inside the SpringSource borders, leading some people to wonder what SpringSource
is up to, and whether or not Spring will continue to be open source after all.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN:&lt;/strong&gt; &lt;em&gt;.NET&lt;/em&gt;: Interest in OpenJDK will bootstrap similar interest
in Rotor/SSCLI. After all, they're both VMs, with lots of interesting ideas and information
about how the managed platforms work. &lt;strong&gt;NOW:&lt;/strong&gt; Nope, hasn't really happened
yet, that I can see. Not even the 2nd edition of the SSCLI book (by Joel Pobar and
yours truly, yes that was a plug) seemed to foster the kind of attention or interest
that I'd expected, or at least, not on the scale I'd thought might happen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN: &lt;/strong&gt;&lt;em&gt;C++/Native&lt;/em&gt;: If you've not heard of LLVM before this,
you will. It's a compiler and bytecode toolchain aimed at the native platforms, complete
with JIT and GC. &lt;strong&gt;NOW:&lt;/strong&gt; Apple sank a lot of investment into LLVM, including
hosting an LLVM conference at the corporate headquarters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN:&lt;/strong&gt; &lt;em&gt;Java&lt;/em&gt;: Somebody will create Yet Another Rails-Killer
Web Framework. 'Nuff said. &lt;strong&gt;NOW:&lt;/strong&gt; You know what? I honestly can't say
whether this happened or not; I was completely not paying attention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;THEN:&lt;/strong&gt; &lt;em&gt;Native&lt;/em&gt;: Developers looking for a native programming
language will discover D, and be happy. Considering D is from the same mind that was
the core behind the Zortech C++ compiler suite, and that D has great native platform
integration (building DLLs, calling into DLLs easily, and so on), not to mention automatic
memory management (except for those areas where you want manual memory management),
it's definitely worth looking into. &lt;a href="http://www.digitalmars.com"&gt;www.digitalmars.com&lt;/a&gt; &lt;strong&gt;NOW:&lt;/strong&gt; D
had its own get-together as well, and appears to still be going strong, among the
group of developers who still work on native apps (and aren't simply maintaining legacy
C/C++ apps).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now, for the 2009 predictions. The last set was a little verbose, so let me see if
I can trim the list down a little and keep it short and sweet:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;General:&lt;/em&gt; "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.)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Java&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;.NET&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;General:&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 "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.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;General:&lt;/em&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;.NET&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;.NET&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;Java&lt;/em&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 "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.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Java&lt;/em&gt;: The invokedynamic JSR will leapfrog in importance to the top of the
list.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Windows&lt;/em&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 "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.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Mac OS&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;Languages&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;XML Services&lt;/em&gt;: 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 &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 "REST"ful
will equate to "I did it myself!", complete with expectations of a gold star and a
lollipop.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Parrot&lt;/em&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;/li&gt;
&lt;li&gt;
&lt;em&gt;Agile&lt;/em&gt;: 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.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Flash&lt;/em&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 "Flash" shops or "Silverlight" shops.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Personal&lt;/em&gt;: Gartner will still come knocking, looking to hire me for outrageous
sums of money to do nothing but blog and wax prophetic.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Well, so much for brief or short. See you all again next year....
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=5394a334-8042-40ca-b80b-748b50ce9253" /&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,5394a334-8042-40ca-b80b-748b50ce9253.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>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Security</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=502a7f84-98f0-40d6-95aa-87513a7c35c6</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,502a7f84-98f0-40d6-95aa-87513a7c35c6.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,502a7f84-98f0-40d6-95aa-87513a7c35c6.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=502a7f84-98f0-40d6-95aa-87513a7c35c6</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
It amazes me how insular and inward-facing the software industry is. And how the "agile"
movement is reaping the benefits of a very simple characteristic.
</p>
        <p>
For example, consider Jeff Palermo's essay on <a href="http://jeffreypalermo.com/blog/the-myth-of-self-organizing-teams/">"The
Myth of Self-Organizing Teams"</a>. Now, nothing against Jeff, or his post, <em>per
se</em>, but it amazes me how our industry believes that they are somehow inventing
new concepts, such as, in this case the "self-organizing team". Team dynamics have
been a subject of study for decades, and anyone with a background in psychology, business,
or sales has probably already been through much of the material on it. The best teams
are those that find their own sense of identity, that grow from within, but still
accept some leadership from the outside--the classic example here being the championship
sports team. Most often, that sense of identity is born of a string of successes,
which is why teams without a winning tradition have such a hard time creating the <em>esprit
de corps</em> that so often defines the difference between success and failure. 
</p>
        <blockquote>
          <p>
            <em>(Editor's note: Here's a free lesson to all of you out there who want to help
your team grow its own sense of identity: give them a chance to win a few successes,
and they'll start coming together pretty quickly. It's not always that easy, but it
works more often than not.)</em>
          </p>
        </blockquote>
        <p>
How many software development managers--much less technical leads or project managers--have
actually gone and looked through the management aisle at the local bookstore?
</p>
        <p>
Tom and Mary Poppendieck have been spending years now talking about "lean" software
development, which itself (at a casual glance) seems to be a refinement of the concepts
Toyota and other Japanese manufacturers were pursuing close to two decades ago. "Total
quality management" was a concept introduced in those days, the idea that anyone on
the production line was empowered to stop the line if they found something that wasn't
right. (My father was one of those "lean" manufacturing advocates back in the 80's,
in fact, and has some great stories he can tell to its successes, and failures.)
</p>
        <p>
How many software development managers or project leads give their developers the
chance to say, "No, it's not right yet, we can't ship", and back them on it? Wouldn't
you, as a developer, feel far more involved in the project if you knew you had that
power--and that responsibility?
</p>
        <p>
Or consider the "agile" notion of customer involvement, the classic XP "On-Site Customer"
principle. Sales people have known for years, even decades (if not centuries), that
if you involve the customer in the process, they are much more likely to feel an ownership
stake sooner than if they just take what's on the lot or the shelf. Skilled salespeople
have done the "let's walk through what you <em>might</em> buy, if you were buying,
of course" trick countless numbers of times, and ended up with a sale where the customer
didn't even intend to buy.
</p>
        <p>
How many software development managers or project leads have read a book on basic
salesmanship? And yet, isn't that notion of extracting what the customer wants endemic
to both software development and basic sales (of anything)?
</p>
        <p>
What is it about the software industry that just collectively refuses to accept that
there might be lots of interesting research on topics that aren't technical yet still
something that we can use? Why do we feel so compelled to trumpet our own "innovations"
to ourselves, when in fact, they've been long-known in dozens of other contexts? When
will we wake up and realize that we can learn a lot more if we cross-train in other
areas... like, for example, getting your MBA?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=502a7f84-98f0-40d6-95aa-87513a7c35c6" />
        <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 Myth of Discovery</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,502a7f84-98f0-40d6-95aa-87513a7c35c6.aspx</guid>
      <link>http://blogs.tedneward.com/2008/12/10/The+Myth+Of+Discovery.aspx</link>
      <pubDate>Wed, 10 Dec 2008 15:48:45 GMT</pubDate>
      <description>&lt;p&gt;
It amazes me how insular and inward-facing the software industry is. And how the "agile"
movement is reaping the benefits of a very simple characteristic.
&lt;/p&gt;
&lt;p&gt;
For example, consider Jeff Palermo's essay on &lt;a href="http://jeffreypalermo.com/blog/the-myth-of-self-organizing-teams/"&gt;"The
Myth of Self-Organizing Teams"&lt;/a&gt;. Now, nothing against Jeff, or his post, &lt;em&gt;per
se&lt;/em&gt;, but it amazes me how our industry believes that they are somehow inventing
new concepts, such as, in this case the "self-organizing team". Team dynamics have
been a subject of study for decades, and anyone with a background in psychology, business,
or sales has probably already been through much of the material on it. The best teams
are those that find their own sense of identity, that grow from within, but still
accept some leadership from the outside--the classic example here being the championship
sports team. Most often, that sense of identity is born of a string of successes,
which is why teams without a winning tradition have such a hard time creating the &lt;em&gt;esprit
de corps&lt;/em&gt; that so often defines the difference between success and failure. 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;(Editor's note: Here's a free lesson to all of you out there who want to help
your team grow its own sense of identity: give them a chance to win a few successes,
and they'll start coming together pretty quickly. It's not always that easy, but it
works more often than not.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
How many software development managers--much less technical leads or project managers--have
actually gone and looked through the management aisle at the local bookstore?
&lt;/p&gt;
&lt;p&gt;
Tom and Mary Poppendieck have been spending years now talking about "lean" software
development, which itself (at a casual glance) seems to be a refinement of the concepts
Toyota and other Japanese manufacturers were pursuing close to two decades ago. "Total
quality management" was a concept introduced in those days, the idea that anyone on
the production line was empowered to stop the line if they found something that wasn't
right. (My father was one of those "lean" manufacturing advocates back in the 80's,
in fact, and has some great stories he can tell to its successes, and failures.)
&lt;/p&gt;
&lt;p&gt;
How many software development managers or project leads give their developers the
chance to say, "No, it's not right yet, we can't ship", and back them on it? Wouldn't
you, as a developer, feel far more involved in the project if you knew you had that
power--and that responsibility?
&lt;/p&gt;
&lt;p&gt;
Or consider the "agile" notion of customer involvement, the classic XP "On-Site Customer"
principle. Sales people have known for years, even decades (if not centuries), that
if you involve the customer in the process, they are much more likely to feel an ownership
stake sooner than if they just take what's on the lot or the shelf. Skilled salespeople
have done the "let's walk through what you &lt;em&gt;might&lt;/em&gt; buy, if you were buying,
of course" trick countless numbers of times, and ended up with a sale where the customer
didn't even intend to buy.
&lt;/p&gt;
&lt;p&gt;
How many software development managers or project leads have read a book on basic
salesmanship? And yet, isn't that notion of extracting what the customer wants endemic
to both software development and basic sales (of anything)?
&lt;/p&gt;
&lt;p&gt;
What is it about the software industry that just collectively refuses to accept that
there might be lots of interesting research on topics that aren't technical yet still
something that we can use? Why do we feel so compelled to trumpet our own "innovations"
to ourselves, when in fact, they've been long-known in dozens of other contexts? When
will we wake up and realize that we can learn a lot more if we cross-train in other
areas... like, for example, getting your MBA?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=502a7f84-98f0-40d6-95aa-87513a7c35c6" /&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,502a7f84-98f0-40d6-95aa-87513a7c35c6.aspx</comments>
      <category>.NET</category>
      <category>C#</category>
      <category>C++</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=d2274e34-b9e5-4771-a877-505b58b8aa28</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,d2274e34-b9e5-4771-a877-505b58b8aa28.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,d2274e34-b9e5-4771-a877-505b58b8aa28.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=d2274e34-b9e5-4771-a877-505b58b8aa28</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Having freshly converted both the Visual Studio 2010 and Oslo SDK VPC images that
we received at PDC 2008 last month to VMWare images, I figure it's time to dive into
M.
</p>
        <p>
At PDC, the Addison-Wesley folks were giving away copies of "The 'Oslo' Modeling Language"
book, which is apparently official canon of the "M" language for Oslo, so I flip to
page 1 and start reading:
</p>
        <blockquote>
          <p>
The "Oslo" Modeling Language (M) is a modern, declarative language for working with
data. M lets users write down how they want to structure and query their data using
a convenient textual syntax that is convenient to both author and read.
</p>
          <p>
M does not mandate how data is stored or accessed, nor does it mandate a specific
implementation technology. Rather, M was designed to allow users to write down <em>what</em> they
want from their data without having to specify <em>how</em> those desires are met
against a given technology or platform. That stated, M in no way prohibits implementations
from providing rich declarative or imperative support for controlling how M constructs
are represented and executed in a given environment.
</p>
        </blockquote>
        <p>
Hmm... I have to admit, all kinds of warning bells and alarm flags are going off in
my head, and we're just two sentences into this thing. This sounds like something
we've all done before; in fact, though I've not tried it, I have a feeling that if
we were to go back through those two paragraphs and replace every instance of "M"
with "SQL", we'd find a paragraph that could easily slip into the opening chapter
of any introductory SQL or RDBMS book.
</p>
        <p>
The goals of "separation of declaration from intent" have been around for that long,
probably longer, and even the fiercest and staunchest defenders of SQL find themselves
sometimes wandering through SQL declarations and code that clearly violate Chris Date's
politely-worded commands around normal form and separation of declaration from intent
and implementation.
</p>
        <p>
I keep reading, though, and a few paragraphs later, find something intriguing.
</p>
        <blockquote>
          <p>
Another important aspect of data management that M does not address is that of update.
M is a functional language that does not have constructs for changing the contents
of an extent. <em>(Author's note: an "extent", defined a few paragraphs earlier, is
that "an extent provides dynamic storage for values.")</em> How data changes is outside
the scope of the language. That said, M anticipates that the contents of an extent
can change via external (to M) stimuli. Subsequent versions of M are expected to provide
declarative constructs for updating data.
</p>
        </blockquote>
        <p>
Wow. So the first question becomes, when are those "subsequent versions" expected?
Is this simply a state of the PDC Preview bits, or something that's not in scope for
v1 of the Oslo SDK?
</p>
        <p>
I flip through the rest of the first chapter, which seems like a decent overview,
and what I see there is an interesting type-declaration language; in many ways, it's
highly reminiscent of XML Schema Descriptions (XSD) more than SQL declarations, but
I suppose that's to be expected, at least for now. I'm sure they're going to cherry-pick
a lot of the best data-declarative constructs from XSD, SQL, and any other metadata-based
formats/languages, and that the semantics will change as they explore what works well
and what doesn't. For now, though, "M" exists essentially as a data-descriptor language,
and this is reinforced when I start playing with "m.exe", the "M compiler" (?).
</p>
        <p>
First thing, I simply fire up "m.exe" to see what the options are. And... nothing.
Huh? I wait for a bit, then Ctrl-C it, and start hunting through the documentation
to see if I'm missing something here. I try a few different tests, like "m /?" or
"m -help", and each time, the compiler just seems to wander off into the weeds, requiring
a Ctrl-C to kill it.
</p>
        <p>
What the heck? I know that these are PDC pre-alpha CTP "nothing is guaranteed to work"
bits, but this seems a bit on the excessive side--I have every faith that Microsoft
wouldn't hand these out if you can't even run the compiler! So acting on a hunch,
I fire up "m /?" again, and tab away to look at something else. Sure enough, my hunch
is rewarded--after a long pause, eventually the help screen comes up. So, apparently,
the m.exe tool just takes <em>fricken forever</em> to run, is all.
</p>
        <p>
Currently, the only targets M can compile to is their internal Repository for storing
types, and a generic "T-SQL" target for any T-SQL-compliant database (which I presume
for now means only SQL Server of various versions, but theoretically, I suppose, Sybase
could work too, given those two systems' shared ancestry. And, given a pretty simple
sample to work with, m.exe produces a pretty-easily-anticipated result; this:
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">module Ted<br />
{<br />
type Person<br />
{<br />
Id : Integer32 = AutoNumber();<br />
Name : Text;<br />
} where identity Id;<br />
People : Person*; 
<br />
}</pre>
          <br />
        </div>
        <p>
turns into this:
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <span style="color: #0000ff">set</span> xact_abort <span style="color: #0000ff">on</span>;<br /><span style="color: #0000ff">go</span><br /><br /><span style="color: #0000ff">begin</span><span style="color: #0000ff">transaction</span>;<br /><span style="color: #0000ff">go</span><br /><br /><span style="color: #0000ff">set</span> ansi_nulls <span style="color: #0000ff">on</span>;<br /><span style="color: #0000ff">go</span><br /><br /><span style="color: #0000ff">create</span><span style="color: #0000ff">schema</span> [Ted];<br /><span style="color: #0000ff">go</span><br /><br /><span style="color: #0000ff">create</span><span style="color: #0000ff">table</span> [Ted].[People]<br />
(<br />
[Id] <span style="color: #0000ff">int</span><span style="color: #0000ff">not</span><span style="color: #0000ff">null</span><span style="color: #0000ff">identity</span>,<br />
[Name] nvarchar(<span style="color: #0000ff">max</span>) <span style="color: #0000ff">not</span><span style="color: #0000ff">null</span>,<br /><span style="color: #0000ff">constraint</span> [PK_People] <span style="color: #0000ff">primary</span><span style="color: #0000ff">key</span><span style="color: #0000ff">clustered</span> ([Id])<br />
);<br /><span style="color: #0000ff">go</span><br /><br /><span style="color: #0000ff">commit</span><span style="color: #0000ff">transaction</span>;<br /><span style="color: #0000ff">go</span><br /></pre>
          <br />
        </div>
        <p>
... which, when you look at it, is pretty much what you'd want.
</p>
        <p>
Interestingly enough, there's no reason why people in the Java or Ruby space couldn't
use "M" just as easily, so long as the database targeted is one that M understands.
(It also wouldn't be a terribly difficult exercise to build an M compiler in Java
or Ruby, for that matter. Might be a fun off-time project, in fact.)
</p>
        <p>
One thing that's also pretty clear is that M is very collection-centric, as the first
chapter spends probably 50% of its time describing all the various ways that collections
in M (written as "{a, b, c}") interact with one another (they can be compared for
equality directly, for example, and have some neat projection/filter capabilities
that were clearly drawn from the relational algebra and LINQ syntax). Having said
that, though, one thing that is obviously missing is the traditional object "reference"-style
connection, where A OWNS-A B.
</p>
        <p>
What this seems to imply, then, is that the object/relational-mapping horrors of the
past two decades aren't yet over. What's not clear is how M will make it easier (or
if it will at all) to access those extents from the languages we traditionally use
in the .NET space (C#, VB, C++/CLI, etc), specifically, what the mechanism for conducting
a query will be like, and what it's return types will be when it cross the boundary
back into C#. 
</p>
        <blockquote>
          <p>
            <em>If you're not sure what I mean by that, consider it this way: ADO.NET has a simple
mechanism for taking the query--a raw string as a parameter--and executing it, and
when it returns, it's handed back to your C# code as a DataSet, or else as an IDataReader
for row-based/column-based firehose-style consumption. Much of the criticism of ADO.NET
stems around two parts: the untyped nature of the query string, leading to potential
typos and errors, and the relative awkwardness for extracting the data from the results,
either the DataSet or the IDataReader, at least when compared to languages that have
built-in set/tuple constructs.</em>
          </p>
        </blockquote>
        <p>
The one sample that does show any sort of C# -&gt; M kinds of interaction is in the
MParserDemo sample, and here, when it queries the database, it does so using traditional
ADO.NET API calls, so I'm not sure it's to be taken as a good indicator of the plans
around M yet.
</p>
        <p>
If all there was to Oslo was "M", I'd say it was an interesting little side-note at
PDC, something that maybe a few folks might find interesting and otherwise not worth
studying, but this is not the sum total of the Oslo bits; there is also Mg, the MGrammar
language, a language specifically for building DSLs, and that's where my attention
(and next blog post) is going next.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=d2274e34-b9e5-4771-a877-505b58b8aa28" />
        <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>Explorations into &amp;quot;M&amp;quot;</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,d2274e34-b9e5-4771-a877-505b58b8aa28.aspx</guid>
      <link>http://blogs.tedneward.com/2008/11/11/Explorations+Into+QuotMquot.aspx</link>
      <pubDate>Tue, 11 Nov 2008 03:34:51 GMT</pubDate>
      <description>&lt;p&gt;
Having freshly converted both the Visual Studio 2010 and Oslo SDK VPC images that
we received at PDC 2008 last month to VMWare images, I figure it's time to dive into
M.
&lt;/p&gt;
&lt;p&gt;
At PDC, the Addison-Wesley folks were giving away copies of "The 'Oslo' Modeling Language"
book, which is apparently official canon of the "M" language for Oslo, so I flip to
page 1 and start reading:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The "Oslo" Modeling Language (M) is a modern, declarative language for working with
data. M lets users write down how they want to structure and query their data using
a convenient textual syntax that is convenient to both author and read.
&lt;/p&gt;
&lt;p&gt;
M does not mandate how data is stored or accessed, nor does it mandate a specific
implementation technology. Rather, M was designed to allow users to write down &lt;em&gt;what&lt;/em&gt; they
want from their data without having to specify &lt;em&gt;how&lt;/em&gt; those desires are met
against a given technology or platform. That stated, M in no way prohibits implementations
from providing rich declarative or imperative support for controlling how M constructs
are represented and executed in a given environment.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Hmm... I have to admit, all kinds of warning bells and alarm flags are going off in
my head, and we're just two sentences into this thing. This sounds like something
we've all done before; in fact, though I've not tried it, I have a feeling that if
we were to go back through those two paragraphs and replace every instance of "M"
with "SQL", we'd find a paragraph that could easily slip into the opening chapter
of any introductory SQL or RDBMS book.
&lt;/p&gt;
&lt;p&gt;
The goals of "separation of declaration from intent" have been around for that long,
probably longer, and even the fiercest and staunchest defenders of SQL find themselves
sometimes wandering through SQL declarations and code that clearly violate Chris Date's
politely-worded commands around normal form and separation of declaration from intent
and implementation.
&lt;/p&gt;
&lt;p&gt;
I keep reading, though, and a few paragraphs later, find something intriguing.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Another important aspect of data management that M does not address is that of update.
M is a functional language that does not have constructs for changing the contents
of an extent. &lt;em&gt;(Author's note: an "extent", defined a few paragraphs earlier, is
that "an extent provides dynamic storage for values.")&lt;/em&gt; How data changes is outside
the scope of the language. That said, M anticipates that the contents of an extent
can change via external (to M) stimuli. Subsequent versions of M are expected to provide
declarative constructs for updating data.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Wow. So the first question becomes, when are those "subsequent versions" expected?
Is this simply a state of the PDC Preview bits, or something that's not in scope for
v1 of the Oslo SDK?
&lt;/p&gt;
&lt;p&gt;
I flip through the rest of the first chapter, which seems like a decent overview,
and what I see there is an interesting type-declaration language; in many ways, it's
highly reminiscent of XML Schema Descriptions (XSD) more than SQL declarations, but
I suppose that's to be expected, at least for now. I'm sure they're going to cherry-pick
a lot of the best data-declarative constructs from XSD, SQL, and any other metadata-based
formats/languages, and that the semantics will change as they explore what works well
and what doesn't. For now, though, "M" exists essentially as a data-descriptor language,
and this is reinforced when I start playing with "m.exe", the "M compiler" (?).
&lt;/p&gt;
&lt;p&gt;
First thing, I simply fire up "m.exe" to see what the options are. And... nothing.
Huh? I wait for a bit, then Ctrl-C it, and start hunting through the documentation
to see if I'm missing something here. I try a few different tests, like "m /?" or
"m -help", and each time, the compiler just seems to wander off into the weeds, requiring
a Ctrl-C to kill it.
&lt;/p&gt;
&lt;p&gt;
What the heck? I know that these are PDC pre-alpha CTP "nothing is guaranteed to work"
bits, but this seems a bit on the excessive side--I have every faith that Microsoft
wouldn't hand these out if you can't even run the compiler! So acting on a hunch,
I fire up "m /?" again, and tab away to look at something else. Sure enough, my hunch
is rewarded--after a long pause, eventually the help screen comes up. So, apparently,
the m.exe tool just takes &lt;em&gt;fricken forever&lt;/em&gt; to run, is all.
&lt;/p&gt;
&lt;p&gt;
Currently, the only targets M can compile to is their internal Repository for storing
types, and a generic "T-SQL" target for any T-SQL-compliant database (which I presume
for now means only SQL Server of various versions, but theoretically, I suppose, Sybase
could work too, given those two systems' shared ancestry. And, given a pretty simple
sample to work with, m.exe produces a pretty-easily-anticipated result; this:
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;module Ted&lt;br&gt;
{&lt;br&gt;
type Person&lt;br&gt;
{&lt;br&gt;
Id : Integer32 = AutoNumber();&lt;br&gt;
Name : Text;&lt;br&gt;
} where identity Id;&lt;br&gt;
People : Person*; 
&lt;br&gt;
}&lt;/pre&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;p&gt;
turns into this:
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;set&lt;/span&gt; xact_abort &lt;span style="color: #0000ff"&gt;on&lt;/span&gt;;&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: #0000ff"&gt;begin&lt;/span&gt; &lt;span style="color: #0000ff"&gt;transaction&lt;/span&gt;;&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: #0000ff"&gt;set&lt;/span&gt; ansi_nulls &lt;span style="color: #0000ff"&gt;on&lt;/span&gt;;&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: #0000ff"&gt;create&lt;/span&gt; &lt;span style="color: #0000ff"&gt;schema&lt;/span&gt; [Ted];&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: #0000ff"&gt;create&lt;/span&gt; &lt;span style="color: #0000ff"&gt;table&lt;/span&gt; [Ted].[People]&lt;br&gt;
(&lt;br&gt;
[Id] &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &lt;span style="color: #0000ff"&gt;identity&lt;/span&gt;,&lt;br&gt;
[Name] nvarchar(&lt;span style="color: #0000ff"&gt;max&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,&lt;br&gt;
&lt;span style="color: #0000ff"&gt;constraint&lt;/span&gt; [PK_People] &lt;span style="color: #0000ff"&gt;primary&lt;/span&gt; &lt;span style="color: #0000ff"&gt;key&lt;/span&gt; &lt;span style="color: #0000ff"&gt;clustered&lt;/span&gt; ([Id])&lt;br&gt;
);&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
&lt;span style="color: #0000ff"&gt;commit&lt;/span&gt; &lt;span style="color: #0000ff"&gt;transaction&lt;/span&gt;;&lt;br&gt;
&lt;span style="color: #0000ff"&gt;go&lt;/span&gt;
&lt;br&gt;
&lt;/pre&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;p&gt;
... which, when you look at it, is pretty much what you'd want.
&lt;/p&gt;
&lt;p&gt;
Interestingly enough, there's no reason why people in the Java or Ruby space couldn't
use "M" just as easily, so long as the database targeted is one that M understands.
(It also wouldn't be a terribly difficult exercise to build an M compiler in Java
or Ruby, for that matter. Might be a fun off-time project, in fact.)
&lt;/p&gt;
&lt;p&gt;
One thing that's also pretty clear is that M is very collection-centric, as the first
chapter spends probably 50% of its time describing all the various ways that collections
in M (written as "{a, b, c}") interact with one another (they can be compared for
equality directly, for example, and have some neat projection/filter capabilities
that were clearly drawn from the relational algebra and LINQ syntax). Having said
that, though, one thing that is obviously missing is the traditional object "reference"-style
connection, where A OWNS-A B.
&lt;/p&gt;
&lt;p&gt;
What this seems to imply, then, is that the object/relational-mapping horrors of the
past two decades aren't yet over. What's not clear is how M will make it easier (or
if it will at all) to access those extents from the languages we traditionally use
in the .NET space (C#, VB, C++/CLI, etc), specifically, what the mechanism for conducting
a query will be like, and what it's return types will be when it cross the boundary
back into C#. 
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;If you're not sure what I mean by that, consider it this way: ADO.NET has a simple
mechanism for taking the query--a raw string as a parameter--and executing it, and
when it returns, it's handed back to your C# code as a DataSet, or else as an IDataReader
for row-based/column-based firehose-style consumption. Much of the criticism of ADO.NET
stems around two parts: the untyped nature of the query string, leading to potential
typos and errors, and the relative awkwardness for extracting the data from the results,
either the DataSet or the IDataReader, at least when compared to languages that have
built-in set/tuple constructs.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The one sample that does show any sort of C# -&amp;gt; M kinds of interaction is in the
MParserDemo sample, and here, when it queries the database, it does so using traditional
ADO.NET API calls, so I'm not sure it's to be taken as a good indicator of the plans
around M yet.
&lt;/p&gt;
&lt;p&gt;
If all there was to Oslo was "M", I'd say it was an interesting little side-note at
PDC, something that maybe a few folks might find interesting and otherwise not worth
studying, but this is not the sum total of the Oslo bits; there is also Mg, the MGrammar
language, a language specifically for building DSLs, and that's where my attention
(and next blog post) is going next.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=d2274e34-b9e5-4771-a877-505b58b8aa28" /&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,d2274e34-b9e5-4771-a877-505b58b8aa28.aspx</comments>
      <category>.NET</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=44481f40-dbca-438c-9398-2ed93a3d62d8</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,44481f40-dbca-438c-9398-2ed93a3d62d8.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,44481f40-dbca-438c-9398-2ed93a3d62d8.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=44481f40-dbca-438c-9398-2ed93a3d62d8</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">Roy
Fielding has weighed in</a> on the recent "buzzwordiness" (hey, if Colbert can make
up "truthiness", then I can make up "buzzwordiness") of calling everything a "REST
API", a tactic that has become more <em>en vogue</em> of late as vendors discover
that the general programming population is finding the WSDL-based XML services stack
too complex to navigate successfully for all but the simplest of projects. Contrary
to what many RESTafarians may be hoping, Roy doesn't gather all these wayward children
to his breast and praise their anti-vendor/anti-corporate/anti-proprietary efforts,
but instead, blasts them pretty seriously for mangling his term:
</p>
        <blockquote>
          <p>
I am getting frustrated by the number of people calling any HTTP-based interface a
REST API. Today’s example is the <a href="http://wikis.glassfish.org/socialsite/Wiki.jsp?page=FinalizeRESTAPI">SocialSite
REST API</a>. That is RPC. It screams RPC. There is so much coupling on display that
it should be given an X rating.
</p>
        </blockquote>
        <p>
Ouch. "So much coupling on display that it should be given an X rating." I have to
remember that phrase--that's a keeper. And I'm shocked that Roy even knows what an
X rating is; he's such a mellow guy with such an innocent-looking face, I would've
bet money he'd never run into one before. <em>(Yes, people, that's a joke.)</em></p>
        <blockquote>
          <p>
What needs to be done to make the REST architectural style clear on the notion that
hypertext is a constraint? In other words, if the engine of application state (and
hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot
be a REST API. Period. Is there some broken manual somewhere that needs to be fixed?
</p>
        </blockquote>
        <p>
Go Roy!
</p>
        <p>
For those of you who've <em>not</em> read Roy's thesis, and are thinking that this
is some kind of betrayal or trick, let's first of all point out that at no point is
Roy saying that your nifty HTTP-based API is not <em>useful</em> or <em>simple</em>.
He's simply saying that it isn't <em>RESTful</em>. That's a key differentiation. REST
has a specific set of goals and constraints it was trying to meet, and as such prescribes
a particular kind of architectural style to fit within those constraints. (Yes, REST
is essentially an architectural pattern: a solution to a problem within a certain
context that yields certain consequences.)
</p>
        <p>
Assuming you haven't tuned me out completely already, allow me to elucidate. In Chapter
5 of <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">Roy's
thesis</a>, Roy begins to build up the style that will ultimately be considered REST.
I'm not going to quote each and every step here--that's what the hyperlink above is
for--but simply call out certain parts. For example, in section 5.1.3, "Stateless",
he suggests that this architectural style should be stateless in nature, and explains
why; the emphasis/italics are mine:
</p>
        <blockquote>
          <p>
We next add a constraint to the client-server interaction: communication must be stateless
in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure
5-3), such that <em>each request from client to server must contain all of the information
necessary to understand the request</em>, and cannot take advantage of any stored
context on the server. <em>Session state is therefore kept entirely on the client</em>. 
</p>
          <p>
This constraint induces the properties of visibility, reliability, and scalability.
Visibility is improved because a monitoring system does not have to look beyond a
single request datum in order to determine the full nature of the request. Reliability
is improved because it eases the task of recovering from partial failures [133]. Scalability
is improved because not having to store state between requests allows the server component
to quickly free resources, and further simplifies implementation because the server
doesn't have to manage resource usage across requests. 
</p>
          <p>
Like most architectural choices, the stateless constraint reflects a design trade-off.
The disadvantage is that it may decrease network performance by increasing the repetitive
data (per-interaction overhead) sent in a series of requests, since that data cannot
be left on the server in a shared context. In addition, placing the application state
on the client-side reduces the server's control over consistent application behavior,
since the application becomes dependent on the correct implementation of semantics
across multiple client versions.
</p>
        </blockquote>
        <p>
In the HTTP case, the state is contained entirely in the document itself, the hypertext.
This has a couple of implications for those of us building "distributed applications",
such as the very real consideration that there's a <em>lot</em> of state we don't
necessarily want to be sending back to the client, such as voluminous information
(the user's e-commerce shopping cart contents) or sensitive information (the user's
credentials or single-signon authentication/authorization token). This is a bitter
pill to swallow for the application development world, because much of the applications
we develop have some pretty hefty notions of server-based state management that we
want or need to preserve, either for legacy support reasons, for legitimate concerns
(network bandwidth or security), or just for ease-of-understanding. Fielding isn't
apologetic about it, though--look at the third paragraph above. "[T]he stateless constraint
reflects a design trade-off."
</p>
        <p>
In other words, if you don't like it, fine, don't follow it, but understand that if
you're not leaving all the application state on the client, you're not doing REST.
</p>
        <p>
By the way, note that technically, HTTP is not tied to HTML, since the document sent
back and forth could easily be a PDF document, too, particularly since PDF supports
hyperlinks to other PDF documents. Nowhere in the thesis do we see the idea that it <em>has</em> to
be HTML flying back and forth.
</p>
        <p>
Roy's thesis continues on in the same vein; in section 5.1.4 he describes how "client-cache-stateless-server"
provides some additional reliability and performance, but only if the data in the
cache is consistent and not stale, which was fine for static documents, but not for
dynamic content such as image maps. Extensions were necessary in order to accomodate
the new ideas.
</p>
        <p>
In section 5.1.5 ("Uniform Interface") we get to another stinging rebuke of REST as
a generalized distributed application scheme; again, the emphasis is mine:
</p>
        <blockquote>
          <p>
The central feature that distinguishes the REST architectural style from other network-based
styles is its emphasis on a uniform interface between components (Figure 5-6). By
applying the software engineering principle of generality to the component interface,
the overall system architecture is simplified and the visibility of interactions is
improved. Implementations are decoupled from the services they provide, which encourages
independent evolvability. The trade-off, though, is that a uniform interface degrades
efficiency, since information is transferred in a standardized form rather than one
which is specific to an application's needs. The REST interface is designed to be
efficient for large-grain hypermedia data transfer, optimizing for the common case
of the Web, but resulting in an interface that is not optimal for other forms of architectural
interaction. 
</p>
          <p>
In order to obtain a uniform interface, multiple architectural constraints are needed
to guide the behavior of components. <em>REST is defined by four interface constraints</em>:
identification of resources; manipulation of resources through representations; self-descriptive
messages; and, <em>hypermedia as the engine of application state</em>. These constraints
will be discussed in Section 5.2.
</p>
        </blockquote>
        <p>
In other words, in order to be doing something that Fielding considers RESTful, you
have to be using hypermedia (that is to say, hypertext documents of some form) as
the core of your application state. It might seem like this implies that you have
to be building a Web application in order to be considered building something RESTful,
so therefore all Web apps are RESTful by nature, but pay close attention to the wording:
hypermedia must be the <em>core</em> of your application state. The way most Web apps
are built today, HTML is clearly not the core of the state, but merely a way to render
it. This is the accidental consequence of treating Web applications and desktop client
applications as just pale reflections of one another.
</p>
        <p>
The next section, 5.1.6 ("Layered System") again builds on the notion of stateless-server
architecture to provide additional flexibility and power:
</p>
        <blockquote>
          <p>
In order to further improve behavior for Internet-scale requirements, we add layered
system constraints (Figure 5-7). As described in Section 3.4.2, the layered system
style allows an architecture to be composed of hierarchical layers by constraining
component behavior such that each component cannot "see" beyond the immediate layer
with which they are interacting. By restricting knowledge of the system to a single
layer, we place a bound on the overall system complexity and promote substrate independence.
Layers can be used to encapsulate legacy services and to protect new services from
legacy clients, simplifying components by moving infrequently used functionality to
a shared intermediary. Intermediaries can also be used to improve system scalability
by enabling load balancing of services across multiple networks and processors. 
</p>
          <p>
The primary disadvantage of layered systems is that they add overhead and latency
to the processing of data, reducing user-perceived performance [32].<em> For a network-based
system that supports cache constraints, this can be offset by the benefits of shared
caching at intermediaries.</em> Placing shared caches at the boundaries of an organizational
domain can result in significant performance benefits [136]. Such layers also allow
security policies to be enforced on data crossing the organizational boundary, as
is required by firewalls [79]. 
</p>
          <p>
The combination of layered system and uniform interface constraints induces architectural
properties similar to those of the uniform pipe-and-filter style (Section 3.2.2).
Although REST interaction is two-way, the large-grain data flows of hypermedia interaction
can each be processed like a data-flow network, with filter components selectively
applied to the data stream in order to transform the content as it passes [26]. <em>Within
REST, intermediary components can actively transform the content of messages because
the messages are self-descriptive and their semantics are visible to intermediaries.</em></p>
        </blockquote>
        <p>
The potential of layered systems (itself not something that people building RESTful
approaches seem to think much about) is only realized if the entirety of the state
being transferred is self-descriptive and visible to the intermediaries--in other
words, intermediaries can only be helpful and/or non-performance-inhibitive if they
have free reign to make decisions based on the state they see being transferred. If
something isn't present in the state being transferred, usually because there is server-side
state being maintained, then they have to be concerned about silently changing the
semantics of what is happening in the interaction, and intermediaries--and layers
as a whole--become a liability. (Which is probably why so few systems seem to do it.)
</p>
        <p>
And if the notion of visible, transported state is not yet made clear in his dissertation,
Fielding dissects the discussion even further in section 5.2.1, "Data Elements". It's
too long to reprint here in its entirety, and frankly, reading the whole thing is
necessary to see the point of hypermedia and its place in the whole system. (The same
could be said of the entire chapter, in fact.) But it's pretty clear, once you read
the dissertation, that hypermedia/hypertext is a core, critical piece to the whole
REST construction. Clients are expected, in a RESTful system, to have <em>no</em> preconceived
notions of structure or relationship between resources, and discover all of that through
the state of the hypertext documents that are sent back to them. In the HTML case,
that discovery occurs inside the human brain; in the SOA/services case, that discovery
is much harder to define and describe. RDF and Semantic Web ideas may be of some help
here, but JSON can't, and simple XML can't, unless the client has some preconceived
notion of what the XML structure looks like, which violates Fielding's rules:
</p>
        <blockquote>
          <p>
A REST API should be entered with no prior knowledge beyond the initial URI (bookmark)
and set of standardized media types that are appropriate for the intended audience
(i.e., expected to be understood by any client that might use the API). From that
point on, all application state transitions must be driven by client selection of
server-provided choices that are present in the received representations or implied
by the user’s manipulation of those representations. The transitions may be determined
(or limited by) the client’s knowledge of media types and resource communication mechanisms,
both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies
that out-of-band information is driving interaction instead of hypertext.]
</p>
        </blockquote>
        <p>
An interesting "fuzzy gray area" here is whether or not the client's knowledge of
a variant or schematic structure of XML could be considered to be a "standardized
media type", but I'm willing to bet that Fielding will argue against it on the grounds
that your application's XML schema is not "standardized" (unless, of course, it is,
through a national/international/industry standardization effort).
</p>
        <p>
But in case you'd missed it, let me summarize the past twenty or so paragraphs: <em>hypermedia
is a core requirement to being RESTful.</em> If you ain't slinging all of your application
state back and forth in hypertext, you ain't REST. Period. Fielding said it, he defined
it, and that settles it.
</p>
        <p>
 
</p>
        <p>
Before the hate mail comes a-flyin', let me reiterate one vitally important point: <em>if
you're not doing REST, it doesn't mean that your API sucks.</em> Fielding may have
his definition of what REST is, and the idealist in me wants to remain true to his
definitions of it (after all, if we can't agree on a common set of definitions, a
common lexicon, then we can't really make much progress as an industry), but...
</p>
        <p>
... the pragmatist in me keeps saying, "so what"?
</p>
        <p>
Look, at the end of the day, if your system wants to misuse HTTP, abuse HTML, and
carnally violate the principles of loose coupling and resource representation that
underlie REST, who cares? Do you get special bonus points from the Apache Foundation
if you use HTTP in the way Fielding intended? Will Microsoft and Oracle and Sun and
IBM offer you discounts on your next software purchases if you create a REST-faithful
system? Will the partisan politics in Washington, or the tribal conflicts in the Middle
East, or even the widely-misnamed "REST-vs-SOAP" debates come to an end if you only
figure out a way to make hypermedia the core engine of your application state?
</p>
        <p>
Yeah, I didn't think so, either.
</p>
        <p>
Point is, REST is <em>just</em> an architectural style. It is nothing more than another
entry alongside such things as client-server, <em>n</em>-tier, distributed objects,
service-oriented, and embedded systems. REST is just a tool for thinking about how
to build an application, and it's high time we kick it off the pedastal on which we've
placed it and let it come back down to earth with the rest of us mortals. HTTP is
useful, but not sufficient, so solve our problems. REST is as well.
</p>
        <p>
And at the end of the day, when we put one tool from our tool belt "above all others",
we end up building some truly horrendous crap.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=44481f40-dbca-438c-9398-2ed93a3d62d8" />
        <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>REST != HTTP</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,44481f40-dbca-438c-9398-2ed93a3d62d8.aspx</guid>
      <link>http://blogs.tedneward.com/2008/11/07/REST+HTTP.aspx</link>
      <pubDate>Fri, 07 Nov 2008 05:34:23 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven"&gt;Roy
Fielding has weighed in&lt;/a&gt; on the recent "buzzwordiness" (hey, if Colbert can make
up "truthiness", then I can make up "buzzwordiness") of calling everything a "REST
API", a tactic that has become more &lt;em&gt;en vogue&lt;/em&gt; of late as vendors discover
that the general programming population is finding the WSDL-based XML services stack
too complex to navigate successfully for all but the simplest of projects. Contrary
to what many RESTafarians may be hoping, Roy doesn't gather all these wayward children
to his breast and praise their anti-vendor/anti-corporate/anti-proprietary efforts,
but instead, blasts them pretty seriously for mangling his term:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I am getting frustrated by the number of people calling any HTTP-based interface a
REST API. Today’s example is the &lt;a href="http://wikis.glassfish.org/socialsite/Wiki.jsp?page=FinalizeRESTAPI"&gt;SocialSite
REST API&lt;/a&gt;. That is RPC. It screams RPC. There is so much coupling on display that
it should be given an X rating.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ouch. "So much coupling on display that it should be given an X rating." I have to
remember that phrase--that's a keeper. And I'm shocked that Roy even knows what an
X rating is; he's such a mellow guy with such an innocent-looking face, I would've
bet money he'd never run into one before. &lt;em&gt;(Yes, people, that's a joke.)&lt;/em&gt; &lt;blockquote&gt; 
&lt;p&gt;
What needs to be done to make the REST architectural style clear on the notion that
hypertext is a constraint? In other words, if the engine of application state (and
hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot
be a REST API. Period. Is there some broken manual somewhere that needs to be fixed?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Go Roy!
&lt;/p&gt;
&lt;p&gt;
For those of you who've &lt;em&gt;not&lt;/em&gt; read Roy's thesis, and are thinking that this
is some kind of betrayal or trick, let's first of all point out that at no point is
Roy saying that your nifty HTTP-based API is not &lt;em&gt;useful&lt;/em&gt; or &lt;em&gt;simple&lt;/em&gt;.
He's simply saying that it isn't &lt;em&gt;RESTful&lt;/em&gt;. That's a key differentiation. REST
has a specific set of goals and constraints it was trying to meet, and as such prescribes
a particular kind of architectural style to fit within those constraints. (Yes, REST
is essentially an architectural pattern: a solution to a problem within a certain
context that yields certain consequences.)
&lt;/p&gt;
&lt;p&gt;
Assuming you haven't tuned me out completely already, allow me to elucidate. In Chapter
5 of &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm"&gt;Roy's
thesis&lt;/a&gt;, Roy begins to build up the style that will ultimately be considered REST.
I'm not going to quote each and every step here--that's what the hyperlink above is
for--but simply call out certain parts. For example, in section 5.1.3, "Stateless",
he suggests that this architectural style should be stateless in nature, and explains
why; the emphasis/italics are mine:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
We next add a constraint to the client-server interaction: communication must be stateless
in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure
5-3), such that &lt;em&gt;each request from client to server must contain all of the information
necessary to understand the request&lt;/em&gt;, and cannot take advantage of any stored
context on the server. &lt;em&gt;Session state is therefore kept entirely on the client&lt;/em&gt;. 
&lt;p&gt;
This constraint induces the properties of visibility, reliability, and scalability.
Visibility is improved because a monitoring system does not have to look beyond a
single request datum in order to determine the full nature of the request. Reliability
is improved because it eases the task of recovering from partial failures [133]. Scalability
is improved because not having to store state between requests allows the server component
to quickly free resources, and further simplifies implementation because the server
doesn't have to manage resource usage across requests. 
&lt;p&gt;
Like most architectural choices, the stateless constraint reflects a design trade-off.
The disadvantage is that it may decrease network performance by increasing the repetitive
data (per-interaction overhead) sent in a series of requests, since that data cannot
be left on the server in a shared context. In addition, placing the application state
on the client-side reduces the server's control over consistent application behavior,
since the application becomes dependent on the correct implementation of semantics
across multiple client versions.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
In the HTTP case, the state is contained entirely in the document itself, the hypertext.
This has a couple of implications for those of us building "distributed applications",
such as the very real consideration that there's a &lt;em&gt;lot&lt;/em&gt; of state we don't
necessarily want to be sending back to the client, such as voluminous information
(the user's e-commerce shopping cart contents) or sensitive information (the user's
credentials or single-signon authentication/authorization token). This is a bitter
pill to swallow for the application development world, because much of the applications
we develop have some pretty hefty notions of server-based state management that we
want or need to preserve, either for legacy support reasons, for legitimate concerns
(network bandwidth or security), or just for ease-of-understanding. Fielding isn't
apologetic about it, though--look at the third paragraph above. "[T]he stateless constraint
reflects a design trade-off."
&lt;/p&gt;
&lt;p&gt;
In other words, if you don't like it, fine, don't follow it, but understand that if
you're not leaving all the application state on the client, you're not doing REST.
&lt;/p&gt;
&lt;p&gt;
By the way, note that technically, HTTP is not tied to HTML, since the document sent
back and forth could easily be a PDF document, too, particularly since PDF supports
hyperlinks to other PDF documents. Nowhere in the thesis do we see the idea that it &lt;em&gt;has&lt;/em&gt; to
be HTML flying back and forth.
&lt;/p&gt;
&lt;p&gt;
Roy's thesis continues on in the same vein; in section 5.1.4 he describes how "client-cache-stateless-server"
provides some additional reliability and performance, but only if the data in the
cache is consistent and not stale, which was fine for static documents, but not for
dynamic content such as image maps. Extensions were necessary in order to accomodate
the new ideas.
&lt;/p&gt;
&lt;p&gt;
In section 5.1.5 ("Uniform Interface") we get to another stinging rebuke of REST as
a generalized distributed application scheme; again, the emphasis is mine:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The central feature that distinguishes the REST architectural style from other network-based
styles is its emphasis on a uniform interface between components (Figure 5-6). By
applying the software engineering principle of generality to the component interface,
the overall system architecture is simplified and the visibility of interactions is
improved. Implementations are decoupled from the services they provide, which encourages
independent evolvability. The trade-off, though, is that a uniform interface degrades
efficiency, since information is transferred in a standardized form rather than one
which is specific to an application's needs. The REST interface is designed to be
efficient for large-grain hypermedia data transfer, optimizing for the common case
of the Web, but resulting in an interface that is not optimal for other forms of architectural
interaction. 
&lt;p&gt;
In order to obtain a uniform interface, multiple architectural constraints are needed
to guide the behavior of components. &lt;em&gt;REST is defined by four interface constraints&lt;/em&gt;:
identification of resources; manipulation of resources through representations; self-descriptive
messages; and, &lt;em&gt;hypermedia as the engine of application state&lt;/em&gt;. These constraints
will be discussed in Section 5.2.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
In other words, in order to be doing something that Fielding considers RESTful, you
have to be using hypermedia (that is to say, hypertext documents of some form) as
the core of your application state. It might seem like this implies that you have
to be building a Web application in order to be considered building something RESTful,
so therefore all Web apps are RESTful by nature, but pay close attention to the wording:
hypermedia must be the &lt;em&gt;core&lt;/em&gt; of your application state. The way most Web apps
are built today, HTML is clearly not the core of the state, but merely a way to render
it. This is the accidental consequence of treating Web applications and desktop client
applications as just pale reflections of one another.
&lt;/p&gt;
&lt;p&gt;
The next section, 5.1.6 ("Layered System") again builds on the notion of stateless-server
architecture to provide additional flexibility and power:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
In order to further improve behavior for Internet-scale requirements, we add layered
system constraints (Figure 5-7). As described in Section 3.4.2, the layered system
style allows an architecture to be composed of hierarchical layers by constraining
component behavior such that each component cannot "see" beyond the immediate layer
with which they are interacting. By restricting knowledge of the system to a single
layer, we place a bound on the overall system complexity and promote substrate independence.
Layers can be used to encapsulate legacy services and to protect new services from
legacy clients, simplifying components by moving infrequently used functionality to
a shared intermediary. Intermediaries can also be used to improve system scalability
by enabling load balancing of services across multiple networks and processors. 
&lt;p&gt;
The primary disadvantage of layered systems is that they add overhead and latency
to the processing of data, reducing user-perceived performance [32].&lt;em&gt; For a network-based
system that supports cache constraints, this can be offset by the benefits of shared
caching at intermediaries.&lt;/em&gt; Placing shared caches at the boundaries of an organizational
domain can result in significant performance benefits [136]. Such layers also allow
security policies to be enforced on data crossing the organizational boundary, as
is required by firewalls [79]. 
&lt;p&gt;
The combination of layered system and uniform interface constraints induces architectural
properties similar to those of the uniform pipe-and-filter style (Section 3.2.2).
Although REST interaction is two-way, the large-grain data flows of hypermedia interaction
can each be processed like a data-flow network, with filter components selectively
applied to the data stream in order to transform the content as it passes [26]. &lt;em&gt;Within
REST, intermediary components can actively transform the content of messages because
the messages are self-descriptive and their semantics are visible to intermediaries.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The potential of layered systems (itself not something that people building RESTful
approaches seem to think much about) is only realized if the entirety of the state
being transferred is self-descriptive and visible to the intermediaries--in other
words, intermediaries can only be helpful and/or non-performance-inhibitive if they
have free reign to make decisions based on the state they see being transferred. If
something isn't present in the state being transferred, usually because there is server-side
state being maintained, then they have to be concerned about silently changing the
semantics of what is happening in the interaction, and intermediaries--and layers
as a whole--become a liability. (Which is probably why so few systems seem to do it.)
&lt;/p&gt;
&lt;p&gt;
And if the notion of visible, transported state is not yet made clear in his dissertation,
Fielding dissects the discussion even further in section 5.2.1, "Data Elements". It's
too long to reprint here in its entirety, and frankly, reading the whole thing is
necessary to see the point of hypermedia and its place in the whole system. (The same
could be said of the entire chapter, in fact.) But it's pretty clear, once you read
the dissertation, that hypermedia/hypertext is a core, critical piece to the whole
REST construction. Clients are expected, in a RESTful system, to have &lt;em&gt;no&lt;/em&gt; preconceived
notions of structure or relationship between resources, and discover all of that through
the state of the hypertext documents that are sent back to them. In the HTML case,
that discovery occurs inside the human brain; in the SOA/services case, that discovery
is much harder to define and describe. RDF and Semantic Web ideas may be of some help
here, but JSON can't, and simple XML can't, unless the client has some preconceived
notion of what the XML structure looks like, which violates Fielding's rules:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
A REST API should be entered with no prior knowledge beyond the initial URI (bookmark)
and set of standardized media types that are appropriate for the intended audience
(i.e., expected to be understood by any client that might use the API). From that
point on, all application state transitions must be driven by client selection of
server-provided choices that are present in the received representations or implied
by the user’s manipulation of those representations. The transitions may be determined
(or limited by) the client’s knowledge of media types and resource communication mechanisms,
both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies
that out-of-band information is driving interaction instead of hypertext.]
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
An interesting "fuzzy gray area" here is whether or not the client's knowledge of
a variant or schematic structure of XML could be considered to be a "standardized
media type", but I'm willing to bet that Fielding will argue against it on the grounds
that your application's XML schema is not "standardized" (unless, of course, it is,
through a national/international/industry standardization effort).
&lt;/p&gt;
&lt;p&gt;
But in case you'd missed it, let me summarize the past twenty or so paragraphs: &lt;em&gt;hypermedia
is a core requirement to being RESTful.&lt;/em&gt; If you ain't slinging all of your application
state back and forth in hypertext, you ain't REST. Period. Fielding said it, he defined
it, and that settles it.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Before the hate mail comes a-flyin', let me reiterate one vitally important point: &lt;em&gt;if
you're not doing REST, it doesn't mean that your API sucks.&lt;/em&gt; Fielding may have
his definition of what REST is, and the idealist in me wants to remain true to his
definitions of it (after all, if we can't agree on a common set of definitions, a
common lexicon, then we can't really make much progress as an industry), but...
&lt;/p&gt;
&lt;p&gt;
... the pragmatist in me keeps saying, "so what"?
&lt;/p&gt;
&lt;p&gt;
Look, at the end of the day, if your system wants to misuse HTTP, abuse HTML, and
carnally violate the principles of loose coupling and resource representation that
underlie REST, who cares? Do you get special bonus points from the Apache Foundation
if you use HTTP in the way Fielding intended? Will Microsoft and Oracle and Sun and
IBM offer you discounts on your next software purchases if you create a REST-faithful
system? Will the partisan politics in Washington, or the tribal conflicts in the Middle
East, or even the widely-misnamed "REST-vs-SOAP" debates come to an end if you only
figure out a way to make hypermedia the core engine of your application state?
&lt;/p&gt;
&lt;p&gt;
Yeah, I didn't think so, either.
&lt;/p&gt;
&lt;p&gt;
Point is, REST is &lt;em&gt;just&lt;/em&gt; an architectural style. It is nothing more than another
entry alongside such things as client-server, &lt;em&gt;n&lt;/em&gt;-tier, distributed objects,
service-oriented, and embedded systems. REST is just a tool for thinking about how
to build an application, and it's high time we kick it off the pedastal on which we've
placed it and let it come back down to earth with the rest of us mortals. HTTP is
useful, but not sufficient, so solve our problems. REST is as well.
&lt;/p&gt;
&lt;p&gt;
And at the end of the day, when we put one tool from our tool belt "above all others",
we end up building some truly horrendous crap.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=44481f40-dbca-438c-9398-2ed93a3d62d8" /&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,44481f40-dbca-438c-9398-2ed93a3d62d8.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Security</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=97495cb3-1448-4b63-a607-8472d5d2a159</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,97495cb3-1448-4b63-a607-8472d5d2a159.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,97495cb3-1448-4b63-a607-8472d5d2a159.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=97495cb3-1448-4b63-a607-8472d5d2a159</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, a blog reader asked me if I wasn't doing any speaking any more since I'd
joined ThoughtWorks, and that's when I realized I'd been bad about updating my speaking
calendar on the website. Sorry, all; no, ThoughtWorks didn't pull my conference visa
or anything, I've just been bad about keeping it up to date. I'll fix that ASAP, but
in the meantime, three events that I'll be at in the coming wintry months include:
</p>
        <h3>
          <a href="http://www.oredev.org/">Øredev 2008</a>: 19 - 21 November, Malmoe, Sweden
</h3>
        <p>
Øredev will be a first for me, and I've ben invited to give a keynote there, along
with a few technical sessions. I'm also told that .NET Rocks! will be on hand, and
that they want to record a session, on whichever topic happens to cross the curious,
crafty and cunning Carl, or the uh... the uh... sorry, Richard, there's just no good
"R" adjectives I can use here. I mean, "rough" and "ready" don't exactly sound flattering
in this context, right? Sorry, man.
</p>
        <p>
In any event, I'm looking forward to this event, because it's a curious mix of technologies
and ideas (agile, ALT.NET, Java, core .NET, languages, and so on), and because I've
never been to Sweden before. One more European country, off my bucket list! :-)
</p>
        <p>
(Yes, I had to cut-and-paste the Ø wherever I needed it. *grin*)
</p>
        <h3>
        </h3>
        <h3>
          <a href="http://www.devteach.com">DevTeach 2008</a>: 1 - 5 December, Montreal,
Quebec (Canada)
</h3>
        <p>
This has been one of my favorite shows since it began, way back in 2003, and a large
part of that love has to do with the cast and crew of characters that I see there
every year: Julie Lerman, Peter DeBetta, Carl and Richard (again!), Beth Massi, "Yag"
Griver, Mario Cardinal and the rest of the Quebecois posse, Ayende, plus some new
faces and friends, like Jessica Moss and James Kovacs. (Oh, and for the record, folks,
for those of you who are <em>still</em> talking about it, the O/R-M smackdown of a
year ago was staged. It was all fake. Ayende and I are really actually friends, we
were paid a great deal of money by Carl and Richard to make it sound good, and in
fact, we both agree that the only place anybody should really ever store their data
is in an XML database.)
</p>
        <p>
If you're near Montreal, and you're a .NET dev, you really owe it to yourself to check
this show out.
</p>
        <p>
          <strong>Update:</strong> I just got this email from Jean-Rene, the guy who runs DevTeach:
</p>
        <blockquote>
          <p>
Every attendees will get Visual Studio 2008 Pro, Expression Web 2 and Tech-Ed DEV
set in their bag! 
</p>
          <p>
DevTeach believe that all developers need the right tool to be productive. This is
what we will give you, free software, when you register to DevTeach or SQLTeach. Yes
that right! We’re pleased to announce that we’re giving over a 1000$ of software when
you register to DevTeach. You will find in your conference bag a version of Visual
Studio 2008 Professional, ExpressionTM Web 2 and the Tech-Ed Conference DVD Set. Is
this a good deal or what? DevTeach and SQLTeach are really the training you can’t
get any other way. 
</p>
        </blockquote>
        <p>
Not bad. Not bad at all.
</p>
        <h3>
          <a href="http://www.devoxx.com/display/JV08/Home">DeVoxx 2008</a>: 8 - 12 December,
Antwerp, Belgium
</h3>
        <p>
DeVoxx, the recently-renamed-formerly-named-JavaPolis conference, has brought me back
to team up with Bill Venners to do a University session on Scala, and to record a
few more of those Parlays videos that people can't seem to get enough of. Given that
this show always seems to draw some of the Java world's best and brightest, I'm definitely
looking forward to the chance to point the mike at somebody's grill and give 'em hell!
Plus, I love Belgium, and I'm looking forward to getting back there. The fact that
it's going to be the middle of winter is only a bonus, as... wait... Belgium, in the
middle of winter? Whose bright idea was that?
</p>
        <p>
(And finally, a show that Carl and Richard won't be at!)
</p>
        <p>
 
</p>
        <p>
Meanwhile, I promise to keep the "Upcoming Events" up to date for 2009. Seriously.
I mean it. :-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=97495cb3-1448-4b63-a607-8472d5d2a159" />
        <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>Winter Travels: &amp;Oslash;redev, DevTeach, DeVoxx</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,97495cb3-1448-4b63-a607-8472d5d2a159.aspx</guid>
      <link>http://blogs.tedneward.com/2008/11/06/Winter+Travels+Oslashredev+DevTeach+DeVoxx.aspx</link>
      <pubDate>Thu, 06 Nov 2008 08:14:17 GMT</pubDate>
      <description>&lt;p&gt;
Recently, a blog reader asked me if I wasn't doing any speaking any more since I'd
joined ThoughtWorks, and that's when I realized I'd been bad about updating my speaking
calendar on the website. Sorry, all; no, ThoughtWorks didn't pull my conference visa
or anything, I've just been bad about keeping it up to date. I'll fix that ASAP, but
in the meantime, three events that I'll be at in the coming wintry months include:
&lt;/p&gt;
&lt;h3&gt;&lt;a href="http://www.oredev.org/"&gt;Øredev 2008&lt;/a&gt;: 19 - 21 November, Malmoe, Sweden
&lt;/h3&gt;
&lt;p&gt;
Øredev will be a first for me, and I've ben invited to give a keynote there, along
with a few technical sessions. I'm also told that .NET Rocks! will be on hand, and
that they want to record a session, on whichever topic happens to cross the curious,
crafty and cunning Carl, or the uh... the uh... sorry, Richard, there's just no good
"R" adjectives I can use here. I mean, "rough" and "ready" don't exactly sound flattering
in this context, right? Sorry, man.
&lt;/p&gt;
&lt;p&gt;
In any event, I'm looking forward to this event, because it's a curious mix of technologies
and ideas (agile, ALT.NET, Java, core .NET, languages, and so on), and because I've
never been to Sweden before. One more European country, off my bucket list! :-)
&lt;/p&gt;
&lt;p&gt;
(Yes, I had to cut-and-paste the Ø wherever I needed it. *grin*)
&lt;/p&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;&lt;a href="http://www.devteach.com"&gt;DevTeach 2008&lt;/a&gt;: 1 - 5 December, Montreal,
Quebec (Canada)
&lt;/h3&gt;
&lt;p&gt;
This has been one of my favorite shows since it began, way back in 2003, and a large
part of that love has to do with the cast and crew of characters that I see there
every year: Julie Lerman, Peter DeBetta, Carl and Richard (again!), Beth Massi, "Yag"
Griver, Mario Cardinal and the rest of the Quebecois posse, Ayende, plus some new
faces and friends, like Jessica Moss and James Kovacs. (Oh, and for the record, folks,
for those of you who are &lt;em&gt;still&lt;/em&gt; talking about it, the O/R-M smackdown of a
year ago was staged. It was all fake. Ayende and I are really actually friends, we
were paid a great deal of money by Carl and Richard to make it sound good, and in
fact, we both agree that the only place anybody should really ever store their data
is in an XML database.)
&lt;/p&gt;
&lt;p&gt;
If you're near Montreal, and you're a .NET dev, you really owe it to yourself to check
this show out.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; I just got this email from Jean-Rene, the guy who runs DevTeach:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Every attendees will get Visual Studio 2008 Pro, Expression Web 2 and Tech-Ed DEV
set in their bag! 
&lt;p&gt;
DevTeach believe that all developers need the right tool to be productive. This is
what we will give you, free software, when you register to DevTeach or SQLTeach. Yes
that right! We’re pleased to announce that we’re giving over a 1000$ of software when
you register to DevTeach. You will find in your conference bag a version of Visual
Studio 2008 Professional, ExpressionTM Web 2 and the Tech-Ed Conference DVD Set. Is
this a good deal or what? DevTeach and SQLTeach are really the training you can’t
get any other way. 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Not bad. Not bad at all.
&lt;/p&gt;
&lt;h3&gt;&lt;a href="http://www.devoxx.com/display/JV08/Home"&gt;DeVoxx 2008&lt;/a&gt;: 8 - 12 December,
Antwerp, Belgium
&lt;/h3&gt;
&lt;p&gt;
DeVoxx, the recently-renamed-formerly-named-JavaPolis conference, has brought me back
to team up with Bill Venners to do a University session on Scala, and to record a
few more of those Parlays videos that people can't seem to get enough of. Given that
this show always seems to draw some of the Java world's best and brightest, I'm definitely
looking forward to the chance to point the mike at somebody's grill and give 'em hell!
Plus, I love Belgium, and I'm looking forward to getting back there. The fact that
it's going to be the middle of winter is only a bonus, as... wait... Belgium, in the
middle of winter? Whose bright idea was that?
&lt;/p&gt;
&lt;p&gt;
(And finally, a show that Carl and Richard won't be at!)
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Meanwhile, I promise to keep the "Upcoming Events" up to date for 2009. Seriously.
I mean it. :-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=97495cb3-1448-4b63-a607-8472d5d2a159" /&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,97495cb3-1448-4b63-a607-8472d5d2a159.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Security</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=8e0ae181-cdae-412c-95c7-ea7ab2da39b9</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,8e0ae181-cdae-412c-95c7-ea7ab2da39b9.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,8e0ae181-cdae-412c-95c7-ea7ab2da39b9.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8e0ae181-cdae-412c-95c7-ea7ab2da39b9</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
PDC 2008 in LA is over now, and like most PDCs, it definitely didn't disappoint on
the technical front--Microsoft tossed out a whole slew of new technologies, ideas,
releases, and prototypes, all with the eye towards getting bits (in this case, a Western
Digital 160 GB USB hard drive) out to the developer community and getting back feedback,
either through the usual channels or, more recently, the blogosphere.
</p>
        <p>
These are the things I think I think about this past PDC:
</p>
        <ul>
          <li>
Windows 7 will be an interesting thing to watch--they handed out DVDs in both 32-
and 64-bit versions, and it's somewhat reminiscent of the Longhorn DVDs of the last
PDC. If you recall, Longhorn (what eventually became known as Vista) looked surprisingly
good--if a bit unstable, something common to any release this early--for a while,
then Vista itself pretty much fell flat. I think it will be interesting, as a social
experiment, to look at what people say about Windows 7 now, compare it to what was
said about Vista back in 2004 (which is I think when the last PDC was), and then compare
what people say 1, 2 and 3 years after the PDC release. 
</li>
          <li>
Azure dominated a lot of the focus, commensurate with the growing interest/hype around
"the cloud". All of this sounds suspiciously familiar to me, thinking back to the
early days of SOAP/WSDL, and the intense pressure for Web services to revolutionize
IT as we know it. This didn't happen, largely for technical reasons at first (incompatibilities
between toolkits most of all), then because people treated it as CORBA++ or DCOM-with-angle-brackets.
Azure and "cloud computing" have a different problem: clear definition of purpose.
I think too many people have no idea what "the cloud" really is for this to be something
to pay much attention to just yet. 
</li>
          <li>
Conference get-togethers and parties are becoming more and more lavish each year,
as the various product teams challenge one another for the coveted title of The "Dude,
were you <em>there</em> last night? It was amazing!" Party of PDC. For my money, that
party was the party at the J Lounge on Wednesday night, complete with three floors
of fun, including a wall-projected image of Rock Band, but--here's the rub--I couldn't
tell you which team actually hosted the party. There was a Microsoft Dynamics CRM
poster up in the middle of the gaming floor (bunch of XBox 360s, though not networked
together, which I found disappointing), so I'm assuming it had something to do with
them, but.... I think Microsoft product teams may want to consider saving some budget
and instead of hiring six LA Lakers Cheerleaders to sit on a couch and allow drooling
geeks to take pictures with them (no touching!), use the money to make the party--and
the hosts--stick in my mind more effectively, or at least use it to hand out technical
data on whatever it is they're building. 
</li>
          <li>
The vendor floor competition for attention is getting a little cutthroat. DevExpress
stole the show this year, importing--no joke--an actor, "Mini-Me", Vern, to essentially
echo (badly) anything Mark Miller (dressed, of course, as Austin Powers' arch-nemesis
Dr. Evil) tried to say about the most recent version of CodeRush. Granted, Mark's
new "do" (and the absurdly large head that was hiding underneath) makes it easy for
him to do a good Dr. Evil impression, but other than that, there was really nothing
parallel in the situation--despite Mark's insistence on writing code with evil Flying
Spaghetti Monsters or what not in it. I think if you're a vendor and you want to make
a splash at PDC, you think long and hard about an effective tie-in, like Infragistics'
clever "I flew 1500 miles for this T-shirt" they were giving away. 
</li>
          <li>
The language world was a bit abuzz at the barely-concealed C# 4.0 features, mostly
centering around the new "dynamic" keyword and the C# REPL loop capabilities, but
noticeably absent was any similar kind of talk or buzz around VB 10. Even C++ got
more attention than VB did, with a presentation clearly intending to call out a direct
reference to Visual C++'s heyday, "Visual C++: Why 10 is the new 6". Conversations
I had with a few Microsofties make it pretty clear that VB is now the red-headed stepchild
of the .NET language family, and that fact is going to start making itself widely
felt through the rest of the ecosystem before long, particularly now that rumors are
beginning to circulate that pretty much all the "gifted kids" that were on the VB
team have gone to find other places to exercise their intellect and innovation, such
as the Oslo team. I think Microsoft is going to find itself in an uncomfortable position
soon, of trying to kill VB off without appearing like they are trying to kill VB off,
lest they create another "VB revolution" like the one in 2001 when unmanaged VB'ers
("Classic VBers"?) looked at VB.NET and collectively puked. 
</li>
          <li>
Speaking of collective revolution, anybody remember Visual FoxPro? Those guys are
still kicking, and they were always a small fraction of the developer community, comparatively
against VB, at least. I think Microsoft is in trouble here, of their own making, for
not defining distinct and clearly differentiated roles for Visual Basic and C#. 
</li>
          <li>
The DLR is quickly moving into a position of high importance in my mind, and the fact
that it now builds on top of expression trees (from C# 3.0/LINQ) and builds its trees
in such a way that they look almost identical to what a corresponding C# or VB tree
would look like means that the DLR is about a half-step away from becoming the most
critical part of the .NET ecosystem, second only to the CLR itself. I think that while
certain Microsoft releases, like Oslo, PowerShell, C# or VB, won't adopt the DLR as
a core component to their implementation, developers looking to explore the DSL space
will find the DLR a very happy place to be, particularly in combination with F# Parser
Expression Grammars. 
</li>
          <li>
Speaking of F#, it's pretty clear that it was the developer darling--if not the media
darling--of the show. The F# Hands-on-Lab looked to be one of the more popular ones
used there, and every time I or my co-author, Amanda Laucher, talked with somebody
who didn't already know we were working on F# in a Nutshell, they were asking questions
about it and trying to understand its role in the world. I think the "cool kids" of
the development community are going to come to check out F#, find that it can do a
lot of what the O-O minded C# and VB can do, discover that the functional approach
works well in certain scenarios, and start looking to use that on their new projects. 
</li>
          <li>
I think that if the Microsoft languages family were Weasley family from Harry Potter,
C++ would be one of the two older brothers (probably Bill or Charlie, the cool older
brothers who've gone on to make their name and don't need to impress anybody any more),
Visual Basic would be Percy (desperate for validation and respect), C# would be Ron
(cleary an up-and-comer in the world, even if he was a little awkward while growing
up), and F# would be Ginny (the spunky one who clearly charts her own path despite
her initial shyness, her accidental involvement in a Voldemortian scheme and her parents'
and big brothers' interference in her life). Oslo, of course, is Professor Snape--we
can't be sure if he's a good guy or a bad guy until the last book. 
</li>
          <li>
Continuing that analogy, by the way, I think Java is clearly Hermione: wickedly book
smart, but sometimes too clever by half.</li>
        </ul>
        <p>
Overall, PDC was an amazing show, and there's clearly a lot of stuff to track. I personally
plan to take a deep dive into Oslo, and will probably blog about what I find, but
in the meantime, remember that all of the PDC bits that we got on the hard drives
are available through the various DevCenters (or so I've been told), so have a look.
There's a lot more there than just what I mentioned above.
</p>
        <p>
          <strong>Update:</strong> Lisa Feigenbaum emailed me with a correction: there <em>was</em> a
session on VB 10 at PDC, and I simply missed it in the schedule. In fact, she was
very subtle about it, simply asking me, "Did you make it to the VB talk?" and posted <a href="http://blogs.msdn.com/vbteam/archive/2008/11/02/tl12-future-directions-for-microsoft-visual-basic-lisa-feigenbaum.aspx">this
URL</a> along with it. Lisa, I stand corrected. :-) Having said that, though, I still
stand by the other points of that piece: that the buzz I was hearing (which may very
well have simply been the social circles I run in, I'll be the first to admit it,
but I can only speak to my experience here and am very willing to be told I'm full
of poopie on this one) was all C#, no VB, and that it bothers me that notable members
of the VB team have departed for other parts of the company. Please, <em>nothing</em> would
make me happier than to see VB stand as a full and equal partner in the .NET family
of languages, but right now, it really still feels like the red-headed stepchild.
Please, prove me wrong.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8e0ae181-cdae-412c-95c7-ea7ab2da39b9" />
        <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>Thoughts of a PDC (2008) Gone By...</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,8e0ae181-cdae-412c-95c7-ea7ab2da39b9.aspx</guid>
      <link>http://blogs.tedneward.com/2008/11/01/Thoughts+Of+A+PDC+2008+Gone+By.aspx</link>
      <pubDate>Sat, 01 Nov 2008 01:01:06 GMT</pubDate>
      <description>&lt;p&gt;
PDC 2008 in LA is over now, and like most PDCs, it definitely didn't disappoint on
the technical front--Microsoft tossed out a whole slew of new technologies, ideas,
releases, and prototypes, all with the eye towards getting bits (in this case, a Western
Digital 160 GB USB hard drive) out to the developer community and getting back feedback,
either through the usual channels or, more recently, the blogosphere.
&lt;/p&gt;
&lt;p&gt;
These are the things I think I think about this past PDC:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Windows 7 will be an interesting thing to watch--they handed out DVDs in both 32-
and 64-bit versions, and it's somewhat reminiscent of the Longhorn DVDs of the last
PDC. If you recall, Longhorn (what eventually became known as Vista) looked surprisingly
good--if a bit unstable, something common to any release this early--for a while,
then Vista itself pretty much fell flat. I think it will be interesting, as a social
experiment, to look at what people say about Windows 7 now, compare it to what was
said about Vista back in 2004 (which is I think when the last PDC was), and then compare
what people say 1, 2 and 3 years after the PDC release. 
&lt;li&gt;
Azure dominated a lot of the focus, commensurate with the growing interest/hype around
"the cloud". All of this sounds suspiciously familiar to me, thinking back to the
early days of SOAP/WSDL, and the intense pressure for Web services to revolutionize
IT as we know it. This didn't happen, largely for technical reasons at first (incompatibilities
between toolkits most of all), then because people treated it as CORBA++ or DCOM-with-angle-brackets.
Azure and "cloud computing" have a different problem: clear definition of purpose.
I think too many people have no idea what "the cloud" really is for this to be something
to pay much attention to just yet. 
&lt;li&gt;
Conference get-togethers and parties are becoming more and more lavish each year,
as the various product teams challenge one another for the coveted title of The "Dude,
were you &lt;em&gt;there&lt;/em&gt; last night? It was amazing!" Party of PDC. For my money, that
party was the party at the J Lounge on Wednesday night, complete with three floors
of fun, including a wall-projected image of Rock Band, but--here's the rub--I couldn't
tell you which team actually hosted the party. There was a Microsoft Dynamics CRM
poster up in the middle of the gaming floor (bunch of XBox 360s, though not networked
together, which I found disappointing), so I'm assuming it had something to do with
them, but.... I think Microsoft product teams may want to consider saving some budget
and instead of hiring six LA Lakers Cheerleaders to sit on a couch and allow drooling
geeks to take pictures with them (no touching!), use the money to make the party--and
the hosts--stick in my mind more effectively, or at least use it to hand out technical
data on whatever it is they're building. 
&lt;li&gt;
The vendor floor competition for attention is getting a little cutthroat. DevExpress
stole the show this year, importing--no joke--an actor, "Mini-Me", Vern, to essentially
echo (badly) anything Mark Miller (dressed, of course, as Austin Powers' arch-nemesis
Dr. Evil) tried to say about the most recent version of CodeRush. Granted, Mark's
new "do" (and the absurdly large head that was hiding underneath) makes it easy for
him to do a good Dr. Evil impression, but other than that, there was really nothing
parallel in the situation--despite Mark's insistence on writing code with evil Flying
Spaghetti Monsters or what not in it. I think if you're a vendor and you want to make
a splash at PDC, you think long and hard about an effective tie-in, like Infragistics'
clever "I flew 1500 miles for this T-shirt" they were giving away. 
&lt;li&gt;
The language world was a bit abuzz at the barely-concealed C# 4.0 features, mostly
centering around the new "dynamic" keyword and the C# REPL loop capabilities, but
noticeably absent was any similar kind of talk or buzz around VB 10. Even C++ got
more attention than VB did, with a presentation clearly intending to call out a direct
reference to Visual C++'s heyday, "Visual C++: Why 10 is the new 6". Conversations
I had with a few Microsofties make it pretty clear that VB is now the red-headed stepchild
of the .NET language family, and that fact is going to start making itself widely
felt through the rest of the ecosystem before long, particularly now that rumors are
beginning to circulate that pretty much all the "gifted kids" that were on the VB
team have gone to find other places to exercise their intellect and innovation, such
as the Oslo team. I think Microsoft is going to find itself in an uncomfortable position
soon, of trying to kill VB off without appearing like they are trying to kill VB off,
lest they create another "VB revolution" like the one in 2001 when unmanaged VB'ers
("Classic VBers"?) looked at VB.NET and collectively puked. 
&lt;li&gt;
Speaking of collective revolution, anybody remember Visual FoxPro? Those guys are
still kicking, and they were always a small fraction of the developer community, comparatively
against VB, at least. I think Microsoft is in trouble here, of their own making, for
not defining distinct and clearly differentiated roles for Visual Basic and C#. 
&lt;li&gt;
The DLR is quickly moving into a position of high importance in my mind, and the fact
that it now builds on top of expression trees (from C# 3.0/LINQ) and builds its trees
in such a way that they look almost identical to what a corresponding C# or VB tree
would look like means that the DLR is about a half-step away from becoming the most
critical part of the .NET ecosystem, second only to the CLR itself. I think that while
certain Microsoft releases, like Oslo, PowerShell, C# or VB, won't adopt the DLR as
a core component to their implementation, developers looking to explore the DSL space
will find the DLR a very happy place to be, particularly in combination with F# Parser
Expression Grammars. 
&lt;li&gt;
Speaking of F#, it's pretty clear that it was the developer darling--if not the media
darling--of the show. The F# Hands-on-Lab looked to be one of the more popular ones
used there, and every time I or my co-author, Amanda Laucher, talked with somebody
who didn't already know we were working on F# in a Nutshell, they were asking questions
about it and trying to understand its role in the world. I think the "cool kids" of
the development community are going to come to check out F#, find that it can do a
lot of what the O-O minded C# and VB can do, discover that the functional approach
works well in certain scenarios, and start looking to use that on their new projects. 
&lt;li&gt;
I think that if the Microsoft languages family were Weasley family from Harry Potter,
C++ would be one of the two older brothers (probably Bill or Charlie, the cool older
brothers who've gone on to make their name and don't need to impress anybody any more),
Visual Basic would be Percy (desperate for validation and respect), C# would be Ron
(cleary an up-and-comer in the world, even if he was a little awkward while growing
up), and F# would be Ginny (the spunky one who clearly charts her own path despite
her initial shyness, her accidental involvement in a Voldemortian scheme and her parents'
and big brothers' interference in her life). Oslo, of course, is Professor Snape--we
can't be sure if he's a good guy or a bad guy until the last book. 
&lt;li&gt;
Continuing that analogy, by the way, I think Java is clearly Hermione: wickedly book
smart, but sometimes too clever by half.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Overall, PDC was an amazing show, and there's clearly a lot of stuff to track. I personally
plan to take a deep dive into Oslo, and will probably blog about what I find, but
in the meantime, remember that all of the PDC bits that we got on the hard drives
are available through the various DevCenters (or so I've been told), so have a look.
There's a lot more there than just what I mentioned above.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Lisa Feigenbaum emailed me with a correction: there &lt;em&gt;was&lt;/em&gt; a
session on VB 10 at PDC, and I simply missed it in the schedule. In fact, she was
very subtle about it, simply asking me, "Did you make it to the VB talk?" and posted &lt;a href="http://blogs.msdn.com/vbteam/archive/2008/11/02/tl12-future-directions-for-microsoft-visual-basic-lisa-feigenbaum.aspx"&gt;this
URL&lt;/a&gt; along with it. Lisa, I stand corrected. :-) Having said that, though, I still
stand by the other points of that piece: that the buzz I was hearing (which may very
well have simply been the social circles I run in, I'll be the first to admit it,
but I can only speak to my experience here and am very willing to be told I'm full
of poopie on this one) was all C#, no VB, and that it bothers me that notable members
of the VB team have departed for other parts of the company. Please, &lt;em&gt;nothing&lt;/em&gt; would
make me happier than to see VB stand as a full and equal partner in the .NET family
of languages, but right now, it really still feels like the red-headed stepchild.
Please, prove me wrong.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=8e0ae181-cdae-412c-95c7-ea7ab2da39b9" /&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,8e0ae181-cdae-412c-95c7-ea7ab2da39b9.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=277a29cb-c011-45a3-82f9-6e702d5ad5df</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,277a29cb-c011-45a3-82f9-6e702d5ad5df.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,277a29cb-c011-45a3-82f9-6e702d5ad5df.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=277a29cb-c011-45a3-82f9-6e702d5ad5df</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The full list is <a href="http://www.noop.nl/2008/09/top-100-blogs-for-development-managers-q3-2008.html">here</a>.
It's a pretty prestigious group--and I'm totally floored that I'm there next to some
pretty big names.
</p>
        <p>
In homage to Ms. Sally Fields, of so many years ago... "You like me, you really like
me". Having somebody come up to me at a conference and tell me how much they like
my blog is second on my list of "fun things to happen to me at a conference", right
behind having somebody come up to me at a conference and tell me how much they like
my blog, except for that one entry, where I said something <em>totally</em> ridiculous
(and here's why) ....
</p>
        <p>
What I find most fascinating about the list was the means by which it was constructed--the
various calculations behind page rank, technorati rating, and so on. Very cool stuff.
</p>
        <p>
Perhaps it's trite to say it, but it's still true: readers are what make writing blogs
worthwhile. Thanks to all of you.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=277a29cb-c011-45a3-82f9-6e702d5ad5df" />
        <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>Apparently I'm #25 on the Top 100 Blogs for Development Managers</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,277a29cb-c011-45a3-82f9-6e702d5ad5df.aspx</guid>
      <link>http://blogs.tedneward.com/2008/09/15/Apparently+Im+25+On+The+Top+100+Blogs+For+Development+Managers.aspx</link>
      <pubDate>Mon, 15 Sep 2008 11:29:19 GMT</pubDate>
      <description>&lt;p&gt;
The full list is &lt;a href="http://www.noop.nl/2008/09/top-100-blogs-for-development-managers-q3-2008.html"&gt;here&lt;/a&gt;.
It's a pretty prestigious group--and I'm totally floored that I'm there next to some
pretty big names.
&lt;/p&gt;
&lt;p&gt;
In homage to Ms. Sally Fields, of so many years ago... "You like me, you really like
me". Having somebody come up to me at a conference and tell me how much they like
my blog is second on my list of "fun things to happen to me at a conference", right
behind having somebody come up to me at a conference and tell me how much they like
my blog, except for that one entry, where I said something &lt;em&gt;totally&lt;/em&gt; ridiculous
(and here's why) ....
&lt;/p&gt;
&lt;p&gt;
What I find most fascinating about the list was the means by which it was constructed--the
various calculations behind page rank, technorati rating, and so on. Very cool stuff.
&lt;/p&gt;
&lt;p&gt;
Perhaps it's trite to say it, but it's still true: readers are what make writing blogs
worthwhile. Thanks to all of you.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=277a29cb-c011-45a3-82f9-6e702d5ad5df" /&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,277a29cb-c011-45a3-82f9-6e702d5ad5df.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Security</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=033a0895-7246-4015-8516-fa26291adc45</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,033a0895-7246-4015-8516-fa26291adc45.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,033a0895-7246-4015-8516-fa26291adc45.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=033a0895-7246-4015-8516-fa26291adc45</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://callvirt.net/blog/entry.aspx?entryid=b9a94d0c-761a-4d6b-bc2f-d6a5f8c1a4a7">As
Joel points out</a>, we've made a draft of the <em>SSCLI 2.0 Internals</em> book available
for download (via his blog). Rather than tell you all about the book, which Joel summarizes
quite well, instead I thought I'd tell you about the process by which the book came
to be.
</p>
        <blockquote>
          <p>
            <em>Editor's note: if you have no interest in the process by which a book can get
done, skip the rest of this blog entry.</em>
          </p>
        </blockquote>
        <p>
One thing that readers will note that's different about this version of "the Rotor
book" is that it's <em>not</em> being done through one of the traditional publishers.
This is deliberate. As Joel and I talk about on the <a href="http://www.dotnetrocks.com/default.aspx?showNum=360">.NET
Rocks! show we did together</a>, the first Rotor book was on the first version of
Rotor, which shipped shortly after the .NET 1.1 bits shipped to customers. That was
back in the summer of 2001. Dave, Geoff and I shipped the book, I did a few conference
talks on Rotor for the relatively few people who had an interest in what was going
on "under the hood" of the CLR, and then we all sort of parted ways. (Dave retired
from Microsoft entirely shortly thereafter, in order "to focus on the two things that
matter in life: making music and making wine", as he put it.) Mission accomplished,
we moved on.
</p>
        <p>
Meanwhile, as we all knew would happen, the world moved on--Whidbey (.NET 2.0) shipped,
and with it came a whole slew of CLR enhancements, most notably generics. Unlike how
generics happened in the JVM, CLR generics are carried through all the way to the
type system, and as a result, a lot of what we said in the first Rotor book was instantly
rendered obsolete. Granted, one could always grab the Gyro patch for Rotor and see
what generics would have looked like, but even that was pretty much rendered obsolete
by the emergence of the SSCLI 2.0 drop, bringing the Rotor code up to date with the
Whidbey production CLR release.
</p>
        <p>
Except the book was, to be blunt about it, left behind.
</p>
        <p>
Speaking honestly, the book never broke any sales records. Sure, for a while there
it was the #1 best-selling book (in Redmond, WA, to my <em>total</em> shock and surprise)
on Amazon, but we never had the kind of best-seller success that that of, say, <em>Programming
Ruby</em> or pick-your-favorite-ASP.NET book. In the book publishing world, this was
kind of the moral equivalent to watching your neighbors' slide show of their vacation:
boring for most people <em>not</em> in the pictures, unless you were <em>really</em> interested
in either the place they were visiting or what they did there. Most of our audience
were either people working on the CLR itself (hence all the copies sold in Redmond,
get it?), people who were researching on the CLR (such as the various Rotor research
projects that came over a few years after its release), or people who just had that
itch to "get wonky with it" and learn how some of the structures worked. Granted,
a lot of what those people in the last category learned turned out to be pretty helpful
in the Real World, but it was a payoff that came with a pretty non-trivial learning
curve.
</p>
        <p>
Fast-forward a few years, to the end of calendar year 2005.
</p>
        <p>
By this point, .NET 2.0 has been out in production form for a bit, and Mark Lewin,
then of Microsoft University Relations (I think that was his job, but to be honest
my recollection on that point is kinda fuzzy) approached me: Microsoft was interested
in seeing a second edition of the book out, to keep the Rotor community up to date
with what was going on in the state of the art in the CLR. Was I interested? Sure,
but the rules surrounding a multi-author book and subsequent editions are pretty clear:
everybody has to be given right of first refusal. Thus a two-fold task was under way:
find a co-author (preferably somebody from the CLR team, since my skills had never
really been in navigating the Rotor source code in the first place, and I hadn't really
spent a significant amount of time in the code since 2001), and get Geoff and Dave
to indicate--in a very proper legal fashion--that they were passing on the second
edition.
</p>
        <p>
Ugh. Lawyers. Contracts. Bleah.
</p>
        <p>
John Osborn then broke the bad news: OReilly wasn't interested in doing a second edition.
I couldn't really blame them, since the first hadn't broken any kind of sales record,
but I was a bit bummed because I thought this was the end of the road.
</p>
        <p>
Mark Lewin to the rescue. Apparently his part of Microsoft <em>really</em> wanted
this book out, to the point where they were willing to fund the effort, if I and my
co-author were still interested. Sure, that sounded like a workable idea. And once
the book was done, maybe we could publish it through MSPress, if that sounded like
a good idea to me. Sure, that sounded good. Then Mark dropped the suggestion that
maybe I could talk to Joel Pobar, former CLR geek extraordinaire, to see if he was
interested. Joel had impressed me back when we'd briefly touched bases during the
first book-writing experience, so yeah, sure, that sounded like a good idea. He was
on board pretty quickly, and so we had the first step out of the way.
</p>
        <p>
Next, we had to get OReilly to release their copyright on the first book, so we (and
possibly MSPress) could work on and publish the second edition. This turned out to
be a huge part of the time between then and now, not owing to any one party's deliberate
attempt to derail the process, but just because copies of contracts had to be sent
to the original three authors (myself, Stutz and Geoff) to sign over our rights with
OReilly to a Creative Commons License, then copies had to be sent to everybody else
so all the signatures could appear on one document, and so on.
</p>
        <p>
Did I say it already? Ugh. Lawyers. Contracts. Bleah.
</p>
        <p>
Then, we had to get a contract from Microsoft signed, and that meant more contracts
flying back and forth across the fax lines, and then later the US (and Australian)
postal system, and that was more delays as the same round of signatures had to be
exchanged.
</p>
        <p>
Just for the record: Ugh. Lawyers. Contracts. Bleah.
</p>
        <p>
Finally, though, the die was cast, the authors were ready to go, and.... Hey, does
anybody have the latest soft copy of the Word docs we used from the first edition?
A quick email to John (Osborn) took longer than we thought, as OReilly tried to find
the post-QA docs for us to work from. (I had my own copies, of course, but they were
pre-QA, and thus not really what we wanted to start from.) More rounds of emails to
try and track those down, so we can get started. Oh, and while we're at it, can we
get the figures/graphics, too? They're not in the manuscript directly, so.... Oh,
wait, does anybody know how to read .EPS files?
</p>
        <p>
Then began the actual writing process, or, to be more precise, the revision process.
We decided on a process similar to the way the first book had been written: Joel,
being the "subject matter expert", would take a first pass on the text, and sketch
in the rough outlines of what needed to be said. I would then take the prose, polish
it up (which in many cases didn't require a whole lot of work, Joel being a great
writer in his own right) and rearrange sections as necessary to make it flow more
easily, as well as flesh out certain sections that didn't require a former position
on the CLR team to write. Joel would then have a look at what I wrote, and assuming
I didn't get it completely wrong, would sign off on it, and the chapter/section/paragraph/whatever
was done.
</p>
        <p>
And now we're in the process of doing that cosmetic cleanup that's part of the overtime
period in book-writing, including generating the table of contents and index, since,
it turns out, we'd rather publish it ourselves than through MSPress (which they're
OK with). So, readers will have a choice: get the free download from Microsoft's website
(once we're done, which should be "real soon now") and read it in soft-copy, or buy
it off of Amazon in "treeware version", which will put a modest amount of money into
Joel's and my collective pocket (once the relatively modest expenses of self-publishing
are covered, that is).
</p>
        <p>
This will be my first experience with self-publishing (as it is for Joel, too), so
I'm eager to see how the whole things turns out. One thing I will warn the prospective
self-publisher, though: do <em>not</em> underestimate the time you will spend doing
those things the editorial/QA/copyedit pass normally handles for you, because it's
kind of a pain in the *ss to do it yourself. Still, it's worth it, particularly if
you're having a hard time selling your book to a publisher who, for reasons of economy
of scale, don't want to publish a niche book (like this one).
</p>
        <p>
Anyway, like many of my blog postings, this post has gone on long enough, so I'll
sign off here with a "go read the draft", even if you're a Java or other execution
engine/virtual machine kind of developer--seeing the nuts and bolts of a complex execution
engine in action is a pretty cool exercise.
</p>
        <p>
Oh, and if anybody's interested in doing a similar kind of effort around the OpenJDK
(once it ships), let me know, 'cuz I'm a glutton for punishment....
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=033a0895-7246-4015-8516-fa26291adc45" />
        <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>Rotor v2 book draft available</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,033a0895-7246-4015-8516-fa26291adc45.aspx</guid>
      <link>http://blogs.tedneward.com/2008/08/20/Rotor+V2+Book+Draft+Available.aspx</link>
      <pubDate>Wed, 20 Aug 2008 18:55:05 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://callvirt.net/blog/entry.aspx?entryid=b9a94d0c-761a-4d6b-bc2f-d6a5f8c1a4a7"&gt;As
Joel points out&lt;/a&gt;, we've made a draft of the &lt;em&gt;SSCLI 2.0 Internals&lt;/em&gt; book available
for download (via his blog). Rather than tell you all about the book, which Joel summarizes
quite well, instead I thought I'd tell you about the process by which the book came
to be.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Editor's note: if you have no interest in the process by which a book can get
done, skip the rest of this blog entry.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
One thing that readers will note that's different about this version of "the Rotor
book" is that it's &lt;em&gt;not&lt;/em&gt; being done through one of the traditional publishers.
This is deliberate. As Joel and I talk about on the &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=360"&gt;.NET
Rocks! show we did together&lt;/a&gt;, the first Rotor book was on the first version of
Rotor, which shipped shortly after the .NET 1.1 bits shipped to customers. That was
back in the summer of 2001. Dave, Geoff and I shipped the book, I did a few conference
talks on Rotor for the relatively few people who had an interest in what was going
on "under the hood" of the CLR, and then we all sort of parted ways. (Dave retired
from Microsoft entirely shortly thereafter, in order "to focus on the two things that
matter in life: making music and making wine", as he put it.) Mission accomplished,
we moved on.
&lt;/p&gt;
&lt;p&gt;
Meanwhile, as we all knew would happen, the world moved on--Whidbey (.NET 2.0) shipped,
and with it came a whole slew of CLR enhancements, most notably generics. Unlike how
generics happened in the JVM, CLR generics are carried through all the way to the
type system, and as a result, a lot of what we said in the first Rotor book was instantly
rendered obsolete. Granted, one could always grab the Gyro patch for Rotor and see
what generics would have looked like, but even that was pretty much rendered obsolete
by the emergence of the SSCLI 2.0 drop, bringing the Rotor code up to date with the
Whidbey production CLR release.
&lt;/p&gt;
&lt;p&gt;
Except the book was, to be blunt about it, left behind.
&lt;/p&gt;
&lt;p&gt;
Speaking honestly, the book never broke any sales records. Sure, for a while there
it was the #1 best-selling book (in Redmond, WA, to my &lt;em&gt;total&lt;/em&gt; shock and surprise)
on Amazon, but we never had the kind of best-seller success that that of, say, &lt;em&gt;Programming
Ruby&lt;/em&gt; or pick-your-favorite-ASP.NET book. In the book publishing world, this was
kind of the moral equivalent to watching your neighbors' slide show of their vacation:
boring for most people &lt;em&gt;not&lt;/em&gt; in the pictures, unless you were &lt;em&gt;really&lt;/em&gt; interested
in either the place they were visiting or what they did there. Most of our audience
were either people working on the CLR itself (hence all the copies sold in Redmond,
get it?), people who were researching on the CLR (such as the various Rotor research
projects that came over a few years after its release), or people who just had that
itch to "get wonky with it" and learn how some of the structures worked. Granted,
a lot of what those people in the last category learned turned out to be pretty helpful
in the Real World, but it was a payoff that came with a pretty non-trivial learning
curve.
&lt;/p&gt;
&lt;p&gt;
Fast-forward a few years, to the end of calendar year 2005.
&lt;/p&gt;
&lt;p&gt;
By this point, .NET 2.0 has been out in production form for a bit, and Mark Lewin,
then of Microsoft University Relations (I think that was his job, but to be honest
my recollection on that point is kinda fuzzy) approached me: Microsoft was interested
in seeing a second edition of the book out, to keep the Rotor community up to date
with what was going on in the state of the art in the CLR. Was I interested? Sure,
but the rules surrounding a multi-author book and subsequent editions are pretty clear:
everybody has to be given right of first refusal. Thus a two-fold task was under way:
find a co-author (preferably somebody from the CLR team, since my skills had never
really been in navigating the Rotor source code in the first place, and I hadn't really
spent a significant amount of time in the code since 2001), and get Geoff and Dave
to indicate--in a very proper legal fashion--that they were passing on the second
edition.
&lt;/p&gt;
&lt;p&gt;
Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
John Osborn then broke the bad news: OReilly wasn't interested in doing a second edition.
I couldn't really blame them, since the first hadn't broken any kind of sales record,
but I was a bit bummed because I thought this was the end of the road.
&lt;/p&gt;
&lt;p&gt;
Mark Lewin to the rescue. Apparently his part of Microsoft &lt;em&gt;really&lt;/em&gt; wanted
this book out, to the point where they were willing to fund the effort, if I and my
co-author were still interested. Sure, that sounded like a workable idea. And once
the book was done, maybe we could publish it through MSPress, if that sounded like
a good idea to me. Sure, that sounded good. Then Mark dropped the suggestion that
maybe I could talk to Joel Pobar, former CLR geek extraordinaire, to see if he was
interested. Joel had impressed me back when we'd briefly touched bases during the
first book-writing experience, so yeah, sure, that sounded like a good idea. He was
on board pretty quickly, and so we had the first step out of the way.
&lt;/p&gt;
&lt;p&gt;
Next, we had to get OReilly to release their copyright on the first book, so we (and
possibly MSPress) could work on and publish the second edition. This turned out to
be a huge part of the time between then and now, not owing to any one party's deliberate
attempt to derail the process, but just because copies of contracts had to be sent
to the original three authors (myself, Stutz and Geoff) to sign over our rights with
OReilly to a Creative Commons License, then copies had to be sent to everybody else
so all the signatures could appear on one document, and so on.
&lt;/p&gt;
&lt;p&gt;
Did I say it already? Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
Then, we had to get a contract from Microsoft signed, and that meant more contracts
flying back and forth across the fax lines, and then later the US (and Australian)
postal system, and that was more delays as the same round of signatures had to be
exchanged.
&lt;/p&gt;
&lt;p&gt;
Just for the record: Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
Finally, though, the die was cast, the authors were ready to go, and.... Hey, does
anybody have the latest soft copy of the Word docs we used from the first edition?
A quick email to John (Osborn) took longer than we thought, as OReilly tried to find
the post-QA docs for us to work from. (I had my own copies, of course, but they were
pre-QA, and thus not really what we wanted to start from.) More rounds of emails to
try and track those down, so we can get started. Oh, and while we're at it, can we
get the figures/graphics, too? They're not in the manuscript directly, so.... Oh,
wait, does anybody know how to read .EPS files?
&lt;/p&gt;
&lt;p&gt;
Then began the actual writing process, or, to be more precise, the revision process.
We decided on a process similar to the way the first book had been written: Joel,
being the "subject matter expert", would take a first pass on the text, and sketch
in the rough outlines of what needed to be said. I would then take the prose, polish
it up (which in many cases didn't require a whole lot of work, Joel being a great
writer in his own right) and rearrange sections as necessary to make it flow more
easily, as well as flesh out certain sections that didn't require a former position
on the CLR team to write. Joel would then have a look at what I wrote, and assuming
I didn't get it completely wrong, would sign off on it, and the chapter/section/paragraph/whatever
was done.
&lt;/p&gt;
&lt;p&gt;
And now we're in the process of doing that cosmetic cleanup that's part of the overtime
period in book-writing, including generating the table of contents and index, since,
it turns out, we'd rather publish it ourselves than through MSPress (which they're
OK with). So, readers will have a choice: get the free download from Microsoft's website
(once we're done, which should be "real soon now") and read it in soft-copy, or buy
it off of Amazon in "treeware version", which will put a modest amount of money into
Joel's and my collective pocket (once the relatively modest expenses of self-publishing
are covered, that is).
&lt;/p&gt;
&lt;p&gt;
This will be my first experience with self-publishing (as it is for Joel, too), so
I'm eager to see how the whole things turns out. One thing I will warn the prospective
self-publisher, though: do &lt;em&gt;not&lt;/em&gt; underestimate the time you will spend doing
those things the editorial/QA/copyedit pass normally handles for you, because it's
kind of a pain in the *ss to do it yourself. Still, it's worth it, particularly if
you're having a hard time selling your book to a publisher who, for reasons of economy
of scale, don't want to publish a niche book (like this one).
&lt;/p&gt;
&lt;p&gt;
Anyway, like many of my blog postings, this post has gone on long enough, so I'll
sign off here with a "go read the draft", even if you're a Java or other execution
engine/virtual machine kind of developer--seeing the nuts and bolts of a complex execution
engine in action is a pretty cool exercise.
&lt;/p&gt;
&lt;p&gt;
Oh, and if anybody's interested in doing a similar kind of effort around the OpenJDK
(once it ships), let me know, 'cuz I'm a glutton for punishment....
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=033a0895-7246-4015-8516-fa26291adc45" /&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,033a0895-7246-4015-8516-fa26291adc45.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=363d5058-a4ab-48ef-9b5b-8b8df2069ef8</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,363d5058-a4ab-48ef-9b5b-8b8df2069ef8.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,363d5058-a4ab-48ef-9b5b-8b8df2069ef8.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=363d5058-a4ab-48ef-9b5b-8b8df2069ef8</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
For those of you who were at the Cinncinnati NFJS show, please continue on to the
next blog entry in your reader--you've already heard this. For those of you who weren't,
then allow me to make the announcement:
</p>
        <p>
Hi. My name's Ted Neward, and I am now a <a href="http://www.thoughtworks.com">ThoughtWorker</a>.
</p>
        <p>
After four months of discussions, interviews, more discussions and more interviews,
I can finally say that ThoughtWorks and I have come to a meeting of the minds, and
starting 3 September I will be a Principal Consultant at ThoughtWorks. My role there
will be to consult, write, mentor, architect and speak on Java, .NET, XML Services
(and maybe even a little Ruby), not to mention help ThoughtWorks' clients achieve
IT success in other general ways.
</p>
        <p>
Yep, I'm basically doing the same thing I've been doing for the last five years. Except
now I'm doing it with a TW logo attached to my name.
</p>
        <blockquote>
          <p>
            <em>By the way, ThoughtWorkers get to choose their own titles, and I'm curious to
know what readers think my title should be. Send me your suggestions, and if one really
strikes home, I'll use it and update this entry to reflect the choice. I have a few
ideas, but I'm finding that other people can be vastly more creative than I, and I'd
love to have a title that rivals Neal's "Meme Wrangler" in coolness. </em>
          </p>
          <p>
            <em>Oh, and for those of you who were thinking this, "Seat Warmer" has already been
taken, from what I understand.</em>
          </p>
        </blockquote>
        <p>
Honestly, this is a connection that's been hovering at the forefront of my mind for
several years. I like ThoughtWorks' focus on success, their willingness to explore
new ideas (both methodologies and technologies), their commitment to the community,
their corporate values, and their overall attitude of "work hard, play hard". There
have definitely been people who came away from ThoughtWorks with a negative impression
of the company, but they're the minority. Any company that encourages T-shirts and
jeans, XBoxes in the office, and wants to promote good corporate values is a winner
in my book. In short, ThoughtWorks is, in many ways, the consulting company that I
would want to build, if I were going to build a consulting firm. I'm not a wild fan
of the travel commitments, mind you, but I am definitely no stranger to travel, we've
got some ideas about how I can stay at home a bit more, and frankly I've been champing
at the bit to get injected into more agile and team projects, so it feels like a good
tradeoff. Plus, I get to think about languages and platforms in a more competitive
and hostile way--not that TW is a competitive and hostile place, mind you, but in
that my new fellow ThoughtWorkers will not let stupid thoughts stand for long, and
will quickly find the holes in my arguments even faster, thus making the arguments
as a whole that much stronger... or shooting them down because they really are stupid.
(Either outcome works pretty well for me.)
</p>
        <p>
What does this mean to the rest of you? Not much change, really--I'm still logging
lots of hours at conferences, I'm still writing (and blogging, when the muse strikes),
and I'm still available for consulting/mentoring/speaking; the big difference is that
now I come with a thousand-strong developers of proven capability at my back, not
to mention two of the more profound and articulate speakers in the industry (in <a href="http://memeagora.blogspot.com/">Neal</a> and <a href="http://www.martinfowler.com/bliki/">Martin</a>)
as peers. So if you've got some .NET, Java, or Ruby projects you're thinking about,
and you want a team to come in and make it happen, you know how to reach me.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=363d5058-a4ab-48ef-9b5b-8b8df2069ef8" />
        <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>An Announcement</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,363d5058-a4ab-48ef-9b5b-8b8df2069ef8.aspx</guid>
      <link>http://blogs.tedneward.com/2008/08/19/An+Announcement.aspx</link>
      <pubDate>Tue, 19 Aug 2008 18:24:39 GMT</pubDate>
      <description>&lt;p&gt;
For those of you who were at the Cinncinnati NFJS show, please continue on to the
next blog entry in your reader--you've already heard this. For those of you who weren't,
then allow me to make the announcement:
&lt;/p&gt;
&lt;p&gt;
Hi. My name's Ted Neward, and I am now a &lt;a href="http://www.thoughtworks.com"&gt;ThoughtWorker&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
After four months of discussions, interviews, more discussions and more interviews,
I can finally say that ThoughtWorks and I have come to a meeting of the minds, and
starting 3 September I will be a Principal Consultant at ThoughtWorks. My role there
will be to consult, write, mentor, architect and speak on Java, .NET, XML Services
(and maybe even a little Ruby), not to mention help ThoughtWorks' clients achieve
IT success in other general ways.
&lt;/p&gt;
&lt;p&gt;
Yep, I'm basically doing the same thing I've been doing for the last five years. Except
now I'm doing it with a TW logo attached to my name.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;By the way, ThoughtWorkers get to choose their own titles, and I'm curious to
know what readers think my title should be. Send me your suggestions, and if one really
strikes home, I'll use it and update this entry to reflect the choice. I have a few
ideas, but I'm finding that other people can be vastly more creative than I, and I'd
love to have a title that rivals Neal's "Meme Wrangler" in coolness. &lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Oh, and for those of you who were thinking this, "Seat Warmer" has already been
taken, from what I understand.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Honestly, this is a connection that's been hovering at the forefront of my mind for
several years. I like ThoughtWorks' focus on success, their willingness to explore
new ideas (both methodologies and technologies), their commitment to the community,
their corporate values, and their overall attitude of "work hard, play hard". There
have definitely been people who came away from ThoughtWorks with a negative impression
of the company, but they're the minority. Any company that encourages T-shirts and
jeans, XBoxes in the office, and wants to promote good corporate values is a winner
in my book. In short, ThoughtWorks is, in many ways, the consulting company that I
would want to build, if I were going to build a consulting firm. I'm not a wild fan
of the travel commitments, mind you, but I am definitely no stranger to travel, we've
got some ideas about how I can stay at home a bit more, and frankly I've been champing
at the bit to get injected into more agile and team projects, so it feels like a good
tradeoff. Plus, I get to think about languages and platforms in a more competitive
and hostile way--not that TW is a competitive and hostile place, mind you, but in
that my new fellow ThoughtWorkers will not let stupid thoughts stand for long, and
will quickly find the holes in my arguments even faster, thus making the arguments
as a whole that much stronger... or shooting them down because they really are stupid.
(Either outcome works pretty well for me.)
&lt;/p&gt;
&lt;p&gt;
What does this mean to the rest of you? Not much change, really--I'm still logging
lots of hours at conferences, I'm still writing (and blogging, when the muse strikes),
and I'm still available for consulting/mentoring/speaking; the big difference is that
now I come with a thousand-strong developers of proven capability at my back, not
to mention two of the more profound and articulate speakers in the industry (in &lt;a href="http://memeagora.blogspot.com/"&gt;Neal&lt;/a&gt; and &lt;a href="http://www.martinfowler.com/bliki/"&gt;Martin&lt;/a&gt;)
as peers. So if you've got some .NET, Java, or Ruby projects you're thinking about,
and you want a team to come in and make it happen, you know how to reach me.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=363d5058-a4ab-48ef-9b5b-8b8df2069ef8" /&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,363d5058-a4ab-48ef-9b5b-8b8df2069ef8.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Security</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=b63b60d2-4c68-4bc4-8d7a-d4c82cde958d</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,b63b60d2-4c68-4bc4-8d7a-d4c82cde958d.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,b63b60d2-4c68-4bc4-8d7a-d4c82cde958d.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=b63b60d2-4c68-4bc4-8d7a-d4c82cde958d</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Another DZone newsletter crosses my Inbox, and again I feel compelled to comment.
Not so much in the uber-aggressive style of my previous attempt, since I find myself
more on the fence on this one, but because I think it's a worthwhile debate and worth
calling out.
</p>
        <p>
The article in question is "5 Reasons Why You Don't Want A Jack-of-all-Trades Developer",
by Rebecca Murphey. In it, she talks about the all-too-common want-ad description
that appears on job sites and mailing lists:
</p>
        <blockquote>
          <p>
I've spent the last couple of weeks trolling Craigslist and have been shocked at the
number of ads I've found that seem to be looking for an entire engineering team rolled
up into a single person. Descriptions like this aren't at all uncommon: 
</p>
          <blockquote>
            <p>
Candidates must have 5 years experience defining and developing data driven web sites
and have solid experience with ASP.NET, HTML, XML, JavaScript, CSS, Flash, SQL, and
optimizing graphics for web use. The candidate must also have project management skills
and be able to balance multiple, dynamic, and sometimes conflicting priorities. This
position is an integral part of executing our web strategy and must have excellent
interpersonal and communication skills.
</p>
          </blockquote>
        </blockquote>
        <p>
Her disdain for this practice is the focus of the rest of the article:
</p>
        <blockquote>
          <p>
Now I don't know about you, but if I were building a house, I wouldn't want an architect
doing the work of a carpenter, or the foundation guy doing the work of an electrician.
But ads like the one above are suggesting that a single person can actually do all
of these things, and the simple fact is that these are fundamentally different skills.
The foundation guy may build a solid base, but put him in charge of wiring the house
and the whole thing could, well, burn down. When it comes to staffing a web project
or product, the principle isn't all that different -- nor is the consequence.
</p>
        </blockquote>
        <p>
I'll admit, when I got to this point in the article, I was fully ready to start the
argument right here and now--developers <em>have</em> to have a well-rounded collection
of skills, since anecdotal evidence suggests that trying to go the route of programming
specialization (along the lines of medical specialization) isn't going to work out,
particularly given the shortage of programmers in the industry right now to begin
with. But she goes on to make an interesting point:
</p>
        <blockquote>
          <p>
The thing is, the more you know, the more you find out you don't know. A year ago
I'd have told you I could write PHP/MySQL applications, and do the front-end too;
now that I've seen what it means to be truly skilled at the back-end side of things,
I realize the most accurate thing I can say is that I understand PHP applications
and how they relate to my front-end development efforts. To say that I can write them
myself is to diminish the good work that truly skilled PHP/MySQL developers are doing,
just as I get a little bent when a back-end developer thinks they can do my job.
</p>
        </blockquote>
        <p>
She really caught me eye (and interest) with that first statement, because it echoes
something Bjarne Stroustrup told me almost 15 years ago, in an email reply sent back
to me (in response to my rather audacious cold-contact email inquiry about the costs
and benefits of writing a book): "The more you know, the more you know you don't know".
What I think also caught my eye--and, I admit it, earned respect--was her admission
that she maybe isn't as good at something as she thought she was before. This kind
of reflective admission is a good thing (and missing far too much from our industry,
IMHO), because it leads not only to better job placements for us as well as the companies
that want to hire us, but also because the more honest we can be about our own skills,
the more we can focus efforts on learning what needs to be learned in order to grow.
</p>
        <p>
She then turns to her list of 5 reasons, phrased more as a list of suggestions to
companies seeking to hire programming talent; my comments are in italics:
</p>
        <blockquote>
          <p>
So to all of those companies who are writing ads seeking one magical person to fill
all of their needs, I offer a few caveats before you post your next Craigslist ad: 
</p>
          <p>
1. If you're seeking a single person with all of these skills, make sure you have
the technical expertise to determine whether a person's skills match their resume.
Outsource a tech interview if you need to. Any developer can tell horror stories about
inept predecessors, but when a front-end developer like myself can read PHP and think
it's appalling, that tells me someone didn't do a very good job of vetting and got
stuck with a programmer who couldn't deliver on his stated skills. 
</p>
          <p>
            <em>(T: I cannot stress this enough--the technical interview process practiced at
most companies is a complete sham and travesty, and usually only succeeds in making
sure the company doesn't hire a serial killer, would-be terrorist, or financially
destitute freeway-underpass resident. I seriously think most companies should outsource
the technical interview process entirely.)</em>
          </p>
          <p>
2. A single source for all of these skills is a single point of failure on multiple
fronts. Think long and hard about what it will mean to your project if the person
you hire falls short in some aspect(s), and about the mistakes that will have to be
cleaned up when you get around to hiring specialized people. I have spent countless
days cleaning up after back-end developers who didn't understand the nuances and power
of CSS, or the difference between a div, a paragraph, a list item, and a span. Really. 
</p>
          <p>
            <em>(T: I'm not as much concerned about the single point of failure argument here,
to be honest. Developers will always have "edges" to what they know, and companies
will constantly push developers to that edge for various reasons, most of which seem
to be financial--"Why pay two people to do what one person can do?" is a really compelling
argument to the CFO, particularly when measured against an unquantifiable, namely
the quality of the project.)</em>
          </p>
          <p>
3. Writing efficient SQL is different from efficiently producing web-optimized graphics.
Administering a server is different from troubleshooting cross-browser issues. Trust
me. All are integral to the performance and growth of your site, and so you're right
to want them all -- just not from the same person. Expecting quality results in every
area from the same person goes back to the foundation guy doing the wiring. You're
playing with fire. 
</p>
          <p>
            <em>(T: True, but let's be honest about something here. It's not so much that the
company wants to play with fire, or that the company has a manual entitled "Running
a Dilbert Company" that says somewhere inside it, "Thou shouldst never hire more than
one person to run the IT department", but that the company is dealing with limited
budgets and headcount. If you only have room for one head under the budget, you want
the maximum for that one head. And please don't tell me how wrong that practice of
headcount really is--you're preaching to the choir on that one. The people you want
to preach to are the Jack Welches of the world, who apparently aren't listening to
us very much.)</em>
          </p>
          <p>
4. Asking for a laundry list of skills may end up deterring the candidates who will
be best able to fill your actual need. Be precise in your ad: about the position's
title and description, about the level of skill you're expecting in the various areas,
about what's nice to have and what's imperative. If you're looking to fill more than
one position, write more than one ad; if you don't know exactly what you want, try
harder to figure it out before you click the publish button. 
</p>
          <p>
            <em>(T: Asking people to think before publishing? Heresy! Truthfully, I don't think
it's a question of not knowing what they want, it's more trying to find what they
want. I've seen how some of these same job ads get generated, and it's usually because
a programmer on the team has left, and they had some degree of skill in all of those
areas. What the company wants, then, is somebody who can step into exactly what that
individual was doing before they handed in their resignation, but ads like, "Candidate
should look at Joe Smith's resume on Dice.com (http://...) and have exactly that same
skill set. Being named Joe Smith a desirable 'plus', since then we won't have to have
the sysadmins create a new login handle for you." won't attract much attention. Frankly,
what I've found most companies want is to just not lose the programmer in the first
place.)</em>
          </p>
          <p>
5. If you really do think you want one person to do the task of an entire engineering
team, prepare yourself to get someone who is OK at a bunch of things and not particularly
good at any of them. Again: the more you know, the more you find out you don't know.
I regularly team with a talented back-end developer who knows better than to try to
do my job, and I know better than to try to do his. Anyone who represents themselves
as being a master of front-to-back web development may very well have no idea just
how much they don't know, and could end up imperiling your product or project -- front
to back -- as a result. 
</p>
          <p>
            <em>(T: Or be prepared to pay a lot of money for somebody who is an expert at all
of those things, or be prepared to spend a lot of time and money growing somebody
into that role. Sometimes the exact right thing to do is have one person do it all,
but usually it's cheaper to have a small team work together.)</em>
          </p>
        </blockquote>
        <p>
(On a side note, I find it amusing that she seems to consider PHP a back-end skill,
but I don't want to sound harsh doing so--that's just a matter of perspective, I suppose.
(I can just imagine the guffaws from the mainframe guys when I talk about EJB, message-queue
and Spring systems being "back-end", too.) To me, the whole "web" thing is front-end
stuff, whether you're the one generating the HTML from your PHP or servlet/JSP or
ASP.NET server-side engine, or you're the one generating the CSS and graphics images
that are sent back to the browser by said server-side engine. If a user sees something
I did, it's probably because something bad happened and they're looking at a stack
trace on the screen.)
</p>
        <p>
The thing I find interesting is that HR hiring practices and job-writing skills haven't
gotten any better in the near-to-two-decades I've been in this industry. I can still
remember a fresh-faced wet-behind-the-ears Stroustrup-2nd-Edition-toting job candidate
named Neward looking at job placement listings and finding much the same kind of laundry
list of skills, including those with the impossible number of years of experience.
(In 1995, I saw an ad looking for somebody who had "10 years of C++ experience", and
wondering, "Gosh, I guess they're looking to hire Stroustrup or Lippmann", since those
two are the only people who could possibly have filled that requirement at the time.
This was right before reading the ad that was looking for 5 years of Java experience,
or the ad below it looking for 15 years of Delphi....)
</p>
        <p>
Given that it doesn't seem likely that HR departments are going to "get a clue" any
time soon, it leaves us with an interesting question: if you're a developer, and you're
looking at these laundry lists of requirements, how do you respond?
</p>
        <p>
Here's my own list of things for programmers/developers to consider over the next
five to ten years:
</p>
        <ol>
          <li>
            <em>These "laundry list" ads are not going away any time soon.</em> We can rant and
rail about the stupidity of HR departments and hiring managers all we want, but the
basic fact is, this is the way things are going to work for the forseeable future,
it seems. Changing this would require a "sea change" across the industry, and sea
change doesn't happen overnight, or even within the span of a few years. So, to me,
the right question to ask isn't, "How do I change the industry to make it easier for
me to find a job I can do?", but "How do I change what I do when looking for a job
to better respond to what the industry is doing?" 
</li>
          <li>
            <em>Exclusively focusing on a single area of technology is the Kiss of Death.</em> If
all you know is PHP, then your days are numbered. I mean no disrespect to the PHP
developers of the world--in fact, were it not too ambiguous to say it, I would rephrase
that as "If all you know is <em>X</em>, your days are numbered." There is no one technical
skill that will be as much in demand in ten years as it is now. Technologies age.
Industry evolves. Innovations come along that completely change the game and leave
our predictions of a few years ago in the dust. Bill Gates (he of the "640K comment")
has said, and I think he's spot on with this, "We routinely overestimate where we
will be in five years, and vastly underestimate where we will be in ten." If you put
all your eggs in the PHP basket, then when PHP gets phased out in favor of <em>(insert
new "hotness" here)</em>, you're screwed. Unless, of course, you want to wait until
you're the last man standing, which seems to have paid off well for the few COBOL
developers still alive.... but not so much for the Algol, Simula, or RPG folks.... 
</li>
          <li>
            <em>Assuming that you can stop learning is the Kiss of Death.</em> Look, if you want
to stop learning at some point and coast on what you know, be prepared to switch industries.
This one, for the forseeable future, is one that's predicated on radical innovation
and constant change. This means we have to accept that everything is in a constant
state of flux--you can either rant and rave against it, or roll with it. This doesn't
mean that you don't have to look back, though--anybody who's been in this industry
for more than 10 years has seen how we keep reinventing the wheel, particularly now
that the relationship between Ruby and Smalltalk has been put up on the big stage,
so to speak. Do yourself a favor: learn stuff that's already "done", too, because
it turns out there's a lot of lessons we can learn from those who came before us.
"Those who cannot remember the past are condemned to repeat it" (George Santanyana).
Case in point: if you're trying to get into XML services, spend some time learning
CORBA and DCOM, and compare how they do things against WSDL and SOAP. What's similar?
What's different? Do some Googling and see if you can find comparison articles between
the two, and what XML services were supposed to "fix" from the previous two. You don't
have to write a ton of CORBA or DCOM code to see those differences (though writing
at least a little CORBA/DCOM code will probably help.) 
</li>
          <li>
            <em>Find a collection of people smarter than you.</em> Chad Fowler calls this "Being
the worst player in any band you're in" (<em>My Job Went to India (and All I Got Was
This Lousy Book)</em>, Pragmatic Press<em>)</em>. The more you surround yourself with
smart people, the more of these kinds of things (tools, languages, etc) you will pick
up merely by osmosis, and find yourself more attractive to those kind of "laundry
list" job reqs. If nothing else, it speaks well to you as an employee/consultant if
you can say, "I don't know the answer to that question, but I know people who do,
and I can get them to help me". 
</li>
          <li>
            <em>Learn to be at least self-sufficient in related, complementary technologies.</em> We
see laundry list ads in "clusters". Case in point: if the company is looking for somebody
to work on their website, they're going to rattle off a list of five or so things
they want he/she to know--HTML, CSS, XML, JavaScript and sometimes Flash (or maybe
now Silverlight), in addition to whatever server-side technology they're using (ASP.NET,
servlets, PHP, whatever). This is a pretty reasonable request, depending on the depth
of each that they want you to know. Here's the thing: the company does <em>not</em> want
the guy who says he knows ASP.NET (and nothing but ASP.NET), when asked to make a
small HTML or CSS change, to turn to them and say, "I'm sorry, that's not in my job
description. I only know ASP.NET. You'll have to get your HTML guy to make that change."
You should at least be comfortable with the basic syntax of all of the above (again,
with possible exception for Flash, which is the odd man out in that job ad that started
this piece), so that you can at least make sure the site isn't going to break when
you push your changes live. In the case of the ad above, learn the things that "surround"
website development: HTML, CSS, JavaScript, Flash, Java applets, HTTP (!!), TCP/IP,
server operating systems, IIS or Apache or Tomcat or some other server engine (including
the necessary admin skills to get them installed and up and running), XML (since it's
so often used for configuration), and so on. These are all "complementary" skills
to being an ASP.NET developer (or a servlet/JSP developer). If you're a C# or Java
programmer, learn different programming languages, a la F# (.NET) or Scala (Java),
IronRuby (.NET) or JRuby (Java), and so on. If you're a Ruby developer, learn either
a JVM language or a CLR language, so you can "plug in" more easily to the large corporate
enterprise when that call comes. 
</li>
          <li>
            <em>Learn to "read" the ad at a higher level.</em> It's often possible to "read between
the lines" and get an idea of what they're looking for, even before talking to anybody
at the company about the job. For example, I read the ad that started this piece,
and the internal dialogue that went on went something like this: <blockquote>Candidates
must have 5 years experience <em>(No entry-level developers wanted, they want somebody
who can get stuff done without having their hand held through the process) </em>defining
and developing data driven <em>(they want somebody who's comfortable with SQL and
databases) </em>web sites <em>(wait for it, the "web cluster" list is coming) </em>and
have solid experience with ASP.NET <em>(OK, they're at least marginally a Microsoft
shop, that means they probably also want some Windows Server and IIS experience)</em>,
HTML, XML, JavaScript, CSS <em>(the "web cluster", knew that was coming)</em>, Flash <em>(OK,
I wonder if this is because they're building rich internet/intranet apps already,
or just flirting with the idea?)</em>, SQL <em>(knew that was coming)</em>, and optimizing
graphics for web use <em>(OK, this is another wrinkle--this smells of "we don't want
our graphics-heavy website to suck")</em>. The candidate must also have project management
skills <em>(in other words, "You're on your own, sucka!"--you're not part of a project
team) </em>and be able to balance multiple, dynamic, and sometimes conflicting priorities <em>(in
other words, "You're own your own trying to balance between the CTO's demands and
the CEO's demands, sucka!", since you're not part of a project team; this also probably
means you're not moving into an existing project, but doing more maintenance work
on an existing site)</em>. This position is an integral part of executing our web
strategy <em>(in other words, this project has public visibility and you can't let
stupid errors show up on the website and make us all look bad) </em>and must have
excellent interpersonal and communication skills <em>(what job </em>doesn't<em> need
excellent interpersonal and communication skills?)</em>.</blockquote>See what I mean?
They want an ASP.NET dev. My guess is that they're thinking a lot about Silverlight,
since Silverlight's closest competitor is Flash, and so theoretically an ASP.NET-and-Flash
dev would know how to use Silverlight well. Thus, I'm guessing that the HTML, CSS,
and JavaScript don't need to be "Adept" level, nor even "Master" level, but "Journeyman"
is probably necessary, and maybe you could get away with "Apprentice" at those levels,
if you're working as part of a team. The SQL part will probably have to be "Journeyman"
level, the XML could probably be just "Apprentice", since I'm guessing it's only necessary
for the web.config files to control the ASP.NET configuration, and the "optimizing
web graphics", push-come-to-shove, could probably be forgiven if you've had some experience
at doing some performance tuning of a website. 
</li>
          <li>
            <em>Be insightful.</em> I know, every interview book ever written says you should
"ask questions", but what they're really getting at is "Demonstrate that you've thought
about this company and this position". Demonstrating insight about the position and
the company and technology as a whole is a good way to prove that you're a neck above
the other candidates, and will help keep the job once you've got it. 
</li>
          <li>
            <em>Be honest about what you know.</em> Let's be honest--we've all met developers
who claimed they were "experts" in a particular tool or technology, and then painfully
demonstrated how far from "expert" status they really were. Be honest about yourself:
claim your skills on a simple four-point scale. "Apprentice" means "I read a book
on it" or "I've looked at it", but "there's no way I could do it on my own without
some serious help, and ideally with a Master looking over my shoulder". "Journeyman"
means "I'm competent at it, I know the tools/technology"; or, put another way, "I
can do 80% of what anybody can ask me to do, and I know how to find the other 20%
when those situations arise". "Master" means "I not only claim that I can do what
you ask me to do with it, I can optimize systems built with it, I can make it do things
others wouldn't attempt, and I can help others learn it better". Masters are routinely
paired with Apprentices as mentors or coaches, and should expect to have this as a
major part of their responsibilities. (Ideally, anybody claiming "architect" in their
title should be a Master at one or two of the core tools/technologies used in their
system; or, put another way, architects should be <em>very</em> dubious about architecting
with something they can't reasonably claim at least Journeyman status in.) "Adept",
shortly put, means you are not only fully capable of pulling off anything a Master
can do, but you routinely take the tool/technology way beyond what anybody else thinks
possible, or you know the depth of the system so well that you can fix bugs just by
thinking about them. With your eyes closed. While drinking a glass of water. Seriously,
Adept status is not something to claim lightly--not only had you better know the guys
who created the thing personally, but you should have offered up suggestions on how
to make it better and had one or more of them accepted. 
</li>
          <li>
            <em>Demonstrate that you have relevant skills beyond what they asked for.</em> Look
at the ad in question: they want an ASP.NET dev, so any familiarity with IIS, Windows
Server, SQL Server, MSMQ, COM/DCOM/COM+, WCF/Web services, SharePoint, the CLR, IronPython,
or IronRuby should be listed prominently on your resume, and brought up at least twice
during your interview. These are (again) complementary technologies, and even if the
company doesn't have a need for those things right now, it's probably because Joe
didn't know any of those, and so they couldn't use them without sending Joe to a training
class. If you bring it up during the interview, it can also show some insight on your
part: "So, any questions for us?" "Yes, are you guys using Windows Server 2008, or
2003, for your back end?" "Um, we're using 2003, why do you ask?" "Oh, well, when
I was working as an ASP.NET dev for my previous company, we moved up to 2008 because
it had the Froobinger Enhancement, which let us...., and I was just curious if you
guys had a similar need." Or something like that. Again, be entirely honest about
what you know--if you helped the server upgrade by just putting the CDs into the drive
and punching the power button, then say as much. 
</li>
          <li>
            <em>Demonstrate that you can talk to project stakeholders and users.</em> Communication
is huge. The era of the one-developer team is long since over--you have to be able
to meet with project champions, users, other developers, and so on. If you can't do
that without somebody being offended at your lack of tact and subtlety (or your lack
of personal hygiene), then don't expect to get hired too often. 
</li>
          <li>
            <em>Demonstrate that you understand the company, its business model, and what would
help it move forward.</em> Developers who actually understand business are surprisingly
and unfortunately rare. Be one of the rare ones, and you'll find companies highly
reluctant to let you go.</li>
        </ol>
        <p>
Is this an exhaustive list? Hardly. Is this list guaranteed to keep you employed forever?
Nope. But this seems to be working for a lot of the people I run into at conferences
and client consulting gigs, so I humbly submit it for your consideration.
</p>
        <p>
But in no way do I consider this conversation completely over, either--feel free to
post your own suggestions, or tell me why I'm full of crap on any (or all) of these.
:-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=b63b60d2-4c68-4bc4-8d7a-d4c82cde958d" />
        <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 Never-Ending Debate of Specialist v. Generalist</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,b63b60d2-4c68-4bc4-8d7a-d4c82cde958d.aspx</guid>
      <link>http://blogs.tedneward.com/2008/08/14/The+NeverEnding+Debate+Of+Specialist+V+Generalist.aspx</link>
      <pubDate>Thu, 14 Aug 2008 22:38:42 GMT</pubDate>
      <description>&lt;p&gt;
Another DZone newsletter crosses my Inbox, and again I feel compelled to comment.
Not so much in the uber-aggressive style of my previous attempt, since I find myself
more on the fence on this one, but because I think it's a worthwhile debate and worth
calling out.
&lt;/p&gt;
&lt;p&gt;
The article in question is "5 Reasons Why You Don't Want A Jack-of-all-Trades Developer",
by Rebecca Murphey. In it, she talks about the all-too-common want-ad description
that appears on job sites and mailing lists:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I've spent the last couple of weeks trolling Craigslist and have been shocked at the
number of ads I've found that seem to be looking for an entire engineering team rolled
up into a single person. Descriptions like this aren't at all uncommon: &lt;blockquote&gt; 
&lt;p&gt;
Candidates must have 5 years experience defining and developing data driven web sites
and have solid experience with ASP.NET, HTML, XML, JavaScript, CSS, Flash, SQL, and
optimizing graphics for web use. The candidate must also have project management skills
and be able to balance multiple, dynamic, and sometimes conflicting priorities. This
position is an integral part of executing our web strategy and must have excellent
interpersonal and communication skills.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Her disdain for this practice is the focus of the rest of the article:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Now I don't know about you, but if I were building a house, I wouldn't want an architect
doing the work of a carpenter, or the foundation guy doing the work of an electrician.
But ads like the one above are suggesting that a single person can actually do all
of these things, and the simple fact is that these are fundamentally different skills.
The foundation guy may build a solid base, but put him in charge of wiring the house
and the whole thing could, well, burn down. When it comes to staffing a web project
or product, the principle isn't all that different -- nor is the consequence.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I'll admit, when I got to this point in the article, I was fully ready to start the
argument right here and now--developers &lt;em&gt;have&lt;/em&gt; to have a well-rounded collection
of skills, since anecdotal evidence suggests that trying to go the route of programming
specialization (along the lines of medical specialization) isn't going to work out,
particularly given the shortage of programmers in the industry right now to begin
with. But she goes on to make an interesting point:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The thing is, the more you know, the more you find out you don't know. A year ago
I'd have told you I could write PHP/MySQL applications, and do the front-end too;
now that I've seen what it means to be truly skilled at the back-end side of things,
I realize the most accurate thing I can say is that I understand PHP applications
and how they relate to my front-end development efforts. To say that I can write them
myself is to diminish the good work that truly skilled PHP/MySQL developers are doing,
just as I get a little bent when a back-end developer thinks they can do my job.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
She really caught me eye (and interest) with that first statement, because it echoes
something Bjarne Stroustrup told me almost 15 years ago, in an email reply sent back
to me (in response to my rather audacious cold-contact email inquiry about the costs
and benefits of writing a book): "The more you know, the more you know you don't know".
What I think also caught my eye--and, I admit it, earned respect--was her admission
that she maybe isn't as good at something as she thought she was before. This kind
of reflective admission is a good thing (and missing far too much from our industry,
IMHO), because it leads not only to better job placements for us as well as the companies
that want to hire us, but also because the more honest we can be about our own skills,
the more we can focus efforts on learning what needs to be learned in order to grow.
&lt;/p&gt;
&lt;p&gt;
She then turns to her list of 5 reasons, phrased more as a list of suggestions to
companies seeking to hire programming talent; my comments are in italics:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
So to all of those companies who are writing ads seeking one magical person to fill
all of their needs, I offer a few caveats before you post your next Craigslist ad: 
&lt;p&gt;
1. If you're seeking a single person with all of these skills, make sure you have
the technical expertise to determine whether a person's skills match their resume.
Outsource a tech interview if you need to. Any developer can tell horror stories about
inept predecessors, but when a front-end developer like myself can read PHP and think
it's appalling, that tells me someone didn't do a very good job of vetting and got
stuck with a programmer who couldn't deliver on his stated skills. 
&lt;p&gt;
&lt;em&gt;(T: I cannot stress this enough--the technical interview process practiced at
most companies is a complete sham and travesty, and usually only succeeds in making
sure the company doesn't hire a serial killer, would-be terrorist, or financially
destitute freeway-underpass resident. I seriously think most companies should outsource
the technical interview process entirely.)&lt;/em&gt; 
&lt;p&gt;
2. A single source for all of these skills is a single point of failure on multiple
fronts. Think long and hard about what it will mean to your project if the person
you hire falls short in some aspect(s), and about the mistakes that will have to be
cleaned up when you get around to hiring specialized people. I have spent countless
days cleaning up after back-end developers who didn't understand the nuances and power
of CSS, or the difference between a div, a paragraph, a list item, and a span. Really. 
&lt;p&gt;
&lt;em&gt;(T: I'm not as much concerned about the single point of failure argument here,
to be honest. Developers will always have "edges" to what they know, and companies
will constantly push developers to that edge for various reasons, most of which seem
to be financial--"Why pay two people to do what one person can do?" is a really compelling
argument to the CFO, particularly when measured against an unquantifiable, namely
the quality of the project.)&lt;/em&gt; 
&lt;p&gt;
3. Writing efficient SQL is different from efficiently producing web-optimized graphics.
Administering a server is different from troubleshooting cross-browser issues. Trust
me. All are integral to the performance and growth of your site, and so you're right
to want them all -- just not from the same person. Expecting quality results in every
area from the same person goes back to the foundation guy doing the wiring. You're
playing with fire. 
&lt;p&gt;
&lt;em&gt;(T: True, but let's be honest about something here. It's not so much that the
company wants to play with fire, or that the company has a manual entitled "Running
a Dilbert Company" that says somewhere inside it, "Thou shouldst never hire more than
one person to run the IT department", but that the company is dealing with limited
budgets and headcount. If you only have room for one head under the budget, you want
the maximum for that one head. And please don't tell me how wrong that practice of
headcount really is--you're preaching to the choir on that one. The people you want
to preach to are the Jack Welches of the world, who apparently aren't listening to
us very much.)&lt;/em&gt; 
&lt;p&gt;
4. Asking for a laundry list of skills may end up deterring the candidates who will
be best able to fill your actual need. Be precise in your ad: about the position's
title and description, about the level of skill you're expecting in the various areas,
about what's nice to have and what's imperative. If you're looking to fill more than
one position, write more than one ad; if you don't know exactly what you want, try
harder to figure it out before you click the publish button. 
&lt;p&gt;
&lt;em&gt;(T: Asking people to think before publishing? Heresy! Truthfully, I don't think
it's a question of not knowing what they want, it's more trying to find what they
want. I've seen how some of these same job ads get generated, and it's usually because
a programmer on the team has left, and they had some degree of skill in all of those
areas. What the company wants, then, is somebody who can step into exactly what that
individual was doing before they handed in their resignation, but ads like, "Candidate
should look at Joe Smith's resume on Dice.com (http://...) and have exactly that same
skill set. Being named Joe Smith a desirable 'plus', since then we won't have to have
the sysadmins create a new login handle for you." won't attract much attention. Frankly,
what I've found most companies want is to just not lose the programmer in the first
place.)&lt;/em&gt; 
&lt;p&gt;
5. If you really do think you want one person to do the task of an entire engineering
team, prepare yourself to get someone who is OK at a bunch of things and not particularly
good at any of them. Again: the more you know, the more you find out you don't know.
I regularly team with a talented back-end developer who knows better than to try to
do my job, and I know better than to try to do his. Anyone who represents themselves
as being a master of front-to-back web development may very well have no idea just
how much they don't know, and could end up imperiling your product or project -- front
to back -- as a result. 
&lt;p&gt;
&lt;em&gt;(T: Or be prepared to pay a lot of money for somebody who is an expert at all
of those things, or be prepared to spend a lot of time and money growing somebody
into that role. Sometimes the exact right thing to do is have one person do it all,
but usually it's cheaper to have a small team work together.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
(On a side note, I find it amusing that she seems to consider PHP a back-end skill,
but I don't want to sound harsh doing so--that's just a matter of perspective, I suppose.
(I can just imagine the guffaws from the mainframe guys when I talk about EJB, message-queue
and Spring systems being "back-end", too.) To me, the whole "web" thing is front-end
stuff, whether you're the one generating the HTML from your PHP or servlet/JSP or
ASP.NET server-side engine, or you're the one generating the CSS and graphics images
that are sent back to the browser by said server-side engine. If a user sees something
I did, it's probably because something bad happened and they're looking at a stack
trace on the screen.)
&lt;/p&gt;
&lt;p&gt;
The thing I find interesting is that HR hiring practices and job-writing skills haven't
gotten any better in the near-to-two-decades I've been in this industry. I can still
remember a fresh-faced wet-behind-the-ears Stroustrup-2nd-Edition-toting job candidate
named Neward looking at job placement listings and finding much the same kind of laundry
list of skills, including those with the impossible number of years of experience.
(In 1995, I saw an ad looking for somebody who had "10 years of C++ experience", and
wondering, "Gosh, I guess they're looking to hire Stroustrup or Lippmann", since those
two are the only people who could possibly have filled that requirement at the time.
This was right before reading the ad that was looking for 5 years of Java experience,
or the ad below it looking for 15 years of Delphi....)
&lt;/p&gt;
&lt;p&gt;
Given that it doesn't seem likely that HR departments are going to "get a clue" any
time soon, it leaves us with an interesting question: if you're a developer, and you're
looking at these laundry lists of requirements, how do you respond?
&lt;/p&gt;
&lt;p&gt;
Here's my own list of things for programmers/developers to consider over the next
five to ten years:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;These "laundry list" ads are not going away any time soon.&lt;/em&gt; We can rant and
rail about the stupidity of HR departments and hiring managers all we want, but the
basic fact is, this is the way things are going to work for the forseeable future,
it seems. Changing this would require a "sea change" across the industry, and sea
change doesn't happen overnight, or even within the span of a few years. So, to me,
the right question to ask isn't, "How do I change the industry to make it easier for
me to find a job I can do?", but "How do I change what I do when looking for a job
to better respond to what the industry is doing?" 
&lt;li&gt;
&lt;em&gt;Exclusively focusing on a single area of technology is the Kiss of Death.&lt;/em&gt; If
all you know is PHP, then your days are numbered. I mean no disrespect to the PHP
developers of the world--in fact, were it not too ambiguous to say it, I would rephrase
that as "If all you know is &lt;em&gt;X&lt;/em&gt;, your days are numbered." There is no one technical
skill that will be as much in demand in ten years as it is now. Technologies age.
Industry evolves. Innovations come along that completely change the game and leave
our predictions of a few years ago in the dust. Bill Gates (he of the "640K comment")
has said, and I think he's spot on with this, "We routinely overestimate where we
will be in five years, and vastly underestimate where we will be in ten." If you put
all your eggs in the PHP basket, then when PHP gets phased out in favor of &lt;em&gt;(insert
new "hotness" here)&lt;/em&gt;, you're screwed. Unless, of course, you want to wait until
you're the last man standing, which seems to have paid off well for the few COBOL
developers still alive.... but not so much for the Algol, Simula, or RPG folks.... 
&lt;li&gt;
&lt;em&gt;Assuming that you can stop learning is the Kiss of Death.&lt;/em&gt; Look, if you want
to stop learning at some point and coast on what you know, be prepared to switch industries.
This one, for the forseeable future, is one that's predicated on radical innovation
and constant change. This means we have to accept that everything is in a constant
state of flux--you can either rant and rave against it, or roll with it. This doesn't
mean that you don't have to look back, though--anybody who's been in this industry
for more than 10 years has seen how we keep reinventing the wheel, particularly now
that the relationship between Ruby and Smalltalk has been put up on the big stage,
so to speak. Do yourself a favor: learn stuff that's already "done", too, because
it turns out there's a lot of lessons we can learn from those who came before us.
"Those who cannot remember the past are condemned to repeat it" (George Santanyana).
Case in point: if you're trying to get into XML services, spend some time learning
CORBA and DCOM, and compare how they do things against WSDL and SOAP. What's similar?
What's different? Do some Googling and see if you can find comparison articles between
the two, and what XML services were supposed to "fix" from the previous two. You don't
have to write a ton of CORBA or DCOM code to see those differences (though writing
at least a little CORBA/DCOM code will probably help.) 
&lt;li&gt;
&lt;em&gt;Find a collection of people smarter than you.&lt;/em&gt; Chad Fowler calls this "Being
the worst player in any band you're in" (&lt;em&gt;My Job Went to India (and All I Got Was
This Lousy Book)&lt;/em&gt;, Pragmatic Press&lt;em&gt;)&lt;/em&gt;. The more you surround yourself with
smart people, the more of these kinds of things (tools, languages, etc) you will pick
up merely by osmosis, and find yourself more attractive to those kind of "laundry
list" job reqs. If nothing else, it speaks well to you as an employee/consultant if
you can say, "I don't know the answer to that question, but I know people who do,
and I can get them to help me". 
&lt;li&gt;
&lt;em&gt;Learn to be at least self-sufficient in related, complementary technologies.&lt;/em&gt; We
see laundry list ads in "clusters". Case in point: if the company is looking for somebody
to work on their website, they're going to rattle off a list of five or so things
they want he/she to know--HTML, CSS, XML, JavaScript and sometimes Flash (or maybe
now Silverlight), in addition to whatever server-side technology they're using (ASP.NET,
servlets, PHP, whatever). This is a pretty reasonable request, depending on the depth
of each that they want you to know. Here's the thing: the company does &lt;em&gt;not&lt;/em&gt; want
the guy who says he knows ASP.NET (and nothing but ASP.NET), when asked to make a
small HTML or CSS change, to turn to them and say, "I'm sorry, that's not in my job
description. I only know ASP.NET. You'll have to get your HTML guy to make that change."
You should at least be comfortable with the basic syntax of all of the above (again,
with possible exception for Flash, which is the odd man out in that job ad that started
this piece), so that you can at least make sure the site isn't going to break when
you push your changes live. In the case of the ad above, learn the things that "surround"
website development: HTML, CSS, JavaScript, Flash, Java applets, HTTP (!!), TCP/IP,
server operating systems, IIS or Apache or Tomcat or some other server engine (including
the necessary admin skills to get them installed and up and running), XML (since it's
so often used for configuration), and so on. These are all "complementary" skills
to being an ASP.NET developer (or a servlet/JSP developer). If you're a C# or Java
programmer, learn different programming languages, a la F# (.NET) or Scala (Java),
IronRuby (.NET) or JRuby (Java), and so on. If you're a Ruby developer, learn either
a JVM language or a CLR language, so you can "plug in" more easily to the large corporate
enterprise when that call comes. 
&lt;li&gt;
&lt;em&gt;Learn to "read" the ad at a higher level.&lt;/em&gt; It's often possible to "read between
the lines" and get an idea of what they're looking for, even before talking to anybody
at the company about the job. For example, I read the ad that started this piece,
and the internal dialogue that went on went something like this: &lt;blockquote&gt;Candidates
must have 5 years experience &lt;em&gt;(No entry-level developers wanted, they want somebody
who can get stuff done without having their hand held through the process) &lt;/em&gt;defining
and developing data driven &lt;em&gt;(they want somebody who's comfortable with SQL and
databases) &lt;/em&gt;web sites &lt;em&gt;(wait for it, the "web cluster" list is coming) &lt;/em&gt;and
have solid experience with ASP.NET &lt;em&gt;(OK, they're at least marginally a Microsoft
shop, that means they probably also want some Windows Server and IIS experience)&lt;/em&gt;,
HTML, XML, JavaScript, CSS &lt;em&gt;(the "web cluster", knew that was coming)&lt;/em&gt;, Flash &lt;em&gt;(OK,
I wonder if this is because they're building rich internet/intranet apps already,
or just flirting with the idea?)&lt;/em&gt;, SQL &lt;em&gt;(knew that was coming)&lt;/em&gt;, and optimizing
graphics for web use &lt;em&gt;(OK, this is another wrinkle--this smells of "we don't want
our graphics-heavy website to suck")&lt;/em&gt;. The candidate must also have project management
skills &lt;em&gt;(in other words, "You're on your own, sucka!"--you're not part of a project
team) &lt;/em&gt;and be able to balance multiple, dynamic, and sometimes conflicting priorities &lt;em&gt;(in
other words, "You're own your own trying to balance between the CTO's demands and
the CEO's demands, sucka!", since you're not part of a project team; this also probably
means you're not moving into an existing project, but doing more maintenance work
on an existing site)&lt;/em&gt;. This position is an integral part of executing our web
strategy &lt;em&gt;(in other words, this project has public visibility and you can't let
stupid errors show up on the website and make us all look bad) &lt;/em&gt;and must have
excellent interpersonal and communication skills &lt;em&gt;(what job &lt;/em&gt;doesn't&lt;em&gt; need
excellent interpersonal and communication skills?)&lt;/em&gt;.&lt;/blockquote&gt;See what I mean?
They want an ASP.NET dev. My guess is that they're thinking a lot about Silverlight,
since Silverlight's closest competitor is Flash, and so theoretically an ASP.NET-and-Flash
dev would know how to use Silverlight well. Thus, I'm guessing that the HTML, CSS,
and JavaScript don't need to be "Adept" level, nor even "Master" level, but "Journeyman"
is probably necessary, and maybe you could get away with "Apprentice" at those levels,
if you're working as part of a team. The SQL part will probably have to be "Journeyman"
level, the XML could probably be just "Apprentice", since I'm guessing it's only necessary
for the web.config files to control the ASP.NET configuration, and the "optimizing
web graphics", push-come-to-shove, could probably be forgiven if you've had some experience
at doing some performance tuning of a website. 
&lt;li&gt;
&lt;em&gt;Be insightful.&lt;/em&gt; I know, every interview book ever written says you should
"ask questions", but what they're really getting at is "Demonstrate that you've thought
about this company and this position". Demonstrating insight about the position and
the company and technology as a whole is a good way to prove that you're a neck above
the other candidates, and will help keep the job once you've got it. 
&lt;li&gt;
&lt;em&gt;Be honest about what you know.&lt;/em&gt; Let's be honest--we've all met developers
who claimed they were "experts" in a particular tool or technology, and then painfully
demonstrated how far from "expert" status they really were. Be honest about yourself:
claim your skills on a simple four-point scale. "Apprentice" means "I read a book
on it" or "I've looked at it", but "there's no way I could do it on my own without
some serious help, and ideally with a Master looking over my shoulder". "Journeyman"
means "I'm competent at it, I know the tools/technology"; or, put another way, "I
can do 80% of what anybody can ask me to do, and I know how to find the other 20%
when those situations arise". "Master" means "I not only claim that I can do what
you ask me to do with it, I can optimize systems built with it, I can make it do things
others wouldn't attempt, and I can help others learn it better". Masters are routinely
paired with Apprentices as mentors or coaches, and should expect to have this as a
major part of their responsibilities. (Ideally, anybody claiming "architect" in their
title should be a Master at one or two of the core tools/technologies used in their
system; or, put another way, architects should be &lt;em&gt;very&lt;/em&gt; dubious about architecting
with something they can't reasonably claim at least Journeyman status in.) "Adept",
shortly put, means you are not only fully capable of pulling off anything a Master
can do, but you routinely take the tool/technology way beyond what anybody else thinks
possible, or you know the depth of the system so well that you can fix bugs just by
thinking about them. With your eyes closed. While drinking a glass of water. Seriously,
Adept status is not something to claim lightly--not only had you better know the guys
who created the thing personally, but you should have offered up suggestions on how
to make it better and had one or more of them accepted. 
&lt;li&gt;
&lt;em&gt;Demonstrate that you have relevant skills beyond what they asked for.&lt;/em&gt; Look
at the ad in question: they want an ASP.NET dev, so any familiarity with IIS, Windows
Server, SQL Server, MSMQ, COM/DCOM/COM+, WCF/Web services, SharePoint, the CLR, IronPython,
or IronRuby should be listed prominently on your resume, and brought up at least twice
during your interview. These are (again) complementary technologies, and even if the
company doesn't have a need for those things right now, it's probably because Joe
didn't know any of those, and so they couldn't use them without sending Joe to a training
class. If you bring it up during the interview, it can also show some insight on your
part: "So, any questions for us?" "Yes, are you guys using Windows Server 2008, or
2003, for your back end?" "Um, we're using 2003, why do you ask?" "Oh, well, when
I was working as an ASP.NET dev for my previous company, we moved up to 2008 because
it had the Froobinger Enhancement, which let us...., and I was just curious if you
guys had a similar need." Or something like that. Again, be entirely honest about
what you know--if you helped the server upgrade by just putting the CDs into the drive
and punching the power button, then say as much. 
&lt;li&gt;
&lt;em&gt;Demonstrate that you can talk to project stakeholders and users.&lt;/em&gt; Communication
is huge. The era of the one-developer team is long since over--you have to be able
to meet with project champions, users, other developers, and so on. If you can't do
that without somebody being offended at your lack of tact and subtlety (or your lack
of personal hygiene), then don't expect to get hired too often. 
&lt;li&gt;
&lt;em&gt;Demonstrate that you understand the company, its business model, and what would
help it move forward.&lt;/em&gt; Developers who actually understand business are surprisingly
and unfortunately rare. Be one of the rare ones, and you'll find companies highly
reluctant to let you go.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Is this an exhaustive list? Hardly. Is this list guaranteed to keep you employed forever?
Nope. But this seems to be working for a lot of the people I run into at conferences
and client consulting gigs, so I humbly submit it for your consideration.
&lt;/p&gt;
&lt;p&gt;
But in no way do I consider this conversation completely over, either--feel free to
post your own suggestions, or tell me why I'm full of crap on any (or all) of these.
:-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=b63b60d2-4c68-4bc4-8d7a-d4c82cde958d" /&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,b63b60d2-4c68-4bc4-8d7a-d4c82cde958d.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Reading</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=c3ad9bf0-39cd-4985-981e-dabc0342dbf2</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,c3ad9bf0-39cd-4985-981e-dabc0342dbf2.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,c3ad9bf0-39cd-4985-981e-dabc0342dbf2.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c3ad9bf0-39cd-4985-981e-dabc0342dbf2</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This comment deserves response:
</p>
        <blockquote>
          <p>
First of all, if you're quoting my post, blocking out my name, and attacking me behind
my back by calling me "our intrepid troll", you could have shown the decency of linking
back to my original post. Here it is, for those interested in the real discussion: 
</p>
          <p>
            <a href="http://www.agilesoftwaredevelopment.com/blog/jurgenappelo/professionalism-knowledge-first">http://www.agilesoftwaredevelopment.com/blog/jurgenappelo/professionalism-knowledge-first</a>
          </p>
        </blockquote>
        <p>
Well, frankly, I didn't get your post from your blog, I got it from an email 'zine
(as indicated by the comment "This crossed my Inbox..."), and I didn't really think
that anybody would have any difficulty tracking down where it came from, at least
in terms of the email blast that put it into my Inbox. Coupled with the fact that,
quite honestly, I don't generally make a practice of using peoples' names without
their permission (and my email to the author asking if I could quote the post with
his name attached generated no response), so I blocked out the name. Having said that,
I'm pleased to offer full credit as to its source. 
</p>
        <blockquote>
          <p>
Now, let's review some of your remarks: 
</p>
          <p>
"COBOL is (at least) twenty years old, so therefore any use of COBOL must clearly
be as idiotic." 
</p>
          <p>
I never talked about COBOL, or any other programming language. I was talking about
old practices that are nowadays considered harmful and seriously damaging. (Like practising
waterfall project management, instead of agile project management.) I don't see how
programming in COBOL could seriously damage a business. Why do you compare COBOL with
lobotomies? I don't understand. I couldn't care less about programming languages.
I care about management practices.
</p>
        </blockquote>
        <p>
Frankly, the distinction isn't very clear in your post, and even more frankly, to
draw a distinction here is a bit specious. "I didn't mean we should throw away the <em>good</em> stuff
that's twenty years old, only the <em>bad</em> stuff!" doesn't seem much like a defense
to me. There are cases where waterfall style development is <em>exactly</em> the right
thing to do a more agile approach is <em>exactly</em> the wrong thing to do--the difference,
as I'm fond of saying, lies entirely in the context of the problem. Analogously, there
are cases where keeping an existing COBOL system up and running is the wrong thing
to do, and replacing it with a new system is the right thing to do. It all depends
on context, and for that reason, any dogmatic suggestion otherwise is flawed. 
</p>
        <blockquote>
          <p>
"How can a developer honestly claim to know "what it can be good for", without some
kind of experience to back it?" 
</p>
          <p>
I'm talking about gaining knowledge from the experience of others. If I hear 10 experts
advising the same best practice, then I still don't have any experience in that best
practice. I only have knowledge about it. That's how you can apply your knowledge
without your experience.
</p>
        </blockquote>
        <p>
Leaving aside the notion that there is no such thing as best practices (another favorite
rant of mine), what you're suggesting is that you, the individual, don't necessarily
have to have experience in the topic but others have to, before we can put faith into
it. That's a very different scenario than saying "We don't need no stinkin' experience",
and is still vastly more dangerous than saying, "I have used this, it works." I (and
lots of IT shops, I've found) will vastly prefer the latter to the former. 
</p>
        <blockquote>
          <p>
"Knowledge, apparently, isn't enough--experience still matters" 
</p>
          <p>
Yes, I never said experience doesn't matter. I only said it has no value when you
don't have gained the appropriate knowledge (from other sources) on when to apply
it, and when not.
</p>
        </blockquote>
        <p>
You said it when you offered up the title, "Knowledge, not Experience". 
</p>
        <blockquote>
          <p>
"buried under all the ludicrous hyperbole, he has a point" 
</p>
          <p>
Thanks for agreeing with me.
</p>
        </blockquote>
        <p>
You're welcome! :-) Seriously, I think I understand better what you were trying to
say, and it's not the horrendously dangerous comments that I thought you were saying,
so I will apologize here and now for believing you to be a wet-behind-the-ears/lets-let-technology-solve-all-our-problems/dangerous-to-the-extreme
developer that I've run across far too often, particularly in startups. So, please,
will you accept my apology? 
</p>
        <blockquote>
          <p>
"developers, like medical professionals, must ensure they are on top of their game
and spend some time investing in themselves and their knowledge portfolio" 
</p>
          <p>
Exactly.
</p>
        </blockquote>
        <p>
Exactly. :-) 
</p>
        <blockquote>
          <p>
"this doesn't mean that everything you learn is immediately applicable, or even appropriate,
to the situation at hand" 
</p>
          <p>
I never said that. You're putting words into my mouth. 
</p>
          <p>
My only claim is that you need to KNOW both new and old practices and understand which
ones are good and which ones can be seriously damaging. I simply don't trust people
who are bragging about their experience. What if a manager tells me he's got 15 years
of experience managing developers? If he's a micro-manager I still don't want him.
Because micro-management is considered harmful these days. A manager should KNOW that.
</p>
        </blockquote>
        <p>
Again, this was precisely the read I picked up out of the post, and my apologies for
the misinterpretation. But I stand by the idea that this is one of those posts that <em>could</em> be
read in a highly dangerous fashion, and used to promote evil, in the form of "Well,
he runs a company, so therefore he must know what he's doing, and therefore having
any kind of experience isn't really necessary to use something new, so... see, Mr.
CEO boss-of-mine? We're safe! Now get out of my way and let me use Software Factories
to build our next-generation mission-critical core-of-the-company software system,
even though nobody's ever done it before." 
</p>
        <p>
To speak to your example for a second, for example: Frankly, there are situations
where a micro-manager is a <em>good</em> thing. Young, inexperienced developers, for
example, need more hand-holding and mentoring than older, more senior, more experienced
developers do (speaking stereotypically, of course). And, quite honestly, the guy
with 15 years managing developers is <em>far</em> more likely to know how to manage
developers than the guy who's never managed developers before at all. The former is
the safer bet; not a guarantee, certainly, but often the safer bet, and that's sometimes
the best we can do in this industry. 
</p>
        <blockquote>
          <p>
"And we definitely shouldn't look at anything older than five years ago and equate
it to lobotomies." 
</p>
          <p>
I never said that either. Why do you claim that I said this? I don't have a problem
with old techniques. The daily standup meeting is a 80-year old best practice. It
was already used by pilots in the second world war. How could I be against that? It's
fine as it is.
</p>
        </blockquote>
        <p>
Um... because you used the term "lobotomies" first? And because your title pretty
clearly implies the statement, perhaps? (And let's lose the term "best practice" entirely,
please? There is no such thing--not even the daily standup.) 
</p>
        <blockquote>
          <p>
It's ok you didn't like my article. Sure it's meant to be provocative, and food for
thought. The article got twice as many positive votes than negative votes from DZone
readers. So I guess I'm adding value. But by taking the discussion away from its original
context (both physically and conceptually), and calling me names, you're not adding
any value for anyone.
</p>
        </blockquote>
        <p>
I took it in exactly the context it was given--a DZone email blast. I can't help it
if it was taken out of context, because that's how it was handed to me. What's worse,
I can see a development team citing this as an "expert opinion" to their management
as a justification to try untested approaches or technologies, or as inspiration to
a young developer, who reads "knowledge, not experience", and thinks, "Wow, if I know
all the cutting-edge latest stuff, I don't need to have those 10 years of experience
to get that job as a senior application architect." If your article was aimed more
clearly at the development process side of things, then I would wish it had appeared
more clearly in the arena of development processes, and made it more clear that your
aim was to suggest that managers (who aren't real big on reading blogs anyway, I've
sadly found) should be a bit more pragmatic and open-minded about who they hire.
</p>
        <p>
Look, I understand the desire for a provocative title--for me, the author of "The
Vietnam of Computer Science", to cast stones at another author for choosing an eye-catching
title is so far beyond hypocrisy as to move into sheer wild-eyed audacity. But I have
seen, first-hand, how that article has been used to justify the most incredibly asinine
technology decisions, and it moves me now to say "Be careful what you wish for" when
choosing titles that meant to be provocative and food for thought. Sure, your piece
got more positive votes than negative ones. So too, in their day, did articles on
client-server, on CORBA, on Six-Sigma, on the necessity for big up-front design....
</p>
        <p>
 
</p>
        <p>
Let me put it to you this way. Assume your child or your wife is sick, and as you
reach the hospital, the admittance nurse offers you a choice of the two doctors on
call. Who do you want more: the doctor who just graduated fresh from medical school
and knows all the latest in holistic and unconventional medicine, or the doctor with
30 years' experience and a solid track record of healthy patients?
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c3ad9bf0-39cd-4985-981e-dabc0342dbf2" />
        <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>From the &amp;quot;Gosh, You Wanted Me to Quote You?&amp;quot; Department...</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,c3ad9bf0-39cd-4985-981e-dabc0342dbf2.aspx</guid>
      <link>http://blogs.tedneward.com/2008/07/25/From+The+QuotGosh+You+Wanted+Me+To+Quote+Youquot+Department.aspx</link>
      <pubDate>Fri, 25 Jul 2008 07:03:40 GMT</pubDate>
      <description>&lt;p&gt;
This comment deserves response:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
First of all, if you're quoting my post, blocking out my name, and attacking me behind
my back by calling me "our intrepid troll", you could have shown the decency of linking
back to my original post. Here it is, for those interested in the real discussion: 
&lt;p&gt;
&lt;a href="http://www.agilesoftwaredevelopment.com/blog/jurgenappelo/professionalism-knowledge-first"&gt;http://www.agilesoftwaredevelopment.com/blog/jurgenappelo/professionalism-knowledge-first&lt;/a&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Well, frankly, I didn't get your post from your blog, I got it from an email 'zine
(as indicated by the comment "This crossed my Inbox..."), and I didn't really think
that anybody would have any difficulty tracking down where it came from, at least
in terms of the email blast that put it into my Inbox. Coupled with the fact that,
quite honestly, I don't generally make a practice of using peoples' names without
their permission (and my email to the author asking if I could quote the post with
his name attached generated no response), so I blocked out the name. Having said that,
I'm pleased to offer full credit as to its source. &lt;blockquote&gt; 
&lt;p&gt;
Now, let's review some of your remarks: 
&lt;p&gt;
"COBOL is (at least) twenty years old, so therefore any use of COBOL must clearly
be as idiotic." 
&lt;p&gt;
I never talked about COBOL, or any other programming language. I was talking about
old practices that are nowadays considered harmful and seriously damaging. (Like practising
waterfall project management, instead of agile project management.) I don't see how
programming in COBOL could seriously damage a business. Why do you compare COBOL with
lobotomies? I don't understand. I couldn't care less about programming languages.
I care about management practices.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Frankly, the distinction isn't very clear in your post, and even more frankly, to
draw a distinction here is a bit specious. "I didn't mean we should throw away the &lt;em&gt;good&lt;/em&gt; stuff
that's twenty years old, only the &lt;em&gt;bad&lt;/em&gt; stuff!" doesn't seem much like a defense
to me. There are cases where waterfall style development is &lt;em&gt;exactly&lt;/em&gt; the right
thing to do a more agile approach is &lt;em&gt;exactly&lt;/em&gt; the wrong thing to do--the difference,
as I'm fond of saying, lies entirely in the context of the problem. Analogously, there
are cases where keeping an existing COBOL system up and running is the wrong thing
to do, and replacing it with a new system is the right thing to do. It all depends
on context, and for that reason, any dogmatic suggestion otherwise is flawed. &lt;blockquote&gt; 
&lt;p&gt;
"How can a developer honestly claim to know "what it can be good for", without some
kind of experience to back it?" 
&lt;p&gt;
I'm talking about gaining knowledge from the experience of others. If I hear 10 experts
advising the same best practice, then I still don't have any experience in that best
practice. I only have knowledge about it. That's how you can apply your knowledge
without your experience.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Leaving aside the notion that there is no such thing as best practices (another favorite
rant of mine), what you're suggesting is that you, the individual, don't necessarily
have to have experience in the topic but others have to, before we can put faith into
it. That's a very different scenario than saying "We don't need no stinkin' experience",
and is still vastly more dangerous than saying, "I have used this, it works." I (and
lots of IT shops, I've found) will vastly prefer the latter to the former. &lt;blockquote&gt; 
&lt;p&gt;
"Knowledge, apparently, isn't enough--experience still matters" 
&lt;p&gt;
Yes, I never said experience doesn't matter. I only said it has no value when you
don't have gained the appropriate knowledge (from other sources) on when to apply
it, and when not.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
You said it when you offered up the title, "Knowledge, not Experience". &lt;blockquote&gt; 
&lt;p&gt;
"buried under all the ludicrous hyperbole, he has a point" 
&lt;p&gt;
Thanks for agreeing with me.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
You're welcome! :-) Seriously, I think I understand better what you were trying to
say, and it's not the horrendously dangerous comments that I thought you were saying,
so I will apologize here and now for believing you to be a wet-behind-the-ears/lets-let-technology-solve-all-our-problems/dangerous-to-the-extreme
developer that I've run across far too often, particularly in startups. So, please,
will you accept my apology? &lt;blockquote&gt; 
&lt;p&gt;
"developers, like medical professionals, must ensure they are on top of their game
and spend some time investing in themselves and their knowledge portfolio" 
&lt;p&gt;
Exactly.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Exactly. :-) &lt;blockquote&gt; 
&lt;p&gt;
"this doesn't mean that everything you learn is immediately applicable, or even appropriate,
to the situation at hand" 
&lt;p&gt;
I never said that. You're putting words into my mouth. 
&lt;p&gt;
My only claim is that you need to KNOW both new and old practices and understand which
ones are good and which ones can be seriously damaging. I simply don't trust people
who are bragging about their experience. What if a manager tells me he's got 15 years
of experience managing developers? If he's a micro-manager I still don't want him.
Because micro-management is considered harmful these days. A manager should KNOW that.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Again, this was precisely the read I picked up out of the post, and my apologies for
the misinterpretation. But I stand by the idea that this is one of those posts that &lt;em&gt;could&lt;/em&gt; be
read in a highly dangerous fashion, and used to promote evil, in the form of "Well,
he runs a company, so therefore he must know what he's doing, and therefore having
any kind of experience isn't really necessary to use something new, so... see, Mr.
CEO boss-of-mine? We're safe! Now get out of my way and let me use Software Factories
to build our next-generation mission-critical core-of-the-company software system,
even though nobody's ever done it before." 
&lt;p&gt;
To speak to your example for a second, for example: Frankly, there are situations
where a micro-manager is a &lt;em&gt;good&lt;/em&gt; thing. Young, inexperienced developers, for
example, need more hand-holding and mentoring than older, more senior, more experienced
developers do (speaking stereotypically, of course). And, quite honestly, the guy
with 15 years managing developers is &lt;em&gt;far&lt;/em&gt; more likely to know how to manage
developers than the guy who's never managed developers before at all. The former is
the safer bet; not a guarantee, certainly, but often the safer bet, and that's sometimes
the best we can do in this industry. &lt;blockquote&gt; 
&lt;p&gt;
"And we definitely shouldn't look at anything older than five years ago and equate
it to lobotomies." 
&lt;p&gt;
I never said that either. Why do you claim that I said this? I don't have a problem
with old techniques. The daily standup meeting is a 80-year old best practice. It
was already used by pilots in the second world war. How could I be against that? It's
fine as it is.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Um... because you used the term "lobotomies" first? And because your title pretty
clearly implies the statement, perhaps? (And let's lose the term "best practice" entirely,
please? There is no such thing--not even the daily standup.) &lt;blockquote&gt; 
&lt;p&gt;
It's ok you didn't like my article. Sure it's meant to be provocative, and food for
thought. The article got twice as many positive votes than negative votes from DZone
readers. So I guess I'm adding value. But by taking the discussion away from its original
context (both physically and conceptually), and calling me names, you're not adding
any value for anyone.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I took it in exactly the context it was given--a DZone email blast. I can't help it
if it was taken out of context, because that's how it was handed to me. What's worse,
I can see a development team citing this as an "expert opinion" to their management
as a justification to try untested approaches or technologies, or as inspiration to
a young developer, who reads "knowledge, not experience", and thinks, "Wow, if I know
all the cutting-edge latest stuff, I don't need to have those 10 years of experience
to get that job as a senior application architect." If your article was aimed more
clearly at the development process side of things, then I would wish it had appeared
more clearly in the arena of development processes, and made it more clear that your
aim was to suggest that managers (who aren't real big on reading blogs anyway, I've
sadly found) should be a bit more pragmatic and open-minded about who they hire.
&lt;/p&gt;
&lt;p&gt;
Look, I understand the desire for a provocative title--for me, the author of "The
Vietnam of Computer Science", to cast stones at another author for choosing an eye-catching
title is so far beyond hypocrisy as to move into sheer wild-eyed audacity. But I have
seen, first-hand, how that article has been used to justify the most incredibly asinine
technology decisions, and it moves me now to say "Be careful what you wish for" when
choosing titles that meant to be provocative and food for thought. Sure, your piece
got more positive votes than negative ones. So too, in their day, did articles on
client-server, on CORBA, on Six-Sigma, on the necessity for big up-front design....
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Let me put it to you this way. Assume your child or your wife is sick, and as you
reach the hospital, the admittance nurse offers you a choice of the two doctors on
call. Who do you want more: the doctor who just graduated fresh from medical school
and knows all the latest in holistic and unconventional medicine, or the doctor with
30 years' experience and a solid track record of healthy patients?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=c3ad9bf0-39cd-4985-981e-dabc0342dbf2" /&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,c3ad9bf0-39cd-4985-981e-dabc0342dbf2.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=7ea05023-cdc1-439d-910d-bcff5f4ff309</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,7ea05023-cdc1-439d-910d-bcff5f4ff309.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,7ea05023-cdc1-439d-910d-bcff5f4ff309.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=7ea05023-cdc1-439d-910d-bcff5f4ff309</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently this little gem crossed my Inbox....
</p>
        <blockquote>
          <p>
            <strong>Professionalism = Knowledge First, Experience Last</strong>
            <br />
By J----- A-----
</p>
          <p>
            <br />
Do you trust a doctor with diagnosing your mental problems if the doctor tells you
he's got 20 years of experience? Do you still trust that doctor when he picks up his
tools, and asks you to prepare for a lobotomy?
</p>
          <p>
Would you still be impressed if the doctor had 20 years of experience in carrying
out lobotomies?
</p>
          <p>
I am always skeptic when people tell me they have X years of experience in a certain
field or discipline, like "5 years of experience as a .NET developer", "8 years of
experience as a project manager" or "12 years of experience as a development manager".
It is as if people's professional levels need to be measured in years of practice.
</p>
          <p>
This, of course, is nonsense.
</p>
          <p>
            <strong>Professionalism is measured by what you are going to do <em>now</em>...</strong>
          </p>
          <p>
Are you going to use some discredited technique from half a century ago?<br />
•    Are you, as a .NET developer, going to use Response.Write, because
you've got 5 years of experience doing exactly that?<br />
•    Are you, as a project manager, going to create Gantt charts, because
that's what you've been doing for 8 years?<br />
•    Are you, as a development manager, going to micro-manage your
team members, as you did in the 12 years before now?
</p>
          <p>
If so, allow me to illustrate the value of your experience...
</p>
          <p>
(Photo of "Zero" signs)
</p>
          <p>
Here's an example of what it means to be a professional:
</p>
          <p>
There's a concept called Kanban making headlines these days in some parts of the agile
community. I honestly and proudly admit that I have no experience at all in applying
Kanban. But that's just a minor inconvenience. Because I have attained the knowledge
of what it is and what it can be good for. And now there are some planning issues
in our organization for which this Kanban-stuff might be the perfect solution. I'm
sure we're going to give it a shot, in a controlled setting, with time allocated for
a pilot and proper evaluations afterwards. That's the way a professional tries to
solve a problem.
</p>
          <p>
            <strong>Professionals don't match problems with their experiences. They match them
with their knowledge.</strong>
          </p>
          <p>
Sure, experience is useful. But only when you already have the knowledge in place.
Experience has no value when there's no knowledge to verify that you are applying
the right experience.
</p>
          <p>
            <strong>Knowledge Comes First, Experience Comes Last</strong>
          </p>
          <p>
This is my message to anyone who wants to be a professional software developer, a
professional project manager, or a professional development manager. 
</p>
          <p>
You must gain and apply knowledge first, and experience will help you after that.
Professionals need to know about the latest developments and techniques. 
</p>
          <p>
They certainly don't bother measuring years of experience.
</p>
          <p>
Are you still practicing lobotomies?
</p>
        </blockquote>
        <p>
Um....
</p>
        <p>
Wow.
</p>
        <p>
Let's start with the logical fallacy in the first section. Do I trust a doctor with
diagnosing my mental problems if he tells me he's got 20 years of experience? Generally,
yes, unless I have reasons to doubt this. If the guy picks up a skull-drill and starts
looking for a place to start boring into my skull, sure, I'll start to question his
judgement.... But what does this have to do with anything? I wouldn't trust the guy
if he picked up a chainsaw and started firing <em>it</em> up, either.
</p>
        <p>
Look, I get the analogy: "Doctor has 20 years of experience using outdated skills",
har har. Very funny, very memorable, and totally inappropriate metaphor for the situation.
To stand here and suggest that developers who aren't using the latest-and-greatest,
so-bleeding-edge-even-saying-the-name-cuts-your-skin tools or languages or technologies
are somehow practicing lobotomies (which, by the way, are still a recommended practice
in certain mental disorder cases, I understand) in order to solve any and all mental-health
issues, is a gross mischaracterization--and the worst form of negligence--I've ever
heard suggested.
</p>
        <p>
And it comes as no surprise that it's coming from the CIO of a consulting company.
(Note to self: here's one more company I don't want anywhere <em>near </em>my clients'
IT infrastructure.)
</p>
        <p>
Let's take this analogy to its logical next step, shall we?
</p>
        <p>
COBOL is (at least) twenty years old, so therefore any use of COBOL must <em>clearly</em> be
as idiotic as drilling holes in your skull to let the demons out. So any company currently
using COBOL has no real option other than to immediately upgrade <em>all</em> of their
currently-running COBOL infrastructure (despite the fact that it's tested, works,
and cashes most of the US banking industry's checks on a daily basis) with something
vastly superior and totally untested (since we don't need experience, just knowlege),
like... oh, I dunno.... how about Ruby? Oh, no, wait, that's at least 10 years old.
Ditto for Java. And let's not even <em>think</em> about C, Perl, Python....
</p>
        <p>
I know; let's rewrite the entire financial industry's core backbone in Groovy, since
it's only, what, 6 years old at this point? I mean, sure, we'll have to do all this
over again in just four years, since that's when Groovy will turn 10 and thus obviously
begin it's long slide into mediocrity, alongside the "four humors" of medicine and
Aristotle's (completely inaccurate) anatomical depictions, but hey, that's progress,
right? Forget experience, it has <em>no value</em> compared to the "knowledge" that
comes from reading the documentation on a brand-new language, tool, library, or platform....
</p>
        <p>
What I find most appalling is this part right here:
</p>
        <blockquote>
          <p>
I honestly and proudly admit that I have no experience at all in applying Kanban. <em>But
that's just a minor inconvenience. Because I have attained the knowledge of what it
is and what it can be good for.</em></p>
        </blockquote>
        <p>
How can a developer honestly claim to <em>know</em> "what it can be good for", without
some kind of experience to back it? (Hell, I'll even accept that you have familiarity
and experience with something vaguely <em>relating</em> to the thing at hand, if you've
got it--after all, experience in Java makes you a pretty damn good C# developer, in
my mind, and vice versa.) 
</p>
        <p>
And, to make things even <em>more</em> interesting, our intrepid troll, having established
the attention-gathering headline, then proceeds to step away from the chasm, by backing
away from this "knowledge-not-experience" position in the same paragraph, just one
sentence later:
</p>
        <blockquote>
          <p>
I'm sure we're going to give it a shot, in a controlled setting, with time allocated
for a pilot and proper evaluations afterwards.
</p>
        </blockquote>
        <p>
Ah... In other words, he and his company are going to experiment with this new technique,
"in a controlled setting, with time allocated for a pilot and proper evaluations afterwards",
in order to gain <em>experience</em> with the technique and see how it works and how
it doesn't. 
</p>
        <p>
In other words....
</p>
        <p>
.... experience matters. 
</p>
        <p>
Knowledge, apparently, isn't enough--experience still matters, and it matters a lot
earlier than his "knowledge first, experience last" mantra seems to imply. Otherwise,
once you "know" something, why not apply it immediately to your mission-critical core?
</p>
        <p>
At the end of the day, buried under all the ludicrous hyperbole, he has a point: developers,
like medical professionals, must ensure they are on top of their game and spend some
time investing in themselves and their knowledge portfolio. Jay Zimmerman takes great
pains to point this out at every No Fluff Just Stuff show, and he's right: those who
spend the time to invest in their own knowledge portfolio, find themselves the last
to be fired and the first to be hired. But this doesn't mean that everything you learn
is immediately applicable, or even appropriate, to the situation at hand. Just because
you learned Groovy last weekend in Austin doesn't mean you have the right--or the
responsibility--to immediately start slipping Groovy in to the production servers.
Groovy has its share of good things, yes, but it's got its share of negative consequences,
too, and you'd better <em>damn</em> well know what they are before you start betting
the company's future on it. (No, I will not tell you what those negative consequences
are--that's <em>your</em> job, because what if it turns out I'm wrong, or they don't
apply to your particular situation?) <em>Every</em> technology, language, library
or tool has a positive/negative profile to it, and if you can't point out the pros
as well as the cons, then you don't understand the technology and you have <em>no</em> business
using it on anything except maybe a prototype that never leaves your local hard disk.
Too many projects were built with "flavor-of-the-year" tools and technologies, and
a few years later, long after the original "bleeding-edge" developer has gone on to
do a new project with a new "bleeding-edge" technology, the IT guys left to admin
and upkeep the project are struggling to find ways to keep this thing afloat.
</p>
        <p>
If you're languishing at a company that seems to resist anything and everything new,
try this exercise on: go down to the IT guys, and <em>ask</em> them why they resist.
Ask them to show you a data flow diagram of how information feeds from one system
to another (assuming they even have one). Ask them how many different operating systems
they have, how many different languages were used to create the various software programs
currently running, what tools they have to know when one of those programs fails,
and how many different data formats are currently in use. Then go find the guys currently
maintaining and updating and bug-fixing those current programs, and ask to see the
code. Figure out how long it would take you to rewrite the whole thing, and keep the
company in business while you're at it.
</p>
        <p>
There is a reason "legacy code" exists, and while we shouldn't be afraid to replace
it, we shouldn't be cavalier about tossing it out, either.
</p>
        <p>
And we <em>definitely</em> shouldn't look at anything older than five years ago and
equate it to lobotomies. COBOL had some good ideas that still echo through the industry
today, and Groovy and Scala and Ruby and F# undoubtedly have some buried mines that
we will, with benefit of ten years' hindsight, look back at in 2018 and say, "Wow,
how dumb were we to think that this was the last language we'd ever have to use!".
</p>
        <p>
That's experience talking. 
</p>
        <p>
And the funny thing is, it seems to have served us pretty well. When we don't listen
to the guys claiming to know how to use something effectively that they've never actually
used before, of course.
</p>
        <p>
          <em>Caveat emptor.</em>
        </p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=7ea05023-cdc1-439d-910d-bcff5f4ff309" />
        <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>From the &amp;quot;You Must Be Trolling for Hits&amp;quot; Department...</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,7ea05023-cdc1-439d-910d-bcff5f4ff309.aspx</guid>
      <link>http://blogs.tedneward.com/2008/07/24/From+The+QuotYou+Must+Be+Trolling+For+Hitsquot+Department.aspx</link>
      <pubDate>Thu, 24 Jul 2008 07:53:02 GMT</pubDate>
      <description>&lt;p&gt;
Recently this little gem crossed my Inbox....
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Professionalism = Knowledge First, Experience Last&lt;/strong&gt;
&lt;br&gt;
By J----- A-----
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Do you trust a doctor with diagnosing your mental problems if the doctor tells you
he's got 20 years of experience? Do you still trust that doctor when he picks up his
tools, and asks you to prepare for a lobotomy?
&lt;/p&gt;
&lt;p&gt;
Would you still be impressed if the doctor had 20 years of experience in carrying
out lobotomies?
&lt;/p&gt;
&lt;p&gt;
I am always skeptic when people tell me they have X years of experience in a certain
field or discipline, like "5 years of experience as a .NET developer", "8 years of
experience as a project manager" or "12 years of experience as a development manager".
It is as if people's professional levels need to be measured in years of practice.
&lt;/p&gt;
&lt;p&gt;
This, of course, is nonsense.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Professionalism is measured by what you are going to do &lt;em&gt;now&lt;/em&gt;...&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Are you going to use some discredited technique from half a century ago?&lt;br&gt;
•&amp;nbsp;&amp;nbsp;&amp;nbsp; Are you, as a .NET developer, going to use Response.Write, because
you've got 5 years of experience doing exactly that?&lt;br&gt;
•&amp;nbsp;&amp;nbsp;&amp;nbsp; Are you, as a project manager, going to create Gantt charts, because
that's what you've been doing for 8 years?&lt;br&gt;
•&amp;nbsp;&amp;nbsp;&amp;nbsp; Are you, as a development manager, going to micro-manage your
team members, as you did in the 12 years before now?
&lt;/p&gt;
&lt;p&gt;
If so, allow me to illustrate the value of your experience...
&lt;/p&gt;
&lt;p&gt;
(Photo of "Zero" signs)
&lt;/p&gt;
&lt;p&gt;
Here's an example of what it means to be a professional:
&lt;/p&gt;
&lt;p&gt;
There's a concept called Kanban making headlines these days in some parts of the agile
community. I honestly and proudly admit that I have no experience at all in applying
Kanban. But that's just a minor inconvenience. Because I have attained the knowledge
of what it is and what it can be good for. And now there are some planning issues
in our organization for which this Kanban-stuff might be the perfect solution. I'm
sure we're going to give it a shot, in a controlled setting, with time allocated for
a pilot and proper evaluations afterwards. That's the way a professional tries to
solve a problem.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Professionals don't match problems with their experiences. They match them
with their knowledge.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Sure, experience is useful. But only when you already have the knowledge in place.
Experience has no value when there's no knowledge to verify that you are applying
the right experience.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Knowledge Comes First, Experience Comes Last&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
This is my message to anyone who wants to be a professional software developer, a
professional project manager, or a professional development manager. 
&lt;/p&gt;
&lt;p&gt;
You must gain and apply knowledge first, and experience will help you after that.
Professionals need to know about the latest developments and techniques. 
&lt;/p&gt;
&lt;p&gt;
They certainly don't bother measuring years of experience.
&lt;/p&gt;
&lt;p&gt;
Are you still practicing lobotomies?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Um....
&lt;/p&gt;
&lt;p&gt;
Wow.
&lt;/p&gt;
&lt;p&gt;
Let's start with the logical fallacy in the first section. Do I trust a doctor with
diagnosing my mental problems if he tells me he's got 20 years of experience? Generally,
yes, unless I have reasons to doubt this. If the guy picks up a skull-drill and starts
looking for a place to start boring into my skull, sure, I'll start to question his
judgement.... But what does this have to do with anything? I wouldn't trust the guy
if he picked up a chainsaw and started firing &lt;em&gt;it&lt;/em&gt; up, either.
&lt;/p&gt;
&lt;p&gt;
Look, I get the analogy: "Doctor has 20 years of experience using outdated skills",
har har. Very funny, very memorable, and totally inappropriate metaphor for the situation.
To stand here and suggest that developers who aren't using the latest-and-greatest,
so-bleeding-edge-even-saying-the-name-cuts-your-skin tools or languages or technologies
are somehow practicing lobotomies (which, by the way, are still a recommended practice
in certain mental disorder cases, I understand) in order to solve any and all mental-health
issues, is a gross mischaracterization--and the worst form of negligence--I've ever
heard suggested.
&lt;/p&gt;
&lt;p&gt;
And it comes as no surprise that it's coming from the CIO of a consulting company.
(Note to self: here's one more company I don't want anywhere &lt;em&gt;near &lt;/em&gt;my clients'
IT infrastructure.)
&lt;/p&gt;
&lt;p&gt;
Let's take this analogy to its logical next step, shall we?
&lt;/p&gt;
&lt;p&gt;
COBOL is (at least) twenty years old, so therefore any use of COBOL must &lt;em&gt;clearly&lt;/em&gt; be
as idiotic as drilling holes in your skull to let the demons out. So any company currently
using COBOL has no real option other than to immediately upgrade &lt;em&gt;all&lt;/em&gt; of their
currently-running COBOL infrastructure (despite the fact that it's tested, works,
and cashes most of the US banking industry's checks on a daily basis) with something
vastly superior and totally untested (since we don't need experience, just knowlege),
like... oh, I dunno.... how about Ruby? Oh, no, wait, that's at least 10 years old.
Ditto for Java. And let's not even &lt;em&gt;think&lt;/em&gt; about C, Perl, Python....
&lt;/p&gt;
&lt;p&gt;
I know; let's rewrite the entire financial industry's core backbone in Groovy, since
it's only, what, 6 years old at this point? I mean, sure, we'll have to do all this
over again in just four years, since that's when Groovy will turn 10 and thus obviously
begin it's long slide into mediocrity, alongside the "four humors" of medicine and
Aristotle's (completely inaccurate) anatomical depictions, but hey, that's progress,
right? Forget experience, it has &lt;em&gt;no value&lt;/em&gt; compared to the "knowledge" that
comes from reading the documentation on a brand-new language, tool, library, or platform....
&lt;/p&gt;
&lt;p&gt;
What I find most appalling is this part right here:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I honestly and proudly admit that I have no experience at all in applying Kanban. &lt;em&gt;But
that's just a minor inconvenience. Because I have attained the knowledge of what it
is and what it can be good for.&lt;/em&gt; 
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
How can a developer honestly claim to &lt;em&gt;know&lt;/em&gt; "what it can be good for", without
some kind of experience to back it? (Hell, I'll even accept that you have familiarity
and experience with something vaguely &lt;em&gt;relating&lt;/em&gt; to the thing at hand, if you've
got it--after all, experience in Java makes you a pretty damn good C# developer, in
my mind, and vice versa.) 
&lt;/p&gt;
&lt;p&gt;
And, to make things even &lt;em&gt;more&lt;/em&gt; interesting, our intrepid troll, having established
the attention-gathering headline, then proceeds to step away from the chasm, by backing
away from this "knowledge-not-experience" position in the same paragraph, just one
sentence later:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I'm sure we're going to give it a shot, in a controlled setting, with time allocated
for a pilot and proper evaluations afterwards.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ah... In other words, he and his company are going to experiment with this new technique,
"in a controlled setting, with time allocated for a pilot and proper evaluations afterwards",
in order to gain &lt;em&gt;experience&lt;/em&gt; with the technique and see how it works and how
it doesn't. 
&lt;/p&gt;
&lt;p&gt;
In other words....
&lt;/p&gt;
&lt;p&gt;
.... experience matters. 
&lt;/p&gt;
&lt;p&gt;
Knowledge, apparently, isn't enough--experience still matters, and it matters a lot
earlier than his "knowledge first, experience last" mantra seems to imply. Otherwise,
once you "know" something, why not apply it immediately to your mission-critical core?
&lt;/p&gt;
&lt;p&gt;
At the end of the day, buried under all the ludicrous hyperbole, he has a point: developers,
like medical professionals, must ensure they are on top of their game and spend some
time investing in themselves and their knowledge portfolio. Jay Zimmerman takes great
pains to point this out at every No Fluff Just Stuff show, and he's right: those who
spend the time to invest in their own knowledge portfolio, find themselves the last
to be fired and the first to be hired. But this doesn't mean that everything you learn
is immediately applicable, or even appropriate, to the situation at hand. Just because
you learned Groovy last weekend in Austin doesn't mean you have the right--or the
responsibility--to immediately start slipping Groovy in to the production servers.
Groovy has its share of good things, yes, but it's got its share of negative consequences,
too, and you'd better &lt;em&gt;damn&lt;/em&gt; well know what they are before you start betting
the company's future on it. (No, I will not tell you what those negative consequences
are--that's &lt;em&gt;your&lt;/em&gt; job, because what if it turns out I'm wrong, or they don't
apply to your particular situation?) &lt;em&gt;Every&lt;/em&gt; technology, language, library
or tool has a positive/negative profile to it, and if you can't point out the pros
as well as the cons, then you don't understand the technology and you have &lt;em&gt;no&lt;/em&gt; business
using it on anything except maybe a prototype that never leaves your local hard disk.
Too many projects were built with "flavor-of-the-year" tools and technologies, and
a few years later, long after the original "bleeding-edge" developer has gone on to
do a new project with a new "bleeding-edge" technology, the IT guys left to admin
and upkeep the project are struggling to find ways to keep this thing afloat.
&lt;/p&gt;
&lt;p&gt;
If you're languishing at a company that seems to resist anything and everything new,
try this exercise on: go down to the IT guys, and &lt;em&gt;ask&lt;/em&gt; them why they resist.
Ask them to show you a data flow diagram of how information feeds from one system
to another (assuming they even have one). Ask them how many different operating systems
they have, how many different languages were used to create the various software programs
currently running, what tools they have to know when one of those programs fails,
and how many different data formats are currently in use. Then go find the guys currently
maintaining and updating and bug-fixing those current programs, and ask to see the
code. Figure out how long it would take you to rewrite the whole thing, and keep the
company in business while you're at it.
&lt;/p&gt;
&lt;p&gt;
There is a reason "legacy code" exists, and while we shouldn't be afraid to replace
it, we shouldn't be cavalier about tossing it out, either.
&lt;/p&gt;
&lt;p&gt;
And we &lt;em&gt;definitely&lt;/em&gt; shouldn't look at anything older than five years ago and
equate it to lobotomies. COBOL had some good ideas that still echo through the industry
today, and Groovy and Scala and Ruby and F# undoubtedly have some buried mines that
we will, with benefit of ten years' hindsight, look back at in 2018 and say, "Wow,
how dumb were we to think that this was the last language we'd ever have to use!".
&lt;/p&gt;
&lt;p&gt;
That's experience talking. 
&lt;/p&gt;
&lt;p&gt;
And the funny thing is, it seems to have served us pretty well. When we don't listen
to the guys claiming to know how to use something effectively that they've never actually
used before, of course.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Caveat emptor.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=7ea05023-cdc1-439d-910d-bcff5f4ff309" /&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,7ea05023-cdc1-439d-910d-bcff5f4ff309.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Development Processes</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=ddbdc499-d4e2-4b12-a2f1-165ab3617887</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,ddbdc499-d4e2-4b12-a2f1-165ab3617887.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,ddbdc499-d4e2-4b12-a2f1-165ab3617887.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=ddbdc499-d4e2-4b12-a2f1-165ab3617887</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
If you've peeked at my blog site in the last twenty minutes or so, you've probably
noticed some churn in the template in the upper-left corner; by now, it's been finalized,
and it reads "JOB REFERRALS".
</p>
        <p>
WTHeck? Has Ted finally sold out? Sort of, not really. At least, <em>I</em> don't
think so.
</p>
        <p>
Here's the deal: the company behind those ads, Entice Labs, contacted me to see if
I was interested in hosting some job ads on my blog, given that I seem to generate
a moderate amount of traffic. I figured it was worthwhile to at least talk to them,
and the more I did, the more I liked what I heard--the ads are focused specifically
at developers of particular types (I chose a criteria string of "Software Developers",
subcategorized by "Java, .NET, .NET (Visual Basic), .NET (C#), C++, Flex, Ruby on
Rails, C, SQL, JavaScript, HTML" though I'm not sure whether "HTML" will bring in
too many web-designer jobs), and visitors to my blog don't have to click through the
ads to get to the content, which was important to me. And, besides, given the current
economic climate, if I can help somebody find a new job, I'd like to.
</p>
        <p>
Now for the full disclaimer: I <em>will</em> be getting money back from these job
ads, though how much, to be honest with you, I'm not sure. I'm really not doing this
for the money, so I make this statement now: I will take 50% of whatever I make through
this program and donate it to a charitable organization. The other 50% I will use
to offset travel and expenses to user groups and/or CodeCamps and/or for-free conferences
put on throughout the country. (Email me if you know of one that you're organizing
or attending and would like to see me speak at, and I'll tell you if there's any room
in the budget left for it. :-) )
</p>
        <p>
Anyway, I figured if the ads got too obnoxious, I could always remove them; it's an
experiment of sorts. Tell me what you think.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=ddbdc499-d4e2-4b12-a2f1-165ab3617887" />
        <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>Blog change? Ads? What gives?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,ddbdc499-d4e2-4b12-a2f1-165ab3617887.aspx</guid>
      <link>http://blogs.tedneward.com/2008/07/17/Blog+Change+Ads+What+Gives.aspx</link>
      <pubDate>Thu, 17 Jul 2008 02:29:46 GMT</pubDate>
      <description>&lt;p&gt;
If you've peeked at my blog site in the last twenty minutes or so, you've probably
noticed some churn in the template in the upper-left corner; by now, it's been finalized,
and it reads "JOB REFERRALS".
&lt;/p&gt;
&lt;p&gt;
WTHeck? Has Ted finally sold out? Sort of, not really. At least, &lt;em&gt;I&lt;/em&gt; don't
think so.
&lt;/p&gt;
&lt;p&gt;
Here's the deal: the company behind those ads, Entice Labs, contacted me to see if
I was interested in hosting some job ads on my blog, given that I seem to generate
a moderate amount of traffic. I figured it was worthwhile to at least talk to them,
and the more I did, the more I liked what I heard--the ads are focused specifically
at developers of particular types (I chose a criteria string of "Software Developers",
subcategorized by "Java, .NET, .NET (Visual Basic), .NET (C#), C++, Flex, Ruby on
Rails, C, SQL, JavaScript, HTML" though I'm not sure whether "HTML" will bring in
too many web-designer jobs), and visitors to my blog don't have to click through the
ads to get to the content, which was important to me. And, besides, given the current
economic climate, if I can help somebody find a new job, I'd like to.
&lt;/p&gt;
&lt;p&gt;
Now for the full disclaimer: I &lt;em&gt;will&lt;/em&gt; be getting money back from these job
ads, though how much, to be honest with you, I'm not sure. I'm really not doing this
for the money, so I make this statement now: I will take 50% of whatever I make through
this program and donate it to a charitable organization. The other 50% I will use
to offset travel and expenses to user groups and/or CodeCamps and/or for-free conferences
put on throughout the country. (Email me if you know of one that you're organizing
or attending and would like to see me speak at, and I'll tell you if there's any room
in the budget left for it. :-) )
&lt;/p&gt;
&lt;p&gt;
Anyway, I figured if the ads got too obnoxious, I could always remove them; it's an
experiment of sorts. Tell me what you think.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=ddbdc499-d4e2-4b12-a2f1-165ab3617887" /&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,ddbdc499-d4e2-4b12-a2f1-165ab3617887.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=05f327f7-95ec-413f-8d41-74ad6c5a4e58</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,05f327f7-95ec-413f-8d41-74ad6c5a4e58.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,05f327f7-95ec-413f-8d41-74ad6c5a4e58.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=05f327f7-95ec-413f-8d41-74ad6c5a4e58</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The Pragmatic Programmer says, "Learn a new language every year". This is great advice,
not just because it puts new tools into your mental toolbox that you can pull out
on various occasions to get a job done, but also because it opens your mind to new
ideas and new concepts that will filter their way into your code even without explicit
language support. For example, suppose you've looked at (J/Iron)Ruby or Groovy, and
come to like the "internal iterator" approach as a way of simplifying moving across
a collection of objects in a uniform way; for political and cultural reasons, though,
you can't write code in anything but Java. You're frustrated, because local anonymous
functions (also commonly--and, I think, mistakenly--called <em>closures</em>) are
not a first-class concept in Java. Then, you later look at Haskell/ML/Scala/F#, which
makes heavy use of what Java programmers would call "static methods" to carry out
operations, and realize that this could, in fact, be adapted to Java to give you the
"internal iteration" concept over the Java Collections:
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum1" style="color: #606060"> 1:</span>
              <span style="color: #0000ff">package</span> com.tedneward.util;</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum2" style="color: #606060"> 2:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum3" style="color: #606060"> 3:</span>
              <span style="color: #0000ff">import</span> java.util.*;</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum4" style="color: #606060"> 4:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum5" style="color: #606060"> 5:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">interface</span> Acceptor</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum6" style="color: #606060"> 6:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum7" style="color: #606060"> 7:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">void</span> each(Object
obj);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum8" style="color: #606060"> 8:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum9" style="color: #606060"> 9:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum10" style="color: #606060"> 10:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">class</span> Collection</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum11" style="color: #606060"> 11:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum12" style="color: #606060"> 12:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> each(List
list, Acceptor acc)</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum13" style="color: #606060"> 13:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum14" style="color: #606060"> 14:</span>
              <span style="color: #0000ff">for</span> (Object
o : list)</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum15" style="color: #606060"> 15:</span> acc.each(o);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum16" style="color: #606060"> 16:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum17" style="color: #606060"> 17:</span> }</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Where using it would look like this:
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum1" style="color: #606060"> 1:</span>
              <span style="color: #0000ff">import</span> com.tedneward.util.*;</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum2" style="color: #606060"> 2:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum3" style="color: #606060"> 3:</span> List
personList = ...;</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum4" style="color: #606060"> 4:</span> Collection.each(<span style="color: #0000ff">new</span> Accpetor()
{</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum5" style="color: #606060"> 5:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">void</span> each(Object
person) {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum6" style="color: #606060"> 6:</span> System.out.println(<span style="color: #006080">"Found
person "</span> + person + <span style="color: #006080">", isn't that nice?"</span>);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum7" style="color: #606060"> 7:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum8" style="color: #606060"> 8:</span> });</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Is it <em>quite</em> as nice or as clean as using it from a language that has first-class
support for anonymous local functions? No, but slowly migrating over to this style
has a couple of definitive effects, most notably that you will start grooming the
rest of your team (who may be reluctant to pick up these new languages) towards the
new ideas that will be present in Groovy, and when they finally do see them (as they
will, eventually, unless they hide under rocks on a daily basis), they will realize
what's going on here that much more quickly, and start adding their voices to the
call to start using (J/Iron)Ruby/Groovy for certain things in the codebase you support.
</p>
        <p>
(By the way, this is <em>so</em> much easier to do in C# 2.0, thanks to generics,
static classes and anonymous delegates...
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum1" style="color: #606060"> 1:</span>
              <span style="color: #0000ff">namespace</span> TedNeward.Util</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum2" style="color: #606060"> 2:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum3" style="color: #606060"> 3:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">delegate</span>
              <span style="color: #0000ff">void</span> EachProc&lt;T&gt;(T
obj);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum4" style="color: #606060"> 4:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">class</span> Collection</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum5" style="color: #606060"> 5:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum6" style="color: #606060"> 6:</span>
              <span style="color: #0000ff">public</span>
              <span style="color: #0000ff">static</span>
              <span style="color: #0000ff">void</span> each(ArrayList
list, EachProc proc)</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum7" style="color: #606060"> 7:</span> {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum8" style="color: #606060"> 8:</span>
              <span style="color: #0000ff">foreach</span> (Object
o <span style="color: #0000ff">in</span> list)</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum9" style="color: #606060"> 9:</span> proc(o);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum10" style="color: #606060"> 10:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum11" style="color: #606060"> 11:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum12" style="color: #606060"> 12:</span> }</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum13" style="color: #606060"> 13:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum14" style="color: #606060"> 14:</span>
              <span style="color: #008000">//
...</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum15" style="color: #606060"> 15:</span>  </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum16" style="color: #606060"> 16:</span> ArrayList
personList = ...;</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum17" style="color: #606060"> 17:</span> Collection.each(list, <span style="color: #0000ff">delegate</span>(Object
person) {</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum18" style="color: #606060"> 18:</span> System.Console.WriteLine(<span style="color: #006080">"Found
"</span> + person + <span style="color: #006080">", isn't that nice?"</span>);</pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum19" style="color: #606060"> 19:</span> });</pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
... though the collection classes in the .NET FCL are nowhere near as nicely designed
as those in the Java Collections library, IMHO. C# programmers take note: spend at
least a week studying the Java Collections API.)
</p>
        <p>
 
</p>
        <p>
This, then, opens the much harder question of, "Which language?" Without trying to
infer any sort of order or importance, here's a list of languages to consider, with
URLs where applicable; I invite your own suggestions, by the way, as I'm sure there's
a lot of languages I <em>don't</em> know about, and quite frankly, would love to.
The "current hotness" is to learn the languages marked in <strong>bold</strong>, so
if you want to be daring and different, try one of those that isn't. (I've provided
some links, but honestly it's kind of tiring to put all of them in; just remember
that Google is your friend, and you should be OK. :-) )
</p>
        <ul>
          <li>
Visual Basic. Yes, as in Visual Basic--if you haven't played with dynamic languages
before, try turning "Option Strict Off", write some code, and see how interacting
with the .NET FCL suddenly changes into a duck-typed scenario. If you're really curious,
have a look at the generated code in Reflector or ILDasm, and notice how the generated
code looks a lot like the generated JVM code from other dynamic languages on an execution
environment, a la Groovy. 
</li>
          <li>
            <a href="http://www.ruby-lang.org/en/">Ruby</a> (<a href="http://jruby.codehaus.org/">JRuby</a>, <a href="http://www.ironruby.net/">IronRuby</a>): 
</li>
          <li>
            <strong>
              <a href="http://groovy.codehaus.org">Groovy</a>
            </strong>: Some call this "javac
2.0"; I'm not sure it merits <em>that</em> title, or the assumption of the mantle
of "King of the JVM" that would seem to go with that title, but the fact is, Groovy's
a useful language. 
</li>
          <li>
            <strong>
              <a href="http://www.scala-lang.org">Scala</a>
            </strong>: A "SCAlable LAnguage"
for the JVM (and CLR, though that feature has been left to the community to support),
incorporating both object-oriented and functional concepts, plus a few new ideas,
into a single package. I'm obviously bullish on Scala, given the talks and articles
I've done on it. 
</li>
          <li>
            <strong>F#</strong>: Originally OCaml-on-the-CLR, now F# is starting to take on a
personality of its own as Microsoft productizes it. Like Scala and Erlang, F# will
be immediately applicable in concurrency scenarios, I think. I'm obviously bullish
on F#, given the talks, articles, and book I'm doing on it. 
</li>
          <li>
            <strong>Erlang</strong>: Functional language with a strong emphasis on parallel processing,
scalability, and concurrency. 
</li>
          <li>
Perl: People will perhaps be surprised I say this, given my public dislike of Perl's
syntax, but I think every programmer should learn Perl, and decide for themselves
what's right and what's wrong about Perl. Besides, there's clearly no argument that
Perl is one of the power tools in every *nix sysadmin's toolbox. 
</li>
          <li>
Python: Again, given my dislike of Python's significant whitespace, my suggestion
to learn it here may surprise some, but Python seems to be stepping into Perl's shoes
as the sysadmin language tool of choice, and frankly, lots of people <em>like</em> the
significant whitespace, since that's how they format their code anyway. 
</li>
          <li>
C++: The grandaddy of them all, in some ways; if you've never looked at C++ before,
you should, particularly what they're doing with templates in the Boost library. As
Scott Meyers once put it, "We're a long way from Stack&lt;T&gt;!" 
</li>
          <li>
            <a href="http://www.digitalmars.com/d/">D</a>: Walter Bright's native-compiling garbage-collected
successor to C++/Java/C#. 
</li>
          <li>
            <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/chapter_1_section_1.html">Objective-C</a> (part
of gcc): Great "other" object-oriented C-based language that never gathered the kind
of attention C++ did, yet ended up making its mark on the industry thanks to Steve
Jobs' love of the language and its incorporation into the NeXT (and later, Mac OS
X) toolchain. Obj-C is a message-passing object language, which has some interesting
implications in its own right. 
</li>
          <li>
Common Lisp (<a href="http://www.sbcl.org/">Steel Bank Common Lisp</a>): What happens
when you create a language that holds as a core principle that the language should
hold no clear delineation between "code" and "data"? Or that the syntactic expression
of the language should be accessible from within that langauge? You get Lisp, and
if you're not sure what I'm talking about, pick up a Lisp or a Scheme implementation
and start experimenting. 
</li>
          <li>
Scheme (<a href="http://www.plt-scheme.org/">PLT Scheme</a>, <a href="http://sisc-scheme.org/">SISC</a>):
Scheme is one of the earliest dialects of Lisp, and much of the same syntactic flexibility
and power of Lisp is in Scheme, as well. While the syntaxes are usually not directly
interchangeable, they're close enough that learning one is usually enough. 
</li>
          <li>
            <a href="http://clojure.org">Clojure</a>: Rich Hickey (who also built "dotLisp" for
the CLR) has done an amazing job of bringing Lisp to the JVM, including a few new
ideas, such as some functional concepts and an implementation of software transactional
memory, among other things. 
</li>
          <li>
            <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a> (<a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm">E4X</a>, <a href="http://www.mozilla.org/rhino/">Rhino</a>, <a href="http://www.ecmascript.org/">ES4</a>):
If you've never looking at JavaScript <em>outside</em> of the browser, you're in for
a surprise--as <a href="http://www.vanderburg.org/Blog">Glenn Vanderburg</a> put it
during one of his NFJS talks, "There's a real programming language in there!". I'm
particularly fond of E4X, which integrates XML as a native primitive type, and the
Rhino implementation fully supports it, which makes it attractive to use as an XML
services implementation language. 
</li>
          <li>
Haskell (<a href="http://jaskell.codehaus.org">Jaskell</a>): One of the original functional
languages. Learning this will give a programmer a leg up on the functional concepts
that are creeping into other environments. Jaskell is an implementation of Haskell
on the JVM, and they've taken the concept of functional further, creating a build
system ("Neptune") on top of Jaskell + Ant, to yield a syntax that's... well... more
Haskellian... for building Java projects. (Whether it's better/cleaner than Ant is
debatable, but it certainly makes clear the functional nature of build scripts.) 
</li>
          <li>
ML: Another of the original functional languages. Probably don't need to learn this
if you learn Haskell, but hey, it can't hurt. 
</li>
          <li>
            <a href="http://www.heron-language.com/">Heron</a>: Heron is interesting because it
looks to take on more of the modeling aspects of programming directly into the language,
such as state transitions, which is definitely a novel idea. I'm eagerly looking forward
to future drops. (I'm not so interested in the graphical design mode, or the idea
of "executable UML", but I think there's a vein of interesting ideas here that could
be mined for other languages that aren't quite so lofty in scope.) 
</li>
          <li>
HaXe: A functional language that compiles to three different target platforms: its
own (Neko), Flash, and/or Javascript (for use in Web DOMs). 
</li>
          <li>
            <a href="http://labs.businessobjects.com/cal/">CAL</a>: A JVM-based statically-typed
language from the folks who bring you Crystal Reports. 
</li>
          <li>
            <a href="http://www.erights.org/">E</a>: An interesting tack on distributed systems
and security. Not sure if it's production-ready, but it's definitely an eye-opener
to look at. 
</li>
          <li>
            <a href="http://www.swi-prolog.org/">Prolog</a>: A language built around the idea
of logic and logical inference. Would love to see this in play as a "rules engine"
in a production system. 
</li>
          <li>
            <a href="http://nemerle.org/Main_Page">Nemerle</a>: A CLR-based language with functional
syntax and semantics, and semantic macros, similar to what we see in Lisp/Scheme. 
</li>
          <li>
            <a href="http://nice.sourceforge.net/language.html">Nice</a>: A JVM-based language
that permits multi-dispatch methods, sometimes known as multimethods. 
</li>
          <li>
OCaml: An object-functional fusion that was the immediate predecessor of F#. The HaXe
and MTASC compilers are both built in OCaml, and frankly, it's in a startlingly small
number of lines of code, highlighting how appropriate functional languages are for
building compilers and interpreters. 
</li>
          <li>
Smalltalk (<a href="http://www.squeak.org">Squeak</a>, VisualWorks, Strongtalk): Smalltalk
was widely-known as "the O-O language that all the C guys turned to in order to learn
how to build object-oriented programs", but very few people at the time understood
that Smalltalk was wildly different because of its message-passing and loosely/un-typed
semantics. Now we know better (I hope). Have a look. 
</li>
          <li>
TCL (Jacl): Tool Command Language, a procedural scripting language that has some nice
embedding capabilities. I'd be curious to try putting a TCL-based language in the
hands of end users to see if it was a good DSL base. The Jacl implementation is built
on top of the JVM. 
</li>
          <li>
Forth: The original (near as I can tell) stack-based language, in which all execution
happens on an execution stack, not unlike what we see in the JVM or CLR. Given how
much Lisp has made out of the "atoms and lists" concept, I'm curious if Forth's stack-based
approach yields a similar payoff. 
</li>
          <li>
            <a href="http://www.lua.org">Lua</a>: Dynamically-typed language that lives to be
embedded; known for its biggest embedder's popularity: World of Warcraft, along with
several other games/game engines. A great demonstration of the power of embedding
a language into an engine/environment to allow users to create emergent behavior. 
</li>
          <li>
            <a href="http://www.fandev.org">Fan</a>: Another language that seeks to incorporate
both static and dynamic typing, running on top of both the JVM or the CLR. 
</li>
          <li>
            <a href="http://factorcode.org/links.fhtml">Factor</a>: I'm curious about Factor because
it's another stack-based language, with a lot of inspiration from some of the other
languages on this list. 
</li>
          <li>
            <a href="http://boo.codehaus.org/">Boo</a>: A Python-inspired CLR language that Ayende
likes for domain-specific languages. 
</li>
          <li>
            <a href="http://www.cobra-language.org">Cobra</a>: A Python-inspired language that
seeks to encompass <em>both</em> static <em>and</em> dynamic typing into one language.
Fascinating stuff. 
</li>
          <li>
            <a href="http://slate.tunes.org/">Slate</a>: A "prototype-based object-oriented programming
language based on Self, CLOS, and Smalltalk-80." Apparently on hold due to loss of
interest from the founder, last release was 0.3.5 in August of 2005. 
</li>
          <li>
            <a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html">Joy</a>: Factor's primary
inspiration, another stack-based language. 
</li>
          <li>
            <a href="http://mythago.net/language.html">Raven</a>: A scripting language that "rips
off" from Python, Forth, Perl, and the creator's own head. 
</li>
          <li>
            <a href="http://www.canonware.com/onyx/">Onyx</a>: "Onyx is a powerful stack-based,
multi-threaded, interpreted, general purpose programming language similar to PostScript.
It can be embedded as an extension language similarly to ficl (Forth), guile (scheme),
librep (lisp dialect), s-lang, Lua, and Tcl." 
</li>
          <li>
            <a href="http://lolcode.com/specs/1.2">LOLCode</a>: No, you won't use LOLcode on a
project any time soon, but LOLCode has had so many different implementations of it
built, it's a great practice tool towards building your own languages, a la DSLs.
LOLcode has all the basic components a language would use, so if you can build a parser,
AST and execution engine (either interpreter or compiler) for LOLcode, then you've
got the basic skills in place to build an external DSL.</li>
        </ul>
        <p>
There's more, of course, but hopefully there's something in this list to keep you
busy for a while. Remember to send me your favorite new-language links, and I'll add
them to the list as seems appropriate. 
</p>
        <p>
Happy hacking!
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=05f327f7-95ec-413f-8d41-74ad6c5a4e58" />
        <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>Polyglot Plurality</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,05f327f7-95ec-413f-8d41-74ad6c5a4e58.aspx</guid>
      <link>http://blogs.tedneward.com/2008/07/03/Polyglot+Plurality.aspx</link>
      <pubDate>Thu, 03 Jul 2008 02:13:10 GMT</pubDate>
      <description>&lt;p&gt;
The Pragmatic Programmer says, "Learn a new language every year". This is great advice,
not just because it puts new tools into your mental toolbox that you can pull out
on various occasions to get a job done, but also because it opens your mind to new
ideas and new concepts that will filter their way into your code even without explicit
language support. For example, suppose you've looked at (J/Iron)Ruby or Groovy, and
come to like the "internal iterator" approach as a way of simplifying moving across
a collection of objects in a uniform way; for political and cultural reasons, though,
you can't write code in anything but Java. You're frustrated, because local anonymous
functions (also commonly--and, I think, mistakenly--called &lt;em&gt;closures&lt;/em&gt;) are
not a first-class concept in Java. Then, you later look at Haskell/ML/Scala/F#, which
makes heavy use of what Java programmers would call "static methods" to carry out
operations, and realize that this could, in fact, be adapted to Java to give you the
"internal iteration" concept over the Java Collections:
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;package&lt;/span&gt; com.tedneward.util;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt; 2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;import&lt;/span&gt; java.util.*;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt; 4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; Acceptor&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt; 6:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; each(Object
obj);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt; 8:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt; 9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt; 10:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Collection&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt; 11:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt; 12:&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; each(List
list, Acceptor acc)&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt; 13:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt; 14:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (Object
o : list)&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt; 15:&lt;/span&gt; acc.each(o);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt; 16:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt; 17:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Where using it would look like this:
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;import&lt;/span&gt; com.tedneward.util.*;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt; 2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt; 3:&lt;/span&gt; List
personList = ...;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt; 4:&lt;/span&gt; Collection.each(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Accpetor()
{&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; each(Object
person) {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt; 6:&lt;/span&gt; System.out.println(&lt;span style="color: #006080"&gt;"Found
person "&lt;/span&gt; + person + &lt;span style="color: #006080"&gt;", isn't that nice?"&lt;/span&gt;);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt; 7:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt; 8:&lt;/span&gt; });&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Is it &lt;em&gt;quite&lt;/em&gt; as nice or as clean as using it from a language that has first-class
support for anonymous local functions? No, but slowly migrating over to this style
has a couple of definitive effects, most notably that you will start grooming the
rest of your team (who may be reluctant to pick up these new languages) towards the
new ideas that will be present in Groovy, and when they finally do see them (as they
will, eventually, unless they hide under rocks on a daily basis), they will realize
what's going on here that much more quickly, and start adding their voices to the
call to start using (J/Iron)Ruby/Groovy for certain things in the codebase you support.
&lt;/p&gt;
&lt;p&gt;
(By the way, this is &lt;em&gt;so&lt;/em&gt; much easier to do in C# 2.0, thanks to generics,
static classes and anonymous delegates...
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt; TedNeward.Util&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt; 2:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&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; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; EachProc&amp;lt;T&amp;gt;(T
obj);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt; 4:&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;class&lt;/span&gt; Collection&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt; 5:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt; 6:&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; each(ArrayList
list, EachProc proc)&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt; 7:&lt;/span&gt; {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt; 8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (Object
o &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; list)&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt; 9:&lt;/span&gt; proc(o);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt; 10:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt; 11:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt; 12:&lt;/span&gt; }&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt; 13:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt; 14:&lt;/span&gt; &lt;span style="color: #008000"&gt;//
...&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt; 15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt; 16:&lt;/span&gt; ArrayList
personList = ...;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt; 17:&lt;/span&gt; Collection.each(list, &lt;span style="color: #0000ff"&gt;delegate&lt;/span&gt;(Object
person) {&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum18" style="color: #606060"&gt; 18:&lt;/span&gt; System.Console.WriteLine(&lt;span style="color: #006080"&gt;"Found
"&lt;/span&gt; + person + &lt;span style="color: #006080"&gt;", isn't that nice?"&lt;/span&gt;);&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum19" style="color: #606060"&gt; 19:&lt;/span&gt; });&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
... though the collection classes in the .NET FCL are nowhere near as nicely designed
as those in the Java Collections library, IMHO. C# programmers take note: spend at
least a week studying the Java Collections API.)
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
This, then, opens the much harder question of, "Which language?" Without trying to
infer any sort of order or importance, here's a list of languages to consider, with
URLs where applicable; I invite your own suggestions, by the way, as I'm sure there's
a lot of languages I &lt;em&gt;don't&lt;/em&gt; know about, and quite frankly, would love to.
The "current hotness" is to learn the languages marked in &lt;strong&gt;bold&lt;/strong&gt;, so
if you want to be daring and different, try one of those that isn't. (I've provided
some links, but honestly it's kind of tiring to put all of them in; just remember
that Google is your friend, and you should be OK. :-) )
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Visual Basic. Yes, as in Visual Basic--if you haven't played with dynamic languages
before, try turning "Option Strict Off", write some code, and see how interacting
with the .NET FCL suddenly changes into a duck-typed scenario. If you're really curious,
have a look at the generated code in Reflector or ILDasm, and notice how the generated
code looks a lot like the generated JVM code from other dynamic languages on an execution
environment, a la Groovy. 
&lt;li&gt;
&lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; (&lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;, &lt;a href="http://www.ironruby.net/"&gt;IronRuby&lt;/a&gt;): 
&lt;li&gt;
&lt;strong&gt;&lt;a href="http://groovy.codehaus.org"&gt;Groovy&lt;/a&gt;&lt;/strong&gt;: Some call this "javac
2.0"; I'm not sure it merits &lt;em&gt;that&lt;/em&gt; title, or the assumption of the mantle
of "King of the JVM" that would seem to go with that title, but the fact is, Groovy's
a useful language. 
&lt;li&gt;
&lt;strong&gt;&lt;a href="http://www.scala-lang.org"&gt;Scala&lt;/a&gt;&lt;/strong&gt;: A "SCAlable LAnguage"
for the JVM (and CLR, though that feature has been left to the community to support),
incorporating both object-oriented and functional concepts, plus a few new ideas,
into a single package. I'm obviously bullish on Scala, given the talks and articles
I've done on it. 
&lt;li&gt;
&lt;strong&gt;F#&lt;/strong&gt;: Originally OCaml-on-the-CLR, now F# is starting to take on a
personality of its own as Microsoft productizes it. Like Scala and Erlang, F# will
be immediately applicable in concurrency scenarios, I think. I'm obviously bullish
on F#, given the talks, articles, and book I'm doing on it. 
&lt;li&gt;
&lt;strong&gt;Erlang&lt;/strong&gt;: Functional language with a strong emphasis on parallel processing,
scalability, and concurrency. 
&lt;li&gt;
Perl: People will perhaps be surprised I say this, given my public dislike of Perl's
syntax, but I think every programmer should learn Perl, and decide for themselves
what's right and what's wrong about Perl. Besides, there's clearly no argument that
Perl is one of the power tools in every *nix sysadmin's toolbox. 
&lt;li&gt;
Python: Again, given my dislike of Python's significant whitespace, my suggestion
to learn it here may surprise some, but Python seems to be stepping into Perl's shoes
as the sysadmin language tool of choice, and frankly, lots of people &lt;em&gt;like&lt;/em&gt; the
significant whitespace, since that's how they format their code anyway. 
&lt;li&gt;
C++: The grandaddy of them all, in some ways; if you've never looked at C++ before,
you should, particularly what they're doing with templates in the Boost library. As
Scott Meyers once put it, "We're a long way from Stack&amp;lt;T&amp;gt;!" 
&lt;li&gt;
&lt;a href="http://www.digitalmars.com/d/"&gt;D&lt;/a&gt;: Walter Bright's native-compiling garbage-collected
successor to C++/Java/C#. 
&lt;li&gt;
&lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/chapter_1_section_1.html"&gt;Objective-C&lt;/a&gt; (part
of gcc): Great "other" object-oriented C-based language that never gathered the kind
of attention C++ did, yet ended up making its mark on the industry thanks to Steve
Jobs' love of the language and its incorporation into the NeXT (and later, Mac OS
X) toolchain. Obj-C is a message-passing object language, which has some interesting
implications in its own right. 
&lt;li&gt;
Common Lisp (&lt;a href="http://www.sbcl.org/"&gt;Steel Bank Common Lisp&lt;/a&gt;): What happens
when you create a language that holds as a core principle that the language should
hold no clear delineation between "code" and "data"? Or that the syntactic expression
of the language should be accessible from within that langauge? You get Lisp, and
if you're not sure what I'm talking about, pick up a Lisp or a Scheme implementation
and start experimenting. 
&lt;li&gt;
Scheme (&lt;a href="http://www.plt-scheme.org/"&gt;PLT Scheme&lt;/a&gt;, &lt;a href="http://sisc-scheme.org/"&gt;SISC&lt;/a&gt;):
Scheme is one of the earliest dialects of Lisp, and much of the same syntactic flexibility
and power of Lisp is in Scheme, as well. While the syntaxes are usually not directly
interchangeable, they're close enough that learning one is usually enough. 
&lt;li&gt;
&lt;a href="http://clojure.org"&gt;Clojure&lt;/a&gt;: Rich Hickey (who also built "dotLisp" for
the CLR) has done an amazing job of bringing Lisp to the JVM, including a few new
ideas, such as some functional concepts and an implementation of software transactional
memory, among other things. 
&lt;li&gt;
&lt;a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"&gt;ECMAScript&lt;/a&gt; (&lt;a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm"&gt;E4X&lt;/a&gt;, &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt;, &lt;a href="http://www.ecmascript.org/"&gt;ES4&lt;/a&gt;):
If you've never looking at JavaScript &lt;em&gt;outside&lt;/em&gt; of the browser, you're in for
a surprise--as &lt;a href="http://www.vanderburg.org/Blog"&gt;Glenn Vanderburg&lt;/a&gt; put it
during one of his NFJS talks, "There's a real programming language in there!". I'm
particularly fond of E4X, which integrates XML as a native primitive type, and the
Rhino implementation fully supports it, which makes it attractive to use as an XML
services implementation language. 
&lt;li&gt;
Haskell (&lt;a href="http://jaskell.codehaus.org"&gt;Jaskell&lt;/a&gt;): One of the original functional
languages. Learning this will give a programmer a leg up on the functional concepts
that are creeping into other environments. Jaskell is an implementation of Haskell
on the JVM, and they've taken the concept of functional further, creating a build
system ("Neptune") on top of Jaskell + Ant, to yield a syntax that's... well... more
Haskellian... for building Java projects. (Whether it's better/cleaner than Ant is
debatable, but it certainly makes clear the functional nature of build scripts.) 
&lt;li&gt;
ML: Another of the original functional languages. Probably don't need to learn this
if you learn Haskell, but hey, it can't hurt. 
&lt;li&gt;
&lt;a href="http://www.heron-language.com/"&gt;Heron&lt;/a&gt;: Heron is interesting because it
looks to take on more of the modeling aspects of programming directly into the language,
such as state transitions, which is definitely a novel idea. I'm eagerly looking forward
to future drops. (I'm not so interested in the graphical design mode, or the idea
of "executable UML", but I think there's a vein of interesting ideas here that could
be mined for other languages that aren't quite so lofty in scope.) 
&lt;li&gt;
HaXe: A functional language that compiles to three different target platforms: its
own (Neko), Flash, and/or Javascript (for use in Web DOMs). 
&lt;li&gt;
&lt;a href="http://labs.businessobjects.com/cal/"&gt;CAL&lt;/a&gt;: A JVM-based statically-typed
language from the folks who bring you Crystal Reports. 
&lt;li&gt;
&lt;a href="http://www.erights.org/"&gt;E&lt;/a&gt;: An interesting tack on distributed systems
and security. Not sure if it's production-ready, but it's definitely an eye-opener
to look at. 
&lt;li&gt;
&lt;a href="http://www.swi-prolog.org/"&gt;Prolog&lt;/a&gt;: A language built around the idea
of logic and logical inference. Would love to see this in play as a "rules engine"
in a production system. 
&lt;li&gt;
&lt;a href="http://nemerle.org/Main_Page"&gt;Nemerle&lt;/a&gt;: A CLR-based language with functional
syntax and semantics, and semantic macros, similar to what we see in Lisp/Scheme. 
&lt;li&gt;
&lt;a href="http://nice.sourceforge.net/language.html"&gt;Nice&lt;/a&gt;: A JVM-based language
that permits multi-dispatch methods, sometimes known as multimethods. 
&lt;li&gt;
OCaml: An object-functional fusion that was the immediate predecessor of F#. The HaXe
and MTASC compilers are both built in OCaml, and frankly, it's in a startlingly small
number of lines of code, highlighting how appropriate functional languages are for
building compilers and interpreters. 
&lt;li&gt;
Smalltalk (&lt;a href="http://www.squeak.org"&gt;Squeak&lt;/a&gt;, VisualWorks, Strongtalk): Smalltalk
was widely-known as "the O-O language that all the C guys turned to in order to learn
how to build object-oriented programs", but very few people at the time understood
that Smalltalk was wildly different because of its message-passing and loosely/un-typed
semantics. Now we know better (I hope). Have a look. 
&lt;li&gt;
TCL (Jacl): Tool Command Language, a procedural scripting language that has some nice
embedding capabilities. I'd be curious to try putting a TCL-based language in the
hands of end users to see if it was a good DSL base. The Jacl implementation is built
on top of the JVM. 
&lt;li&gt;
Forth: The original (near as I can tell) stack-based language, in which all execution
happens on an execution stack, not unlike what we see in the JVM or CLR. Given how
much Lisp has made out of the "atoms and lists" concept, I'm curious if Forth's stack-based
approach yields a similar payoff. 
&lt;li&gt;
&lt;a href="http://www.lua.org"&gt;Lua&lt;/a&gt;: Dynamically-typed language that lives to be
embedded; known for its biggest embedder's popularity: World of Warcraft, along with
several other games/game engines. A great demonstration of the power of embedding
a language into an engine/environment to allow users to create emergent behavior. 
&lt;li&gt;
&lt;a href="http://www.fandev.org"&gt;Fan&lt;/a&gt;: Another language that seeks to incorporate
both static and dynamic typing, running on top of both the JVM or the CLR. 
&lt;li&gt;
&lt;a href="http://factorcode.org/links.fhtml"&gt;Factor&lt;/a&gt;: I'm curious about Factor because
it's another stack-based language, with a lot of inspiration from some of the other
languages on this list. 
&lt;li&gt;
&lt;a href="http://boo.codehaus.org/"&gt;Boo&lt;/a&gt;: A Python-inspired CLR language that Ayende
likes for domain-specific languages. 
&lt;li&gt;
&lt;a href="http://www.cobra-language.org"&gt;Cobra&lt;/a&gt;: A Python-inspired language that
seeks to encompass &lt;em&gt;both&lt;/em&gt; static &lt;em&gt;and&lt;/em&gt; dynamic typing into one language.
Fascinating stuff. 
&lt;li&gt;
&lt;a href="http://slate.tunes.org/"&gt;Slate&lt;/a&gt;: A "prototype-based object-oriented programming
language based on Self, CLOS, and Smalltalk-80." Apparently on hold due to loss of
interest from the founder, last release was 0.3.5 in August of 2005. 
&lt;li&gt;
&lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html"&gt;Joy&lt;/a&gt;: Factor's primary
inspiration, another stack-based language. 
&lt;li&gt;
&lt;a href="http://mythago.net/language.html"&gt;Raven&lt;/a&gt;: A scripting language that "rips
off" from Python, Forth, Perl, and the creator's own head. 
&lt;li&gt;
&lt;a href="http://www.canonware.com/onyx/"&gt;Onyx&lt;/a&gt;: "Onyx is a powerful stack-based,
multi-threaded, interpreted, general purpose programming language similar to PostScript.
It can be embedded as an extension language similarly to ficl (Forth), guile (scheme),
librep (lisp dialect), s-lang, Lua, and Tcl." 
&lt;li&gt;
&lt;a href="http://lolcode.com/specs/1.2"&gt;LOLCode&lt;/a&gt;: No, you won't use LOLcode on a
project any time soon, but LOLCode has had so many different implementations of it
built, it's a great practice tool towards building your own languages, a la DSLs.
LOLcode has all the basic components a language would use, so if you can build a parser,
AST and execution engine (either interpreter or compiler) for LOLcode, then you've
got the basic skills in place to build an external DSL.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
There's more, of course, but hopefully there's something in this list to keep you
busy for a while. Remember to send me your favorite new-language links, and I'll add
them to the list as seems appropriate. 
&lt;/p&gt;
&lt;p&gt;
Happy hacking!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=05f327f7-95ec-413f-8d41-74ad6c5a4e58" /&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,05f327f7-95ec-413f-8d41-74ad6c5a4e58.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=ba80e0d6-9926-43d6-9846-2f65daffac45</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,ba80e0d6-9926-43d6-9846-2f65daffac45.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,ba80e0d6-9926-43d6-9846-2f65daffac45.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=ba80e0d6-9926-43d6-9846-2f65daffac45</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As <a href="http://www.pandamonial.com/2008/06/devlink-bus-route.html">Amanda notes</a>,
I'm riding with 46 other folks (and lots of beer) on a bus from Michigan to devLink
in Tennessee, as part of sponsoring the show. (I think she got my language preferences
just a teensy bit mixed up, though.)
</p>
        <p>
Which brings up a related point, actually: Amanda (of "the great F# T-shirt" fame
from TechEd this year) and I are teaming up to do <em>F# In A Nutshell</em> for O'Reilly.
The goal is to have a Rough Cut ready (just the language parts) by the time F# goes
CTP this summer or fall, so we're on an accelerated schedule. If you don't see much
from me via the blog for a while, now you know why. :-) Once that's done, I'm going
dark on a Scala book to follow--details to follow when that contract is nailed down.
</p>
        <p>
Meanwhile.... As she suggests, the bus will likely be filled with lots of lively debate.
The nice thing about having a technical debate with drunk geeks on a bus traveling
down the highway at speed is that it's actually pretty easy to win the debate, if
you really want to:
</p>
        <blockquote>
          <p>
            <em>"You are such an idiot! Object-relashunal mappers are just... *burp* so cool!
Why can't you see that?"</em>
          </p>
          <p>
            <em>"Idiot, am I? I demand satisfaction! Step outside, sir!"</em>
          </p>
          <p>
            <em>"Fine, you--" WHOOSH ... THUMP-THUMP....</em>
          </p>
          <p>
            <em>"Next?"</em>
          </p>
        </blockquote>
        <p>
I'm looking forward to this. :-)
</p>
        <blockquote>
          <p>
            <em>Editor's note: (Contact Amanda if you're interested in participating <u>on the
devLink bus</u>, not the book. Thanks for the interest, but we aren't soliciting co-authors.
We think we have this one pretty well covered, but we're always interested in reviewers--for
that, you can contact either of us.)</em>
          </p>
        </blockquote>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=ba80e0d6-9926-43d6-9846-2f65daffac45" />
        <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>Let the Great Language Wars commence....</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,ba80e0d6-9926-43d6-9846-2f65daffac45.aspx</guid>
      <link>http://blogs.tedneward.com/2008/06/24/Let+The+Great+Language+Wars+Commence.aspx</link>
      <pubDate>Tue, 24 Jun 2008 16:56:39 GMT</pubDate>
      <description>&lt;p&gt;
As &lt;a href="http://www.pandamonial.com/2008/06/devlink-bus-route.html"&gt;Amanda notes&lt;/a&gt;,
I'm riding with 46 other folks (and lots of beer) on a bus from Michigan to devLink
in Tennessee, as part of sponsoring the show. (I think she got my language preferences
just a teensy bit mixed up, though.)
&lt;/p&gt;
&lt;p&gt;
Which brings up a related point, actually: Amanda (of "the great F# T-shirt" fame
from TechEd this year) and I are teaming up to do &lt;em&gt;F# In A Nutshell&lt;/em&gt; for O'Reilly.
The goal is to have a Rough Cut ready (just the language parts) by the time F# goes
CTP this summer or fall, so we're on an accelerated schedule. If you don't see much
from me via the blog for a while, now you know why. :-) Once that's done, I'm going
dark on a Scala book to follow--details to follow when that contract is nailed down.
&lt;/p&gt;
&lt;p&gt;
Meanwhile.... As she suggests, the bus will likely be filled with lots of lively debate.
The nice thing about having a technical debate with drunk geeks on a bus traveling
down the highway at speed is that it's actually pretty easy to win the debate, if
you really want to:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;"You are such an idiot! Object-relashunal mappers are just... *burp* so cool!
Why can't you see that?"&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;"Idiot, am I? I demand satisfaction! Step outside, sir!"&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;"Fine, you--" WHOOSH ... THUMP-THUMP....&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;"Next?"&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I'm looking forward to this. :-)
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Editor's note: (Contact Amanda if you're interested in participating &lt;u&gt;on the
devLink bus&lt;/u&gt;, not the book. Thanks for the interest, but we aren't soliciting co-authors.
We think we have this one pretty well covered, but we're always interested in reviewers--for
that, you can contact either of us.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=ba80e0d6-9926-43d6-9846-2f65daffac45" /&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,ba80e0d6-9926-43d6-9846-2f65daffac45.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=a00766d9-6994-4611-8bc1-e6b169167949</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,a00766d9-6994-4611-8bc1-e6b169167949.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,a00766d9-6994-4611-8bc1-e6b169167949.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=a00766d9-6994-4611-8bc1-e6b169167949</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html">Steve
Yegge posted the transcript</a> from a talk on dynamic languages that he gave at Stanford.
</p>
        <p>
          <a href="http://beust.com/weblog/archives/000483.html">Cedric Beust posted a response</a> to
Steve's talk, espousing statically-typed languages.
</p>
        <p>
Numerous comments and flamewars erupted, not to mention a Star Wars analogy (which <em>always</em> makes
things more fun).
</p>
        <p>
This is my feeble attempt to play galactic peacemaker. Or at least galactic color
commentary and play-by-play. I have no doubts about its efficacy, and that it will
only fan the flames, for that's how these things work. Still, I feel a certain perverse
pleasure in pretending, so....
</p>
        <p>
Enjoy the carnage that results.
</p>
        <hr />
        <p>
First of all, let me be very honest: I like Steve's talk. I think he does a pretty
good job of representing the negatives and positives of dynamic languages, though
there are obviously places where I'm going to disagree:
</p>
        <ul>
          <li>
            <em>"Because we all know that C++ has some very serious problems, that organizations,
you know, put hundreds of staff years into fixing. Portability across compiler upgrades,
across platforms, I mean the list goes on and on and on. C++ is like an evolutionary
sort of dead-end. But, you know, it's fast, right?"</em> Funny, I doubt Bjarne Stroustrup
or Herb Sutter would agree with the "evolutionary dead-end" statement, but they're
biased, so let's put that aside for a moment. Have organizations put hundreds of staff
years into fixing the problems of C++? Possibly--it would be good to know what Steve
considers the "very serious problems" of C++, because that list he does give (compiler/platform/language
upgrades and portability across platforms) seems problematic regardless of the langauge
or platform you choose--Lord knows we saw that with Java, and Lord knows we see it
with ECMAScript in the browser, too. The larger question should be, can, and does,
the language evolve? Clearly, based on the work in the Boost libraries and the C++0X
standards work, the answer is yes, every bit as much as Java or C#/.NET is, and arguably
much more so than what we're seeing in some of the dynamic languages. C++ is getting
a standardized memory model, which will make a portable threading package possible,
as well as lambda expressions, which is a far cry from the language that <em>I</em> grew
up with. That seems evolutionary to me. What's more, Bjarne has said, point-blank,
that he prefers taking a slow approach to adopting new features or ideas, so that
it can be "done right", and I think that's every bit a fair position to take, regardless
of whether I agree with it or not. (I'd probably wish for a faster adoption curve,
but that's me.) Oh, and if you're thinking that C++'s problems stem from its memory
management approach, you've never written C++ with a garbage collector library. 
</li>
          <li>
            <em>"And so you ask them, why not use, like, D? Or Objective-C. And they say, "well,
what if there's a garbage collection pause?" "</em> Ah, yes, the "we fear garbage
collection" argument. I would <em>hope</em> that Java and C#/.NET have put that particular
debate to rest by now, but in the event that said dragon's not yet slain, let's do
so now: GC <em>does</em> soak up some cycles, but for the most part, for most applications,
the cost is lost in the noise of everything else. As with all things performance related,
however, profile. 
</li>
          <li>
            <em>"And so, you know, their whole argument is based on these fallacious, you know,
sort of almost pseudo-religious... and often it's the case that they're actually based
on things that used to be true, but they're not really true anymore, and we're gonna
get to some of the interesting ones here."</em> Steve, almost <em>all</em> of these
discussions are pseudo-religious in nature. For some reason, programmers like to identify
themselves in terms of the language they use, and that just sets up the religious
nature of the debate from the get-go. 
</li>
          <li>
            <em>"You know how there's Moore's Law, and there are all these conjectures in our
industry that involve, you know, how things work. And one of them is that languages
get replaced every ten years. ... Because that's what was happening up until like
1995. But the barriers to adoption are really high."</em> I can't tell from the transcript
of Steve's talk if this is <em>his</em> opinion, or that this is a conjecture/belief
of the industry; in either case, I thoroughly disagree with this sentiment--the barriers
to entry to create your own language have <em>never</em> been lower than today, and
various elements of research work and available projects just keep making it easier
and easier to do, particularly if you target one of the available execution engines.
Now, granted, if you want your language to look <em>different</em> from the other
languages out there, or if you want to do some seriously cool stuff, yes, there's
a fair amount of work you still have to do... but that's always going to be the case.
As we find ways to make it easier to build what's "cool" today, the definition of
what's "cool" rises in result. (Nowhere is this more clear than in the game industry,
for example.) Moore's Law begets Ballmer's Corollary: <em>User expectations double
every eighteen months, requiring us to use up all that power trying to meet those
expectations with fancier ways of doing things</em>. 
</li>
          <li>
It's a section that's too long to quote directly here, but Steve goes on to talk about
how programmers aren't <em>using</em> these alternative languages, and that if you
even suggest trying to use D or Scala or [fill in the blank], you're going to get <em>"lynched
for trying to use a language that the other engineers don't know. ... And [my intern]
is, like, "well I understand the argument" and I'm like "No, no, no! You've never
been in a company where there's an engineer with a Computer Science degree and ten
years of experience, an architect, who's in your face screaming at you, with spittle
flying on you, because you suggested using, you know... </em><a href="http://www.digitalmars.com/d"><em>D</em></a><em>.
Or </em><a href="http://www.haskell.org/"><em>Haskell</em></a><em>. Or Lisp, or </em><a href="http://www.amazon.com/gp/product/193435600X?ie=UTF8&amp;tag=steveysblogra-20&amp;link_code=wql&amp;camp=212361&amp;creative=380601"><em>Erlang</em></a><em>,
or take your pick." "</em> Steve, with all due respect to your experience, I know
plenty of engineers and companies who <em>are</em> using some of these "alternative"
languages, and they're having some good success. But frankly, if you work in a company
where an architect is "in your face screaming at you, with spittle flying on you",
frankly, it's time to move on, because that company is <em>never</em> going to try
anything new. Period. I don't care if we're talking about languages, Spring, agile
approaches, or trying a new place for lunch today. Companies get into a rut just as
much as individuals do, and if the company doesn't challenge that rut every so often,
they're going to get bypassed. Period, end of story. That doesn't mean trying every
new thing under the sun on your next "mission-critical" project, but for God's sake,
Mr. CTO, do you really want to wait until your competition has bypassed you before
adopting something new? There's a lot of project work that goes on that has room for
some experimentation and experience-gathering before utilizing something on the next
big project. 
</li>
          <li>
            <em>"I made the famously, horribly, career-shatteringly bad mistake of trying to use
Ruby at Google, for this project. ... And I became, very quickly, I mean almost overnight,
the Most Hated Person At Google. And, uh, and I'd have arguments with people about
it, and they'd be like Nooooooo, WHAT IF... And ultimately, you know, ultimately they
actually convinced me that they were right, in the sense that there actually were
a few things. There were some taxes that I was imposing on the systems people, where
they were gonna have to have some maintenance issues that they wouldn't have [otherwise
had]. Those reasons I thought were good ones."</em> Recognizing the cost of deploying
a new platform into the IT sphere is a <em>huge</em> deal that programmers frequently
try to ignore in their zeal to adopt something new, and as a result, IT departments
frequently swing the <em>other</em> way, resisting all change until it becomes inevitable.
This is where running on top of one of the existing execution environments (the JVM
or the CLR in particular) becomes so powerful--the actual deployment platform doesn't
change, and the IT guys remain more or less disconnected from the whole scenario.
This is the principal advantage JRuby and IronPython and Jython and IronRuby will
have over their native-interpreted counterparts. As for maintenance issues, aside
from the "somebody's gonna have to learn this language" tax (which is a real tax but
far less costly, I believe, than most people think it to be), I'm not sure what issues
would crop up--the IT guys don't usually change your Java or C# or Visual Basic code
in production, do they? 
</li>
          <li>
Steve then gets into the discussion about tools around dynamic languages, and I heartily
agree with him: the tool vendors have a much deeper toolchest than we (non-tool vendor
programmers) give them credit for, and they're proving it left and right as IDEs get
better and better for dynamic languages like Groovy and Ruby. In some areas, though,
I think we as developers lean too strongly against our tools, expecting them to be
able to do the thinking <em>for</em> us, and getting all grumpy when they can't or
don't. Granted, I don't want to give up my IntelliJ any time soon, but let's think
about this for a second: if I can't program Java today without IntelliJ, then is that
my fault, the language's fault, the industry's fault, or some combination thereof?
Or is it maybe just a fact of progress? (Would anybody consider building assembly
language in Notepad today? Does that make assembly language <em>wrong</em>? Or just
the wrong tool for the job?) 
</li>
          <li>
Steve's point about how Java IDE's miss the Reflective case is a good one, and one
that every Java programmer should consider. How much of your Java (or C# or C++) code
actually <em>isn't</em> capturable directly in the IDE? 
</li>
          <li>
Steve then goes into the ubiquitous Java-generics rant, and I'll have to admit, he's
got some good points here--why <em>didn't</em> we (Java, though this applies just
as equally to C#) just let the runtime throw the exception when the cast fails, and
otherwise just let things go? My guess is that there's probably some good rationale
that presumes you already accept the necessity of more verbose syntax in exchange
for knowing where the cast might potentially fail, even though there's plenty of other
places in the language where exceptions can be thrown <em>without</em> that verbose
syntax warning you of that fact, array indexers being a big one. One thing I will
point out, however, in what I believe is a refutation of what Steve's suggesting in
this discussion: from my research in the area and my memory about the subject from
way back when, the javac compiler really <em>doesn't</em> do much in the way of optimizations,
and hasn't tried since about JDK 1.1, for the precise reason he points out: the JITter's
going to optimize all this stuff anyway, so it's easier to just relax and let the
JITter do the heavy lifting. 
</li>
          <li>
The discussion about optimizations is interesting, and while I think he glosses over
some issues and hyper-focuses on others, two points stand out, in my mind: performance
hits often come from places you don't expect, and that micro-benchmarks generally
don't prove much of anything. Sometimes that hit will come from the language, and
sometimes that hit will come from something entirely differently. <em>Profile first</em>.
Don't let your intuition get in the way, because your intuition sucks. Mine does,
too, by the way--there's just too many moving parts to be able to keep it all straight
in your head.</li>
        </ul>
        <p>
Steve then launches into a series of Q&amp;A with the audience, but we'll let the
light dim on that stage, and turn our attention over to Cedric's response.
</p>
        <ul>
          <li>
            <em>"... the overall idea is that dynamically typed languages are on the rise and
statically typed languages are on their way out."</em> Actually, the transcript <em>I</em> read
seemed to imply that Steve thought that dynamically typed languages are cool but that
nobody will use them for a variety of reasons, some of which he agreed with. I thoroughly
disagree with Steve's conclusion there, by the way, but so be it ... 
</li>
          <li>
            <em>"I'm happy to be the Luke Skywalker to his Darth Vader. ... Evil shall not prevail."</em> Yes,
let's not let this debate fall into the <em>pseudo</em>-religious category, shall
we? Fully religious debates have <em>such</em> a better track record of success, so
let's just make it "good vs evil", in order to <em>ensure</em> emotions get all neatly
wrapped throughout. Just remember, Cedric, even Satan can quote the Bible... and it
was Jesus telling us that, so if you disagree with anything I say below you must be
some kind of Al-Qaeda terrorist. Or something. 
<ul><li><em>[Editor's note: Oh, shit, he did NOT just call Cedric a terrorist and a Satanist
and invoke the name of Christ in all this. Time to roll out the disclaimer... "Ladies
and gentlemen, the views and opinions expressed in this blog entry...."]</em></li><li><em>[Author's note: For the humor-challenged in the crowd, no I do </em>not<em> think
Cedric is a terrorist. I </em>like<em> Cedric, and hopefully he still likes me, too.
Of course, I have also been accused of being the Antichrist, so what that says about
Cedric I'm not sure.]</em></li></ul></li>
          <li>
Cedric on Scala: 
<ul><li><em>"Have you taken a look at implicits? Seriously? Just when I thought we were not
just done realizing that global variables are bad, but we have actually come up with
better ways to leverage the concept with DI frameworks such as Guice, Scala knocks
the wind out of us with implicits and all our hardly earned knowledge about side effects
is going down the drain again."</em> Umm.... Cedric? One reaction comes to mind here,
and it's best expressed as.... WTF?!? Implicits are not global variables or DI, they're
more a way of doing conversions, a la autoboxing but more flexible. I agree that casual
use of implicits can get you in trouble, but I'd have thought Scala's "there are no
operators just methods with funny names" would be the more disconcerting of the two. 
</li><li><em>"As for pattern matching, it makes me feel as if all the careful data abstraction
that I have built inside my objects in order to isolate them from the unforgiving
world are, again, thrown out of the window because I am now forced to write deconstructors
to expose all this state just so my classes can be put in a statement that doesn't
even have the courtesy to dress up as something that doesn't smell like a switch/case..."</em> I
suppose if you looked at pattern-matching and saw nothing more than a switch/case,
then I'd agree with you, but it turns out that pattern-matching is a lot more powerful
than just being a switch/case. I <em>think</em> what Cedric's opposing is the fact
that pattern-matching can actually bind to variables expressed in the individual match
clauses, which might look like deconstructors exposing state... but that's not the
way they get used, from what I've seen thus far. But, hey, just because the language
offers it, people will use it wrongly, right? So God forbid a language's library should
allow me to, say, execute private methods or access private fields....</li></ul></li>
          <li>
Cedric on the difficulty to impose a non-mainstream language in the industry: <em>"Let
me turn the table on you and imagine that one of your coworkers comes to you and tells
you that he really wants to implement his part of the project in this awesome language
called Draco. How would you react? Well, you're a pragmatic kind of guy and even though
the idea seems wacky, I'm sure you would start by doing some homework (which would
show you that Draco was an awesome language used back in the days on the Amiga). Reading
up on Draco, you realize that it's indeed a very cool language that has some features
that are a good match for the problem at hand. But even as you realize this, you already
know what you need to tell that guy, right? Probably something like "You're out of
your mind, go back to Eclipse and get cranking". And suddenly, you've become *that*
guy. Just because you showed some common sense."</em> If, I suppose, we equate "common
sense" with "thinking the way Cedric does", sure, that makes sense. But you know,
if it turned out that I was writing something that targeted the Amiga, and Draco did,
in fact, give us a huge boost on the competition, and the drawbacks of using Draco
seemed to pale next to the advantages of using it, then... Well, gawrsh, boss, it
jus' might make <em>sense</em> to use 'dis har Draco thang, even tho it ain't Java.
This is called <em>risk mitigation</em>, and frankly, it's something too few companies
go through because they've "standardized" on a language and API set across the company
that's hardly applicable to the problem at hand. Don't get me wrong--you don't want
the opposite extreme, which is total anarchy in the operations center as people use
any and all languages/platforms available to them on a willy-nilly basis, but the
funny thing is, this is a <em>continuum</em>, not a binary switch. This is where languages-on-execution-engines
(like the JVM or CLR) gets such a great win-win condition: IT can just think in terms
of supporting the JVM or CLR, and developers can then think in whatever language they
want, so long it compiles/runs on those platforms. 
</li>
          <li>
Cedric on building tools for dynamic languages: <em>"I still strongly disagree with
that. It is different *and* harder (and in some cases, </em><a href="http://beust.com/weblog/archives/000414.html"><em>impossible</em></a><em>).
Your point regarding the fact that static refactoring doesn't cover 100% of the cases
is well taken, but it's 1) darn close to 100% and 2) getting closer to it much faster
than any dynamic tool ever could. By the way, Java refactorings correcting comments,
XML and property files are getting pretty common these days, but good luck trying
to perform a reliable method renaming in 100 Ruby files."</em> I'm not going to weigh
in here, since I don't write tools for either dynamic or static languages, but watching
what the IntelliJ IDEA guys are doing with Groovy, and what the NetBeans guys are
doing with Ruby, I'm more inclined to believe in what Steve thinks than what Cedric
does. As for the "reliable method renaming in 100 Ruby files", I don't know this for
a fact, but I'll be willing to be that we're a lot closer to that than Cedric thinks
we are. <em>(I'd love to hear comments from somebody neck-deep in the Ruby crowd who's
done this and their experience doing so.)</em></li>
          <li>
Cedric on generics: <em>"I no longer bother trying to understand why complex Generic
examples are so... well, darn complex. Yes, it's pretty darn hard to follow sometimes,
but here are a few points for you to ponder: </em><ul><li><em>90% of the Java programmers (including myself) only ever use Generics for Collections. </em></li><li><em>These same programmers never go as far as nesting two Generic declarations. </em></li><li><em>For API developers and users alike, Generics are a huge progress. </em></li><li><em>Scala still requires you to understand covariance and contravariance (but with
different rules. People seem to say that Scala's rules are simpler, I'm not so sure,
but not interested in finding out for the aforementioned reasons)."</em></li></ul>
Honestly, Cedric, the fact that 90% of the Java programmers are only using generics
for collections doesn't sway me in the slightest. 90% of the world's population doesn't
use Calculus, either, but that doesn't mean that it's not useful, or that we shouldn't
be trying to improve our understanding of it and how to do useful things with it.
After looking at what the C++ community has done with templates (the Boost libraries)
and what .NET is doing with its generic system (LINQ and F# to cite two examples),
I think Java missed a <em>huge</em> opportunity with generics. Type erasure may have
made sense in a world where Java was the only practical language on top of the JVM,
but in a world that's coming to accept Groovy and JRuby and Scala as potential equals
on the JVM, it makes no sense whatsoever. Meanwhile, when thinking about Scala, let's
take careful note that a Scala programmer can go a <em>long</em> way with the langauge
before having to think about covariance, contravariance, upper and lower type bounds,
simpler or not. (For what it's worth, I agree with you, I'm not sure if they're simpler,
either.) 
</li>
          <li>
Cedric on dynamic language performance: <em>"What will keep preventing dynamically
typed languages from displacing statically typed ones in large scale software is not
performance, it's the simple fact that it's impossible to make sense of a giant ball
of typeless source files, which causes automatic refactorings to be unreliable, hence
hardly applicable, which in turn makes developers scared of refactoring. And it's
all downhill from there. Hello bit rot."</em> There's a certain circular logic here--if
we presume that IDEs can't make sense of "typeless source files" (I wasn't aware that <em>any</em> source
file was statically typed, honestly--this must be something Google teaches), then
it follows that refactoring will be impossible or at least unreliable, and thus a
giant ball of them will be unmanageable. I disagree with Cedric's premise--that IDEs
can't make sense of dynamic language code--so therefore I disagree with the entire
logical chain as a result. What I <em>don't</em> disagree with is the implicit presumption
that the larger the dynamic language source base, the harder it is to keep straight
in your head. In fact, I'll even amend that statement further: the larger the source
base (dynamic or otherwise), the harder it is to keep straight in your head. Abstractions
are key to the long-term success of any project, so the language I work with had best
be able to help me create those abstractions, or I'm in trouble once I cross a certain
threshold. That's true regardless of the language: C++, Java, C#, Ruby, or whatever.
That's one of the reasons I'm spending time trying to get my head around Lisp and
Scheme, because those languages were all about building abstractions upon abstractions
upon abstractions, but in libraries, rather than in the language itself, so they could
be swapped out and replaced with something else when the abstractions failed or needed
evolution. 
</li>
          <li>
Cedric on program unmaintainability: <em>"I hate giving anecdotal evidence to support
my points, but that won't stop me from telling a short story that happened to me just
two weeks ago: I found myself in this very predicament when trying to improve a Ruby
program that 1) I just wrote a few days before and 2) is 200 lines long. I was staring
at an object, trying to remember what it does, failing, searching manually in emacs
where it was declared, found it as a "Hash", and then realized I still had no idea
what the darn thing is. You see my point..."</em> Ain't nothing wrong with anecdotal
evidence, Cedric. We all have it, and if we all examine it <em>en masse</em>, some
interesting patterns can emerge. Funny thing is, I've had exactly the same experience
with C++ code, Java code, and C# code. What does that tell you? It tells me that I
probably should have cooked up some better abstractions for those particular snippets,
and that's what I ended up doing. As a matter of fact, I just helped a buddy of mine
untangle some Ruby code to turn it into C#, and despite the fact that he's never written
(or read) a Ruby program in his life, we managed to flip it over to C# in a couple
of hours, including the execution of Ruby code blocks (I <em>love</em> anonymous methods)
stored in a string-keyed hash within an array. And this was Ruby code that neither
of us had ever seen before, much less written it a few days prior. 
</li>
          <li>
Cedric (and Steve) on error messages: <em>"[Steve said] And the weird thing is, I
realized early in my career that I would actually rather have a runtime error than
a compile error. [Cedric responded] You probably already know this, but you drew the
wrong conclusion. You didn't want a runtime error, you wanted a clear error. One that
doesn't lie to you, like CFront (and a lot of C++ compilers even today, I hear) used
to spit in our faces. And once I have a clear error message, I much prefer to have
it as early as possible, thank you very much."</em> Honestly, I agree with Cedric
here: I would much prefer errors <em>before</em> execution, as early as possible,
so that there's less chance of my users finding the errors I haven't found yet. And
I agree that some of the error messages we sometimes get are pretty incomprehensible,
particularly from the C++ compiler during template expansion. But how is that different
from the ubiquitous Java "ClassCastException: Cannot cast Person to Person" that arises
from time to time? Once you know what the message is telling you, it's easy to know
how to fix it, but getting to the point of knowing what the error message is telling
you requires a good working understanding of Java ClassLoaders. Do we really expect
that any tool--static or dynamic, compiler or runtime, is going to be able to produce
error messages that somehow precludes the need to have the necessary background to
understand it? <em>All errors are relative to the context from which they are born.</em> If
you lack that context, the error message, no matter how well-written or phrased, is
useless. 
</li>
          <li>
Cedric on "The dynamic nuclear winter": <em>"[Steve said] And everybody else went
and chased static. And they've been doing it like crazy. And they've, in my opinion,
reached the theoretical bounds of what they can deliver, and it has FAILED. [Cedric
responded] Quite honestly, words fail me here."</em> Wow. Just... wow. I can't agree
with Steve at all, that static(ically typed languages) has FAILED, or that they've
reached the theoretical bounds of what they can deliver, but neither can I say with
complete confidence that statically-typed languages are The Way Forward, either. I
think, for the time, chasing statically-typed languages was the right thing to do,
because for a long time we were in a position where programmer time was cheaper than
computer time; now, I believe that this particular metric has flipped, and that it's
time we started thinking about what the costs of programmer time really are. (Frankly,
I'd love to see a double-blind study on this, but I've no idea how one would carry
that out in a scientific manner.)</li>
        </ul>
        <p>
So.... what's left?
</p>
        <p>
Oh, right: if Steve/Vader is Cedric/Luke's father, then who is Cedric/Luke's sister,
and why is she wearing a copper-wire bikini while strangling the Haskell/ML crowd/Jabba
the Hutt?
</p>
        <p>
Maybe this whole Star Wars analogy thing was a bad idea.
</p>
        <hr />
        <p>
Look, at the end of the day, the whole static-vs-dynamic thing is a red herring. <em>It
doesn't matter</em>. The crucial question is whether or not the language being used
does two things, and how well it does them:
</p>
        <ol>
          <li>
Provide the ability to express the concept in your head, and 
</li>
          <li>
Provide the ability to evolve as the concepts in your head evolve</li>
        </ol>
        <p>
There are certain things that are just impossible to do in C++, for example. I cannot
represent the C++ AST inside the program itself. (Before you jump all over me, C++ers
of the world, take careful note: I'm <em>not</em> saying that C++ cannot represent
an AST, but an AST of <em>itself</em>, at the time it is executing.) This is something
dynamic languages--most notably Lisp, but also other languages, including Ruby--do
pretty well, because they're building the AST at runtime anyway, in order to execute
the code in the first place. <em>Could</em> C++ do this? Perhaps, but the larger question
is, would any self-respecting C++ programmer <em>want</em> to? Look at your average
Ruby program--80% to 90% (the number may vary, but most of the Rubyists I talk to
agree its somewhere in this range) of the program isn't really using the meta-object
capabilities of the language, and is just a "simpler/easier/scarier/unchecked" object
language. Most of the weird-*ss Rubyisms don't show up in your average Ruby program,
but are buried away in some library someplace, and away from the view of the average
Ruby programmer.
</p>
        <p>
Keep the simple things simple, and make the hard things possible. That' should be
the overriding goal of any language, library, or platform.
</p>
        <p>
Erik Meijer coined this idea first, and I like it a lot: Why can't we operate on a
basic principle of "static when we can (or should), dynamic otherwise"? (Reverse that
if it makes you feel better: "dynamic when we can, static otherwise", because the
difference is really only one of gradation. It's also an interesting point for discussion,
just how much of each is necessary/desirable.) Doing this means we get the best of
both worlds, and we can stop this Galactic Civil War before anybody's planet gets
blown up.
</p>
        <p>
'Cuz that would suck.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=a00766d9-6994-4611-8bc1-e6b169167949" />
        <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>Guide you, the Force should</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,a00766d9-6994-4611-8bc1-e6b169167949.aspx</guid>
      <link>http://blogs.tedneward.com/2008/05/19/Guide+You+The+Force+Should.aspx</link>
      <pubDate>Mon, 19 May 2008 04:34:54 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html"&gt;Steve
Yegge posted the transcript&lt;/a&gt; from a talk on dynamic languages that he gave at Stanford.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://beust.com/weblog/archives/000483.html"&gt;Cedric Beust posted a response&lt;/a&gt; to
Steve's talk, espousing statically-typed languages.
&lt;/p&gt;
&lt;p&gt;
Numerous comments and flamewars erupted, not to mention a Star Wars analogy (which &lt;em&gt;always&lt;/em&gt; makes
things more fun).
&lt;/p&gt;
&lt;p&gt;
This is my feeble attempt to play galactic peacemaker. Or at least galactic color
commentary and play-by-play. I have no doubts about its efficacy, and that it will
only fan the flames, for that's how these things work. Still, I feel a certain perverse
pleasure in pretending, so....
&lt;/p&gt;
&lt;p&gt;
Enjoy the carnage that results.
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
First of all, let me be very honest: I like Steve's talk. I think he does a pretty
good job of representing the negatives and positives of dynamic languages, though
there are obviously places where I'm going to disagree:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;"Because we all know that C++ has some very serious problems, that organizations,
you know, put hundreds of staff years into fixing. Portability across compiler upgrades,
across platforms, I mean the list goes on and on and on. C++ is like an evolutionary
sort of dead-end. But, you know, it's fast, right?"&lt;/em&gt; Funny, I doubt Bjarne Stroustrup
or Herb Sutter would agree with the "evolutionary dead-end" statement, but they're
biased, so let's put that aside for a moment. Have organizations put hundreds of staff
years into fixing the problems of C++? Possibly--it would be good to know what Steve
considers the "very serious problems" of C++, because that list he does give (compiler/platform/language
upgrades and portability across platforms) seems problematic regardless of the langauge
or platform you choose--Lord knows we saw that with Java, and Lord knows we see it
with ECMAScript in the browser, too. The larger question should be, can, and does,
the language evolve? Clearly, based on the work in the Boost libraries and the C++0X
standards work, the answer is yes, every bit as much as Java or C#/.NET is, and arguably
much more so than what we're seeing in some of the dynamic languages. C++ is getting
a standardized memory model, which will make a portable threading package possible,
as well as lambda expressions, which is a far cry from the language that &lt;em&gt;I&lt;/em&gt; grew
up with. That seems evolutionary to me. What's more, Bjarne has said, point-blank,
that he prefers taking a slow approach to adopting new features or ideas, so that
it can be "done right", and I think that's every bit a fair position to take, regardless
of whether I agree with it or not. (I'd probably wish for a faster adoption curve,
but that's me.) Oh, and if you're thinking that C++'s problems stem from its memory
management approach, you've never written C++ with a garbage collector library. 
&lt;li&gt;
&lt;em&gt;"And so you ask them, why not use, like, D? Or Objective-C. And they say, "well,
what if there's a garbage collection pause?" "&lt;/em&gt; Ah, yes, the "we fear garbage
collection" argument. I would &lt;em&gt;hope&lt;/em&gt; that Java and C#/.NET have put that particular
debate to rest by now, but in the event that said dragon's not yet slain, let's do
so now: GC &lt;em&gt;does&lt;/em&gt; soak up some cycles, but for the most part, for most applications,
the cost is lost in the noise of everything else. As with all things performance related,
however, profile. 
&lt;li&gt;
&lt;em&gt;"And so, you know, their whole argument is based on these fallacious, you know,
sort of almost pseudo-religious... and often it's the case that they're actually based
on things that used to be true, but they're not really true anymore, and we're gonna
get to some of the interesting ones here."&lt;/em&gt; Steve, almost &lt;em&gt;all&lt;/em&gt; of these
discussions are pseudo-religious in nature. For some reason, programmers like to identify
themselves in terms of the language they use, and that just sets up the religious
nature of the debate from the get-go. 
&lt;li&gt;
&lt;em&gt;"You know how there's Moore's Law, and there are all these conjectures in our
industry that involve, you know, how things work. And one of them is that languages
get replaced every ten years. ... Because that's what was happening up until like
1995. But the barriers to adoption are really high."&lt;/em&gt; I can't tell from the transcript
of Steve's talk if this is &lt;em&gt;his&lt;/em&gt; opinion, or that this is a conjecture/belief
of the industry; in either case, I thoroughly disagree with this sentiment--the barriers
to entry to create your own language have &lt;em&gt;never&lt;/em&gt; been lower than today, and
various elements of research work and available projects just keep making it easier
and easier to do, particularly if you target one of the available execution engines.
Now, granted, if you want your language to look &lt;em&gt;different&lt;/em&gt; from the other
languages out there, or if you want to do some seriously cool stuff, yes, there's
a fair amount of work you still have to do... but that's always going to be the case.
As we find ways to make it easier to build what's "cool" today, the definition of
what's "cool" rises in result. (Nowhere is this more clear than in the game industry,
for example.) Moore's Law begets Ballmer's Corollary: &lt;em&gt;User expectations double
every eighteen months, requiring us to use up all that power trying to meet those
expectations with fancier ways of doing things&lt;/em&gt;. 
&lt;li&gt;
It's a section that's too long to quote directly here, but Steve goes on to talk about
how programmers aren't &lt;em&gt;using&lt;/em&gt; these alternative languages, and that if you
even suggest trying to use D or Scala or [fill in the blank], you're going to get &lt;em&gt;"lynched
for trying to use a language that the other engineers don't know. ... And [my intern]
is, like, "well I understand the argument" and I'm like "No, no, no! You've never
been in a company where there's an engineer with a Computer Science degree and ten
years of experience, an architect, who's in your face screaming at you, with spittle
flying on you, because you suggested using, you know... &lt;/em&gt;&lt;a href="http://www.digitalmars.com/d"&gt;&lt;em&gt;D&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.
Or &lt;/em&gt;&lt;a href="http://www.haskell.org/"&gt;&lt;em&gt;Haskell&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Or Lisp, or &lt;/em&gt;&lt;a href="http://www.amazon.com/gp/product/193435600X?ie=UTF8&amp;amp;tag=steveysblogra-20&amp;amp;link_code=wql&amp;amp;camp=212361&amp;amp;creative=380601"&gt;&lt;em&gt;Erlang&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,
or take your pick." "&lt;/em&gt; Steve, with all due respect to your experience, I know
plenty of engineers and companies who &lt;em&gt;are&lt;/em&gt; using some of these "alternative"
languages, and they're having some good success. But frankly, if you work in a company
where an architect is "in your face screaming at you, with spittle flying on you",
frankly, it's time to move on, because that company is &lt;em&gt;never&lt;/em&gt; going to try
anything new. Period. I don't care if we're talking about languages, Spring, agile
approaches, or trying a new place for lunch today. Companies get into a rut just as
much as individuals do, and if the company doesn't challenge that rut every so often,
they're going to get bypassed. Period, end of story. That doesn't mean trying every
new thing under the sun on your next "mission-critical" project, but for God's sake,
Mr. CTO, do you really want to wait until your competition has bypassed you before
adopting something new? There's a lot of project work that goes on that has room for
some experimentation and experience-gathering before utilizing something on the next
big project. 
&lt;li&gt;
&lt;em&gt;"I made the famously, horribly, career-shatteringly bad mistake of trying to use
Ruby at Google, for this project. ... And I became, very quickly, I mean almost overnight,
the Most Hated Person At Google. And, uh, and I'd have arguments with people about
it, and they'd be like Nooooooo, WHAT IF... And ultimately, you know, ultimately they
actually convinced me that they were right, in the sense that there actually were
a few things. There were some taxes that I was imposing on the systems people, where
they were gonna have to have some maintenance issues that they wouldn't have [otherwise
had]. Those reasons I thought were good ones."&lt;/em&gt; Recognizing the cost of deploying
a new platform into the IT sphere is a &lt;em&gt;huge&lt;/em&gt; deal that programmers frequently
try to ignore in their zeal to adopt something new, and as a result, IT departments
frequently swing the &lt;em&gt;other&lt;/em&gt; way, resisting all change until it becomes inevitable.
This is where running on top of one of the existing execution environments (the JVM
or the CLR in particular) becomes so powerful--the actual deployment platform doesn't
change, and the IT guys remain more or less disconnected from the whole scenario.
This is the principal advantage JRuby and IronPython and Jython and IronRuby will
have over their native-interpreted counterparts. As for maintenance issues, aside
from the "somebody's gonna have to learn this language" tax (which is a real tax but
far less costly, I believe, than most people think it to be), I'm not sure what issues
would crop up--the IT guys don't usually change your Java or C# or Visual Basic code
in production, do they? 
&lt;li&gt;
Steve then gets into the discussion about tools around dynamic languages, and I heartily
agree with him: the tool vendors have a much deeper toolchest than we (non-tool vendor
programmers) give them credit for, and they're proving it left and right as IDEs get
better and better for dynamic languages like Groovy and Ruby. In some areas, though,
I think we as developers lean too strongly against our tools, expecting them to be
able to do the thinking &lt;em&gt;for&lt;/em&gt; us, and getting all grumpy when they can't or
don't. Granted, I don't want to give up my IntelliJ any time soon, but let's think
about this for a second: if I can't program Java today without IntelliJ, then is that
my fault, the language's fault, the industry's fault, or some combination thereof?
Or is it maybe just a fact of progress? (Would anybody consider building assembly
language in Notepad today? Does that make assembly language &lt;em&gt;wrong&lt;/em&gt;? Or just
the wrong tool for the job?) 
&lt;li&gt;
Steve's point about how Java IDE's miss the Reflective case is a good one, and one
that every Java programmer should consider. How much of your Java (or C# or C++) code
actually &lt;em&gt;isn't&lt;/em&gt; capturable directly in the IDE? 
&lt;li&gt;
Steve then goes into the ubiquitous Java-generics rant, and I'll have to admit, he's
got some good points here--why &lt;em&gt;didn't&lt;/em&gt; we (Java, though this applies just
as equally to C#) just let the runtime throw the exception when the cast fails, and
otherwise just let things go? My guess is that there's probably some good rationale
that presumes you already accept the necessity of more verbose syntax in exchange
for knowing where the cast might potentially fail, even though there's plenty of other
places in the language where exceptions can be thrown &lt;em&gt;without&lt;/em&gt; that verbose
syntax warning you of that fact, array indexers being a big one. One thing I will
point out, however, in what I believe is a refutation of what Steve's suggesting in
this discussion: from my research in the area and my memory about the subject from
way back when, the javac compiler really &lt;em&gt;doesn't&lt;/em&gt; do much in the way of optimizations,
and hasn't tried since about JDK 1.1, for the precise reason he points out: the JITter's
going to optimize all this stuff anyway, so it's easier to just relax and let the
JITter do the heavy lifting. 
&lt;li&gt;
The discussion about optimizations is interesting, and while I think he glosses over
some issues and hyper-focuses on others, two points stand out, in my mind: performance
hits often come from places you don't expect, and that micro-benchmarks generally
don't prove much of anything. Sometimes that hit will come from the language, and
sometimes that hit will come from something entirely differently. &lt;em&gt;Profile first&lt;/em&gt;.
Don't let your intuition get in the way, because your intuition sucks. Mine does,
too, by the way--there's just too many moving parts to be able to keep it all straight
in your head.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Steve then launches into a series of Q&amp;amp;A with the audience, but we'll let the
light dim on that stage, and turn our attention over to Cedric's response.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;"... the overall idea is that dynamically typed languages are on the rise and
statically typed languages are on their way out."&lt;/em&gt; Actually, the transcript &lt;em&gt;I&lt;/em&gt; read
seemed to imply that Steve thought that dynamically typed languages are cool but that
nobody will use them for a variety of reasons, some of which he agreed with. I thoroughly
disagree with Steve's conclusion there, by the way, but so be it ... 
&lt;li&gt;
&lt;em&gt;"I'm happy to be the Luke Skywalker to his Darth Vader. ... Evil shall not prevail."&lt;/em&gt; Yes,
let's not let this debate fall into the &lt;em&gt;pseudo&lt;/em&gt;-religious category, shall
we? Fully religious debates have &lt;em&gt;such&lt;/em&gt; a better track record of success, so
let's just make it "good vs evil", in order to &lt;em&gt;ensure&lt;/em&gt; emotions get all neatly
wrapped throughout. Just remember, Cedric, even Satan can quote the Bible... and it
was Jesus telling us that, so if you disagree with anything I say below you must be
some kind of Al-Qaeda terrorist. Or something. 
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;[Editor's note: Oh, shit, he did NOT just call Cedric a terrorist and a Satanist
and invoke the name of Christ in all this. Time to roll out the disclaimer... "Ladies
and gentlemen, the views and opinions expressed in this blog entry...."]&lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;[Author's note: For the humor-challenged in the crowd, no I do &lt;/em&gt;not&lt;em&gt; think
Cedric is a terrorist. I &lt;/em&gt;like&lt;em&gt; Cedric, and hopefully he still likes me, too.
Of course, I have also been accused of being the Antichrist, so what that says about
Cedric I'm not sure.]&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Cedric on Scala: 
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;"Have you taken a look at implicits? Seriously? Just when I thought we were not
just done realizing that global variables are bad, but we have actually come up with
better ways to leverage the concept with DI frameworks such as Guice, Scala knocks
the wind out of us with implicits and all our hardly earned knowledge about side effects
is going down the drain again."&lt;/em&gt; Umm.... Cedric? One reaction comes to mind here,
and it's best expressed as.... WTF?!? Implicits are not global variables or DI, they're
more a way of doing conversions, a la autoboxing but more flexible. I agree that casual
use of implicits can get you in trouble, but I'd have thought Scala's "there are no
operators just methods with funny names" would be the more disconcerting of the two. 
&lt;li&gt;
&lt;em&gt;"As for pattern matching, it makes me feel as if all the careful data abstraction
that I have built inside my objects in order to isolate them from the unforgiving
world are, again, thrown out of the window because I am now forced to write deconstructors
to expose all this state just so my classes can be put in a statement that doesn't
even have the courtesy to dress up as something that doesn't smell like a switch/case..."&lt;/em&gt; I
suppose if you looked at pattern-matching and saw nothing more than a switch/case,
then I'd agree with you, but it turns out that pattern-matching is a lot more powerful
than just being a switch/case. I &lt;em&gt;think&lt;/em&gt; what Cedric's opposing is the fact
that pattern-matching can actually bind to variables expressed in the individual match
clauses, which might look like deconstructors exposing state... but that's not the
way they get used, from what I've seen thus far. But, hey, just because the language
offers it, people will use it wrongly, right? So God forbid a language's library should
allow me to, say, execute private methods or access private fields....&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
Cedric on the difficulty to impose a non-mainstream language in the industry: &lt;em&gt;"Let
me turn the table on you and imagine that one of your coworkers comes to you and tells
you that he really wants to implement his part of the project in this awesome language
called Draco. How would you react? Well, you're a pragmatic kind of guy and even though
the idea seems wacky, I'm sure you would start by doing some homework (which would
show you that Draco was an awesome language used back in the days on the Amiga). Reading
up on Draco, you realize that it's indeed a very cool language that has some features
that are a good match for the problem at hand. But even as you realize this, you already
know what you need to tell that guy, right? Probably something like "You're out of
your mind, go back to Eclipse and get cranking". And suddenly, you've become *that*
guy. Just because you showed some common sense."&lt;/em&gt; If, I suppose, we equate "common
sense" with "thinking the way Cedric does", sure, that makes sense. But you know,
if it turned out that I was writing something that targeted the Amiga, and Draco did,
in fact, give us a huge boost on the competition, and the drawbacks of using Draco
seemed to pale next to the advantages of using it, then... Well, gawrsh, boss, it
jus' might make &lt;em&gt;sense&lt;/em&gt; to use 'dis har Draco thang, even tho it ain't Java.
This is called &lt;em&gt;risk mitigation&lt;/em&gt;, and frankly, it's something too few companies
go through because they've "standardized" on a language and API set across the company
that's hardly applicable to the problem at hand. Don't get me wrong--you don't want
the opposite extreme, which is total anarchy in the operations center as people use
any and all languages/platforms available to them on a willy-nilly basis, but the
funny thing is, this is a &lt;em&gt;continuum&lt;/em&gt;, not a binary switch. This is where languages-on-execution-engines
(like the JVM or CLR) gets such a great win-win condition: IT can just think in terms
of supporting the JVM or CLR, and developers can then think in whatever language they
want, so long it compiles/runs on those platforms. 
&lt;li&gt;
Cedric on building tools for dynamic languages: &lt;em&gt;"I still strongly disagree with
that. It is different *and* harder (and in some cases, &lt;/em&gt;&lt;a href="http://beust.com/weblog/archives/000414.html"&gt;&lt;em&gt;impossible&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).
Your point regarding the fact that static refactoring doesn't cover 100% of the cases
is well taken, but it's 1) darn close to 100% and 2) getting closer to it much faster
than any dynamic tool ever could. By the way, Java refactorings correcting comments,
XML and property files are getting pretty common these days, but good luck trying
to perform a reliable method renaming in 100 Ruby files."&lt;/em&gt; I'm not going to weigh
in here, since I don't write tools for either dynamic or static languages, but watching
what the IntelliJ IDEA guys are doing with Groovy, and what the NetBeans guys are
doing with Ruby, I'm more inclined to believe in what Steve thinks than what Cedric
does. As for the "reliable method renaming in 100 Ruby files", I don't know this for
a fact, but I'll be willing to be that we're a lot closer to that than Cedric thinks
we are. &lt;em&gt;(I'd love to hear comments from somebody neck-deep in the Ruby crowd who's
done this and their experience doing so.)&lt;/em&gt; 
&lt;li&gt;
Cedric on generics: &lt;em&gt;"I no longer bother trying to understand why complex Generic
examples are so... well, darn complex. Yes, it's pretty darn hard to follow sometimes,
but here are a few points for you to ponder: &lt;/em&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;90% of the Java programmers (including myself) only ever use Generics for Collections. &lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;These same programmers never go as far as nesting two Generic declarations. &lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;For API developers and users alike, Generics are a huge progress. &lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;Scala still requires you to understand covariance and contravariance (but with
different rules. People seem to say that Scala's rules are simpler, I'm not so sure,
but not interested in finding out for the aforementioned reasons)."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
Honestly, Cedric, the fact that 90% of the Java programmers are only using generics
for collections doesn't sway me in the slightest. 90% of the world's population doesn't
use Calculus, either, but that doesn't mean that it's not useful, or that we shouldn't
be trying to improve our understanding of it and how to do useful things with it.
After looking at what the C++ community has done with templates (the Boost libraries)
and what .NET is doing with its generic system (LINQ and F# to cite two examples),
I think Java missed a &lt;em&gt;huge&lt;/em&gt; opportunity with generics. Type erasure may have
made sense in a world where Java was the only practical language on top of the JVM,
but in a world that's coming to accept Groovy and JRuby and Scala as potential equals
on the JVM, it makes no sense whatsoever. Meanwhile, when thinking about Scala, let's
take careful note that a Scala programmer can go a &lt;em&gt;long&lt;/em&gt; way with the langauge
before having to think about covariance, contravariance, upper and lower type bounds,
simpler or not. (For what it's worth, I agree with you, I'm not sure if they're simpler,
either.) 
&lt;li&gt;
Cedric on dynamic language performance: &lt;em&gt;"What will keep preventing dynamically
typed languages from displacing statically typed ones in large scale software is not
performance, it's the simple fact that it's impossible to make sense of a giant ball
of typeless source files, which causes automatic refactorings to be unreliable, hence
hardly applicable, which in turn makes developers scared of refactoring. And it's
all downhill from there. Hello bit rot."&lt;/em&gt; There's a certain circular logic here--if
we presume that IDEs can't make sense of "typeless source files" (I wasn't aware that &lt;em&gt;any&lt;/em&gt; source
file was statically typed, honestly--this must be something Google teaches), then
it follows that refactoring will be impossible or at least unreliable, and thus a
giant ball of them will be unmanageable. I disagree with Cedric's premise--that IDEs
can't make sense of dynamic language code--so therefore I disagree with the entire
logical chain as a result. What I &lt;em&gt;don't&lt;/em&gt; disagree with is the implicit presumption
that the larger the dynamic language source base, the harder it is to keep straight
in your head. In fact, I'll even amend that statement further: the larger the source
base (dynamic or otherwise), the harder it is to keep straight in your head. Abstractions
are key to the long-term success of any project, so the language I work with had best
be able to help me create those abstractions, or I'm in trouble once I cross a certain
threshold. That's true regardless of the language: C++, Java, C#, Ruby, or whatever.
That's one of the reasons I'm spending time trying to get my head around Lisp and
Scheme, because those languages were all about building abstractions upon abstractions
upon abstractions, but in libraries, rather than in the language itself, so they could
be swapped out and replaced with something else when the abstractions failed or needed
evolution. 
&lt;li&gt;
Cedric on program unmaintainability: &lt;em&gt;"I hate giving anecdotal evidence to support
my points, but that won't stop me from telling a short story that happened to me just
two weeks ago: I found myself in this very predicament when trying to improve a Ruby
program that 1) I just wrote a few days before and 2) is 200 lines long. I was staring
at an object, trying to remember what it does, failing, searching manually in emacs
where it was declared, found it as a "Hash", and then realized I still had no idea
what the darn thing is. You see my point..."&lt;/em&gt; Ain't nothing wrong with anecdotal
evidence, Cedric. We all have it, and if we all examine it &lt;em&gt;en masse&lt;/em&gt;, some
interesting patterns can emerge. Funny thing is, I've had exactly the same experience
with C++ code, Java code, and C# code. What does that tell you? It tells me that I
probably should have cooked up some better abstractions for those particular snippets,
and that's what I ended up doing. As a matter of fact, I just helped a buddy of mine
untangle some Ruby code to turn it into C#, and despite the fact that he's never written
(or read) a Ruby program in his life, we managed to flip it over to C# in a couple
of hours, including the execution of Ruby code blocks (I &lt;em&gt;love&lt;/em&gt; anonymous methods)
stored in a string-keyed hash within an array. And this was Ruby code that neither
of us had ever seen before, much less written it a few days prior. 
&lt;li&gt;
Cedric (and Steve) on error messages: &lt;em&gt;"[Steve said] And the weird thing is, I
realized early in my career that I would actually rather have a runtime error than
a compile error. [Cedric responded] You probably already know this, but you drew the
wrong conclusion. You didn't want a runtime error, you wanted a clear error. One that
doesn't lie to you, like CFront (and a lot of C++ compilers even today, I hear) used
to spit in our faces. And once I have a clear error message, I much prefer to have
it as early as possible, thank you very much."&lt;/em&gt; Honestly, I agree with Cedric
here: I would much prefer errors &lt;em&gt;before&lt;/em&gt; execution, as early as possible,
so that there's less chance of my users finding the errors I haven't found yet. And
I agree that some of the error messages we sometimes get are pretty incomprehensible,
particularly from the C++ compiler during template expansion. But how is that different
from the ubiquitous Java "ClassCastException: Cannot cast Person to Person" that arises
from time to time? Once you know what the message is telling you, it's easy to know
how to fix it, but getting to the point of knowing what the error message is telling
you requires a good working understanding of Java ClassLoaders. Do we really expect
that any tool--static or dynamic, compiler or runtime, is going to be able to produce
error messages that somehow precludes the need to have the necessary background to
understand it? &lt;em&gt;All errors are relative to the context from which they are born.&lt;/em&gt; If
you lack that context, the error message, no matter how well-written or phrased, is
useless. 
&lt;li&gt;
Cedric on "The dynamic nuclear winter": &lt;em&gt;"[Steve said] And everybody else went
and chased static. And they've been doing it like crazy. And they've, in my opinion,
reached the theoretical bounds of what they can deliver, and it has FAILED. [Cedric
responded] Quite honestly, words fail me here."&lt;/em&gt; Wow. Just... wow. I can't agree
with Steve at all, that static(ically typed languages) has FAILED, or that they've
reached the theoretical bounds of what they can deliver, but neither can I say with
complete confidence that statically-typed languages are The Way Forward, either. I
think, for the time, chasing statically-typed languages was the right thing to do,
because for a long time we were in a position where programmer time was cheaper than
computer time; now, I believe that this particular metric has flipped, and that it's
time we started thinking about what the costs of programmer time really are. (Frankly,
I'd love to see a double-blind study on this, but I've no idea how one would carry
that out in a scientific manner.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So.... what's left?
&lt;/p&gt;
&lt;p&gt;
Oh, right: if Steve/Vader is Cedric/Luke's father, then who is Cedric/Luke's sister,
and why is she wearing a copper-wire bikini while strangling the Haskell/ML crowd/Jabba
the Hutt?
&lt;/p&gt;
&lt;p&gt;
Maybe this whole Star Wars analogy thing was a bad idea.
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
Look, at the end of the day, the whole static-vs-dynamic thing is a red herring. &lt;em&gt;It
doesn't matter&lt;/em&gt;. The crucial question is whether or not the language being used
does two things, and how well it does them:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Provide the ability to express the concept in your head, and 
&lt;li&gt;
Provide the ability to evolve as the concepts in your head evolve&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
There are certain things that are just impossible to do in C++, for example. I cannot
represent the C++ AST inside the program itself. (Before you jump all over me, C++ers
of the world, take careful note: I'm &lt;em&gt;not&lt;/em&gt; saying that C++ cannot represent
an AST, but an AST of &lt;em&gt;itself&lt;/em&gt;, at the time it is executing.) This is something
dynamic languages--most notably Lisp, but also other languages, including Ruby--do
pretty well, because they're building the AST at runtime anyway, in order to execute
the code in the first place. &lt;em&gt;Could&lt;/em&gt; C++ do this? Perhaps, but the larger question
is, would any self-respecting C++ programmer &lt;em&gt;want&lt;/em&gt; to? Look at your average
Ruby program--80% to 90% (the number may vary, but most of the Rubyists I talk to
agree its somewhere in this range) of the program isn't really using the meta-object
capabilities of the language, and is just a "simpler/easier/scarier/unchecked" object
language. Most of the weird-*ss Rubyisms don't show up in your average Ruby program,
but are buried away in some library someplace, and away from the view of the average
Ruby programmer.
&lt;/p&gt;
&lt;p&gt;
Keep the simple things simple, and make the hard things possible. That' should be
the overriding goal of any language, library, or platform.
&lt;/p&gt;
&lt;p&gt;
Erik Meijer coined this idea first, and I like it a lot: Why can't we operate on a
basic principle of "static when we can (or should), dynamic otherwise"? (Reverse that
if it makes you feel better: "dynamic when we can, static otherwise", because the
difference is really only one of gradation. It's also an interesting point for discussion,
just how much of each is necessary/desirable.) Doing this means we get the best of
both worlds, and we can stop this Galactic Civil War before anybody's planet gets
blown up.
&lt;/p&gt;
&lt;p&gt;
'Cuz that would suck.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=a00766d9-6994-4611-8bc1-e6b169167949" /&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,a00766d9-6994-4611-8bc1-e6b169167949.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=2f65e7ea-67cf-407a-b7f9-08f4b968e08c</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,2f65e7ea-67cf-407a-b7f9-08f4b968e08c.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,2f65e7ea-67cf-407a-b7f9-08f4b968e08c.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=2f65e7ea-67cf-407a-b7f9-08f4b968e08c</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://steve.vinoski.net/blog/2008/05/09/thinking-in-language-but-not-clearly/">Steve
Vinoski thinks to deflate my arguments with suppositions and presumptions</a>, which
I cannot simply let stand.
</p>
        <blockquote>
          <p>
            <em>(Sorry, Steve-O, but I think you're out in left field on this one. I'm happy to
argue it further with you over beer, but if you want the last word, have at it, and
we'll compare scores when we run into each other at the next conference.)</em>
          </p>
        </blockquote>
        <p>
Steve first takes aim at my comparison of the Erlang process model to the *nix process
model:
</p>
        <blockquote>
          <p>
First, Ted says: 
</p>
          <blockquote>
            <p>
              <em>Erlang’s reliability model–that is, the spawn-a-thousand-processes model–is not
unique to Erlang. In fact, it’s been the model for Unix programs and servers, most
notably the Apache web server, for decades. When building a robust system under Unix,
a master-slave model, in which a master process spawns (and monitors) n number of
child processes to do the actual work, offers that same kind of reliability and robustness.
If one of these processes fail (due to corrupted memory access, operating system fault,
or what-have-you), the process can simply die and be replaced by a new child process.</em>
            </p>
          </blockquote>
          <p>
There’s really no comparison between the UNIX process model (which BTW I hold in very
high regard) and Erlang’s approach to achieving high reliability. They are simply
not at all the same, and there’s no way you can claim that UNIX “offers that same
kind of reliability and robustness” as Erlang can. If it could, wouldn’t virtually
every UNIX process be consistently yielding reliability of five nines or better?
</p>
        </blockquote>
        <p>
What Steve misses here is that just because something <em>can</em>, doesn't mean it <em>does</em>.
Processes in *nix are just as vulnerable to bad coding practices as are processes
in Windows or Mac OS X, and let's be very clear: the robustness and reliability of
a system is <em>entirely</em> held hostage to the skill and care of the worst programmer
on the system. There is a large difference between theory and practice, Steve, and
whether somebody takes *nix up on that offer depends a great deal on how much they're
interested in building robust and reliable software.
</p>
        <p>
This is where a system's architecture becomes so important--architecture leads developers
down a particular path, enabling them to fall into what Rico Mariani once described
as "the pit of success", or what I like to call "correctness by default". Windows
leads developers down a single-process/multi-thread-based model, and UNIX leads developers
down a multi-process-based model. Which one seems more robust and reliable <em>by
default</em> to you?
</p>
        <p>
(By the way, Erlang's model is apparently neither processes nor threads; according
to <a href="http://en.wikipedia.org/wiki/Erlang_%28programming_language%29">Wikipedia's
entry on Erlang</a>,
</p>
        <blockquote>
          <p>
Erlang processes are neither operating system processes nor operating system threads,
but lightweight processes somewhat similar to Java's original “green threads”. Like
operating system processes (and unlike green threads and operating system threads)
they have no shared state between them.
</p>
        </blockquote>
        <p>
Now, I grant you, Wikipedia is about as accurate as graffiti scrawled on the wall,
but if that's an incorrect summation, please point me to the documentation that contradicts
this and let's fix the Wikipedia entry while we're at it. But in the meantime, assuming
this is correct, it means that Erlang's model is similar to the CLR's AppDomain construct,
which has been around since .NET 1.0, and Java's proposed "Isolate" feature which
has yet to be implemented.)
</p>
        <p>
(Oh, and if the argument here is that Erlang's reliability comes from its lack of
shared state between threads, hell, man, that's hardly a difficult architecture to
cook up. Most transactional systems get there pretty easily, including EJB, though
then programmers then go through dozens of hoops to try and break it.)
</p>
        <p>
Next, Steve makes some interesting fundamental assumptions about "high reliability":
</p>
        <blockquote>
          <p>
Obviously, achieving high reliability requires at least two computers. On those systems,
what part of the UNIX process model allows a process on one system to seamlessly fork
child processes on another and monitor them over there? Yes, there are ways to do
it, but would anyone claim they are as reliable and robust as Erlang’s approach? I
sure wouldn’t. Also, UNIX pipes provide IPC for processes on the same host, but what
about communicating with processes on other hosts? Yes, there are many, many ways
to achieve that as well — after all, I’ve spent most of my career working on distributed
computing systems, so I’m well aware of the myriad choices here — but that’s actually
a problem in this case: too many choices, too many trade-offs, and far too many ways
to get it wrong. Erlang can achieve high reliability in part because it solves these
issues, and a whole bunch of other related issues such as live code upgrade/downgrade,
extremely well.
</p>
        </blockquote>
        <p>
I think you're making some serious assumptions about the definition of "high reliability"
here, Steve--building reliable software no more depends on having at least two computers
as it does having at least two power sources, two network infrastructures, or two
continents. Obviously, the more reliable you want to get with your software, the more
redundancy you want to have, but that's a continuum, and one man's "high" reliability
is another man's "low" reliability. Often, having just two processes running is redundant
enough to get the job done.
</p>
        <p>
As for UNIX's process model making it seamless to fork child processes "over there"
and monitor them "over here", I know other languages that have supported precisely
that since 1995, SR (Synchronizing Resources) being one of them. (SR later was adapted
to the JVM to become JR, and the reason I'm aware of them is because I took a couple
of classes from both langauges' creator, Ron Olsson, from UC Davis.) 
</p>
        <p>
Frankly, I think Steve's reaching with this argument--there's no reasoning here, just
"I sure wouldn't [claim that they are as reliable and robust as Erlang's approach]"
as persuasion. You <em>like</em> Erlang's ability to spin off child processes, Steve,
and that's fine, but let's not pretend that Erlang's doing anything incredibly novel
here--it's just taking the UNIX model and incorporating it directly into the language.
</p>
        <p>
And that's part of the problem--any time we incorporate something directly as part
of the language, there's all kinds of versioning and revision issues that come with
it. This, to my mind, is one of Scala's (and F#'s and Lisp's and Clojure's and Scheme's
and other composite languages') greatest strengths, the ability to create constructs
that <em>look</em> like they're part of the language, but in fact come from libraries.
Libraries are much much easier to revise and adapt right now, largely because we know
how to do it, at least compared against what we know about how to do it with languages.
</p>
        <p>
Next, Steve hollers at me for being apparently inconsistent:
</p>
        <blockquote>
          <p>
Ted continues: 
</p>
          <blockquote>
            <p>
              <em>There is no reason a VM (JVM, CLR, Parrot, etc) could not do this. In fact, here’s
the kicker: it would be easier for a VM environment to do this, because VM’s, by their
nature, seek to abstract away the details of the underlying platform that muddy up
the picture.</em>
            </p>
          </blockquote>
          <p>
In your original posting, Ted, you criticized Erlang for having its own VM, yet here
you say that a VM approach can yield the best solution for this problem. Aren’t you
contradicting yourself?
</p>
        </blockquote>
        <p>
I do criticize Erlang for having its own VM (though I think it's not a VM, it's an
interpreter, which is a far cry from an actual VM), and yet I do believe the VMs can
yield the best solution for the problem. The key here is simple: how much energy has
gone into making the VM fast, robust, scalable, manageable, monitorable, and so on?
The JVM and the CLR have (literally) thousands of man-months sunk into them to reach
high levels in all those areas. Can Erlang claim the same? How do I tune Erlang's
GC? How do I find out if Erlang's GC is holding objects longer than it should? How
do I discover if an Erlang process is about to die due to a low-memory condition?
Can I hold objects inside of a weak reference in Erlang? All of these were things
developed in the JVM and CLR in response to real customer problems, and once done,
were available to any and all languages that run on top of that platform. In order
to keep up, Erlang must sink a significant amount of effort into these same scenarios,
and I'm willing to bet that Erlang didn't get feature "X" unless Ericsson ran into
the need for it themselves.
</p>
        <p>
By the way, the same argument applies to Ruby, at least until you start talking about
JRuby or IronRuby. Ditto for Python up until IronPython or Jython (both of which,
I understand, now run faster than the native C Python interpreter).
</p>
        <p>
Steve continues attacking my VM-based arguments:
</p>
        <blockquote>
          <blockquote>
            <p>
              <em>It would be relatively simple to take an Actors-based Java application, such as
that currently being built in Scala, and move it away from a threads-based model and
over to a process-based model (with the JVM constuction[sic]/teardown being handled
entirely by underlying infrastructure) with little to no impact on the programming
model.</em>
            </p>
          </blockquote>
          <p>
Would it really be “relatively simple?” Even if what you describe really were relatively
simple, which I strongly doubt, there’s still no guarantee that the result would help
applications get anywhere near the levels of reliability they can achieve using Erlang.
</p>
        </blockquote>
        <p>
Actually, yes, it would, because Scala's already done it. Actors is a library, not
part of the language, and as such, is extensible in ways we haven't anticipated yet.
As for creating and tearing down JVMs automatically, again, JR has done that already.
Combining the two is probably not much more than talking to Prof. Olsson and Prof.
Odersky for a while, then writing the code for the host; if I get some time, I'll
take a stab at it, if nobody's done it before now. More importantly, <a href="http://blog.lostlake.org/index.php?/archives/73-For-all-you-know,-its-just-another-Java-library.html">the
lift web framework is seeing some pretty impressive scalability and performance numbers
using Actors</a>, thanks to the inherent nature of an Actors model and the intrinsic
perf and scale capabilities of the JVM, though I don't know how much anybody's measured
its reliability or robustness yet. (How <em>should</em> we measure it, come to think
of it?)
</p>
        <p>
Best part is, the IT department doesn't have to do anything different to their existing
Java-based network topology to start taking advantage of this. Can you say the same
for Erlang?
</p>
        <p>
Continuing...
</p>
        <blockquote>
          <blockquote>
            <p>
              <em>As to Steve’s comment that the Erlang interpreter isn’t monitorable, I never said
that–I said that Erlang was not monitorable using current IT operations monitoring
tools. The JVM and CLR both have gone to great lengths to build infrastructure hooks
that make it easy to keep an eye not only on what’s going on at the process level
(”Is it up? Is it down?”) but also what’s going on inside the system (”How many requests
have we processed in the last hour? How many of those were successful? How many database
connections have been created?” and so on). Nothing says that Erlang–or any other
system–can’t do that, but it requires the Erlang developer build that infrastructure
him-or-herself, which usually means it’s either not going to get done, making life
harder for the IT support staff, or else it gets done to a minimalist level, making
life harder for the IT support staff.</em>
            </p>
          </blockquote>
          <p>
I know what you meant in your original posting, Ted, and my objection still stands.
Are you saying here that all Java and .NET applications are by default network-monitoring-friendly,
whereas Erlang applications are not? I seem to recall quite a bit of effort spent
by various teams at my previous employer to make sure our distributed computing products,
including the Java-based products and .NET-based products, played reasonably well
with network monitoring systems, and I sure don’t recall any of it being automatic.
Yes, it’s nice that the Java and CLR guys have made their infrastructure monitorable,
but that doesn’t relieve developers of the need to put actual effort into tying their
applications into the monitoring system in a way that provides useful information
that makes sense. There is no magic here, and in my experience, even with all this
support, it <em>still</em> doesn’t guarantee that monitoring support will be done
to the degree that the IT support staff would like to see. 
</p>
          <p>
And do you honestly believe Erlang — conceived, designed, implemented, and maintained
by a large well-established telecommunications company for use in highly-reliable
telecommunications systems — would offer <em>nothing</em> in the way of tying into
network monitoring systems? I guess SNMP, for example, doesn’t count anymore? 
</p>
          <p>
(Coincidentally, I recently had to tie some of the Erlang stuff I’m currently working
on into a monitoring system which isn’t written in Erlang, and it took me maybe a
quarter of a workday to integrate them. I’m absolutely certain it would have taken
longer in Java.)
</p>
        </blockquote>
        <p>
Every JVM and CLR process are, by default, network-monitoring-friendly. Java5 introduced
JMX, and the CLR has had PerfMon and WMI hooks in it since Day One. Can't make that
any clearer. Dunno what kind of efforts your previous employer was going through,
but perhaps those efforts were back in the Java 1.4 and earlier days, when JMX wasn't
a part of the platform. Frankly, whether the application you're monitoring hooks into
the monitoring infrastructure is not really part of the argument, since Erlang doesn't
offer that, either. I'm more concerned with whether the <em>infrastructure</em> is
monitoring-friendly.
</p>
        <p>
Considering that most IT departments are happy if you give them <em>any</em> monitoring
capabilities, having the infrastructure monitoring-friendly is a big deal.
</p>
        <p>
And Steve, if it takes you more than a quarter of a workday to create an MBean-friendly
interface, write an implementation of that interface and register the object under
an ObjectName with the MBeanServer, then you're woefully out of practice in Java--you
should be able to do that in an hour or so.
</p>
        <p>
More to the point, though, if Erlang ties into SNMP out of the box with no work required
by the programmer, please tell me where that's doc'ed and how it works! I won't claim
to be the smartest Erlang programmer on the block, so anywhere you can point to facts
about Erlang that I'm missing, please point 'em out!
</p>
        <p>
Finally, Steve approaches the <em>coup de grace</em>:
</p>
        <blockquote>
          <p>
But here’s the part of Ted’s response that I really don’t understand: 
</p>
          <blockquote>
            <p>
              <em>So given that an execution engine could easily adopt the model that gives Erlang
its reliability, and that using Erlang means a lot more work to get the monitorability
and manageability (which is a necessary side-effect requirement of accepting that
failure happens), hopefully my reasons for saying that Erlang (or Ruby’s or any other
native-implemented language) is a non-starter for me becomes more clear.</em>
            </p>
          </blockquote>
          <p>
Ted, first you state that an execution engine could (emphasis mine) “<em>easily</em> adopt
the model that gives Erlang its reliability,” and then you say that it’s “a lot more
work” for anyone to write an Erlang application that can be monitored and managed?
Aren’t you getting those backwards? It should be obvious that in reality, writing
a monitorable Erlang app is not hard at all, whereas building Erlang-level reliability
into another VM would be a considerably complicated and time-consuming undertaking.
</p>
        </blockquote>
        <p>
Yes, the JVM could easily adopt the multi-process model if it chose to. (Said work
is being done via the Java Isolates JSR.) The CLR already does (via AppDomains). I
mean what I say when I say it. If you have facts that disagree, please cite them.
You've already stated that Erlang hooks into SNMP, so please, if you want to get the
same degree of monitoring and management that the JVM and CLR have, write the full
set of monitoring hooks to keep track of all the same things the JVM and CLR track
inside their respective VMs and expose them via SNMP. If you're looking for the full
set, look either in the javax.management package JavaDoc and take every interface
that ends in "MBean", or walk up to any Windows machine with the .NET framework installed
and look at the set of PerfMon counters exposed there.
</p>
        <p>
If you <em>really</em> want to prove your point, let's have a bake-off: on the sound
of the gun firing, you start adding the monitoring and management hooks to the Erlang
interpreter, and I'll add the spin-a-process-off hooks to the CLR or the JVM, and
we'll see who's done first. Then we'll release the whole thing to the world and both
camps will have been made better for the experience.
</p>
        <p>
Or maybe you could just port Erlang to the JVM or CLR, and then we'll both be happy.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=2f65e7ea-67cf-407a-b7f9-08f4b968e08c" />
        <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>Clearly Thinking... whether in Language, or otherwise</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,2f65e7ea-67cf-407a-b7f9-08f4b968e08c.aspx</guid>
      <link>http://blogs.tedneward.com/2008/05/18/Clearly+Thinking+Whether+In+Language+Or+Otherwise.aspx</link>
      <pubDate>Sun, 18 May 2008 06:16:13 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://steve.vinoski.net/blog/2008/05/09/thinking-in-language-but-not-clearly/"&gt;Steve
Vinoski thinks to deflate my arguments with suppositions and presumptions&lt;/a&gt;, which
I cannot simply let stand.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;(Sorry, Steve-O, but I think you're out in left field on this one. I'm happy to
argue it further with you over beer, but if you want the last word, have at it, and
we'll compare scores when we run into each other at the next conference.)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Steve first takes aim at my comparison of the Erlang process model to the *nix process
model:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
First, Ted says: &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Erlang’s reliability model–that is, the spawn-a-thousand-processes model–is not
unique to Erlang. In fact, it’s been the model for Unix programs and servers, most
notably the Apache web server, for decades. When building a robust system under Unix,
a master-slave model, in which a master process spawns (and monitors) n number of
child processes to do the actual work, offers that same kind of reliability and robustness.
If one of these processes fail (due to corrupted memory access, operating system fault,
or what-have-you), the process can simply die and be replaced by a new child process.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
There’s really no comparison between the UNIX process model (which BTW I hold in very
high regard) and Erlang’s approach to achieving high reliability. They are simply
not at all the same, and there’s no way you can claim that UNIX “offers that same
kind of reliability and robustness” as Erlang can. If it could, wouldn’t virtually
every UNIX process be consistently yielding reliability of five nines or better?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
What Steve misses here is that just because something &lt;em&gt;can&lt;/em&gt;, doesn't mean it &lt;em&gt;does&lt;/em&gt;.
Processes in *nix are just as vulnerable to bad coding practices as are processes
in Windows or Mac OS X, and let's be very clear: the robustness and reliability of
a system is &lt;em&gt;entirely&lt;/em&gt; held hostage to the skill and care of the worst programmer
on the system. There is a large difference between theory and practice, Steve, and
whether somebody takes *nix up on that offer depends a great deal on how much they're
interested in building robust and reliable software.
&lt;/p&gt;
&lt;p&gt;
This is where a system's architecture becomes so important--architecture leads developers
down a particular path, enabling them to fall into what Rico Mariani once described
as "the pit of success", or what I like to call "correctness by default". Windows
leads developers down a single-process/multi-thread-based model, and UNIX leads developers
down a multi-process-based model. Which one seems more robust and reliable &lt;em&gt;by
default&lt;/em&gt; to you?
&lt;/p&gt;
&lt;p&gt;
(By the way, Erlang's model is apparently neither processes nor threads; according
to &lt;a href="http://en.wikipedia.org/wiki/Erlang_%28programming_language%29"&gt;Wikipedia's
entry on Erlang&lt;/a&gt;,
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Erlang processes are neither operating system processes nor operating system threads,
but lightweight processes somewhat similar to Java's original “green threads”. Like
operating system processes (and unlike green threads and operating system threads)
they have no shared state between them.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Now, I grant you, Wikipedia is about as accurate as graffiti scrawled on the wall,
but if that's an incorrect summation, please point me to the documentation that contradicts
this and let's fix the Wikipedia entry while we're at it. But in the meantime, assuming
this is correct, it means that Erlang's model is similar to the CLR's AppDomain construct,
which has been around since .NET 1.0, and Java's proposed "Isolate" feature which
has yet to be implemented.)
&lt;/p&gt;
&lt;p&gt;
(Oh, and if the argument here is that Erlang's reliability comes from its lack of
shared state between threads, hell, man, that's hardly a difficult architecture to
cook up. Most transactional systems get there pretty easily, including EJB, though
then programmers then go through dozens of hoops to try and break it.)
&lt;/p&gt;
&lt;p&gt;
Next, Steve makes some interesting fundamental assumptions about "high reliability":
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Obviously, achieving high reliability requires at least two computers. On those systems,
what part of the UNIX process model allows a process on one system to seamlessly fork
child processes on another and monitor them over there? Yes, there are ways to do
it, but would anyone claim they are as reliable and robust as Erlang’s approach? I
sure wouldn’t. Also, UNIX pipes provide IPC for processes on the same host, but what
about communicating with processes on other hosts? Yes, there are many, many ways
to achieve that as well — after all, I’ve spent most of my career working on distributed
computing systems, so I’m well aware of the myriad choices here — but that’s actually
a problem in this case: too many choices, too many trade-offs, and far too many ways
to get it wrong. Erlang can achieve high reliability in part because it solves these
issues, and a whole bunch of other related issues such as live code upgrade/downgrade,
extremely well.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I think you're making some serious assumptions about the definition of "high reliability"
here, Steve--building reliable software no more depends on having at least two computers
as it does having at least two power sources, two network infrastructures, or two
continents. Obviously, the more reliable you want to get with your software, the more
redundancy you want to have, but that's a continuum, and one man's "high" reliability
is another man's "low" reliability. Often, having just two processes running is redundant
enough to get the job done.
&lt;/p&gt;
&lt;p&gt;
As for UNIX's process model making it seamless to fork child processes "over there"
and monitor them "over here", I know other languages that have supported precisely
that since 1995, SR (Synchronizing Resources) being one of them. (SR later was adapted
to the JVM to become JR, and the reason I'm aware of them is because I took a couple
of classes from both langauges' creator, Ron Olsson, from UC Davis.) 
&lt;/p&gt;
&lt;p&gt;
Frankly, I think Steve's reaching with this argument--there's no reasoning here, just
"I sure wouldn't [claim that they are as reliable and robust as Erlang's approach]"
as persuasion. You &lt;em&gt;like&lt;/em&gt; Erlang's ability to spin off child processes, Steve,
and that's fine, but let's not pretend that Erlang's doing anything incredibly novel
here--it's just taking the UNIX model and incorporating it directly into the language.
&lt;/p&gt;
&lt;p&gt;
And that's part of the problem--any time we incorporate something directly as part
of the language, there's all kinds of versioning and revision issues that come with
it. This, to my mind, is one of Scala's (and F#'s and Lisp's and Clojure's and Scheme's
and other composite languages') greatest strengths, the ability to create constructs
that &lt;em&gt;look&lt;/em&gt; like they're part of the language, but in fact come from libraries.
Libraries are much much easier to revise and adapt right now, largely because we know
how to do it, at least compared against what we know about how to do it with languages.
&lt;/p&gt;
&lt;p&gt;
Next, Steve hollers at me for being apparently inconsistent:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
Ted continues: &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;There is no reason a VM (JVM, CLR, Parrot, etc) could not do this. In fact, here’s
the kicker: it would be easier for a VM environment to do this, because VM’s, by their
nature, seek to abstract away the details of the underlying platform that muddy up
the picture.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
In your original posting, Ted, you criticized Erlang for having its own VM, yet here
you say that a VM approach can yield the best solution for this problem. Aren’t you
contradicting yourself?
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I do criticize Erlang for having its own VM (though I think it's not a VM, it's an
interpreter, which is a far cry from an actual VM), and yet I do believe the VMs can
yield the best solution for the problem. The key here is simple: how much energy has
gone into making the VM fast, robust, scalable, manageable, monitorable, and so on?
The JVM and the CLR have (literally) thousands of man-months sunk into them to reach
high levels in all those areas. Can Erlang claim the same? How do I tune Erlang's
GC? How do I find out if Erlang's GC is holding objects longer than it should? How
do I discover if an Erlang process is about to die due to a low-memory condition?
Can I hold objects inside of a weak reference in Erlang? All of these were things
developed in the JVM and CLR in response to real customer problems, and once done,
were available to any and all languages that run on top of that platform. In order
to keep up, Erlang must sink a significant amount of effort into these same scenarios,
and I'm willing to bet that Erlang didn't get feature "X" unless Ericsson ran into
the need for it themselves.
&lt;/p&gt;
&lt;p&gt;
By the way, the same argument applies to Ruby, at least until you start talking about
JRuby or IronRuby. Ditto for Python up until IronPython or Jython (both of which,
I understand, now run faster than the native C Python interpreter).
&lt;/p&gt;
&lt;p&gt;
Steve continues attacking my VM-based arguments:
&lt;/p&gt;
&lt;blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;It would be relatively simple to take an Actors-based Java application, such as
that currently being built in Scala, and move it away from a threads-based model and
over to a process-based model (with the JVM constuction[sic]/teardown being handled
entirely by underlying infrastructure) with little to no impact on the programming
model.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Would it really be “relatively simple?” Even if what you describe really were relatively
simple, which I strongly doubt, there’s still no guarantee that the result would help
applications get anywhere near the levels of reliability they can achieve using Erlang.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Actually, yes, it would, because Scala's already done it. Actors is a library, not
part of the language, and as such, is extensible in ways we haven't anticipated yet.
As for creating and tearing down JVMs automatically, again, JR has done that already.
Combining the two is probably not much more than talking to Prof. Olsson and Prof.
Odersky for a while, then writing the code for the host; if I get some time, I'll
take a stab at it, if nobody's done it before now. More importantly, &lt;a href="http://blog.lostlake.org/index.php?/archives/73-For-all-you-know,-its-just-another-Java-library.html"&gt;the
lift web framework is seeing some pretty impressive scalability and performance numbers
using Actors&lt;/a&gt;, thanks to the inherent nature of an Actors model and the intrinsic
perf and scale capabilities of the JVM, though I don't know how much anybody's measured
its reliability or robustness yet. (How &lt;em&gt;should&lt;/em&gt; we measure it, come to think
of it?)
&lt;/p&gt;
&lt;p&gt;
Best part is, the IT department doesn't have to do anything different to their existing
Java-based network topology to start taking advantage of this. Can you say the same
for Erlang?
&lt;/p&gt;
&lt;p&gt;
Continuing...
&lt;/p&gt;
&lt;blockquote&gt; &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;As to Steve’s comment that the Erlang interpreter isn’t monitorable, I never said
that–I said that Erlang was not monitorable using current IT operations monitoring
tools. The JVM and CLR both have gone to great lengths to build infrastructure hooks
that make it easy to keep an eye not only on what’s going on at the process level
(”Is it up? Is it down?”) but also what’s going on inside the system (”How many requests
have we processed in the last hour? How many of those were successful? How many database
connections have been created?” and so on). Nothing says that Erlang–or any other
system–can’t do that, but it requires the Erlang developer build that infrastructure
him-or-herself, which usually means it’s either not going to get done, making life
harder for the IT support staff, or else it gets done to a minimalist level, making
life harder for the IT support staff.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I know what you meant in your original posting, Ted, and my objection still stands.
Are you saying here that all Java and .NET applications are by default network-monitoring-friendly,
whereas Erlang applications are not? I seem to recall quite a bit of effort spent
by various teams at my previous employer to make sure our distributed computing products,
including the Java-based products and .NET-based products, played reasonably well
with network monitoring systems, and I sure don’t recall any of it being automatic.
Yes, it’s nice that the Java and CLR guys have made their infrastructure monitorable,
but that doesn’t relieve developers of the need to put actual effort into tying their
applications into the monitoring system in a way that provides useful information
that makes sense. There is no magic here, and in my experience, even with all this
support, it &lt;em&gt;still&lt;/em&gt; doesn’t guarantee that monitoring support will be done
to the degree that the IT support staff would like to see. 
&lt;p&gt;
And do you honestly believe Erlang — conceived, designed, implemented, and maintained
by a large well-established telecommunications company for use in highly-reliable
telecommunications systems — would offer &lt;em&gt;nothing&lt;/em&gt; in the way of tying into
network monitoring systems? I guess SNMP, for example, doesn’t count anymore? 
&lt;p&gt;
(Coincidentally, I recently had to tie some of the Erlang stuff I’m currently working
on into a monitoring system which isn’t written in Erlang, and it took me maybe a
quarter of a workday to integrate them. I’m absolutely certain it would have taken
longer in Java.)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Every JVM and CLR process are, by default, network-monitoring-friendly. Java5 introduced
JMX, and the CLR has had PerfMon and WMI hooks in it since Day One. Can't make that
any clearer. Dunno what kind of efforts your previous employer was going through,
but perhaps those efforts were back in the Java 1.4 and earlier days, when JMX wasn't
a part of the platform. Frankly, whether the application you're monitoring hooks into
the monitoring infrastructure is not really part of the argument, since Erlang doesn't
offer that, either. I'm more concerned with whether the &lt;em&gt;infrastructure&lt;/em&gt; is
monitoring-friendly.
&lt;/p&gt;
&lt;p&gt;
Considering that most IT departments are happy if you give them &lt;em&gt;any&lt;/em&gt; monitoring
capabilities, having the infrastructure monitoring-friendly is a big deal.
&lt;/p&gt;
&lt;p&gt;
And Steve, if it takes you more than a quarter of a workday to create an MBean-friendly
interface, write an implementation of that interface and register the object under
an ObjectName with the MBeanServer, then you're woefully out of practice in Java--you
should be able to do that in an hour or so.
&lt;/p&gt;
&lt;p&gt;
More to the point, though, if Erlang ties into SNMP out of the box with no work required
by the programmer, please tell me where that's doc'ed and how it works! I won't claim
to be the smartest Erlang programmer on the block, so anywhere you can point to facts
about Erlang that I'm missing, please point 'em out!
&lt;/p&gt;
&lt;p&gt;
Finally, Steve approaches the &lt;em&gt;coup de grace&lt;/em&gt;:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
But here’s the part of Ted’s response that I really don’t understand: &lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;So given that an execution engine could easily adopt the model that gives Erlang
its reliability, and that using Erlang means a lot more work to get the monitorability
and manageability (which is a necessary side-effect requirement of accepting that
failure happens), hopefully my reasons for saying that Erlang (or Ruby’s or any other
native-implemented language) is a non-starter for me becomes more clear.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Ted, first you state that an execution engine could (emphasis mine) “&lt;em&gt;easily&lt;/em&gt; adopt
the model that gives Erlang its reliability,” and then you say that it’s “a lot more
work” for anyone to write an Erlang application that can be monitored and managed?
Aren’t you getting those backwards? It should be obvious that in reality, writing
a monitorable Erlang app is not hard at all, whereas building Erlang-level reliability
into another VM would be a considerably complicated and time-consuming undertaking.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Yes, the JVM could easily adopt the multi-process model if it chose to. (Said work
is being done via the Java Isolates JSR.) The CLR already does (via AppDomains). I
mean what I say when I say it. If you have facts that disagree, please cite them.
You've already stated that Erlang hooks into SNMP, so please, if you want to get the
same degree of monitoring and management that the JVM and CLR have, write the full
set of monitoring hooks to keep track of all the same things the JVM and CLR track
inside their respective VMs and expose them via SNMP. If you're looking for the full
set, look either in the javax.management package JavaDoc and take every interface
that ends in "MBean", or walk up to any Windows machine with the .NET framework installed
and look at the set of PerfMon counters exposed there.
&lt;/p&gt;
&lt;p&gt;
If you &lt;em&gt;really&lt;/em&gt; want to prove your point, let's have a bake-off: on the sound
of the gun firing, you start adding the monitoring and management hooks to the Erlang
interpreter, and I'll add the spin-a-process-off hooks to the CLR or the JVM, and
we'll see who's done first. Then we'll release the whole thing to the world and both
camps will have been made better for the experience.
&lt;/p&gt;
&lt;p&gt;
Or maybe you could just port Erlang to the JVM or CLR, and then we'll both be happy.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=2f65e7ea-67cf-407a-b7f9-08f4b968e08c" /&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,2f65e7ea-67cf-407a-b7f9-08f4b968e08c.aspx</comments>
      <category>.NET</category>
      <category>Java/J2EE</category>
      <category>Ruby</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=94fda66c-4dda-438c-af27-a53a8e0692c8</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,94fda66c-4dda-438c-af27-a53a8e0692c8.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,94fda66c-4dda-438c-af27-a53a8e0692c8.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=94fda66c-4dda-438c-af27-a53a8e0692c8</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, a former student asked me,
</p>
        <blockquote>
          <p>
I was in a .NET web services training class that you gave probably 4 or so years ago
on-site at a <em>[company name]</em> office in <em>[city]</em>, north of Atlanta. 
At that time I asked you for a list of the technical blogs that you read, and I am
curious which blogs you are reading now.  I am now with a small company where
I have to be a jack of all trades, in the last year I have worked in C++ and Perl
backend type projects and web frontend projects with Java, C#, and RoR, so I find
your perspective interesting since you also work with various technologies and aren't
a zealot for a specific one.
</p>
          <p>
Any way, please either respond by email or in your blog, because I think that others
may be interested in the list also.
</p>
        </blockquote>
        <p>
As one might expect, my blog list is a bit eclectic, but I suppose that's part of
the charm of somebody looking to study Java, .NET, C++, Smalltalk, Ruby, Parrot, LLVM,
and other languages and environments. So, without further ado, I've pasted in the
contents of my OPML file for cut&amp;paste and easy import.
</p>
        <p>
Having said that, though, I would strongly suggest <em>not</em> just blindly importing
the whole set of feeds into your nearest RSS reader, but take a moment and go visit
each one before you add it. It takes longer, granted, but the time spent is a worthy
investment--you don't want to have to declare "blog bankruptcy".
</p>
        <blockquote>
          <p>
            <em>Editor's note: We pause here as readers look at each other and go... "WTF?!?"</em>
          </p>
        </blockquote>
        <p>
"Blog bankruptcy" is a condition similar to "email bankruptcy", when otherwise perfectly
high-functioning people give up on trying to catch up to the flood of messages in
their email client's Inbox and delete the whole mess (usually with some kind of public
apology explaining why and asking those who've emailed them in the past to resend
something if it was really important), effectively trying to "start over" with their
email in much the same way that Chapter Seven or Chapter Eleven allows companies to
"start over" with their creditors, or declaring bankruptcy allows private citizens
to do the same with theirs. "Blog bankruptcy" is a similar kind of condition: your
RSS reader becomes so full of stuff that you can't keep up, and you can't even remember
which blogs were the interesting ones, so you nuke the whole thing and get away from
the blog-reading thing for a while.
</p>
        <p>
This happened to me, in fact: a few years ago, when I became the editor-in-chief of
TheServerSide.NET, I asked a few folks for their OPML lists, so that I could quickly
and easily build a list of blogs that would "tune me in" to the software industry
around me, and many of them quite agreeably complied. I took my RSS reader (Newsgator,
at the time) and dutifully imported all of them, and ended up with a collection of
blogs that was easily into the hundreds of feeds long. And, over time, I found myself
reading fewer and fewer blogs, mostly because the whole set was so... <em>intimidating</em>.
I mean, I would pick at the list of blogs and their entries in the same way that I
picked at vegetables on my plate as a child--half-heartedly, with no real enthusiasm,
as if this was something my parents were forcing me to do. That just ruined the experience
of blog-reading for me, and eventually (after I left TSS.NET for other pastures),
I nuked the whole thing--even going so far as to uninstall my copy of Newsgator--and
gave up.
</p>
        <p>
Naturally, I missed it, and slowly over time began to rebuild the list, this time,
taking each feed one at a time, carefully weighing what value the feed was to me and
selecting only those that I thought had a high signal-to-noise ratio. (This is partly
why I don't include much "personal" info in this blog--I found myself routinely stripping
away those blogs that had more personal content and less technical content, and I
figured if I didn't want to read it, others probably felt the same way.) Over the
last year or two, I've rebuilt the list to the point where I probably need to prune
a bit and close a few of them back down, but for now, I'm happy with the list I've
got.
</p>
        <p>
And speaking of which....
</p>
        <div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4">
          <div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum1" style="color: #606060"> 1:</span>
              <span style="color: #0000ff">&lt;?</span>
              <span style="color: #800000">xml</span>
              <span style="color: #ff0000">version</span>
              <span style="color: #0000ff">="1.0"</span>?<span style="color: #0000ff">&gt;</span></pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum2" style="color: #606060"> 2:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">opml</span>
              <span style="color: #ff0000">version</span>
              <span style="color: #0000ff">="1.0"</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum3" style="color: #606060"> 3:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">head</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum4" style="color: #606060"> 4:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">title</span>
              <span style="color: #0000ff">&gt;</span>OPML
exported from Outlook<span style="color: #0000ff">&lt;/</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span></pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum5" style="color: #606060"> 5:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">dateCreated</span>
              <span style="color: #0000ff">&gt;</span>Thu,
15 May 2008 20:55:19 -0700<span style="color: #0000ff">&lt;/</span><span style="color: #800000">dateCreated</span><span style="color: #0000ff">&gt;</span></pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum6" style="color: #606060"> 6:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">dateModified</span>
              <span style="color: #0000ff">&gt;</span>Thu,
15 May 2008 20:55:19 -0700<span style="color: #0000ff">&lt;/</span><span style="color: #800000">dateModified</span><span style="color: #0000ff">&gt;</span></pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum7" style="color: #606060"> 7:</span>
              <span style="color: #0000ff">&lt;/</span>
              <span style="color: #800000">head</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum8" style="color: #606060"> 8:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">body</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum9" style="color: #606060"> 9:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="If
broken it is, fix it you should"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum10" style="color: #606060"> 10:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/tess/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum11" style="color: #606060"> 11:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Artima
Developer Buzz"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum12" style="color: #606060"> 12:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://www.artima.com/news/feeds/news.rss"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum13" style="color: #606060"> 13:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Artima
Weblogs"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum14" style="color: #606060"> 14:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://www.artima.com/weblogs/feeds/weblogs.rss"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum15" style="color: #606060"> 15:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Artima
Chapters Library"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum16" style="color: #606060"> 16:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://www.artima.com/chapters/feeds/chapters.rss"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum17" style="color: #606060"> 17:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Neal
Gafter's blog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum18" style="color: #606060"> 18:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://gafter.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum19" style="color: #606060"> 19:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Room
101"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum20" style="color: #606060"> 20:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://gbracha.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum21" style="color: #606060"> 21:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Kelly
O'Hair's Blog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum22" style="color: #606060"> 22:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://weblogs.java.net/blog/kellyohair/index.rdf"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum23" style="color: #606060"> 23:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="John
Rose @ Sun"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum24" style="color: #606060"> 24:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.sun.com/jrose/feed/entries/atom"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum25" style="color: #606060"> 25:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="The
Daily WTF"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum26" style="color: #606060"> 26:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://syndication.thedailywtf.com/TheDailyWtf"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum27" style="color: #606060"> 27:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Brad
Wilson"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum28" style="color: #606060"> 28:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.feedburner.com/BradWilson"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum29" style="color: #606060"> 29:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Mike
Stall's .NET Debugging Blog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum30" style="color: #606060"> 30:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/jmstall/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum31" style="color: #606060"> 31:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Stevey's
Blog Rants"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum32" style="color: #606060"> 32:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://steve-yegge.blogspot.com/atom.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum33" style="color: #606060"> 33:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Brendan's
Roadmap Updates"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum34" style="color: #606060"> 34:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://weblogs.mozillazine.org/roadmap/index.rdf"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum35" style="color: #606060"> 35:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="pl
patterns"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum36" style="color: #606060"> 36:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://plpatterns.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum37" style="color: #606060"> 37:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Joel
Pobar's weblog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum38" style="color: #606060"> 38:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.feedburner.com/callvirt"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum39" style="color: #606060"> 39:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Let&amp;amp;#39;s
Kill Dave!"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum40" style="color: #606060"> 40:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://letskilldave.com/rss.aspx"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum41" style="color: #606060"> 41:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Why
does everything suck?"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum42" style="color: #606060"> 42:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://whydoeseverythingsuck.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum43" style="color: #606060"> 43:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="cdiggins.com"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://cdiggins.com/feed"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum44" style="color: #606060"> 44:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="LukeH's
WebLog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum45" style="color: #606060"> 45:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/lukeh/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum46" style="color: #606060"> 46:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Jomo
Fisher -- Sharp Things"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum47" style="color: #606060"> 47:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/jomo_fisher/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum48" style="color: #606060"> 48:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Chance
Coble"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum49" style="color: #606060"> 49:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://leibnizdream.wordpress.com/feed/"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum50" style="color: #606060"> 50:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Don
Syme's WebLog on F# and Other Research Projects"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum51" style="color: #606060"> 51:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/dsyme/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum52" style="color: #606060"> 52:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="David
Broman's CLR Profiling API Blog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum53" style="color: #606060"> 53:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/davbr/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum54" style="color: #606060"> 54:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="JScript
Blog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum55" style="color: #606060"> 55:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/jscript/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum56" style="color: #606060"> 56:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Yet
Another Language Geek"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum57" style="color: #606060"> 57:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://blogs.msdn.com/wesdyer/rss.xml"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum58" style="color: #606060"> 58:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">=".NET
Languages Weblog"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum59" style="color: #606060"> 59:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://www.dotnetlanguages.net/DNL/Rss.aspx"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum60" style="color: #606060"> 60:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="DevHawk"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum61" style="color: #606060"> 61:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.feedburner.com/Devhawk"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum62" style="color: #606060"> 62:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="The
Cobra Programming Language"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum63" style="color: #606060"> 63:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://cobralang.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum64" style="color: #606060"> 64:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Code
Miscellany"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum65" style="color: #606060"> 65:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://codemiscellany.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum66" style="color: #606060"> 66:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Fred,
Let it go!"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum67" style="color: #606060"> 67:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://freddy33.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum68" style="color: #606060"> 68:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Codedependent"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum69" style="color: #606060"> 69:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://graphics-geek.blogspot.com/feeds/posts/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum70" style="color: #606060"> 70:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Presentation
Zen"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum71" style="color: #606060"> 71:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://www.presentationzen.com/presentationzen/index.rdf"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum72" style="color: #606060"> 72:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="The
Extreme Presentation(tm) Method"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum73" style="color: #606060"> 73:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://extremepresentation.typepad.com/blog/index.rdf"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum74" style="color: #606060"> 74:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="ZapThink"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum75" style="color: #606060"> 75:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.feedburner.com/zapthink"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum76" style="color: #606060"> 76:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Chris
Smith's completely unique view"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum77" style="color: #606060"> 77:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.feedburner.com/ChrisSmithsCompletelyUniqueView"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum78" style="color: #606060"> 78:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Code
Commit"</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum79" style="color: #606060"> 79:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://feeds.codecommit.com/codecommit"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum80" style="color: #606060"> 80:</span>
              <span style="color: #0000ff">&lt;</span>
              <span style="color: #800000">outline</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum81" style="color: #606060"> 81:</span>
              <span style="color: #ff0000">text</span>
              <span style="color: #0000ff">="Comments
on Ola Bini: Programming Language Synchronicity: A New Hope: Polyglotism"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum82" style="color: #606060"> 82:</span>
              <span style="color: #ff0000">type</span>
              <span style="color: #0000ff">="rss"</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum83" style="color: #606060"> 83:</span>
              <span style="color: #ff0000">xmlUrl</span>
              <span style="color: #0000ff">="http://ola-bini.blogspot.com/feeds/5778383724683099288/comments/default"</span>
              <span style="color: #0000ff">/&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum84" style="color: #606060"> 84:</span>
              <span style="color: #0000ff">&lt;/</span>
              <span style="color: #800000">body</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
            <pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
              <span id="lnum85" style="color: #606060"> 85:</span>
              <span style="color: #0000ff">&lt;/</span>
              <span style="color: #800000">opml</span>
              <span style="color: #0000ff">&gt;</span>
            </pre>
            <!--CRLF-->
          </div>
        </div>
        <p>
Happy reading.....
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=94fda66c-4dda-438c-af27-a53a8e0692c8" />
        <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>Blogs I'm currently reading</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,94fda66c-4dda-438c-af27-a53a8e0692c8.aspx</guid>
      <link>http://blogs.tedneward.com/2008/05/16/Blogs+Im+Currently+Reading.aspx</link>
      <pubDate>Fri, 16 May 2008 07:08:07 GMT</pubDate>
      <description>&lt;p&gt;
Recently, a former student asked me,
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
I was in a .NET web services training class that you gave probably 4 or so years ago
on-site at a &lt;em&gt;[company name]&lt;/em&gt; office in &lt;em&gt;[city]&lt;/em&gt;, north of Atlanta.&amp;nbsp;
At that time I asked you for a list of the technical blogs that you read, and I am
curious which blogs you are reading now.&amp;nbsp; I am now with a small company where
I have to be a jack of all trades, in the last year I have worked in C++ and Perl
backend type projects and web frontend projects with Java, C#, and RoR, so I find
your perspective interesting since you also work with various technologies and aren't
a zealot for a specific one.
&lt;/p&gt;
&lt;p&gt;
Any way, please either respond by email or in your blog, because I think that others
may be interested in the list also.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
As one might expect, my blog list is a bit eclectic, but I suppose that's part of
the charm of somebody looking to study Java, .NET, C++, Smalltalk, Ruby, Parrot, LLVM,
and other languages and environments. So, without further ado, I've pasted in the
contents of my OPML file for cut&amp;amp;paste and easy import.
&lt;/p&gt;
&lt;p&gt;
Having said that, though, I would strongly suggest &lt;em&gt;not&lt;/em&gt; just blindly importing
the whole set of feeds into your nearest RSS reader, but take a moment and go visit
each one before you add it. It takes longer, granted, but the time spent is a worthy
investment--you don't want to have to declare "blog bankruptcy".
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Editor's note: We pause here as readers look at each other and go... "WTF?!?"&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
"Blog bankruptcy" is a condition similar to "email bankruptcy", when otherwise perfectly
high-functioning people give up on trying to catch up to the flood of messages in
their email client's Inbox and delete the whole mess (usually with some kind of public
apology explaining why and asking those who've emailed them in the past to resend
something if it was really important), effectively trying to "start over" with their
email in much the same way that Chapter Seven or Chapter Eleven allows companies to
"start over" with their creditors, or declaring bankruptcy allows private citizens
to do the same with theirs. "Blog bankruptcy" is a similar kind of condition: your
RSS reader becomes so full of stuff that you can't keep up, and you can't even remember
which blogs were the interesting ones, so you nuke the whole thing and get away from
the blog-reading thing for a while.
&lt;/p&gt;
&lt;p&gt;
This happened to me, in fact: a few years ago, when I became the editor-in-chief of
TheServerSide.NET, I asked a few folks for their OPML lists, so that I could quickly
and easily build a list of blogs that would "tune me in" to the software industry
around me, and many of them quite agreeably complied. I took my RSS reader (Newsgator,
at the time) and dutifully imported all of them, and ended up with a collection of
blogs that was easily into the hundreds of feeds long. And, over time, I found myself
reading fewer and fewer blogs, mostly because the whole set was so... &lt;em&gt;intimidating&lt;/em&gt;.
I mean, I would pick at the list of blogs and their entries in the same way that I
picked at vegetables on my plate as a child--half-heartedly, with no real enthusiasm,
as if this was something my parents were forcing me to do. That just ruined the experience
of blog-reading for me, and eventually (after I left TSS.NET for other pastures),
I nuked the whole thing--even going so far as to uninstall my copy of Newsgator--and
gave up.
&lt;/p&gt;
&lt;p&gt;
Naturally, I missed it, and slowly over time began to rebuild the list, this time,
taking each feed one at a time, carefully weighing what value the feed was to me and
selecting only those that I thought had a high signal-to-noise ratio. (This is partly
why I don't include much "personal" info in this blog--I found myself routinely stripping
away those blogs that had more personal content and less technical content, and I
figured if I didn't want to read it, others probably felt the same way.) Over the
last year or two, I've rebuilt the list to the point where I probably need to prune
a bit and close a few of them back down, but for now, I'm happy with the list I've
got.
&lt;/p&gt;
&lt;p&gt;
And speaking of which....
&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="border-right: silver 1px solid; padding-right: 4px; border-top: silver 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: silver 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: silver 1px solid; font-family: 'Courier New', courier, monospace; background-color: #f4f4f4"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt; 1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #800000"&gt;xml&lt;/span&gt; &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1.0"&lt;/span&gt;?&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt; 2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;opml&lt;/span&gt; &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="1.0"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt; 3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt; 4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;OPML
exported from Outlook&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt; 5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;dateCreated&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Thu,
15 May 2008 20:55:19 -0700&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;dateCreated&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt; 6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;dateModified&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;Thu,
15 May 2008 20:55:19 -0700&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;dateModified&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt; 7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt; 8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt; 9:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="If
broken it is, fix it you should"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt; 10:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/tess/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt; 11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Artima
Developer Buzz"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt; 12:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://www.artima.com/news/feeds/news.rss"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt; 13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Artima
Weblogs"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt; 14:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://www.artima.com/weblogs/feeds/weblogs.rss"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt; 15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Artima
Chapters Library"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum16" style="color: #606060"&gt; 16:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://www.artima.com/chapters/feeds/chapters.rss"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum17" style="color: #606060"&gt; 17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Neal
Gafter's blog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum18" style="color: #606060"&gt; 18:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://gafter.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum19" style="color: #606060"&gt; 19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Room
101"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum20" style="color: #606060"&gt; 20:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://gbracha.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum21" style="color: #606060"&gt; 21:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Kelly
O'Hair's Blog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum22" style="color: #606060"&gt; 22:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://weblogs.java.net/blog/kellyohair/index.rdf"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum23" style="color: #606060"&gt; 23:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="John
Rose @ Sun"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum24" style="color: #606060"&gt; 24:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.sun.com/jrose/feed/entries/atom"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum25" style="color: #606060"&gt; 25:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="The
Daily WTF"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum26" style="color: #606060"&gt; 26:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://syndication.thedailywtf.com/TheDailyWtf"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum27" style="color: #606060"&gt; 27:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Brad
Wilson"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum28" style="color: #606060"&gt; 28:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.feedburner.com/BradWilson"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum29" style="color: #606060"&gt; 29:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Mike
Stall's .NET Debugging Blog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum30" style="color: #606060"&gt; 30:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/jmstall/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum31" style="color: #606060"&gt; 31:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Stevey's
Blog Rants"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum32" style="color: #606060"&gt; 32:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://steve-yegge.blogspot.com/atom.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum33" style="color: #606060"&gt; 33:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Brendan's
Roadmap Updates"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum34" style="color: #606060"&gt; 34:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://weblogs.mozillazine.org/roadmap/index.rdf"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum35" style="color: #606060"&gt; 35:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="pl
patterns"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum36" style="color: #606060"&gt; 36:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://plpatterns.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum37" style="color: #606060"&gt; 37:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Joel
Pobar's weblog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum38" style="color: #606060"&gt; 38:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.feedburner.com/callvirt"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum39" style="color: #606060"&gt; 39:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Let&amp;amp;amp;#39;s
Kill Dave!"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum40" style="color: #606060"&gt; 40:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://letskilldave.com/rss.aspx"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum41" style="color: #606060"&gt; 41:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Why
does everything suck?"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum42" style="color: #606060"&gt; 42:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://whydoeseverythingsuck.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum43" style="color: #606060"&gt; 43:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="cdiggins.com"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://cdiggins.com/feed"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum44" style="color: #606060"&gt; 44:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="LukeH's
WebLog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum45" style="color: #606060"&gt; 45:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/lukeh/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum46" style="color: #606060"&gt; 46:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Jomo
Fisher -- Sharp Things"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum47" style="color: #606060"&gt; 47:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/jomo_fisher/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum48" style="color: #606060"&gt; 48:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Chance
Coble"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum49" style="color: #606060"&gt; 49:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://leibnizdream.wordpress.com/feed/"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum50" style="color: #606060"&gt; 50:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Don
Syme's WebLog on F# and Other Research Projects"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum51" style="color: #606060"&gt; 51:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/dsyme/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum52" style="color: #606060"&gt; 52:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="David
Broman's CLR Profiling API Blog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum53" style="color: #606060"&gt; 53:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/davbr/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum54" style="color: #606060"&gt; 54:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="JScript
Blog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum55" style="color: #606060"&gt; 55:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/jscript/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum56" style="color: #606060"&gt; 56:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Yet
Another Language Geek"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum57" style="color: #606060"&gt; 57:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://blogs.msdn.com/wesdyer/rss.xml"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum58" style="color: #606060"&gt; 58:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=".NET
Languages Weblog"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum59" style="color: #606060"&gt; 59:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://www.dotnetlanguages.net/DNL/Rss.aspx"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum60" style="color: #606060"&gt; 60:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="DevHawk"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum61" style="color: #606060"&gt; 61:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.feedburner.com/Devhawk"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum62" style="color: #606060"&gt; 62:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="The
Cobra Programming Language"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum63" style="color: #606060"&gt; 63:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://cobralang.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum64" style="color: #606060"&gt; 64:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Code
Miscellany"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum65" style="color: #606060"&gt; 65:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://codemiscellany.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum66" style="color: #606060"&gt; 66:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Fred,
Let it go!"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum67" style="color: #606060"&gt; 67:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://freddy33.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum68" style="color: #606060"&gt; 68:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Codedependent"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum69" style="color: #606060"&gt; 69:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://graphics-geek.blogspot.com/feeds/posts/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum70" style="color: #606060"&gt; 70:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Presentation
Zen"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum71" style="color: #606060"&gt; 71:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://www.presentationzen.com/presentationzen/index.rdf"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum72" style="color: #606060"&gt; 72:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="The
Extreme Presentation(tm) Method"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum73" style="color: #606060"&gt; 73:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://extremepresentation.typepad.com/blog/index.rdf"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum74" style="color: #606060"&gt; 74:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="ZapThink"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum75" style="color: #606060"&gt; 75:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.feedburner.com/zapthink"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum76" style="color: #606060"&gt; 76:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Chris
Smith's completely unique view"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum77" style="color: #606060"&gt; 77:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.feedburner.com/ChrisSmithsCompletelyUniqueView"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum78" style="color: #606060"&gt; 78:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Code
Commit"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum79" style="color: #606060"&gt; 79:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://feeds.codecommit.com/codecommit"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum80" style="color: #606060"&gt; 80:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;outline&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum81" style="color: #606060"&gt; 81:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;text&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Comments
on Ola Bini: Programming Language Synchronicity: A New Hope: Polyglotism"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum82" style="color: #606060"&gt; 82:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="rss"&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum83" style="color: #606060"&gt; 83:&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlUrl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="http://ola-bini.blogspot.com/feeds/5778383724683099288/comments/default"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum84" style="color: #606060"&gt; 84:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span id="lnum85" style="color: #606060"&gt; 85:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;opml&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;!--CRLF--&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Happy reading.....
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=94fda66c-4dda-438c-af27-a53a8e0692c8" /&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,94fda66c-4dda-438c-af27-a53a8e0692c8.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>Conferences</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Reading</category>
      <category>Review</category>
      <category>Ruby</category>
      <category>Security</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=4a44324b-e95c-4ba9-b5ab-a38e8166cdb4</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,4a44324b-e95c-4ba9-b5ab-a38e8166cdb4.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,4a44324b-e95c-4ba9-b5ab-a38e8166cdb4.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4a44324b-e95c-4ba9-b5ab-a38e8166cdb4</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Not too long ago, <a href="http://pluralsight.com/blogs/dbox/archive/2008/04/29/50808.aspx">Don
wrote</a>:
</p>
        <blockquote>
          <p>
The three most “personal” choices a developer makes are language, tool, and OS.
</p>
        </blockquote>
        <p>
No.
</p>
        <p>
That may be true for somebody who works for a large commercial or open source vendor,
whose team is building something that fits into one of those three categories and
wants to see that language/tool/OS succeed.
</p>
        <p>
That is not where most of us live. If you do, certainly, you are welcome to your opinion,
but please accept with good grace that your agenda is not the same as my own.
</p>
        <p>
Most of us in the practitioner space are <em>using</em> languages, tools and OSes
to solve customer problems, and making the decision to use a particular language,
tool or OS a personal one generally gets us into trouble--how many developers do you
know that identify themselves so closely with that decision that they include it in
their personal metadata? 
</p>
        <p>
"Hi, I'm Joe, and I'm a Java programmer."
</p>
        <p>
Or, "Oh, good God, you're running Windows? What are you, some kind of Micro$oft lover
or something?"
</p>
        <p>
Or, "Linux? You really <em>are</em> a geek, aren't you? Recompiled your kernel lately
(snicker, snicker)?"
</p>
        <p>
Sorry, but all of those make me want to hurl. Of these kinds of statements are technical
zealotry and flame wars built. When programmers embed their choice so deeply into
their psyche that it becomes the tagline by which they identify themselves, it becomes
an "ego" thing instead of a "tool" thing. 
</p>
        <p>
What's more, it involves customers and people outside the field in an argument that
has <em>nothing</em> to do with them. Think about it for a second; the last time you
hired a contractor to add a deck to your house, what's your reaction when they introduce
themselves as,
</p>
        <p>
"Hi, I'm Kim, and I'm a Craftsman contractor."
</p>
        <p>
Or, overheard at the job site, "Oh, good God, you're using a Skil? What are you, some
kind of nut or something?"
</p>
        <p>
Or, as you look at the tools on their belt, "Nokita? You really <em>are</em> a geek,
aren't you? Rebuilt your tools from scratch lately (snicker, snicker)?"
</p>
        <p>
Do you, the customer, <em>really</em> care what kind of tools they use? Or do you
care more for the quality of solution they build for you?
</p>
        <p>
It's hard to imagine how the discussion can even come up, it's so ludicrous.
</p>
        <p>
Try this one on, instead:
</p>
        <p>
"Hi, I'm Ted, and I'm a programmer."
</p>
        <p>
I use a variety of languages, tools, and OSes, and my choice of which to use are all
geared around a single end goal: not to promote my own social or political agenda,
but to <em>make my customer happy</em>. 
</p>
        <p>
Sometimes that means using C# on Windows. Sometimes that means using Java on Linux.
Sometimes that means Ruby on Mac OS X. Sometimes that means creating a DSL. Sometimes
that means using EJB, or Spring, or F#, or Scala, or FXCop, or FindBugs, or log4j,
or ... <em>ad infinitum</em>.
</p>
        <p>
Don't get me wrong, I have my opinions, just as contractors (and truck drivers, it
turns out) do. And, like most professionals in their field, I'm happy to share those
opinions with others in my field, and also with my customers when they ask: I think
C# provides a good answer in certain contexts, and that Java provides an equally good
answer, but in different contexts. I will be happy to explain my recommendation on
which languages, tools and OSes to use, because unlike the contractor, the languages,
tools, and OSes I use <em>will</em> be visible to the customer when the software goes
into Production, at a variety of levels, and thus, the customer should be involved
in that decision. (Sometimes the situation is really one where the customer won't
see it, in which case the developer can have full confidence in whatever language/tool/OS
they choose... but that's far more often the exception than the rule, and will generally
only be true in cases where the developer is providing a complete customer "hands-off"
hosting solution.)
</p>
        <p>
I choose to be pro-choice.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=4a44324b-e95c-4ba9-b5ab-a38e8166cdb4" />
        <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>I'm Pro-Choice... Pro Programmer Choice, that is</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,4a44324b-e95c-4ba9-b5ab-a38e8166cdb4.aspx</guid>
      <link>http://blogs.tedneward.com/2008/05/11/Im+ProChoice+Pro+Programmer+Choice+That+Is.aspx</link>
      <pubDate>Sun, 11 May 2008 04:20:46 GMT</pubDate>
      <description>&lt;p&gt;
Not too long ago, &lt;a href="http://pluralsight.com/blogs/dbox/archive/2008/04/29/50808.aspx"&gt;Don
wrote&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The three most “personal” choices a developer makes are language, tool, and OS.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
No.
&lt;/p&gt;
&lt;p&gt;
That may be true for somebody who works for a large commercial or open source vendor,
whose team is building something that fits into one of those three categories and
wants to see that language/tool/OS succeed.
&lt;/p&gt;
&lt;p&gt;
That is not where most of us live. If you do, certainly, you are welcome to your opinion,
but please accept with good grace that your agenda is not the same as my own.
&lt;/p&gt;
&lt;p&gt;
Most of us in the practitioner space are &lt;em&gt;using&lt;/em&gt; languages, tools and OSes
to solve customer problems, and making the decision to use a particular language,
tool or OS a personal one generally gets us into trouble--how many developers do you
know that identify themselves so closely with that decision that they include it in
their personal metadata? 
&lt;/p&gt;
&lt;p&gt;
"Hi, I'm Joe, and I'm a Java programmer."
&lt;/p&gt;
&lt;p&gt;
Or, "Oh, good God, you're running Windows? What are you, some kind of Micro$oft lover
or something?"
&lt;/p&gt;
&lt;p&gt;
Or, "Linux? You really &lt;em&gt;are&lt;/em&gt; a geek, aren't you? Recompiled your kernel lately
(snicker, snicker)?"
&lt;/p&gt;
&lt;p&gt;
Sorry, but all of those make me want to hurl. Of these kinds of statements are technical
zealotry and flame wars built. When programmers embed their choice so deeply into
their psyche that it becomes the tagline by which they identify themselves, it becomes
an "ego" thing instead of a "tool" thing. 
&lt;/p&gt;
&lt;p&gt;
What's more, it involves customers and people outside the field in an argument that
has &lt;em&gt;nothing&lt;/em&gt; to do with them. Think about it for a second; the last time you
hired a contractor to add a deck to your house, what's your reaction when they introduce
themselves as,
&lt;/p&gt;
&lt;p&gt;
"Hi, I'm Kim, and I'm a Craftsman contractor."
&lt;/p&gt;
&lt;p&gt;
Or, overheard at the job site, "Oh, good God, you're using a Skil? What are you, some
kind of nut or something?"
&lt;/p&gt;
&lt;p&gt;
Or, as you look at the tools on their belt, "Nokita? You really &lt;em&gt;are&lt;/em&gt; a geek,
aren't you? Rebuilt your tools from scratch lately (snicker, snicker)?"
&lt;/p&gt;
&lt;p&gt;
Do you, the customer, &lt;em&gt;really&lt;/em&gt; care what kind of tools they use? Or do you
care more for the quality of solution they build for you?
&lt;/p&gt;
&lt;p&gt;
It's hard to imagine how the discussion can even come up, it's so ludicrous.
&lt;/p&gt;
&lt;p&gt;
Try this one on, instead:
&lt;/p&gt;
&lt;p&gt;
"Hi, I'm Ted, and I'm a programmer."
&lt;/p&gt;
&lt;p&gt;
I use a variety of languages, tools, and OSes, and my choice of which to use are all
geared around a single end goal: not to promote my own social or political agenda,
but to &lt;em&gt;make my customer happy&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;
Sometimes that means using C# on Windows. Sometimes that means using Java on Linux.
Sometimes that means Ruby on Mac OS X. Sometimes that means creating a DSL. Sometimes
that means using EJB, or Spring, or F#, or Scala, or FXCop, or FindBugs, or log4j,
or ... &lt;em&gt;ad infinitum&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
Don't get me wrong, I have my opinions, just as contractors (and truck drivers, it
turns out) do. And, like most professionals in their field, I'm happy to share those
opinions with others in my field, and also with my customers when they ask: I think
C# provides a good answer in certain contexts, and that Java provides an equally good
answer, but in different contexts. I will be happy to explain my recommendation on
which languages, tools and OSes to use, because unlike the contractor, the languages,
tools, and OSes I use &lt;em&gt;will&lt;/em&gt; be visible to the customer when the software goes
into Production, at a variety of levels, and thus, the customer should be involved
in that decision. (Sometimes the situation is really one where the customer won't
see it, in which case the developer can have full confidence in whatever language/tool/OS
they choose... but that's far more often the exception than the rule, and will generally
only be true in cases where the developer is providing a complete customer "hands-off"
hosting solution.)
&lt;/p&gt;
&lt;p&gt;
I choose to be pro-choice.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=4a44324b-e95c-4ba9-b5ab-a38e8166cdb4" /&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,4a44324b-e95c-4ba9-b5ab-a38e8166cdb4.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Flash</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>LLVM</category>
      <category>Mac OS</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Solaris</category>
      <category>Visual Basic</category>
      <category>VMWare</category>
      <category>Windows</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=bd815751-151d-4876-a86b-bc13fc0349ab</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,bd815751-151d-4876-a86b-bc13fc0349ab.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,bd815751-151d-4876-a86b-bc13fc0349ab.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=bd815751-151d-4876-a86b-bc13fc0349ab</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, it has become the fad to weigh in on the Groovy vs JRuby debate, usually
along the lines of "Which is <em>X</em>?", where <em>X</em> is one of "better", "faster",
"more powerful", "more acceptable", "easier", and so on. (Everybody seems to have
their own adjective/adverb to slide in there, so I won't even begin to try to list
them all.)
</p>
        <p>
Rick Hightower, <a href="http://www.jroller.com/RickHigh/entry/thanks_zed_btw_syntax_matters">in
a blog post</a> from January, weighs in on this and comes down harshly on both Scala
and JRuby. Frankly, I found the whole post to ooze bitterness and maybe a touch of
jealousy. Some of the highlights:
</p>
        <ul>
          <li>
            <strong>"In short: Scala seems like the next over-hyped language."</strong> Rick,
they're <em>all</em> over-hyped, including your own nominee for the Presidential race,
Groovy. I mean, if we're going to weigh this on the grounds of syntax or familiarity,
let's throw {ECMA/Java}script into the ring, since it's: 
<ol><li>
... been around a lot longer than Groovy and therefore a lot more familiar and comfortable
to the programmers that might use either or both, 
</li><li>
... always going to be around, thanks to its inclusion in HTML browsers, and therefore
a good investment in your knowledge portfolio regardless of where you end up using
it, client- or server- or wherever-side, 
</li><li>
... has many, if not all, of the same features that Groovy (or JRuby) supports, 
</li><li>
... runs on top of the JVM (several ways, including Rhino, which ships with JDK 6
now, and FESI), 
</li><li>
... and has Steve Yegge's vote of confidence, so you know is <em>has</em> to be good,
right? 
</li></ol></li>
          <li>
            <strong>"Sun please drop JRuby support. It is a waste of time. Take that money and
spend it on Groovy which has a compatible syntax to Java. ... Does Ruby and Rails
have good ideas? Yes. Borrow them and move on."</strong> This seems like a questionable
decision to me--why cherry-pick features from one language and port them over to a
different language, for no other reason than to say you did? Why not just use said
original language in the first place, assuming it can run on your particular platform?
Down this path lies the madness that C# and VB have become, as the C# and VB teams
seek to create "feature parity" between the two languages, just so that you as a developer
can either have your curly-braces-and-semicolons or not. Stupid. Talk about a waste
of time and energy. Ruby's syntax is (mostly) vetted, the test cases written, and
the featureset understood. Do something <em>different</em> if you're going to create
a new language, don't just take the existing features of a language and put new tokens
around it. In the South, that's called putting lipstick on the pig: it may be prettier
than it was, but underneath, it's still just a pig. (Note: sometimes the new language
is designed specifically to be a subset of the feature set of the source language,
and I'm completely supportive of that--sometimes it's necessary to scale back just
as much as it is to innovate.) 
</li>
          <li>
            <strong>"After reading the Scala docs, my thought is: while the language features
sound great, the syntax makes me want to hurl. Why do things differently just for
the sake of it?"</strong> Strangely enough, they didn't. (This is frequently the complaint
of those who don't understand something. "The designers <em>couldn't</em> have had
a good reason for doing it that way, so it must have been just because they wanted
to do it differently".) Scala's syntax is actually quite consistent in many ways,
particularly if you came from the functional language world, and the underlying rationale
is pretty easy to grok... if you bother spending enough time to find out. Scala drops
static, for example, because it turns out that Java developers spend a fair amount
of time trying to resolve the "should this be a static method or should it be an instance
method on a Singleton object" way too often, for example. See <a href="http://gbracha.blogspot.com/2008/02/cutting-out-static.html">Gilad
Bracha's arguments against static</a> if you want to find out more of the rationale
here. The "def" syntax for method definition is strikingly similar to Groovy, for
the same reason: it makes it clear where a definition is taking place. The name-colon-type
syntax is deliberate because then it's much easier to leave off the type signatures
and let the compiler do the type inferencing for you (a feature, notably, that Rick
says he likes). For what it's worth, Rick, here's a lesson I continue to learn the
hard way: Spend some time learning the <em>why</em> of something before you take aim
and let fly. 
</li>
          <li>
            <strong>"Final words: I declare the "Ruby will rule the world" fallacy officially
over. Remember: Quit pimple pimping Ruby on JRoller! Scala devotees (both of you).
Don't even start!"</strong> Well, frankly, the "Ruby will rule the world" meme was
that over-hyped thing you mentioned earlier, and before anybody starts the next one,
let me nip it in the bud: <em>nothing</em> will take over the world. Nothing <em>has</em> taken
over the world: not C++, not C, not Java, not C#, not Visual Basic, nothing. The best
a language can hope for is to cross what Simon Peyton-Jones calls the "Threshold of
Immortality", and lots of languages have done that, too many to list all of them here,
though you could probably do so yourself. Some of those include Java, C++, C#, C,
Pascal, FORTRAN, COBOL, Perl, Python, Ruby, SQL, maybe even Smalltalk and Lisp and
Scheme and the others we normally don't think about. 
</li>
        </ul>
        <p>
And we haven't even bothered to go into some kind of feature shootout or performance
shootout between any of these guys.
</p>
        <p>
Don't get me wrong--like me, Rick is entirely entitled to his own opinions and he
doesn't owe me (or anybody else) a lick of rationale to defend them. But when he comes
out and suggests that Sun should drop JRuby entirely in favor of Groovy instead, I
feel compelled to point out that there's some logic missing from the reasoning behind
that suggestion. Cynics of this blog will suggest that I'm speaking out of both sides
of my mouth: that I get to say Perl sucks, and get away with it because it's just
one man's opinion but Rick can't say JRuby sucks in turn. Fact is, I'm not suggesting
that Larry Wall and chromatic and the others should drop Perl and go work on something
more meaningful--quite the opposite, in fact: so long as there are people who continue
to use Perl, they have a responsibility to continue to develop and update that language.
And Parrot is quite the interesting VM to explore in its own right. But don't expect
me any time soon to be writing a bunch of Perl code except under strongly-worded protest
to the United Nations.
</p>
        <p>
At the end of the day, the way I think about these languages loosely falls like this:
</p>
        <ul>
          <li>
            <strong>C++.</strong> For me, programing started here, so I will always have a special
place in my heart for it. Templates were vastly more powerful than most people realized
until the STL was released, and even to this day, C++ is usually blamed for the complexities
of memory management even when garbage collector libraries (like the Boehm collector)
were available and could have reduced that complexity significantly. The Boost libraries
just blow my mind, and there's some new stuff coming in C++0X that brings C++ to a
degree of parity with Java and C#. I wish I could get back to this for a project in
the same way that guys fantasize about running into an old high school girlfriend
on a business trip. 
</li>
          <li>
            <strong>C++/CLI.</strong> C++ adapted for the CLR. Interesting idea, but it's hard
to see why I'd use this, given its syntactical and semantical similarities to C#.
Frankly, C++/CLI seems destined to be forever the "glue" language to write managed
wrappers on top of unmanaged C/C++ libraries, and that's hardly a compelling reason
to pick this guy up for anything beyond that niche area. 
</li>
          <li>
            <strong>Java.</strong> The language I want to feature-freeze, though I do see a value
in adding closures, if only to permit closures to enter the design and implementation
of the Java libraries, thus making them widely available across all JVM languages.
However, if I <em>really</em> got my way, we'd drop the closures-in-Java debate entirely
and throw our weight behind John Rose's proposal for method handles in the JVM, since
that would enable the same kind of facilities for libraries and without having to
rev the Java language significantly. (Lesson to the Java community from the CLR community:
not all features of the virtual machine have to be exposed in one language. Not even
C# or VB do this.) The JVM I want to continue to enhance and revise and improve. 
</li>
          <li>
            <strong>Scala.</strong> Functional-object hybrid language for the JVM. Pure goodness.
Hey, I'm bullish here, I admit it. Scala's type inference makes for lower ceremony,
the static type system provides a degree of confidence in code that dynamic languages
don't have without programmer-authored unit tests, and the functional nature offers
a new design dimension that we haven't been able to easily express before. I won't
say that I'm "thinking in Scala", but I'm thinking a lot <em>about</em> Scala these
days, and F# too. 
</li>
          <li>
            <strong>Groovy.</strong> "Ruby meets Java in a bar and has a love child." Groovy's
syntax is easy and based on Java, and that's both a good and a bad thing. Good if
you're a Java programmer who doesn't want to have to reach very far to get some dynamic
goodness; bad if you're trying to avoid some of the stranger or syntactically inconsistent
aspects of the Java language, or looking to do some entirely new ways of doing things.
Personally, I don't find Groovy all that intellectually stimulating, which is both
a blessing and a curse. 
</li>
          <li>
            <strong>JRuby, IronRuby.</strong> Ruby on the JVM. 'nuff said. Ditto for IronRuby
on to CLR. All the linguistic power (and flaws) of Ruby, on top of the JVM/CLR, which
now means it's a far easier sell to the IT boys who run the datacenter. 
</li>
          <li>
            <strong>C#.</strong> The language is great, so long as it retains its original vision
and scope. Memo to the C# team: <em>Please</em> let's not try to make C# into a scripting
language. Scripting languages have a purpose, and that purpose is generally different
from what general-purpose languages do. C# really doesn't need a REPL--don't fall
into the trap of trying to make it into Lisp. 
</li>
          <li>
            <strong>Visual Basic.</strong> The language is great (!), so long as it retains its
original vision and scope. Yes, I think the language is a good one--you don't really
believe how much of a PITA case-sensitivity is until you start programming without
it, and suddenly you realize that it's mostly a holdover from the C days. What right-thinking
programmer overloads a symbolic name by case? Programmers have <em>died</em> for less
than that. So why does case sensitivity matter? More importantly, VB has always been
the dynamic language of choice for millions of programmers, it's time for those of
us from the C++ community to just own up, admit that there was a place for VB after
all, apologize, and let VB go back to being a powerful dynamic language on top of
the CLR. Give it a REPL loop, make it the default choice for building top-of-the-stack
code, and let VB guys build UIs that call into middle-tier components built by C#
and F# guys. Everybody comes out a winner. 
</li>
          <li>
            <strong>F#.</strong> Functional-object hybrid language for the CLR. Pure goodness.
The syntax again will seem quirky and strange to people unused to it, but it makes
a lot of sense, and compositional construction using higher-order functions is a vastly
underestimated and underused design technique. When functions are values, lots of
things become possible, as people working in dynamic languages already know. 
</li>
          <li>
            <strong>Ruby.</strong> "Smalltalk meets Perl in a bar and has a love child." I like
parts of the Ruby syntax, but there's too many Perl-isms in there for my taste. The
fact that Ruby runs on top of its own interpreter (which is neither monitorable nor
manageable using IT-datacenter-established tools) is a significant drawback. RoR may
be great for vertical silo apps that don't need to integrate with the rest of the
datacenter, but that's a pretty scary place to put yourself. 
</li>
          <li>
            <strong>Python.</strong> Dynamic language (goodness) with some functional concepts
(goodness) on its own interpreter (badness) with a radical innovation in syntax called
significant whitespace to do away with brackets to denote code blocks. Significant
whitespace makes it incredibly awkward to embed Python code anywhere but in .py files,
meaning Python's suitability for DSLs is reduced significantly. If I could get Python
without significant whitespace, I'd be a lot happier camper. 
</li>
          <li>
            <strong>Jython/IronPython.</strong> Python on the JVM/CLR. 'nuff said. 
</li>
          <li>
            <strong>Perl.</strong> Parrot good. Perl syntax and philosophy not one I care for.
Use as a shell scripting tool good. Use as a general-purpose programming language
not one I recommend. Perl 6's incredibly delayed departure, very bad, unless you're
one of those who wants to see Perl become extinct. 
</li>
          <li>
            <strong>{ECMA/Java}Script.</strong> Can we please finally just accept that ES is much
more than just a browser extensibility tool? For most developers, this is their first
exposure to a classless prototype-based object-oriented language, and unfortunately,
most developers don't ever bother exploring it beyond "How do I make my web page do
that floating image thing...?" Gah. 
</li>
          <li>
            <strong>Rhino/FESI/JScript.NET.</strong> {ECMA/Java}Script on the JVM/JVM/CLR. 'nuff
said, though I wish the JScript guys would incorporate the E4X bits. JScript on the
CLR makes for an interesting case study, and maybe (hopefully) they'll use it as another
sanity-check for the DLR. 
</li>
          <li>
            <strong>PowerShell.</strong> Scripting language that finally brings much of the power
of bash and tcsh and other shells to the Windows world and unifies a ton of different
things together into one space: WMI, .NET, COM, and more. Highly necessary for IT
admins who've suffered with batch files for decades. Language syntax isn't too bad,
and I could even consider using it in an application/system as an extension language
to give to power users so I can turn them loose to create emergent behavior without
having to keep coming back to me with their feature requests. 
</li>
          <li>
            <strong>Lisp.</strong> With all apologies to Paul Graham, Lisp's window of opportunity
(the "woo" factor, as Jay Zimmerman likes to call it) is essentially gone. We will
always be looking back at it for ideas, I think, but it's very hard to imagine doing
a project that's even remotely near an IT data center in it, for the same reason that
Ruby or Erlang are hard to imagine here: running on top of an execution environment
that doesn't have managability and monitorability baked in is a non-starter for me.
Despite all that, however, programmers owe it to themselves to learn it, because until
somebody points it out, you never realize you're color-blind. There's so many interesting
ideas in here that you don't even realize what you're missing until you explore it. 
</li>
          <li>
            <strong>Scheme.</strong> See Lisp. 
</li>
          <li>
            <strong>Haskell.</strong> Love it or leave it, but you have to learn it. Functional
languages are becoming big, and Haskell is a major influence on them. 
</li>
          <li>
            <strong>ML.</strong> Ditto to Haskell. If you want to see another functional/object
hybrid language based on ML, check out OCaml. Note that OCaml is the direct predecessor
to F# and the two are frequently (deliberately) syntax-compatible. 
</li>
          <li>
            <strong>Erlang.</strong> Joe Armstrong's baby was built to solve a specific set of
problems at Ericsson, and from it we can learn a phenomenal amount about building
massively parallel concurrent programs. The fact that it runs on its own interpreter,
bad.</li>
        </ul>
        <p>
And there's still so many more to learn..... but that's the subject of another blog
post, coming soon.
</p>
        <p>
          <strong>Update:</strong> Naturally, people complained about the languages that were
left off the list. No slight is intended--there's a lot more that I could have included
here, and I will go into each of these in more detail (I hope), but there's only so
much time in the day, and shipping (or posting, in this case) is always a feature.
;-)
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bd815751-151d-4876-a86b-bc13fc0349ab" />
        <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>Groovy or JRuby?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,bd815751-151d-4876-a86b-bc13fc0349ab.aspx</guid>
      <link>http://blogs.tedneward.com/2008/04/29/Groovy+Or+JRuby.aspx</link>
      <pubDate>Tue, 29 Apr 2008 07:38:03 GMT</pubDate>
      <description>&lt;p&gt;
Recently, it has become the fad to weigh in on the Groovy vs JRuby debate, usually
along the lines of "Which is &lt;em&gt;X&lt;/em&gt;?", where &lt;em&gt;X&lt;/em&gt; is one of "better", "faster",
"more powerful", "more acceptable", "easier", and so on. (Everybody seems to have
their own adjective/adverb to slide in there, so I won't even begin to try to list
them all.)
&lt;/p&gt;
&lt;p&gt;
Rick Hightower, &lt;a href="http://www.jroller.com/RickHigh/entry/thanks_zed_btw_syntax_matters"&gt;in
a blog post&lt;/a&gt; from January, weighs in on this and comes down harshly on both Scala
and JRuby. Frankly, I found the whole post to ooze bitterness and maybe a touch of
jealousy. Some of the highlights:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"In short: Scala seems like the next over-hyped language."&lt;/strong&gt; Rick,
they're &lt;em&gt;all&lt;/em&gt; over-hyped, including your own nominee for the Presidential race,
Groovy. I mean, if we're going to weigh this on the grounds of syntax or familiarity,
let's throw {ECMA/Java}script into the ring, since it's: 
&lt;ol&gt;
&lt;li&gt;
... been around a lot longer than Groovy and therefore a lot more familiar and comfortable
to the programmers that might use either or both, 
&lt;li&gt;
... always going to be around, thanks to its inclusion in HTML browsers, and therefore
a good investment in your knowledge portfolio regardless of where you end up using
it, client- or server- or wherever-side, 
&lt;li&gt;
... has many, if not all, of the same features that Groovy (or JRuby) supports, 
&lt;li&gt;
... runs on top of the JVM (several ways, including Rhino, which ships with JDK 6
now, and FESI), 
&lt;li&gt;
... and has Steve Yegge's vote of confidence, so you know is &lt;em&gt;has&lt;/em&gt; to be good,
right? 
&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;
&lt;strong&gt;"Sun please drop JRuby support. It is a waste of time. Take that money and
spend it on Groovy which has a compatible syntax to Java. ... Does Ruby and Rails
have good ideas? Yes. Borrow them and move on."&lt;/strong&gt; This seems like a questionable
decision to me--why cherry-pick features from one language and port them over to a
different language, for no other reason than to say you did? Why not just use said
original language in the first place, assuming it can run on your particular platform?
Down this path lies the madness that C# and VB have become, as the C# and VB teams
seek to create "feature parity" between the two languages, just so that you as a developer
can either have your curly-braces-and-semicolons or not. Stupid. Talk about a waste
of time and energy. Ruby's syntax is (mostly) vetted, the test cases written, and
the featureset understood. Do something &lt;em&gt;different&lt;/em&gt; if you're going to create
a new language, don't just take the existing features of a language and put new tokens
around it. In the South, that's called putting lipstick on the pig: it may be prettier
than it was, but underneath, it's still just a pig. (Note: sometimes the new language
is designed specifically to be a subset of the feature set of the source language,
and I'm completely supportive of that--sometimes it's necessary to scale back just
as much as it is to innovate.) 
&lt;li&gt;
&lt;strong&gt;"After reading the Scala docs, my thought is: while the language features
sound great, the syntax makes me want to hurl. Why do things differently just for
the sake of it?"&lt;/strong&gt; Strangely enough, they didn't. (This is frequently the complaint
of those who don't understand something. "The designers &lt;em&gt;couldn't&lt;/em&gt; have had
a good reason for doing it that way, so it must have been just because they wanted
to do it differently".) Scala's syntax is actually quite consistent in many ways,
particularly if you came from the functional language world, and the underlying rationale
is pretty easy to grok... if you bother spending enough time to find out. Scala drops
static, for example, because it turns out that Java developers spend a fair amount
of time trying to resolve the "should this be a static method or should it be an instance
method on a Singleton object" way too often, for example. See &lt;a href="http://gbracha.blogspot.com/2008/02/cutting-out-static.html"&gt;Gilad
Bracha's arguments against static&lt;/a&gt; if you want to find out more of the rationale
here. The "def" syntax for method definition is strikingly similar to Groovy, for
the same reason: it makes it clear where a definition is taking place. The name-colon-type
syntax is deliberate because then it's much easier to leave off the type signatures
and let the compiler do the type inferencing for you (a feature, notably, that Rick
says he likes). For what it's worth, Rick, here's a lesson I continue to learn the
hard way: Spend some time learning the &lt;em&gt;why&lt;/em&gt; of something before you take aim
and let fly. 
&lt;li&gt;
&lt;strong&gt;"Final words: I declare the "Ruby will rule the world" fallacy officially
over. Remember: Quit pimple pimping Ruby on JRoller! Scala devotees (both of you).
Don't even start!"&lt;/strong&gt; Well, frankly, the "Ruby will rule the world" meme was
that over-hyped thing you mentioned earlier, and before anybody starts the next one,
let me nip it in the bud: &lt;em&gt;nothing&lt;/em&gt; will take over the world. Nothing &lt;em&gt;has&lt;/em&gt; taken
over the world: not C++, not C, not Java, not C#, not Visual Basic, nothing. The best
a language can hope for is to cross what Simon Peyton-Jones calls the "Threshold of
Immortality", and lots of languages have done that, too many to list all of them here,
though you could probably do so yourself. Some of those include Java, C++, C#, C,
Pascal, FORTRAN, COBOL, Perl, Python, Ruby, SQL, maybe even Smalltalk and Lisp and
Scheme and the others we normally don't think about. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And we haven't even bothered to go into some kind of feature shootout or performance
shootout between any of these guys.
&lt;/p&gt;
&lt;p&gt;
Don't get me wrong--like me, Rick is entirely entitled to his own opinions and he
doesn't owe me (or anybody else) a lick of rationale to defend them. But when he comes
out and suggests that Sun should drop JRuby entirely in favor of Groovy instead, I
feel compelled to point out that there's some logic missing from the reasoning behind
that suggestion. Cynics of this blog will suggest that I'm speaking out of both sides
of my mouth: that I get to say Perl sucks, and get away with it because it's just
one man's opinion but Rick can't say JRuby sucks in turn. Fact is, I'm not suggesting
that Larry Wall and chromatic and the others should drop Perl and go work on something
more meaningful--quite the opposite, in fact: so long as there are people who continue
to use Perl, they have a responsibility to continue to develop and update that language.
And Parrot is quite the interesting VM to explore in its own right. But don't expect
me any time soon to be writing a bunch of Perl code except under strongly-worded protest
to the United Nations.
&lt;/p&gt;
&lt;p&gt;
At the end of the day, the way I think about these languages loosely falls like this:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C++.&lt;/strong&gt; For me, programing started here, so I will always have a special
place in my heart for it. Templates were vastly more powerful than most people realized
until the STL was released, and even to this day, C++ is usually blamed for the complexities
of memory management even when garbage collector libraries (like the Boehm collector)
were available and could have reduced that complexity significantly. The Boost libraries
just blow my mind, and there's some new stuff coming in C++0X that brings C++ to a
degree of parity with Java and C#. I wish I could get back to this for a project in
the same way that guys fantasize about running into an old high school girlfriend
on a business trip. 
&lt;li&gt;
&lt;strong&gt;C++/CLI.&lt;/strong&gt; C++ adapted for the CLR. Interesting idea, but it's hard
to see why I'd use this, given its syntactical and semantical similarities to C#.
Frankly, C++/CLI seems destined to be forever the "glue" language to write managed
wrappers on top of unmanaged C/C++ libraries, and that's hardly a compelling reason
to pick this guy up for anything beyond that niche area. 
&lt;li&gt;
&lt;strong&gt;Java.&lt;/strong&gt; The language I want to feature-freeze, though I do see a value
in adding closures, if only to permit closures to enter the design and implementation
of the Java libraries, thus making them widely available across all JVM languages.
However, if I &lt;em&gt;really&lt;/em&gt; got my way, we'd drop the closures-in-Java debate entirely
and throw our weight behind John Rose's proposal for method handles in the JVM, since
that would enable the same kind of facilities for libraries and without having to
rev the Java language significantly. (Lesson to the Java community from the CLR community:
not all features of the virtual machine have to be exposed in one language. Not even
C# or VB do this.) The JVM I want to continue to enhance and revise and improve. 
&lt;li&gt;
&lt;strong&gt;Scala.&lt;/strong&gt; Functional-object hybrid language for the JVM. Pure goodness.
Hey, I'm bullish here, I admit it. Scala's type inference makes for lower ceremony,
the static type system provides a degree of confidence in code that dynamic languages
don't have without programmer-authored unit tests, and the functional nature offers
a new design dimension that we haven't been able to easily express before. I won't
say that I'm "thinking in Scala", but I'm thinking a lot &lt;em&gt;about&lt;/em&gt; Scala these
days, and F# too. 
&lt;li&gt;
&lt;strong&gt;Groovy.&lt;/strong&gt; "Ruby meets Java in a bar and has a love child." Groovy's
syntax is easy and based on Java, and that's both a good and a bad thing. Good if
you're a Java programmer who doesn't want to have to reach very far to get some dynamic
goodness; bad if you're trying to avoid some of the stranger or syntactically inconsistent
aspects of the Java language, or looking to do some entirely new ways of doing things.
Personally, I don't find Groovy all that intellectually stimulating, which is both
a blessing and a curse. 
&lt;li&gt;
&lt;strong&gt;JRuby, IronRuby.&lt;/strong&gt; Ruby on the JVM. 'nuff said. Ditto for IronRuby
on to CLR. All the linguistic power (and flaws) of Ruby, on top of the JVM/CLR, which
now means it's a far easier sell to the IT boys who run the datacenter. 
&lt;li&gt;
&lt;strong&gt;C#.&lt;/strong&gt; The language is great, so long as it retains its original vision
and scope. Memo to the C# team: &lt;em&gt;Please&lt;/em&gt; let's not try to make C# into a scripting
language. Scripting languages have a purpose, and that purpose is generally different
from what general-purpose languages do. C# really doesn't need a REPL--don't fall
into the trap of trying to make it into Lisp. 
&lt;li&gt;
&lt;strong&gt;Visual Basic.&lt;/strong&gt; The language is great (!), so long as it retains its
original vision and scope. Yes, I think the language is a good one--you don't really
believe how much of a PITA case-sensitivity is until you start programming without
it, and suddenly you realize that it's mostly a holdover from the C days. What right-thinking
programmer overloads a symbolic name by case? Programmers have &lt;em&gt;died&lt;/em&gt; for less
than that. So why does case sensitivity matter? More importantly, VB has always been
the dynamic language of choice for millions of programmers, it's time for those of
us from the C++ community to just own up, admit that there was a place for VB after
all, apologize, and let VB go back to being a powerful dynamic language on top of
the CLR. Give it a REPL loop, make it the default choice for building top-of-the-stack
code, and let VB guys build UIs that call into middle-tier components built by C#
and F# guys. Everybody comes out a winner. 
&lt;li&gt;
&lt;strong&gt;F#.&lt;/strong&gt; Functional-object hybrid language for the CLR. Pure goodness.
The syntax again will seem quirky and strange to people unused to it, but it makes
a lot of sense, and compositional construction using higher-order functions is a vastly
underestimated and underused design technique. When functions are values, lots of
things become possible, as people working in dynamic languages already know. 
&lt;li&gt;
&lt;strong&gt;Ruby.&lt;/strong&gt; "Smalltalk meets Perl in a bar and has a love child." I like
parts of the Ruby syntax, but there's too many Perl-isms in there for my taste. The
fact that Ruby runs on top of its own interpreter (which is neither monitorable nor
manageable using IT-datacenter-established tools) is a significant drawback. RoR may
be great for vertical silo apps that don't need to integrate with the rest of the
datacenter, but that's a pretty scary place to put yourself. 
&lt;li&gt;
&lt;strong&gt;Python.&lt;/strong&gt; Dynamic language (goodness) with some functional concepts
(goodness) on its own interpreter (badness) with a radical innovation in syntax called
significant whitespace to do away with brackets to denote code blocks. Significant
whitespace makes it incredibly awkward to embed Python code anywhere but in .py files,
meaning Python's suitability for DSLs is reduced significantly. If I could get Python
without significant whitespace, I'd be a lot happier camper. 
&lt;li&gt;
&lt;strong&gt;Jython/IronPython.&lt;/strong&gt; Python on the JVM/CLR. 'nuff said. 
&lt;li&gt;
&lt;strong&gt;Perl.&lt;/strong&gt; Parrot good. Perl syntax and philosophy not one I care for.
Use as a shell scripting tool good. Use as a general-purpose programming language
not one I recommend. Perl 6's incredibly delayed departure, very bad, unless you're
one of those who wants to see Perl become extinct. 
&lt;li&gt;
&lt;strong&gt;{ECMA/Java}Script.&lt;/strong&gt; Can we please finally just accept that ES is much
more than just a browser extensibility tool? For most developers, this is their first
exposure to a classless prototype-based object-oriented language, and unfortunately,
most developers don't ever bother exploring it beyond "How do I make my web page do
that floating image thing...?" Gah. 
&lt;li&gt;
&lt;strong&gt;Rhino/FESI/JScript.NET.&lt;/strong&gt; {ECMA/Java}Script on the JVM/JVM/CLR. 'nuff
said, though I wish the JScript guys would incorporate the E4X bits. JScript on the
CLR makes for an interesting case study, and maybe (hopefully) they'll use it as another
sanity-check for the DLR. 
&lt;li&gt;
&lt;strong&gt;PowerShell.&lt;/strong&gt; Scripting language that finally brings much of the power
of bash and tcsh and other shells to the Windows world and unifies a ton of different
things together into one space: WMI, .NET, COM, and more. Highly necessary for IT
admins who've suffered with batch files for decades. Language syntax isn't too bad,
and I could even consider using it in an application/system as an extension language
to give to power users so I can turn them loose to create emergent behavior without
having to keep coming back to me with their feature requests. 
&lt;li&gt;
&lt;strong&gt;Lisp.&lt;/strong&gt; With all apologies to Paul Graham, Lisp's window of opportunity
(the "woo" factor, as Jay Zimmerman likes to call it) is essentially gone. We will
always be looking back at it for ideas, I think, but it's very hard to imagine doing
a project that's even remotely near an IT data center in it, for the same reason that
Ruby or Erlang are hard to imagine here: running on top of an execution environment
that doesn't have managability and monitorability baked in is a non-starter for me.
Despite all that, however, programmers owe it to themselves to learn it, because until
somebody points it out, you never realize you're color-blind. There's so many interesting
ideas in here that you don't even realize what you're missing until you explore it. 
&lt;li&gt;
&lt;strong&gt;Scheme.&lt;/strong&gt; See Lisp. 
&lt;li&gt;
&lt;strong&gt;Haskell.&lt;/strong&gt; Love it or leave it, but you have to learn it. Functional
languages are becoming big, and Haskell is a major influence on them. 
&lt;li&gt;
&lt;strong&gt;ML.&lt;/strong&gt; Ditto to Haskell. If you want to see another functional/object
hybrid language based on ML, check out OCaml. Note that OCaml is the direct predecessor
to F# and the two are frequently (deliberately) syntax-compatible. 
&lt;li&gt;
&lt;strong&gt;Erlang.&lt;/strong&gt; Joe Armstrong's baby was built to solve a specific set of
problems at Ericsson, and from it we can learn a phenomenal amount about building
massively parallel concurrent programs. The fact that it runs on its own interpreter,
bad.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And there's still so many more to learn..... but that's the subject of another blog
post, coming soon.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Update:&lt;/strong&gt; Naturally, people complained about the languages that were
left off the list. No slight is intended--there's a lot more that I could have included
here, and I will go into each of these in more detail (I hope), but there's only so
much time in the day, and shipping (or posting, in this case) is always a feature.
;-)
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=bd815751-151d-4876-a86b-bc13fc0349ab" /&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,bd815751-151d-4876-a86b-bc13fc0349ab.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>Windows</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=6309b523-4c9d-4933-9d2c-b35dd4f16573</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,6309b523-4c9d-4933-9d2c-b35dd4f16573.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,6309b523-4c9d-4933-9d2c-b35dd4f16573.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=6309b523-4c9d-4933-9d2c-b35dd4f16573</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
From <a href="http://en.wikipedia.org/wiki/Folk_etymology">Wikipedia</a> (itself a
source of conceptual folk etymology, but that's another rant):
</p>
        <ul>
          <ul>
            <li>
A commonly held misunderstanding of the origin of a particular word, a false etymology</li>
            <li>
"The popular perversion of the form of words in order to render it apparently significant";
"the process by which a word or phrase, usually one of seemingly opaque formation,
is arbitrarily reshaped so as to yield a form which is considered to be more transparent"</li>
          </ul>
        </ul>
        <p>
What do I mean by "technical folk etymology"? 
</p>
        <ol>
          <li>
If you're a Java developer, consider the term <em>EJB</em>. No, I mean, seriously
think about it for a moment. What images are conjured before your eyes when you do
so? Horrendous APIs, hideous deployment requirements, complete untestability, and
something that takes forty-five minutes to start?</li>
          <li>
If you're a Ruby developer, consider the phrase <em>static typing</em>. Same sort
of reaction?</li>
          <li>
If you're a .NET developer, try on <em>COM</em> or <em>COM+</em> or even <em>ATL</em>.
Mystifying collections of code repeated by rote, cut-and-pasted from that very first
project you built by hand from <em>Inside OLE 2</em>, and once you got it to work,
served as your basic template for every other COM/MTS/COM+ entity you ever built?</li>
          <li>
Or, if you're any of these, how about <em>Visual Basic</em>?</li>
          <li>
Or maybe <em>Web services</em>, specifically all those WS-* specifications?</li>
        </ol>
        <p>
As the MVP Summit Product Team dinners wound down here in Redmond tonight, I found
myself at a table with (not surprisingly) Neal Ford and Venkat Subramaniam, two of
my close friends from the NFJS tour, and who should join us but first Amanda Silver
(lately of the Office team, but with her heart still firmly rooted in her Visual Basic
dev days), then Don Box (lately of the Oslo team) and Chris Sells (also lately of
the Oslo team), and a rousing discussion around the concept of DSLs--domain specific
languages--arose, largely because Don wanted to sound out Venkat and Neal on the subject.
</p>
        <p>
Listening to the conversation (Don was mostly interested in Neal and Venkat's opinions,
so I just relaxed and listened for the most part), I realized that the discussion
was entirely rooted in this concept of <em>context</em>, that ephemeral structure
surrounding a concept that gives it shape and color and taste and the other aesthetic
qualities that lead us to "like" or "dislike" or "accept" or "reject" certain concepts.
Don held the position--either for arguments' sake or because he believes it, I'm not
sure which--that domain-specific languages lose context too easily once stored on
the file system, in ways that data does not. His test was to suggest "What if a random
piece of text drops into my email, how do I know what consumes this text?" The answer,
of course, is that you don't, unless you somehow have a context by which to understand
a piece of text, in many cases based solely on nothing more than filesystem extension,
or MIME type, or the "#!/bin/..." line that precedes many shell scripts, and so on.
</p>
        <p>
Interestingly enough, as I drove home after the dinner, I realized that the conversation
echoed an exchange Neal and Venkat and I were having in the car on the way over, about
how Microsoft (I think) is making a <em>huge</em> mistake by looking to make C# more
dynamic in nature[1]. My position was (and is) that Microsoft needs to differentiate
the two key languages they offer--C# and Visual Basic--and an obvious way to do so
would be to designate VB as the official "dynamic language" for the CLR, and C# as
the official "static language" for the CLR, and encourage developers to use C# to
build infrastructure (libraries and business types and so on) and VB to build "top
of the stack" kinds of code (WinForms, ASP.NET, and so on).
</p>
        <p>
Neal put me squarely back on my heels with this (paraphrased) comment: Microsoft will
never do this, because Visual Basic will <em>never</em> be able to shed the image
it has gained, that of being the programming language for idiots[2].
</p>
        <p>
Wow.
</p>
        <p>
Sad thing is, he's right. Go back to the terms I suggested you think about at the
top of this blog post. If you're like most Java developers, you heard the term "EJB"
and immediately got a note of distaste in your mouth. You know that if you suggest
EJB on your next Java project, you will be ridiculed and shamed and made to stand
in the corner with the Dunce Cap on, <em>even if it makes complete sense from a technical
perspective</em>. Companies are choosing instead to build their own transactional-oriented
client/server middleware infrastructure, just to avoid the "shame" of using EJB. Because,
as we all know, you just can't test EJB.
</p>
        <p>
Which, by the way, is a fallacy, and always has been. Oh, I know, you meant you can't <em>unit</em>-test
EJB, but that's a fallacy too. It's <a href="http://openejb.apache.org/">always been
testable</a>, to the same degree that any servlet application has been testable, it's
just that nobody wanted to take the time to figure out how to test it effectively,
particularly not once Rod Johnson had unleashed Spring upon the world and Made Everything
Better(TM) (or, at least, XML configurable, which is better... right?).
</p>
        <p>
Static typing suffers the same kind of negative prejudice today. Suggest that C++
has a place in the world, and you will be kicked to the curb by any Right-Thinking
Technical Leader. Suggest that C++ has a place on your next project, and you're likely
to get sternly reprimanded, possibly even cut loose from the project. Suggest <em>anything</em> that
doesn't fit with the Way We Build Software Today, and you're swimming upstream, either
with management or with your fellow developers.
</p>
        <p>
All because they fall prey to technical folk etymology. They bend the context around
the phrases in question to mean something entirely different than what the words actually
mean, and as a result, the words take on an aura of snarling, bitter distaste, or,
worse, angelic euphoric enlightenment.
</p>
        <p>
Domain-specific languages are the new phrase of the moment, and its emotional context
is being built as we speak. Functional languages will be there sometime next year
or the year after. For both, the euphoria is growing, and for each, in some period
of <em>n</em> (three, maybe four) years will be crashing just as hard as they were
built up, just as Ruby's and Visual Basic's and COM's and EJB's and WS-*'s and other
technologies have done before it. It's as predictable as the flow of alcohol at an
MVP Summit, or the consumption of either caffeine at an all-night code frenzy.
</p>
        <p>
Other industries have varying relationships with this notion of context: the medical
field seems to be almost as susceptible to it as we are, particularly the area of
weight management and holistic health (remember the water diet? the South Beach diet?
the no-sodium diet? the low-cholesterol diet?), whereas traditional engineering disciplines,
such as electrical and construction disciplines, seem far less vulnerable to "the
hip new thing of the day". I'm not sure why this is, quite honestly, except that software
and medicine share the similar characteristics of a rapid influx of new information
on a regular, even daily, basis.
</p>
        <p>
People often call me a contrarian, a technical fuddy-duddy who refuses to embrace
anything new or anything "bleeding-edge". In many respects, I welcome and accept that
label, but frankly, I bristle at the implicit "you just don't want to learn anything
new" accusation, because it's a gross misunderstanding and hideous misinterpretation
of what I'm <em>really</em> trying to do: Distance myself from the emotional context
surrounding a technology, and examine it through the lens of dispassionate observation.
</p>
        <p>
In short, I actively seek to defeat technical folk etymology, if only in the small
area I personally can affect.
</p>
        <p>
Do you?
</p>
        <p>
 
</p>
        <p>
 
</p>
        <p>
 
</p>
        <p>
[1] <em>That particular discussion will have to wait for a different blog post on
a different day.</em></p>
        <p>
[2] <em>I should point out, before the hate mail comes flooding in, that this isn't
Neal's own opinion, nor mine--witness my post on "Mort means productivity". What he--and
I--refer to here is the reputation Visual Basic has garnered, not the fact surrounding
it. And if you care to argue that point, then you're not paying attention to the relative
average salary numbers between C# and Visual Basic developers. The laws of economics
do not lie.</em></p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6309b523-4c9d-4933-9d2c-b35dd4f16573" />
        <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>Do you fall prey to technical folk etymology?</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,6309b523-4c9d-4933-9d2c-b35dd4f16573.aspx</guid>
      <link>http://blogs.tedneward.com/2008/04/16/Do+You+Fall+Prey+To+Technical+Folk+Etymology.aspx</link>
      <pubDate>Wed, 16 Apr 2008 11:08:46 GMT</pubDate>
      <description>&lt;p&gt;
From &lt;a href="http://en.wikipedia.org/wiki/Folk_etymology"&gt;Wikipedia&lt;/a&gt; (itself a
source of conceptual folk etymology, but that's another rant):
&lt;/p&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;
A commonly held misunderstanding of the origin of a particular word, a false etymology&lt;/li&gt;
&lt;li&gt;
"The popular perversion of the form of words in order to render it apparently significant";
"the process by which a word or phrase, usually one of seemingly opaque formation,
is arbitrarily reshaped so as to yield a form which is considered to be more transparent"&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;
What do I mean by "technical folk etymology"? 
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
If you're a Java developer, consider the term &lt;em&gt;EJB&lt;/em&gt;. No, I mean, seriously
think about it for a moment. What images are conjured before your eyes when you do
so? Horrendous APIs, hideous deployment requirements, complete untestability, and
something that takes forty-five minutes to start?&lt;/li&gt;
&lt;li&gt;
If you're a Ruby developer, consider the phrase &lt;em&gt;static typing&lt;/em&gt;. Same sort
of reaction?&lt;/li&gt;
&lt;li&gt;
If you're a .NET developer, try on &lt;em&gt;COM&lt;/em&gt; or &lt;em&gt;COM+&lt;/em&gt; or even &lt;em&gt;ATL&lt;/em&gt;.
Mystifying collections of code repeated by rote, cut-and-pasted from that very first
project you built by hand from &lt;em&gt;Inside OLE 2&lt;/em&gt;, and once you got it to work,
served as your basic template for every other COM/MTS/COM+ entity you ever built?&lt;/li&gt;
&lt;li&gt;
Or, if you're any of these, how about &lt;em&gt;Visual Basic&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;
Or maybe &lt;em&gt;Web services&lt;/em&gt;, specifically all those WS-* specifications?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
As the MVP Summit Product Team dinners wound down here in Redmond tonight, I found
myself at a table with (not surprisingly) Neal Ford and Venkat Subramaniam, two of
my close friends from the NFJS tour, and who should join us but first Amanda Silver
(lately of the Office team, but with her heart still firmly rooted in her Visual Basic
dev days), then Don Box (lately of the Oslo team) and Chris Sells (also lately of
the Oslo team), and a rousing discussion around the concept of DSLs--domain specific
languages--arose, largely because Don wanted to sound out Venkat and Neal on the subject.
&lt;/p&gt;
&lt;p&gt;
Listening to the conversation (Don was mostly interested in Neal and Venkat's opinions,
so I just relaxed and listened for the most part), I realized that the discussion
was entirely rooted in this concept of &lt;em&gt;context&lt;/em&gt;, that ephemeral structure
surrounding a concept that gives it shape and color and taste and the other aesthetic
qualities that lead us to "like" or "dislike" or "accept" or "reject" certain concepts.
Don held the position--either for arguments' sake or because he believes it, I'm not
sure which--that domain-specific languages lose context too easily once stored on
the file system, in ways that data does not. His test was to suggest "What if a random
piece of text drops into my email, how do I know what consumes this text?" The answer,
of course, is that you don't, unless you somehow have a context by which to understand
a piece of text, in many cases based solely on nothing more than filesystem extension,
or MIME type, or the "#!/bin/..." line that precedes many shell scripts, and so on.
&lt;/p&gt;
&lt;p&gt;
Interestingly enough, as I drove home after the dinner, I realized that the conversation
echoed an exchange Neal and Venkat and I were having in the car on the way over, about
how Microsoft (I think) is making a &lt;em&gt;huge&lt;/em&gt; mistake by looking to make C# more
dynamic in nature[1]. My position was (and is) that Microsoft needs to differentiate
the two key languages they offer--C# and Visual Basic--and an obvious way to do so
would be to designate VB as the official "dynamic language" for the CLR, and C# as
the official "static language" for the CLR, and encourage developers to use C# to
build infrastructure (libraries and business types and so on) and VB to build "top
of the stack" kinds of code (WinForms, ASP.NET, and so on).
&lt;/p&gt;
&lt;p&gt;
Neal put me squarely back on my heels with this (paraphrased) comment: Microsoft will
never do this, because Visual Basic will &lt;em&gt;never&lt;/em&gt; be able to shed the image
it has gained, that of being the programming language for idiots[2].
&lt;/p&gt;
&lt;p&gt;
Wow.
&lt;/p&gt;
&lt;p&gt;
Sad thing is, he's right. Go back to the terms I suggested you think about at the
top of this blog post. If you're like most Java developers, you heard the term "EJB"
and immediately got a note of distaste in your mouth. You know that if you suggest
EJB on your next Java project, you will be ridiculed and shamed and made to stand
in the corner with the Dunce Cap on, &lt;em&gt;even if it makes complete sense from a technical
perspective&lt;/em&gt;. Companies are choosing instead to build their own transactional-oriented
client/server middleware infrastructure, just to avoid the "shame" of using EJB. Because,
as we all know, you just can't test EJB.
&lt;/p&gt;
&lt;p&gt;
Which, by the way, is a fallacy, and always has been. Oh, I know, you meant you can't &lt;em&gt;unit&lt;/em&gt;-test
EJB, but that's a fallacy too. It's &lt;a href="http://openejb.apache.org/"&gt;always been
testable&lt;/a&gt;, to the same degree that any servlet application has been testable, it's
just that nobody wanted to take the time to figure out how to test it effectively,
particularly not once Rod Johnson had unleashed Spring upon the world and Made Everything
Better(TM) (or, at least, XML configurable, which is better... right?).
&lt;/p&gt;
&lt;p&gt;
Static typing suffers the same kind of negative prejudice today. Suggest that C++
has a place in the world, and you will be kicked to the curb by any Right-Thinking
Technical Leader. Suggest that C++ has a place on your next project, and you're likely
to get sternly reprimanded, possibly even cut loose from the project. Suggest &lt;em&gt;anything&lt;/em&gt; that
doesn't fit with the Way We Build Software Today, and you're swimming upstream, either
with management or with your fellow developers.
&lt;/p&gt;
&lt;p&gt;
All because they fall prey to technical folk etymology. They bend the context around
the phrases in question to mean something entirely different than what the words actually
mean, and as a result, the words take on an aura of snarling, bitter distaste, or,
worse, angelic euphoric enlightenment.
&lt;/p&gt;
&lt;p&gt;
Domain-specific languages are the new phrase of the moment, and its emotional context
is being built as we speak. Functional languages will be there sometime next year
or the year after. For both, the euphoria is growing, and for each, in some period
of &lt;em&gt;n&lt;/em&gt; (three, maybe four) years will be crashing just as hard as they were
built up, just as Ruby's and Visual Basic's and COM's and EJB's and WS-*'s and other
technologies have done before it. It's as predictable as the flow of alcohol at an
MVP Summit, or the consumption of either caffeine at an all-night code frenzy.
&lt;/p&gt;
&lt;p&gt;
Other industries have varying relationships with this notion of context: the medical
field seems to be almost as susceptible to it as we are, particularly the area of
weight management and holistic health (remember the water diet? the South Beach diet?
the no-sodium diet? the low-cholesterol diet?), whereas traditional engineering disciplines,
such as electrical and construction disciplines, seem far less vulnerable to "the
hip new thing of the day". I'm not sure why this is, quite honestly, except that software
and medicine share the similar characteristics of a rapid influx of new information
on a regular, even daily, basis.
&lt;/p&gt;
&lt;p&gt;
People often call me a contrarian, a technical fuddy-duddy who refuses to embrace
anything new or anything "bleeding-edge". In many respects, I welcome and accept that
label, but frankly, I bristle at the implicit "you just don't want to learn anything
new" accusation, because it's a gross misunderstanding and hideous misinterpretation
of what I'm &lt;em&gt;really&lt;/em&gt; trying to do: Distance myself from the emotional context
surrounding a technology, and examine it through the lens of dispassionate observation.
&lt;/p&gt;
&lt;p&gt;
In short, I actively seek to defeat technical folk etymology, if only in the small
area I personally can affect.
&lt;/p&gt;
&lt;p&gt;
Do you?
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
[1] &lt;em&gt;That particular discussion will have to wait for a different blog post on
a different day.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
[2] &lt;em&gt;I should point out, before the hate mail comes flooding in, that this isn't
Neal's own opinion, nor mine--witness my post on "Mort means productivity". What he--and
I--refer to here is the reputation Visual Basic has garnered, not the fact surrounding
it. And if you care to argue that point, then you're not paying attention to the relative
average salary numbers between C# and Visual Basic developers. The laws of economics
do not lie.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=6309b523-4c9d-4933-9d2c-b35dd4f16573" /&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,6309b523-4c9d-4933-9d2c-b35dd4f16573.aspx</comments>
      <category>.NET</category>
      <category>C++</category>
      <category>F#</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Parrot</category>
      <category>Ruby</category>
      <category>Visual Basic</category>
      <category>XML Services</category>
    </item>
    <item>
      <trackback:ping>http://blogs.tedneward.com/Trackback.aspx?guid=9b36e213-f072-4f86-ae29-bbb66a12eb45</trackback:ping>
      <pingback:server>http://blogs.tedneward.com/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.tedneward.com/PermaLink,guid,9b36e213-f072-4f86-ae29-bbb66a12eb45.aspx</pingback:target>
      <dc:creator>Ted Neward</dc:creator>
      <wfw:comment>http://blogs.tedneward.com/CommentView,guid,9b36e213-f072-4f86-ae29-bbb66a12eb45.aspx</wfw:comment>
      <wfw:commentRss>http://blogs.tedneward.com/SyndicationService.asmx/GetEntryCommentsRss?guid=9b36e213-f072-4f86-ae29-bbb66a12eb45</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
From the "Where the hell was I that day?" Department....
</p>
        <blockquote>
          <p>
The JRuby community is pleased to announce the release of JRuby 1.1! 
</p>
          <p>
Homepage: <a href="http://www.jruby.org/">http://www.jruby.org/</a><br />
Download: <a href="http://dist.codehaus.org/jruby/">http://dist.codehaus.org/jruby/</a></p>
          <p>
JRuby 1.1 is the second major release for our project.  The main goal for 1.1<br />
has been improving performance.  We have made great strides in performance<br />
during the last nine months.  There have been more and more reports of<br />
applications exceeding Ruby 1.8.6 performance; we are even beating Ruby 1.9<br />
in some microbenchmarks. ... 
</p>
          <p>
            <em>(Source: </em>
            <a title="http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released" href="http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released">
              <em>http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released</em>
            </a>
            <em>)</em>
          </p>
        </blockquote>
        <p>
Congratulations to Thomas and Charlie and the rest of the JRuby team; I'm looking
forward to playing around with JRuby, specifically in AOT/compiled mode, and for using
it as Ruby was originally intended, as a scripting language to make working with systems
(in this case, the JVM) easier, a la JMX client scripts to stop-and-start a web application
during development/deployment.
</p>
        <img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=9b36e213-f072-4f86-ae29-bbb66a12eb45" />
        <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>JRuby 1.1 released</title>
      <guid isPermaLink="false">http://blogs.tedneward.com/PermaLink,guid,9b36e213-f072-4f86-ae29-bbb66a12eb45.aspx</guid>
      <link>http://blogs.tedneward.com/2008/04/12/JRuby+11+Released.aspx</link>
      <pubDate>Sat, 12 Apr 2008 23:40:56 GMT</pubDate>
      <description>&lt;p&gt;
From the "Where the hell was I that day?" Department....
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
The JRuby community is pleased to announce the release of JRuby 1.1! 
&lt;p&gt;
Homepage: &lt;a href="http://www.jruby.org/"&gt;http://www.jruby.org/&lt;/a&gt;
&lt;br&gt;
Download: &lt;a href="http://dist.codehaus.org/jruby/"&gt;http://dist.codehaus.org/jruby/&lt;/a&gt; 
&lt;p&gt;
JRuby 1.1 is the second major release for our project.&amp;nbsp; The main goal for 1.1&lt;br&gt;
has been improving performance.&amp;nbsp; We have made great strides in performance&lt;br&gt;
during the last nine months.&amp;nbsp; There have been more and more reports of&lt;br&gt;
applications exceeding Ruby 1.8.6 performance; we are even beating Ruby 1.9&lt;br&gt;
in some microbenchmarks. ... 
&lt;p&gt;
&lt;em&gt;(Source: &lt;/em&gt;&lt;a title="http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released" href="http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released"&gt;&lt;em&gt;http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
Congratulations to Thomas and Charlie and the rest of the JRuby team; I'm looking
forward to playing around with JRuby, specifically in AOT/compiled mode, and for using
it as Ruby was originally intended, as a scripting language to make working with systems
(in this case, the JVM) easier, a la JMX client scripts to stop-and-start a web application
during development/deployment.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=9b36e213-f072-4f86-ae29-bbb66a12eb45" /&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,9b36e213-f072-4f86-ae29-bbb66a12eb45.aspx</comments>
      <category>.NET</category>
      <category>Java/J2EE</category>
      <category>Languages</category>
      <category>Ruby</category>
    </item>
  </channel>
</rss>