<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6928325842095718321</id><updated>2012-01-03T13:06:45.010-05:00</updated><category term='ruby'/><category term='wcf'/><category term='xml'/><category term='technology'/><category term='linq'/><category term='active directory'/><category term='continuous integration'/><category term='javascript'/><category term='IoC'/><category term='erlang'/><category term='silverlight'/><category term='REST'/><category term='ajax'/><category term='TFS'/><category term='security'/><category term='programming'/><category term='localization'/><category term='ALT.NET'/><category term='Clojure'/><category term='F#'/><category term='workflow foundation'/><category term='Apple'/><category term='LDAP'/><category term='C#'/><category term='MEF'/><category term='RavenDB'/><category term='off-topic'/><category term='TDD'/><category term='agile'/><category term='sql'/><category term='powershell'/><category term='cruisecontrol'/><category term='telerik'/><category term='asp.net'/><category term='performance'/><category term='architecture'/><category term='review'/><category term='sql server 2005'/><category term='xp'/><category term='todo list'/><category term='mbunit'/><category term='.NET'/><title type='text'>IFormattable</title><subtitle type='html'>Thoughts, experiments, and opinions of a software developer... chronicling my journey in technology.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default?start-index=101&amp;max-results=100'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>123</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1347536774822127152</id><published>2011-08-02T22:47:00.009-04:00</published><updated>2011-08-03T01:01:41.762-04:00</updated><title type='text'>Fostering a Culture of Effective Feedback</title><content type='html'>&lt;p&gt;As of the last few months, I've had numerous occasions to ruminate on the purpose, efficacy, and goals of feedback.  It's a risky business to give someone unsolicited feedback, for example, and it is difficult to do so tactfully.  So, most folks simply don't bother to the detriment of themselves and the person being deprived of needful insight into their &lt;a href="http://en.wikipedia.org/wiki/Shadow_(psychology)"&gt;blind spots&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In a retrospective today we were asked some poignant questions about how to foster a feedback culture.  Initially as a joke, I challenged our project sponsor to use the word as an acronym to define itself, a la "GNU".  As I began thinking about my own description of effective feedback, some ideas came to mind.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3 style="font-variant:small-caps"&gt;FEEDBACK&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Fast&lt;/span&gt;&amp;mdash;feedback should be given as close in time to the event that triggered the feedback as possible.  Feedback given too long after an event risks being revisionist, or perceived as such, due to our fallible memories, making it more difficult to agree on what happened.  Feedback given soon after an precipitating event will be received in context and have a proportionately stronger impact. It's much easier to take remedial, corrective action given incremental, regular feedback; likewise, regular positive feedback can raise morale and engender positive &lt;em&gt;espirit de corps&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Expected&lt;/span&gt;&amp;mdash;make no mistake, the surest way to have feedback blow up in your face is for it to find your interlocutor surprised to be receiving it.  Different social situations have different norms of feedback expectations.  In most situations that come to mind, thoughtful feedback from a "superior" to a "subordinate" is almost assuredly going to be received gladly, whereas the reverse is nearly equally likely to not go so well.  A similar gradient exists between a senior and a junior employee, and peers are not likely to expect any feedback from each other at all.  The challenge is a cultural one, and cultures are shaped by their rituals.  Effort must be expended to normalize feedback, making it an expected part of day-to-day life in the culture.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Empathetic&amp;mdash;&lt;/span&gt;how would you feel if you were receiving the feedback you intend to give?  This is the most important question you can ask as it informs all other aspects of feedback.  Some feedback can be delivered within earshot of others; often a quick private chat is more apropos.  Before ever giving feedback, try to imagine being the receiver.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Definite&amp;mdash;&lt;/span&gt;feedback should not be opinion and conjecture. Details should be concrete and accurate.  The feedback must be clear.  Saying, "you are acting like a jerk," is spurious; "I am put on edge when say X, and I fear others may be as well," does not invite interpretation nor ascribe subjective qualities.  If the receiver cannot understand the feedback, it is likely to have a deleterious effect on the relationship.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Beneficial&amp;mdash;&lt;/span&gt;it should be obvious that if there is not benefit to the team or the receiver the feedback will likely have a negative effect.  What's important is that you can articulate the benefit of giving the feedback.  If the receiver acts in a responsible way vis-&amp;agrave;-vis the feedback, how does our situation improve?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Actionable&amp;mdash;&lt;/span&gt;articulating the benefit necessarily highlights the question of appropriate actions that address the feedback.  If feedback is not actionable, it cannot be beneficial. The giver and receiver should work together to identify action that can be taken to incorporate the feedback.  This discussion can lead to a fuller understanding of the feedback that was given and how it is manifested in behavior.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Considered&amp;mdash;&lt;/span&gt;much worse than delaying feedback too long is a rash, immediate response.  The qualities that make for effective feedback are not to be evaluated retroactively; they should be considered before the feedback is given in order to ensure good outcomes.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-variant:small-caps;font-size:larger"&gt;Kind&amp;mdash;&lt;/span&gt;"If you can't say something [nicely], say nothing." It is entirely possible to provide, accurate, beneficial, efficacious feedback and to do so with a negative spirit.  Feedback is not revenge; it is a dish best served warm.  Kindness is king, and if you want to get the most of a feedback culture, it must be compulsory.  The goal of feedback is to give rise to high functioning teams, and a key indicator of such teams is &lt;a href="http://iformattable.blogspot.com/2011/07/how-agile-makes-you-dumb-or-smart.html"&gt;social sensitivity&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1347536774822127152?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1347536774822127152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1347536774822127152' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1347536774822127152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1347536774822127152'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2011/08/fostering-culture-of-effective-feedback.html' title='Fostering a Culture of Effective Feedback'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6045620600226698346</id><published>2011-07-27T00:34:00.004-04:00</published><updated>2011-07-27T01:02:33.009-04:00</updated><title type='text'>How Agile Makes You Dumb (or Smart)</title><content type='html'>&lt;p&gt;While many of the thought leaders in the Agile community decry the inexorable march toward banal, brand-oriented adoption, entreating us to internalize the principles of Agile and not blindly follow prescriptive practices, proscribing such phrases as “being agile” or “doing agile”, there remains an elusiveness to what makes Agile work.  We’ve heard the stories: high-functioning teams churning through a product backlog, steadily delivering week after week. Nothing impedes these paragons of Agile values, while the rest of us struggle.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The picture looks quite different for most Agile teams: stories are estimated inaccurately; pair performance varies widely; velocity suffers at the mercy of technical debt; knowledge silos emerge; defect cycles lengthen; customers start getting frustrated. Very soon managers start trying to identify problems with the process, invariably looking for their keys under the lamplight instead of where they dropped them—looking for problems they can solve instead of solving the problems.&lt;/p&gt;&lt;p&gt;One cold Chicago winter night, Robert C. Martin, “Uncle Bob”, related a tale wherein a company engaged in the adoption of Scrum saw a very promising early spike in velocity followed by decline.  They brought in Ken Schwaber, looking for the problems in their Agile practices and methodologies.  With some tweaking they saw another bump in velocity but were too soon again swimming upstream.   The Scrum Master himself next recommended they bring in Uncle Bob.  They had done all the Agile stuff right—everything but the engineering.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As Uncle Bob relates the tale, Extreme Programming (XP) neatly codified the marriage of what we now call Agile with fundamental, essential software engineering principles and techniques.  Unfortunately, most managers have very little aptitude for or mastery of the engineering, and naturally focus on those things they perceive they can directly impact. Consequently, the Agile aspects got top billing, and the engineering relegated to understudy. The unequivocal result is underperforming teams and projects.  Agile made them dumb.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;“Whoa! What about those teams who are delivering,” I hear you ask! Those fabled unicorns of the software industry where every iteration delivers substantial business value and change is accommodated like an accidental in a Kind of Blue reprise… surely they’ve got the system right.  Or, maybe it isn’t the system at all.  That’s the pretext of the Agile guru’s foreboding about “doing Agile”—there is no system, no prescription… There’s just really smart, wise, motivated people working together effectively.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Organizations are driven to Agile practices for a number of reasons, but few managers would suggest that Agile makes their teams smarter.  But that is truly the secret sauce of what makes so-called Agile teams successful.  They have a high collective intelligence. As a group they can overcome a great many obstacles and continue performing at a high level. They create fewer problems for themselves and deal swiftly and precisely with the problems they don’t create. They work.&lt;/p&gt;&lt;p&gt;Recent research into high-performing teams—those with a high collective intelligence—shows two distinct and surprising facts.  First, individual intelligence is only weakly correlated with team performance.  Second, there is a strong positive correlation with the number of women on the team and team performance.  Women make teams smarter than men.  Full Stop.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Why? Those of us with a Y-chromosome will be relieved to know that there is a similar correlation with social sensitivity and team performance.  Women generally rate significantly better at social sensitivity than men.  The researcher states, "what it suggests is that if you don't know the social sensitivity of a group, it is a better bet to include females than not."  "The team also found that groups in which members took turns speaking were more collectively intelligent." (New Scientist)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In most enterprises, groups develop software.  The engineering aspects of software development are extremely difficult and require a great deal of intelligence.  It stands to reason the groups with high emotional intelligence are better at developing software than not.  A bunch of hotshots don’t make for a smart group. So how would we go about maximizing the collective intelligence of development team?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;“…took turns speaking…” Sound familiar?  Stand-ups and pair programming, when effectively fostered, should result in an effective increase in the social sensitivity of the individuals on the team.  The corollary is that teams that are good at stand-ups and pairing are better at delivering software.  Agile makes them smarter.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Managers should be cogitating on ways to increase the social sensitivity of their developers.  To those that can’t break their addiction to quick fixes: fire all the asshole, prima dons and use the windfall to hire some competent women.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6045620600226698346?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6045620600226698346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6045620600226698346' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6045620600226698346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6045620600226698346'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2011/07/how-agile-makes-you-dumb-or-smart.html' title='How Agile Makes You Dumb (or Smart)'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8763473181803864517</id><published>2011-02-21T14:47:00.003-05:00</published><updated>2011-02-21T14:56:40.848-05:00</updated><title type='text'>Code qua Art</title><content type='html'>The positronic sqrt program in rod logic is art.  Damian Conway, Thoughtstream: "&lt;a href="http://blip.tv/file/1145545/"&gt;Temporally Quaquaversal Virtual Nanomachine Programming In Multiple Topologically Connected Quantum-Relativistic Parallel Timespaces...Made Easy!&lt;/a&gt;"&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://mamememo.blogspot.com/2010/09/qlobe.html"&gt;Qlobe&lt;/a&gt; is art.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8763473181803864517?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8763473181803864517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8763473181803864517' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8763473181803864517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8763473181803864517'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2011/02/code-qua-art.html' title='Code qua Art'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7091905364332266467</id><published>2010-09-06T15:33:00.007-04:00</published><updated>2010-09-08T19:20:48.806-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='xp'/><title type='text'>Real Software Engineering &amp; The Agile Value Graph</title><content type='html'>&lt;div&gt;Glen Vanderburg (@glv) recently reprised his talk "Real Software Engineering" as a keynote at Ruby Hoedown 2010. In the words of Jim Weirich "every software developer should hear this"... Motivated to see what all the buzz was about, I watched the recording of the same talk from earlier this year (&lt;a href="http://j.mp/9dqw9Q"&gt;http://j.mp/9dqw9Q&lt;/a&gt;).  The thesis is simple--Agile IS the state of the art in Software Engineering, not some sort of anti-engineering, or accidental engineering.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This, of course, is not news to most practioners, but his approach to defending this thesis is pretty novel, I think. He begins by quoting a paper from the proceedings of a NATO computing conference in 1969:&lt;/div&gt;&lt;div&gt;"A software system can best be designed if the testing is interlaced with the designing instead of being used after the design."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pretty compelling huh?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;He then frames the inception and growth of the Waterfall methodology as stemming from two errors: 1) the misinterpretation of a 1970 paper by Dr. Winston Royce by Pointy-Haired Bosses (a la &lt;a href="http://www.paulgraham.com/icad.html"&gt;http://www.paulgraham.com/icad.html&lt;/a&gt;), and 2) the Barry Boehm "cost of errors" graph had a hidden bias in that only Waterfall projects were measured.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope you are interested enough to check out the talk.  I couldn't do it justice here. And you will find he draws several other valuable conclusions.  Personally, I was compelled to read another of Vanderburg's papers referenced at the end of this talk, "Extreme Programming Annealed" (&lt;a href="http://vanderburg.org/Writing/xpannealed.pdf"&gt;http://vanderburg.org/Writing/xpannealed.pdf&lt;/a&gt;), published in ACM SIGPLAN proceedings 2005.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In this paper he attempts an exposition of the coupling between the 12 (+1) XP practices to understand how to cope with a situation where one of the practices is disallowed.  I won't recapitulate that work here, but he did present an interesting arrangement of the practices in relation to time. To me there was an immediate correlation between the cost of errors graph and this arrangement.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As providence would have it, I had recently been thinking about visual depictions of the "value" of Agile/XP.  The pointy-haired bosses need something simple(-ish) to understand why these Agile practices are important.  Ideally, they'd like to see how they affect the bottom-line; everything in business is a trade-off, after all...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After a few iterations, I came up with something that I hope Edward Tufte wouldn't snarl at and Kent Beck might nod at approvingly.  I present you, the "Value of Agile Methods"&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_FQ1igFTZD04/TIgaJfeMD8I/AAAAAAAAAHI/jZYLMvixQFM/s1600/AgileValueGraph.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 272px;" src="http://4.bp.blogspot.com/_FQ1igFTZD04/TIgaJfeMD8I/AAAAAAAAAHI/jZYLMvixQFM/s400/AgileValueGraph.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5514686494084435906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Some notes:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;P(Error) is the probability of introducing an error.  I make the facile assumption that there is a linear relationship between the frequency with which an activity is performed and the frequency of errors introduced by that activity.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;P(Error&lt;sub&gt;Agile&lt;/sub&gt;) is the result of flattening of P(Error) by four particular Agile methods (see downward arrows); in Vanderburg's paper these are called noise-filters&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the "x-axis" is a logarithmic arrangement of time; in the case of the probability of error curves, this is how frequently an activity is performed; in the case of the cost of errors curve, it is the length of an interval between when an error is introduced and when it is discovered&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the groupings of the time axis represent the "epochs" of different practices: engineering (code, test, vet req's etc.); process (define requirements, team meetings, project management, etc.); and strategy (direction set from executives, market research, etc.).  There is obviously some overlap and flexibility in what activities correspond to which "epochs"&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Inferences&lt;/h3&gt;&lt;br /&gt;&lt;div&gt;I hope the graph would compel the following inferences:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Agile practices reduce the frequency of errors in engineering activities while reducing the time between when an error is introduced and when it is identified in both engineering and process epochs.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The cumulative effect of these practices is to reduce the probability of errors and limit the overall cost of errors.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Engineering errors are invariably frequent and cheap to fix when applying Agile practices, in stark contrast to errors in strategic decisions that are both infrequent and very, very expensive.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Call to Action&lt;/h3&gt;&lt;br /&gt;&lt;div&gt;If you think this graph is interesting, flawed, has potentional, etc. I encourage you to iterate it and share it.&lt;br /&gt;&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"&gt;&lt;img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /&gt;&lt;/a&gt;&lt;br /&gt;This work is licensed under a &lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"&gt;Creative Commons Attribution-ShareAlike 3.0 Unported License&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7091905364332266467?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7091905364332266467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7091905364332266467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7091905364332266467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7091905364332266467'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/09/real-software-engineering-agile-value.html' title='Real Software Engineering &amp; The Agile Value Graph'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_FQ1igFTZD04/TIgaJfeMD8I/AAAAAAAAAHI/jZYLMvixQFM/s72-c/AgileValueGraph.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1231575020516459711</id><published>2010-09-04T12:00:00.005-04:00</published><updated>2010-09-04T16:33:05.386-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Hipster Programming: Coding in F# on Mac OS X</title><content type='html'>&lt;p&gt;The vitriol towards Microsoft has a long and graceless tradition with a lexicon sporting such inventive neologisms as the venerable "M$FT" and the puerile "Total Failure System" in reference to Team Foundation Server (TFS). Oh, how these countless little slights must wound the souls of those folks toiling away under the yoke of stodgy corporate masters!  Their inner light having been dimmed and filtered by a soulless, crushing capitalism so much so that they unconsciously embrace their sameness, adopting a uniform of pique polo shirts and khaki pants.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The iconoclasts, the individualists, the thinkers--these bear the nome d'guerre "Rubyist", "Rails aficionado", "Python hacker", "open source developer".  You will know them not by their similarity but their diversity, their vestiture definitively anti-establishment and their mocking of any tool that you don't have to download from github and compile from source.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As in all things, there is a middle road whose pedestrians are accused of compromise with the Devil by one side and "just trying to be different" on the other. Yet in this camp we find many sagacious, experienced craftspeople who have spent time in both camps.  With the reader's indulgence, I shall call them hipster programmers.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For what its worth, I consider myself a hipster programmer, as evinced by how I spent my morning.  Having been developing in .NET for nearly a decade and of recent years drawn strongly to functional programming, I am of course learning F#. But, I'm also experimenting with Erlang, Ruby, and more recently Clojure.  As far as platforms go, you've got a lot of choice these days: Windows, Linux, Mac OS X. With Windows you certainly need Cygwin and a git port. Linux is probably the easiest to get going on but lacks some of the day-to-day niceties (e.g. iTunes). Mac OS X can't be (legally) virtualized, so it makes an obvious choice as the base system.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;My work machine is a MacBook Pro running VMWare Fusion.  My recent explorations of Clojure have kept my exclusive in the Java tools domain--Maven, Ant, Netbeans, etc., but the Chicago Clojure user group recently invited Dr. David Miller to come talk about clojure-clr, a C# implementation of Clojure for the CLR, very hipster!  What could be cooler than that?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Well, porting clojure-clr to F# of course!&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Sure, I could fire up Fusion and VS 2010 and start rocking, but I like to begin with the end in mind, namely moving seamlessly between writing code in Clojure targetting the CLR and the JVM.  I'd like to use similar tool chains.  And, I'd like to present to a group of the cool kids in their native tongue.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The first step is getting an environment setup.  Robert Pickering has a &lt;a href="http://strangelights.com/fsharp/MonoLinux.aspx"&gt;great article to get Mono setup on Mac OS X&lt;/a&gt;.   Don't skip the 'sudo install-mono.sh' step.  At the time of this writing their is a strange error in his instructions regarding the mono.snk file.  The install-mono.sh file makes this pretty clear, so just ignore that part.  Basically, you have to give the F# assemblies a proper strong name to add it to the GAC.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, I love vim--it was my first code editor--but the Ruby kids have been using TextMate, so let's use that since someone kindly shared &lt;a href="http://code.google.com/p/fsharp-tmbundle/"&gt;an F# bundle&lt;/a&gt;.  That bundle uses &lt;a href="http://iterm.sourceforge.net/"&gt;iTerm&lt;/a&gt; to evaluate function in F# interactive, so we'll need that too.  Finally, we need to alias "fsi" to run F# interactive using Mono, so the TextMate bundle will run it properly. Edit ~/.profile adding this command.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;alias fsi='mono ~/path/to/fsi.exe'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;So we've got the beginnings of a build environment going; what's next?&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Get a branch going on github, referencing the clojure-clr project&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Get a build system stack setup (Maven? Rake?)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Find an unit testing suite for F#/Mono/Mac OS X&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Start hacking&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1231575020516459711?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1231575020516459711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1231575020516459711' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1231575020516459711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1231575020516459711'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/09/hipster-programming-coding-in-f-on-mac.html' title='Hipster Programming: Coding in F# on Mac OS X'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4549258813145428287</id><published>2010-08-09T17:16:00.001-04:00</published><updated>2010-08-10T10:04:51.415-04:00</updated><title type='text'>REST: The Uniform Interface</title><content type='html'>&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. (Fielding’s Dissertation, Sec. 5.1.5)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Street RESTers will immediately submit that the uniform interface is simply having a URL that reads: “/controller/method/id”.&amp;#160; While this maps nicely to their server-side MVC application, it does not represent the necessary constraints to satisfy the uniform interface of REST.&lt;/p&gt;  &lt;p&gt;In the dissertation Fielding defines four interface constraints for REST:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Identification of resources &lt;/li&gt;    &lt;li&gt;Manipulation of resources through representations &lt;/li&gt;    &lt;li&gt;Self-descriptive messages &lt;/li&gt;    &lt;li&gt;Hypermedia as the engine of application state &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The benefits realized by the uniform interface are best understood in terms of the effects upon the architecture when applying these constraints.&lt;/p&gt;  &lt;h2&gt;Identification of Resources&lt;/h2&gt;  &lt;p&gt;To understand this constraint we must first have a solid definition of a resource.&amp;#160; A resource is some named entity that is provided by our application.&amp;#160; On the web we generally use URLs to name these entities.&amp;#160; The normal notion of a URL is “a link to a web page”.&amp;#160; A URL is a special kind of Uniform Resource Identifier.&amp;#160; REST constrains the URIs we use in a few ways:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The semantics of the mapping of a URI to a resource must not change.&amp;#160; So, while the contents of example.com/Top10 can change over time, the thing that it names—e.g. the top 10 examples of the day—cannot. &lt;/li&gt;    &lt;li&gt;A resource’s identity is independent of its value. So, two resources could point to the same value at some point in time, but they are not the same resource. &lt;/li&gt;    &lt;li&gt;The provider of a resource is solely responsible for maintaining the semantic validity of the URI.&amp;#160; This just means that we should choose good URLs that are easy to maintain. &lt;/li&gt;    &lt;li&gt;A URI should not contain any reference to the media type used to represent the resource; example.com/Top10/json is verboten. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This seems like a simple constraint, and it is, but its significant benefits include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;There is just one way to get at a particular resource. &lt;/li&gt;    &lt;li&gt;The value of a resource at a point in time (representation) can be served up in any appropriate media type at the time it is requested, based on the characteristics of the request (Accept header). &lt;/li&gt;    &lt;li&gt;Since the semantics of resource identifiers are static, and the media type of the representation is determined at the time of the request, clients dependent on a resource do not have to change any identifiers in order for the content type to change. &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Manipulation of Resources through Representations&lt;/h2&gt;  &lt;p&gt;The abstract notion of a resource named by a URI is reified by a representation in a media type selected based upon the nature of the request for that resource.&amp;#160; A representation contains the data and metadata describing the data, such as the media type of the data.&amp;#160; All of the perceived work done by a server in REST architecture is initiated by a client either: a) requesting a resource whereupon the server returns a representation of that resource; b) sending a representation of a resource whereupon the server nominally mutates/creates the resource.&lt;/p&gt;  &lt;p&gt;There are additional details to the semantics of representation-based interactions, but the salient point is that URLs are not akin to call sites in a program.&amp;#160; These interactions are more akin to message passing.&lt;/p&gt;  &lt;p&gt;An important and often overlooked consequence of this constraint is that there is no distributed consistency, and so the notion of a “transactional REST” is anathema:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;REST just says that there is no consistency -- only representations that indicate state at some point in the past and an implicit grant of use for some time into the future. –&lt;a href="http://tech.groups.yahoo.com/group/rest-discuss/message/3593"&gt;Fielding on rest-discuss&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Besides decoupling the resource from a particular representation, the benefit to this approach are seen in the application of the next two constraints.&lt;/p&gt;  &lt;h2&gt;Self-Descriptive Messages&lt;/h2&gt;  &lt;p&gt;All of the details required to route, interpret, and process a message must be in the message itself.&amp;#160; This enables the communication between components to be stateless and allows messages to be cached appropriately.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;REST concentrates all of the control state into the representations received in response to interactions. The goal is to improve server scalability by eliminating any need for the server to maintain an awareness of the client state beyond the current request. (dissertation)&lt;/p&gt; &lt;/blockquote&gt;  &lt;h2&gt;Hypermedia as the Engine of Application State&lt;/h2&gt;  &lt;blockquote&gt;   &lt;p&gt;The model application is therefore an engine that moves from one state to the next by examining and choosing from among the alternative state transitions in the current set of representations. (dissertation)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is probably the least applied of the REST constraints, especially with the proliferation of AJAX clients. The core idea is that the representation given to the client will have embedded hyperlinks that completely disambiguate what actions are available to interact with the server.&lt;/p&gt;  &lt;p&gt;Dr. Fielding wrote an &lt;a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven"&gt;extended exposition of the hypermedia constraint&lt;/a&gt; wherein he makes explicit some rules that apply to a RESTful API.&amp;#160; He also says this,&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;A truly RESTful API looks like hypertext. Every addressable unit of information carries an address, either explicitly (e.g., link and id attributes) or implicitly (e.g., derived from the media type definition and representation structure). Query results are represented by a list of links with summary information, not by arrays of object representations (query is not a substitute for identification of resources).&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Lest you think you can apply REST to your architecture sans this “hypermedia constraint”, Dr. Fielding further clarifies.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;ROA is supposed to be a kind of design method for RESTful services, apparently, but most folks who use the term are talking about REST without the hypertext constraint. In other words, not RESTful at all. REST without the hypertext constraint is like pipe-and-filter without the pipes: completely useless because it no longer induces any interesting properties. (&lt;a href="http://roy.gbiv.com/untangled/2008/on-software-architecture"&gt;blog&lt;/a&gt;)&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Towards a RESTful Client&lt;/h3&gt;  &lt;p&gt;Taken together, the constraints that engender the uniform interface of REST-style architecture, in turn force certain characteristics in clients of a RESTful API.&amp;#160; Among these client characteristics are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Ability to process one or more media types available for a resource’s representation. &lt;/li&gt;    &lt;li&gt;Ability to maintain and manage state by selecting among hyperlinks. &lt;/li&gt;    &lt;li&gt;Awareness of potential inconsistency of representations. &lt;/li&gt;    &lt;li&gt;Only enters the interaction from a known entry point. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If we are building RESTful web applications, we have to supply such a client that can run in a browser.&amp;#160; For example, the user agent can navigate to the URL that identifies the client. This client is assembled in the browser via normal mechanisms for displaying a web page.&amp;#160; The various JavaScript libraries loaded then augment the capabilities of the browser to exhibit the characteristics mentioned above while interacting with the RESTful API on the server.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4549258813145428287?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4549258813145428287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4549258813145428287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4549258813145428287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4549258813145428287'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/08/rest-uniform-interface.html' title='REST: The Uniform Interface'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2860199053600277408</id><published>2010-07-25T04:34:00.001-04:00</published><updated>2010-07-25T04:35:22.399-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Clojure'/><title type='text'>Dynamic Dispatch (Multimethods) in C#?</title><content type='html'>&lt;p&gt;I’ve recently become enamored with the multimethods system of Clojure, as well as its approach to polymorphism and “type” hierarchies in general.&amp;#160; Having never heard the term, I consulted &lt;a href="http://en.wikipedia.org/wiki/Multimethods"&gt;Wikipedia about multimethods&lt;/a&gt;, hoping to have its origins elucidated, though it appears it is simply a synonym of multiple dispatch.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming"&gt;Polymorphism&lt;/a&gt;, “the ability of one type to appear as and be used like another type”, is limited to inheritance with simple overloading semantics (and generics) in C#.&amp;#160; The ability to be “used as” another type is implemented by allowing subclasses to implement any virtual methods defined on their respective superclasses.&amp;#160; Then, at compile time, the method to be called is determined based on the actual types of the objects upon which the function/method is invoked; we call this compile-time binding or early-binding.&lt;/p&gt;  &lt;p&gt;Let’s look at it from a more mechanical perspective.&amp;#160; In most OO languages, when we write &lt;em&gt;obj.Foo()&lt;/em&gt; we are implicitly writing &lt;em&gt;(Foo obj)&lt;/em&gt;.&amp;#160; In other words, &lt;em&gt;obj&lt;/em&gt; is the first argument in the invocation of &lt;em&gt;Foo&lt;/em&gt;;&lt;em&gt; &lt;/em&gt;an argument called &lt;em&gt;this&lt;/em&gt; in many languages.&amp;#160; (See JavaScript’s call/apply.) So, in our inheritance example, the compiler looks at the actual type of this first argument &lt;em&gt;obj&lt;/em&gt; (the target of the invocation) when determining the &lt;em&gt;Foo&lt;/em&gt; to call. This is called single dispatch.&lt;/p&gt;  &lt;p&gt;What about the other arguments to the function?&amp;#160; Can we vary which function is called based on the other arguments to a method besides the target (i.e. the first implicit argument)?&amp;#160; Well, of course, we can have method overloads that take a different number and/or type of arguments.&amp;#160; However, unlike the first argument, there’s no mechanism in C# to evaluate the the derived types of these other arguments to make a dispatch decision;&lt;strong&gt; there is no multiple dispatch in C#&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;This blog article, &lt;a href="http://blogs.msdn.com/b/devdev/archive/2005/08/29/457798.aspx"&gt;“The Visitor Pattern and Multiple Dispatch”&lt;/a&gt;, usefully explains the problem in terms of the Visitor pattern.&amp;#160; As a means of implementing &lt;a href="http://en.wikipedia.org/wiki/Double_dispatch"&gt;double dispatch&lt;/a&gt; the Visitor pattern has some shortcomings.&amp;#160; First, the targets must be aware of and receive the visitor, violating the single responsibility principle.&amp;#160; Second, the visitor itself must evaluate the type of the target and invoke the correct method. Though some suggest &lt;a href="http://stackoverflow.com/questions/42587/double-dispatch-in-c/42656#42656"&gt;using reflection to invoke the correct method&lt;/a&gt;, that implementation, reflecting on the runtime type of the object and using dynamic invocation through the type to get to the right method can be expensive.&amp;#160; &lt;/p&gt;  &lt;p&gt;We can simplify that approach &lt;a href="http://blogs.msdn.com/b/laurionb/archive/2009/08/13/multimethods-in-c-4-0-with-dynamic.aspx"&gt;using the dynamic keyword to effect dynamic dispatch&lt;/a&gt;.&amp;#160; Using the &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/dd264736.aspx"&gt;dynamic keyword&lt;/a&gt;&lt;/em&gt; to “box” the arguments to the target method (&lt;em&gt;Foo&lt;/em&gt; above), we can let the runtime system do the reflection for us. In the code below, I build on the Visitor example in “The Visitor Pattern and Multiple Dispatch” article, see line 28.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:7c614de1-6b00-4851-9ce2-457687c2bbde" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Program&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt; { }&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ConstantExpression&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;int&lt;/span&gt; constant;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;SumExpression&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt; left, right;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;EvaluateVisitor&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;int&lt;/span&gt; Visit(&lt;span style="color:#2b91af"&gt;Expression&lt;/span&gt; e)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Exception&lt;/span&gt;(&lt;span style="color:#a31515"&gt;&amp;quot;Unsupported type of expression&amp;quot;&lt;/span&gt;); &lt;span style="color:#008000"&gt;// or whatever&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;int&lt;/span&gt; Visit(&lt;span style="color:#2b91af"&gt;ConstantExpression&lt;/span&gt; e)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; e.constant;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;int&lt;/span&gt; Visit(&lt;span style="color:#2b91af"&gt;SumExpression&lt;/span&gt; e)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; Visit(e.left &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#0000ff"&gt;dynamic&lt;/span&gt;) + Visit(e.right &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#0000ff"&gt;dynamic&lt;/span&gt;);&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&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;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; one = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ConstantExpression&lt;/span&gt; { constant = 1 };&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; two = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ConstantExpression&lt;/span&gt; { constant = 2 };&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; sum = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;SumExpression&lt;/span&gt; { left = one, right = two };&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; vistor = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;EvaluateVisitor&lt;/span&gt;();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515"&gt;&amp;quot;Visit result {0}&amp;quot;&lt;/span&gt;, vistor.Visit(sum));&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;This technique has some utility but should be used wisely.&amp;#160; Obviously there will be &lt;a href="http://code.logos.com/blog/2010/03/the_visitor_pattern_and_dynamic_in_c_4.html"&gt;some cost for “dynamic” dispatch&lt;/a&gt;.&amp;#160; It’s important to note that this isn’t a generalized system for multiple dispatch, just a great spot welding technique to &lt;a href="http://blogs.msdn.com/b/laurionb/archive/2009/05/29/implementing-the-visitor-pattern-with-the-dynamic-feature-of-c-4-0.aspx"&gt;make the Visitor pattern more palatable&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In contrast, Clojures multimethods allow you to define a function on the arguments that is evaluated and cached, while the “overloads” define the results of that evaluation that they correspond to.&amp;#160; In this way dispatch on multimethods in Clojure can consider not only the “types” and values of all the arguments, but really any sort of inspection or evaluation you choose.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2860199053600277408?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2860199053600277408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2860199053600277408' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2860199053600277408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2860199053600277408'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/07/dynamic-dispatch-multimethods-in-c.html' title='Dynamic Dispatch (Multimethods) in C#?'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1280506045788386661</id><published>2010-07-20T22:24:00.001-04:00</published><updated>2010-07-20T22:24:58.132-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Using the Web to Create the Web</title><content type='html'>&lt;p&gt;Wikis do this, as do blogs.&lt;/p&gt;  &lt;p&gt;Fast JavaScript in browsers is enabling a new generation of programmers to develop applications completely in their browser.&amp;#160; While the most obvious commercial example is Force.com, there are many other ideas out there.&amp;#160; In no particular order:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.tiddlywiki.com/"&gt;TiddlyWiki&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://jsbin.com/"&gt;JsBin&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://jsfiddle.net/"&gt;jsFiddle&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.lively-kernel.org/index.html"&gt;Lively Kernel&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://mozillalabs.com/bespin/"&gt;Bespin&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.flapjax-lang.org/"&gt;FlapJax&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The common connection between these frameworks is the notion of bootstrapping the web; that is, using the web to create the web.&lt;/p&gt;  &lt;p&gt;If you’ll forgive the inchoate thoughts, let me attempt to connect some mental dots.&lt;/p&gt;  &lt;p&gt;Dr. Alan Kay has of late been discussing the SmallTalk architecture of real objects (computers) all the way down and how this might improve the nature of software on the Internet.&lt;/p&gt;  &lt;p&gt;In September 2009 in an &lt;a href="http://www.simple-talk.com/opinion/geek-of-the-week/alan-kay-geek-of-the-week/"&gt;interview&lt;/a&gt;, Dr. Kay said,&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The ARPA/PARC research community tried to do as many things ‘no center’ as possible and this included Internet […] and the Smalltalk system which was ‘objects all the way down’ and used no OS at all. This could be done much better these days, but very few people are interested in it (we are). We’ve got some nice things to show not quite half way through our project. Lots more can be said on this subject.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This month in an &lt;a href="http://www.computerworld.com.au/article/352182/z_programming_languages_smalltalk-80/?pp=2"&gt;interview with ComputerWorld Australia&lt;/a&gt;, Dr. Kay expounded,&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;To me, one of the nice things about the semantics of real objects is that they are “real computers all the way down (RCATWD)” – this always retains the full ability to represent anything. The old way quickly gets to two things that aren’t computers – data and procedures – and all of a sudden the ability to defer optimizations and particular decisions in favour of behaviours has been lost.&lt;/p&gt;    &lt;p&gt;In other words, always having real objects always retains the ability to simulate anything you want, and to send it around the planet. If you send data 1000 miles you have to send a manual and/or a programmer to make use of it. If you send the needed programs that can deal with the data, then you are sending an object (even if the design is poor).&lt;/p&gt;    &lt;p&gt;And RCATWD also provides perfect protection in both directions. We can see this in the hardware model of the Internet (possibly the only real object-oriented system in working order).&lt;/p&gt;    &lt;p&gt;You get language extensibility almost for free by simply agreeing on conventions for the message forms.&lt;/p&gt;    &lt;p&gt;My thought in the 70s was that the Internet we were all working on alongside personal computing was a really good scalable design, and that we should make a virtual internet of virtual machines that could be cached by the hardware machines. It’s really too bad that this didn’t happen.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://www.infoq.com/news/2010/07/objects-smalltalk-erlang"&gt;Is OOP the wrong path&lt;/a&gt;? What is this RCATWD concept really about?&amp;#160; Doesn’t the stateless communication constraint of REST force us to think of web applications in the browser as true peers of server applications?&amp;#160; &lt;em&gt;Should we store our stateful browser-based JavaScript applications in a cloud object-database&lt;/em&gt;, in keeping with the Code-On-Demand constraint of REST?&amp;#160; Can we make a them “real objects” per Dr. Kay?&amp;#160; Are RESTful server applications just functional programs?&amp;#160; If so, &lt;em&gt;shouldn’t we be writing them in functional languages&lt;/em&gt;?&lt;/p&gt;  &lt;p&gt;I definitely believe we can gain many benefits from adopting a more message-passing oriented programming style.&amp;#160; I would go so far as to say that OO classes should only export functions, never methods.&amp;#160; (They can use methods privately of course, to keep things DRY.)&lt;/p&gt;  &lt;p&gt;I’ve written extensively in a never published paper about related topics: single-page applications, not writing new applications to build and deliver applications for every web site, intent-driven design, event sourcing, and others.&amp;#160; Hopefully I’ll find the time to return to that effort and incorporate some of this thinking.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1280506045788386661?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1280506045788386661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1280506045788386661' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1280506045788386661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1280506045788386661'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/07/using-web-to-create-web.html' title='Using the Web to Create the Web'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3580891128603389055</id><published>2010-07-20T21:14:00.001-04:00</published><updated>2010-07-20T21:14:33.328-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MEF'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='RavenDB'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>RavenDB: In the Code, Part 1—MEF</title><content type='html'>&lt;p&gt;If you’ve not heard of &lt;a href="http://ravendb.net/"&gt;RavenDB&lt;/a&gt;, it’s essentially a .NET-from-the-ground-up document database taking its design cues from CouchDB (and MongoDB to a lesser degree). Rather than go into the details about its design and motivations, I’ll let &lt;a href="http://herdingcode.com/?p=255"&gt;Ayende speak for himself&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Instead, I would like to document some of the great things I’ve found in the &lt;a href="http://github.com/ravendb/ravendb/"&gt;codebase of RavenDB&lt;/a&gt;, as I &lt;a href="http://www.hanselman.com/blog/HanselminutesPodcast72BeABetterDeveloperInSixMonths.aspx"&gt;read to be a better developer&lt;/a&gt;.&amp;#160; This series of articles discusses RavenDBs use of the following .NET 4 features.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Managed Extensibility Framework (MEF) &lt;/li&gt;    &lt;li&gt;New Concurrency Primitives in .NET 4.0 &lt;/li&gt;    &lt;li&gt;The new &lt;em&gt;dynamic&lt;/em&gt; keyword in C# 4 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;While discussing RavenDB’s use of these features, I hope to provide a gentle introduction to these technologies.&amp;#160; In this, the first post of the series, we discuss MEF.&amp;#160; For a very brief introduction to MEF and its core concepts, see the &lt;a href="http://mef.codeplex.com/wikipage?title=Overview"&gt;Overview in the wiki&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;Managed Extensibility Framework&lt;/h3&gt;  &lt;p&gt;MEF was originally in the Patterns &amp;amp; Practices team and has since moved into the BCL as the System.ComponentModel.Composition namespace.&amp;#160; &lt;a href="http://channel9.msdn.com/shows/SilverlightTV/Silverlight-TV-7-When-and-Where-to-use-MEF/"&gt;Glenn Block has nominated it&lt;/a&gt; as a plug-in framework, an application partitioning framework, and has given &lt;a href="http://codebetter.com/blogs/glenn.block/archive/2009/08/16/should-i-use-mef-for-my-general-ioc-needs.aspx"&gt;many reasons&lt;/a&gt; why you may not want to attempt to use it as your &lt;a href="http://martinfowler.com/articles/injection.html"&gt;inversion-of-control container&lt;/a&gt; (especially if you listen to &lt;a href="http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion"&gt;Uncle Bob’s advice&lt;/a&gt;). RavenDB uses MEF to handle extensibility for it’s RequestResponder classes.&lt;/p&gt;  &lt;p&gt;RavenDB’s communication architecture is essentially an HTTP server that has a number of registered handlers of requests, not unlike the front-controller model of ASP.NET MVC.&amp;#160; Akin to MVC’s Routes, each RequestResponder provides a UrlPattern and SupportedVerbs to identify those requests it will handle. A given RequestResponder will vary it’s work depending on the HTTP verbs, headers, and body of the request.&amp;#160; It is in this sense that RavenDB can be considered RESTful (even if it isn’t, see &lt;a href="http://tech.groups.yahoo.com/group/rest-discuss/message/15027"&gt;street REST&lt;/a&gt;).&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2e9bc6a9-7b75-4d98-a390-0d63f0274a73" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;HttpServer&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;IDisposable&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;[&lt;span style="color:#2b91af"&gt;ImportMany&lt;/span&gt;]&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;RequestResponder&lt;/span&gt;&amp;gt; RequestResponders { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;This HttpServer class dispatches requests to one of the items in the RequestResponders. This is populated by MEF because of the ImportManyAttribute.&amp;#160;&amp;#160;&amp;#160; MEF looks in its catalogs and finds the RequestResponder class is exported, as is all of it’s subclasses; see below.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b0e82968-1462-4fc0-b0a1-82720b8b5a84" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;[&lt;span style="color:#2b91af"&gt;InheritedExport&lt;/span&gt;]&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;RequestResponder&lt;/span&gt;&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;The InheritedExportAttribute ensures that MEF considers all subclasses of the attributed class are themselves as exports.&amp;#160; So, if your class inherits from RequestResponder and MEF can see your class, it will automatically be considered for each incoming request.&lt;/p&gt;  &lt;p&gt;How does MEF “see your class”? Out-of-the-box MEF provides for the definition of what is discoverable in a number of useful ways. RavenDB makes use of these by providing it’s own MEF CompositionContainer.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f0f92a4f-ee53-4b7b-9f26-382444d409d3" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; HttpServer(&lt;span style="color:#2b91af"&gt;RavenConfiguration&lt;/span&gt; configuration, &lt;span style="color:#2b91af"&gt;DocumentDatabase&lt;/span&gt; database)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Configuration = configuration;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;configuration.Container.SatisfyImportsOnce(&lt;span style="color:#0000ff"&gt;this&lt;/span&gt;);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;Above, in the constructor of the HttpServer class, we see the characteristic call to &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.compositioncontainer.satisfyimportsonce.aspx"&gt;SatisfyImportsOnce&lt;/a&gt; on the CompositionContainer. This instructs the container to satisfy all the imports for the HttpServer, namely the RequestResponders.&amp;#160; The configuration.Container property is below:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:3560a294-7de5-4919-b2b5-88cc8122eb27" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;CompositionContainer&lt;/span&gt; Container&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;get&lt;/span&gt; { &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; container ?? (container = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;CompositionContainer&lt;/span&gt;(Catalog)); }&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;And the Catalog property is initialized in the configuration class’ constructor like this:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:ef603f52-b319-4845-a9f3-fc55a5b20219" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;Catalog = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;AggregateCatalog&lt;/span&gt;(&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;AssemblyCatalog&lt;/span&gt;(&lt;span style="color:#0000ff"&gt;typeof&lt;/span&gt; (&lt;span style="color:#2b91af"&gt;DocumentDatabase&lt;/span&gt;).Assembly)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;So the container is created with a single AggregateCatalog that can contain multiple catalogs.&amp;#160; That AggregateCatalog is initialized with an AssemblyCatalog which pulls in all the MEF parts (classes with Import and Export attributes) in the assembly containing the DocumentDatabase class (more on that later).&lt;/p&gt;  &lt;p&gt;That takes care of the built-in RequestResponders, because those are in the same assembly as the DocumentDatabase class.&amp;#160; If that smells like it violates orthogonality, you are not alone. But, I digress; what about extensibility? How does Raven get MEF to see RequestResponder plugins? &lt;/p&gt;  &lt;p&gt;The configuration class also has a PluginsDirectory property; in the setter, is the following code.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:36badf63-775c-4272-bb06-260773211ca2" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;if&lt;/span&gt;(&lt;span style="color:#2b91af"&gt;Directory&lt;/span&gt;.Exists(pluginsDirectory))&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Catalog.Catalogs.Add(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DirectoryCatalog&lt;/span&gt;(pluginsDirectory));&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;So, in Raven’s configuration you can specify a directory where MEF will look for parts.&amp;#160; That’s the raison d'être of MEF’s DirectoryCatalog, since a plugins folder is such a common deployment/extensibility pattern.&amp;#160; You can learn more about the various &lt;a href="http://mef.codeplex.com/wikipage?title=Using%20catalogs"&gt;MEF catalogs in the CodePlex wiki&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Now, the &lt;u&gt;real&lt;/u&gt; extensibility story for RavenDB is its &lt;strong&gt;triggers&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;RavenDB Triggers&lt;/h3&gt;  &lt;p&gt;The previously mentioned DocumentDatabase class is responsible for the high-level orchestration of the actual database work.&amp;#160; It maintains four groups of triggers.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:63deb6c5-4c47-4d2e-a083-1613a22d23b9" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"&gt; &lt;li&gt;[&lt;span style="color:#2b91af"&gt;ImportMany&lt;/span&gt;]&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;AbstractPutTrigger&lt;/span&gt;&amp;gt; PutTriggers { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;[&lt;span style="color:#2b91af"&gt;ImportMany&lt;/span&gt;]&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;AbstractDeleteTrigger&lt;/span&gt;&amp;gt; DeleteTriggers { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;[&lt;span style="color:#2b91af"&gt;ImportMany&lt;/span&gt;]&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;AbstractIndexUpdateTrigger&lt;/span&gt;&amp;gt; IndexUpdateTriggers { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;[&lt;span style="color:#2b91af"&gt;ImportMany&lt;/span&gt;]&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;AbstractReadTrigger&lt;/span&gt;&amp;gt; ReadTriggers { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;Following the same pattern as RequestResponders, the DocumentDatabase calls &lt;em&gt;configuration.Container.SatisfyImportsOnce(this)&lt;/em&gt;. So, the imports are satisfied in the same way, i.e. from DocumentDatabase’s assembly and from a configured plug-ins directory.&lt;/p&gt;  &lt;p&gt;In RavenDB triggers are the way to perform some custom action when documents are “put” (i.e. &lt;a href="http://en.wikipedia.org/wiki/Upsert"&gt;upsert&lt;/a&gt;) or read or deleted.&amp;#160; RavenDB triggers also provide a way to block any of these actions from happening.&lt;/p&gt;  &lt;p&gt;Raven also allows for custom actions to be performed when the database spins up using the IStartupTask interface.&lt;/p&gt;  &lt;h3&gt;Startup Tasks&lt;/h3&gt;  &lt;p&gt;When the DocumentDatabase class is constructed, it executes the following method after initializing itself.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:8e581c60-e856-4c94-9041-3c1e386e9eaf" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; ExecuteStartupTasks()&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; task &lt;span style="color:#0000ff"&gt;in&lt;/span&gt; Configuration.Container.GetExportedValues&amp;lt;&lt;span style="color:#2b91af"&gt;IStartupTask&lt;/span&gt;&amp;gt;())&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;task.Execute(&lt;span style="color:#0000ff"&gt;this&lt;/span&gt;);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;This method highlights the use of the CompositionContainer’s GetExportedValues&amp;lt;T&amp;gt; function, which returns all of the IStartupTasks in the catalogs created in the configuration object.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;We’ve seen three important extensibility points in RavenDB supported by MEF: RequestResponders, triggers, and startup tasks.&amp;#160; Next time, we’ll look at two more—view generators and dynamic compilation extensions—while learning more about RavenDB indices.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3580891128603389055?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3580891128603389055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3580891128603389055' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3580891128603389055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3580891128603389055'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/07/ravendb-in-code-part-1mef.html' title='RavenDB: In the Code, Part 1—MEF'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7721964691966593327</id><published>2010-06-21T15:40:00.001-04:00</published><updated>2010-06-21T15:40:15.645-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='technology'/><category scheme='http://www.blogger.com/atom/ns#' term='review'/><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><title type='text'>iPad: The InterPersonal Computer</title><content type='html'>&lt;p&gt;There’s no shortage of information on the “how” of the iPad.&amp;#160; Apple’s reification of Alan Kay’s Dynabook makes no sacrifices in terms of processing, communications, display—even the audio is surprisingly good.&amp;#160; But what does the A4 system-on-a-chip, IPS display, Wifi/Bluetooth/3G add up to in terms of experience?&lt;/p&gt;  &lt;p&gt;Having spent a week with the iPad, I feel compelled to write down my answers to that question. The iPad is nothing short of a joy in my home.&amp;#160; It’s the device we didn’t know we needed: the fourth screen.&amp;#160; It’s the morning paper, the evening magazine, and the after dinner board game.&amp;#160; It’s the vacation photo album, the argument settler, and the cookbook.&amp;#160; The iPad is the first interpersonal computer (iPC); the PC has artfully been disguised as an intelligent, portable screen that facilitates rather than stymies interpersonal interaction.&lt;/p&gt;  &lt;p&gt;Why did we need this device? Surely I could use Wikipanion on my phone to settle the debate on the national language of Côte d’Ivoire during the game. But, I couldn’t show you the map of the region from across the room.&amp;#160; I definitely could have turned on my PC and connected my TV via DLNA to show our vacation photos. But I’d rather just hand you the album to scan at your leisure.&amp;#160; We could get all the tiles out, flip them over, mix them up, and arrange them, but board games are much more fun (and more apt to be played) when you don’t have to set them up or put them away. I could have done an internet search for recipes that included lemon balm and printed one out, but it’s nice to just go straight from searching to cooking. If we had kids the raison d'être of this latter-day Dynabook would be handsomely fulfilled by an interactive periodic table, a sketchbook, musical toys, and a huge library of books.&amp;#160; For now we’ll just have to settle for loving these apps as grown-ups.&lt;/p&gt;  &lt;p&gt;This is a device for kids of all ages, to be sure.&amp;#160; Each app acts as a mask, transforming the iPad to a device well-suited to the task at hand. Who wouldn’t find something to enjoy?&lt;/p&gt;  &lt;p&gt;I’d be remiss if I didn’t offer some lament or prognostication on future enhancements.&amp;#160; This device would be truly magical if I didn’t have to plug it in and synch with iTunes.&amp;#160; If my photos, videos, and music were just wirelessly transported from the cloud on demand and cached locally, I wouldn’t have to wait forever to synch or chew up a bunch of space with things I rarely want.&amp;#160; &lt;/p&gt;  &lt;p&gt;I would love it if the apps knew me. Maybe a fingerprint scanner could be added to help applications identify me; when I launch a game or Twitter client, if I swiped my finger it could load my saved game or timeline.&amp;#160; An iPC should be like a family friend, a unique relationship with each of us, but impartial and accessible to all.&lt;/p&gt;  &lt;p&gt;AT&amp;amp;T+Apple could score quite the coup if the 3G was free up to a certain level of usage.&amp;#160; How many snowbirds would buy an iPad to stay in touch with the family back home?&amp;#160; How many more&amp;#160; business travelers would be able to keep up with their inbox without having to be nickel-and-dimed all the time?&amp;#160; More importantly, they would have a device that would be complete out-of-the-box; thank you for purchasing this magical screen that is connected to everyone, everywhere, anywhere you are—right now.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7721964691966593327?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7721964691966593327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7721964691966593327' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7721964691966593327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7721964691966593327'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/06/ipad-interpersonal-computer.html' title='iPad: The InterPersonal Computer'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8591155088987658164</id><published>2010-05-17T11:36:00.001-04:00</published><updated>2010-05-17T11:41:44.766-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>The Law of Demeter and Command-Query Separation</title><content type='html'>&lt;p&gt;My first encounter of the &lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Law of Demeter&lt;/a&gt; (LoD) was in the Meilir Page-Jones book, &lt;a href="http://www.amazon.com/gp/product/020169946X?ie=UTF8&amp;amp;tag=iforma-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=020169946X"&gt;Fundamentals of Object-Oriented Design in UML&lt;/a&gt;. It is also referenced in &lt;a href="http://www.amazon.com/gp/product/0132350882?ie=UTF8&amp;amp;tag=iforma-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0132350882"&gt;Clean Code&lt;/a&gt; by Robert C. Martin.&amp;#160; Basically, the law states that methods on an object should only invoke methods on objects in their &lt;strong&gt;immediate context&lt;/strong&gt;: locally created objects, containing instance members, and arguments to the method itself.&amp;#160; This limits what Page-Jones calls the &lt;strong&gt;direct encumbrance&lt;/strong&gt; of a class;&amp;#160; the total set of types a class directly depends upon to do its work.&amp;#160; Martin points out that if an object effectively encapsulates it’s internal state, we should not be able “navigate through it.”&amp;#160; Not to put too fine of a point on it, but the kind of code we are talking about here is:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:4c83f155-3c42-4a17-84d8-13e271c38d13" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 200px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;"&gt; &lt;li&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;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; a = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;A&lt;/span&gt;();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;a.Foo().Bar();&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;A&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;B&lt;/span&gt; Foo()&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#008000"&gt;// do some work and yield B&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;B&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; Bar()&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;Martin calls line 4 above a “train wreck” due to its resemblance to a series of train cars.&amp;#160; Our Main program has a direct encumbrance of types A &amp;amp; B. We “navigate through” A and invoke a method of B.&amp;#160; Whatever Foo() does, it is not effectively encapsulating it; we cannot change it to an implementation that uses C transparently.&lt;/p&gt;  &lt;p&gt;LoD is a heuristic that leverages the encumbrance of a type to determine code quality. We observe that effective encapsulation directly constrains encumbrance, so we can say that the Law of Demeter is a partial corollary to an already well known OOP principle: encapsulation.&amp;#160; Another such principle is Command-Query Separation (CQS) as identified by Bertrand Meijer in his work on the Eiffel programming language.&lt;/p&gt;  &lt;p&gt;CQS simply states that methods should either be commands or query; they should either mutate state or return state without side-effects.&amp;#160; Queries must be &lt;strong&gt;referentially transparent&lt;/strong&gt;; that is you can replace all query call sites with the value returned by the query without changing the meaning of the program. Commands must perform some action but not yield a value.&amp;#160; Martin illustrates this principle quite succinctly in Clean Code.&lt;/p&gt;  &lt;p&gt;Referring to our snippet above again, we can see that if CQS were to have been observed, Foo() would return void and our main program would not have been returned an instance of B.&amp;#160; CQS thus reinforces LoD, both of which manifest as specializations of OO encapsulation.&amp;#160; Following these principles force us to change the semantics of our interfaces, creating contracts that are much more declarative.&lt;/p&gt;  &lt;p&gt;CQS has many implications.&amp;#160; Fowler &lt;a href="http://martinfowler.com/bliki/CommandQuerySeparation.html"&gt;observes&lt;/a&gt; that CQS allows consumers of classes to utilize query methods with a sense of “confidence, introducing them anywhere, changing their order.”&amp;#160; In other words, CQS allows for arbitrary composition of queries; this is a very important concept in functional programming.&amp;#160; Queries in CQS are also necessarily idempotent, by definition; this is extremely important in caching.&lt;/p&gt;  &lt;p&gt;In Martin’s discussion of LoD, he notes that if B above were simply a data structure—if all of its operations were Queries—we would not have a violation of LoD, in principle.&amp;#160; This is because LoD is really only concerned with the proper abstraction of Commands. From the &lt;a href="http://c2.com/cgi/wiki?DontConfuseYourDog"&gt;C2 wiki&lt;/a&gt;, &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;In the discussion on the &lt;a href="http://c2.com/wiki?LawOfDemeter"&gt;LawOfDemeter&lt;/a&gt;, &lt;a href="http://c2.com/wiki?MichaelFeathers"&gt;MichaelFeathers&lt;/a&gt; offers the analogy, &amp;quot;If you want your dog to run, do you talk [to] your dog or to each leg? Further, should you be able to manipulate the dog's leg without it knowing about it? What if your dog wants to move its leg and it doesn't know how you left it? You can really confuse your dog.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;To extend the analogy, when you are walking your dog, you don’t command it’s legs, you command the dog.&amp;#160; But, if you want to have a smooth walk, you’ll stop and wait if you one of the dog’s legs is raised. It is in this sense that we can restate the Law of Demeter in terms of Command-Query Separation.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Whereas a &lt;strong&gt;Query&lt;/strong&gt; of an object must:&lt;/li&gt;   &lt;ol&gt;   &lt;li&gt;never alter the observable state of the object, i.e. the results of any queries; &lt;/li&gt;    &lt;li&gt;and return only objects entirely composed of queries, &lt;strong&gt;no commands&lt;/strong&gt;.&lt;/li&gt;   &lt;/ol&gt;   &lt;li&gt;A &lt;strong&gt;Command&lt;/strong&gt; of an object must: &lt;/li&gt;   &lt;ol&gt;    &lt;li&gt;constrain its actions to be dependent upon the observable state, i.e. Queries, of &lt;strong&gt;only&lt;/strong&gt; those objects in its immediate context (as defined above); &lt;/li&gt;   &lt;li&gt;and hide the internal state changes that result of its actions from observers. &lt;/li&gt; &lt;/ol&gt; &lt;/ul&gt;  &lt;p&gt;This restating is helpful in that it implies that we refactor to CQS before applying LoD. In the first phase we clearly separate commands from queries. In the second phase we alter the semantics of our commands and queries to comply with LoD.&amp;#160; While the first phase is rather mechanical, it give us a good starting point to reconsider the semantics of our objects as we bring them into compliance with LoD.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8591155088987658164?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8591155088987658164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8591155088987658164' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8591155088987658164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8591155088987658164'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/05/law-of-demeter-and-command-query.html' title='The Law of Demeter and Command-Query Separation'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-622019689424252535</id><published>2010-04-22T16:04:00.001-04:00</published><updated>2010-04-22T16:05:00.066-04:00</updated><title type='text'>Usability Apothegms</title><content type='html'>&lt;p&gt;A common saying in computing is that “Security is inversely proportional to usability”… or something like that.&amp;#160; As we critical examine the security of our systems, we realize we need to put measures in place that make the system harder to access and thus harder to use.&amp;#160; A good interaction design can help mitigate the usability issues, but at the end of the day a system that doesn’t require me to memorize a password or login is easier to use than a system that does.&lt;/p&gt;  &lt;p&gt;We can say definitively that security and usability exist in tension.&lt;/p&gt;  &lt;p&gt;As software architects we seek simplicity in our designs in the name of maintainability, if not intelligibility.&amp;#160; We also seek modularity in the name of reusability. I submit that simplicity and modularity exist in tension.&lt;/p&gt;  &lt;p&gt;Accepting &lt;em&gt;a priori&lt;/em&gt; that simplicity is the absence of complexity, we can obtain the simplicity of a program by measuring its complexity.&amp;#160; A field of computer science called algorithmic information theory defines the complexity of something to be the length of the simplest program for calculating it.&amp;#160; We might infer from this that a monolithic program (no components, no objects, no abstractions, etc.) is a simpler program than our common object-oriented code.&amp;#160; In general we can say that modularity implies no small increase in the use of abstractions to enable that modularity.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;In object-oriented* systems, an increase in modularity results in a proportional increase in complexity.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I limit this to object-oriented systems purposefully.&amp;#160; In my experience functional programming languages modularity is &lt;em&gt;de rigueur&lt;/em&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-622019689424252535?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/622019689424252535/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=622019689424252535' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/622019689424252535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/622019689424252535'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/04/usability-apothegms.html' title='Usability Apothegms'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6454097093418069977</id><published>2010-04-12T19:53:00.001-04:00</published><updated>2010-04-12T19:53:28.959-04:00</updated><title type='text'>Converting Oranges to Apple’s: Meta-competition in the Platform Wars</title><content type='html'>&lt;p&gt;Updates to the developer agreement in the new iPhone SDK restrict developers to using C, C++, or Objective-C to create their native iPhone applications.&amp;#160; That is, they must have been “originally written” in one of those languages.&lt;/p&gt;  &lt;p&gt;This move has made its rounds among the pundits and bloggers.&amp;#160; Rather than rehashing any of those points, I’ll give my own opinions on why Apple made this move.&lt;/p&gt;  &lt;p&gt;Make no mistake, this is about stewardship of the iPhone experience.&amp;#160; Steve Jobs has responded to the criticism (emphasis my own),&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[…] intermediate layers between the platform and the developer ultimately produces sub-standard apps and hinders the progress of &lt;strong&gt;the platform&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Before you go say they’re really just trying to kill Flash, let’s address that up front.&amp;#160; Flash does not run in Safari on the iPhone for the same reason that you are prohibited in the developer agreement from hosting a virtual machine in your iPhone application.&amp;#160; As the steward of the platform, Apple has to attempt to ensure that users have consistently good experience.&amp;#160; Trying to squeeze a bloated swf player into a memory and processor constrained device is just not workable currently.&amp;#160; As any iPhone user can attest, websites that are not optimized for mobile browsers are horribly slow to load.&amp;#160; Flash content would just make that worse.&amp;#160; And, guess what, my mom doesn’t know that your website or Flash animation is a pig, she just thinks her phone is slow.&lt;/p&gt;  &lt;p&gt;Let’s look at it from another perspective.&amp;#160; The latest incarnation of Microsoft’s flagship development suite, Visual Studio 2010, has been re-written on their WPF platform.&amp;#160; Well, everything except the splash screen.&amp;#160; You see, it takes too long to load WPF and .NET up to affect the desired result of a splash screen—giving you something to look at while the main application loads.&amp;#160; The iPhone developer guide makes it abundantly clear that you should load something as quickly as possible to give the user the sense that your app is responsive.&amp;#160; Try explaining to your mom that, yes, her phone has registered her tap on the application icon, but that it has to spin up a virtual machine or load some large libraries that abstract away Cocoa.&lt;/p&gt;  &lt;p&gt;Next, try to explain to her why the extra cycles required by the VM and/or interoperability libraries drain her battery.&amp;#160; She’ll just be annoyed that she’s constantly plugging the darn thing in.&lt;/p&gt;  &lt;p&gt;Apologies to all the technical moms out there.&lt;/p&gt;  &lt;p&gt;so, Flash [1] is not the target here, at least in the sense that Apple cares if Flash is around or perceives it as a threat.&amp;#160; And, assuredly, we cannot say that stewardship of the performance of the phones is the only reason.&amp;#160; That’s part of Steve’s “sub-standard apps” argument, and it is not entirely convincing given that it becomes an optimization problem, and developers are notoriously good at those when they set their mind to it.&amp;#160; As a steward though, you really cannot afford to wait from them to figure it out.&amp;#160; Nevertheless, I think the original ban on virtual machines and this subsequent tightening to a whitelist of languages comes down to a stewardship of a different kind: keeping out the riff-raff.&lt;/p&gt;  &lt;p&gt;Keeping up with AppStore submissions is already pretty hard and very expensive.&amp;#160; Developers are often frustrated by the time it takes to get their updates into the store, especially developers used to patching websites with no downtime. Don’t imagine for a second that your $99 covers the cost of the program.&amp;#160; This is Apple’s investment in the ecosystem.&amp;#160; Imagine the deluge of useless, crappy submissions they will get if every Flash developer and every VB developer can just tick a box to target the iPhone.&lt;/p&gt;  &lt;p&gt;But, it’s not just about raising the bar for entry to keep out sub-standard developers and their apps.&amp;#160; They have to look after all those developers who have committed to their platform.&amp;#160; They aren’t going to invest significant resources to enabling C#, VB, Python, Ruby, or Flash developers to compete against their own.&amp;#160; &lt;/p&gt;  &lt;p&gt;Apple is not interested in seeing your app run on a Droid, Windows Mobile 7, and iPhone.&amp;#160; They are actively controverting homogenization of the mobile application marketplace.&amp;#160; They have an insurmountable lead[2] in the mobile applications marketplace, and the iPad, another device on the iPhone OS platform, marks the next step in their overall competitive strategy for leveraging that lead.&amp;#160; At the center of all of this is the AppStore, perhaps the single most valuable asset in computing today.&amp;#160; Whereas no one controls the Internet, Apple owns the AppStore outright with all the rights and responsibilities that entails; think of Salesforce.com and their AppExchange.&lt;/p&gt;  &lt;p&gt;Microsoft has long understood that developers are what make their ecosystem work.&amp;#160; Steve Ballmer’s famous rallying cry, “Developers! Developers! Developers!”, is poignant illustration of this reality.&amp;#160; Apple understands that to usurp Microsoft’s position in the PC and enterprise markets, to continue their domination of consumer segments, they need a large population of developers that understand their platform.&amp;#160; What they don’t need are more ways for developers to “write once, run everywhere.”&amp;#160; In the platform wars, he who has the developers wins.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;[1] Anyway, it isn’t just about Flash.&amp;#160; Look no further than Microsoft’s Windows Mobile 7 announcements to see that.&amp;#160; Silverlight, a Flash competitor to say that least, will be the native platform of those devices.&amp;#160; Where Flash is Silverlight will surely follow.&lt;/p&gt;  &lt;p&gt;[2] I believe that Google will continue to have limited success as a web-native device.&amp;#160; There is a significant segment of the marketplace that just want a phone, email, web-browsing device.&amp;#160; RIM has an Apple-style loyalty thing going for it.&amp;#160; Microsoft?&amp;#160; Well, they still have such a big footprint; they could fail and still make a huge impact.&amp;#160; I think the move to Silverlight helps shield their effort from their internal Windows-Office power structure enough that it actually has a chance of competing, but they are way too far behind to win.&amp;#160; There’s not a huge population of Silverlight developers in the world, after all.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6454097093418069977?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6454097093418069977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6454097093418069977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6454097093418069977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6454097093418069977'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2010/04/converting-oranges-to-apples-meta.html' title='Converting Oranges to Apple’s: Meta-competition in the Platform Wars'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3854116137404118635</id><published>2009-12-29T19:23:00.001-05:00</published><updated>2009-12-29T19:37:30.060-05:00</updated><title type='text'>Inchoate Thoughts on New Programming Abstractions for the Cloud</title><content type='html'>&lt;p&gt;I watched an InfoQ video of &lt;a href="http://www.infoq.com/presentations/liskov-power-of-abstraction"&gt;Barbara Liskov at OOPSLA&lt;/a&gt; this evening.&amp;#160; At the end of her talk in a look at the challenges looking forward she said, “I’ve been waiting for thirty years for a new abstraction mechanism,” and, “There’s a funny disconnect in how we write distributed programs.&amp;#160; You write your individual modules, but then when you want to connect them together you’re out of the programming language, and sort of into this other world.&amp;#160; Maybe we need languages that are a little more complete now so that we can write the whole thing in the language.”&amp;#160; Her talk was an interesting journey through the history of Computer Science through the lens of her work, but this notion connected with something I’ve been thinking about lately.&lt;/p&gt;  &lt;p&gt;Earlier this month I was catching up on the happenings on Channel9 and stumbled on &lt;a href="http://channel9.msdn.com/posts/Charles/JAOO-2007-Erik-Meijer-and-Dave-Thomas-Objects-Functions-Virtual-Machines-IDEs-and-Other-Fun-St/"&gt;this conversation between Erik Meijer and Dave Thomas&lt;/a&gt;.&amp;#160; I would have preferred a different interview-style, but Dave Thomas’ opinions are always interesting.&amp;#160; “I find it hard to believe that people would build a business application in Java or C#. […] The real opportunity is recognizing that there is really no need for people to do all of the stuff they have to do today.&amp;#160; And, I really believe that is fundamentally a language problem, whether that’s through an extended SQL, or its a new functional language, whether its a vector functional language; I can see lots of possibilities there. […] I see a future where there are objects in the modeling layer, but not in the execution infrastructure.”&lt;/p&gt;  &lt;p&gt;I see a connection between Liskov’s desire “new abstraction mechanism” and Thomas’ “language problem”.&amp;#160; If you look at the history of “execution infrastructure”, there has been an unremitting trend toward greater and greater abstraction of the hardware that makes it all happen.&amp;#160; From twiddling bits, to manipulating registers, to compiled languages, to compiled to virtual machine bytecode and attendant technologies like garbage collection, interpreters, to very declarative constructs, we continually move away from the hardware to focus on the actual problems that we began writing the program to solve in the first place(1).&amp;#160; Both Liskov and Thomas are bothered by the expressivity of languages; that is, programming languages are still burdened with the legacy of the material world.&lt;/p&gt;  &lt;p&gt;I think this may very well be the point of “Oslo” and the “M” meta-language.&amp;#160; One might view that effort as a concession that even DSLs are too far burdened by their host language’s legacy to effectively move past the &lt;strong&gt;machine programming era&lt;/strong&gt; into the &lt;strong&gt;solution modeling&lt;/strong&gt; era.&amp;#160; So, rather than create a language with which to write solution code, create a language/runtime to write such languages.&amp;#160; This is really just the logical next step, isn’t it?&lt;/p&gt;  &lt;p&gt;I didn’t quite understand this viewpoint at the time, but I had this discussion to some extent with &lt;a href="http://www.shycohen.com/blog/"&gt;Shy Cohen&lt;/a&gt; at TechEd09.&amp;#160; I just didn’t grasp the gestalt of “Oslo”.&amp;#160; This certainly wasn’t a failing of his explanatory powers nor—hopefully—my ability to understand.&amp;#160; Rather I think it’s because they keep demoing it as one more data access technology.&amp;#160; The main demo being to develop an M grammar of some simple type and have a database created.&amp;#160; Again, the legacy of computing strikes again.&amp;#160; To make the demo relevant, they have to show you how it works with all your existing infrastructure.&lt;/p&gt;  &lt;p&gt;So, maybe the solution to developing new abstractions is to once and for all abstract away the rest of the infrastructure.&amp;#160; Both Liskov and Thomas were making this point.&amp;#160; Why should we care how and where the data is stored?&amp;#160; Why should most developers care about concurrency?&amp;#160; Why should we have to understand the behemoth that is WCF in order to get to modules/systems/components talking to each other?&lt;/p&gt;  &lt;p&gt;Let’s start over with an abstraction of the entirety of computing infrastructure(2): servers, networking, disks, backups, databases, etc..&amp;#160; We’ll call it, oh, I don’t know… a cloud.&amp;#160; Now, what properties must a cloud exhibit in order to ensure this abstraction doesn’t leak?&amp;#160; I suggest we can examine why existing abstractions in computing have been successful, understand the problems they solve at a fundamental level, and then ensure that our cloud can do the same.&amp;#160; Some candidates for this examination are: relational databases, virtual machines/garbage collectors, REST, Ruby on Rails, and LINQ.&amp;#160; I’m sure there are countless other effective abstractions that could serve as guideposts.&lt;/p&gt;  &lt;p&gt;Should we not be able to express things naturally in a &lt;strong&gt;solution modeling language&lt;/strong&gt;?&amp;#160; Why can’t I write, “When Company X sends us a shipment notification for the next Widget shipment, make sure that all Whatzit production is expedited. And, let me know immediately if Whatzit production capacity is insufficient to meet our production goals for the month.”&amp;#160; Sure, this is a bit imperative, but it’s imperatively modeling a solution, not instructions on how to push bits around to satisfy the solution model; in that sense it is very, very declarative.&amp;#160; I believe the cloud abstraction enables this kind of &lt;strong&gt;solution modeling language&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;How about a cloud as the ambient monad for all programs?&amp;#160; What about a Google Wave bot as a sort of REPL loop for this solution modeling language?&amp;#160; What about extensive use of the Maybe monad or &lt;a href="http://community.schemewiki.org/?amb"&gt;amb&lt;/a&gt; style evaluation in a constraint driven lexicon so that imperative rules like those in the sample above are evaluated in a &lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"&gt;reactive&lt;/a&gt; rather than deterministic fashion?&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Quantum computing productively remains undecided as to “how” it actually works.&amp;#160; That is, “how” is somewhat dependent on your interpretation of quantum mechanics.&amp;#160; Maybe an infinite number of calculation occur simultaneously in infinite universes with the results summed over via quantum mechanical effects.&lt;/li&gt;    &lt;li&gt;I should say here that I think the Salesforce.com model is pretty far down this path, as is Windows Azure to a lesser extent.&amp;#160; Crucially, neither of these platforms mitigate the overhead of persistence and communications constructs.&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3854116137404118635?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3854116137404118635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3854116137404118635' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3854116137404118635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3854116137404118635'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/12/inchoate-thoughts-on-new-programming.html' title='Inchoate Thoughts on New Programming Abstractions for the Cloud'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1588974030003788432</id><published>2009-12-21T08:52:00.001-05:00</published><updated>2009-12-21T08:52:59.033-05:00</updated><title type='text'>System.Tuple: More .NET 4.0 Functional Goodness</title><content type='html'>&lt;p&gt;In functional languages, tuples are pretty much a requirement.&amp;#160; Of the functional languages I’ve used, including Erlang and T-SQL, tuples are bread’n’butter.&amp;#160; Every release of .NET has included more and more support for functional programming paradigms, and we’re getting tuple support in the BCL in .NET 4.0, though first-class language support is still not there.&amp;#160; Here’s an example of using System.Tuple with the new Zip LINQ operator.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:8d9a9a9f-9d40-42d0-a958-00e3675fd297" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; xs = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;int&lt;/span&gt;&amp;gt; { &lt;span style="color:#a52a2a"&gt;1&lt;/span&gt;, &lt;span style="color:#a52a2a"&gt;3&lt;/span&gt;, &lt;span style="color:#a52a2a"&gt;5&lt;/span&gt; };&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; ys = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;string&lt;/span&gt;&amp;gt; { &lt;span style="color:#a31515"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515"&gt;&amp;quot;world&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515"&gt;&amp;quot;channel&amp;quot;&lt;/span&gt; };&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; zs = xs.Zip(ys, &lt;span style="color:#2b91af"&gt;Tuple&lt;/span&gt;.Create);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; z &lt;span style="color:#0000ff"&gt;in&lt;/span&gt; zs)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515"&gt;&amp;quot;{1}:{0}&amp;quot;&lt;/span&gt;,z.Item1, z.Item2);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1588974030003788432?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1588974030003788432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1588974030003788432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1588974030003788432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1588974030003788432'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/12/systemtuple-more-net-40-function.html' title='System.Tuple: More .NET 4.0 Functional Goodness'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2800616891134478972</id><published>2009-12-17T23:31:00.001-05:00</published><updated>2009-12-21T04:01:18.900-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Quicksort Random Integers with PLINQ</title><content type='html'>&lt;div&gt;The first “homework assignment” of &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1/"&gt;Dr. Erik Meijer’s functional programming course on Channel 9&lt;/a&gt; was to write quicksort using C# (or VB) functional comprehensions.&amp;#160; I did it in a very naïve way, then I wondered if I could get a “free” speed up simply by leveraging some of the Parallel Extensions to .NET 4.0.&amp;#160; &lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;My results were mixed.&amp;#160; As the number of integers in the unsorted array increases, the parallel implementation begins to pull away, but with smaller numbers the sequential implementation is faster.&amp;#160; I think I’ll try to do something very similar in Erlang this weekend.&amp;#160; It should be an interesting comparison exercise since Erlang terms are immutable.&amp;#160; A naïve implementation should look pretty similar I think.&amp;#160; Neither of them would be true quicksort implementations, since the algorithm was specified by Hoare to work in a mutable fashion with the original array being changed in situ.&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;My dual core machine yielded times of about 80s and 100s when sorting an array of a thousand for the parallel (QsortP) and sequential (Qsort) methods respectively.&amp;#160; So that’s definitely not impressive, but I did it in a very abstract way.&amp;#160; The same function could sort strings or floats or anything else that implements IComparable.&amp;#160; &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e927f59b-4f71-4bcd-842d-de3cdfc0166e" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px"&gt;Code Snippet&lt;/div&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;using&lt;/span&gt; System;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;using&lt;/span&gt; System.Linq;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&lt;span style="color:#0000ff"&gt;using&lt;/span&gt; System.Threading.Tasks;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;using&lt;/span&gt; System.Diagnostics;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;namespace&lt;/span&gt; ConsoleApplication3&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Program&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&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;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;int&lt;/span&gt;[] ints = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#0000ff"&gt;int&lt;/span&gt;[&lt;span style="color:#a52a2a"&gt;100&lt;/span&gt;];&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; rand = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Random&lt;/span&gt;();&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff"&gt;int&lt;/span&gt; i = &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;; i &amp;lt; ints.Length; i++)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;ints[i] = rand.Next(&lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;Int32&lt;/span&gt;.MaxValue);&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;int&lt;/span&gt;[] sortedP;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;int&lt;/span&gt;[] sorted;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Time(() =&amp;gt; sortedP = QsortP(ints).ToArray());&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;Time(() =&amp;gt; sorted = Qsort(ints).ToArray());&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#2b91af"&gt;Debugger&lt;/span&gt;.Break();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; QsortP&amp;lt;T&amp;gt;(&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; arr) &lt;span style="color:#0000ff"&gt;where&lt;/span&gt; T : &lt;span style="color:#2b91af"&gt;IComparable&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (arr.Count() == &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; arr;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;T pivot = arr.First();&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; sortLess = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;(() =&amp;gt; QsortP(arr.Where(v =&amp;gt; v.CompareTo(pivot) &amp;lt; &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;)));&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; sortMore = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;(() =&amp;gt; QsortP(arr.Where(v =&amp;gt; v.CompareTo(pivot) &amp;gt; &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;)));&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;sortLess.Start(); sortMore.Start();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; equal = arr.AsParallel().Where(v =&amp;gt; v.CompareTo(pivot) == &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;);&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; sortLess.Result.Concat(equal).Concat(sortMore.Result);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; Qsort&amp;lt;T&amp;gt;(&lt;span style="color:#2b91af"&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt; arr) &lt;span style="color:#0000ff"&gt;where&lt;/span&gt; T : &lt;span style="color:#2b91af"&gt;IComparable&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (arr.Count() == &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; arr;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;T pivot = arr.First();&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;return&lt;/span&gt; Qsort(arr.Where(v =&amp;gt; v.CompareTo(pivot) &amp;lt; &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;))&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;.Concat(arr.Where(v =&amp;gt; v.CompareTo(pivot) == &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;))&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;.Concat(Qsort(arr.Where(v =&amp;gt; v.CompareTo(pivot) &amp;gt; &lt;span style="color:#a52a2a"&gt;0&lt;/span&gt;)));&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&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; Time(&lt;span style="color:#2b91af"&gt;Action&lt;/span&gt; a)&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;{&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#0000ff"&gt;var&lt;/span&gt; t = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Stopwatch&lt;/span&gt;();&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;t.Start();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;a();&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;t.Stop();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;span style="color:#2b91af"&gt;Debug&lt;/span&gt;.Write(t.Elapsed.TotalSeconds);&lt;/li&gt; &lt;li&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2800616891134478972?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2800616891134478972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2800616891134478972' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2800616891134478972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2800616891134478972'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/12/quicksort-million-random-integers-with.html' title='Quicksort Random Integers with PLINQ'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8302202152676085175</id><published>2009-12-15T14:57:00.001-05:00</published><updated>2009-12-15T15:12:47.958-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Premature Optimization and LINQ to SQL</title><content type='html'>&lt;p&gt;Don’t count your chickens before they hatch.&amp;#160; Let’s call that adage the “count-no” principle.&amp;#160; I promise that will be funny later.&lt;/p&gt;  &lt;p&gt;The common interpretation of this adage is that you should not rely on future results when making decisions in the present.&amp;#160; It is generally an admonishment to not be too cocky about the future.&amp;#160; What might the corollary be?&amp;#160; Perhaps to concern ourselves with the details of the present moment rather than thinking about the future.&amp;#160; We’ll call this corollary “nocount”.&amp;#160; One specific example of this corollary is the programmer’s maxim about premature optimization.&amp;#160; In fact, it was &lt;a href="http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf"&gt;Donald Knuth&lt;/a&gt; who said, “&amp;quot;We should forget about small efficiencies, say about 97% of the time: premature &lt;a href="http://en.wikipedia.org/wiki/Optimization_(computer_science)"&gt;optimization&lt;/a&gt; is the root of all evil,” in a response to Dijkstra’s “Go to statement considered harmful”.&lt;/p&gt;  &lt;p&gt;So, I’m debugging a particularly pernicious problem today.&amp;#160; In production (and only production) we were getting a &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.linq.changeconflictexception.aspx"&gt;ChangeConflictException&lt;/a&gt; when updating a row in the database.&amp;#160; Unfortunately, the logs indicated that there were no &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.linq.memberchangeconflict.aspx"&gt;MemberChangeConflict&lt;/a&gt; objects.&amp;#160; In other words we weren’t violating optimistic concurrency.&amp;#160; So, I profiled the SQL statements and it appeared to be just what I expected, a simple update supporting optimistic concurrency.&lt;/p&gt;  &lt;p&gt;Did you know you can eek out an exceedingly miniscule amount of performance by using the “SET NOCOUNT ON” option with SQL Server?&amp;#160; Did you know that you can actually set this option at the &lt;strong&gt;&lt;em&gt;server level&lt;/em&gt;&lt;/strong&gt;? Do you know what happens when your LINQ to SQL DataContext uses the row count returned from your optimistically concurrent update statement to determine if one and only one row was updated?&lt;/p&gt;  &lt;p&gt;Yes dear reader, premature optimization can cause the most insidious and difficult to discover problems.&amp;#160; Please, don’t ever violate the “nocount princple”!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8302202152676085175?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8302202152676085175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8302202152676085175' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8302202152676085175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8302202152676085175'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/12/premature-optimization-and-linq-to-sql.html' title='Premature Optimization and LINQ to SQL'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1603908937942063713</id><published>2009-11-10T13:44:00.001-05:00</published><updated>2009-11-10T13:47:03.378-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='localization'/><title type='text'>Create an XML Schema Enumeration of Supported .NET CultureInfo with Powershell</title><content type='html'>&lt;p&gt;Here’s a Powershell script to generate the enumeration elements of an XML Schema simpleType restriction.&amp;#160; The first command loads the .NET Assembly you’ll need, sysglobl.dll.&lt;/p&gt;  &lt;code&gt;PS&amp;gt;  [System.Reflection.Assembly]::Load("sysglobl, Version=2.0.0.0, Culture=neutral, PublicKeyToken= b03f5f7f11d50a3a, processorArchitecture=MSIL")&lt;/code&gt; &lt;br /&gt; &lt;code&gt;PS&amp;gt; [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::FrameworkCultures)    &lt;br /&gt;| ? {$_.Name.Trim().Length -eq 5} | % { &amp;quot;&amp;lt;xs:enumeration value=`&amp;quot;$_`&amp;quot;/&amp;gt;&amp;quot;} | Out-File cultures.txt&lt;/code&gt;  &lt;p&gt;See my earlier post on locale identifiers for more background. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1603908937942063713?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1603908937942063713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1603908937942063713' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1603908937942063713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1603908937942063713'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/11/create-xml-schema-enumeration-of.html' title='Create an XML Schema Enumeration of Supported .NET CultureInfo with Powershell'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6556379108377014761</id><published>2009-10-30T20:17:00.001-04:00</published><updated>2009-10-30T20:17:52.770-04:00</updated><title type='text'>Whoa!!! HP Software Sucks!</title><content type='html'>&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_FQ1igFTZD04/SuuCLkS3DJI/AAAAAAAAAFU/6zeC_dwICao/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_FQ1igFTZD04/SuuCMApAFqI/AAAAAAAAAFY/lzGMxXy9sBw/image_thumb%5B3%5D.png?imgmax=800" width="491" height="233" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is the error that was reported after the HP installer forced me to restart my computer to continue installation…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6556379108377014761?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6556379108377014761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6556379108377014761' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6556379108377014761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6556379108377014761'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/10/whoa-hp-software-sucks.html' title='Whoa!!! HP Software Sucks!'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_FQ1igFTZD04/SuuCMApAFqI/AAAAAAAAAFY/lzGMxXy9sBw/s72-c/image_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4527204857540689070</id><published>2009-10-15T10:12:00.001-04:00</published><updated>2009-10-15T10:12:07.253-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><title type='text'>TFS: Locked for Check-out</title><content type='html'>&lt;p&gt;Today a co-worker was attempting to edit a file, and TFS reported that it was “locked for check-out by [me] in workspace …”.&lt;/p&gt;  &lt;p&gt;I didn’t have it checked out.&amp;#160; I tried to use “tf lock /lock:none” on the file in question, but it would simply report:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;TF10152: The item … must remain locked because its file type prevents multiple check-outs.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We don’t allow multiple checkouts for this Team Project.&amp;#160; Unfortunately, this meant that not only didn’t I intend to lock the file, I couldn’t unlock it.&lt;/p&gt;  &lt;p&gt;My solution was to just check-in some dummy changes, comments full of expletives if you must know, since TFS will not perform a check-in unless there are actually changes to the files.&lt;/p&gt;  &lt;p&gt;So yeah, not TFS’ most shining moment.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4527204857540689070?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4527204857540689070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4527204857540689070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4527204857540689070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4527204857540689070'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/10/tfs-locked-for-check-out.html' title='TFS: Locked for Check-out'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4766525039184089136</id><published>2009-08-06T00:01:00.001-04:00</published><updated>2009-08-06T00:01:49.300-04:00</updated><title type='text'>Cloud Morphology</title><content type='html'>&lt;p&gt;Spent some time this evening tracking down the various component technologies of the myriad cloud offerings out there.&amp;#160; Here’s the result.&amp;#160; This will be updated over time.&lt;/p&gt; &lt;!-- Google Spreadsheets Element Code --&gt; &lt;iframe frameborder="0" marginwidth="0" marginheight="0" border="0" style="border:0;margin:0;width:720px;height:360px;" src="http://spreadsheets.google.com/pub?output=html&amp;amp;widget=true&amp;amp;single=true&amp;amp;element=true&amp;amp;gid=0&amp;amp;key=tLRUKXB-k-n0ON92stPlMIA" scrolling="no" allowtransparency="true"&gt;&lt;/iframe&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4766525039184089136?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4766525039184089136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4766525039184089136' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4766525039184089136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4766525039184089136'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/08/cloud-morphology.html' title='Cloud Morphology'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-9172548469184328298</id><published>2009-08-04T17:45:00.001-04:00</published><updated>2009-08-04T17:50:13.133-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>NASA’s Cloud Platform: NEBULA, and Amorphous Morphology</title><content type='html'>&lt;blockquote&gt;   &lt;p&gt;&lt;a href="http://nebula.nasa.gov/services" target="_blank"&gt;NEBULA&lt;/a&gt; is a Cloud Computing environment developed at NASA Ames Research Center, integrating a set of open-source components into a seamless, self-service platform. It provides high-capacity computing, storage and network connectivity, and uses a virtualized, scalable approach to achieve cost and energy efficiencies.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;They always write it in all caps, though it doesn’t appear to be an acronym. My guess is that it’s easier to search for “NEBULA” and find what you want at NASA. And, what better name for a cloud computing platform?&lt;/p&gt;  &lt;p&gt;To be frank, I didn’t recognize any of the technologies other than RabbitMQ and Apache. So I set out to find out what each piece does, and it’s these times that really make me envious of the LAMP folks. There is so much going on in the OSS world!&lt;/p&gt;  &lt;p&gt;In fact, it’s that sheer volume of innovation that makes it such a nightmare. Here’s where having NASA or Amazon or Elastra or EngineYard or Rackspace or Google AppEngine discuss their respective cloud infrastructures is so beneficial. If you look at their technology choices as a Venn diagram, you might find an optimal set of technologies in the overlap. Beyond that, you can begin to form a generalized blueprint of a cloud platform, identifying the core components.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_FQ1igFTZD04/Snir7-NT8pI/AAAAAAAAAE0/KYVeGPFTGlg/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="cloud provider Venn diagram" border="0" alt="cloud provider Venn diagram" src="http://lh6.ggpht.com/_FQ1igFTZD04/Snir8nV_TfI/AAAAAAAAAE4/5_qQ1KY0RHg/image_thumb%5B12%5D.png?imgmax=800" width="244" height="145" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this way the cloud begins to take shape. Were we to sit all the big industry players down and say, define the cloud al a the OSI model, no one would have gotten around to building one. If we find the clouds in the wild, we can dissect them and find out what makes them tick. We can reverse engineer our blueprint.&lt;/p&gt;  &lt;p&gt;There’s a few major players missing here, of course, most notably Salesforce.com (SFDC) and Microsoft’s Azure platform.&amp;#160; SFDC doesn’t have an infrastructure that you can replicate, per se, because it is inseparable from their proprietary technologies.&amp;#160; In fact, Stu Charlton and others have noted that this is their biggest failing.&amp;#160; Similarly, Microsoft’s Azure is also a monolithic platform play, with the major difference that the platform can be deployed on premises, a so-called private cloud.&lt;/p&gt;  &lt;p&gt;Still though, we can include SFDC and Azure in our analysis.&amp;#160; We can develop our morphology of the cloud platforms that have published their constituent technologies.&amp;#160; With the language of this morphology in hand, we can classify the facilities of other cloud platforms.&amp;#160; Perhaps a taxonomy will evolve that allows us to identify Platform-as-a-Service, Infrastructure-as-a-Service, Software-as-a-Service, hybrids, and perhaps some novel species.&lt;/p&gt;  &lt;p&gt;Despite the amorphous character implied by the term cloud computing, these platforms have well-defined structure.&amp;#160; Moreover, unlike the traditional use of clouds in architecture diagrams, the details of this structure are important.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-9172548469184328298?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/9172548469184328298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=9172548469184328298' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9172548469184328298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9172548469184328298'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/08/nasas-cloud-platform-nebula-and.html' title='NASA’s Cloud Platform: NEBULA, and Amorphous Morphology'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_FQ1igFTZD04/Snir8nV_TfI/AAAAAAAAAE4/5_qQ1KY0RHg/s72-c/image_thumb%5B12%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7380910121744605614</id><published>2009-08-02T23:33:00.001-04:00</published><updated>2009-08-02T23:33:24.509-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><title type='text'>Powershell: Get Size of Child Directories</title><content type='html'>&lt;p&gt;gci -recurse -force |   &lt;br /&gt; ? { $_.GetType() -like 'System.IO.DirectoryInfo'} |    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; select-object Name,@{Name=&amp;quot;size&amp;quot;; Expression = {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ($_.GetFiles()&amp;#160; |    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Measure-Object -Property Length -Sum |    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Measure-Object -Property Sum -Sum).Sum}} | sort-object -Property size&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7380910121744605614?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7380910121744605614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7380910121744605614' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7380910121744605614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7380910121744605614'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/08/powershell-get-size-of-child.html' title='Powershell: Get Size of Child Directories'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6465441172974950307</id><published>2009-07-08T14:09:00.001-04:00</published><updated>2009-07-08T14:10:55.667-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Three Common Fallacies Concerning REST</title><content type='html'>&lt;blockquote&gt;   &lt;p&gt;Better to light a candle than to curse the darkness. -Chinese Proverb&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I purposely did not title this post “&lt;u&gt;&lt;a href="http://blogs.sun.com/jag/resource/Fallacies.html" target="_blank"&gt;The 3 Fallacies of RESTful Computing&lt;/a&gt;&lt;/u&gt;” as I am certainly not an expert in either REST or fallacy. :)&amp;#160; I am, however, quite well-versed in auto-didacticism, and over the past week I’ve been boning up on REST.&amp;#160; Along the way I’ve had one of my early notions of REST disabused (it is neither an architecture nor a protocol) and noticed a few other common misconceptions in the blogosphere and tweet stream.&amp;#160; If you are new to REST, or even if you aren’t, you might very well find a few edifying points in this post; I hope to light a candle or two out there. &lt;/p&gt;  &lt;p&gt;Without further ado, here are three common fallacies concerning REST.&amp;#160; &lt;/p&gt;  &lt;h3&gt;&lt;a name="fallacy1"&gt;Fallacy #1 REST is CRUD&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;Perhaps the most common fallacy of RESTful computing is that &lt;a href="http://twitter.com/dnene/status/2052779808" target="_blank"&gt;REST is simply CRUD&lt;/a&gt; (Create, Read, Update, and Delete) over HTTP.&amp;#160; &lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx" target="_blank"&gt;Microsoft’s ADO.NET Data Services&lt;/a&gt; endeavors to provide developers a “data service being surfaced to the web as a REST-style resource collection[…]”; this would seem to further the notion that REST is another way of doing CRUD.&lt;/p&gt;  &lt;p&gt;However, &lt;a href="http://www.stucharlton.com/blog/archives/000551.html" target="_blank"&gt;REST is not CRUD&lt;/a&gt; as Stu Charlton states in a blog post about REST design guidelines; &lt;a href="http://www.rgoarchitects.com/nblog/2009/06/23/CRUDIsBadForREST.aspx" target="_blank"&gt;Arnon Rotem-Gal-Oz says CRUD is bad for REST&lt;/a&gt;, too.&amp;#160; If we are going to attempt to abridge RESTful architecture with an innocuous statement of the form “REST is X over HTTP” let us say that &lt;strong&gt;REST is using URLs to facilitate application state changes over HTTP&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;&lt;a name="fallacy2"&gt;Fallacy #2 POST is not RESTful&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;First, it is very important to note that REST is not tied to a specific protocol.&amp;#160; As an architectural style, it is protocol agnostic; though to be sure HTTP is a natural fit for many reasons.&amp;#160; As Fielding said in &lt;a href="http://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post" target="_blank"&gt;It is okay to use POST&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Search my dissertation and you won’t find any mention of CRUD or POST. The only mention of PUT is in regard to HTTP’s lack of write-back caching.&amp;#160; The main reason for my lack of specificity is because the methods defined by HTTP are part of the Web’s architecture definition, not the REST architectural style.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Since the nominal use of POST is orthogonal to RESTfulness, by definition, it cannot be the case that POST is antithetical to REST.&amp;#160; Nevertheless, it is important to understand the reasoning that generally goes into this fallacy, because it speaks directly to a core principle of REST.&amp;#160; Most architectures expose an API that allows consumers to affect the state of the application only indirectly.&amp;#160; To understand the implications of your actions as a consumer, you then have—at best—to be very familiar with the application architecture and be aware that you are making a lot of assumptions.&amp;#160; The state mechanics are hidden from you.&amp;#160; You cannot explicitly move the application from one state to another, nor can you directly observe the transition(s) that have taken place.&amp;#160; &lt;/p&gt;  &lt;p&gt;A primary goal of Representational State Transfer is to make the application’s state machine unambiguous by exposing representations of application resources that have embedded within them &lt;a href="http://www.w3.org/Addressing/" target="_blank"&gt;URI&lt;/a&gt;s pertinent to the resource.&amp;#160; In this way a consumer of a RESTful service can discover the current state of the resource, the mechanisms to affect change in the resource, and other resources related to the current resource in the application’s state.&amp;#160; This is what is known as Hypertext as the Engine of Application State (HatEoAS).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.stucharlton.com/blog/archives/000141.html" target="_blank"&gt;HatEoAS&lt;/a&gt; implies a model where all of your important resources are represented by unique URIs and all important state changes are done by interacting with representations sent to or retrieved from those URIs. Most people first approaching REST view it in terms of opposing other architectural “styles” such as SOA or get mired in implementation immediately and begin contrasting their understanding of REST over HTTP against WS-*. Another common problem is reducing the ethos of REST to “RPC is bad” and “we don’t need all that complexity, we have HTTP” (see &lt;a href="#fallacy3"&gt;REST is better than WS-*&lt;/a&gt;).&amp;#160; These views are commonplace because REST is being promulgated as a better solution for many types of applications on the Web.&lt;/p&gt;  &lt;p&gt;The specifics of how REST works over HTTP are beyond the scope of this article, and the subject of a &lt;a href="http://www.tbray.org/ongoing/When/200x/2009/07/02/Slow-REST" target="_blank"&gt;lot of debate&lt;/a&gt;, but, since a &lt;a href="http://www.tbray.org/ongoing/When/200x/2009/03/20/Rest-Casuistry" target="_blank"&gt;lot of uses of POST seem very much like RPC-style invocations&lt;/a&gt;, people have a knee-jerk reaction that POST is not RESTful.&amp;#160; By now you know this is not the case, but let’s hear from the experts.&lt;/p&gt;  &lt;p&gt;From Fielding:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;POST only becomes an issue when it is used in a situation for which some other method is ideally suited: e.g., retrieval of information that should be a representation of some resource (GET), complete replacement of a representation (PUT) […]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Stu Charlton’s &lt;a href="http://www.stucharlton.com/blog/archives/000551.html" target="_blank"&gt;design guidelines&lt;/a&gt; say nearly the same thing:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The problem with POST is when we abuse it by having it perform things that are more expressive in one of the other methods. GET being the obvious one that needs no hypermedia description. For the other methods, a good design guideline is that you MUST not break the general contract of the HTTP method you choose -- but you SHOULD describe the specific intent of that method in hypermedia.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;&lt;a name="fallacy3"&gt;Fallacy #3 REST is better than WS-*&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;In fact, Fielding’s thesis does address many of the problems and advantages of various &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/net_arch_styles.htm" target="_blank"&gt;network-based architectural styles&lt;/a&gt;, but no where does he claim REST is the one ring to rule them all.&amp;#160; In his aforementioned blog post Fielding says (emphasis my own),&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[…]there are plenty of information systems that can be designed using the &lt;strong&gt;REST architectural style&lt;/strong&gt; and gain the &lt;strong&gt;associated benefits&lt;/strong&gt;. Managing cloud instances is certainly one of those applications for which REST is a good fit[…]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;From his thesis, here is the definition of the &lt;strong&gt;REST architectural style&lt;/strong&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;REST consists of a set of architectural constraints chosen for the properties they induce on candidate architectures. […] [It] is an abstraction of the architectural elements within a distributed hypermedia system. […] It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So, the &lt;strong&gt;associated benefits&lt;/strong&gt; are induced by constraints that collectively are referred to as the REST architectural style.&amp;#160; The benefits are myriad, and many of the constraints are are recognizable in how the web works. Section #5 of the thesis is concise and readable, and I encourage the reader to internalize it.&amp;#160; &lt;/p&gt;  &lt;p&gt;The salient point here is that REST is not a protocol; it’s not even an architecture.&amp;#160; REST is an architectural &lt;strong&gt;&lt;em&gt;style!&lt;/em&gt;&lt;/strong&gt; By understanding its constraints and benefits, we can make informed decisions about its applicability to our problem domain and appropriation of technologies.&amp;#160; Comparing REST to the WS-* suite of protocols is comparing apples to oranges, though there are those who &lt;a href="http://blog.therestfulway.com/2009/06/rest-and-http-services-as-business.html" target="_blank"&gt;strongly argue the benefits of REST and HTTP over SOAP&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6465441172974950307?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6465441172974950307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6465441172974950307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6465441172974950307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6465441172974950307'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/07/three-common-fallacies-concerning-rest.html' title='Three Common Fallacies Concerning REST'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1882311768173650630</id><published>2009-06-27T11:28:00.001-04:00</published><updated>2009-06-27T11:28:29.452-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>What, Not How &amp; Why, Not When</title><content type='html'>&lt;p&gt;It occurred to me this morning that many software development principles seem to emerge from the rigorous application of the following principle:&lt;/p&gt; &lt;blockquote&gt;Your architecture and code should make What &amp;amp; Why explicit without specifying How &amp;amp; When.&lt;/blockquote&gt; &lt;dl&gt; &lt;dt&gt;What, Not How&lt;dt&gt; &lt;dl&gt;&lt;p&gt;It is well known that we should prefer declarative over imperative code. By observing the Law of Demeter, we are in fact forced to create declarative, What, semantics in our interfaces since we can't get at the How, the imperative constructs. The Single-Responsibility Principle tends to force us to factor out the How into other classes, leaving us to consume other classes with What semantics. Further, the Interface Segregation Principle requires us to explicity segregate the interfaces our clients consume based on What they are trying to accomplish; if our focus was How, such segregation would be less of a concern.&lt;/p&gt; &lt;p&gt;Event-Driven Architectures (EDA) are another example of What, Not How.  Whereas the SOLID principles operate at the class design level of abstraction, EDA is concerned with system-level architecture. In an Event-Drive Architecture, we explicitly model happenings in the domain.  Rather than coupling the site of the happening to a specific party designating for dealing with that happening, we create an Event and use reliabile messaging and subscription schemes to allow one or many services to handle it. In other words, instead of specifying How to deal with a happening at the site that generates it, we explicitly model What happened and let other parties worry about How to deal with it.&lt;/p&gt;&lt;/dl&gt; &lt;dt&gt;Why, Not When&lt;/dt&gt; &lt;dl&gt;&lt;p&gt;This maxim is both more subtle and more prosaic than What, Not How.  It is probably pretty obvious that when given a requirement stated, "if the purchase order acknowledgement is not received within two hours, notify someone in fulfillment," we should model an Event "POAckIsLate" as opposed to "TwoHoursHaveElapsedWithoutReceivingPOAck". We will have different SLAs with different vendors; those SLAs will change, etc. So we can say, when modeling Events in our domain, we should prefer specifying Why, Not When.&lt;/p&gt; &lt;p&gt;Perhaps more subtle is the implications for communication semantics between modules.  If we model our communications with Why in mind, we don't get mired in the concurrency problems of specifying When.  Consider a workflow.  If we specify When to go to a particular step, the underlying reason may have changed unless we take some sort of explicit lock on shared state.  If we instead specify Why a particular state transition takes place, we can avoid inconsistent states through continuous evaluation. If we make Why explicit and consequently create semantics to evaluate Why independently of "current" state, it becomes possible to evaluate the state consistently without any shared state, i.e. without a notion of When.&lt;/p&gt;&lt;/dl&gt;  &lt;p&gt;As an example, if we had the requirement, "when a PO is received with a quantity for part X above a twenty units, move the order to the top of the work queue," we should model a "BulkProductionRequest" Event and an "ExpediteProduction"; we should not implement a "Reprioritize Production Queue For Order of PartX Over Twenty Units".  Begin with the end in mind and ask What do we want to do (expedite production) not How (re-prioritize production queue).  Ask Why are we expediting this order? Because it is Bulk.  What is Bulk?  Bulk is a quality determined by a CapacityPlanning service and implies that the quantity exceeds some production capacity threshold.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1882311768173650630?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1882311768173650630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1882311768173650630' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1882311768173650630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1882311768173650630'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/06/what-not-how-why-not-when.html' title='What, Not How &amp;amp; Why, Not When'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-5717631758636986403</id><published>2009-06-26T14:33:00.001-04:00</published><updated>2009-06-26T14:33:16.042-04:00</updated><title type='text'>Pareto, Zipf, Heap: The 80-20 Rule, Language, and Diminishing Returns</title><content type='html'>&lt;p&gt;Please consider this a sort of layman’s disambiguation page.&lt;/p&gt;  &lt;p&gt;The classic “80-20 rule” refers to a Pareto distribution.&amp;#160; The thin distribution of the 20% is the subject of Chris Anderson’s “The Long Tail”.&amp;#160; Originally, the Pareto distribution referred to the fact that 20% of the people control 80% of the wealth, but it has turned up in many other contexts.&lt;/p&gt;  &lt;p&gt;A Zipf’s Law is about rankings and frequency.&amp;#160; The second item’s frequency will be half of the first; the third’s frequency will be half the second, and so on.&amp;#160; The “half” may be some other factor, but it remains constant in the distribution; the rank is inversely proportional to the frequency. The item in Zipf’s Law is a word and its frequency is its appearance in a corpus of English text.&amp;#160; However, Zipf’s Law holds for texts generated from a fixed alphabet by picking letters randomly with a uniform distribution.&lt;/p&gt;  &lt;p&gt;Heaps’ Law is about diminishing returns.&amp;#160; It has an exact formula, but generally it says that the more you look into a text, the fewer new discoveries of words you’ll find.&amp;#160; So, as you read through the text it takes longer and longer to find new words in the text.&amp;#160; Heaps’ Law applied to the general case where the “words” are just classifiers of some collection of things.&amp;#160; So, it could be applied to the nationality of a collection of people; you’d have to gather more and more people from a random sampling to get a representative from all countries.&lt;/p&gt;  &lt;p&gt;The implications of these laws in various contexts are the subject of much interesting study and postulation.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-5717631758636986403?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/5717631758636986403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=5717631758636986403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5717631758636986403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5717631758636986403'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/06/pareto-zipf-heap-80-20-rule-language.html' title='Pareto, Zipf, Heap: The 80-20 Rule, Language, and Diminishing Returns'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8552488741575482016</id><published>2009-06-16T21:29:00.001-04:00</published><updated>2009-06-16T21:58:05.872-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='wcf'/><title type='text'>Value Objects and Value Domains</title><content type='html'>&lt;p&gt;I’ve written relatively extensively on the topic of &lt;a href="http://iformattable.blogspot.com/2007/09/replacing-enum-constructs-with-classes.html" target="_blank"&gt;replacing enum constructs with classes&lt;/a&gt;, so I won’t rehash the topic. Instead, I’d like to introduce you to some code I’ve written that enables you to create finite domains of Value Objects in C#.&amp;#160; Please see my two &lt;a href="http://iformattable.blogspot.com/2007/09/replacing-enum-constructs-with-classes.html" target="_blank"&gt;previous&lt;/a&gt; &lt;a href="http://iformattable.blogspot.com/2007/07/replace-enum-constructs-with-classes.html" target="_blank"&gt;posts&lt;/a&gt; on the subject to learn more about the benefits of this approach.&amp;#160; To see how the Value Object semantics and making a finite domain a first class concept in the pattern improves the approach, read on.&lt;/p&gt;  &lt;p&gt;First, we need some definitions.&amp;#160; We are taking the concept of a Value Object from Eric Evans’ book “Domain Driven Design” p.99:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;When you care only about the attributes of an element of the model, classify it as a Value Object. Make it express the meaning of the attributes it conveys and give it related functionality. Treat the Value Object as immutable.&amp;#160; Don’t give it any identity […] The attributes that make up a Value Object should form a &lt;a href="http://fit.c2.com/wiki.cgi?WholeValue" target="_blank"&gt;conceptual whole&lt;/a&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;An example here is useful.&amp;#160; Consider modeling the domain of a book publisher.&amp;#160; At some point you need to capture all the different formats of books: A4, B, Pinched Crown, etc.&amp;#160; The attributes of width, height, unit of measure, and name would go into your model.&amp;#160; But, any instance of your A4 Value Object should be completely interchangeable from any other A4.&amp;#160; And, it goes without saying that you can’t change the width or height or any other attribute of A4.&lt;/p&gt;  &lt;p&gt;All of the different formats of books belong to a &lt;em&gt;Value Domain&lt;/em&gt;. According to &lt;a href="http://wordnetweb.princeton.edu/perl/webwn?s=domain" target="_blank"&gt;WordNet&lt;/a&gt;, a domain (we are using the mathematical notion) is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;the set of values of the independent variable for which a function is defined&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The functional complement of a domain is the range of the function; i.e. domain is what you can put in, the range is what you can expect to get out.&amp;#160; I like calling this concept in my approach a domain instead of a set, because it neatly captures a key benefit.&amp;#160; When we are writing code.&amp;#160; We want to declare our parameters as being a proper member of domain of values, instead of just primitive types or strings.&lt;/p&gt;  &lt;p&gt;Now we’re ready to dive into the implementation.&amp;#160; Let’s begin with the end in mind.&amp;#160; I want to write a function, say, that let’s me search for a document with a particular format about an arbitrary topic.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;SearchDocs(DocFormat docFormat, &lt;span style="color: blue"&gt;string &lt;/span&gt;topic)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ok, so we could create a base class or an interface called DocFormat and create Word doc, PDF, etc. that inherit from or implement DocFormat.&amp;#160; Easy.&amp;#160; But, SearchDocs has to be able to handle all current and future implementations of DocFormat; it must not violate the &lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle" target="_blank"&gt;Liskov substitution principle&lt;/a&gt;. What if the repository or search algorithm depends on the what the doc format actually is?&amp;#160; Also, we’d have a subclass of DocFormat to write for every document type, and we’d have to do a &lt;a href="http://blogs.msdn.com/lucabol/archive/2007/12/03/creating-an-immutable-value-object-in-c-part-i-using-a-class.aspx" target="_blank"&gt;lot of work&lt;/a&gt; to remove object identity, since your instance of PDF is not the same as my instance of PDF.&amp;#160; And, don’t forget to make the whole thing &lt;a href="http://blogs.msdn.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx" target="_blank"&gt;immutable&lt;/a&gt;. [Note: I know this is a contrived example with well-established OOP solutions that don’t require LSP violation.&amp;#160; Work with me here. :)]&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Clearly we have a lot of work to do to make our Value Objects a reality.&amp;#160; It’s not impossible, though, and a quick &lt;strike&gt;Bing&lt;/strike&gt; Google turns up a couple of investigations and approaches.&amp;#160; &lt;a href="http://grabbagoft.blogspot.com/2007/06/generic-value-object-equality.html" target="_blank"&gt;Jimmy Bogard’s approach&lt;/a&gt; gave me a clue that I needed to get it working.&amp;#160; What I wanted was a base type, ValueObject, that I could inherit from and get the Value Object semantics described in Evans.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Jimmy’s approach used a self-referencing &lt;a href="http://msdn.microsoft.com/en-us/library/sz6zd40f(VS.80).aspx" target="_blank"&gt;open constructed type&lt;/a&gt; to allow the ValueObject base class to do all the work of providing Value Object semantics.&amp;#160; This base class uses dynamic reflection to determine what properties to use in the derived class to do equality comparisons (an approach &lt;a href="http://elegantcode.com/2009/06/07/generic-value-object/" target="_blank"&gt;nominally improved upon here&lt;/a&gt;). He saw his approach as having a single fundamental flaw; it only worked for the first level of inheritance, i.e. the first descendent from ValueObject.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;For my purposes—creating a bounded, finite domain of Value Objects to replace enum-type classes--this is not a flaw.&amp;#160; Substantively, all that remains to do is introduce the concept of the the Value Domain into Jimmy’s approach and put the Value Objects in it.&amp;#160; Because I wanted to use these Value Domains throughout the enterprise, I baked WCF support into my approach.&amp;#160; Further, because the Value Domain is defined &lt;em&gt;a priori&lt;/em&gt;, I didn’t have to play with object identity; I could simply look the value up in the domain.&amp;#160; (It took a little out-of-the-box thinking to get that to work transparently.)&amp;#160; Finally, I wanted it to be trivially easy to create these Value Domains, so I created a snippet for use in Visual Studio.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here’s an example of Value Domain and Value Objects implementation:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;DataContract&lt;/span&gt;]&lt;br /&gt;&lt;span style="color: blue"&gt;public sealed class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DocFormats &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ValueObject&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;DocFormats&lt;/span&gt;.&lt;span style="color: #2b91af"&gt;DocFormat&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;DocFormats&lt;/span&gt;&amp;gt;.&lt;span style="color: #2b91af"&gt;Values&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;DocFormats&lt;/span&gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;private &lt;/span&gt;DocFormats()&lt;br /&gt;    {&lt;br /&gt;        Word = Add(&lt;span style="color: #a31515"&gt;&amp;quot;Word&amp;quot;&lt;/span&gt;);&lt;br /&gt;        PDF = Add(&lt;span style="color: #a31515"&gt;&amp;quot;PDF&amp;quot;&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [&lt;span style="color: #2b91af"&gt;DataMember&lt;/span&gt;]&lt;br /&gt;    &lt;span style="color: blue"&gt;public readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;BindingType &lt;/span&gt;Word, PDF;&lt;br /&gt;&lt;br /&gt;    [&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]&lt;br /&gt;    &lt;span style="color: blue"&gt;public sealed class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DocFormat &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ValueObject&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;DocFormat&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;DocFormats&lt;/span&gt;&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;private &lt;/span&gt;DocFormat(&lt;span style="color: blue"&gt;string &lt;/span&gt;v) : &lt;span style="color: blue"&gt;base&lt;/span&gt;(v) { }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;DocFormats is the Value Domain.&amp;#160; DocFormat is the type of the Value Object.&amp;#160; String is the underlying type of the values, but the pattern supports anything that implements IEquatable and IComparable.&amp;#160; Methods can accept DocFormats.DocFormat as a parameter and only Word and PDF will be valid.&amp;#160; Code can specify those values through a Singleton accessor: DocFormats.Instance.PDF.&amp;#160; You’ll notice that the only constructor is private; the Singleton implementation is in the base value domain base class (ValueObject&amp;lt;…&amp;gt;.Values&amp;lt;…&amp;gt;).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: green"&gt;// our new method interface&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;SearchDocs(DocFormats.DocFormat docFormat, &lt;span style="color: blue"&gt;string &lt;/span&gt;topic)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: green"&gt;// referencing an individual value&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt;(DocFormats.Instance.Word == docFormat)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: green"&gt;//...&lt;br /&gt;    &lt;/span&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Above you’ll note that the Value Object type definition (subclass of ValueObject&amp;lt;…&amp;gt;) is nested inside of the Value Domain.&amp;#160; Doing that groups the two together syntactically in a very natural way (FooTypes.FooType); the entire domain of values is contained in one place.&amp;#160; That locality makes the snippet to produce them cohesive too.&amp;#160; [Note: I’ve included the snippet XML at the end of this post.] &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Interestingly, the underlying implementation necessarily inverts this nesting; the Value Domain base class is nested in the Value Object base class.&amp;#160; That allows the Value Domain Singleton to create instances of Value Objects.&amp;#160; I only had to resort to reflection in order to allow the Value Domain base class to provide the Singleton implementation.&amp;#160; Inversion of Control containers like Unity and Castle Windsor do this kind of reflection all the time, and it’s cheap since .NET 2.0.&amp;#160; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Without further ado, here’s the base classes implementation.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;&lt;br /&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Collections.Generic;&lt;br /&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Reflection;&lt;br /&gt;&lt;br /&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]&lt;br /&gt;&lt;span style="color: blue"&gt;public abstract class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ValueObject&lt;/span&gt;&amp;lt;T, TValue, TValues&amp;gt; : &lt;span style="color: #2b91af"&gt;IEquatable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;where &lt;/span&gt;T : ValueObject&amp;lt;T, TValue, TValues&amp;gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;where &lt;/span&gt;TValue : &lt;span style="color: #2b91af"&gt;IEquatable&lt;/span&gt;&amp;lt;TValue&amp;gt;, &lt;span style="color: #2b91af"&gt;IComparable&lt;/span&gt;&amp;lt;TValue&amp;gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;where &lt;/span&gt;TValues : ValueObject&amp;lt;T, TValue, TValues&amp;gt;.Values&amp;lt;TValues&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: gray"&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// &lt;/span&gt;&lt;span style="color: green"&gt;This is the encapsulated value.&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: gray"&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;public readonly &lt;/span&gt;TValue Value;&lt;br /&gt;    &lt;span style="color: blue"&gt;protected &lt;/span&gt;ValueObject(TValue value)&lt;br /&gt;    {&lt;br /&gt;        Value = value;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;#region &lt;/span&gt;equality&lt;br /&gt;    &lt;span style="color: blue"&gt;public override bool &lt;/span&gt;Equals(&lt;span style="color: blue"&gt;object &lt;/span&gt;other)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;other != &lt;span style="color: blue"&gt;null &lt;/span&gt;&amp;amp;&amp;amp; other &lt;span style="color: blue"&gt;is &lt;/span&gt;T &amp;amp;&amp;amp; Equals(other &lt;span style="color: blue"&gt;as &lt;/span&gt;T);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public override int &lt;/span&gt;GetHashCode()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: green"&gt;// TODO provide an efficient implementation&lt;br /&gt;        // http://www.dotnetjunkies.com/weblog/tim.weaver/archive/2005/04/04/62285.aspx&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;return &lt;/span&gt;Value.GetHashCode();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public bool &lt;/span&gt;Equals(T other)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;other != &lt;span style="color: blue"&gt;null &lt;/span&gt;&amp;amp;&amp;amp; Value.Equals(other.Value);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public static bool operator &lt;/span&gt;==(ValueObject&amp;lt;T, TValue, TValues&amp;gt; x, ValueObject&amp;lt;T, TValue, TValues&amp;gt; y)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: green"&gt;// pointing to same heap location&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(ReferenceEquals(x, y)) &lt;span style="color: blue"&gt;return true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: green"&gt;// both references are null&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;(&lt;span style="color: blue"&gt;null &lt;/span&gt;== (&lt;span style="color: blue"&gt;object&lt;/span&gt;)(x ?? y)) &lt;span style="color: blue"&gt;return true&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: green"&gt;// auto-boxed LHS is not null&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;((&lt;span style="color: blue"&gt;object&lt;/span&gt;)x != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;x.Equals(y);&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;return false&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public static bool operator &lt;/span&gt;!=(ValueObject&amp;lt;T, TValue, TValues&amp;gt; x, ValueObject&amp;lt;T, TValue, TValues&amp;gt; y)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;!(x == y);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue"&gt;#endregion&lt;br /&gt;&lt;br /&gt;    public static implicit operator &lt;/span&gt;TValue(ValueObject&amp;lt;T, TValue, TValues&amp;gt; obj)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;obj.Value;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public static implicit operator &lt;/span&gt;ValueObject&amp;lt;T, TValue, TValues&amp;gt;(TValue val)&lt;br /&gt;    {&lt;br /&gt;        T valueObject;&lt;br /&gt;        &lt;span style="color: blue"&gt;if &lt;/span&gt;(Values&amp;lt;TValues&amp;gt;.Instance.TryGetValue(val, &lt;span style="color: blue"&gt;out &lt;/span&gt;valueObject))&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;valueObject;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;InvalidCastException&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;{0} cannot be converted&amp;quot;&lt;/span&gt;, val));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public override string &lt;/span&gt;ToString()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;Value.ToString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;#region &lt;/span&gt;comparison&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public int &lt;/span&gt;CompareTo(T other)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;Value.CompareTo(other);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public int &lt;/span&gt;CompareTo(&lt;span style="color: blue"&gt;object &lt;/span&gt;obj)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;if &lt;/span&gt;(&lt;span style="color: blue"&gt;null &lt;/span&gt;== obj)&lt;br /&gt;            &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ArgumentNullException&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;if &lt;/span&gt;(obj &lt;span style="color: blue"&gt;is &lt;/span&gt;T)&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;Value.CompareTo((obj &lt;span style="color: blue"&gt;as &lt;/span&gt;T).Value);&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ArgumentException&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;String&lt;/span&gt;.Format(&lt;span style="color: #a31515"&gt;&amp;quot;Must be of type {0}&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(T)));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;#endregion&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;[&lt;span style="color: #2b91af"&gt;Serializable&lt;/span&gt;]&lt;br /&gt;    &lt;span style="color: blue"&gt;public abstract class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Values&lt;/span&gt;&amp;lt;TDomain&amp;gt; &lt;span style="color: blue"&gt;where &lt;/span&gt;TDomain : Values&amp;lt;TDomain&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        [&lt;span style="color: #2b91af"&gt;NonSerialized&lt;/span&gt;]&lt;br /&gt;        &lt;span style="color: blue"&gt;protected readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&amp;lt;TValue, T&amp;gt; _values = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&amp;lt;TValue, T&amp;gt;();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;private void &lt;/span&gt;Add(T valueObject)&lt;br /&gt;        {&lt;br /&gt;            _values.Add(valueObject.Value, valueObject);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;protected &lt;/span&gt;T Add(TValue val)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: blue"&gt;var &lt;/span&gt;valueObject = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(T).InvokeMember(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(T).Name,&lt;br /&gt;                           &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.CreateInstance | &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.Instance |&lt;br /&gt;                           &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.NonPublic, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;new object&lt;/span&gt;[] { val }) &lt;span style="color: blue"&gt;as &lt;/span&gt;T;&lt;br /&gt;            Add(valueObject);&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;valueObject;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;public bool &lt;/span&gt;TryGetValue(TValue value, &lt;span style="color: blue"&gt;out &lt;/span&gt;T valueObject)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;_values.TryGetValue(value, &lt;span style="color: blue"&gt;out &lt;/span&gt;valueObject);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;public bool &lt;/span&gt;Contains(T valueObject)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;_values.ContainsValue(valueObject);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;static volatile &lt;/span&gt;TDomain _instance;&lt;br /&gt;        &lt;span style="color: blue"&gt;static readonly object &lt;/span&gt;Lock = &lt;span style="color: blue"&gt;new object&lt;/span&gt;();&lt;br /&gt;        &lt;span style="color: blue"&gt;public static &lt;/span&gt;TDomain Instance&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: blue"&gt;get&lt;br /&gt;            &lt;/span&gt;{&lt;br /&gt;                &lt;span style="color: blue"&gt;if &lt;/span&gt;(_instance == &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br /&gt;                    &lt;span style="color: blue"&gt;lock &lt;/span&gt;(Lock)&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span style="color: blue"&gt;if &lt;/span&gt;(_instance == &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br /&gt;                            _instance = &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TDomain)&lt;br /&gt;                                .InvokeMember(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(TDomain).Name,&lt;br /&gt;                                                  &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.CreateInstance |&lt;br /&gt;                                                  &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.Instance |&lt;br /&gt;                                                  &lt;span style="color: #2b91af"&gt;BindingFlags&lt;/span&gt;.NonPublic, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;null&lt;/span&gt;, &lt;span style="color: blue"&gt;null&lt;/span&gt;) &lt;span style="color: blue"&gt;as &lt;/span&gt;TDomain;&lt;br /&gt;                    }&lt;br /&gt;                &lt;span style="color: blue"&gt;return &lt;/span&gt;_instance;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I’d love to hear your feedback.&amp;#160; This is approach is not intended to support unbounded Value Domains, such as the canonical example of Address.&amp;#160; It is meant for the enums-as-classes problem, i.e. finite, bounded Value Domains.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;ValueObject.snippet&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;?&amp;gt;&lt;br /&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeSnippets  &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeSnippet &lt;/span&gt;&lt;span style="color: red"&gt;Format&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0.0&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Header&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;ValueOjbect&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Title&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Shortcut&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;vo&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Shortcut&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Description&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Code snippet for ValueObject and domain&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Description&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Christopher Atkins&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Author&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;SnippetTypes&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;SnippetType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Expansion&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;SnippetType&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;SnippetTypes&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Header&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Snippet&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Declarations&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;domain&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Value domain name&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;MyValues&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;value&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;ValueObject Class name&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;MyValueObject&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;type&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ID&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;Value Type&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;ToolTip&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;          &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;string&lt;span style="color: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Default&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Literal&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Declarations&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;            &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Code &lt;/span&gt;&lt;span style="color: red"&gt;Language&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;csharp&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;![CDATA[    &lt;br /&gt;    &lt;/span&gt;&lt;span style="color: gray"&gt;[DataContract]&lt;br /&gt;    public sealed class $domain$ : ValueObject&amp;lt;$domain$.$value$, $type$, $domain$&amp;gt;.Values&amp;lt;$domain$&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        private $domain$()&lt;br /&gt;        {&lt;br /&gt;            Value1 = Add(String.Empty);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        [DataMember]&lt;br /&gt;        public readonly $value$ Value1;&lt;br /&gt;&lt;br /&gt;        [Serializable]&lt;br /&gt;        public sealed class $value$ : ValueObject&amp;lt;$value$, $type$, $domain$&amp;gt;&lt;br /&gt;        {&lt;br /&gt;            private $value$($type$ v) : base(v) { }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;]]&amp;gt;&lt;br /&gt;            &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Code&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;        &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Snippet&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeSnippet&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;CodeSnippets&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8552488741575482016?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8552488741575482016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8552488741575482016' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8552488741575482016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8552488741575482016'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/06/value-objects-and-value-domains.html' title='Value Objects and Value Domains'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7274348729478024879</id><published>2009-05-28T16:57:00.001-04:00</published><updated>2009-05-28T16:57:21.998-04:00</updated><title type='text'>Google Wave</title><content type='html'>&lt;p&gt;Upon the day mankind's children ask    &lt;br /&gt;Who it was made their world intelligible,     &lt;br /&gt;Those who set about the grand task     &lt;br /&gt;of creating the &lt;a href="http://wave.google.com/" target="_blank"&gt;Wave&lt;/a&gt; will be eligible. &lt;/p&gt;  &lt;p&gt;For never will they have occasion to think    &lt;br /&gt;how to create discourse, share knowledge,     &lt;br /&gt;Wonder about the universe and link     &lt;br /&gt;Without the this wonderful prodigy. &lt;/p&gt;  &lt;p&gt;Like hieroglyphs in the tombs of Kings,    &lt;br /&gt;eee-may-uhls voy-s'-may-uhls eye-ems and tweets     &lt;br /&gt;will serious study to the curious bring,     &lt;br /&gt;to be shared in Waves while ancestors sleep. &lt;/p&gt;  &lt;p&gt;How is it the first step of a journey    &lt;br /&gt;Can put the past so far behind thee?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7274348729478024879?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7274348729478024879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7274348729478024879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7274348729478024879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7274348729478024879'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/05/google-wave.html' title='Google Wave'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7762982293106810697</id><published>2009-05-25T13:34:00.002-04:00</published><updated>2010-05-18T12:37:32.881-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>Connascence: The Underlying Principle of OO Design?</title><content type='html'>&lt;p&gt;This is a great talk at a Ruby conference by Jim Weirich about his attempt to frame all object-oriented design (OOD) principles as special cases of an underlying principle called “connascence”.&amp;#160; Connascence is a term co-opted by Meilir Page-Jones in the ‘90s for use in OOD; below is the definition from his book with Larry Constantine entitled, “Fundamentals of Object-Oriented Design in UML” (page 214):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Connascence between two software elements A and B means either&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;that you can postulate some change to A that would require B to be changed (or at least carefully checked) in order to perserve overall correctness, or &lt;/li&gt;      &lt;li&gt;that you can postulate some change that would require both A and B to be changed together in order to preserve overall correctness. &lt;/li&gt;   &lt;/ol&gt; &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE:&lt;/b&gt; Jim Weirich's talk can be found &lt;a href="http://mwrc2009.confreaks.com/14-mar-2009-18-10-the-building-blocks-of-modularity-jim-weirich.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7762982293106810697?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7762982293106810697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7762982293106810697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7762982293106810697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7762982293106810697'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/05/connascence-underlying-principle-of-oo.html' title='Connascence: The Underlying Principle of OO Design?'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2413651036772682449</id><published>2009-05-21T11:24:00.001-04:00</published><updated>2009-05-21T11:54:51.740-04:00</updated><title type='text'>WolframAlpha: A New Kind of Site</title><content type='html'>&lt;p&gt;&lt;a href="http://www.techcrunch.com/2009/05/12/what-is-google-squared-it-is-how-google-will-crush-wolfram-alpha-exclusive-video/" target="_blank"&gt;TechCrunch called Google Squared the imminent Cain to WolframAlpha’s Abel&lt;/a&gt;. &lt;a href="http://www.25hoursaday.com/weblog/2009/05/16/WolframAlphaTheWikipediaKiller.aspx" target="_blank"&gt;Dare Obsanajo warns Wikipedia to beware the ides of March&lt;/a&gt;, casting WolframAlpha as Brutus.&amp;#160; But, I would cast WolframAlpha in quite a different role: Hamlet.&lt;/p&gt;  &lt;p&gt;If you’ve not used &lt;a href="http://www.wolframalpha.com/" target="_blank"&gt;WolframAlpha&lt;/a&gt;, head over there come back once you’ve exhausted its novelty.&amp;#160; Go ahead, I’ll wait.&lt;/p&gt;  &lt;p&gt;So, now you know why they call it a “computational knowledge engine” whose mission it is to “make the world’s knowledge computable”.&amp;#160; Ignoring, for the present, the interesting epistemological discussion viz. the validity of that mission, let’s instead talk about why you might use it.&lt;/p&gt;  &lt;p&gt;If you are looking for something, go to Google.&amp;#160; This is not a search engine.&lt;/p&gt;  &lt;p&gt;If you are looking to mine the web for hard data, be patient, Google Squared will be your guide (when it is baked).&lt;/p&gt;  &lt;p&gt;If you would like to learn about a particular topic, Wikipedia stands ready to help you begin.&lt;/p&gt;  &lt;p&gt;If you want to apply your existing domain knowledge to posing interesting questions about a wide variety of topics, if you can phrase such questions as nominal computations, then go to WolframAlpha, though your attempts might be frustrated, e.g. it fails to compute the following “annual energy consumption of the average American * projected worldwide population in 2020.”&lt;/p&gt;  &lt;p&gt;In other words for 98% of the world, WolframAlpha is simply a curiosity. For the other 2%, it’s only useful as a way to experiment with such questions, since the rigor required of formal academia is not satisfied by simply saying, “WolframAlpha said so.”&lt;/p&gt;  &lt;p&gt;To understand WolframAlpha’s raison d'être, you have to understand NKS: Stephen Wolfram’s “New Kind of Science”.&amp;#160; To understand NKS you can either go read the book or trust what I’m about to say.&amp;#160; At its core, the claim it makes to novelty is based on the notion that all phenomena can be viewed as computations, and thus real science can be done by exploring the “universe” of possible computations.&amp;#160; Of course the only apparatus sufficient for doing this “new” science is Wolfram’s own Mathematica program, a program originally created by Dr. Wolfram in a single summer.&amp;#160; Twenty or so years later after leaving academia to build the company that develops and sells Mathematica, Wolfram brought forth the the 1,200+ page tome that is NKS.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_FQ1igFTZD04/ShVyROlZ0KI/AAAAAAAAAEs/M3mulvQSmXo/s1600-h/101440%5B2%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="101440" border="0" alt="101440" src="http://lh6.ggpht.com/_FQ1igFTZD04/ShVyRIvUg8I/AAAAAAAAAEw/7KnhSnU1NOs/101440_thumb.jpg?imgmax=800" width="244" height="196" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Wolfram is no lightweight; we’re talking about one of those few people in the world with the intellectual capacity and training to do modern quantum mechanics at age 17—when it comes to mathematics he is the real McCoy.&amp;#160; But, very few seriously look at NKS as being fundamentally new, and no few academics treat Wolfram with vitriol and ire due to his claim of novelty.&amp;#160; We all—it is universally agreed—stand upon the shoulders of giants.&amp;#160; Further, many argue that NKS contributes nothing new to the existing corpus of mathematics or science.&amp;#160; Here are some notes for the dramaturg:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The NKS book was self-published by Wolfram-Media &lt;/li&gt;    &lt;li&gt;Wolfram opens the book with a statement of his childhood dream to “know everything” &lt;/li&gt;    &lt;li&gt;NKS is the culmination of twenty years of work outside of academia &lt;/li&gt;    &lt;li&gt;The precipitating event that put him on that path was his not being able to understand the pattern generated by a cellular automata (simple computer program) he’d written &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;My personal belief is that the cognitive dissonance created by having not contributed to science in any recognized, significant way over twenty years, in the face of soaring hubris born out of his prodigious intellect and early summiting of some of the highest peaks of academia, forces Dr. Wolfram to eschew—even denigrate—the trappings of mainstream academia and embrace his self-created role of the father of a new kind of science.&amp;#160; But, hey, I don’t know the guy; and it goes without saying that I’m criticizing Michael Jordan’s cross-over.&amp;#160; Maybe it will take twenty years for everyone else to get it; if it is new, it's nascent, and you have to walk before you can crawl.&lt;/p&gt;  &lt;p&gt;He may be an egoist, but he has excellent taste.&amp;#160; I think he’d make Edward Tufte proud.&lt;/p&gt;  &lt;p&gt;What WolframAlpha owes its life to is the attempt to make NKS immediately relevant in a roundabout way.&amp;#160; Remember, everything—everything—is simply a computation.&amp;#160; Another concept that is critical to understanding WolframAlpha from NKS is “computational equivalence”; essentially this is the reason why NKS doesn’t permit predicting the future: to do that you would need a computer the equivalent of our universe.&amp;#160; Reality, you see, is simply the current result of the continuous computation being performed by the fabric of our universe.&amp;#160; (As strange as that may sound, it is not dissimilar from the beliefs of proponents of the much vaunted string theories of the universe.)&lt;/p&gt;  &lt;p&gt;Since we don’t have a computer the size of the world, we can’t calculate everything in reality.&amp;#160; What we can do, though, is examine the current results of the computation, in the form of data that can be collected and mined and extruded by domain experts into an symbolic ontology that is computable by Mathematica.&amp;#160; We can then run computations with these synthetic ontologies, because they can be related via formal ontology of units we have created throughout human history.&amp;#160; To what end?&amp;#160; Well, I suppose that depends on the answers you get.&lt;/p&gt;  &lt;p&gt;I hope by now you understand why it is called WolframAlpha.&amp;#160; And, for those lovers of the theater who haven’t yet guessed, here is the cast of characters.&lt;/p&gt; &lt;dl&gt;&lt;dt&gt;Hamlet&lt;/dt&gt;&lt;dd&gt;WolframAlpha&lt;/dd&gt;&lt;dt&gt;Fortinbras&lt;/dt&gt;&lt;dd&gt;Google Squared &lt;/dd&gt;&lt;dt&gt;Gertrude&lt;/dt&gt;&lt;dd&gt;Capitalism&lt;/dd&gt;&lt;dt&gt;Ophelia&lt;/dt&gt;&lt;dd&gt;Wikipedia &lt;/dd&gt;&lt;dt&gt;Claudius&lt;/dt&gt;&lt;dd&gt;Academia&lt;/dd&gt;&lt;/dl&gt;  &lt;p&gt;I think it is obvious who plays the role of the murdered king. Ok, I've surely stretched the metaphor a bit too thin, but I really like the notion that these kinds of current events are manifestations of the same archetypes described in our great literature. I think Wolfram would like it too, but I have no doubt his protagonist wouldn't be from one of Shakespeare's tragedies.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2413651036772682449?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2413651036772682449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2413651036772682449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2413651036772682449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2413651036772682449'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/05/wolframalpha-new-kind-of-site.html' title='WolframAlpha: A New Kind of Site'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_FQ1igFTZD04/ShVyRIvUg8I/AAAAAAAAAEw/7KnhSnU1NOs/s72-c/101440_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2131652274283759420</id><published>2009-05-11T01:05:00.001-04:00</published><updated>2009-05-11T01:05:07.600-04:00</updated><title type='text'>Microsoft TechEd: Day 0</title><content type='html'>&lt;p&gt;It’s the evening before the official start of the Microsoft’s annual IT conference, TechEd.&amp;#160; In 2009 we find ourselves in sunny, yet cool, Los Angeles.&amp;#160; I couldn’t be happier with the weather and the hotel, but so far the conference sucks.&lt;/p&gt;  &lt;p&gt;Why—or, more appropriately, how can I say it sucks when the conference hasn’t begun?&amp;#160; Easy, go to msteched.com and attempt to build a schedule.&amp;#160; Well, you have to be signed in with Windows Live and a registered attendee I believe, but if you could and did you would quickly discover a rather pathetic fail on the part of the conference planners.&amp;#160; The session builder is garbage.&amp;#160; You’ll spend the majority time watching this animation, since they’ve not seemed to master the partial page update without updating the entire 670K+ page weight.&amp;#160; Seriously, I’d rather look at the source and see and XML Data Island than wait for the entire page to reload every time I updated my schedule.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_FQ1igFTZD04/Sgex9jzHN-I/AAAAAAAAAEc/6CezBJ9LAkc/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_FQ1igFTZD04/Sgex-IvHGzI/AAAAAAAAAEg/8JvS7kkCJ6A/image_thumb.png?imgmax=800" width="244" height="88" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Aesthetically, it isn’t bad, the site I mean, but the session builder is garbage.&amp;#160; The session builder for Web 2.0 Expo at least displayed all the tracks and timeslots in a calendar-like fashion, so you could make your decision by sight and rather quickly.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_FQ1igFTZD04/Sgex_-V52lI/AAAAAAAAAEk/29stAGhf6iU/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_FQ1igFTZD04/SgeyAgYFHvI/AAAAAAAAAEo/pA20lZd0w4k/image_thumb%5B1%5D.png?imgmax=800" width="244" height="209" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;But, you know, if the content is there, if the sessions are just awesome, who cares about some clunky, hacked-together conference website?&amp;#160; Don’t judge a book by its cover, right?&amp;#160; So, what are my options for tomorrow’s 11am timeslot?&amp;#160; Well, the first keynote is this one.&lt;/p&gt; &lt;form id="aspnetForm" method="post" name="aspnetForm" action="https://www.msteched.com/schedulebuilder.aspx" jquery1242016308914="21" sizset="1" sizcache="179" oldonsubmit="null"&gt;   &lt;div id="page" jquery1242016308914="20" sizset="1" sizcache="179"&gt;     &lt;div id="content" jquery1242016308914="19" sizset="1" sizcache="179"&gt;       &lt;table width="100%" jquery1242016308914="18" sizset="1" sizcache="179"&gt;&lt;tbody jquery1242016308914="17" sizset="1" sizcache="179"&gt;           &lt;tr jquery1242016308914="16" sizset="1" sizcache="179"&gt;             &lt;td valign="top" sizset="1" sizcache="179"&gt;               &lt;div style="padding-bottom: 5px; padding-left: 5px; width: 545px; padding-right: 5px; height: 218px; padding-top: 5px" sizset="1" sizcache="179"&gt;                 &lt;div id="topicInfoTabContainer" sizset="1" sizcache="179"&gt;                   &lt;div id="topicInfoDiv" sizset="1" sizcache="179"&gt;                     &lt;div style="display: block" id="selectedItemDetails" jquery1242016308914="26" sizset="125" sizcache="169"&gt;                       &lt;div id="selectedTitle"&gt;KEY01 Moving Forward Together: The Potential of IT Innovation&lt;/div&gt;                        &lt;div style="font-size: 8pt" id="selectedPresenter"&gt;Presenter: Bill Veghte&lt;/div&gt;                        &lt;div style="font-size: 8pt" id="selectedTimeslotInfo" sizset="125" sizcache="168"&gt;                         &lt;div class="sessionInfo"&gt;Mon 5/11 | 10:00 AM-11:30 AM | West Hall A&lt;/div&gt;                       &lt;/div&gt;                        &lt;br /&gt;&lt;/div&gt;                      &lt;div id="pnlContainer" sizset="1" sizcache="179"&gt;                       &lt;div style="display: block" id="pnlAbstract" jquery1242016308914="28" sizset="0" sizcache="180"&gt;                         &lt;div class="desc"&gt;In today's economic environment, your company is faced with unprecedented pressures to reduce costs and drive operating efficiencies. At the same time, the demands on IT to deliver more connected services and greater flexibility continue to grow. With the upcoming release of Windows 7, Windows Server 2008 R2, and Exchange &amp;quot;14,&amp;quot; Microsoft helps IT organizations better meet these competing demands. Join Bill Veghte, Senior Vice President of Windows Business, as we explore how these technologies combine to give you the tools and resources to better manage your infrastructure--from back-end services through client-side experiences, and the network in between.&lt;/div&gt;                       &lt;/div&gt;                     &lt;/div&gt;                   &lt;/div&gt;                 &lt;/div&gt;               &lt;/div&gt;             &lt;/td&gt;           &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;     &lt;/div&gt;      &lt;div jquery1242016308914="19" sizset="1" sizcache="179"&gt;Doesn’t exactly inspire.&amp;#160; But, never fear, there is an alternative!&lt;/div&gt;   &lt;/div&gt; &lt;/form&gt;&lt;form id="aspnetForm" method="post" name="aspnetForm" action="https://www.msteched.com/schedulebuilder.aspx" jquery1242016308914="21" sizset="1" sizcache="162" oldonsubmit="null"&gt;   &lt;div id="page" jquery1242016308914="20" sizset="1" sizcache="162"&gt;     &lt;div id="content" jquery1242016308914="19" sizset="1" sizcache="162"&gt;       &lt;table width="100%" jquery1242016308914="18" sizset="1" sizcache="162"&gt;&lt;tbody jquery1242016308914="17" sizset="1" sizcache="162"&gt;           &lt;tr jquery1242016308914="16" sizset="1" sizcache="162"&gt;             &lt;td valign="top" sizset="1" sizcache="162"&gt;               &lt;div style="padding-bottom: 5px; padding-left: 5px; width: 519px; padding-right: 5px; height: 161px; padding-top: 5px" sizset="1" sizcache="162"&gt;                 &lt;div id="topicInfoTabContainer" sizset="1" sizcache="162"&gt;                   &lt;div id="topicInfoDiv" sizset="1" sizcache="162"&gt;                     &lt;div style="display: block" id="selectedItemDetails" jquery1242016308914="26" sizset="125" sizcache="152"&gt;                       &lt;div id="selectedTitle"&gt;PAN59 Agile: A Process or an Excuse?&lt;/div&gt;                        &lt;div style="font-size: 8pt" id="selectedPresenter"&gt;Presenters: Richard Campbell, Stephen Forte, Chris Menegay, Joel Semeniuk&lt;/div&gt;                        &lt;div style="font-size: 8pt" id="selectedTimeslotInfo" sizset="125" sizcache="151"&gt;                         &lt;div class="sessionInfo"&gt;Mon 5/11 | 11:00 AM-12:00 PM | 501C&lt;/div&gt;                       &lt;/div&gt;                        &lt;br /&gt;&lt;/div&gt;                      &lt;div id="pnlContainer" sizset="1" sizcache="162"&gt;                       &lt;div style="display: block" id="pnlAbstract" jquery1242016308914="28" sizset="0" sizcache="163"&gt;                         &lt;div class="desc"&gt;Over the last few years, the community at large has created a number of agile development styles; Scrum, XP, and more are there for you and your team to choose. However, is agile really a process? On the other hand, is it an excuse to avoid accountability and proper development techniques? Come to this interactive session to see what Chris, Steve, and Joel have to say, and, if you are up for it, share your opinion.&lt;/div&gt;                       &lt;/div&gt;                     &lt;/div&gt;                   &lt;/div&gt;                 &lt;/div&gt;               &lt;/div&gt;             &lt;/td&gt;           &lt;/tr&gt;         &lt;/tbody&gt;&lt;/table&gt;     &lt;/div&gt;   &lt;/div&gt; &lt;/form&gt;  &lt;p&gt;Seriously, I’m not making this up.&amp;#160; I came to Los Angeles for this?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2131652274283759420?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2131652274283759420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2131652274283759420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2131652274283759420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2131652274283759420'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/05/microsoft-teched-day-0.html' title='Microsoft TechEd: Day 0'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_FQ1igFTZD04/Sgex-IvHGzI/AAAAAAAAAEg/8JvS7kkCJ6A/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4373118901024978152</id><published>2009-04-09T13:52:00.001-04:00</published><updated>2009-04-09T13:52:10.683-04:00</updated><title type='text'>The Coming Apocalypse of your "Friends"</title><content type='html'>&lt;p&gt;What's a friend on MySpace, Facebook, and Orkut?&amp;#160; If you have five hundred friends, are they really friends?&amp;#160; These are the main reasons why I have not, to this point, joined any of those sites.&amp;#160; I don't have many friends, because I just can't give a lot of people the energy needed to maintain a true, lasting friendship.&lt;/p&gt;  &lt;p&gt;What does this have to do with technology?&amp;#160; Well, Facebook Connect and Google FriendConnect are two apis, with many more to come, that allow you to take your social graph with you.&amp;#160; So now, instead of just being a bunch of people that post something they copy and pasted onto your &amp;quot;wall&amp;quot; at major holidays, they are now people who are going to affect recommendations you get on other websites.&lt;/p&gt;  &lt;p&gt;Tell me, do you want five hundred of your &amp;quot;closest&amp;quot; friends opinions, tastes, and web surfing habits to have a direct effect on your web experience?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4373118901024978152?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4373118901024978152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4373118901024978152' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4373118901024978152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4373118901024978152'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/coming-apocalypse-of-your.html' title='The Coming Apocalypse of your &amp;quot;Friends&amp;quot;'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-5891745495833848830</id><published>2009-04-03T15:10:00.001-04:00</published><updated>2009-04-03T15:10:50.157-04:00</updated><title type='text'>Web 2.0 Expo Day 2</title><content type='html'>&lt;p&gt;This morning started with keynotes, though there didn't seem to be a theme beyond &amp;quot;here is who we could get to come and talk.&amp;quot; The sole exception was the very first speaker, &lt;a href="http://rushkoff.com/" target="_blank"&gt;Douglas Rushkoff&lt;/a&gt;, was fantastic.&amp;#160; I'm really excited about his new book, Life Inc.&amp;#160; His main theses were that corporations were not created to allow competition and artificial currency was not &lt;/p&gt;  &lt;p&gt;Nokia's CEO showed us his vision for ten years from now.&amp;#160; Wearable computers?&amp;#160; Wow, now that's innovative.&amp;#160; He got off on some weird metaphysical rant about projecting our consciousness into the 'net.&amp;#160; What he really means is a constant data stream of my location, mood, and random thoughts.&amp;#160; The only interesting thing he mentioned was geolocation through photography.&amp;#160; I really feel like that is an idea whose time has come.&lt;/p&gt;  &lt;p&gt;Next I attended a session that discussed the relative merits of building directly for the iPhone or the web, and the conclusion was use PhoneGap to do both.&amp;#160; it had some interesting points in making the case to stay web-based, but none of them were very convincing.&amp;#160; He attacked the following five arguments for going native:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Performance--the recent &amp;quot;fast javascript&amp;quot; movement combined with paring down the page bloat that has occurred in recent years &lt;/li&gt;    &lt;li&gt;Offline Usage--there is HTML 5 (and thus embedded mySQL support) in iPhone since v2.0 &lt;/li&gt;    &lt;li&gt;Findability--there are now 25K+ apps in the AppStore &lt;/li&gt;    &lt;li&gt;Device Capabilities (GPS, camera, accelerometer, etc.)--the GPS capabilities are &amp;quot;opening up&amp;quot;, and PhoneGap let's you go native &lt;/li&gt;    &lt;li&gt;Monetization--4% of devices get turned down, people use iPhone apps like tissue paper, you have to sell your app for $0.99 to get any traction &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Some valid points there, but it's ironic that the solution proffered is to start web-based and enhance to native.&lt;/p&gt;  &lt;p&gt;Microsoft Bizspark were the underwriters for Launch Pad at Web 2.0 Expo.&amp;#160; There were five companies who presented:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.phonegap.com"&gt;PhoneGap&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.80legs.com"&gt;80legs&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;zeaLOG &lt;/li&gt;    &lt;li&gt;Dub (at &lt;a href="http://www.dubmenow.com"&gt;DubMeNow&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;Bantam (&lt;a href="http://www.bantamlive.com"&gt;Bantam Networks&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Honestly, I wish I had gone to a different session.&amp;#160; I already knew about PhoneGap from the ten other times it was mentioned this week.&amp;#160; What they are doing at 80legs is really cool, but I'm not sure about its applicability.&amp;#160; They've made something that is really hard to do really cheap, but they've not made it easy.&amp;#160; That is, you still have to write Java code.&amp;#160; I'm more excited about what people are doing with it, a sure sign of a platform play.&amp;#160; I hope they get acquired and rewarded for their hard work.&amp;#160; One last thing, there was maybe a hundred people in the room.&amp;#160; Maybe.&lt;/p&gt;  &lt;p&gt;I went to a talk from the guys at EngineYard.&amp;#160; Pretty good talk, but really centered on the implications of systems management in the could-era.&amp;#160; I really enjoyed the talk, pretty fun.&amp;#160; The gave it in this paired presenter style where one would pick up where the other left off.&amp;#160; Nothing terrible prescient or relevant to me, but they host a lot of really awesome new companies, like github.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-5891745495833848830?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/5891745495833848830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=5891745495833848830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5891745495833848830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5891745495833848830'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/web-20-expo-day-2.html' title='Web 2.0 Expo Day 2'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6305261274278119099</id><published>2009-04-01T21:17:00.001-04:00</published><updated>2009-04-01T21:17:51.009-04:00</updated><title type='text'>Werner Vogels</title><content type='html'>&lt;p&gt;Super cool guy.&amp;#160; He's one of those super geeks that's past the point where he feels it necessary to get dragged into details but is totally upbeat.&amp;#160; It's good to be the king, right?&amp;#160; Perhaps my biggest surprise was to learn just how much Amazon views itself as a technology company.&amp;#160; Amazon's retail experience is just a customer of AWS.&amp;#160; Riiiight.&amp;#160; I find that hard to believe, but he claims that Amazon.com the retail site is not even the biggest customer of AWS.&amp;#160; Whoa.&lt;/p&gt;  &lt;p&gt;My big takeaway from his talk and comments afterward is that only companies that really, really must scale to incredible extremes should build their applications for AWS, i.e. bake in use of SimpleDB, SQS, etc.&amp;#160; What he said to me was, &amp;quot;run your Linux infrastructure on EC2 so you can leave if you don't like us.&amp;quot;&amp;#160; So, really, build great SOA systems and use AWS as a virtualization provider.&amp;#160; He had a lot of great principles in his talk for building scalable systems, including:&lt;/p&gt; &lt;dl&gt;&lt;dt&gt;Autonomy &lt;/dt&gt;&lt;dd&gt;individual components make decisions only based on local information &lt;/dd&gt;&lt;dt&gt;Asynchrony&lt;/dt&gt;&lt;dd&gt;Make progress under all circumstances &lt;/dd&gt;&lt;dt&gt;Controlled Concurrency&lt;/dt&gt;&lt;dd&gt;operations are designed such that limmited or no concurrency control is required &lt;/dd&gt;&lt;dt&gt;Controlled Parallelism&lt;/dt&gt;&lt;dd&gt;use fully decentralized (p2p) techniques to remove bottlenecks &lt;/dd&gt;&lt;dt&gt;Decentralize&lt;/dt&gt;&lt;dd&gt;Remove dependencies &lt;/dd&gt;&lt;dt&gt;Decompose&lt;/dt&gt;&lt;dd&gt;Break up into more granular services &lt;/dd&gt;&lt;dt&gt;Failure Tolerant&lt;/dt&gt;&lt;dd&gt;Failure is a normal part of operation &lt;/dd&gt;&lt;dt&gt;Local Responsibility for Consistency&lt;/dt&gt;&lt;dd&gt;Similar to Autonomy, don't look elsewhere for consistent state &lt;/dd&gt;&lt;dt&gt;Simplicity&lt;/dt&gt;&lt;dd&gt;pare away functionality until you cannot &lt;/dd&gt;&lt;dt&gt;Symmetry&lt;/dt&gt;&lt;dd&gt;all nodes can do any function in the system &lt;/dd&gt;&lt;/dl&gt;  &lt;p&gt;Some other interesting bits were that the Amazon Homepage is produced by 200-300 services. Every service at Amazon is developed and operated by the same team. There are about 500-600 services/teams. Elasticity is both shrinking AND growing on demand.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6305261274278119099?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6305261274278119099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6305261274278119099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6305261274278119099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6305261274278119099'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/werner-vogels.html' title='Werner Vogels'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6298343166500452071</id><published>2009-04-01T21:04:00.001-04:00</published><updated>2009-04-01T21:04:17.600-04:00</updated><title type='text'>Geolocation: The new W3C API</title><content type='html'>&lt;p&gt;A thought leader in geolocation from the company that created Loki gave a talk about geolocation on the web.&amp;#160; His first recommendation was to build your applications to adopt latitude and longitude as the basic unit of location.&amp;#160; He then went on to talk about all the other ways location can be represented.&amp;#160; For example, the names of business, location descriptions, planar areas (rather than points) on a map, etc.&amp;#160; These are generally much more welcome in the UX than map coordinates.&lt;/p&gt;  &lt;p&gt;Some ways of getting local businesses are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Yahoo! Local Search API&lt;/li&gt;    &lt;li&gt;Yelp&lt;/li&gt;    &lt;li&gt;Localeze&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The skinny on geolocation for the web right now is that it relies on browser plug-ins or extensions.&amp;#160; The nice thing is that a W3C working group put together a standard for accessing the geolocation capabilities of the browser from Javascript.&amp;#160; It's quite easy to use, if not widely available.&lt;/p&gt;  &lt;p&gt;One interesting stat is the precision one can expect from the various means of geolocation.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;GPS can be accurate to within 10m for commercial applications&lt;/li&gt;    &lt;li&gt;Wifi (database lookup and triangulation from SSIDs and signal strength) can be as good as 20m up to 80m&lt;/li&gt;    &lt;li&gt;Cell towers are up around 1000m&lt;/li&gt;    &lt;li&gt;IP address based schemes are wildly inaccurate and limited to city/region precision&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Loki.com/how and Google Gears utilize hybrid approaches to do geolocation, obviously, to balance speed of acquisition, device capability, desire precision, etc.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6298343166500452071?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6298343166500452071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6298343166500452071' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6298343166500452071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6298343166500452071'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/geolocation-new-w3c-api.html' title='Geolocation: The new W3C API'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4441300661661801130</id><published>2009-04-01T20:49:00.001-04:00</published><updated>2009-04-01T20:49:39.259-04:00</updated><title type='text'>Web Developer Tools from Web 2.0</title><content type='html'>&lt;p&gt;This was by far the best presentation I saw today.&amp;#160; A couple of Mozilla guys gave this great talk really about the past, present, and future of the web developer experience.&amp;#160; I'm really buzzed about the near future of HTML 5, &amp;quot;fast javascript&amp;quot;, and the &amp;quot;web worker&amp;quot; model, enabling the kind of interactivity available on desktop applications.&lt;/p&gt;  &lt;p&gt;The introduced a lot of tools, mostly around Firebug and its extensions.&amp;#160; I wasn't familiar with the unit testing stuff in that space: Code Coverage and FireUnit.&amp;#160; Some of the more interesting tools were the CSS tools: &lt;a href="http://developer.yahoo.com/yui/grids/builder/" target="_blank"&gt;YUI CSS Grid Builder&lt;/a&gt;, &lt;a href="http://www.blueprintcss.org/" target="_blank"&gt;blueprint&lt;/a&gt;, and the recently announced &lt;a href="http://blogs.msdn.com/xweb/archive/2009/03/18/Microsoft-Expression-Web-SuperPreview-for-Windows-Internet-Explorer.aspx" target="_blank"&gt;Microsoft SuperPreview&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;They also mentioned some &amp;quot;future&amp;quot; tools like Bespin and Thunderhead.&amp;#160; Bespin is wonderful, a source code editor on the web, with concurrent-versioning system support (git now and later SVN?).&amp;#160; I really feel like this is boostrapping the web, you can begin to think of creating the web ON the web.&amp;#160; Avi Bryant has already plugged Seaside into Bespin.&amp;#160; Thunderhead is a prototype for marrying grid-layouts with the HTML 5 canvas.&amp;#160; They are talking about doing an &amp;quot;Open Tools Directory&amp;quot;.&lt;/p&gt;  &lt;p&gt;One thing they mentioned that was only tagentially related to their talk was &lt;a href="http://phonegap.com/" target="_blank"&gt;PhoneGap&lt;/a&gt;.&amp;#160; This let's HTML/Javascript developers create native mobile phone applications (iPhone, Android, and Blackberrry are supported to different extents at this time).&amp;#160; Atlas, which let's you write native Cocoa (Mac OS) applications in Javascript (their Objective J) was given an excited nod, too.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4441300661661801130?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4441300661661801130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4441300661661801130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4441300661661801130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4441300661661801130'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/web-developer-tools-from-web-20.html' title='Web Developer Tools from Web 2.0'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7863972162865414454</id><published>2009-04-01T20:32:00.001-04:00</published><updated>2009-04-01T20:32:49.788-04:00</updated><title type='text'>Why Scala?</title><content type='html'>&lt;p&gt;I'm trying to catch up with blogging about the sessions I've attended this first day of the Web 2.0 Expo.&amp;#160; The second session I attended today was entitled, &amp;quot;Why Scala?&amp;quot; Presented by a fellow from Twitter, it was essentially a discussion on their adoption of Scala from their initial appraisal of the technology landscape through the pilot project successes to their company-wide embrace of Scala.&lt;/p&gt;  &lt;p&gt;Despite not having any major investment in Java code, the JVM platform gave them access to the myriad Java libraries already out there, as well as the ability to do things like hydrate JSON as a JVM object and reason about it naturally within Scala.&amp;#160; Given that they were looking for a language with a great concurrency story, this appears to be the number one reason for choosing Scala, that it is a JVM language written by people who really understand the JVM internals.&amp;#160; Some of the other reasons put forth were:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Actor model--like Erlang the primary programming paradigm of Scala is independent workers that share no state and pass messages&lt;/li&gt;    &lt;li&gt;Immutability--with built-in immutable data structures and the Actor model, Scala heavily encourages immutability, but doesn't force it, meaning you can take advantage of mutability when it is more expressive or performant&lt;/li&gt;    &lt;li&gt;Type inference--yay, strong typing AND pretty code&lt;/li&gt;    &lt;li&gt;First-class functions&lt;/li&gt;    &lt;li&gt;Traits--not real clear on what this is, I think the Erlang/OTP equivalent would be behaviors&lt;/li&gt;    &lt;li&gt;Pattern matching--this is similar to what Erlang does, but isn't limited to tuples or other terms, i.e. you can match objects&lt;/li&gt;    &lt;li&gt;XML Literals &amp;amp; Query methods baked into the language&lt;/li&gt;    &lt;li&gt;Case Classes--these sound like structs, maybe message types?&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The &amp;quot;bad&amp;quot; thing about Scala is that it forces you to learn a bit more about the JVM than perhaps you were inclined to learn, and it is very complex.&amp;#160; There seems to be quite a community evolving around Scala, and the mainstreaam web framework is called Lift.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7863972162865414454?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7863972162865414454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7863972162865414454' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7863972162865414454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7863972162865414454'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/why-scala.html' title='Why Scala?'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6266396974476382550</id><published>2009-04-01T19:49:00.001-04:00</published><updated>2009-04-01T19:49:29.434-04:00</updated><title type='text'>Identity Wars and Joseph Smarr</title><content type='html'>&lt;p&gt;I remember Mr. Smarr's talk about OpenID and OAuth from a couple of years ago.&amp;#160; I got the impression that his biggest fear was that Facebook would always be a walled garden.&amp;#160; For reasons I don't quite understand, perhaps a sort of social consciousness (no pun intended), Facebook has opened their platform up, albeit in a limited and proprietary way.&lt;/p&gt;  &lt;p&gt;Fortunately, there are companies like Google and JanRain who are hiding the differences between the Open Stack and Facebook's APIs.&amp;#160; First, let's have a look at the Open Stack proper.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;OpenID for authentication &lt;/li&gt;    &lt;li&gt;OAuth for authorization &lt;/li&gt;    &lt;li&gt;XRD a service discovery protocol&lt;/li&gt;    &lt;li&gt;&lt;a href="http://portablecontacts.net/" target="_blank"&gt;Portable Contacts&lt;/a&gt; (self-explanatory)&lt;/li&gt;    &lt;li&gt;&lt;a href="http://code.google.com/apis/opensocial/" target="_blank"&gt;Open Social&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://www.janrain.com/products/rpx_faq" target="_blank"&gt;JanRain has RPX&lt;/a&gt;, and &lt;a href="http://www.google.com/friendconnect/" target="_blank"&gt;Google has FriendConnect&lt;/a&gt;, so using the OpenID/OAuth stuff is easy without really knowing a lot.&amp;#160; What is needed is a way to marry the existing authentication stacks of all the common web platforms (ASP.NET, PHP, etc.) with the Open Stack, I think.&lt;/p&gt;  &lt;p&gt;For more information, here are some blogs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;TheSocialWeb.tv &lt;/li&gt;    &lt;li&gt;JosephSmarr.com &lt;/li&gt;    &lt;li&gt;TheRealMcCrea.com &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6266396974476382550?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6266396974476382550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6266396974476382550' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6266396974476382550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6266396974476382550'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/identity-wars-and-joseph-smarr.html' title='Identity Wars and Joseph Smarr'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1909731660141018568</id><published>2009-04-01T12:22:00.001-04:00</published><updated>2009-04-01T12:22:46.489-04:00</updated><title type='text'>SEO: From Soup to Nuts--Web 2.0 Expo Workshop</title><content type='html'>&lt;p&gt;It's workshop day in the first and only pre-conference day of Web 2.0 Expo San Francisco.&amp;#160; Among the first sessions of the day, I opted to attend the presentation given by Stephan Spencer of Netconcepts: &amp;quot;SEO: From Soup to Nuts.&amp;quot; &lt;/p&gt;  &lt;p&gt;His presentation was organized around his &amp;quot;three pillars of SEO&amp;quot;: Content, Architecture, and Links.&amp;#160; His SEO practice is very data driven as evidenced by his egregious use of statistics.&amp;#160; Among the highlights of those statistics:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;1.25 to 1.5 times more conversions to PPC versus &amp;quot;natural&amp;quot; (normal search result click-through) &lt;/li&gt;    &lt;li&gt;86% of search engine clicks are natural &lt;/li&gt;    &lt;li&gt;47% click-through on first Google result falls to 10% on second, and half of the first natural for the first paid &lt;/li&gt;    &lt;li&gt;Double click through rate for short URLs according to Marketing Sherpa &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It definitely isn't all about statistics in the SEO game, though.&amp;#160; In fact, it seemed as if getting hard data about efficacy was the biggest and enduring challenge.&amp;#160; There are some hard-and-fast techniques to employ, thankfully.&amp;#160; Page titles, using 301s, nofollow links, canonical tags, there should be only one url for any given content, etc., as well as some great tools (both free and pay) including:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;SEOmoz.org's LinkScape &lt;/li&gt;    &lt;li&gt;SEObrowser.com &lt;/li&gt;    &lt;li&gt;Google Web Optimizer &lt;/li&gt;    &lt;li&gt;SIFR &lt;/li&gt;    &lt;li&gt;Adobe Search Engine SDK &lt;/li&gt;    &lt;li&gt;Yahoo! Site Explorer &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There were also a lot of surprises, at least to me:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Search result rankings can vary from city to city (of searcher) &lt;/li&gt;    &lt;li&gt;Underscores do not count as word separators to Google &lt;/li&gt;    &lt;li&gt;YouTube doesn't give link juice (nofollow) &lt;/li&gt;    &lt;li&gt;Digg users do not buy anything &lt;/li&gt;    &lt;li&gt;User generated content can get you so-called &amp;quot;long tail terms&amp;quot; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_FQ1igFTZD04/SdOU0_CxtgI/AAAAAAAAAEU/z9k3CevNsZE/s1600-h/eyetrackingseo4.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="eyetrackingseo" src="http://lh5.ggpht.com/_FQ1igFTZD04/SdOU1fOYq7I/AAAAAAAAAEY/qmgppn6kLDk/eyetrackingseo_thumb2.jpg?imgmax=800" width="169" align="left" border="0" /&gt;&lt;/a&gt;One thing I wondered, looking at this image that shows the distribution of eye movement on the Google results page, is what are people actually looking for one Google.&amp;#160; They aren't looking for knowledge, but information, a gateway to knowledge, perhaps.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1909731660141018568?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1909731660141018568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1909731660141018568' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1909731660141018568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1909731660141018568'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/04/seo-from-soup-to-nuts-web-20-expo.html' title='SEO: From Soup to Nuts--Web 2.0 Expo Workshop'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_FQ1igFTZD04/SdOU1fOYq7I/AAAAAAAAAEY/qmgppn6kLDk/s72-c/eyetrackingseo_thumb2.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7359336337206279143</id><published>2009-03-29T12:48:00.001-04:00</published><updated>2009-03-29T12:48:40.923-04:00</updated><title type='text'>Web 2.0 Expo travel</title><content type='html'>We have just been incredibly fortunate this far. I last flew commercial soon after 9/11, and the experience was harsh to say the least. Anotinio Gramsci once wrote that the downfall of a secular democracy was the continuous surrendering of freedoms in exchange for protection from our fellow citizens. Our travel experience to SF this weekend has taught me how much the human spirit can shine despite and perhaps paradoxically because of difficult circumstance. We have been graced by the goodwill of so many of our fellow citizens that I am tacitly aware of Gramsci's error if unable to put words to it.&lt;br /&gt;&lt;br /&gt;Today has been incredible, but I must save my emotive prose for another time. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a href='http://blogpress.w18.net/photos/09/03/29/165.jpg'&gt;&lt;img src='http://blogpress.w18.net/photos/09/03/29/s_165.jpg' border='0' width='280' height='281' style='margin:5px'&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7359336337206279143?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7359336337206279143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7359336337206279143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7359336337206279143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7359336337206279143'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/03/web-20-expo-travel.html' title='Web 2.0 Expo travel'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4078913350720578645</id><published>2009-03-18T22:35:00.001-04:00</published><updated>2009-03-18T22:35:23.926-04:00</updated><title type='text'>Sex-Software Simile</title><content type='html'>&lt;p&gt;Using software vendors' technology demos as the metric for your software development is like measuring your sexual prowess by watching porn films: accurate for edge cases but ultimately not relevant.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4078913350720578645?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4078913350720578645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4078913350720578645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4078913350720578645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4078913350720578645'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/03/sex-software-simile.html' title='Sex-Software Simile'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-339166809452097069</id><published>2009-03-13T13:51:00.001-04:00</published><updated>2009-03-13T14:09:38.325-04:00</updated><title type='text'>Why ORM? Why Cloud Computing?</title><content type='html'>&lt;p&gt;I think it was Fred Brooks that once wrote that someone will inevitably look at any software system and ask, &amp;quot;how did we get here?&amp;quot; And, the answer is invariably, &amp;quot;one logical choice at a time.&amp;quot;&amp;#160; Rather than answer the questions, &amp;quot;Why ORM?&amp;quot; and &amp;quot;Why Cloud Computing?&amp;quot;, I will endeavor to elucidate those logical choices.&lt;/p&gt;  &lt;p&gt;The monolithic database model (MDM) has served the IT sector very well for about fifty years.&amp;#160; I will explicitly define it as a model of software development where myriad applications are integrated through a shared database, or--more accurately--more than one user interface is provided to a database.&amp;#160; In this model the database itself is where business processes and domain modeling exist.&amp;#160; Enterprises often expanded these databases to include all aspects of the business, or perhaps a few databases integrated via ETL, until the number of objects exceeded any one person's capacity to understand the system.&amp;#160; EDI, data warehousing, and data marts are all extensions of the (MDM) for dealing with M&amp;amp;A, e-biz partners, etc.&amp;#160; Given a large number of well-trained database professionals with rigorous communication and documentation requirements, the monolithic database model is efficacious and expedient. &lt;/p&gt;  &lt;p&gt;As object-oriented programming techniques became more well-known, developers began modeling the domain and business process using advanced general purpose programming languages like Lisp, Smalltalk, C++, etc.&amp;#160; They used object databases to persist these models and all was good and productive.&amp;#160; Unfortunately, few developers grok those technologies, and even fewer have a mastery of the techniques needed to use them well, so it didn't catch on.&amp;#160; Perhaps the biggest impediment to adoption was the success of the MDM. The MDM was working and understood.&amp;#160; The deficiencies of the model were insufficient to move IT development en masse to the object crowd. &lt;/p&gt;  &lt;p&gt;Still, a lot of software was being written outside of IT.&amp;#160; Embedded developers loved object programming and had no need to store loads of data.&amp;#160; So, the hardcore programmers--those that relish writing life support systems, flight control systems, nuclear power plant control systems, etc.--were exclusively &amp;quot;object guys&amp;quot;.&amp;#160; Meanwhile, Sun Microsystems was building a runtime for embedded systems to simplify programming across hardware--Java.&amp;#160; A 4GL, Java had all the object-oriented bells and whistles, and Sun had written runtimes for Unix, Solaris, and even Windows!&amp;#160; These runtimes came bundled with AWT, allowing developers to nominally &amp;quot;write once, run anywhere.&amp;quot;&lt;/p&gt;  &lt;p&gt;Suddenly there was the WWW.&amp;#160; I say suddenly because even Bill Gates once purportedly remarked that it was irrelevant.&amp;#160; As IT understood the implications of Metcalfe's Law for the Internet, it became the elephant in every boardroom.&amp;#160; No single company in the world wanted to be a loser in the new, connected economy.&amp;#160; All IT decisions were tempered by the Internet revolution.&lt;/p&gt;  &lt;p&gt;Now the cohesive, insular world of the MDM was really looking problematic.&amp;#160; Still, that's where the data was, and ultimately the Internet was about access to information.&amp;#160; So, every IT vendor that wanted to compete was pitching platforms that claimed to do one central task better than anyone else: turn relational data into web pages.&amp;#160; These platforms were either backed by scripting or 4GL, and DBI, JDBC, ODBC, ADO, etc., in all their versions and iterations were simply libraries used by the object guys to get at the data.&lt;/p&gt;  &lt;p&gt;Concurrently, universities had been turning out software developers who started writing C++ or Java in their freshman year, graduating to &amp;quot;real&amp;quot; object languages in subsequent years.&amp;#160; The worldwide demand for IT developers skyrocketed, and technical colleges met the challenge with programs designed to get people into the market with the minimal set of skills to create web applications.&amp;#160; At this point the technologies for building web applications were infantile relative to RDBMS technologies.&amp;#160; The result was a lot of really bad developers developing really bad applications, slowly.&lt;/p&gt;  &lt;p&gt;The good developers, the object guys with strong Lisp kung fu, really resented having to interface with databases--to go from their object model to a data model.&amp;#160; IT programmers oft complained of the inordinate amount of time they spent move data in and out of databases.&amp;#160; Architects started designing systems built around messaging again, calling them web services this time, and the canon said that these messages were serialization of object state.&amp;#160; So smart people started writing libraries for interfacing with databases in a tacit fashion, attempting to abstract away the &amp;quot;implementation details&amp;quot; of data storage and retrieval: object-relational mappers (ORM).&amp;#160; The &amp;quot;real&amp;quot; model of business entities and processes, after all, were their objects.&lt;/p&gt;  &lt;p&gt;Now, the old IT systems in DB2 and Cobol were &amp;quot;legacy&amp;quot; systems to be tolerated until they could eventually be re-written.&amp;#160; New IT initiatives would set out in their own silo (usually an application server), with their own persistence engines that utilized ORM, and integrate with the legacy systems via message-oriented middleware (MOM): Biztalk, SOA, ESB, etc.&amp;#160; Vendors were happy because MOM was expensive; object-guys were happy because their jobs now matched up with their education; and business owners were hopefully optimistic because mainframe vendors all operate on an annuity model, and the owners' hope was to escape from a world of multi-million dollar support contracts.&lt;/p&gt;  &lt;p&gt;Lo, the MDM guys sneered, since the whole enterprise--the business itself--was still built upon their systems, and every attempt to re-write their systems was an incredibly expensive failure.&lt;/p&gt;  &lt;p&gt;Business owners were getting pretty angry, too.&amp;#160; All these application servers needed lots of new hardware, and the new servers needed to be partitioned by firewalls, and they needed new database servers too, since RDBMS was still the persistence engine of choice, and of course all of this needed fail-over and clustering.&amp;#160; Meanwhile, what the developers were producing wasn't sufficient to run the entire business on, so they now had to maintain two systems in parallel, putting increased strain on the middleware servers.&amp;#160; Further, the developer's velocity was slow, since everything had to be integrated, and years and years of process refinements implicit in the MDM had to be re-imagined and re-discovered.&amp;#160; This integration stuff was expensive.&lt;/p&gt;  &lt;p&gt;Again, though, not all software was being written in IT shops.&amp;#160; There were companies building applications hosted on web servers that were available on-demand, so called Application Service Providers (ASP).&amp;#160; These companies didn't have any legacy systems and drew the smartest object guys.&amp;#160; Many of them were wildly successful, but when the dot-com bubble burst, the idea that a company that you relied upon for mission critical systems could just disappear caused many IT shops to reject the idea out-of-hand.&amp;#160; The ASPs that survived were those companies that offered important but not &amp;quot;mission-critical&amp;quot; (like email, production data management, etc.) services, such as sales force automation or marketing support.&amp;#160; Another class of ASPs that won were those that offered hosted services to SME customers who could not or chose not to afford the sunk costs of providing their own infrastructure.&lt;/p&gt;  &lt;p&gt;In the U.S., capital was king; the financial markets were providing great returns and due to foreign investment and interest rate cuts the cost of capital was low.&amp;#160; Businesses were now faced with enormous capital expenditures from their IT operations during a time when capital investments were the most prudent choice, but no one was willing to give up the very real productivity gains that had been made steadily in the last decade.&amp;#160; The solution to the dilemma was to defer expenditures, to lease.&lt;/p&gt;  &lt;p&gt;At the same time, the business owner's frustration with the lack of agility of their IT operations peaked.&amp;#160; The costs were high, the pace of development was slow, the requirements gathering and definition process was pain-staking, and the failure rate was abominable.&amp;#160; The maintenance costs alone for all the manifold servers, languages, and platforms was choking the life out of new business opportunities before they could be explored.&lt;/p&gt;  &lt;p&gt;So, the market itself demanded cloud-computing.&amp;#160; Rather than buying the infrastructure and paying to provision it, they wanted to &amp;quot;pay as you go.&amp;quot;&amp;#160; Elastic demand on IT systems meant provisioning for the worst-possible scenario; cloud-computing meant scaling-up (and down) on demand.&amp;#160; Rather than having to pay for and maintain application servers, database servers, load-balancers, etc., they could just write the app and see if it sticks.&lt;/p&gt;  &lt;p&gt;Yea, though I walk through the valley of the shadow of integration, I shall fear no SQL.&lt;/p&gt;  &lt;p&gt;The problem of integration remains.&amp;#160; No cloud platform fits any enterprise's IT needs completely, so now the challenge is how to integrate a world where the web application server platform is considered a legacy.&amp;#160; Microsoft's solution is to position all ASP.NET development as &amp;quot;cloud&amp;quot; development, making it easy to keep the application on-premise or move it to the cloud (Azure).&amp;#160; Ironically, the major impediment to this approach is the persistence engine: the database.&amp;#160; &lt;/p&gt;  &lt;p&gt;Moving a database that fully exploits the RDBMS platform to the cloud is non-trivial.&amp;#160; In other words, developers that wrote stored procedures, utilized event brokers or extended stored procedures, created ETL jobs, made it unlikely that they can move their applications to Azure.&amp;#160; If they instead had only used pure ORM (LINQ2SQL), this could be done mechanically.&lt;/p&gt;  &lt;p&gt;This property of not violating the ORM abstraction, namely the ease with which the backing data store can be mechanically replaced, is the key reason why ORM advocates promulgate the principle that the application should never accept a dependency on the data store.&amp;#160; In other words, no stored procedures allowed.&amp;#160; The Entity Data Model is an attempt to abstract the universality of the data model--arguably the best feature of MDM--away from the persistent storage engine(s), in order to ensure the portability of the data model in the enterprise and beyond, i.e. to the cloud.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-339166809452097069?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/339166809452097069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=339166809452097069' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/339166809452097069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/339166809452097069'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/03/why-orm-why-cloud-computing.html' title='Why ORM? Why Cloud Computing?'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4176837127183443509</id><published>2009-03-04T06:24:00.001-05:00</published><updated>2009-03-04T06:24:20.895-05:00</updated><title type='text'>How We Will Develop for the Web in Five Years</title><content type='html'>&lt;p&gt;Okay, I admit that I'm predisposed to prognostication, but I'm less inclined to blog if I'm not confident.&amp;#160; So comeback in five years so I can say, &amp;quot;Told ya so!&amp;quot;&lt;/p&gt;  &lt;p&gt;In five years, nearly everyone who writes code for the web will be using a web-based IDE to create those applications.&amp;#160; All of the libraries that you use to create your UI will be hosted on a CDN, freely available to all, and your IDE will be aware of the CDN.&amp;#160; You'll add new widgets to your toolbox by specifying CDN URLs.&lt;/p&gt;  &lt;p&gt;The MVCC for your web project will be hosted by your cloud infrastructure provider.&amp;#160; Unit tests and code coverage requirements will be imposed on check-in, and continuous integration will be &lt;em&gt;de rigueur&lt;/em&gt;.&amp;#160; The other distributed developers on your team will receive a notification of failed builds in the web-based IDE, and workgroup chat capabilities in the IDE will be used to coordinate a fix.&lt;/p&gt;  &lt;p&gt;On the server-side, the distinction between persistent storage and in-flight objects will have all but disappeared.&amp;#160; No longer will there be a separate notion of a data store and middle-tier objects.&amp;#160; Ad-hoc object composition will be supported via interfaces in the object runtime, as opposed to a query language.&amp;#160; Backups and disaster recovery will be outmoded ideas, as the cloud infrastructure provider will ensure redundancy and edge computing performance in myriad datacenters.&amp;#160; Data replication between these points-of-presence will be completely automatic and unnoticeable.&lt;/p&gt;  &lt;p&gt;The standard application architecture will be server-coordinated real-time continuations.&amp;#160; The majority of applications will have just a handful of screens in the UI, with one screen generally accounting for 80% of interactions.&amp;#160; These screens will be HTML pages generated primarily using JavaScript UI toolkits.&amp;#160; That is, the server will not generate individual pages, but will deliver client-side applications.&amp;#160; These applications/screens will interact with the server via RESTful AJAX calls returning JSON that will move forward a state-machine facilitated by continuations on the server.&amp;#160; Browser extensions like AIR/Flex, Gears, and Silverlight will be used primarily for their ability to allow offline application interactions, not for flashy graphics or rich-media, but this usage will eventually be deprecated by browser implementations of offline storage in HTML 5.&lt;/p&gt;  &lt;p&gt;State machines and workflows will be specified using a constraint language layered on top of the fluent interface/DSL available &lt;em&gt;ipso facto&lt;/em&gt; on a platform that requires an object model to get any work done.&amp;#160; So, business rules will be clearer and organized, allowing more transparency in the development process.&lt;/p&gt;  &lt;p&gt;This state of affairs will require domain-driven design &lt;em&gt;a priori&lt;/em&gt;.&amp;#160; While user interfaces and the mechanics of interactions could be built ahead of other development, all meaningful interactions will require the construction of workflows out of domain models.&lt;/p&gt;  &lt;p&gt;Much of these ideas already exist.&amp;#160; Seaside is a great example of browser-based development and server-side continuations.&amp;#160; Salesforce.com's Force.com platform imposes code coverage restrictions for production code. LINQ provides an object-runtime method of programming without an explicit query language.&amp;#160; Google hosts jQuery and other tools on its CDN.&amp;#160; ASP.NET 4.0 stands poised to take client-side templating to the masses. AWS, Azure, AppEngine, and RailYard are providing the infrastructure we need.&amp;#160; The pieces exist, what I wanted to do was articulate a vision for the future where these technologies are mainstream, integrated, and proven.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4176837127183443509?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4176837127183443509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4176837127183443509' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4176837127183443509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4176837127183443509'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/03/how-we-will-develop-for-web-in-five.html' title='How We Will Develop for the Web in Five Years'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1445507765407301764</id><published>2009-02-16T13:32:00.001-05:00</published><updated>2009-02-19T10:24:47.700-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='localization'/><title type='text'>Public Global Resources</title><content type='html'>&lt;p&gt;In VS 2008, the addition of a resources (.resx) file to the App_GlobalResources file defaults the custom tool to GlobalResourceProxyGenerator.&amp;#160; This tool generate a class (&lt;em&gt;resource_file&lt;/em&gt;.designer.cs) that is internal (friend in VB), therefore classes outside of the web project assembly cannot access these resources.&amp;#160; The solution is to simply change the custom tool from GlobalResourceProxyGenerator to PublicResXFileCodeGenerator in the properties of the resx files.&amp;#160; This tool will create a publicly accessible in the designer file; however, it will also default the namespace to &lt;em&gt;WebProjectName.App_GlobalResources&lt;/em&gt;. If you put &amp;quot;Resources&amp;quot; into the Custom Tool Namespace property of the resx file, you will be able to recompile without any problems, and your resources will be accessible outside of the web project's assembly.&lt;/p&gt;  &lt;p&gt;One last note, it is my experience that you must also set the Build Action to &amp;quot;Embedded Resource&amp;quot; or you will receive an &lt;b&gt;MissingManifestResourceException&lt;/b&gt; in your consuming web project at runtime.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1445507765407301764?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1445507765407301764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1445507765407301764' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1445507765407301764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1445507765407301764'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/02/public-global-resources.html' title='Public Global Resources'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-9136798311825011637</id><published>2009-01-30T15:11:00.001-05:00</published><updated>2009-01-30T15:11:55.286-05:00</updated><title type='text'>Guilt</title><content type='html'>&lt;p&gt;Guilt is the feeling of being separate from our own model of true self; but we should build upon guilt, for it is only possible when we both aspire and look honestly upon our actions.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-9136798311825011637?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/9136798311825011637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=9136798311825011637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9136798311825011637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9136798311825011637'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2009/01/guilt.html' title='Guilt'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8483832718570629843</id><published>2008-12-17T18:19:00.001-05:00</published><updated>2008-12-17T18:19:56.578-05:00</updated><title type='text'>A Corollary to Ockham's Razor</title><content type='html'>&lt;p&gt;The popular phrasing of the maxim known as &lt;a href="http://en.wikipedia.org/wiki/Occam's_Razor" target="_blank"&gt;Ockham's Razor&lt;/a&gt; is, &amp;quot;the simplest solution is usually the right one.&amp;quot;&amp;#160; This is not the original statement or William of Ockham.&amp;#160; He might better be paraphrased: &amp;quot;a solution with fewer assumptions is to be preferred.&amp;quot;&amp;#160; That restatement, though still not precisely correct, captures the spirit but leaves out the concept of simplicity.&amp;#160; Karl Popper, the imminent epistemologist, would have us define simplicity as the &amp;quot;&lt;em&gt;degree of falsifiability [sic]&lt;/em&gt;&amp;quot; of our solution; i.e., how easy is it to prove the solution incorrect?&amp;#160; Popper goes further:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Simple statements, if knowledge is our object, are to be prized more highly than less simple ones &lt;em&gt;because they tell us more; because their empirical content is greater; and because they are better testable&lt;/em&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;He could have well been talking about programming! If would follow that declarative programming, currying, constraint programming, and domain-specific languages are to be preferred over alternate paradigms, but so too would an entry to the &lt;a href="http://www.ioccc.org/" target="_blank"&gt;obfuscated C contest&lt;/a&gt; and your average unreadable Perl program.&amp;#160; To rectify this seeming contradiction, we need to understand that a &amp;quot;simple statement&amp;quot;, according to Popper, is one with &lt;strong&gt;fewer parameters&lt;/strong&gt;--precisely because it is more testable.&lt;/p&gt;  &lt;p&gt;So more testable code is better code, and we might induce that a test driven approach is to be preferred, insofar as the practice encourages the writing of simpler, more testable statements.&amp;#160; But, Ockham's razor is about solutions, not approaches.&amp;#160; So, what can we say about deciding between solutions?&lt;/p&gt;  &lt;p&gt;I offer the Programmer's Corollary to Ockham's Razor:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;To pick the best solution architecture, choose the one that consistently requires fewest number of parameters.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8483832718570629843?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8483832718570629843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8483832718570629843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8483832718570629843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8483832718570629843'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/12/corollary-to-ockham-razor.html' title='A Corollary to Ockham&amp;#39;s Razor'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7143975031070009255</id><published>2008-12-16T18:16:00.001-05:00</published><updated>2008-12-16T18:16:38.769-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>HOWTO: SQL Server Return Value with Enterprise Library</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;int &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;returncode &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= 0;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Database &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;db &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;DatabaseFactory&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;CreateDatabase&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;();&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;DbCommand &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;dbCommand &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;db&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetStoredProcCommand&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #60ff60"&gt;&amp;quot;&amp;lt;your procedure&amp;gt;&amp;quot;&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;db&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;AddParameter&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;dbCommand&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #60ff60"&gt;&amp;quot;@RETURN_VALUE&amp;quot;&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #2b91af"&gt;DbType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Int32&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #2b91af"&gt;ParameterDirection&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;ReturnValue&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;String&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Empty&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #2b91af"&gt;DataRowVersion&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Default&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;null&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;db&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;ExecuteNonQuery&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;dbCommand&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;if &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(!&lt;/span&gt;&lt;span style="background: #181818; color: #2b91af"&gt;Int32&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;TryParse&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Convert&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;ToString&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;dbCommand&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Parameters&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;[&lt;/span&gt;&lt;span style="background: #181818; color: #60ff60"&gt;&amp;quot;@RETURN_VALUE&amp;quot;&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;].&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Value&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;), &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;out &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;returncode&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;))&lt;br /&gt;        &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;returncode &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= -1;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;The returncode local variable is useful, but generally not necessary. It's good to state your assumptions about the operation of external code explicitly.  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7143975031070009255?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7143975031070009255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7143975031070009255' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7143975031070009255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7143975031070009255'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/12/howto-sql-server-return-value-with.html' title='HOWTO: SQL Server Return Value with Enterprise Library'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2107519501377837125</id><published>2008-11-12T13:59:00.001-05:00</published><updated>2008-11-12T13:59:42.226-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Everything Crashes, But Programmers Are Still Jocular</title><content type='html'>&lt;p&gt;This is completely off-topic, but I couldn't resist sharing this with anyone and everyone.&amp;#160; Whilst researching the frequent crashes on my iPhone, I ran across &lt;a href="http://www.iphoneatlas.com/2007/07/20/special-report-troubleshooting-iphone-application-crashes/" target="_blank"&gt;this post&lt;/a&gt;, and the first comment made me chuckle.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Posted by Kee Hinckley     &lt;br /&gt;24 July 2007 @ 4am&lt;/p&gt;    &lt;p&gt;It appears that if the OS was unable to get a traceback for the crash (which seems to be the case in a lot of my crashes), the exception code given is: 0&amp;#215;&lt;strong&gt;8badf00d&lt;/strong&gt;.&lt;/p&gt;    &lt;p&gt;Could be worse. I remember one company getting a confused call from a customer about a 0x&lt;strong&gt;deadbeef&lt;/strong&gt; crash.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2107519501377837125?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2107519501377837125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2107519501377837125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2107519501377837125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2107519501377837125'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/11/everything-crashes-but-programmers-are.html' title='Everything Crashes, But Programmers Are Still Jocular'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4741944267901436617</id><published>2008-11-04T12:36:00.001-05:00</published><updated>2009-08-18T12:45:13.588-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='localization'/><title type='text'>Dealing with Globalization Differences in Windows Versions</title><content type='html'>&lt;p&gt;Recently I was charged with leading an effort to localize an ASP.NET application to a few different locales, including The Netherlands and India.&amp;#160; I was reminded again how difficult it is to get this right.&amp;#160; There are those who argue that using the same view across all the cultures supported in your application is a bad idea.&amp;#160; For example, an RTL culture, e.g. Hebrew, when done right, requires a mirroring of the entire view layout: not an easy thing to accomplish without changing the view.&lt;/p&gt;  &lt;p&gt;Regardless, the .NET Framework and ASP.NET provide many facilities for localizing your application around a single view: App_LocalResources, App_GlobalResources, &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx" target="_blank"&gt;CultureInfo&lt;/a&gt;, etc.&amp;#160; ASP.NET has a particularly helpful feature; you can set the CultureInfo used by the application in the web.config using the &lt;a href="http://msdn.microsoft.com/en-us/library/hy4kkhe0.aspx" target="_blank"&gt;globalization element&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There are lots of different ways of representing a culture in Windows: culture name, culture identifier, locale identifier (LCID), and others.&amp;#160; Generally, though, the culture name is used, e.g. en-US, en-GB, and es-MX for English (US), English (Great Britain), and Spanish (Mexico), respectively.&amp;#160; As the world's second most populous country with many ancient and highly varied cultures, India have no less than nine culture names defined in the .NET Framework.&amp;#160; This is, however, a narrow view of India's diversity with its 28 states, 7 union territories, and literally hundreds of spoken languages.&amp;#160; Obviously, there isn't 100% coverage of this diversity in the cultures supported in .NET.&lt;/p&gt;  &lt;p&gt;One particularly useful culture name in use in Windows is en-IN.&amp;#160; In India, the de facto language of the law and by extension government and business is English, due to both the historical influence of British colonization and the need for a lingua franca in such an amazingly diverse country.&amp;#160; The en-IN culture code codifies this, making it possible for an application developer to effectively gloss over this diversity in the Indian market.&amp;#160; Unfortunately, en-IN is not available in the core .NET Framework release.&amp;#160; As you can see from &lt;a href="http://www.microsoft.com/globaldev/nlsweb/default.mspx?OS=Windows%20Vista" target="_blank"&gt;this list&lt;/a&gt;, Windows Vista supports this culture, as does Windows 2008.&lt;/p&gt;  &lt;p&gt;Obviously, this is problematic for developers doing development on Vista but deploying to Windows 2003 R2.&amp;#160; Fortunately, Microsoft developers faced with the incredible diversity of the world's cultures provided a way to customize the available cultures on any Windows installation: the &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureandregioninfobuilder.aspx" target="_blank"&gt;CultureAndRegionInfoBuilder&lt;/a&gt; (CARIB) class.&amp;#160; There is a standard how-to create custom cultures with this class, but we will take a slightly different approach in this entry.&amp;#160; We will export the en-IN culture from our Windows Vista development machine, and import it on our Windows 2003 R2 server.&lt;/p&gt;  &lt;p&gt;We'll use PowerShell here, but the examples should be clear enough that you can write your own console or Windows application to execute these steps.&amp;#160; Let's begin with exporting the en-IN culture.&amp;#160; The CARIB class is in sysglobl.dll, so we need a &amp;quot;reference&amp;quot; to that assembly. We can load the assembly from the GAC in PowerShell.&amp;#160; To do so we use its strong name, obtained by using &amp;quot;gacutil /l sysglobl&amp;quot; from a Visual Studio command prompt. In PowerShell on the Vista machine,&lt;/p&gt;  &lt;p&gt;PS&amp;gt; [System.Reflection.Assembly]::Load(&amp;quot;sysglobl, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL&amp;quot;)&lt;/p&gt;  &lt;p&gt;Now that we can reference the class, let's export the culture into an industry standard format called &lt;a href="http://www.unicode.org/cldr/" target="_blank"&gt;Locale Data Markup Language (LDML) version 1.1&lt;/a&gt; using &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureandregioninfobuilder.save.aspx" target="_blank"&gt;the Save method&lt;/a&gt;.&amp;#160; We can import this later with the &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureandregioninfobuilder.createfromldml.aspx" target="_blank"&gt;CreateFromLdml&lt;/a&gt; method.&lt;/p&gt;  &lt;p&gt;PS&amp;gt; $enIN = New-Object System.Globalization.CultureAndRegionInfoBuilder(&amp;quot;en-IN&amp;quot;, &amp;quot;Replacement&amp;quot;)    &lt;br /&gt;PS&amp;gt; $enIN.LoadDataFromCultureInfo((New-Object System.Globalization.CultureInfo(&amp;quot;en-IN&amp;quot;)))     &lt;br /&gt;PS&amp;gt; $enIN.LoadDataFromRegionInfo((New-Object System.Globalization.RegionInfo(&amp;quot;IN&amp;quot;)))     &lt;br /&gt;PS&amp;gt; $enIN.Save(&amp;quot;enIN.ldml&amp;quot;)&lt;/p&gt;  &lt;p&gt;Now we can copy enIN.ldml to our server and import it.&amp;#160; There are three very important modification we must make to enIN.ldml, however.&amp;#160; The en-IN culture is defined in terms of some other Windows locale information that won't be found on Windows 2003 R2, specifically &amp;quot;text info&amp;quot;, &amp;quot;sort&amp;quot;, and &amp;quot;fallback&amp;quot;.&amp;#160; If you open enIN.ldml, you'll find the following three elements.&lt;/p&gt;  &lt;p&gt;&amp;lt;msLocale:textInfoName type=&amp;quot;en-IN&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;msLocale:sortName type=&amp;quot;en-IN&amp;quot; /&amp;gt;     &lt;br /&gt;...     &lt;br /&gt;&amp;lt;msLocale:consoleFallbackName type=&amp;quot;en-IN&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;If we try to load a CARIB from this file as-is, we'll receive the following error.&amp;#160; For more information, see the section &lt;a href="http://www.codeproject.com/KB/books/CustomCultures.aspx" target="_blank"&gt;&amp;quot;Exporting Operating System-Specific Cultures&amp;quot; in this CodeProject on-line book&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Culture name 'en-in' is not supported.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;We've got to change these to a sensible alternative that is supported on Windows 2003 R2.&amp;#160; I chose &amp;quot;en-US&amp;quot;, though &amp;quot;en-GB&amp;quot; would've also been appropriate.&amp;#160; For other cultures, this may prove more difficult.&amp;#160; My changed LDML file contains these lines.&lt;/p&gt;  &lt;p&gt;&amp;lt;msLocale:textInfoName type=&amp;quot;en-US&amp;quot; /&amp;gt;    &lt;br /&gt;&amp;lt;msLocale:sortName type=&amp;quot;en-US&amp;quot; /&amp;gt;     &lt;br /&gt;...     &lt;br /&gt;&amp;lt;msLocale:consoleFallbackName type=&amp;quot;en-US&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;With that done, we can load and register the culture on the Windows 2003 server.&lt;/p&gt;  &lt;p&gt;PS&amp;gt; [System.Reflection.Assembly]::Load(&amp;quot;sysglobl, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL&amp;quot;)    &lt;br /&gt;PS&amp;gt; $enIN = [System.Globalization.CultureAndRegionInfoBuilder]::CreateFromLdml(&amp;quot;enIN.ldml&amp;quot;)     &lt;br /&gt;PS&amp;gt; $enIN.Register()&lt;/p&gt;  &lt;p&gt;The culture en-IN is now available to all applications running on your server.&amp;#160; To see this in action, you could now augment the web.config of you web application with a globalization element:&lt;/p&gt;  &lt;p&gt;...    &lt;br /&gt;&amp;lt;system.web&amp;gt;     &lt;br /&gt;&amp;#160; &amp;lt;globalization culture=&amp;quot;en-IN&amp;quot; uiCulture=&amp;quot;en-IN&amp;quot; /&amp;gt;     &lt;br /&gt;...&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Create a file called i18n.aspx and add the following code:&lt;/p&gt;  &lt;p&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot;%&amp;gt;    &lt;br /&gt;&amp;lt;% = (10.5).ToString(&amp;quot;c&amp;quot;) %&amp;gt;&lt;/p&gt;  &lt;p&gt;Navigate to i18n.aspx and you should see the following:&lt;/p&gt;  &lt;p&gt;Rs. 10.50&lt;/p&gt;  &lt;p&gt;I hope this helps!    &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4741944267901436617?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4741944267901436617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4741944267901436617' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4741944267901436617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4741944267901436617'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/11/dealing-with-globalization-differences.html' title='Dealing with Globalization Differences in Windows Versions'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4921295644510317720</id><published>2008-10-19T19:00:00.001-04:00</published><updated>2008-11-06T21:56:07.563-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>Using ASP.NET to Write Files to a Remote UNC Share</title><content type='html'>&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Let's say you have an ASP.NET site on a public web server.&amp;#160; The server itself is in an un-trusted domain, e.g. a workgroup server, and the site needs to write files to a UNC share that &lt;strong&gt;is&lt;/strong&gt; in the domain.&amp;#160; There are many reasons you may need to do this, but the difficulty is that you cannot specify NetworkCredentials for the DirectoryInfo class.&amp;#160; You cannot, therefore, authenticate against the UNC share programmatically, and since your application is running in an un-trusted domain, the ASP.NET process identity is of no help.&amp;#160; If possible, the easiest thing to do is write the file locally and have the system that needs the file pull from there via a UNC.&amp;#160; Of course, if you're attempting to share the file across web applications, you'd likely be in the same scenario.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; The solution I have developed for a slightly more complex scenario utilizes a few relatively little known facilities:.&amp;#160; Basically, we'll use an ASP.NET FileUpload to receive a file, write it to a temporary location, perform any needed processing, and then use the WebClient class to perform an HTTP PUT to a local virtual directory that points to an UNC share.&amp;#160; Let's start with the page that receives the file.&lt;/p&gt;  &lt;p&gt;Using the FileUpload control couldn't be easier.&amp;#160; Add it to your page and call its SaveAs(string) method to save the file locally.&amp;#160; Of course, that doesn't help us get that file to a remote UNC share, does it?&amp;#160; What we'll do is save that file to a temporary location on the web server, do any necessary processing, and then upload that file.&amp;#160; Here's the code to do that.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;WebClient &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;wc &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;new &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;WebClient&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;string &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;tempFileName &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;= &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Path&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetTempFileName&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;();&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;fileUpload1&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;SaveAs&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;tempFileName&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;    &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;wc&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;UploadFile&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;uploadUrl&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #60ff60"&gt;&amp;quot;PUT&amp;quot;&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;tempFileName&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Let's talk about that uploadUrl variable.&amp;#160; You are probably already familiar with GET and POST, but you may not have had occasion to use PUT and DELETE.&amp;#160; When specifying PUT in an HTTP request, the request URL is the location where the request's file payload should be stored by the web server.&amp;#160; IIS 6 supports HTTP PUT requests via its WebDAV module, but the functionality is disabled by default.&amp;#160; Turn it on the same way you turn on ASP.NET, by clicking Allow after selecting WebDAV in the Web Extensions in IIS manager.&amp;#160; Once it's turned on, the IIS server hosting your application will now accept HTTP PUT requests.&amp;#160; If you do not turn on WebDAV, PUT requests will result in 405 Not Implemented being returned by IIS.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Having enabled PUT, you now need a place to put the files.&amp;#160; Let's create a virtual directory in our site that points at the UNC path that is our final destination.&amp;#160; There are three key points here.&amp;#160; First, we need to ensure that the new virtual directory has Write access.&amp;#160; Second, we need to tell IIS to &lt;strong&gt;connect as&lt;/strong&gt; an account with the same username and password as an account on the machine where the UNC share exists.&amp;#160; Finally, we have to allow Anonymous access to the virtual directory.&amp;#160; If the UploadFile call returns a 401 Unauthorized, one of these three things is wrong.&amp;#160; The account that authenticates to the UNC share should have the necessary permissions to to the share of course, including write access.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There you have it a few lines of code and a virtual directory.&amp;#160; You're not likely to find a simpler solution to this problem.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4921295644510317720?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4921295644510317720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4921295644510317720' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4921295644510317720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4921295644510317720'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/10/using-aspnet-to-write-files-to-remote.html' title='Using ASP.NET to Write Files to a Remote UNC Share'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1153666058166508127</id><published>2008-07-17T11:25:00.001-04:00</published><updated>2008-07-17T11:25:16.226-04:00</updated><title type='text'>BizTalk Mapper: Mapping a the Value of a Node when Present, Otherwise Nil</title><content type='html'>&lt;p&gt;If you have an optional node in your source schema (e.g. minOccurs=&amp;quot;0&amp;quot;) who value must map to a nillable node in your destination schema, this tidy little mapper construct is for you.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/christopher316/SH9kWkXiguI/AAAAAAAAADA/kW7zKbCw9Zw/s1600-h/BizTalk%20Conditional%20Value%20or%20Nil%20mapping%5B2%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="104" alt="BizTalk Conditional Value or Nil mapping" src="http://lh6.ggpht.com/christopher316/SH9kW60DRmI/AAAAAAAAADE/rvAcww4_v8M/BizTalk%20Conditional%20Value%20or%20Nil%20mapping_thumb.png?imgmax=800" width="238" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It occurs to me that a cookbook containing many of these patterns would be useful to folks just getting started with the BizTalk mapper. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1153666058166508127?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1153666058166508127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1153666058166508127' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1153666058166508127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1153666058166508127'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/07/biztalk-mapper-mapping-the-value-of.html' title='BizTalk Mapper: Mapping a the Value of a Node when Present, Otherwise Nil'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/christopher316/SH9kW60DRmI/AAAAAAAAADE/rvAcww4_v8M/s72-c/BizTalk%20Conditional%20Value%20or%20Nil%20mapping_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-5391195275659579449</id><published>2008-07-10T17:20:00.001-04:00</published><updated>2008-10-20T12:25:34.806-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql server 2005'/><category scheme='http://www.blogger.com/atom/ns#' term='wcf'/><title type='text'>Calling a WCF Service from a SQL Server 2005 CLR User-Defined Function</title><content type='html'>&lt;p&gt;On my current project I developed a Membership Service that consolidates all user identities into a single authority, allowing for things like enterprise single sign-on, impersonation, and centralized auditing.&amp;#160; Now that we're ready to convert our users over from the previous system, we need to register them all through the service interface.&amp;#160; Since the existing user data will be staged to a SQL Server, it was appropriate to give that import access to the service.&lt;/p&gt;  &lt;p&gt;Enter a user-defined function.&amp;#160; Adding a SQL Server Project to my Membership Service solution, I quickly wrapped the call to the RegisterUser web method in a SqlFunction, i.e. a method tagged with the Microsoft.SqlServer.Server.SqlFunction attribute.&amp;#160; David Hayden has a &lt;a href="http://davidhayden.com/blog/dave/archive/2006/04/25/2924.aspx" target="_blank"&gt;good post&lt;/a&gt; on the steps necessary to get this right.&amp;#160; &lt;a href="http://footheory.com/blogs/bennie/archive/2006/12/07/invoking-a-web-service-from-a-sqlclr-stored-procedure.aspx" target="_blank"&gt;Here's an even more detailed discussion&lt;/a&gt; to get you going.&amp;#160;&amp;#160; In addition to these two posts, &lt;a href="http://en.csharp-online.net/In-Process_Data_Access_in_SQL_Server_2005%E2%80%94Calling_a_Web_Service_from_SQLCLR" target="_blank"&gt;this article&lt;/a&gt; covers how to impersonate the principal in calling your function; it also discusses how you can modify the proxy class to not require the UNSAFE permission set.&amp;#160; The SQLCLR team also has a &lt;a href="http://blogs.msdn.com/sqlclr/archive/2005/07/25/Vineet.aspx" target="_blank"&gt;great post&lt;/a&gt; on doing this.&lt;/p&gt;  &lt;p&gt;All of these authors used wsdl.exe to generate the proxy class for the web service.&amp;#160; This is a fine approach, but I prefer the ease of adding a Web Service to my project.&lt;/p&gt;  &lt;p&gt;Both approaches also used the &lt;a href="http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx" target="_blank"&gt;sgen utility&lt;/a&gt; to generate an XML Serialization Assembly for the classes in the web service proxy that was created with wsdl.exe or adding a Web Reference.&amp;#160; This &lt;a href="http://support.microsoft.com/kb/913668" target="_blank"&gt;knowledge base article&lt;/a&gt; explains why this is absolutely necessary when hosting your proxy in SQLCLR.&lt;/p&gt;  &lt;p&gt;There is an addition consideration with using wsdl.exe and/or Web Reference generated proxies against a WCF Service that uses the wsHttpBinding, &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1142598&amp;amp;SiteID=1" target="_blank"&gt;highlighted here&lt;/a&gt;.&amp;#160; These proxies only support the basicHttpBinding, that is they don't support WS-Addressing as required by the wsHttpBinding.&amp;#160; So, if you got your sql clr function or stored procedure calling your WCF web service, but you are getting a web service timeout, check to make sure it is using a compatible binding.&amp;#160; You may also notice the System.ServiceModel.ActionMismatchAddressingException in the &lt;a href="http://msdn.microsoft.com/en-us/library/ms732023.aspx" target="_blank"&gt;service log&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-5391195275659579449?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/5391195275659579449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=5391195275659579449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5391195275659579449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5391195275659579449'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/07/calling-wcf-service-from-sql-server.html' title='Calling a WCF Service from a SQL Server 2005 CLR User-Defined Function'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1015509906886846975</id><published>2008-06-10T09:23:00.002-04:00</published><updated>2009-01-27T14:33:29.812-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>XML Schema dateTime Primer for C# Developers</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;The &lt;a href="http://www.w3.org/TR/xmlschema-2/#dateTime" target="_blank"&gt;XML Schema dateTime&lt;/a&gt; primitive data type represents the current date and time (June 10th, 2008 at 9:30am Eastern Daylight Savings at the time of this writing) in the following format:&lt;/p&gt;  &lt;p&gt;2008-06-10T13:30:00Z&lt;/p&gt;  &lt;p&gt;The above format represents the UTC date/time.&amp;#160; UTC, or coordinated universal time, is just Greenwich Mean Time (or Zulu time, hence the &amp;quot;Z&amp;quot;).&amp;#160; UTC is the SI name for this zero time offset.&amp;#160; To get the UTC date/time for your local time, simply add your time zone offset.&amp;#160; In Indiana, where I'm from, our GMT offset is currently -04:00 (colloquially, &amp;quot;four hours behind&amp;quot;).&lt;/p&gt;  &lt;p&gt;Here's a C# one-liner to format the current time in the XML Schema dateTime format.&lt;/p&gt;  &lt;p&gt;string xsDateTime = System.DateTime.Now.ToUniversalTime().ToString(&amp;quot;o&amp;quot;);&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1015509906886846975?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1015509906886846975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1015509906886846975' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1015509906886846975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1015509906886846975'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/06/xml-schema-datetime-primer-for-c.html' title='XML Schema dateTime Primer for C# Developers'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-932108544219015961</id><published>2008-06-05T12:46:00.001-04:00</published><updated>2008-10-20T12:26:02.485-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><title type='text'>PowerShell: Convert Unix line-ending to Windows CrLf</title><content type='html'>&lt;p&gt;function GetFiles   &lt;br /&gt;{    &lt;br /&gt;&amp;#160; foreach ($i in $input) {    &lt;br /&gt;&amp;#160;&amp;#160; ? -inputObject $i -filterScript { $_.GetType().Name -eq &amp;quot;FileInfo&amp;quot; }    &lt;br /&gt;&amp;#160; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function ConvertToCrLf   &lt;br /&gt;{     &lt;br /&gt;&amp;#160; param([string] $path)    &lt;br /&gt;&amp;#160; gci $path |     &lt;br /&gt;&amp;#160; GetFiles |    &lt;br /&gt;&amp;#160; % {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $c = gc $_.FullName    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $c | % {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (([regex] &amp;quot;`r`n$&amp;quot;).IsMatch($_) -eq $false) {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $_ -replace &amp;quot;`n&amp;quot;, &amp;quot;`r`n&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } else {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $_     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } |     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set-content $path    &lt;br /&gt;&amp;#160; }    &lt;br /&gt;}&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-932108544219015961?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/932108544219015961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=932108544219015961' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/932108544219015961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/932108544219015961'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/06/powershell-convert-unix-line-ending-to.html' title='PowerShell: Convert Unix line-ending to Windows CrLf'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6898603168907874066</id><published>2008-05-29T11:14:00.001-04:00</published><updated>2008-10-20T12:26:12.698-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>SafeExecute: A Functional Pattern for Cross-cutting Exception Handling</title><content type='html'>&lt;p&gt;In some cases, you may find yourself implementing the exact same exception handling logic in several methods within a class, and your brain screams DRY!&amp;#160; Here's way to use C# 3.0 to put that exception handling logic in one place:&lt;/p&gt;  &lt;pre class="code" style="background: #181818"&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;        &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;public string &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Foo&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;string &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;string &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;greeting&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;return &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;SafeExecute&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;string&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;gt;(() =&amp;gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;return &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;greeting &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;+ &lt;/span&gt;&lt;span style="background: #181818; color: #60ff60"&gt;&amp;quot; &amp;quot; &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;+ &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;;&lt;br /&gt;                });&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;public int &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Bar&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;int &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;i&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;return &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;SafeExecute&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;int&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;gt;(() =&amp;gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;return &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;i &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;+ 1;&lt;br /&gt;                });&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;protected &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;T SafeExecute&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;T&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #2b91af"&gt;Func&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;lt;&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;T&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;funcToExecute&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;try&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;{&lt;br /&gt;                &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;return &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;funcToExecute&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Invoke&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;();&lt;br /&gt;            }&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;catch &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Exception&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;throw&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;/span&gt;&lt;span style="background: #181818; color: #c080c0"&gt;//if your error handling does not throw an exception&lt;br /&gt;            //return default(T);&lt;br /&gt;        &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The details of proper exception handling are elided above to allow the reader to focus on the functional aspects of the pattern.&amp;#160; This pattern is really only useful when you are using exactly the same exception handling logic.&amp;#160; This is often the case in classes due to common implications of SRP.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Actually, this pattern is more generalized by the common functional pattern of wrapping the execution of another function, but this provides a useful concrete example.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6898603168907874066?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6898603168907874066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6898603168907874066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6898603168907874066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6898603168907874066'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/safeexecute-functional-pattern-for.html' title='SafeExecute: A Functional Pattern for Cross-cutting Exception Handling'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3094670180426846050</id><published>2008-05-28T20:19:00.001-04:00</published><updated>2008-10-20T12:26:23.997-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Learning New Tools</title><content type='html'>&lt;p&gt;I sometimes wonder which is more complex, in the information theory sense: the functioning of a given vital organ or the functioning of a modern IDE.&amp;#160; In the case of Emacs, I would tend to favor the the IDE.&lt;/p&gt;  &lt;p&gt;I learned vi in college; because, truthfully, it was the default editor for elm, and I wanted to send email.&amp;#160; Most other folks used pine, but I didn't hear about that for a while.&amp;#160; Anyway, that was how it began, and I came to love vi and later vim.&amp;#160; This loved flowered even after I found out Bill Joy wrote it, probably because he hated Emacs.&lt;/p&gt;  &lt;p&gt;Now, there are a few flawed attempts to bring syntax highlighting and indenting for Erlang to my favorite little editor, but they're far from perfect.&amp;#160; There's even an aborted attempt to bring Erlang to Eclipse.&amp;#160; Alas, it too is seriously flawed.&amp;#160; It would seem that most of the Erlang programming universe writes code in Emacs.&lt;/p&gt;  &lt;p&gt;I've never been a joiner, and I wore my iconoclastic editor as a badge of honor.&amp;#160; Now, however, I've resolved to follow the pack and learn Emacs.&amp;#160; As a side benefit, it would appear that I'll be learning a little Lisp along the way, well elisp at least, more out of necessity than desire.&lt;/p&gt;  &lt;p&gt;What bugs me is that I don't really want to learn Emacs, I'd rather spend that time exploring OTP. But, c'est la vie!&amp;#160; It will just take some time to become proficient.&lt;/p&gt;  &lt;p&gt;At work these days I'm learning the ins-and-outs of BizTalk.&amp;#160; This, too, is less than ideal.&amp;#160; BizTalk is really powerful, very enterprise-y message-oriented middleware.&amp;#160; Truthfully, I wouldn't mind it so much if its development tools had any notion of refactoring.&amp;#160; The whole thing just seems to brittle, and could there be a more miserable way to spend ones time mapping messages types?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3094670180426846050?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3094670180426846050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3094670180426846050' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3094670180426846050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3094670180426846050'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/learning-new-tools.html' title='Learning New Tools'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1671917086255965171</id><published>2008-05-28T00:36:00.001-04:00</published><updated>2008-10-20T12:27:03.901-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='erlang'/><title type='text'>Getting Erlang Going on a Vanilla Ubuntu Install</title><content type='html'>&lt;p&gt;Before you are able to configure and make Erlang OTP from source, you're going to need to be sure your have the right dependencies installed.&amp;#160; For a vanilla Ubuntu installation, this means:   &lt;br /&gt;sudo apt-get install libc6-dev    &lt;br /&gt;sudo apt-get install libncurses6-dev    &lt;br /&gt;sudo apt-get install m4    &lt;br /&gt;sudo apt-get install libssl-dev    &lt;br /&gt;sudo apt-get install sun-java6-jdk&lt;/p&gt;  &lt;p&gt;The last two aren't strictly necessary, but libssl-dev is the source files the OTP system needs to utilize OpenSSL.&amp;#160; Now, that last dependency on the JDK may seem a bit odd, but the standard makefile for the OTP system tries to build &lt;a href="http://www.erlang.org/doc/apps/jinterface/index.html"&gt;jinterface&lt;/a&gt;, an OTP application that enables running an Erlang node in Java.&amp;#160; (As an aside, there is a similar package called &lt;a href="https://launchpad.net/twotp"&gt;twotp&lt;/a&gt; that does the same thing for Python.)&lt;/p&gt;  &lt;p&gt;Assuming all goes well, you should be able to cd into the source directory (wherever it is you extracted it to when you &lt;a href="http://www.erlang.org/download.html"&gt;downloaded&lt;/a&gt; it) and execute the following commands in order:    &lt;br /&gt;./configure    &lt;br /&gt;make    &lt;br /&gt;sudo make install&lt;/p&gt;  &lt;p&gt;Depending on the permissions to /usr/local/* you may not need elevated privileges, but again this is for a vanilla install.&amp;#160; Now, you should be able to run Erlang.&amp;#160; Next time, I'll have some notes on setting up vim and Emacs for Erlang.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1671917086255965171?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1671917086255965171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1671917086255965171' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1671917086255965171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1671917086255965171'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/getting-erlang-going-on-vanilla-ubuntu.html' title='Getting Erlang Going on a Vanilla Ubuntu Install'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1575586242672797870</id><published>2008-05-24T15:43:00.001-04:00</published><updated>2008-10-20T12:26:43.398-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ALT.NET'/><title type='text'>The ALT.NET Times for May 24th, 2008</title><content type='html'>&lt;p&gt;A bit of a quiet week on the list this week.&amp;#160; In the U.S. this coming Monday is Memorial Day, and we get the day off--a fact that compels many to plan their vacations around it.&amp;#160; Whatever the reason, there wasn't much traffic, and so there's not much to report.&lt;/p&gt;  &lt;p&gt;Probably the most interesting messages of the week revolved around ALT programming languages.&amp;#160; The Boo programming language--which is a full-on CLR language in the style of Python--seemed to be a favorite of many on the list.&amp;#160; Oren Eini is a primary contributor and uses &lt;a href="http://boo.codehaus.org/"&gt;Boo&lt;/a&gt; for his &lt;a href="http://castleproject.org/container/index.html"&gt;Windsor&lt;/a&gt; configuration tool, &lt;a href="http://www.ayende.com/Blog/archive/7268.aspx"&gt;Binsor&lt;/a&gt;.&amp;#160; There's a healthy community around the language, one which created &lt;a href="http://www.codeplex.com/BooLangStudio"&gt;VS2008 integration&lt;/a&gt; for it.&lt;/p&gt;  &lt;p&gt;There was also some discussion of &lt;a href="http://research.microsoft.com/fsharp/"&gt;F#&lt;/a&gt;, a language that is something like a CLR implementation of OCaml, with some changes required to behave well with the runtime and other CLR languages.&amp;#160; Additionally, it is missing one quintessential OCaml feature: &lt;a href="http://www.ocaml-tutorial.org/modules#functors"&gt;functors&lt;/a&gt;.&amp;#160; Nevertheless, F# delivers many of the familiar mainstays of a dynamic functional language--like currying, first-class functions, pattern matching, and tuples/records--while integrating with all the .NET libraries and providing strong typing through type inference.&amp;#160; It also works seamlessly when installed over Visual Studio 2008.&amp;#160; To learn more, a good place to start would be to &lt;a href="http://research.microsoft.com/fsharp/manual/default.aspx"&gt;RTM&lt;/a&gt;, or Ted Neward's &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc164244.aspx"&gt;F# Primer&lt;/a&gt;.&amp;#160; The place where the F# community gathers is called &lt;a href="http://cs.hubfs.net/"&gt;hubFS&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;So, that's the short version (or at least the thematically relevant version) of what I learned from the alt.netters this week.&amp;#160; Have a great one!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1575586242672797870?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1575586242672797870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1575586242672797870' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1575586242672797870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1575586242672797870'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/altnet-time-for-may-24th-2008.html' title='The ALT.NET Times for May 24th, 2008'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4743396025073194356</id><published>2008-05-21T09:07:00.001-04:00</published><updated>2008-10-20T12:27:14.312-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>VMWare Blues</title><content type='html'>&lt;p&gt;&lt;a href="http://lh6.ggpht.com/christopher316/SDQeifyMOTI/AAAAAAAAACw/MCqbG6vD9Uw/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="231" alt="image" src="http://lh4.ggpht.com/christopher316/SDQei_yMOUI/AAAAAAAAAC4/KXulA_T4A7c/image_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I suspect it's my fault.&amp;#160; I let Vista update to SP1 while I had the VM paused then tried resuming.&amp;#160; I got this BSOD while VMWare was restoring the virtual machine's state.&amp;#160; Since Vista now shows 4GB of RAM instead of 3.5GB after the update, I'm guessing the memory manager changed, and that caused VMWare to choke on its old memory map.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4743396025073194356?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4743396025073194356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4743396025073194356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4743396025073194356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4743396025073194356'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/vmware-blues.html' title='VMWare Blues'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/christopher316/SDQei_yMOUI/AAAAAAAAAC4/KXulA_T4A7c/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1278010887432058862</id><published>2008-05-17T12:46:00.001-04:00</published><updated>2008-05-17T12:46:41.977-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ALT.NET'/><title type='text'>The ALT.NET Times for May 17th, 2008</title><content type='html'>&lt;p&gt;They say if you do something three times, it becomes a habit.&amp;#160; This is the second post in a series highlighting what I gleaned from the sharp minds in the ALT.NET scene over last week.&lt;/p&gt;  &lt;p&gt;Early in the week, Harry McIntyre from London shared his process and custom code for managing change to DBML files, the XML that defines your classes in Linq to SQL.&amp;#160; Folks using Linq to SQL know the pain of managing change to these files.&amp;#160; You cannot regenerate them from your database without wiping out any customizations that you made.&amp;#160; The Linq to SQL designer is pretty good about capturing most of the idiosyncrasies of your tables, but you inevitably have to customize the generated DBML to cover the corner cases, such as having a default value on a non-nullable CreatedOn column.&lt;/p&gt;  &lt;p&gt;Harry's project is called &lt;a href="http://code.google.com/p/linqtodbmlrunner/" target="_blank"&gt;Linq to DBML Runner&lt;/a&gt;, and he has &lt;a href="http://www.adverseconditionals.com/2008/05/scripting-changes-to-linq-to-sql-dbml.html" target="_blank"&gt;a post about the process he uses&lt;/a&gt;.&amp;#160; It's dependent on a couple of other projects, including &lt;a href="http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to-xsd-alpha-0-2.aspx" target="_blank"&gt;Linq to XSD&lt;/a&gt; and in yet another case of trickle-down technology from Ruby: &lt;a href="http://code.google.com/p/migratordotnet/" target="_blank"&gt;Migrator.NET&lt;/a&gt;.&amp;#160; If you're committed to effectively managing change to your DBML files, and you will be if you use it on greenfield projects involving more than a couple of developers, check out Linq to DBML Runner.&lt;/p&gt;  &lt;p&gt;There was a lot of talk about MVC and MVP, along with specializations formalized by Fowler including Passive View.&amp;#160; A few astute alt.netters shared some exposition on the venerable MVC pattern as it was first conceived and developed in Smalltalk.&amp;#160; Among these posts, &lt;a href="http://ctrl-shift-b.blogspot.com/2007/08/interactive-application-architecture.html" target="_blank"&gt;Derek Greer's extensive exposition of these patterns&lt;/a&gt; was linked up.&amp;#160; This is a fantastic, thorough, and cogent examination of the patterns and the origin, highly recommended. &lt;/p&gt;  &lt;p&gt;You can also add another implementation to your MVP list: &lt;a href="http://www.mvcsharp.org/" target="_blank"&gt;MVC#&lt;/a&gt;.&amp;#160; This looks very interesting, but I haven't had a chance to delve into it.&lt;/p&gt;  &lt;p&gt;Also in the rich-client/WPF world, I heard the first rumblings about Prism this week.&amp;#160; Glenn Block has been a frequent poster to the mailing list in the past.&amp;#160; He's the Technical Product Planner for the Client User Experience (UX) program in Microsoft's Patterns &amp;amp; Practices (PnP) team.&amp;#160; Glenn &lt;a href="http://blogs.msdn.com/gblock/archive/2008/03/12/prism-ri-first-drop.aspx" target="_blank"&gt;posted about a code drop of a Prism reference implementation&lt;/a&gt;.&amp;#160; This is essentially an application that will bake-in all the concepts that will eventually be extracted, formalized, and generalized into the Prism framework for composite applications.&amp;#160; This is cool stuff, and it will be good to see a lot of the disparate PnP frameworks rolled up.&lt;/p&gt;  &lt;p&gt;One ActionScript developer (now &lt;strong&gt;that&lt;/strong&gt; is ALT) asked about dealing with nested asynchronous web service calls.&amp;#160; Two suggestions were given: &lt;a href="http://en.wikipedia.org/wiki/Flow-based_programming" target="_blank"&gt;Flow-based programming&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Continuation_passing_style" target="_blank"&gt;continuation passing style&lt;/a&gt;.&amp;#160; The latter is familiar, I would imagine, to most developers, at least those with some exposure to functional programming, and it is now very easy to accomplish with C# and lambda expressions.&amp;#160; The former, Flow-based programming, is an unfamiliar programming style to me, but at first blush it appears to fit in very well with the current interest in SOA.&lt;/p&gt;  &lt;p&gt;Our final topic is an appropriate one to this column, namely, how do we process all the technology out there? Asked by J.P. Hamilton on the list, the most interesting response was from Oren:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I don't.&amp;#160; I read some interesting blogs, but I don't go into technology unless I have a need for it.&amp;#160; I try to keep an eye for new ideas, but technology itself is not something that I even try to keep up.&amp;#160; I find that knowing he fundamentals helps immensely when you learn new stuff, so focusing on that is never a bad idea. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Have a great week!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1278010887432058862?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1278010887432058862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1278010887432058862' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1278010887432058862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1278010887432058862'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/altnet-times-for-may-17th-2008.html' title='The ALT.NET Times for May 17th, 2008'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-332806407326230200</id><published>2008-05-12T13:27:00.001-04:00</published><updated>2009-10-22T13:27:43.302-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Hpricot Ruby Script to Digest ISO Currency Codes</title><content type='html'>&lt;p&gt;UPDATE: I fixed a couple of bugs in this and changed the XML Schema DataType namespace alias to “xs”.&amp;#160; You will likely want to remove some enumeration items because they aren’t particular useful for e-commerce applications, e.g. palladium troy ounce.&lt;/p&gt;  &lt;p&gt;require 'hpricot'    &lt;br /&gt;require 'open-uri'     &lt;br /&gt;doc = Hpricot(open(&amp;quot;&lt;a href="http://en.wikipedia.org/wiki/ISO_4217" ))?="))?"&gt;http://en.wikipedia.org/wiki/ISO_4217&amp;quot;))&lt;/a&gt;     &lt;br /&gt;codetable = doc.search(&amp;quot;//table[@class='wikitable sortable']&amp;quot;)[0]     &lt;br /&gt;rows = codetable.search(&amp;quot;//tr&amp;quot;)     &lt;br /&gt;for i in 1..rows.length     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; tds = rows[i].search(&amp;quot;//td&amp;quot;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; unless rows[i] == nil     &lt;br /&gt;&lt;nobr&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; puts '&amp;lt;xs:enumeration id=&amp;quot;' + tds[3].search(&amp;quot;//a[@title]&amp;quot;).inner_html.inner_html.gsub(/\s/, '_') + '&amp;quot;&amp;#160; value=&amp;quot;' + tds[0].inner_html + '&amp;quot; /&amp;gt;' &lt;/nobr&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; end     &lt;br /&gt;end&lt;/p&gt;  &lt;p&gt;Also, here's a Powershell script to process the &lt;a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm" target="_blank"&gt;ISO 3166 country code list&lt;/a&gt; (semi-colon delimited): &lt;/p&gt; &lt;nobr&gt;gc countrycodes.txt | ? {$_ -match ';'} | % { $s0 = $_.split(';')[0]; $s1 = $_.split(';')[1]; &amp;quot;&amp;lt;xsd:enumeration id=`&amp;quot;$s0`&amp;quot; value=`&amp;quot;$s1`&amp;quot; /&amp;gt;&amp;quot; }&amp;#160; | out-file codes.txt&lt;/nobr&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-332806407326230200?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/332806407326230200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=332806407326230200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/332806407326230200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/332806407326230200'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/hpricot-ruby-script-to-digest-iso.html' title='Hpricot Ruby Script to Digest ISO Currency Codes'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4586232605140654413</id><published>2008-05-10T11:01:00.001-04:00</published><updated>2008-05-10T11:08:21.704-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ALT.NET'/><title type='text'>The ALT.NET Times for May 10th, 2008</title><content type='html'>&lt;p&gt;This is the inaugural post of a series I propose to do over Saturday morning coffee.&amp;#160; I hope to cherry-pick the posts on the ALT.NET mailing list, and record here for posterity (and my feeble, fallible brain) the best information of the week.&amp;#160; Think of it as an ALT.NET Lazy Web distilled. &lt;/p&gt;  &lt;p&gt;So, what did we learn this week?&amp;#160; Well, if you're writing, thinking about writing, or desperately need an HTML parser, you should check out &lt;a href="http://code.whytheluckystiff.net/hpricot/" target="_blank"&gt;Hpricot&lt;/a&gt;.&amp;#160; Incidentally, if you're not a fan of Ruby, beware!&amp;#160; The usage syntax of this library might make you a convert.&amp;#160; If you're looking for a .NET library, &lt;a href="http://www.mindtouch.com/blog/2007/12/09/sgmlreader-172/" target="_blank"&gt;SgmlReader&lt;/a&gt; is a great place to start.&lt;/p&gt;  &lt;p&gt;Speaking of Ruby, Dave Newman let us know about his &lt;a href="http://sentia.com.au/2008/05/i-love-haml-but-i.html" target="_blank"&gt;VS plug-in&lt;/a&gt; for syntax highlighting of &lt;a href="http://haml.hamptoncatlin.com/" target="_blank"&gt;Haml&lt;/a&gt;.&amp;#160; Haml is a templating language for creating views in RoR.&lt;/p&gt;  &lt;p&gt;A topic that frequently comes up made another appearance this week: &amp;quot;TDD: Where to Start?&amp;quot;&amp;#160; Ah, a fine question and one the ALT.NET crowd answers rather well.&amp;#160; A resounding chorus of alt.netters always seem to respond with one book title in particular: &lt;a href="http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052" target="_blank"&gt;Working Effectively with Legacy Code&lt;/a&gt; by Michael Feathers.&amp;#160; Starting out with TDD is hard work, says the crowd, and starting out with TDD on a brownfield project that doesn't utilize inversion of control is considerably harder.&amp;#160; Another popular suggestion is to see &lt;a href="http://evanhoff.com/archive/2007/10/17/56.aspx" target="_blank"&gt;TDD in action&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The &lt;a href="http://blogs.msdn.com/kcwalina/archive/2008/04/25/MEF.aspx" target="_blank"&gt;Managed Extensibility Framework&lt;/a&gt; got some pixels towards the beginning of the week.&amp;#160; To quote &lt;a href="http://blogs.msdn.com/kcwalina/" target="_blank"&gt;Krzysztof Cwalina&lt;/a&gt;, contributing author of &amp;quot;.NET Framework Design Guidelines&amp;quot; and PM of the Application Framework Core team at Microsoft:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;MEF is a set of features referred in the academic community and in the industry as a &lt;i&gt;Naming and Activation Service&lt;/i&gt; (returns an object given a &amp;#8220;name&amp;#8221;), &lt;i&gt;Dependency Injection&lt;/i&gt; (DI) framework, and a &lt;i&gt;Structural Type System&lt;/i&gt; (duck typing). These technologies (and other like System.AddIn) together are intended to enable the world of what we call &lt;i&gt;Open and Dynamic Applications&lt;/i&gt;, i.e. make it easier and cheaper to build extensible applications and extensions.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is exciting news for .NET developers.&amp;#160; Incorporating these features into the BCL means we don't have to get permission from our clients and project managers to use them.&amp;#160; We won't have to take dependencies on Unity, Windsor, Structure Map, AutoFac, or Spring.NET to get inversion of control goodness into our applications.&lt;/p&gt;  &lt;p&gt;One classically &amp;quot;ALT&amp;quot; exchange about distributing configuration changes mentioned some technologies with which I was unfamiliar.&amp;#160; &lt;a href="http://activemq.apache.org/" target="_blank"&gt;ActiveMQ&lt;/a&gt; is a huge, mature Apache project for Message Brokering and Enterprise Integration Patterns.&amp;#160; Under its umbrella are projects such as the &lt;a href="http://activemq.apache.org/nms.html" target="_blank"&gt;.NET Messaging API&lt;/a&gt; which provides a common API for interacting with messaging providers (ActiveMQ, STOMP, MSMQ, and EMS).&amp;#160; &lt;a href="http://www.ikvm.net/" target="_blank"&gt;IKVM&lt;/a&gt; is, to put it succinctly, Java running on Mono.&amp;#160; The OP was keen on using custom WCF extensions to make distributed configuration caching with &lt;a href="http://www.danga.com/memcached/" target="_blank"&gt;Memcached&lt;/a&gt; transparent.&amp;#160; Oren Eini posted some time ago about &lt;a href="http://www.ayende.com/Blog/archive/7508.aspx" target="_blank"&gt;using Memcached with .NET&lt;/a&gt;, and it is definitely something you should check out, should the need for a distributed object cache arise.&lt;/p&gt;  &lt;p&gt;That's all I have to report this week.&amp;#160; Have a great weekend and to quote Joe Krutulis of Appirio, &amp;quot;Think &amp;amp; Enjoy!&amp;quot;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4586232605140654413?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4586232605140654413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4586232605140654413' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4586232605140654413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4586232605140654413'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/altnet-times-for-may-10th-2008.html' title='The ALT.NET Times for May 10th, 2008'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4709549229494975651</id><published>2008-05-05T11:18:00.001-04:00</published><updated>2008-05-10T11:09:00.160-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>Using LINQ from .NET 2.0</title><content type='html'>&lt;p&gt;A few months back when I was migrating a project to VS 2008, the PM was very concerned that .NET 3.5 would cause problems on our servers, interfering with existing applications or creating new bugs in the existing codebase.&amp;#160; I did my best to educate my PM on the nature of .NET 3.5, that it still ran on the .NET 2.0 CLR, that it was a bunch of new libraries, that it include SDK tools that compiled the new C# 3.0 language, that it wouldn't affect existing applications.&amp;#160; Ever the pragmatic fellow, he insisted on late night installs and system testing, nevertheless.&lt;/p&gt;  &lt;p&gt;Now, I don't mind pragmatism, in fact, I applaud it; however, a different situation can arise than the one I just described.&amp;#160; A non-technical PM or a draconian operations manager might insist that you don't &amp;quot;use .NET 3.5&amp;quot; and stick with &amp;quot;.NET 2.0&amp;quot;.&amp;#160; If you take this at face value, it means you can't use C# 3.0, LINQ, etc.&amp;#160; Well, first you must get them into a Slammer worm recovery group.&amp;#160; Next, you can still use some .NET 3.5 goodness without having to install it on the production server.&lt;/p&gt;  &lt;p&gt;Here's a &lt;a href="http://weblogs.asp.net/fmarguerie/archive/2007/09/05/linq-support-on-net-2-0.aspx" target="_blank"&gt;minimalist approach&lt;/a&gt;: include System.Core.dll in your .NET 2.0 project.&amp;#160; You may already know that you can build strictly for .NET 2.0 from VS 2008, so just set the reference, set it to copy local, and roll. You'll have to convince them to let you install .NET 2.0 SP1, though.&amp;#160; Another thing you could try is &lt;a href="http://www.albahari.com/nutshell/linqbridge.html" target="_blank"&gt;LINQBridge&lt;/a&gt;, a .NET 2.0 re-implementation of LINQ to Objects along with Action&amp;lt;T&amp;gt; and Func&amp;lt;T&amp;gt;.&lt;/p&gt;  &lt;p&gt;At the end of the day, you should probably just stay within the environment's strictures.&amp;#160; If you can make the case that .NET 3.5 will save time and money, you'll be much more successful in changing minds than if you just think it is cool.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4709549229494975651?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4709549229494975651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4709549229494975651' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4709549229494975651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4709549229494975651'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/05/using-linq-from-net-20.html' title='Using LINQ from .NET 2.0'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-816520415956260660</id><published>2008-04-28T17:13:00.001-04:00</published><updated>2008-05-10T11:09:28.117-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><title type='text'>Take Ownership and Full Control in Vista</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Sometimes you move a bunch of files from an old machine, in a different domain, and you want to modify those files in the new environment.&amp;#160; Generally, the process is to take ownership of the files, then grant yourself full control.&amp;#160; This can be a tedious process in Windows Vista, especially in light of LUA.&amp;#160; So, I present here some scripting you can use from PowerShell perform this burdensome task.&lt;/p&gt;  &lt;p&gt;First, taking ownership is still best accomplished using the &amp;quot;&lt;a href="http://technet2.microsoft.com/windowsserver/en/library/2278512b-fe04-419c-8331-99c91b78d7dd1033.mspx?mfr=true" target="_blank"&gt;takeown&lt;/a&gt;&amp;quot; command.&amp;#160; You can look the command syntax up, but if you wanted to take ownership of all the files in the current directory, you can do this from your PowerShell prompt:&lt;/p&gt;  &lt;p&gt;gci | % { takeown /f $_}&lt;/p&gt;  &lt;p&gt;Next, you want to grant yourself full control.&amp;#160; This is normally done with the cacls command, but in Windows Vista this has been deprecated and you should use the &lt;a href="http://technet2.microsoft.com/windowsserver2008/en/library/403edfcc-328a-479d-b641-80c290ccf73e1033.mspx?mfr=true" target="_blank"&gt;icacls&lt;/a&gt; command.&amp;#160; Here's how to grant yourself full control on all the files in the current directory, replacing your current permissions:&lt;/p&gt;  &lt;p&gt;gci | % { icacls $_.FullName /grant:r your_domain\your_username:F }&lt;/p&gt;  &lt;p&gt;Replace your_domain and your_username above with the information appropriate to your environment.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-816520415956260660?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/816520415956260660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=816520415956260660' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/816520415956260660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/816520415956260660'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/04/take-ownership-and-full-control-in.html' title='Take Ownership and Full Control in Vista'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3449207255280465990</id><published>2008-04-20T22:04:00.001-04:00</published><updated>2008-05-10T11:10:28.781-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IoC'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>.NET 3.5 TDD Frameworks from the ALT.NET Scene</title><content type='html'>&lt;p&gt;From the ALTNET mailing list this week, I've come across to very capable frameworks for enabling true test-driven development.&amp;#160; Both seem to be born out of a dissatisfaction with current implementations.&lt;/p&gt;  &lt;p&gt;First up, I'll mention MoQ; pronounced &amp;quot;Maw-kyoo&amp;quot; or just &amp;quot;mawk&amp;quot;, it is written alternatively as both moq and MoQ.&amp;#160; The tagline from the &lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;MoQ Google code site&lt;/a&gt; says it is &amp;quot;The simplest mocking library for .NET 3.5 with deep C# 3.0 integration.&amp;quot;&amp;#160; From here, we can already say that his library isn't for everyone.&amp;#160; Folks working on greenfield projects or converting existing projects may be able to choose .NET 3.5, but many are working in situations where lambdas and LINQ are out-of-bounds.&lt;/p&gt;  &lt;p&gt;Those of us lucky enough to be using Func and Action in our code will find moq to be an elegant approach to unit testing interfaces.&amp;#160; But, other Mocking frameworks support some of the new C# syntax, so why moq? &lt;a href="http://www.clariusconsulting.net/blogs/kzu/archive/2008/03/17/WhydoweneedyetanotherNETmockingframework.aspx" target="_blank"&gt;According to Daniel Cazzulino&lt;/a&gt; (kzu), a developer on moq and a Microsoft XML MVP,&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The value we think Moq brings to the community is simplicity through a more natural programming model.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So, what does kzu mean by &amp;quot;natural&amp;quot;?&amp;#160; Well, traditional mocking uses a record/playback model for setting expectations in TDD, and, due to a legacy that often extends back to .NET 1.0, they have &amp;quot;more than one way to do it&amp;quot;, to use an oft invoked Perl-ism and a big reason why Perl is frequently referred to as &amp;quot;write once, read never&amp;quot;.&amp;#160; Certainly, simpler APIs are to be preferred as long as they can get the job done, and APIs tend to become simpler and more natural over time as long as they aren't required to prevent breaking changes.&amp;#160; So, moq was meant to be a simpler mocking framework that leverages C# 3.0 language features.&amp;#160; And, so it does.&lt;/p&gt;  &lt;p&gt;If you are just getting into TDD and are a little overwhelmed by the myriad mocking frameworks out there and their unfamiliar semantics, you should definitely look into MoQ.&lt;/p&gt;  &lt;p&gt;Now, the next item on our agenda is Total Recall.&amp;#160; Okay, not Total Recall, but another story by Phillip K. Dick: Autofac; in any event, we're going to take a look at the eponymous Inversion of Control container.&amp;#160; &lt;a href="http://code.google.com/p/autofac/" target="_blank"&gt;Autofac&lt;/a&gt; is an MIT licensed project that has gotten some pixel time on the ALT.NET mailing list as of late.&amp;#160; The community around Autofac writes on Google code that:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Autofac was designed with modern .NET features and &lt;i&gt;obsessive&lt;/i&gt; object-orientation in mind. It will change the way you approach dependency injection in .NET.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Well, if you aren't doing DI just yet, it will certainly change the way you do it.&amp;#160; If you're using many of the other .NET IoC containers out there, you're probably not leveraging lambda expressions and LINQ either, so Autofac would be a change.&amp;#160; Like MoQ, Autofac sheds some of the legacy cruft and fully embraces .NET 3.5 as a platform.&amp;#160; Also note that Autofac leverages &lt;a href="http://www.albahari.com/nutshell/linqbridge.html" target="_blank"&gt;LinqBridge&lt;/a&gt; to remain compatible with .NET 2.0 applications.&lt;/p&gt;  &lt;p&gt;So, will I be doing my next greenfield project using DDD with moq, Autofac, and db4o?&amp;#160; Well, I don't think my clients are ready for that yet.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3449207255280465990?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3449207255280465990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3449207255280465990' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3449207255280465990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3449207255280465990'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/04/net-35-tdd-frameworks-from-altnet-scene.html' title='.NET 3.5 TDD Frameworks from the ALT.NET Scene'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7016601020125780190</id><published>2008-04-13T22:23:00.001-04:00</published><updated>2008-05-10T11:10:48.023-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><title type='text'>Advanced Web Programming Techniques: Dynamic Script Tags</title><content type='html'>&lt;p&gt;I was researching some techniques for doing Comet programming, and I ran across a PowerPoint presentation on &lt;a href="http://sota.nonun.com/moniwiki/wiki.php/%EC%9E%90%EB%A3%8C%EC%8B%A4?action=download&amp;amp;value=Brent.Hamby_%26_Geoff_Hendrey_-_deCarta.ppt" target="_blank"&gt;Dynamic Script Tags&lt;/a&gt;.&amp;#160; If you speak GWT, you'll find they outline &lt;a href="http://code.google.com/support/bin/answer.py?hl=en&amp;amp;answer=55954" target="_blank"&gt;this technique in their FAQ&lt;/a&gt;.&amp;#160; Here's the basic idea.&lt;/p&gt;  &lt;p&gt;First, a little background about the Javascript Same-Origin Policy, first introduced in Netscape 2.&amp;#160; From &lt;a href="http://taossa.com/index.php/2007/02/08/same-origin-policy/"&gt;The Art of Software Security Assessment&lt;/a&gt; blog, &amp;quot;same-origin prevents a document or script loaded from one site of origin from manipulating properties of or communicating with a document loaded from another site of origin. In this case the term &lt;em&gt;origin&lt;/em&gt; refers to the domain name, port, and protocol of the site hosting the document.&amp;quot;&amp;#160; These restrictions extended to XmlHttpRequests (xhr), i.e. a script cannot make an xhr to a domain other than the one from whence the script originated.&lt;/p&gt;  &lt;p&gt;The Same-Origin Policy poses a bit of a problem for two kinds of AJAX applications.&amp;#160; First, the developer attempting to make xhr calls to sub-domains (see my previous post on web performance optimization) will have problems.&amp;#160; Generally (IE &amp;amp; FF only?), Resources are not of the same origin if they have a different URL, essentially.&amp;#160; Scripts, however, from the same top-level domain can set the document.domain property to the TLD to allow them to interact.&amp;#160; This doesn't solve the xhr problem.&amp;#160; The second type of AJAX application that can be fettered by the Same-Origin Policy is the mashup.&amp;#160; Most mashups proxy the browser request to get the data from the others sites.&amp;#160; In other word, xyzmaps.com would have all of its scripts/xhr point to xyzmaps.com which would in turn make an HTTP request to e.g. maps.google.com, essentially proxying the browser request.&amp;#160; This presents a huge difficulty for implementing mashups, as all requests have to be proxied through the origin server.&amp;#160; A more thorough understanding of the Same-Origin Policy leads us to a better solution.&lt;/p&gt;  &lt;p&gt;If you've ever used the Google maps API or the Virtual Earth api, you'll note that you include the api in your page via script tags.&amp;#160; Of course, this works perfectly for many sites, but doesn't it violate the Same-Origin Policy?&amp;#160; It does not, in fact, because the browser rightly assumes that scripts included via tags in the document are &amp;quot;safe&amp;quot; insofar as they are not alien.&amp;#160; So, we can get around the Same-Origin Policy by&amp;#160; adding script tags from other domains in our document.&amp;#160; This works statically in or pages, but we can also add script tags dynamically via script DOM manipulation!&amp;#160; Thus, a better solution than proxying requests for our mashups is found.&lt;/p&gt;  &lt;p&gt;So, SiteA dynamically adds a script tag whose src attribute is set to a url on SiteB that will generate JavaScript, embedding the name of SiteA's callback method in the request.&lt;/p&gt;  &lt;p&gt;There are several other rather &lt;a href="http://fettig.net/weblog/2005/11/28/how-to-make-xmlhttprequest-connections-to-another-server-in-your-domain/" target="_blank"&gt;unsatisfactory approaches outlined at Abe Fettig's Weblog&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7016601020125780190?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7016601020125780190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7016601020125780190' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7016601020125780190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7016601020125780190'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/04/advanced-web-programming-techniques.html' title='Advanced Web Programming Techniques: Dynamic Script Tags'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6714333922553934002</id><published>2008-03-29T14:51:00.002-04:00</published><updated>2008-05-10T11:12:11.947-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Website Performance Talk</title><content type='html'>&lt;p&gt;This is a really &lt;a href="http://video.google.com/videoplay?docid=374343798097710096"&gt;enlightening talk&lt;/a&gt; from Steve Souders, author of &lt;a href="http://www.oreilly.com/catalog/9780596529307/"&gt;High Performance Websites&lt;/a&gt;, and Chief Performance Yahoo!.&amp;#160; Below is a summary of his talk, but they also have a &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;page detailing their rules&lt;/a&gt;.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Make fewer HTTP requests: combing CSS and Javascript files, CSS sprites*, use image maps instead of multiple images where possible, inline images* &lt;/li&gt;    &lt;li&gt;Use a Content Distribution Network.&amp;#160; Akamai, Panther Express, Limelight, Mirror Image, SAVVIS.&amp;#160; Distribute your static content before creating a distributed architecture for your dynamic content. &lt;/li&gt;    &lt;li&gt;Add an Expires header.&amp;#160; If you aren't already, you should be changing the URL of your resources when you version them, to ensure that all users will get updates and fixes.&amp;#160; Since you then won't be updating a given resource, you should give it a far future expires header. &lt;/li&gt;    &lt;li&gt;Gzip all content: html, css, and javascript. &lt;/li&gt;    &lt;li&gt;Put stylesheets at the top.&amp;#160; IE will not begin rendering until all CSS files are downloaded.&amp;#160; Use the link HTML tag to pull in stylesheets, not the @import CSS directive, as IE will defer the download of the stylesheet. &lt;/li&gt;    &lt;li&gt;Put javascripts at the bottom.&amp;#160; HTTP 1.1 allows for two parallel server connections per hostname, but all downloads are blocked until the script is downloaded.&amp;#160; The defer attribute of the script block is not supported in Firefox and doesn't really defer in IE. &lt;/li&gt;    &lt;li&gt;Avoid CSS expressions.&amp;#160; The speaker doesn't cover this, but I gather from my own experience that this can seriously delay rendering as the expression will not be evaluated until the page is fully loaded. &lt;/li&gt;    &lt;li&gt;Make CSS and JS external.&amp;#160; This rule can be bent in situations where page views are low and users don't revisit often.&amp;#160; In this situation in-lining is suggested. &lt;/li&gt;    &lt;li&gt;Reduce DNS lookups.&amp;#160; He didn't cover this either, but it follows from rule #1 that additional network requests negatively impact performance.&amp;#160; He does mention later in the talk that splitting your requests across domains can drastically increase response time.&amp;#160; This is a consequence of the two connections per domain limit in the HTTP 1.1 specification.&amp;#160; It is important to remember that JavaScripts from one domain cannot affect JavaScripts or pages from another domain, due to browser security restrictions.&amp;#160; Also, this is a case of diminishing returns, as beyond four domains causes negative returns from, presumably DNS lookups and resource contention in the browser itself. &lt;/li&gt;    &lt;li&gt;&amp;quot;Minify&amp;quot; Javascript.&amp;#160; JSMin written by Doug Crockford is the most popular tool.&amp;#160; This is just removing whitespace, generally.&amp;#160; YUI compressor may be preferred and also does CSS. &lt;/li&gt;    &lt;li&gt;Avoid redirects. &lt;/li&gt;    &lt;li&gt;Remove duplicate scripts. &lt;/li&gt;    &lt;li&gt;Configure &lt;a href="http://en.wikipedia.org/wiki/HTTP_ETag"&gt;ETags&lt;/a&gt;.&amp;#160; These are used to uniquely identify a resource in space and time, such that if the ETag header received is identical to the cached result from a previous request for that resource, the browser can choose to use the local cache without need to download the remainder of the response stream.&amp;#160; The speaker doesn't go into this subject, so questions about how this improves caching performance over caching headers remain unanswered until you read his book. &lt;/li&gt;    &lt;li&gt;Make AJAX cacheable.&amp;#160; If you embed a last modified token into the URL of your AJAX request, you can cause the browser to pull from cache when possible. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;A great tool to analyze your site's conformance to these rules is &lt;a href="http://www.yahooapis.com/yslow/"&gt;YSlow&lt;/a&gt;.&amp;#160; It's an add-on for Firebug.&amp;#160; During development your YSlow grade can give you a very good indication of what is happening to the response time of your application.&amp;#160; This metric, the YSlow grade, seems to me to be a much better quality gate for iterative development than does something as variable and volatile measured response time.&lt;/p&gt;  &lt;p&gt;Some additional rules from the next version of the book:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;As mentioned in my commentary in rule #9, split dominant content domains. &lt;/li&gt;    &lt;li&gt;Reduce cookie weight. &lt;/li&gt;    &lt;li&gt;Make static content cookie free. &lt;/li&gt;    &lt;li&gt;Minify CSS (see rule #10 comments above). &lt;/li&gt;    &lt;li&gt;Use iframes wisely.&amp;#160; The are a very expensive DOM operation.&amp;#160; Think about it--it's an entirely new page, but linked to another. &lt;/li&gt;    &lt;li&gt;Optimize images.&amp;#160; Should your GIFs be PNGs?&amp;#160; Should your PNGs be JPGs?&amp;#160; Can you shrink your color palette? &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6714333922553934002?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6714333922553934002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6714333922553934002' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6714333922553934002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6714333922553934002'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/03/website-performance-talk.html' title='Website Performance Talk'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-130182176878417290</id><published>2008-03-19T19:41:00.001-04:00</published><updated>2008-05-10T11:11:19.485-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='erlang'/><title type='text'>Erlang News</title><content type='html'>&lt;p&gt;Robert Virding's First Rule: &amp;quot;Any sufficiently complicated concurrent program in another language contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Erlang.&amp;quot;&lt;/p&gt;  &lt;p&gt;&amp;quot;I now know based on hard-won experience that you could replace &amp;quot;concurrent program&amp;quot; with &amp;quot;distributed system&amp;quot; in Robert's rule and it would still be just as accurate.&amp;quot; --Steve Vinosky &lt;/p&gt;  &lt;p&gt;Yariv wrote a &lt;a href="http://yarivsblog.com/articles/2008/03/09/in-response-to-what-sucks-about-erlang/"&gt;cogent response&lt;/a&gt; to &amp;quot;What Sucks About Erlang&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.planeterlang.org/story.php?title=LFE_-_Lisp-Flavoured_Erlang"&gt;Erlang Flavored Lisp&lt;/a&gt; anyone?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-130182176878417290?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/130182176878417290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=130182176878417290' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/130182176878417290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/130182176878417290'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/03/erlang-news.html' title='Erlang News'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-1171954125991997054</id><published>2008-03-10T21:13:00.001-04:00</published><updated>2008-05-10T11:12:45.664-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='erlang'/><title type='text'>Programming Erlang: Chapter 8 Problem 2</title><content type='html'>&lt;p&gt;'Tis an odd title, I know.&amp;#160; My puppy is prancing around the kitchen trying to get me interested in his chew toy, dropping it near me so I can see that it bounces and wiggles.&lt;/p&gt;  &lt;p&gt;Do you want to see Erlang bounce and wiggle? The code below creates a circular linked list of Erlang N processes, then sends a Message around it M times. Pretty cool, huh? Well, it was meant to be used by readers of &amp;quot;Programming Erlang&amp;quot; to compare their favorite language to Erlang. I didn't bother doing this with C# threads, though it would be interesting to try it out with the concurrency and co-ordination runtime.&lt;/p&gt;  &lt;p&gt;Here's the out put of the code (time is in milliseconds):&lt;/p&gt;  &lt;pre&gt;Sent 30000000 messages in 27453 / 29186&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;-module(problem2).&lt;br /&gt;-compile(export_all).&lt;br /&gt;&lt;br /&gt;start(N, M, Message) when is_integer(N), is_integer(M) -&amp;gt;&lt;br /&gt;  statistics(runtime),&lt;br /&gt;  statistics(wall_clock),&lt;br /&gt;  FirstPid = spawn(?MODULE,loop,[[]]),&lt;br /&gt;  LastPid = create(1, N, FirstPid),&lt;br /&gt;  FirstPid ! LastPid, %% the ring is closed&lt;br /&gt;  send(0, M, FirstPid, Message),&lt;br /&gt;  {_, Time1} = statistics(runtime),&lt;br /&gt;  {_, Time2} = statistics(wall_clock),&lt;br /&gt;  io:format(&amp;quot;Sent ~p messages in ~p / ~p~n&amp;quot;, [N * M, Time1, Time2]).&lt;br /&gt;  &lt;br /&gt;send(C, C, _Pid,  _Message) -&amp;gt; void;&lt;br /&gt;send(I, C, Pid, Message) -&amp;gt;&lt;br /&gt;  Pid ! {self(), Message},&lt;br /&gt;  receive&lt;br /&gt;    finished -&amp;gt; void&lt;br /&gt;  end,&lt;br /&gt;  send(I+1, C, Pid, Message).&lt;br /&gt;&lt;br /&gt;create(C, C, Pid) -&amp;gt; Pid; &lt;br /&gt;create(I, C, Pid) -&amp;gt; &lt;br /&gt;  create(I+1, C, spawn(?MODULE, loop, [Pid])).&lt;br /&gt;&lt;br /&gt;loop(Next) -&amp;gt;&lt;br /&gt;  receive&lt;br /&gt;    {Caller, FirstPid, Message} -&amp;gt;&lt;br /&gt;      if&lt;br /&gt;        FirstPid =:= self() -&amp;gt; Caller ! finished;&lt;br /&gt;        true -&amp;gt; Next ! {Caller, FirstPid, Message}&lt;br /&gt;      end,&lt;br /&gt;      loop(Next);&lt;br /&gt;    {Caller, Message} -&amp;gt;&lt;br /&gt;      Next ! {Caller, self(), Message},&lt;br /&gt;      loop(Next);&lt;br /&gt;    NewNext when Next =:= [] -&amp;gt;&lt;br /&gt;      loop(NewNext)&lt;br /&gt;  end.&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-1171954125991997054?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/1171954125991997054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=1171954125991997054' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1171954125991997054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/1171954125991997054'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/03/programming-erlang-chapter-8-problem-2.html' title='Programming Erlang: Chapter 8 Problem 2'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8214960151022220375</id><published>2008-02-15T15:42:00.001-05:00</published><updated>2008-02-15T15:42:11.632-05:00</updated><title type='text'>Presenter First with POA</title><content type='html'>&lt;p&gt;Plain-old ASP.NET (POA) has a lot of advantages: rapid UI prototyping, incomparable support from 3rd-party vendors, and a simplified programming model that abstracts away the problems of a stateless application to name a few.&amp;#160; But there remains the problem of testing.&amp;#160; ASP.NET applications--any web-based application--is difficult to test.&amp;#160; The traditional architecture of having your code-behind orchestrate your business logic components in response to events generated through the postback mechanism requires that you instigate those postbacks in order to test the orchestration.&amp;#160; In other words, you have to drive the UI to test your application.&lt;/p&gt;  &lt;p&gt;UI testing is expensive.&amp;#160; If you've done it, you already know that.&amp;#160; If you've not done it, then trust us on this one; the cost of tools, the complexity, and brittleness of web tests drive the cost up.&amp;#160; Furthermore, if an application isn't designed to be UI tested, it becomes a nearly intractable problem to do so.&amp;#160; The folks at &lt;a href="http://www.atomicobject.com/"&gt;Atomic Object&lt;/a&gt; know this from experience.&amp;#160; As proponents of test-driven development, they have looked down the barrel of that gun and found a better way.&amp;#160; They call it &lt;a href="http://www.atomicobject.com/pages/Presenter+First"&gt;Presenter First&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The basic idea behind Presenter First (PF) is to obviate the need for UI testing.&amp;#160; It is a Model-View-Presenter (MVP) variant that is closely related to Martin Fowler's &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;Passive View&lt;/a&gt;.&amp;#160; The application architecture is such that UI is so &lt;a href="http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf"&gt;humble&lt;/a&gt; that there is no need to test the UI.&amp;#160; This architecture requires that the Presenter be responsible for orchestrating the Model (business components) in response to events generated by the View, and updating the View appropriately.&amp;#160; A View in PF only implements events and property set methods.&amp;#160; This View can be defined by contract, e.g. IView, and mocked to allow for test-driven development.&amp;#160; &lt;/p&gt;  &lt;p&gt;A hallmark of PF is that Presenters are constructed with an IView and an IModel and do not implement any other public interface members.&amp;#160; Thus, the encapsulated worfklow is driven completely through IView and (possibly) IModel events.&amp;#160; Concordantly, it becomes evident that PF architectures are implicitly stateful, i.e. the Presenter is extant between events.&amp;#160; In POA, the HttpContext only exists for the duration of the processing of a request.&amp;#160; While the HttpSession remains there is a non-trivial amount of complexity involved with it; ultimately, this too should be considered transient in the general case.&amp;#160; From these facts one might conclude that PF is not applicable to POA.&lt;/p&gt;  &lt;p&gt;The purpose of this writing is to &lt;strong&gt;propose&lt;/strong&gt; a method of implementing Presenter First in ASP.NET.&amp;#160; The general approach is outlined below:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;All page's implementing a PF IView (e.g. ICustomerEditView) must inherit from PFPage.&lt;/li&gt;    &lt;li&gt;PFPage implements a Dictionary&amp;lt;typeof(IView),PresenterInstance&amp;gt; lookup.&lt;/li&gt;    &lt;li&gt;Before Page processing, the PresenterInstance is given a reference to the View, i.e. the current page.&lt;/li&gt;    &lt;li&gt;The IView events are fired (from postback) and the Presenter handles them appropriately, updating the View via setters.&lt;/li&gt;    &lt;li&gt;The Presenter handles the Page.Unload event and drops its View reference&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;This approach diverges from &amp;quot;classical&amp;quot; PF in a few ways.&amp;#160; Most importantly, the actual concrete View acted upon by the Presenter instance is transient.&amp;#160; This should not pose any particular difficulty as the ASP.NET postback model ameliorates this stateless condition of web applications.&amp;#160; Further, while this requires the Presenter interface to implement a mutator for its View reference, the Presenter implementation need not diverge from the &amp;quot;classical&amp;quot; PF approach, save in one important way.&amp;#160; IModel events would need to be queued.[1]&lt;/p&gt;  &lt;p&gt;Furthermore, the Presenter instance and the dictionary must be serializable if that pattern is to be used in an ASP.NET deployment where the HttpSession was out-of-process.&amp;#160; This might propose problems with Presenter references to cached objects that can't be extended to support serialization; though this is considered a minor flaw in the general case and an impediment that can be ameliorated by recreating objects from metadata.&lt;/p&gt;  &lt;p&gt;To compose views it would only be necessary to create a PFControl base class that implemented nearly identical functionality to the PFPage.&amp;#160; Also, though declarative databinding is no longer possible, DTOs could be used in View mutators for databinding.&lt;/p&gt;  &lt;p&gt;Through the use of mock objects, this approach to ASP.NET development using Presenter First enables Test-Driven Development of the business objects and their orchestration in response UI events to without the need to involve ASP.NET pages.[2]&amp;#160; Additionally, this allows for the tandem of presentation (.aspx) and interaction (.aspx.cs) to be isolated from business logic (Model) and orchestration (Presenter).&lt;/p&gt;  &lt;p&gt;Please let me know what you think.&amp;#160; Is your organization using a very similar approach?&amp;#160; How have you fared?&lt;/p&gt;  &lt;p&gt;[1] Because the Presenter MUST NOT call mutator methods on the View between postbacks, IModel events must be queued until a new View instance is received.&lt;/p&gt;  &lt;p&gt;[2] While issues such as declarative security and AJAX can make UI testing a necessity, we are assuming that these are not direct considerations for vetting the business logic and orchestration.&amp;#160; Further this kind of UI testing will generally be done as a part of UAT and thus does not &amp;quot;cost&amp;quot; the development team.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8214960151022220375?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8214960151022220375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8214960151022220375' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8214960151022220375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8214960151022220375'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/02/presenter-first-with-poa.html' title='Presenter First with POA'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2073265930207146524</id><published>2008-02-12T22:30:00.001-05:00</published><updated>2008-05-10T11:13:30.831-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Upgrading to Windows Vista</title><content type='html'>&lt;p&gt;There's a certain voodoo to searching for problems. I don't expect that anyone is actually going to read this before upgrading to Vista... but here are the three problems I had.&lt;/p&gt;  &lt;p&gt;First, make sure if you are running DaemonTools that you uninstall it first.&amp;#160; The Vista upgrade will force you to do this before proceeding, but &lt;a href="http://www.daemon-tools.cc/dtcc/workaround-upgrading-vista-t15757.html"&gt;sptd.sys&lt;/a&gt; will not be removed.&amp;#160; So... remove it.&amp;#160; It's in your Windows directory.&lt;/p&gt;  &lt;p&gt;Next, make sure you download Vista updates for all your drivers.&amp;#160; I couldn't get my external monitor for my laptop to use it's native resolution.&amp;#160; The generic monitor driver in Vista didn't allow it.&amp;#160; I went to my manufacturer's website, NEC's, and download Vista drivers for the monitor.&lt;/p&gt;  &lt;p&gt;Lastly (I hope), you might have trouble connecting to a cheaper broadband router.&amp;#160; Well, you'll be able to connect, but you won't get a DHCP address.&amp;#160; &lt;a href="http://support.microsoft.com/kb/928233/en-us"&gt;This knowledge base article&lt;/a&gt; should do the trick.&lt;/p&gt;  &lt;p&gt;So, what do I think of Vista...?&lt;/p&gt;  &lt;p&gt;I guess I don't know what all the hullabaloo has been about in the blogs and press.&amp;#160; Surely no one was expecting Mac OSX?&amp;#160; I run Ubuntu Linux too, and I don't expect it to be OSX.&amp;#160; In fact, I think Ubuntu's desktop experience sucks compared to Vista, but I love it as a Linux distro.&amp;#160; I ran Slackware in '98, and I can tell you things have REALLY changed in ten years.&amp;#160; And, I can tell you Vista is better than XP.&amp;#160; You have to take that with a grain of salt; I relish change.&lt;/p&gt;  &lt;p&gt;Sure, you will have more trouble pirating music, but it's more secure, prettier, and cooler.&lt;/p&gt;  &lt;p&gt;I guess that's why Vista is making Microsoft money.&amp;#160; Go figure.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2073265930207146524?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2073265930207146524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2073265930207146524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2073265930207146524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2073265930207146524'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/02/upgrading-to-windows-vista.html' title='Upgrading to Windows Vista'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6608709089032929728</id><published>2008-02-03T17:10:00.001-05:00</published><updated>2008-02-03T17:13:05.692-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Weekend Update with Christopher Atkins</title><content type='html'>&lt;p&gt;Dennis Miller was my favorite Weekend Update anchorman.&amp;#160; His wry, sardonic--if verbose--commentaries always made me laugh.&amp;#160; As I think about it, that sketch seems a direct ancestor of the news shows on Comedy Central so popular with the college crowd.&lt;/p&gt;  &lt;p&gt;Anyway, my weekend has been interesting.&amp;#160; I found out that despite what the documentation says, ECDiffieHellmanCng is not supported on Windows XP.&amp;#160; In fact, its constructors check for the presence of NCrypt.dll: a library only available for Windows Vista and Windows Server 2003+.&amp;#160; So, despite that fact that it ships with .NET 3.5, you can't use it on XP.&amp;#160; Joy.&amp;#160; I hope this is not a trend.&amp;#160; You'll also find that you cannot use a BigInt, because it is marked internal.&amp;#160; If you're trying to do modern cryptography on Windows XP, in other words, you are out of luck.&lt;/p&gt;  &lt;p&gt;So, I spent the remainder of my weekend working through Programming Erlang, and I have to say I am even more excited about it.&amp;#160; I'm only on page 51, but I've already learned about list comprehensions and custom flow control abstractions using higher-order functions.&amp;#160; The cool thing is I can apply some of this stuff to C#, now that we have lambda expressions.&lt;/p&gt;  &lt;p&gt;I'm excited about the year ahead.&amp;#160; There are a lot of changes on the horizon.&amp;#160; Imagine, Windows Server 2008, SQL Server 2008, a Yahoo! and Microsoft merger, widespread adoption of OpenID, and a new presidential election are all on their way.&amp;#160; To quote the folk poet Bob Dylan:&lt;/p&gt;  &lt;p&gt;Come writers and critics   &lt;br /&gt;Who prophesize with your pen    &lt;br /&gt;And keep your eyes wide    &lt;br /&gt;The chance won't come again    &lt;br /&gt;And don't speak too soon    &lt;br /&gt;For the wheel's still in spin    &lt;br /&gt;And there's no tellin' who    &lt;br /&gt;That it's namin'.    &lt;br /&gt;For the loser now    &lt;br /&gt;Will be later to win    &lt;br /&gt;For the times they are a-changin'&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6608709089032929728?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6608709089032929728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6608709089032929728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6608709089032929728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6608709089032929728'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/02/weekend-update-with-christopher-atkins.html' title='Weekend Update with Christopher Atkins'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-659134741302742633</id><published>2008-01-30T20:41:00.001-05:00</published><updated>2008-01-30T20:46:03.392-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Competence != Compensation</title><content type='html'>&lt;p&gt;In America we are conditioned to believe that working hard, being diligent, and producing great work is the road to fiscal success.&amp;#160; Anyone who has really worked here will tell you that is simply not the case.&amp;#160; Prima facie, you must recognize that you are not paid what you are &amp;quot;worth&amp;quot;; that is, your personal worth has nothing to do with your income.&amp;#160; One must never forget this simple fact.&amp;#160; Despite the fact that you may do three times the work of your peers, you will not be compensated even twice as much.&lt;/p&gt;  &lt;p&gt;Witness the Home Depot CEO who purposefully runs his stock in the ground, knowing well that a golden parachute awaits for him once the board of directors requests that he &amp;quot;step down.&amp;quot;&amp;#160; Negative output results in a cash payout worth over $200 million dollars.&amp;#160; In America, you are worth what someone will pay you.&amp;#160; There is no such thing as intrinsic value, only assessed value.&amp;#160; In software development there are two ways of having your value assessed, by managers and by investors.&lt;/p&gt;  &lt;p&gt;Make sure you don't hang your hopes on managers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-659134741302742633?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/659134741302742633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=659134741302742633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/659134741302742633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/659134741302742633'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/competence-compensation.html' title='Competence != Compensation'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-5064830694421400279</id><published>2008-01-30T07:12:00.001-05:00</published><updated>2008-01-30T13:16:20.909-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Continuous Integration with TFS: Pre-compiling a Web Application Project</title><content type='html'>&lt;p&gt;If you are looking to pre-compile your web application projects with TFS 2008 Team Build, here are some tips.&lt;/p&gt;  &lt;p&gt;First, you'll want to add the following to your TFSBuild.proj:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target &lt;/span&gt;&lt;span style="color: red"&gt;Name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AfterDropBuild&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;AspNetCompiler&lt;br /&gt;     &lt;/span&gt;&lt;span style="color: red"&gt;PhysicalPath&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;$(DropLocation)\$(BuildNumber)\Release\_PublishedWebsites\web_project_name&lt;/span&gt;&amp;quot;&lt;br /&gt;     &lt;span style="color: red"&gt;Debug&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;false&lt;/span&gt;&amp;quot;&lt;br /&gt;     &lt;span style="color: red"&gt;Force&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot;&lt;br /&gt;     &lt;span style="color: red"&gt;TargetPath&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;font color="#0000ff"&gt;C:\path_to_copy_precompiled_web_to&lt;/font&gt;&amp;quot;&lt;br /&gt;     &lt;span style="color: red"&gt;VirtualPath&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;/Path_to_your_web&lt;/span&gt;&amp;quot;&lt;br /&gt;&lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;Target&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There a few things to note here.&amp;#160; First, the Target Name is crucial; this Target will get executed after the drop is made, i.e. after the build successfully runs and your files are copied to the drop folder you specified when you created the build.&amp;#160; Secondly, remember that this is running from the machine where your build agent runs.&amp;#160; The AspNetCompiler MSBuild tag shown here will launch aspnet_compiler.exe on that build agent machine, and so &amp;quot;/Path_to_your_web&amp;quot; points to the virtual directory on the default web site of your build agent machine.&amp;#160; Please note that &amp;quot;/Path_to_your_web&amp;quot; would be &amp;quot;/&amp;quot; in the case of your application being in the root directory.&amp;#160; Finally, the Force parameter is required since we will be writing over the existing pre-compiled web on subsequent builds.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you want setup a build agent on another machine, perhaps a development web server where you would prefer to deploy the pre-compiled web application, you'll need to configure that agent according to &lt;a href="http://blogs.msdn.com/buckh/archive/2007/08/14/tfs-2008-a-basic-guide-to-team-build-2008.aspx"&gt;these instructions&lt;/a&gt;.&amp;#160; This is a good idea when running verification tests that drive the web UI.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Happy Coding!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-5064830694421400279?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/5064830694421400279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=5064830694421400279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5064830694421400279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5064830694421400279'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/continuous-integration-with-tfs-pre.html' title='Continuous Integration with TFS: Pre-compiling a Web Application Project'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-7612699296406705537</id><published>2008-01-26T13:20:00.001-05:00</published><updated>2008-01-26T15:11:23.703-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>On a Positive Note</title><content type='html'>&lt;p&gt;&lt;a href="http://www.jpboodhoo.com/"&gt;Jean-Paul Boodhoo&lt;/a&gt; is a developer and consultant who used to work at &lt;a href="http://www.thoughtworks.com/"&gt;ThoughtWorks&lt;/a&gt; and has been featured on the &lt;a href="http://polymorphicpodcast.com/shows/developpassion/"&gt;Polymorphic Podcast&lt;/a&gt; and &lt;a href="http://www.dnrtv.com/default.aspx?showNum=10"&gt;DNRtv&lt;/a&gt;.&amp;#160; He recently posted a &lt;a href="http://codebetter.com/blogs/jean-paul_boodhoo/archive/2008/01/16/dream-big-take-some-risks-reap-the-rewards.aspx"&gt;very encouraging post about dreams, risk, and reward&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Here's an excerpt.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I was speaking with a friend yesterday who made an interesting comment:&lt;/p&gt;    &lt;p&gt;&amp;#8220;You seem to regularly take on more stress than most other people would ever think to take on&amp;#8221;&lt;/p&gt;    &lt;p&gt;I corrected him and made this statement. I don&amp;#8217;t feel like I am stressed out that much. In all honesty, the times that I feel stressed out almost always constitute a failure to plan on my part. I did say that what I do take on regularly is: Challenge and Risk. I am not afraid of the opportunity to fall flat on my face taking a risk, because I now that it is in the times of struggle/pain that growth happens.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Bravo.&amp;#160; That's well said.&amp;#160; Paul Graham (all your Lisp are belong to us) wrote a year ago explaining: &lt;a href="http://www.paulgraham.com/love.html"&gt;How to Do What You Love&lt;/a&gt;.&amp;#160; Here's a quote, &lt;strong&gt;&lt;em&gt;emphasis&lt;/em&gt;&lt;/strong&gt; added:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Once, when I was about 9 or 10, my father told me I could&lt;strong&gt;&lt;em&gt; be whatever I wanted when I grew up, so long as I enjoyed it&lt;/em&gt;&lt;/strong&gt;. I remember that precisely because it seemed so anomalous. It was like being told to use dry water. Whatever I thought he meant, I didn't think he meant work could &lt;i&gt;literally&lt;/i&gt; be fun&amp;#8212;fun like playing. It took me years to grasp that.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Sure, sure, I heard you saying... do what you love, right?&amp;#160; Well, I love vacations, the ocean, playing guitar, and chasing my puppy--how do I get paid to do that?&amp;#160; The truth is you don't; you won't; and you shouldn't.&amp;#160; Again, from Mr. Graham:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Unproductive pleasures pall eventually. After a while you get tired of lying on the beach. If you want to stay happy, &lt;strong&gt;&lt;em&gt;you have to do something.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I can't tell you how invigorating working in the yard can be or how exciting solving some mildly difficult programming problem can be.&amp;#160; It's enough to make people blog about their experiences.&amp;#160; But, even these are just short-term examples, what is it that you would love to do over the long haul?&amp;#160; Is there some sort of heuristic that we can apply to help use decide?&amp;#160; Here's Graham's idea:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I think the best test is one Gino Lee taught me: to try to do things that would make your friends say wow.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you hate what you do, I cannot convince you that trying to impress your friends with it is going to make it fun.&amp;#160; So, think of the things you do that you do try to impress your friends with?&amp;#160; Do you love to cook?&amp;#160; Master the art, learn the language, hone your technique, and blog about the experience.&amp;#160; Start a in-home cooking class consultancy.&amp;#160; Do you love to take photographs?&amp;#160; Practice, learn, take your camera everywhere, make it your first thought.&amp;#160; Do you love it enough to do it for free?&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The test of whether people love what they do is whether they'd do it even if they weren't paid for it&amp;#8212;even if they had to work at another job to make a living. How many corporate lawyers would do their current work if they had to do it for free, in their spare time, and take day jobs as waiters to support themselves?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you don't have enough passion to work hard at something and get better, then you either don't love it or you don't have an audience.&amp;#160; You might just need new friends.&amp;#160; Seek them out in classes or online discussion groups.&amp;#160; But seek them out.&lt;/p&gt;  &lt;p&gt;If you are worried about money, if you're worried about being responsible for the well-being of your children or spouse, remember that you have a responsibility to them.&amp;#160; You are responsible for loving them, for inspiring them, for trying to be the best person you can for them.&amp;#160; Those are your true responsibilities; you can find a way to pay the really important bills.&amp;#160; Don't let fear admit apathy.&amp;#160; Don't use your family as an excuse.&lt;/p&gt;  &lt;p&gt;If you don't already know what you love to do--and so few of us really do--Graham has further advice:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;It's hard to find work you love; it must be, if so few do. So don't underestimate this task. And don't feel bad if you haven't succeeded yet. In fact, if you admit to yourself that you're discontented, you're a step ahead of most people, who are still in denial. [..] Finding great work you love does usually require discipline.&amp;#160; Is there some test you can use to keep yourself honest? One is to try to do a good job at whatever you're doing, even if you don't like it. [...] Another test you can use is: &lt;strong&gt;always produce&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you are telling yourself that you hate your day job, and one day you will be set free to do what you love, then you better being doing what you love and consistently.&amp;#160; Otherwise, you're lying to yourself and everyone around you.&amp;#160; The hardest thing to admit is that at age 20, 30, 40, or 50 is that you don't know what you love; you don't know what you want to do when you grow up.&amp;#160; My point here is that you must do something; &lt;strong&gt;you must produce&lt;/strong&gt;.&amp;#160; Even if you prove to be rather amateurish in all you attempt, but you really gave it your best, you will be happier--and much more interesting.&amp;#160; The worst thing you can be in your work-life, truly, is be a dilettante.&lt;/p&gt;  &lt;p&gt;I will close by leaving you with these further words from &lt;a href="http://www.paulgraham.com/love.html"&gt;Graham's essay&lt;/a&gt; (please read it):&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;Always produce&amp;quot; is also a heuristic for finding the work you love. If you subject yourself to that constraint, it will automatically push you away from things you think you're supposed to work on, toward things you actually like. &amp;quot;Always produce&amp;quot; will discover your life's work the way water, with the aid of gravity, finds the hole in your roof.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;One last note before parting that I have is simply this: seek out good teachers.&amp;#160; My wife recently told me what the tuition for a four-year degree at local technical college is: nearly $84,000.&amp;#160; Most of their students do not finish, and most of them are there because they want to make more money.&amp;#160; And, sadly, most of them don't learn a thing--because they're not there to learn, they're there to make more money (via a diploma).&amp;#160; This is not the road to happiness.&amp;#160; It would be much better for those people to find work they love and to see out the best teachers.&amp;#160; I guarantee you that those technical colleges do not have the best teachers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-7612699296406705537?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/7612699296406705537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=7612699296406705537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7612699296406705537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/7612699296406705537'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/on-positive-note.html' title='On a Positive Note'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6611704125450518647</id><published>2008-01-24T13:52:00.001-05:00</published><updated>2008-01-24T13:53:44.232-05:00</updated><title type='text'>IndyTFS January Meeting: These Guys Rawk!</title><content type='html'>&lt;p&gt;Jamie Kurtz of Open Solutions presented on TFS Work Items.&amp;#160; Now, I really hate going to user group meetings in the midwest, because most of the time the speakers are not really all that knowledgeable about their topic.&amp;#160; This session, however, could have been entitled, &amp;quot;TFS: All Questions Answered.&amp;quot;&amp;#160; Between Paul Hacker and Jamie Kurtz, not one question was a stumper.&amp;#160; I learned more about TFS in that two hours than I could have in two days on my own.&amp;#160; It was truly fantastic; they had a great attitude!&lt;/p&gt;  &lt;p&gt;Here are some of the things we learned.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Customizing Work Item types: workflow, states, custom form fields, custom field controls&lt;/li&gt;    &lt;li&gt;Details and gotchas on how to get business users setup to edit work items from Excel&lt;/li&gt;    &lt;li&gt;Details about securing fields and work items&lt;/li&gt;    &lt;li&gt;Editing MSBuild files to work appropriately with WorkItems&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Kudos to both gentlemen.&amp;#160; I encourage anyone using or considering using TFS to &lt;a href="http://indytfs.org/sig/Default.aspx"&gt;member up&lt;/a&gt; and start attending meetings.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6611704125450518647?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6611704125450518647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6611704125450518647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6611704125450518647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6611704125450518647'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/indytfs-january-meeting-these-guys-rawk.html' title='IndyTFS January Meeting: These Guys Rawk!'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-8466237567817232481</id><published>2008-01-12T19:11:00.001-05:00</published><updated>2008-01-12T23:55:42.981-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>List of Links for Learning LINQ</title><content type='html'>&lt;p&gt;Since I often use this blog as a brain back-up device.&amp;#160; I will add another list of links, this time for learning LINQ.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx"&gt;Building a LINQ Provider&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/charlie/archive/2006/10/05/Links-to-LINQ.aspx"&gt;Links to LINQ (another link-post)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://aabs.wordpress.com/2006/12/15/how-linq-works-%e2%80%93-creating-queries/"&gt;How LINQ Works: Creating Queries&lt;/a&gt; (part of a series of great posts on &lt;a href="http://aabs.wordpress.com/linq/"&gt;LINQ internals&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb394939.aspx"&gt;The .NET Standard Query Operators&lt;/a&gt; (slightly out-of-date, but very relevant)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/bb399342.aspx"&gt;Standard Query Operator Translation (LINQ to SQL)&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-8466237567817232481?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/8466237567817232481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=8466237567817232481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8466237567817232481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/8466237567817232481'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/list-of-links-for-learning-linq.html' title='List of Links for Learning LINQ'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-9033686836009549715</id><published>2008-01-11T12:57:00.001-05:00</published><updated>2008-01-12T23:55:28.788-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>Happy 70th Birthday to Don Knuth</title><content type='html'>&lt;p&gt;I still haven't read The Art of Computer Programming, Volume 1, but I'm definitely an admirer of this man.&amp;#160; Here's to many, many more years where we are blessed to have him among us.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/christopher316/R4euF3skKqI/AAAAAAAAACg/EyVkqQY1m0o/knuth-sticker-0-show%5B4%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="527" alt="Don Knuth is my homeboy" src="http://lh5.google.com/christopher316/R4euGXskKrI/AAAAAAAAACo/4bCGgCHHaGs/knuth-sticker-0-show_thumb%5B2%5D" width="324" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-9033686836009549715?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/9033686836009549715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=9033686836009549715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9033686836009549715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/9033686836009549715'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/happy-70th-birthday-to-don-knuth.html' title='Happy 70th Birthday to Don Knuth'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6932169038133383242</id><published>2008-01-10T19:46:00.001-05:00</published><updated>2008-01-10T22:36:28.646-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='off-topic'/><title type='text'>A Twitter-style Blog Post from a User Group</title><content type='html'>&lt;p&gt;Larry Clarkin is a developer evangelist for Microsoft based out of Milwaukee.&amp;#160; He gave a talk this evening to the IndyNDA group at the Junior Achievement center on Keystone.&amp;#160; He spent the first twenty minutes of his talk showing us Microsoft's Virtual Earth maps site.&amp;#160; To use the Virtual Earth client libraries you need to include their script library and create a DIV to contain the map renderings.&amp;#160; A very informative site for learning Virtual Earth was demonstrated; it's called &lt;a href="http://dev.live.com/virtualearth/sdk/"&gt;&amp;quot;The Virtual Earth Interactive SDK&amp;quot;&lt;/a&gt;.&amp;#160; Very cool.&lt;/p&gt;  &lt;p&gt;He's showed us a pretty tame example of overlaying a Silverlight control on a Virtual Earth map.&amp;#160; The Silverlight control references the map via Javascript.&amp;#160; Pretty simple, but I believe the concept is solid.&amp;#160; You could really have a lot of fun with this approach.&lt;/p&gt;  &lt;p&gt;7:09pm and we've been enlightened that SOAP has lost the battle to REST on the public web.&amp;#160; Now we're getting some of the Twitter hype...&amp;#160; boring.&amp;#160; More Twitter, more boring.&amp;#160; I guess I just don't get Twitter. It seems like a way to fill the gaps when you are alone with yourself.&amp;#160; What's next--a microphone for your thoughts?&amp;#160; I will never waste my time reading that crap.&lt;/p&gt;  &lt;p&gt;7:23pm and we're learning that RSS is gee-wowie!&amp;#160; &amp;quot;We need more things like RSS.&amp;quot;&amp;#160; Good to know.&amp;#160; Larry likes Flickr.&lt;/p&gt;  &lt;p&gt;The guy sitting behind me has returned to his seat and reeks of cigarette smoke.&amp;#160; Joy!&lt;/p&gt;  &lt;p&gt;Oooh, now I'm learning how to get an ugly slideshow in Blend from a Flickr RSS feed.&amp;#160; It's 7:37pm and he's done--felt longer but under an hour.&lt;/p&gt;  &lt;p&gt;The highlight was hearing guys get excited about being able to update Twitter via SMS.&amp;#160; They thought, &amp;quot;Wow, I can point my applications at that feed and then send control codes via SMS.&amp;quot;&amp;#160; It feels like you should probably skip the middle-man.&amp;#160; Though, a free SMS to RSS gateway is a fun idea for homebrew mash-ups.&lt;/p&gt;  &lt;p&gt;Well, the pizza was better this time.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-6932169038133383242?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/6932169038133383242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=6932169038133383242' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6932169038133383242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/6932169038133383242'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/larry-clarkin-presents-to-indynda.html' title='A Twitter-style Blog Post from a User Group'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-4411188694434033473</id><published>2008-01-09T18:50:00.001-05:00</published><updated>2008-01-12T23:55:14.169-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TFS'/><title type='text'>TFS Build Failure: MSBuild Tool missing sgen.exe</title><content type='html'>&lt;p&gt;We're running TFS 2008 now at my client.&amp;#160; I installed the trial edition just to expedite things, as I'm not the one who works with the licenses.&amp;#160; (You can do an in-place upgrade of the trial to a live license.)&amp;#160; As I was getting the continuous integration build setup for our pilot project, I kept getting a build error similar to the following.&amp;#160; &lt;/p&gt;  &lt;pre&gt;error MSB3091: Task failed because &amp;quot;sgen.exe&amp;quot; was not found, or the correct Microsoft Windows SDK is not installed. The task is looking for &amp;quot;sgen.exe&amp;quot; in the &amp;quot;bin&amp;quot; subdirectory beneath the location specified in the InstallationFolder value of the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A. You may be able to solve the problem by doing one of the following:&amp;#160; 1) Install the Microsoft Windows SDK for Windows Server 2008 and .NET Framework 3.5.&amp;#160; 2) Install Visual Studio 2008.&amp;#160; 3) Manually set the above registry key to the correct location.&amp;#160; 4) Pass the correct location into the &amp;quot;ToolPath&amp;quot; parameter of the task.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Some extensive searching only yielded &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2466921&amp;amp;SiteID=1"&gt;this post&lt;/a&gt;, but I ignored the suggestion that followed the original posting... at first.&amp;#160; Turns out, it works quite fine.&amp;#160; Basically, you should have two registry keys under HKLM\SOFTWARE\Microsoft\Microsoft SDKs&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.google.com/christopher316/R4Vd4nskKoI/AAAAAAAAACQ/hJJQyi72p-w/image%5B6%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="107" alt="image" src="http://lh5.google.com/christopher316/R4Vd43skKpI/AAAAAAAAACY/y0xOuCBLPpA/image_thumb%5B4%5D" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The InstallationFolder value in the .NETFramework\v2.0 subkey is the thing we're after in the case.&amp;#160; Make an exact copy of that value under the Windows\V6.0A key.&amp;#160; I did this, as the &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2466921&amp;amp;SiteID=1"&gt;previously mentioned post suggested&lt;/a&gt;, and things worked fine!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Mas Importante!&amp;#160; You may need to install the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&amp;amp;displaylang=en"&gt;.NET Framework 2.0 SDK&lt;/a&gt; onto your TFS Server/Build Agent machine in order to do the above.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-4411188694434033473?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/4411188694434033473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=4411188694434033473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4411188694434033473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/4411188694434033473'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/tfs-build-failure-msbuild-tool-missing.html' title='TFS Build Failure: MSBuild Tool missing sgen.exe'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-5344644832694339866</id><published>2008-01-05T22:18:00.001-05:00</published><updated>2008-01-12T23:54:47.571-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Lambdas &amp; Closures in C# 3.0</title><content type='html'>&lt;p&gt;Here's some code the exhibits the creation of a closure in C#.&amp;#160; This was possible with the advent of anonymous delegates in C# 2.0, but it looks a lot cleaner in C# 3.0.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;&lt;br /&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Linq;&lt;br /&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Program&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public static void &lt;/span&gt;Main(&lt;span style="color: blue"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #2b91af"&gt;ClosuresWithLambdas &lt;/span&gt;a = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ClosuresWithLambdas&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;&amp;gt; fs = a.GetNumberFunctions();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; increments_i_func = fs[0];&lt;br /&gt;        &lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; just_returns_i_func = fs[1];&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: green"&gt;//prints 1&lt;br /&gt;        &lt;/span&gt;a.PrintReturnValue(increments_i_func);&lt;br /&gt;        &lt;span style="color: green"&gt;//prints 2&lt;br /&gt;        &lt;/span&gt;a.PrintReturnValue(just_returns_i_func);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ClosuresWithLambdas&lt;br /&gt;    &lt;/span&gt;{&lt;br /&gt;        &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;&amp;gt; GetNumberFunctions()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: green"&gt;//this variable gets included in the closure&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: blue"&gt;int &lt;/span&gt;j = 1;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: green"&gt;//we use this to return two functions&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;&amp;gt; fs = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;&amp;gt;(2);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: green"&gt;//don't get confused by the postfix operator&lt;br /&gt;            //the f lambda returns j BEFORE incrementing it&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; f = () =&amp;gt; j++;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: green"&gt;//g just returns the variable j&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; g = () =&amp;gt; j;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: green"&gt;//add the two functions to the list and return it&lt;br /&gt;            &lt;/span&gt;fs.Add(f);&lt;br /&gt;            fs.Add(g);&lt;br /&gt;            &lt;span style="color: blue"&gt;return &lt;/span&gt;fs;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;public void &lt;/span&gt;PrintReturnValue(&lt;span style="color: #2b91af"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; f)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(f());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This closure of which I speak is not immediately evident to the untrained eye.&amp;#160; The basic concept in this example is that the variable &amp;quot;j&amp;quot; has to survive past the end of its normal scope, i.e. the execution of GetNumberFunctions.&amp;#160; It has to survive because the two functions passed out of GetNumberFunctions--the lambdas &amp;quot;f&amp;quot; and &amp;quot;g&amp;quot;--refer to &amp;quot;j&amp;quot; outside of the function in which they were defined.&amp;#160; The compiler detects this (perfectly legal) reference as a &lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29"&gt;lexical closure&lt;/a&gt;; it generates a class to contain these functions and the variable &amp;quot;j&amp;quot;.&amp;#160; Here is that generated helper class viewed from Lutz Roeder's Reflector.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;[&lt;span style="color: #2b91af"&gt;CompilerGenerated&lt;/span&gt;]&lt;br /&gt;&lt;span style="color: blue"&gt;private sealed class &lt;/span&gt;&amp;lt;&amp;gt;c__DisplayClass2&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: green"&gt;// Fields&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;public int &lt;/span&gt;j;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: green"&gt;// Methods&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: blue"&gt;public int &lt;/span&gt;&amp;lt;GetNumberFunctions&amp;gt;b__0()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return this&lt;/span&gt;.j++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public int &lt;/span&gt;&amp;lt;GetNumberFunctions&amp;gt;b__1()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return this&lt;/span&gt;.j;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As you can probably gather b__0 is &amp;quot;f&amp;quot; and b__1 is &amp;quot;g&amp;quot; (or, &amp;quot;increments_i_func&amp;quot; and &amp;quot;just_returns_i_func&amp;quot; respectively).&amp;#160; They share &amp;quot;j&amp;quot; in the scope of an instance of this compiler generated sealed class instance.&amp;#160; There are other ways for language and compiler to implement closures, but this generated inner class works just fine.&amp;#160; For a practical example of using closures, please see my previous article on &lt;a href="http://iformattable.blogspot.com/2007/07/more-on-closures.html"&gt;doing asynchronous network I/O with closures&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-5344644832694339866?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/5344644832694339866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=5344644832694339866' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5344644832694339866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/5344644832694339866'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2008/01/lambdas-closures-in-c-30.html' title='Lambdas &amp;amp; Closures in C# 3.0'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3949579154967636694</id><published>2007-12-28T16:33:00.001-05:00</published><updated>2007-12-28T22:20:34.195-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>"Fixing" the Enter Key in CreateUserWizard</title><content type='html'>&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; You find that when you press the &amp;quot;Enter&amp;quot; or &amp;quot;Return&amp;quot; key on a page that contains the CreateUserStep of your CreateUserWizard (or any other step of any other wizard), your form does not get submitted.&amp;#160; Put another way, something else on the page gets triggered instead of your Create User button.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; In ASP.NET 2.0 the Page.Form has a new property: DefaultButton.&amp;#160; This effectively traps the Enter key and causes the specified button to execute its onclick event handler.&amp;#160; We would like to set this Page.Form.DefaultButton property to the UniqueID property of the CreateUserStep's Create User button.&amp;#160; Unfortunately, we do not have a reliable way of accessing this button in our code-behind.&amp;#160; The solution is to replace it with our own button and wire up the DefaultButton property in the button's pre-render event handler, since it is in a template and we cannot access it directly.&lt;/p&gt;  &lt;p&gt;In your .aspx add the following CustomNavigationTemplate to your CreateUserStep:&lt;/p&gt;  &lt;p&gt;&amp;lt;CustomNavigationTemplate &amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;asp:Button ID=&amp;quot;CreateUserButton&amp;quot; OnPreRender=&amp;quot;CreateUserButtonRender&amp;quot; runat=&amp;quot;server&amp;quot; Text=&amp;quot;Register User&amp;quot; CommandName=&amp;quot;MoveNext&amp;quot; ValidationGroup=&amp;quot;CreateUserWizard&amp;quot;/&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/CustomNavigationTemplate&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In your .aspx.cs add the following:&lt;/p&gt;  &lt;p&gt;protected void CreateUserButtonRender(object sender, EventArgs e)   &lt;br /&gt; {    &lt;br /&gt;&amp;#160; this.Page.Form.DefaultButton = (sender as Button).UniqueID;    &lt;br /&gt; }&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3949579154967636694?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3949579154967636694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3949579154967636694' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3949579154967636694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3949579154967636694'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2007/12/enter-key-in-createuserwizard.html' title='&amp;quot;Fixing&amp;quot; the Enter Key in CreateUserWizard'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-2840026743694907283</id><published>2007-12-26T19:00:00.001-05:00</published><updated>2007-12-26T19:00:44.278-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Choosing a Web Application Server Stack</title><content type='html'>&lt;p&gt;There's this great book entitled, &amp;quot;The Paradox of Choice: Why More Is Less,&amp;quot; that really opened my eyes to a rather non-intuitive way to improve my experience in life.&amp;#160; I won't go into it more than to say the author posits that there is an inflection point where &amp;quot;happiness&amp;quot; does not increase with additional accretion of choices.&amp;#160; This is non-intuitive, but he does a good job of explaining the many factors underlying this phenomenon.&amp;#160; For one, consider the opportunity cost of making a decision; you are buying what you consider the best at the time, but you are also carrying the burden of not having chosen from many other options.&amp;#160; Very often, buyer's remorse sets in after a purchase, and we have no one to blame but ourselves.&lt;/p&gt;  &lt;p&gt;So, as I tore through blogs, email archives, tutorials, and documentation today, looking for the &amp;quot;best&amp;quot; platform for my personal pet project, I became acutely aware of just how much choice there is available to build web applications these days.&amp;#160; The result is that it's very late in the day, my weekend spent, and I am writing this blog post to reason aloud, as it were, and to force myself to pick one.&lt;/p&gt;  &lt;p&gt;By way of introduction, let me say that my skill set falls squarely in the tried-and-true .NET 2.0 ASP.NET developer model.&amp;#160; I don't do MVC, MVP, Presenter First (PF), O/RM, TDD, DDD, BDD, or any other TLAs, except maybe DRY, SRP, and all those other solid OOP principles.&amp;#160; Also, I'm building this application for myself, by myself, and I can't seem to get a free copy of Visual Studio 2008, so .NET 3.5 and LINQ are out of reach.&amp;#160; I know I need forums, but that's about my only &amp;quot;requirement&amp;quot;.&amp;#160; Sure, I've got lots of ideas of what I'm going to build, but I am staring at the blank canvas right now.&lt;/p&gt;  &lt;p&gt;Here's the thing: I'm productive.&amp;#160; I build good applications.&amp;#160; I suspect that probably has more to do with my empathy and diligence rather than some prodigious development or architecture skills.&amp;#160; I'm certain I can get better at the latter, but my competitive advantage, if you will, comes from design good interactions.&amp;#160; I'm good a UI design and ideation.&amp;#160; And, frankly, all those TLAs are a bit intimidating, as is the prospect of writing so much more code.&lt;/p&gt;  &lt;p&gt;It may sound like I'm leaning toward an ASP.NET 2.0 application, so let me reflect on that.&amp;#160; I am definitely not going that direction.&amp;#160; The major strengths of that platform are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Tooling support---Visual Studio beats vim an SciTE hands down &lt;/li&gt;    &lt;li&gt;3rd-Party Controls---Telerik, Infragistics, etc. &lt;/li&gt;    &lt;li&gt;Familiarity---myself and thousands like me use it every day &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Those advantages sound great if you are an IT manager building line-of-business applications.&amp;#160; That's not me.&amp;#160; Among the disadvantages for me are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Mundane---I use it for a living and wouldn't be learning anything new &lt;/li&gt;    &lt;li&gt;Visual Studio 2005 is not free and the Express editions are...Express editions &lt;/li&gt;    &lt;li&gt;I won't be purchasing any 3rd-party controls &lt;/li&gt;    &lt;li&gt;The Page-based application model seems outmoded &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So, what are my options?&amp;#160; Well, I would like to try building an application using the MVC/MVP/PF paradigm.&amp;#160; I've invested many hours learning about it, and I want to take a stab at it.&amp;#160; This means, almost certainly, using an IoC container--but which one?&amp;#160; Also, MVC differs significantly from MVP as does PF; which shall I use?&amp;#160; I have to select an environment to do this all in as well.&lt;/p&gt;  &lt;h3&gt;Supervising Presenter First?&lt;/h3&gt;  &lt;p&gt;I have settled on &lt;a href="http://www.martinfowler.com/eaaDev/PassiveScreen.html"&gt;Presenter First&lt;/a&gt; (PF).&amp;#160; This doesn't have the widespread community support that MVC/MVP have today, which means less tooling and &amp;quot;free&amp;quot; functionality, but that's okay. PF takes SRP and the Humble Dialog to the extreme, forcing you to develop a testable presenter that reads like user stories and easily mocked views and models that can also be tested.&amp;#160; Because PF dictates an stateless and ignorant view, it should be easy to replace and change the UI.&amp;#160; Now, I can definitely say I won't be doing &amp;quot;pure&amp;quot; PF; I plan to allow tuples/ActiveRecord objects into my UI, because I want to use databinding and all the built-in goodness of ASP.NET when it is efficacious to do so.&amp;#160; In this sense, I want PF with &lt;a href="http://www.martinfowler.com/eaaDev/SupervisingPresenter.html"&gt;Supervising Controller&lt;/a&gt; leanings.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;h3&gt;Views: Plain-old Pages&lt;/h3&gt;  &lt;p&gt;I believe ASP.NET Pages are a very strong candidate for views, despite what I have heard from the ALT.NET crowd.&amp;#160; As a template engine, they are very mature; you can even nest master pages in 2008!&amp;#160; The ASP.NET Membership provider (Authentication, Authorization, Personalization, etc.), declarative security, and databinding are a few great things you get out-of-the-box.&amp;#160; There are lots of controls out there to work in ASP.NET Pages, including all the ASP.NET AJAX stuff.&amp;#160; This absolutely does force you to think about your views in terms of pages at some level, but I believe partial page updates allow user controls to be views as well.&lt;/p&gt;  &lt;h3&gt;Choosing a Framework&lt;/h3&gt;  &lt;p&gt;There are lots of choices out there for doing MVC/MVP style ASP.NET application, each with their own peculiar twists.&amp;#160; I have mentioned a couple of these before, but here are the ones I've looked at:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.springframework.net/"&gt;Spring.NET Framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://castleproject.org/monorail/index.html"&gt;MonoRail&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.cuyahoga-project.org/"&gt;Cuyahoga&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://asp.net/downloads/3.5-extensions/"&gt;ASP.NET MVC&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.ayende.com/Blog/archive/2007/09/03/Rhino-Igloo-ndash-MVC-Framework-for-Web-Forms.aspx"&gt;Rhino Igloo&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.codeplex.com/websf"&gt;Web Client Software Factory&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The main problem with each of these is that they are not PF pattern friendly.&amp;#160; That isn't to say that they are antagonistic, not at all.&amp;#160; I'm guessing, relatively blindly, that each of these would be equally difficult to implement PF.&amp;#160; So, what other criteria can I use to cull the herd?&amp;#160; Well, MonoRail doesn't play nice with ASP.NET Pages, so it's out.&amp;#160; Cuyahoga is a real pain in the butt to configure, quite possibly the longest &lt;a href="http://oodt.jpl.nasa.gov/better-web-app.mov"&gt;time-to-hello-world&lt;/a&gt; [&lt;em&gt;Note: ~400MB QuickTime movie about alternative web frameworks, including plone&lt;/em&gt;] of all these frameworks--gone!&amp;#160; Rhino Igloo has some very, very interesting ideas reminiscent of Guice and Spring javaconfig in its used of an InjectAttribute.&amp;#160; WCSF does this, too.&amp;#160; Both of these require that the request is made to and handled by the view (the Page), and they use DI tricks to get the Controller involved.&amp;#160; ASP.NET MVC is using an extensible URL rewrite feature to put the controller first.&amp;#160; This lets us be &lt;a href="http://ryandaigle.com/articles/2007/4/26/what-s-new-in-edge-rails-activeresource-gets-custom-methods"&gt;RESTful&lt;/a&gt; in addition to being PF-friendly, e.g. we can handle requests with our controller.&lt;/p&gt;  &lt;h3&gt;Continuations&lt;/h3&gt;  &lt;p&gt;My major complaint with all of these frameworks is that don't let me writing applications in a natural way.&amp;#160; I don't write my application in terms of logical processes, instead I implement page flows and deal with all &lt;a href="http://www.brainbell.com/tutorials/java/The_Problem.htm"&gt;the problems of stateless web applications&lt;/a&gt;.&amp;#160; In the nine years that I have been building web applications, my view of what a web application is and should be have changed a lot.&amp;#160; Now, I believe I have seen the promised land, as it were.&amp;#160; Web application servers and frameworks should allow me to develop my applications with logical continuations and take care of the plumbing for me.&lt;/p&gt;  &lt;h3&gt;REST + Continuations + Presenter First = ?&lt;/h3&gt;  &lt;p&gt;So, REST is good because it provides clean, bookmark-able URLs, a sort of coherent web-based command-line.&amp;#160; Continuations are good because they let me write applications that simply do not care that the next program event is dependent on transient sessions over a stateless protocol.&amp;#160; The Presenter First pattern is good because its raison d'&amp;#234;tre is making MVP more amenable to test-driven development.&amp;#160; Unfortunately, there are no ASP.NET web frameworks out there that take these three to be their cardinal virtues.&amp;#160; So, we'll just have to go invent our own.&lt;/p&gt;  &lt;p&gt;In a follow-up post to this one, I plan to introduce my prototype for just such a framework.&amp;#160; Utilizing some of the functionality of ASP.NET MVC and Windows Workflow Foundation, along with a lot of new code and concepts, I am building a prototype that I hope proves to be a huge evolution in web programming on the ASP.NET platform.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-2840026743694907283?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/2840026743694907283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=2840026743694907283' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2840026743694907283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/2840026743694907283'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2007/12/choosing-web-application-server-stack.html' title='Choosing a Web Application Server Stack'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-926571962834414157</id><published>2007-12-21T13:28:00.001-05:00</published><updated>2007-12-28T22:20:53.262-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>Liking LINQ: A Question of Efficacy</title><content type='html'>&lt;p&gt;Consider these two equivalent blocks of code.&amp;#160; First, the LINQ way:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="background: #181818; color: #8080c0"&gt;foreach&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;var &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assignable &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;in &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;from &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Assembly &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;a &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;in &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;BuildManager&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetReferencedAssemblies&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;()&lt;br /&gt;                           &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;select &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;a&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetTypes&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;() &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;into &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;types&lt;br /&gt;                           &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;from &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;t1 &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;in &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;types&lt;br /&gt;                           &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;where typeof&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;I&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;).&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;IsAssignableFrom&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;t1&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;)&lt;br /&gt;                           &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;select &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;t1&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;))&lt;br /&gt;         &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Cache&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;AddType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assignable&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Cache&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;ContainsType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assignable&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;) ? &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;DUPLICATE_TYPE &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;: &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assignable&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;And, the &amp;quot;normal way&amp;quot;:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="background: #181818; color: #8080c0"&gt;foreach &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Assembly &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assembly &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;in &lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;BuildManager&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetReferencedAssemblies&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;())&lt;br /&gt;     &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;foreach &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #c7c7f1"&gt;Type &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;in &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;assembly&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;GetTypes&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;())&lt;br /&gt;          &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;if &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;typeof&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;I&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;).&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;IsAssignableFrom&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;))&lt;br /&gt;          {&lt;br /&gt;                &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;if &lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(!&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Cache&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;ContainsType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;))&lt;br /&gt;                      &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Cache&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;AddType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;                &lt;/span&gt;&lt;span style="background: #181818; color: #8080c0"&gt;else&lt;br /&gt;                      &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Cache&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;AddType&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;(&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;type&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;.&lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;Name&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;, &lt;/span&gt;&lt;span style="background: #181818; color: #fef1a9"&gt;DUPLICATE_TYPE&lt;/span&gt;&lt;span style="background: #181818; color: #e0e0e0"&gt;);&lt;br /&gt;          }&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I cannot rightly make a judgement call on which way is better.&amp;#160; They have the same result.&amp;#160; Though, it is safe to say that normal way should perform better.&amp;#160; It is also clear, oddly, that the normal way has fewer lines of meaningful code; thus, it is easier to grok.&amp;#160; So, what do you think?&amp;#160; If you had to maintain the code base, which one would you prefer.&amp;#160; FWIW, I'm going to go with the normal way.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This leaves me with the question of efficacy.&amp;#160; Certainly there are niches where LINQ is superior, or the only option, but for general object collection work, should we just ignore this language feature?&amp;#160; Perhaps when PLINQ comes available we'll have a good reason to use it.&amp;#160; Time will tell.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-926571962834414157?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/926571962834414157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=926571962834414157' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/926571962834414157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/926571962834414157'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2007/12/liking-linq-question-of-efficacy.html' title='Liking LINQ: A Question of Efficacy'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-3015965025036094880</id><published>2007-12-21T13:11:00.001-05:00</published><updated>2007-12-21T13:11:47.800-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><title type='text'>SQL Optimization: Substring Joins</title><content type='html'>&lt;p&gt;The DBA at my current client has some mad T-SQL skills.&amp;#160; He took a na&amp;#239;ve join implementation I had written and improved its performance by three orders of magnitude.&lt;/p&gt;  &lt;p&gt;My initial query looked something like this:&lt;/p&gt; &lt;code&gt;SELECT A.*, B.* FROM A JOIN B ON A.Message LIKE '%' + B.Identifier + '%'&lt;/code&gt;   &lt;p&gt;Obviously this isn't the best situation in the first place. We don't have a clean relation between these two tables, instead we've got to pick out an identifier (GUID/uniqueidentifier) from a larger text field. Notwithstanding some obvious ETL or trigger possibilities, the statement above seems the simplest solution. The only problem is it is slooow.&lt;/p&gt;  &lt;p&gt;The DBA had a great optimization which was essentially to tease out the identifier from the field as you would if you were writing a trigger to create a join column. Putting this in your query allows you to join on this derived column in your code. The performance implications are well above what I would have guessed them to be, operating&amp;#8211;as I am&amp;#8211;from na&amp;#239;vet&amp;#233;. Here's the generalized solution based on our example above:&lt;/p&gt;  &lt;p&gt;&lt;code&gt;SELECT B.*, J.* FROM B JOIN      &lt;br /&gt;(       &lt;br /&gt;&amp;#160; SELECT A2.*,       &lt;br /&gt;&amp;#160; CAST(SUBSTRING(A2.Message, A2.GuidStart, A2.GuidEnd - A2.GuidStart) AS uniqueidentifier) AS JoinGuid       &lt;br /&gt;&amp;#160; FROM       &lt;br /&gt;&amp;#160; (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; SELECT A1.*,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; CHARINDEX('TokenAfterGuid', A1.Message, A1.Start) as GuidEnd       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; FROM       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SELECT A.*,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CHARINDEX('TokenBeforeGuid:', A.Message) + LEN('TokenBeforeGuid:') + 1 AS GuidStart       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FROM A       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ) AS A1       &lt;br /&gt;&amp;#160; ) AS A2       &lt;br /&gt;) ON B.Guid = J.JoinGuid &lt;/code&gt;&lt;/p&gt;  &lt;p&gt;Of course, you would expand the wildcard (*) references. This is really a great technique considering the performance ramifications. Certainly in our case, where the query was for a view, this was a wonderful improvement.&amp;#160; Obviously, the best option from a performance stand point would be to tease out the uniqueidentifier in an INSERT/UPDATE trigger, create an index on the new column, and join the tables on that; however, in situations where you don't have the option of doing ETL or triggers this can be useful.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6928325842095718321-3015965025036094880?l=iformattable.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iformattable.blogspot.com/feeds/3015965025036094880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6928325842095718321&amp;postID=3015965025036094880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3015965025036094880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6928325842095718321/posts/default/3015965025036094880'/><link rel='alternate' type='text/html' href='http://iformattable.blogspot.com/2007/12/sql-optimization-substring-joins.html' title='SQL Optimization: Substring Joins'/><author><name>Christopher</name><uri>http://www.blogger.com/profile/00936599699870104928</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-4hNVUbOPSeA/TwMXOGGD_OI/AAAAAAAAAIA/Kh2lx0GBsZY/s1600/39dc3c6e348c11e19896123138142014_7.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6928325842095718321.post-6957059930636211749</id><published>2007-12-16T02:08:00.001-05:00</published><updated>2007-12-16T02:08:08.351-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sql'/><category scheme='http://www.blogger.com/atom/ns#' term='linq'/><title type='text'>Liking LINQ: The Learning Curve</title><content type='html'>&lt;p&gt;This is the second post in a series on Language Integrated Query.&amp;#160; I'm pushing LINQ's buttons and bumping into some of its boundaries.&amp;#160; &lt;/p&gt;  &lt;p&gt;Every abstraction leaks at some point, and LINQ to SQL is no exception.&amp;#160; Consider the following code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext &lt;/span&gt;d = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt;(); &lt;br /&gt;&lt;span style="color: blue"&gt;int&lt;/span&gt;? quantityThreshold = &lt;span style="color: blue"&gt;null&lt;/span&gt;; &lt;br /&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;sales = &lt;span style="color: blue"&gt;from &lt;/span&gt;p &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Products &lt;br /&gt;&lt;span style="color: blue"&gt;join &lt;/span&gt;od &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Order_Details &lt;span style="color: blue"&gt;on &lt;/span&gt;p.ProductID &lt;span style="color: blue"&gt;equals &lt;/span&gt;od.ProductID &lt;br /&gt;&lt;span style="color: blue"&gt;where &lt;/span&gt;!p.Discontinued &amp;amp;&amp;amp; (quantityThreshold.HasValue ? od.Quantity &amp;gt;= quantityThreshold.Value : &lt;span style="color: blue"&gt;true&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: blue"&gt;select &lt;/span&gt;p;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, when you begin fetching data out of &amp;quot;sales&amp;quot; you'll see the problem.&amp;#160; A run-time error is thrown because the expression tree visitor attempts to greedily evaluate quantityThreshold.Value.&amp;#160; Let's try to move the evaluation out of the LINQ expression.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Predicate&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Order_Detail&lt;/span&gt;&amp;gt; hasSufficientQuantity = o =&amp;gt; quantityThreshold.HasValue ? o.Quantity &amp;gt;= quantityThreshold : &lt;span style="color: blue"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;sales = &lt;span style="color: blue"&gt;from &lt;/span&gt;p &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Products&lt;br /&gt;            &lt;span style="color: blue"&gt;join &lt;/span&gt;od &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Order_Details &lt;span style="color: blue"&gt;on &lt;/span&gt;p.ProductID &lt;span style="color: blue"&gt;equals &lt;/span&gt;od.ProductID&lt;br /&gt;            &lt;span style="color: blue"&gt;where &lt;/span&gt;!p.Discontinued &amp;amp;&amp;amp; hasSufficientQuantity.Invoke(od)&lt;br /&gt;            &lt;span style="color: blue"&gt;select &lt;/span&gt;p;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Well, that doesn't work either.&amp;#160; &amp;quot;The method or operation is not implemented.&amp;quot; The expression tree visitor has no idea what this hasSufficientQuantity method is... changing it to hasSufficientQuantity.Invoke(od) reveals that we are barking up the wrong tree, no pun intended.&amp;#160; The error given then is that our Predicate function cannot be translated.&amp;#160; Okay... let's look at why.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This fun LINQ expression syntax in C# is just syntactic sugar for a bunch of extension methods with signatures so jam-packed with Generics, you'd think it was Wal-Mart.&amp;#160; So, we are grateful to our C# language team for the sugar.&amp;#160; But, it does tend to hide what is really going on, making it difficult to figure out why the syntax seems so finicky.&amp;#160; Our LINQ expression above would translate into imperative code similar to the following:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;sales = d.Products.Join(d.Order_Details, p =&amp;gt; p.ProductID, o =&amp;gt; o.ProductID, (p, o) =&amp;gt; &lt;span style="color: blue"&gt;new &lt;/span&gt;{ Product = p, Order_Detail = o }).Where(p =&amp;gt; !p.Product.Discontinued &amp;amp;&amp;amp; hasSufficientQuantity.Invoke(p.Order_Detail)).Select(p =&amp;gt; p.Product);&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This isn't exactly pretty, and it doesn't really help us to understand why our function can't be translate, or does it?&amp;#160; Consider what these function calls are doing.&amp;#160; They are taking arguments, primarily Func&amp;lt;...&amp;gt; objects, and storing them internal in an expression tree.&amp;#160; We know from stepping through the code that the execution of our supplied Func&amp;lt;...&amp;gt; objects (the lambda expressions above) is deferred until we start accessing values from &amp;quot;sales&amp;quot;.&amp;#160; So, there must be some internal storage of our intent.&amp;#160; Further, the code above must be translated to SQL by the System.Data.Linq libraries, and we can gather from they call stack on our exception that they are using the Visitor pattern to translate the nodes of the expression tree into SQL statements.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What happens when they visit the node that calls invokes the hasSufficientQuantity Predicate?&amp;#160; Well, that code--the Preciate object instance itself--is not available in SQL, so the translation fails.&amp;#160; This seems obvious, but consider that if we were using LINQ to Objects here, any of these approaches would work fine, as the predicate would be available in the execution environment of the translated expression tree, where it wasn't for SQL.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is a contrived example, of course, and we could &amp;quot;code around&amp;quot; this in any number of ways, e.g.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;where &lt;/span&gt;!p.Discontinued &amp;amp;&amp;amp; od.Quantity &amp;gt;= (quantityThreshold ?? 0)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;However, we are still seeing the LINQ to SQL abstraction leak pretty severely.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There are some gotchas out there as well, of course.&amp;#160; Consider the following SQL statement that answers the question, &amp;quot;How many orders have my customers had for each of my products?&amp;quot;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;SELECT &lt;/span&gt;o.CustomerID, od.ProductID, &lt;span style="color: blue"&gt;COUNT&lt;/span&gt;(*) &lt;span style="color: blue"&gt;as &lt;/span&gt;[Number of Orders] &lt;br /&gt;&lt;span style="color: blue"&gt;FROM &lt;/span&gt;dbo.Orders o &lt;span style="color: blue"&gt;JOIN &lt;/span&gt;dbo.[Order Details] od &lt;br /&gt;    &lt;span style="color: blue"&gt;ON &lt;/span&gt;o.OrderID = od.OrderID &lt;br /&gt;&lt;span style="color: blue"&gt;GROUP BY &lt;/span&gt;od.ProductID, o.CustomerID&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;How might we attempt to answer the same question with LINQ to SQL?&amp;#160; Notice that we are specifying two columns to group by in our query.&amp;#160; Here's what we might &lt;strong&gt;like&lt;/strong&gt; to write in LINQ:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext &lt;/span&gt;d = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NorthwindDataContext&lt;/span&gt;();&lt;br /&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;results = &lt;span style="color: blue"&gt;from &lt;/span&gt;o &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Orders&lt;br /&gt;              &lt;span style="color: blue"&gt;join &lt;/span&gt;od &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Order_Details &lt;span style="color: blue"&gt;on &lt;/span&gt;o.OrderID &lt;span style="color: blue"&gt;equals &lt;/span&gt;od.OrderID&lt;br /&gt;              &lt;span style="color: blue"&gt;group by &lt;/span&gt;o.CustomerID, od.ProductID into g&lt;br /&gt;              select &lt;span style="color: blue"&gt;new &lt;/span&gt;{g.CustomerID, g.ProductID, g.Count()};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Of course, this doesn't even come close to compiling.&amp;#160; Here's the right way to do use multiple columns in a groupby: use a tuple!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;results = &lt;span style="color: blue"&gt;from &lt;/span&gt;od &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Order_Details&lt;br /&gt;              &lt;span style="color: blue"&gt;group &lt;/span&gt;od &lt;span style="color: blue"&gt;by new &lt;/span&gt;{od.Order.CustomerID, od.ProductID} &lt;span style="color: blue"&gt;into &lt;/span&gt;orders&lt;br /&gt;              &lt;span style="color: blue"&gt;select new &lt;/span&gt;{ orders.Key.CustomerID, orders.Key.ProductID, NumberOfOrders = orders.Count() };&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Once you start getting the gestalt of LINQ, you'll find yourself creating tuples all over the place.&amp;#160; Consider this query expression to retrieve the total sales of each product in each territory:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;territorySales = &lt;span style="color: blue"&gt;from &lt;/span&gt;p &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Products&lt;br /&gt;                     &lt;span style="color: blue"&gt;join &lt;/span&gt;od &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Order_Details &lt;span style="color: blue"&gt;on &lt;/span&gt;p.ProductID &lt;span style="color: blue"&gt;equals &lt;/span&gt;od.ProductID&lt;br /&gt;                     &lt;span style="color: blue"&gt;join &lt;/span&gt;o &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Orders &lt;span style="color: blue"&gt;on &lt;/span&gt;od.OrderID &lt;span style="color: blue"&gt;equals &lt;/span&gt;o.OrderID&lt;br /&gt;                     &lt;span style="color: blue"&gt;join &lt;/span&gt;e &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Employees &lt;span style="color: blue"&gt;on &lt;/span&gt;o.EmployeeID &lt;span style="color: blue"&gt;equals &lt;/span&gt;e.EmployeeID&lt;br /&gt;                     &lt;span style="color: blue"&gt;join &lt;/span&gt;et &lt;span style="color: blue"&gt;in &lt;/span&gt;d.EmployeeTerritories &lt;span style="color: blue"&gt;on &lt;/span&gt;e.EmployeeID &lt;span style="color: blue"&gt;equals &lt;/span&gt;et.EmployeeID&lt;br /&gt;                     &lt;span style="color: blue"&gt;join &lt;/span&gt;t &lt;span style="color: blue"&gt;in &lt;/span&gt;d.Territories &lt;span style="color: blue"&gt;on &lt;/span&gt;et.TerritoryID &lt;span style="color: blue"&gt;equals &lt;/span&gt;t.TerritoryID&lt;br /&gt;                     &lt;span style="color: 
