<?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-6794675998088145034</id><updated>2012-01-28T22:37:59.705Z</updated><category term='Mocks'/><category term='london marathon'/><category term='Lean'/><category term='DLR'/><category term='marathon'/><category term='value'/><category term='Domain Driven Design'/><category term='chariry'/><category term='Women in IT'/><category term='XP'/><category term='patterns'/><category term='Code Smells'/><category term='UX'/><category term='ALT.NET'/><category term='Build'/><category term='ThoughtWorks'/><category term='specification pattern'/><category term='OO'/><category term='fluent interface'/><category term='sponsor'/><category term='Refactoring'/><category term='C#'/><category term='TDD'/><category term='Agile'/><category term='BDD'/><category term='mono'/><category term='Encapsulation'/><category term='breaks4kids'/><title type='text'>Jupiter Moonbeam &amp; the Geeks from Cyberspace</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6774264014149498049</id><published>2010-10-01T07:37:00.000+01:00</published><updated>2010-10-01T07:37:22.479+01:00</updated><title type='text'>I am NOT a geek</title><content type='html'>I am writing this due to provocation by an number of colleagues who seem intent on labelling me as a Geek.  Making claim to bullying of this character in a technical organization such as ThoughtWorks may sound implausible but my public derision finds root in the rallying call I made (on an internal mailing list): I AM NOT A GEEK.&lt;br /&gt;&lt;br /&gt;So why would a respected developer such as myself risk a well earned reputation with such a perilous statement?  And then why would I go onto circulate the claim amongst the wider community of readers on the ThoughtWorks blog roll (I am still on it aren't I?)?&lt;br /&gt;&lt;br /&gt;It has been a dark secret that I have been keeping from all but my closest colleagues; only my friends and family have really ever known the truth.  Coming out of the closet on an internal mailing list may have been tough, but - apart from the odd comment from the usually insensitive and ignorant (well emotional intelligence was never the geeks strong point) - it has been a liberating experience.  No longer do I have to pretend that I actually care about the resolution of iPhones versus HTCs, no longer do I have to feign interest in the difference between the generics implementation in Java and dotnet.  And, for the first time in my career, I have felt that I could style my hair in a moderately fashionable manner.  And the support has been incredible: BAs and QAs and even other devs have quite literally wrapped their arms around me in deep sympathy to confess that they too couldn't work out what pub everyone was meeting at every night until they twigged that all the socializing occurred within the realms of the World of Warcraft servers.&lt;br /&gt;&lt;br /&gt;Though one cannot make such a claim as I have without some hard evidence.  After all, over a decade in the IT industry would suggest that my declaration is fraudulent.  But no, the truth is that my participation in the geek subculture is limited at best.  I don't like science fiction or fantasy, I find Lord of the Rings far fetched and ridiculous, I own not a single gadget (no honestly not even a fancy phone), I perceive the playing of computer games to be a waste of my life, I don't like Star Wars (but I want to ride my bicycle).  On the other hand I like being outside - especially if involved sport - adore music (and no, not Heavy Metal), enjoy the company of others and I can relate to women.  Some may go as far as describing me as a "people person".&lt;br /&gt;&lt;br /&gt;To sum it up, once out of the workplace, technology plays a very minor role in my life, except in the places where I can leverage it as an enabler (for typing this blog on, or finding cinema times on the Internet).  Careful not to misconstrue me: I believe technology is a great enabler for many things, from opening information to social justice.  As a power in society it is arguably the single greatest development since the printing press.  However, if it all disappeared overnight would I cry?  If I was born fifty years ago would I have struggled to find my calling in life?  No, no and definitely no.  So hence my assertion: I AM NOT A GEEK.&lt;br /&gt;&lt;br /&gt;Please, before you make your judgement to find my decision wise or foolish, let me impart you with my reasoning.  Firstly I hope my actions will path the way for others, but also, I believe this selfless acts of hari kari will be the catalyst to make our industry a better place.&lt;br /&gt;&lt;br /&gt;Within our great industry there is a template, an expectation, a stereo-type if you like, of what a typical IT worker should be.  So deep it is within the culture I should not need to draw this caricature in too much detail but, let's throw some words out there: spotty, socially awkward, coffee drinking, light hating, arrogant, emotionally unintelligent male that spits when he talks and is probably wearing a t-shirt - for several days and smelling a bit - with some witticism along the lines of '/me 0mwz j00' or something equally as mystical - possibly even written in Klingon - to the majority of society.  For cultural references consult The IT Crowd, that Russian guy in that James Bond film, Big Bang Theory or any other computer guy you can think of in any mainstream film or TV comedy.&lt;br /&gt;&lt;br /&gt;Before continuing let me state, on the record, that the number of individuals I find that meet this template in IT are ever decreasing.  Of course it was considerably greater a decade ago when they locked us in the basement but since we've been allowed to occupy floors that let in natural light, like Gremlins, they've bubbled up and exploded (I believe getting them wet was equally dangerous).&lt;br /&gt;&lt;br /&gt;Regardless, the stereotype still persists.  My concern is this stereotype is a barrier to the IT industry reaching its full potential.  It has a number of negative effects: it deters potentially able people from the industry (women for example, but not exclusively); it normalizes a set of behaviours which are damaging; and it prevents peoples development by narrowing their horizons to a limited template.    &lt;br /&gt;&lt;br /&gt;Though there are people out there who not only relate to the stereotype but will defend its place within the unique culture of IT.  They will state that the attributes to be good with technology are exclusive to geeks and therefore they are the best people to run IT - yet looking at the state of the industry I'd say you've not done a very good job so get out of the way and let someone else have a go.  But this is a complete fabrication.  Without trying too hard to burst the whole indulgent We are Special myth and point out that lots of normal people in other industries have these skills in abundance too there truth is that there are many skills that IT people, in particular developers need, to enable technology in a manner that brings value to the business which are both arguably more important and that the stereotypical geek lacks; whether communication skills, awareness of business, empathy and understanding for users, prioritization, even the ability to solve problems WITHOUT technology. Of all of the key skills those attributed to the geekier sensibilities are, in modern development, the least critical.  Wizzy maths and clever algorithms do not form the heart of the vast majority of software.  Thanks to the Agile movement and things like BDD and Domain Driven Design, the business is at the heart of software development.  &lt;br /&gt;&lt;br /&gt;Modern software places the emphasis on those other skills that the stereotypical geek doesn't tend to have.  Normal people on the other hand do.  And what's more, plenty of normal people have those other problem solving skills that geeks believed made them stand out - I'm sorry but attention to detail, inquisitive nature, analytical skills, logical thinking, problem solving etc. are not, and never have been, attributes exclusive to the introverted middle class white male plagued by OCD and touched by autism.  The simple truth is that non-geeks can and do make great developers and often even better developers than geeks (in fact some of the worst developers I've worked with in my career have been the geekiest and the inverse has also been true).  &lt;br /&gt;&lt;br /&gt;Let me restate this for crystal clarity: you do NOT need to be a geek to be a great developer; you don't even need to be a bit of a geek - not even give into the odd geeky impulse and no, no, no you don't even need to try and fit in and do geeky stuff - 'cos it doesn't make one tiny bit of difference to how good you are as a developer.&lt;br /&gt;&lt;br /&gt;In a by-gone age when geeks were the main consumers of technology then the natural geek instinct of the developer was enough to satisfy any demands the audience may have.  One bunch of geeks produced stuff for other geeks to consume.  What the first geeks produced made perfect sense to the other geeks.  But that isn't true any more.  Geeks are a minority of users.  Do you want evidence?  Go and look at how many users are running Linux (no true geek would run Windows): the number is insignificant.  The majority of technology in the majority of the world is used by non-geeks.  &lt;br /&gt;&lt;br /&gt;To write effective software for non-geeks you need people who understand them, and unfortunately geeks tend not to.  The things that geeks prioritize are often not what non-geeks prioritize.  Remember when everyone derided Macs for being 'simple' and how dumb Apple users were because they couldn't manage more than one mouse button, whilst MS covered every possible surface of the mouse with different ways to click and Opera invented 'mouse gestures' (yes, only a geek could have done that).  And then Apple go and produce a music product with only one button and a wheel?  What geek would have come up with that idea?  No, that required someone who understood how normal people want to interact with a music player (the geek stood back in shock that normal people could manage to rip, manage and sync their CD collection without any guidance just because were given an interface that made sense).&lt;br /&gt;&lt;br /&gt;Now my tirade is over, my blows made, wounds inflicted, oil spilt and lit, I wish to make my peace.  The future of IT and software development needs to be one where the creativity, the passion, the human element of building brilliant software and the skills and attributes required to achieve this are encouraged and nurtured regardless of it's source, geek or non-geek.  The industry must stop holding the geek up as the exemplar and alienating, or degrading, those that do not meet or wish to conform with this caste.  With each generation IT moves further into the consciousness of the mainstream and in doing so its appeal will grow beyond those great pioneers, the geeks, upon which today's industry is founded.  &lt;br /&gt;&lt;br /&gt;So here's to an industry which attracts the brightest and the best from the entire psychological and sociological spectrum and a long overdue fairwell to that which limits it to that one tiny, specific character with its limited range of skills.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6774264014149498049?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6774264014149498049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6774264014149498049' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6774264014149498049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6774264014149498049'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/10/i-am-not-geek.html' title='I am NOT a geek'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-2269403098970287579</id><published>2010-04-26T17:09:00.003+01:00</published><updated>2010-04-26T17:17:33.322+01:00</updated><title type='text'>UK politics and the battle between Old and Social Media</title><content type='html'>Firstly this content is about politics. &amp;nbsp;Though the purpose of the post is not to 'push' any specific political agenda but to examine the role&amp;nbsp;social media has played in the&amp;nbsp;sudden, and unexpected rise, of the Liberal Democrats&amp;nbsp;and how that too has impacted the 'old' media.&lt;br /&gt;&lt;br /&gt;For those of you reading this who are not in touch with the current affairs in the UK, currently there is a general election being held it appeared that the 13 year majority of the current Labour government would be seriously contested by the opposition Conservative party. &amp;nbsp;Then, on the 15th April, the UKs first live televised debate went out with the three main leaders. &amp;nbsp;The result was that the previously marginal Liberal Democrat party were &lt;a href="http://www.bloomberg.com/apps/news?sid=a8_JJ.88zHqs&amp;amp;pid=20601087"&gt;declared the outright winners&lt;/a&gt;. &amp;nbsp;All hell broke loose.&lt;br /&gt;&lt;br /&gt;The TV debates are an historic first for the UK but something else that is also a historic first is the use of social media. &amp;nbsp;Of course, over in the US, the effective use of social media gave it &lt;a href="http://webtrends.about.com/b/2008/11/06/did-social-media-win-obama-the-presidency.htm"&gt;claim to Obama's victory&lt;/a&gt;. &amp;nbsp;I don't think that this was a fact ignored by the election teams in the UK as politicians ran to pick up their own Twitter accounts and Facebook profiles but the nature of on the &lt;a href="http://blogs.reuters.com/great-debate-uk/2010/04/22/uk-political-parties-take-mixed-approach-to-social-media"&gt;ground campaigning hasn't altered quite so dramaticall&lt;/a&gt;y.&lt;br /&gt;&lt;br /&gt;Traditionally, in the UK, the main stream press has held &lt;a href="http://en.wikipedia.org/wiki/It%27s_The_Sun_Wot_Won_It"&gt;the single greatest influence over elections&lt;/a&gt; and this sudden swing is evidence that their grip is breaking. &amp;nbsp;There is no doubting that the televised debates have been the single biggest influencer in the dramatic shift in political ground over the last two weeks however there is a real &lt;a href="http://www.guardian.co.uk/media/2010/apr/26/election-2010-sun-twitter"&gt;war between social media and the mainstream press&lt;/a&gt;. &amp;nbsp;After all, the UK has taken fondly to social media, being only second behind the US and with &lt;a href="http://www.blogherald.com/2009/08/06/london-is-twitters-top-city/"&gt;London having the highest percentage of Twitter users&lt;/a&gt; than any other city.&lt;br /&gt;&lt;br /&gt;Although it is easy for some in the press to dismiss social media users the intensity of UK usage compared to other countries is no doubt going to have an impact on the end result.&lt;br /&gt;&lt;br /&gt;Real evidence of this was available even before the first leaders debate had finished. &amp;nbsp;Looking at what was trending on Twitter gave a solid prediction of the outcome. &amp;nbsp;Nick Clegg was far in front with Cameron and Brown just nipping in at the bottom of the top ten terms. &amp;nbsp;Ironically Clegg was kept off the top spot by the hash tag &lt;a href="http://twitter.com/#search?q=%23iagreewithnick"&gt;#iagreewithnick&lt;/a&gt;. &amp;nbsp;A few minutes after the debate had finished Nick Robinson delivered the catchphrase live on BBC. &amp;nbsp;For Twitter users he was only confirming what they'd known for the last ninety minutes.&lt;br /&gt;&lt;br /&gt;It was in the week after the first leaders debate when the power of social networking was truly demonstrated. &amp;nbsp;After Cleggs surpirse win the right wing press went into overdrive to discredit the new upstart. &amp;nbsp;What resulted was a &lt;a href="http://www.bbc.co.uk/blogs/nickrobinson/2010/04/one_good_smear.html"&gt;simultaneous barrage&lt;/a&gt; of &lt;a href="http://www.youtube.com/watch?v=J8coHSQ49q0"&gt;front page smear campaigns&lt;/a&gt; across the four main right wing papers (Daily Mail, Daily Express, Daily Telegraph, Sun). &amp;nbsp;Twitter users reacted instantly with disdainful satire by manufacturing a series of ridiculous claims and blaming them on Clegg. &amp;nbsp;Before lunch time the same day &lt;a href="http://twitter.com/#search?q=%23nickcleggsfault"&gt;#nickcleggsfault&lt;/a&gt; was the &lt;a href="http://www.bbc.co.uk/blogs/thereporters/rorycellanjones/2010/04/its_all_nick_cleggs_fault.html"&gt;highest trending hashtag&lt;/a&gt;.&amp;nbsp;&amp;nbsp;And it stayed there, trumping even #leadersdebate, for several days. &amp;nbsp;Even if the press couldn't pick up on the subtleties of that then the fact that "&lt;a href="http://twitter.com/#search?q=%23Murdoch%20Lose%20Britain"&gt;murdoch lose britain&lt;/a&gt;" was trending a few positions &amp;nbsp;behind should have been a clear enough message.&lt;br /&gt;&lt;br /&gt;Then the Murdochractic media made its second mistake when &amp;nbsp;Sky TVs host Adam Boulton questioned Clegg on one of those very front pages. &amp;nbsp;It was outside the rules and hundreds of tweets popped up within seconds protesting against it. &amp;nbsp;These soon translated into over &lt;a href="http://www.guardian.co.uk/media/2010/apr/23/leaders-debate-complaints-nick-clegg"&gt;100 complaints to Ofcom&lt;/a&gt;&amp;nbsp;and of course news coverage of the slight. &amp;nbsp;From that moment Twitter had a microscope over Sky's coverage of Clegg and was even accusing Sky of deliberately 'cutting' Cleggs shots so he couldn't 'look into the camera' whilst giving Cameron more opportunity to do so. &amp;nbsp;Of course this is pure conspiracy but it was a small enough seed of doubt that people believed deserved to be retweeted.&lt;br /&gt;&lt;br /&gt;And this seed of doubt had serious consequences. &amp;nbsp;Once Sky announced that YouGov had David Cameron in first place Twitter &lt;a href="http://twitpic.com/1hla5j"&gt;reacted with disbelief&lt;/a&gt;. &amp;nbsp;Within seconds people were posting that they'd taken part in the YouGov poll and felt it was biased, they were even posting screenshots of the &lt;a href="http://twitpic.com/1hm9fn"&gt;survey to prove it&lt;/a&gt;. &amp;nbsp;This lead to &lt;a href="http://www.craigmurray.org.uk/archives/2010/04/yougovmurdoch_d.html"&gt;accusations&lt;/a&gt; of &lt;a href="http://www.libdemvoice.org/are-yougov-and-murdoch-pushpolling-for-the-tories-18997.html"&gt;'push-polling'&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And it didn't end there. &amp;nbsp;The day after the Daily Mail were claiming on their home page that their polls showed that Cameron came out on top. &amp;nbsp;But a Twitter user had observed that the Mail had withdrawn their original survey which had &lt;a href="http://refpls.wordpress.com/2010/04/23/daily-mail-rigs-poll"&gt;Clegg top and republished it&lt;/a&gt;. &amp;nbsp;The result was a Twitter call for poll-jacking to put the numbers 'right' (which they eventually did).&lt;br /&gt;&lt;br /&gt;What is interesting about all the above is how UKs Right Wing press inadvertently waged war with social media users. &amp;nbsp;The press forced people into camps: with us or against us, and to against us was to be with Clegg. &amp;nbsp; And so social media users reacted in the same way they had against what they perceived as the mainstream bullying and manipulation of Simon Cowell by campaigning to deny him the Christmas number one by replacing it with Rage Against The Machine anthem&amp;nbsp;&lt;i&gt;"Fuck You I won't do what you tell me".&lt;/i&gt;&amp;nbsp;&amp;nbsp;Except this time they are reacting against the Right Wing Press and Clegg is their Rage. &amp;nbsp;Evidence? &amp;nbsp;Well a facebook group called &lt;a href="http://www.facebook.com/group.php?gid=113749985304255"&gt;"We got Rage Against the Machine to #1, we can get the Lib Dems into office!"&lt;/a&gt; that has already collected over 150,000 members - which is more than any political party.&lt;br /&gt;&lt;br /&gt;Why did they make such an error? &amp;nbsp;Well perhaps it's because the press like to dismiss social networking as something for 'young people' and 'young people' &lt;a href="http://blogs.pressgazette.co.uk/fleetstreet/2006/11/12/naughton-on-young-people-and-newspaper-readership/"&gt;don't read newspapers&lt;/a&gt;&amp;nbsp;and, so they thought, &lt;a href="http://news.bbc.co.uk/1/hi/education/2699275.stm"&gt;young people don't vote&lt;/a&gt;. &amp;nbsp;But, thanks to social networking, a kick-back against the 'old' media and a some dramatic TV coverage it looks like &lt;a href="http://www.guardian.co.uk/commentisfree/2010/apr/26/election-youth-vote-clegg-registration"&gt;that all might change&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Of course the truth will out on May 6th when people turn out to vote. &amp;nbsp; The Right Wing press still hold considerable influence over the British public, let's not forget that social networkers are a specific, though not insignificant,&amp;nbsp;demographic. But, though it's hard, look behind the politics and you'll see, just like the XFactor Christmas single, there is a clear theme from the 'internet generation' that they won't be dictated to by the traditional media and now, thanks to social media, they can quickly mobilize and &lt;a href="http://twitter.com/#search?q=%23disobeymurdoch"&gt;push back&lt;/a&gt;. &amp;nbsp;Perhaps the press should take warning from the Rage campaign, because when they do push back, they push back on mass, and they &lt;a href="http://www.twitvoteuk.org.uk/"&gt;push back hard&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-2269403098970287579?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/2269403098970287579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=2269403098970287579' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2269403098970287579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2269403098970287579'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/04/uk-politics-and-battle-between-old-and.html' title='UK politics and the battle between Old and Social Media'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6752961256742593874</id><published>2010-04-09T11:56:00.000+01:00</published><updated>2010-04-09T11:56:49.780+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UX'/><title type='text'>nPower and my UX nightmare</title><content type='html'>I saw npowers new Wallace and Gromit ads for their energy monitoring device. &amp;nbsp;Apparently just ask and you'll get one. &amp;nbsp;Brilliant. &amp;nbsp;After lots and lots of web searching and scratching of heads I found out the way to do it is register for a paperless billing (which I was already on) - this is of course once I'd worked out how to log in (tip: &lt;a href="http://www.npower.com/"&gt;tiny link top left corner in a sea of red&lt;/a&gt;). &amp;nbsp;More confusion and then I find you just have to edit your details (it took me a couple of reads of the clearly written English to work this out):&lt;br /&gt;&lt;blockquote&gt;To request a FREE smartpower electricity monitor, set up paperless billing, or activate other smartpower options, simply add or edit your account details now&amp;nbsp;&lt;/blockquote&gt;First, what's wrong here? &amp;nbsp;Do an ad campaign and then make it hard for existing customers to follow through? You'd at least thought that all you have to do is log into your account and see a picture of Wallace and Gromit inviting you to click the big Apply for Smart Power Monitor? &amp;nbsp;No? &amp;nbsp;Well, obviously the marketing guys at nPower don't think so.&lt;br /&gt;&lt;br /&gt;But it gets worse. &amp;nbsp;I try to edit my details and the page blows up with a load of error messages about missing information. &amp;nbsp;But there's only check boxes, the stuff that's missing is your account details? Huh? There's no place to enter them either (and why do I need to enter something you should already know)? &amp;nbsp; So I try to re-register for paperless (I think I'm smart here, I'll disable it then re-enable it). &amp;nbsp;This time the fields it moaned about not being filled in are there and blank and apparantly I have to refer to the bill npower sent me for the details (even though they are all on the previous page next to the link I clicked to get here). &amp;nbsp;But it blows up, this time horredously, logs me out and gives me a 'sorry, our system appears to be experiencing problems'. &amp;nbsp;You don't say.&lt;br /&gt;&lt;br /&gt;So I email npower to ask them to sort it out. &amp;nbsp;Explain clearly that the website keeps blowing up every time I try register for the monitor and ask them if they could just sort it out for me behind the scenes. &amp;nbsp;A few days later I get this reply:&lt;br /&gt;&lt;blockquote&gt; &lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; border-collapse: separate; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px;"&gt;I have lokked into this for you and customer do have to apply for the smart power monitor on line please follow the information below to apply ofyou still have issues please call our web support team direct on 08451663443.&lt;/span&gt;&lt;/span&gt; &amp;nbsp;&lt;/blockquote&gt;Did they read my message? &amp;nbsp;Did they read there's before sending it? Can they read? &amp;nbsp;They certainly can't write. &amp;nbsp;Great customer service nPower. &amp;nbsp;I feel really valued. &amp;nbsp;Well done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6752961256742593874?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6752961256742593874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6752961256742593874' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6752961256742593874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6752961256742593874'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/04/npower-and-my-ux-nightmare.html' title='nPower and my UX nightmare'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8770707585421528847</id><published>2010-03-11T10:24:00.001Z</published><updated>2010-03-11T10:26:04.771Z</updated><title type='text'>A Thoroughly Modern Developer</title><content type='html'>The world of development has changed rapidly over the last decade or so. &amp;nbsp;Thanks to Agile, great tools such as TDD, O/R mapping, dynamic and functional languages and a million other little things, the way companies approach development is changing. &amp;nbsp;A bright new future awaits where only the true veterans wince as the CEO discusses going waterfall when promoting the merits of the new hydroelectric generator.&lt;br /&gt;&lt;br /&gt;Inevitably, as development changes so will developers need to adapt. &amp;nbsp;The stereotype of a socially awkward, green screen loving, mouse hating, hacker who wears black-now-grey jeans and t-shirts that state "127.0.0.1 is where the heart is" for a week at a time and mumbles through the pizza crumbs that drop in piles from his beard onto his ever rounding belly, is not going to cut it in this new world. &amp;nbsp;Future projects will be run on the basis of success and that means you can't forgive someone's shortcomings because they are a "code wizard".&lt;br /&gt;&lt;br /&gt;So what sort of developer does cut it at the beginning of this new decade? &amp;nbsp;What sort of skills are you going to need? &amp;nbsp;Well, funny you should ask-&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Domain Knowledge&lt;/h2&gt;Or, knowledge of the business you are working for. &amp;nbsp;Systems are more complex than ever and businesses increasingly rely on them. &amp;nbsp;Regardless of the general mistrust of IT it has moved right into the heart of business, providing the engine, one without which many businesses couldn't survive.&lt;br /&gt;To build successful systems The Thoroughly Modern Developer has a thorough knowledge of the businesses intention and the value being delivered; it isn't good enough to rely on a BA and a Development Manager to 'translate' business speak into dev syntax.&lt;br /&gt;&lt;br /&gt;Eric Evans goes into this in detail in Domain Driven Design. &amp;nbsp;Designing and building a system is a collaborative effort between the domain experts and the developers to create a common model (or a ubiquitous language). &amp;nbsp;If you don't understand the business how can you model it? &amp;nbsp;But it goes further than that; if you don't understand the business value how can you deliver it?&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;QA&lt;/h2&gt;Back in the old days testing meant running up the app, clicking a couple of times and then waiting a month or two before the testing team raised a list of bugs for the junior devs to pick up and fix. &amp;nbsp;It took XP to change our attitudes on this. &amp;nbsp;TDD meant we wrote unit tests and verified our systems with at least some code. &amp;nbsp;Agile put QAs at the heart of the development process and bugs where fixed at the end of every iteration, but the 'throw it over the wall' principle was still there, just shorter.&lt;br /&gt;&lt;br /&gt;The Thoroughly Modern Developer takes responsibility for her own quality, she cares more about meeting the acceptance criteria in a bug free fashion than anything else. &amp;nbsp;This makes the QA's role even more critical as they must &lt;a href="http://christianralph.blogspot.com/2010/02/menage-trois-in-kinky-teams.html"&gt;continuously guide and help the dev&lt;/a&gt; but they will no longer be reduced to simply checking they've done the work.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Usability&lt;/h2&gt;The average developers idea of building something usable is akin to [the car Homer designed]. &amp;nbsp;For some strange reason even the simplest of tasks, such as getting a column of text boxes to line up, seems to be a feat of incredible endurance.&lt;br /&gt;&lt;br /&gt;But usability is crucial. &amp;nbsp;The first developer I ever worked for told me The users don't care about how clean and beautiful your code is, they never see it, but the smallest spelling mistake on the UI and they're on the phone.&lt;br /&gt;&lt;br /&gt;The Thoroughly Modern Developer builds systems with usability in mind from the start. &amp;nbsp;Sure, she's no expert - but she knows enough simple rules to get her by - so she works closely with the UX person to ensure what is being produced is usable not just functional.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Polyglot&lt;/h2&gt;The Thoroughly Modern Developer does not define her role or skillset around a single language (or worse, a single toolkit - i.e. ASP.NET Developer). &lt;br /&gt;&lt;br /&gt;She is language agnostic, and she has experience of a number of different languages, using different paradigms (OOP, functional, dynamic etc.) and her level of understanding goes beyond syntax. &lt;br /&gt;The Thoroughly Modern Developer will choose the best tool for the job or circumstance. &amp;nbsp;Throw her a language she's never worked in and she has no issues about picking it up. &amp;nbsp;Or put her on a project where she's expected to work in two or more different languages and she isn't phased.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://en.wikipedia.org/wiki/Code_Complete"&gt;Code Complete&lt;/a&gt; Steve McConnell&amp;nbsp;talks about Programming "into" a langague over programming "in" a language. &amp;nbsp;The Thoroughly Modern Developer does the former.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Value Driven&lt;/h2&gt;To every new feature, ever request, every line of code, the Thoroughly Modern Developer asks the same question: how does this deliver value or what's the value of doing this? &amp;nbsp;She's obsessed, she keeps going on about it, it's all most as if it's all she cares about.&lt;br /&gt;&lt;br /&gt;Which it is of course. &amp;nbsp;To the Thoroughly Modern Developer value is the sole purpose of her job.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;A People Person&lt;/h2&gt;Oh yes, it's that horrible phrase, one that causes many devs of old to run away and hide behind a wall of cabinets filled with specification documents. &amp;nbsp;The Thoroughly Modern Developer, on the other hand, likes people, gets on with people, can talk to people. &amp;nbsp;She doesn't need 'Relationship Managers' or 'Business Interfacers'; put her in a room full of real people and she'll hold her own without spitting when she talks or snorting Beavis and Buthead style when someone uses any word, or collection of words, which bear a vague resemblance to bodily functions.&lt;br /&gt;&lt;br /&gt;Why is the Thoroughly Modern Developer such a people person? &amp;nbsp;Because she understands that in order to build quality software, that delivers business value she needs to talk to people, all different sorts of people, all the time. &amp;nbsp;Whether it's to find out whether the button should say Save or Create or to explain to non-technical people why it took longer to integrate the zobertron with the phlargbleg initiator (of course the Thoroughly Modern Developer would never have come up with those names but she's still got to get along with the old skool) and for the client to be confidant.&lt;br /&gt;&lt;br /&gt;People are what makes a software project successful and if you can't do people you can't do software.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Facilitation&lt;/h2&gt;The Thoroughly Modern Developer often finds herself in the middle of difficult and complex situations. &amp;nbsp;Because she wants to get the system right she has to raise difficult questions about the way the business works. &lt;br /&gt;&lt;br /&gt;The Thoroughly Modern Developer needs basic facilitation skills. &amp;nbsp;She needs to be able to lead a group of people through creative and difficult exercises. To get the right answers you have to keep people on track, resolve conflicts, remove distractions, know when to call time-out, get them to make a decision. &lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Has "other" interests&lt;/h2&gt;For athletes &lt;a href="http://www.britishrowing.org/indoor/cross-training"&gt;cross-training&lt;/a&gt; (training in your non-core sport) is a essential technique to ensuring you excel in your core discipline. &amp;nbsp;This is no less true for intellectual disciplines and even more true for creative ones (artists/writers/musicians have known for centuries the importance of pursing other arts - think Da Vinci). &amp;nbsp;If your entire existence is writing software then you are greatly narrowing your reference points and are more likely to suffer from boredom or stagnation. &amp;nbsp;For example many prominent developers have blogged on the strange &lt;a href="http://www.codinghorror.com/blog/2009/01/the-one-thing-programmers-and-musicians-have-in-common.html"&gt;relation between developmen&lt;/a&gt;t and &lt;a href="http://www.threeriversinstitute.org/blog/?p=435"&gt;music&lt;/a&gt;&amp;nbsp;(as a failed musician I entirely concur). &lt;br /&gt;&lt;br /&gt;Personally, I have found that long distance sports have allowed me to strengthen and develop a lot of essential development skills: focus, pace, general discipline; not to mention the health benefits that keep my brain active and my energy levels high.&lt;br /&gt;&lt;br /&gt;But not only does it benefit your work but it makes you a more interesting person, which is always useful when talking to 'real' people like the users. So do your self a favour, when you get home do something that doesn't involve the computer.&lt;br /&gt;&lt;h2&gt;&lt;br /&gt;&lt;/h2&gt;&lt;h2&gt;Understands that technology isn't important&lt;/h2&gt;The Thoroughly Modern Developer has a healthy cynicism towards technology. If something can be done without&amp;nbsp;technology that's her preference and she'll push for it. &amp;nbsp;She actually wants to&amp;nbsp;&lt;a href="http://gettingreal.37signals.com/ch10_Less_Software.php"&gt;write less software&lt;/a&gt;;&amp;nbsp;complex clever gadgetry and features fill her with a great sense of foreboding.&lt;br /&gt;&lt;br /&gt;If she was a developer at Timpsons (who have no centralized till system), she'd be strong in resisting all efforts to introduce one. &amp;nbsp;She only cares about technology if it offers real benefit, if it provides genuine value or is essential to the business or user. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;She's great is the Thoroughly Modern Developer. &amp;nbsp;She's so awesome people high five her every time she gets up to make a cup of tea. &amp;nbsp;And yet she's so humble with it. &amp;nbsp;If only I could be just like her (sigh).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8770707585421528847?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8770707585421528847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8770707585421528847' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8770707585421528847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8770707585421528847'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/03/thoroughly-modern-developer.html' title='A Thoroughly Modern Developer'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-1557929198340672831</id><published>2010-03-10T11:27:00.001Z</published><updated>2010-03-10T11:27:46.873Z</updated><title type='text'>Fear of the new (how TDD and DI encourage bad practice)</title><content type='html'>When I first started doing TDD back in the mid-naughties it changed the way I programmed dramatically. &amp;nbsp;It took me a while to get it at first, how can you test one unit? until I discovered the tricks of dependency injection. &amp;nbsp;Now my code was shaped in loosely-coupled wonderness and I felt invincible. &amp;nbsp;I thought I had reached the pinnacle of OOP. Everything suddenly became so easy, it was well tested, easy to change, easy to wrap, swap implementations, decorate, whatever, I was throwing the best design patterns out with such ease that I barely needed to refer to the Gang-of-Four anymore.&lt;br /&gt;&lt;br /&gt;I went on in this vein for a good year or so. &amp;nbsp;And as the millenium's first decade entered early evening and its bright lights began to fade I took a step back and looked at my code. &amp;nbsp;My god, I thought, this is terrible, what the hell have I been doing? And it was terrible, hundreds of interfaces named somebody's Manager, Persister, Service (oh so many classes called Service), Validator &lt;a href="http://jupitermoonbeam.blogspot.com/2008/09/agent-nouns-are-code-smells.html"&gt;etc. etc.&lt;/a&gt;, all with a single namesake class implementing them. &amp;nbsp;There were tens of classes whose purpose seemed to be to co-ordinate these little buggers - for they were little, ten or so lines each (oh how I thought I was doing a grand job) - and they would hand off to other similar classes who co-ordinated other classes and it was turtles all the way down. &amp;nbsp;And in amongst all of it there were about a dozen classes that had real names like Customer, Account (but even they had interfaces too) and, aye how the sting of memory pains me to this day, they only had getters and setters (it's the shame, you never get over the shame).&lt;br /&gt;&lt;br /&gt;It was with great pain I realized for the last year of my professional life I had been producing procedural code with all the idealistic misguided joy of a card holding Russian worker pouring cheap cement to build pointless roads. &amp;nbsp;I knew the culprit alright: TDD and DI. &amp;nbsp;I had gone decoupling, unit testing mad. &amp;nbsp;The result was an irrational fear of the new keyword. &amp;nbsp;As far as I was concerned the new keyword was banished to the dark depths of Containers, it was a clumsy language feature never to be used again. &amp;nbsp;But what I had instead was a dependency graph made up almost entirely of stateless singletons. &amp;nbsp;A simple Ruby script could have replaced every injected dependency with calls to static methods and sure the application would have lost its testability, it would no longer be decoupled, but essentially, at it's essence, and in terms of structure, it would be the same. &amp;nbsp;TDD and DI had simply given me a fancy way of decoupling static classes.&lt;br /&gt;&lt;br /&gt;The new keyword is a wonderful thing. &amp;nbsp;It lies at the heart of OOP. &amp;nbsp;Its sole objective is to create a new instance of an object. &amp;nbsp;If you don't use new you can't create new objects and if you can't create new objects you can't write object orientated code. &amp;nbsp;And the other fundamental thing about objects is they encapsulate behavior and state. &amp;nbsp;Singletons don't. &amp;nbsp;Singletons are procedural. &amp;nbsp;Regardless of whether they are loosely coupled and injectable. &amp;nbsp;Real OO classes have private fields (the fewer the better) and methods which do things based on those private fields, sometimes based on arguments passed in, but always, always in the context of those private fields. &amp;nbsp;And the only way, the one single true way you get values into those private fields is via the constructor and that means using the new keyword. &amp;nbsp;Let's put it clearly: this '&lt;i&gt;new ValidatedCustomer(customer).IsEmailAddressValid&lt;/i&gt;' is OOP. This '&lt;i&gt;c&lt;/i&gt;&lt;i&gt;ustomerValidator.Validate(customer).IsEmailAddressValid&lt;/i&gt;' is procedural.&lt;br /&gt;&lt;br /&gt;Now I was writing code using TDD and DI that was object orientated code. &amp;nbsp;But my fear of the new was still there. &amp;nbsp;In order to maintain the injectable, loosely-coupled gorgeousness I had begun to do a horrible thing. &amp;nbsp;I started injecting factories everywhere. &amp;nbsp;Sure it was an improvement but there was still something horribly smelly going on. &amp;nbsp;After all the factories were essentially static, singletons whose sole purpose was to delegate to the new statement. &amp;nbsp;I mean there's single responsibility and then there's craziness!&lt;br /&gt;&lt;br /&gt;So I started doing something I thought was really bad: I created objects in my classes! But I wanted to keep loosely coupled and all of that wonderfulness. &amp;nbsp;This required a dramatic shift in thinking. &amp;nbsp;Remember when you first did TDD and how it really hurt because you had to structure programs in a different way? &amp;nbsp;Well it was like doing that all over again. &amp;nbsp;Every time I started doing something I had to spend half an hour thinking, how do I make this work? &amp;nbsp;I know I'm right but how?&lt;br /&gt;&lt;br /&gt;I learnt a few lessons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Not all classes are about interactions, sometimes they are about results. &amp;nbsp;Mocking everything out for the sake of it doesn't gain you anything. &amp;nbsp;Use state based testing to assert the end results not interaction testing to assert what is happening to achieve those results. &amp;nbsp;&lt;/li&gt;&lt;li&gt;It's OK for your collaborators to new up something if you ask them, so you can say &lt;i&gt;fileSystem.NewFile(name&lt;/i&gt;) if you need to. &amp;nbsp;&lt;/li&gt;&lt;li&gt;Collaborators don't always have to be passed in the constructor: they can be passed as arguments to methods as well, so you can say &lt;i&gt;new File('myfile.txt', 'Some text').SaveTo(filesystem)&lt;/i&gt;. &amp;nbsp;&lt;/li&gt;&lt;li&gt;If a class is unavoidably all boilerplate and co-ordination consider using integration tests, after all mocking the interactions of boilerplate code doesn't tell you anything useful at all. &amp;nbsp;&lt;/li&gt;&lt;li&gt;The container shouldn't contain everything, it should be the things that generally require configuration or are likely to change: databases, filesystems, web services etc. Rarely do core domain classes or business principles need to be 'switchable'.&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/6794675998088145034-1557929198340672831?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/1557929198340672831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=1557929198340672831' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/1557929198340672831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/1557929198340672831'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/03/fear-of-new-how-tdd-and-di-encourage.html' title='Fear of the new (how TDD and DI encourage bad practice)'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8919625627641093912</id><published>2010-01-12T13:11:00.003Z</published><updated>2010-01-12T15:44:19.320Z</updated><title type='text'>Desktop Mashup</title><content type='html'>The concept of mashups generated a leap forward for web applications.  By exposing data and functionality in an open and standard way other sites could use it, mashed up with other data using the functions from a different site, to provide services beyond the imagination of the original owners.  It presented a significant shift in thinking: that data and function was more powerful - and arguably more valuable - if applications outside your own could leverage it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This shift in thinking is not only limited to the web; desktop applications can also leverage these ideas.  Locally running rich client desktop applications can be enabled to expose their features to other local, or even distributed, applications.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In fact, in Unix, this concept has been around for decades in the very simple, yet immensely powerful, form of &lt;a href="http://en.wikipedia.org/wiki/Pipeline_%28Unix%29"&gt;software pipelines&lt;/a&gt;.  By chaining the output of one program's data (via stdout) another program, with it's own distinct functionality, can then manipulate the result.  This simple technique has enabled Unix developers and administrators to solve an infinite number of problems from a small set of tools.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Between these two extremes is the idea of desktop mashups.  But instead of following the pull nature of the web, or the push nature of software pipelines, desktop applications can take advantage of the event driven nature of GUI systems and thus create a rich desktop experience.  Thus separate programs, with distinctly different functional offerings, can leverage each other to provide functionality beyond the others original intention.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For clarification consider this simple example: you have two separate applications: one which rips DVDs, another which catalogues them ready for playbook (e.g. iTunes).  When the DVD ripping applications completes it sends a message to say a new movie is available.  The cataloging application - which has no direct knowledge of the first, receives the event and interrogates the new movie and adds it, and its metadata to the catalogue.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course this is nothing more than &lt;a href="http://en.wikipedia.org/wiki/Event-driven_architecture"&gt;Event Driven Architecture&lt;/a&gt; which is hardly a new concept.  The move to mashups comes when we create new applications from the existing apps functionality.  So, in our simple example, we create a new application which fetches film reviews from imdb.  When the user inserts a DVD from ripping it fetches the review so the user can decide whether they should go ahead.  When the user does rip the DVD the review application updates the catalogue application so the review is part of the movie's meta.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Enterprises are ripe for desktop mashups.  A significant number of problems for users is the lack of integration between applications, whether they are different internal apps or even third party.  Another advantage, especially in large enterprises, is that development teams can focus on developing small applications that do their jobs well, or integrating with legacy apps, and mashing them together rather than struggling to develop all-in-one god apps.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8919625627641093912?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8919625627641093912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8919625627641093912' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8919625627641093912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8919625627641093912'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2010/01/desktop-mashup.html' title='Desktop Mashup'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6152272792232895817</id><published>2009-12-09T18:57:00.005Z</published><updated>2009-12-09T19:04:14.340Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><title type='text'>Immutable Wrapper</title><content type='html'>&lt;div&gt;I am a huge fan of immutables, especially for value objects.  Even in clumsy static languages like C# and Java that seem to throw every obstacle in your way to deter you from using them I find the benefits outweigh the costs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes though a mutable makes sense.  Whether that's because of the restrictiveness of a framework or the paradigm of the language.  But what if we don't want to loose the power of immutables behind the scenes?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Introducing The Immutable Wrapper Pattern!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Immutable Wrapper is a wonderfully simple pattern because there are only two things you need to do.  &lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Create a class with only one mutable field&lt;/li&gt;&lt;li&gt;Wrap the immutables functions.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;Here's an example.  You've got a copy-on-write list implementation but your binding it to some GUI control that gives you a big headache if you try and point it to a different data source.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's your immutable:&lt;/div&gt;&lt;pre class="prettyprint"&gt;  class CopyOnWriteList&lt;br /&gt; {&lt;br /&gt;   private readonly IEnumerable items;&lt;br /&gt;&lt;br /&gt;   CopyOnWriteList Add(item)&lt;br /&gt;   {&lt;br /&gt;     return new CopyOnWriteList(new List(items, item));&lt;br /&gt;   }&lt;br /&gt; }&lt;/pre&gt;&lt;div&gt;Now wrap it:&lt;/div&gt;&lt;pre class="prettyprint"&gt;  class WrappedCopyOnWriteList&lt;br /&gt; {&lt;br /&gt;   CopyOnWriteList list;&lt;br /&gt;&lt;br /&gt;   void Add(item)&lt;br /&gt;   {&lt;br /&gt;     list = list.Add(item)&lt;br /&gt;   }&lt;br /&gt; }&lt;/pre&gt;&lt;div&gt;There, it couldn't be simpler.  So simple in fact I don't know what else to say.  Enjoy!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6152272792232895817?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6152272792232895817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6152272792232895817' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6152272792232895817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6152272792232895817'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/12/immutable-wrapper.html' title='Immutable Wrapper'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-276486578218422486</id><published>2009-12-09T13:51:00.005Z</published><updated>2009-12-09T14:08:09.685Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Refactoring'/><category scheme='http://www.blogger.com/atom/ns#' term='Code Smells'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><title type='text'>The Singleton Killer</title><content type='html'>&lt;div&gt;We all hate singletons so here's another useful refactoring pattern: The Singleton Killer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's a common snippet of code we all love to hate:&lt;/div&gt;&lt;pre class="prettyprint"&gt;class Transfer&lt;br /&gt; def funds(from_number, to_number, amount)&lt;br /&gt;   from = AccountRepository.instance.get(from_number)&lt;br /&gt;   to = AccountRepository.instance.get(to_number)&lt;br /&gt;   from.balance -= amount&lt;br /&gt;   to.balance += amount&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;div&gt;So how do we kill this beast?  Simply follow these idiot proof steps:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step One: Introduce Field&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Stop asking the singleton for it's reference and store your own by creating a field:&lt;/div&gt;&lt;pre class="prettyprint"&gt;class Transfer&lt;br /&gt; @repository = AccountRepository.instance&lt;br /&gt; def funds(from_number, to_number, amount)&lt;br /&gt;   from = repository.get(from_number)&lt;br /&gt;   to = repository.get(to_number)&lt;br /&gt;   ...&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;div&gt;Wow: it's starting to look like normal code!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step Two: Initialize in constructor&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Move the initialization to the constructor:&lt;/div&gt;&lt;pre class="prettyprint"&gt;def initialize()&lt;br /&gt; @repository = AccountRepository.instance&lt;br /&gt;end&lt;/pre&gt;&lt;div&gt;This is good but wouldn't it be better if the dependancy could be injected?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step Three: Chain constructor&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;In languages where dependency injection is useful you will need to chain the constructors:&lt;/div&gt;&lt;pre class="prettyprint"&gt;public Transfer() : this(AccountRepository.instance)&lt;br /&gt;public Transfer(AccountRepository repository)&lt;br /&gt;{&lt;br /&gt; this.repository = repository&lt;br /&gt;}&lt;/pre&gt;&lt;div&gt;Now the &lt;b&gt;AccountRepository&lt;/b&gt; can be injected which of course means we can mock it out!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step Four: Extract interface (for statically typed languages)&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Except statically languages: they'll need to extract an interface:&lt;/div&gt;&lt;pre class="prettyprint"&gt;public interface IAccountRepository&lt;br /&gt;{&lt;br /&gt; Account Get(string number);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Transfer(IAccountRepository repository) ...&lt;/pre&gt;&lt;div&gt;Good: now you can start mocking and testing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step Five: Introduce container&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;If you haven't already got a container then get one (else ensure you a wiring up your dependencies in one place).  Then get that to wire up the Transfer object for you:&lt;/div&gt;&lt;pre class="prettyprint"&gt;container.Add(AccountRepository)&lt;br /&gt;container.Add(Transfer)&lt;br /&gt;transfer = container.Get(Transfer)&lt;br /&gt;transfer.funds("YOUACCNUM", "MYACCNUM", 50000)&lt;/pre&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;b&gt;Step Six: Remove singleton&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Once a container is doing all your injection for you that singleton is a waste of space: get rid of him by removing that horrible &lt;i&gt;instance&lt;/i&gt; accessor.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Choose your strategies with this refactoring wisely: if your objective is to get a class tested then first repeat steps one-four within the same class until it is clean of all singletons.  This is a good exercise in it's own right - even if you're not going to move on to test or remove the singleton completely - as you start to move all the dependancies to the constructor you gain a better picture of the classes collaborators (and the quality of design).  On the other hand if your objective is to remove the singleton repeat steps one-three on every usage you can find then finish up with steps four-six.  Another technique is to keep pushing the useage of the singleton up through the code so each client then takes on responsibility for passing the singleton down when it creates an instance of the class.  Like so:&lt;/div&gt;&lt;pre class="prettyprint"&gt;  Transfer.new(AccountRepository.Instance)&lt;/pre&gt;&lt;div&gt;Then repeat steps one-three on the class you've just pushed into, then push the singleton up again up and so on until you can't push it anymore.  This can be an interesting exercise in itself as it starts to push out the paths through the code base as you move through the layers and may also give you a clear point where your container needs to be.  Be warned though: it can get messy (though strangely satisfying)!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On larger, messier codebases none of these approaches may be realistic in which case opt for the guerilla approach and pick them off as you find them.  Though I would encourage trying to at least clean out a whole class using steps one-three even if you won't end up testing it right away.  With all your dependancies in one place you'll still have a better picture of the design.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-276486578218422486?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/276486578218422486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=276486578218422486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/276486578218422486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/276486578218422486'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/12/singleton-killer.html' title='The Singleton Killer'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5950428284351827489</id><published>2009-12-05T07:56:00.001Z</published><updated>2009-12-05T07:57:56.346Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Beware Metanarratives</title><content type='html'>Now my darlings gather round while I tell you a story.  But not just any story.  A story about stories.  About BIG stories.&lt;br /&gt;&lt;br /&gt;Not so many decades ago, when the French still measured their GDP on the combined weight of their philosophical works, a particular man, with the amusing name of &lt;a href="http://en.wikipedia.org/wiki/Jean-Fran%C3%A7ois_Lyotard"&gt;Lyotard&lt;/a&gt;, came up with the concept of &lt;a href="http://en.wikipedia.org/wiki/Metanarrative"&gt;Metanarratives&lt;/a&gt; (or Grand Narratives).&lt;br /&gt;&lt;br /&gt;A Metanarrative, simply put, is a big story, often idealistic in tone, essential a grand, universal theory which is then applied to every aspect of life.  There are many good examples of metanarratives from religious narratives, humanist, to economical and social theories communist, capitalist, freemarket etc. &lt;br /&gt;&lt;br /&gt;The IT industry is brimming with metanarratives.  Whether it is Stallman's completely open source future, no software patents, where everyone collaborates and all is wonderful, or the visions of an open web which overflows with information causing the end of totalitarianism, poverty etc. or the whole proprietary vs Open Source battle of the metanarratives.&lt;br /&gt;&lt;br /&gt;Even as we move closer to home in the ever rational world of Enterprise Software Development we too find it overspilling.  Waterfall has a wonderfully convincing metanarrative.  And if SOA isn't a metanarrative (of Joycean composition) with it's land of milk and honey then I don't know what is.  Probably the fastest growing metanarratives in IT is that of the Agile and Lean movement.&lt;br /&gt;&lt;br /&gt;We humans love a good metanarrative to pin our life story on.  They make us feel safe and cosy; it's nice to comprehend the world through the view of a single cohesive story with a beginning, middle and happy end (which is why marketing departments love forming them).  We look around us finding more and more things to embellish and support our narratives.  As we gain experience we see it as evidence to the greater truth of our chosen metanarrative.&lt;br /&gt;&lt;br /&gt;But metanarratives are not a good thing - especially in an ever shifting landscape like IT.  They make us lazy and prevent us from considering other stories.  And if they are considered it is as a threat (e.g. MS' campaign against Open Source).  Which is a problem in it's own right: if someone has subscribed to a metanarrative then it is almost impossible to win them round to any other story.  Put one metanarrative against another and your blocked - queue visions of an evolutionist and a creationist locked in a room for eternity - monkeys would have written the works of Shakespeare before either changes their mind.&lt;br /&gt;&lt;br /&gt;Metanarratives ultimately disappoint - especially in the ever shifting landscape of IT.  Not so much because they are wrong but because they cannot be right.  Everything, especially in IT, cannot fit into one nice story.  The world is too culturally rich and diverse.  As with the thousands of varying religions, The British Empire, Communism, the American Dream, DNA architecture, eventually the world shifts into a state where the narrative becomes ridiculous to apply.  Yet people will keep doing so - the continued prevalence of Waterfall in some businesses being a case in point.&lt;br /&gt;&lt;br /&gt;My concern is that we are guilty of promoting Agile as a metanarrative.  Evangelists have moved it, from being a local story about a collection of problems in software development, to a model for the entire way businesses are run.  Now, let's be clear, there are many elements of Agile I strongly subscribe to and promote, and I often agree with the basis of many of these claims.  However the danger occurs when the Agile movement (or any other movement) seeks to displace any other narrative and claim itself universal.  That ALL software should be developed this way, and ALL businesses should model themselves to support this.  That's just crazy speak!&lt;br /&gt;&lt;br /&gt;Interestingly (in my opinion) in their original forms Agile and Lean are post-modern in their attitudes towards metanarratives.  Both attempt to promote fresh thinking and new ideas and move away from grand prescriptivism and dogma, especially of those found in the industry at the time.  Most importantly both movements promote the fact that there isn't one universal way.  For many people it was this breaking away from the metanarrative of the time and creating space to form our own stories which made Agile so attractive.  Perhaps it is the inherent paradox in the post-modernists view of metanarratives that have caused them to, ironically, become metanarratives themselves.&lt;br /&gt;&lt;br /&gt;The world of IT is too rich and diverse and full of too many stories (some old, some new) to support metanarratives.  There is nothing wrong with some of these stories (such as Lean and Agile) when viewed in isolation; some are full of rich culture and ideas, some are simply misconceived and naive.  On their own they are harmless and together with other stories they are invaluable.  But as soon as people start turning them into something with which to narrate the whole Industry they are deadly.&lt;br /&gt;&lt;br /&gt;So my warning is this: beware of metanarratives.  If you notice that you are tending to frame the IT world around one story, whether that is Scrum, SOA, BDUF etc. please consider whether you have been caught in a metanarrative.  Equally if you find yourself embattled due to someone's particular metanarrative, don't try and slam another one around their head.  Instead try and appreciate their story at a local level whilst keeping your own stories localized and nonthreatening - they may even begin to fit it into theirs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5950428284351827489?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5950428284351827489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5950428284351827489' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5950428284351827489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5950428284351827489'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/12/beware-metanarratives.html' title='Beware Metanarratives'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-2344824427162826443</id><published>2009-11-05T10:11:00.001Z</published><updated>2009-11-05T10:13:58.930Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Killing the Config</title><content type='html'>Most applications require config of some description and it is considered good practice to wrap any calls which retrieve configured values in a config class and pass that around rather than &lt;a href="http://www.thekua.com/atwork/2008/08/treat-your-appconfig-like-a-global-variable/"&gt;splattering the codebase with direct calls to the frameworks inbuilt static methods&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;With all the applications configs neatly wrapped in one place the code starts to become more maintainable.  Yet are we just replacing one evil with another, if somewhat lesser, one?  The problem I often see is this Config class finds itself passed from class to class flouting it's promiscuity and leading writers of articles on config objects down paths dangerous and full of inappropriate metaphors more commonly favoured by the ruby crowd.&lt;br /&gt;&lt;br /&gt;There is no doubt that it is useful to collate all of the configurable elements together in one (or more) common classes.  What should be avoided is leaking this concept through the whole domain and kicking it from object to object like a dirty old data bag which everyone rumages through, unchecked, pulling out stuff on their own whim.  Config is an implementation detail which the majority of the application should have no concept of and (like any other such implementation details) it needs to be locked firmly away like a lump of kryptonite in a lead cased layer so it can no longer leak and permeate and weaken your SuperApp.&lt;br /&gt;&lt;br /&gt;Let's think about this in a BDD fashion.  When your class want's a ghostbusting url who's it gonna call (they have a webpage now dinyuknow)?  string Config.GhostBusterUrl? Or perhaps the GhostBusterUrl class?  If your class needs a typed collaborator with certain logic and behaviour (even if it is just supplying a valid url) then that's what your class should get.  Not some smelly generic config object that dishes out dirty unparsed strings.  The tests should be enough to tell you I'm telling you the right thing: several lines of priming the mockConfig are replaced with the simple supply of a GhostbusterUrl.&lt;br /&gt;&lt;br /&gt;So how do we get the GhostBusterUrl from a line in config to those poor desperate classes who are being terrorized by spooks?  With a little Tell don't ask and a container.  Turn the config object inside out, make its role to inject into the application the dependencies it wants to supply.  If your config believes it has a GhostBusterUrl then get it to construct one and register it (along with anything else it thinks it might have of use) into the container when the application tells it to.  Not only does the config object gain some of its dignity back (some other classes were calling it nasty names, I know, it's the new millennium, but some people still hold the old fashioned ideas) and is safely kept right to the very edges of your application where no one can get at it.&lt;br /&gt;&lt;br /&gt;Another positive side effect is that now your config object is giving birth to loads of lovely typed objects that actually do real stuff rather than having wandering hands pluck at its primitives (I know but I did warn it was a dangerous path laden with tasteless innuendos, I was bound to trip).  Though of course, be careful not to pollute your codebase with a million classes that simply represent strings and do nothing else (it's a fine line and one you'll need to argue between me, myself and I).  It's also one of the easiest refactorings you can do to your code.  Give it a go (and if you object on the grounds of their being loads of small types then please find the closet crumbling procedural bridge and throw yourself into the polluted sequential river below).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-2344824427162826443?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/2344824427162826443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=2344824427162826443' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2344824427162826443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2344824427162826443'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/11/killing-config.html' title='Killing the Config'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5142866955064641434</id><published>2009-07-08T06:55:00.003+01:00</published><updated>2009-07-08T07:03:58.635+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='value'/><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><title type='text'>Value Driven Development</title><content type='html'>At the beginning of the year I blogged about using value as a measure of productivity.  Since that time I have had the opportunity to refine my thinking and be influenced by some other ideas.  I want to revisit the original idea of using value as a measure.  I may be guilty of repeating myself a little but it's a small cost for clarity.&lt;br /&gt;&lt;br /&gt;The concept focuses around one very simple idea: the primary objective of a project is to deliver value.  The more value we deliver the more successful the project is.  If you agree with this then my next idea shouldn't be too hard to grasp: the primary measure of a project is value.  Not velocity, not story points, flow, throughput, cycle time, capacity, cyclic complexity, code quality, but value, pure and simple.  Of course we can use the other measurements to help us discover more effective ways of delivering value but on their own they tell little about how much value is being delivered.&lt;br /&gt;&lt;br /&gt;Strangely, despite the fact that agile and Lean and Kanban and all of it's derivatives tell us how important value is none of them propose explicitly measuring it.  Agile proponents often argue that it is their focus on delivering value early and often which makes them unique over conservative methodologies but how do they know?  I've never picked a story off the wall and been able to tell what worth the customer gains by delivering it - ten, a hundred, a thousand, a millions pounds?  Hell, who knows? The BA? The PM? The product owner?  And how many projects out there can raise their hands to the question "How much value has your project delivered in the last week/month/year?"  So if we're all so very value focused in our lean and agile worlds how are we not answering these simple questions?  Are the statements about delivering more value pure assumption?  How do we know that when we make 'improvements' to our processes the effect is to deliver more value?  Or is at case of substituting value with story points mapped against velocity?  If so how do you know that twenty-five story points to improve online advertising generated any revenue?  Or is it a case of take the points and run?&lt;br /&gt;&lt;br /&gt;Before we can confidently improve the amount of value we deliver we need to  be measuring the value we are delivering.  The first problem that presents itself is how do we do this?  Value is hard to quantify and even harder to estimate.  Which sound awfully similar to the problems with size so why not transfer the techniques used to estimate of story size to estimating value.  Start simple, use relative sizes, but instead of t-shirts maybe use precious metals (aluminium, bronze, silver, gold, platinum etc.) or any other metaphor that helps the team visualize features in relative worth and as with size estimation it's an estimate, it doesn't have to be exact, the important thing is that we have some sort of gage and that we track it and refine it.&lt;br /&gt;&lt;br /&gt;Once stories have value estimates they can go through the normal delivery process: estimate size, queue them up, stick them in iterations (or do some funky Kanban pulling on them).  Except now every story card has it's most important piece of information branded to it: it's value.  During prioritisation the platinum card which is the size of a small T-Shirt should obviously be delivered before the XXL bronze one.  When stories are worked on people know that it's worth putting that extra effort into putting the plating on the platinum one but perhaps the aluminium story requires a more pragmatic approach than spending two days of cross functional refactoring to perfect it's design.  During standups if someone says a platinum card is blocked the whole team knows it's important to get this sorted and coming up to a release with three gold stories complete but a stubborn bronze proving difficult to get across the line you may be more tempted to make the call to leave it out this time and hell to the size points.  Very quickly every part of the process focuses around the amount of value being delivered, every decision is being influenced by the value of the story, not by it's size, not by how cool it is, not how much can be crammed into an iteration, but by how much value this piece of functionality is actually going to bring to the customer.  Now that's being agile!&lt;br /&gt;&lt;br /&gt;The purpose of putting values on stories is to measure how much value has been delivered.  Now let's be clear about what delivered means: out there, in production, available to everyone who should have it, in full use.  Basically, not dev complete, not in UAT, not in live pilot to a handful of select users, but out there live and in concert, fully functional, fully delivered, bringing value.  Until then the functionality is worthless; until it is delivering value then you ain't delivered any value.  Once it is though start totting it up: add the value points onto the delivery (note: delivery not iteration - iterations cannot deliver value unless they release), repeat for the next delivery plotting the value delivered on a chart and voila: the project's true velocity: how much value, for each delivery, it has been delivering.&lt;br /&gt;&lt;br /&gt;But what if the value didn't quite get delivered?  What if the functionality was released but with a bug which somehow hindered it's full capability?  Maybe it is too slow, too difficult to use, doesn't do quite the right thing etc.   Anything that prevents the application from delivering all of the value it promised is an issue (regardless of whether it is a bug or 'a feature').  However by resolving the issue the lost value can be reclaimed.  By fixing the bug, performance or usability problems, the project claws back the value it lost when it didn't get it quite right first time.&lt;br /&gt;&lt;br /&gt;It's important the project's value velocity reflects this.  So when a fix is raised it is given a value which is then deducted from the velocity: this is because the full value of that feature was not delivered.  Once the fix is in use and active then the value points go back on.  Personally I find this one of the most powerful ideas behind measuring the velocity of value as the bad habits of delivering bug ridden functionality iteration after iteration by dismissing fixes in order to keep earning the points will not get you anywhere as the value velocity either struggles to move or even, in extreme cases, goes backwards.&lt;br /&gt;&lt;br /&gt;I think there are many other benefits to be gained from using value as the primary measure that are yet to be discovered (possibly placing value onto technical debt? Though I'm not yet convinced of that one).  Explicitly placing value at the forefront of the project gives teams the power to optimize themselves and discover new ways to improve their efficiency.  And it isn't necessarily limited to individual teams: projects themselves should be measured in this way with teams 'contributing' to value - not simply earning points for delivering 'their part' - breaking down silo attitudes by finding ways to effectively work as a whole so value can be delivered.&lt;br /&gt;&lt;br /&gt;I think it's pretty exciting stuff.  Of course all the other metrics out there may or may not find use, dependant on whether they are contributing to the delivery of value or not, and holes will be found in the technique, but overall I think it shifts the debate and discussion forward to a entirely new level of thinking.  It will allow us to reach a whole new level in the Value Enlightenment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5142866955064641434?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5142866955064641434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5142866955064641434' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5142866955064641434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5142866955064641434'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/07/value-driven-development.html' title='Value Driven Development'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-3025624887247076858</id><published>2009-01-28T20:42:00.004Z</published><updated>2009-01-28T20:54:22.887Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='value'/><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><title type='text'>Getting the measure of Value</title><content type='html'>In my &lt;a href="http://jupitermoonbeam.blogspot.com/2009/01/measure-for-measure-why-were-doing-it.html"&gt;previous post&lt;/a&gt; I made the claim that we should not be measuring velocity (to the customer at least) in terms of functionality and effort delivered but in terms of value delivered.  In this post I will expand on this by explaining how value and velocity work together.&lt;br /&gt;&lt;br /&gt;The idea behind measuring velocity in terms of value is simple and, at its core, doesn't greatly differ from the way in which we measure velocity now.  Functionality is still broken up into stories (or MMFs if you prefer the Kanban approach) and they are still assigned points.  The subtle change comes from what the points represent: not the size of the story but instead the &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;value&lt;/span&gt; of delivering it.&lt;br /&gt;&lt;br /&gt;The first problem with this is how to assign points of value to a story?  Value is something that can be hard to define, that is variable and may be measuring different things (monetary value, visitors to a web site, time saved).  Story sizing has similar difficulties so it makes sense that the solution is the same: estimation. Value can be estimated by having the team discuss a story and assign points to it. It doesn't have to be accurate - it's an estimate - but it does have to be representative and the more the project goes on the better it will get.  The important thing is to decide on what a unit of value represents and as a team (customer, users etc.) agree to it.  But guess what?  Estimating the value of something is a core activity of most businesses and they should be both used to it and good at it to.&lt;br /&gt;&lt;br /&gt;Which begs the question what should a unit of value be?  This is highly dependent on the domain and type of business.  In most domains value could simply be represented in terms of money: a story to allow people to purchase your widget online is the profit of the widget * the increase in the number of sales.  In some domains it might be different, for example a web site (wikipedia for example) may measure value in terms of how many visitors it gets.  Some domains may be more complex and have a combination of the two (or more): number of visitors and the money raised in advertising.  In these cases the solution would be to find a common representation: maybe one visitor is worth £10 in advertising revenue (for example).  Some domains may even express value in a way entirely different (schools: exams passed, hospitals: lives saved etc.).  The important thing is that what the unit of value represents is consistent and meaningful.&lt;br /&gt;&lt;br /&gt;Now stories have been assigned points which represent their &lt;span class="Apple-style-span" style="font-style: italic;"&gt;potential value&lt;/span&gt; how does a team earn (or &lt;span class="Apple-style-span" style="font-style: italic;"&gt;realize&lt;/span&gt;) them?  If you read my last post you may remember that I started by explaining that in Lean you don't earn value until a customer receives it.  This rule is extremely important and velocity should work the same way.  Until the customer (or end user) has the functionality out there, working and &lt;span class="Apple-style-span" style="font-style: italic;"&gt;in use&lt;/span&gt; the team does not get the points.  Functionality not delivered, only partially delivered (delivered only to a pilot group etc.) or released but unused is not considered delivered - it is inventory - and therefore does not realize its value.  Until the customer has realized the value then it is not recorded on the velocity.&lt;br /&gt;&lt;br /&gt;Recording velocity in this way ensures that it represents the reality as perceived by the customer and aligns it with the rules of Lean.  It should also change   the way teams are measured and motivated: their focus switches from getting functionality out of the door to genuinely delivering value into the hands of the end user.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-3025624887247076858?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/3025624887247076858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=3025624887247076858' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3025624887247076858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3025624887247076858'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/01/getting-measure-of-value.html' title='Getting the measure of Value'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-7619707495297198664</id><published>2009-01-22T20:01:00.002Z</published><updated>2009-01-22T20:11:10.610Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='value'/><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><title type='text'>Measure for measure (why we're doing it wrong)</title><content type='html'>In this post I will outline that the way in which we measure productivity in software development is still flawed - even in agile.&lt;br /&gt;&lt;br /&gt;One tenet of Lean is that the core activity of production is to deliver value to your customer.  A second tenet of Lean is that something is not finished until the customer receives it.  Only then do you record it on your balance sheet.  Combining the two is a simple statement: the purpose is to deliver value to the customer; it is not delivered until the customer receives it.  &lt;br /&gt;&lt;br /&gt;Everything else is unimportant.  Anything that is not contributing to the first tenet is waste (muda) anything that is produced but isn't delivered to the customer is inventory and inventory is also waste.&lt;br /&gt;&lt;br /&gt;The relationship between productivity and value in Lean is fundamental.  If something which is produced yet not delivered doesn't have any value then we have not produced.  Regardless of how many hours worked, how many items output, how much blood, sweat and tears, if all you have created is inventory then you have as good as done nothing.&lt;br /&gt;&lt;br /&gt;Measuring productivity has been a holy grail of software development.  It sits at the heart of many of Agile methodologies.  Thanks to essays such as The Mythical Man Month and with tools such as estimation, iterations, velocity and burn down charts Agile has moved us beyond measuring productivity with the highly flawed method of counting hours worked.  Instead it breaks projects into units of functionality (stories) which are given sizes (points) relative to their complexity/effort.  Productivity is then measured by totaling up the measure of effort once the functionality is completed and 'signed off'.&lt;br /&gt;&lt;br /&gt;Using velocity to measure progress and productivity has resulted in a revolution in thinking.  Using velocity teams are better placed to manage and schedule workload (scope) and much more able to accurately report what has been done and what is left to do.  The result has been much more predictable and achievable project timelines.&lt;br /&gt;&lt;br /&gt;However there is a disconnect between the customer (and user) and the producing team.  The producing team is measuring its productivity based on how much effort is realized into working software.  The customers success will be ultimately measured (whether they are aware of it or not) on how much value they have delivered (note the tense: not how much they potentially will/may deliver but HAVE delivered).&lt;br /&gt;&lt;br /&gt;The result of this disconnect is that teams responsible for production are working within a model which is not based on reality.  The real value of what they are producing is nowhere to be seen in any of the measurements or reports output by the team.  The result is their measure of success being out of line with that of the customers.  The team ends up working to its goal to maximize output of functionality but not to producing value.&lt;br /&gt;&lt;br /&gt;Teams need to change the way they measure productivity to bring it inline with the way the customer is measured.  To achieve this is simple: measure velocity in terms of value, not effort.  And by keeping with the Lean tenet to only record value when it is delivered to the end user.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-7619707495297198664?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/7619707495297198664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=7619707495297198664' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7619707495297198664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7619707495297198664'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2009/01/measure-for-measure-why-were-doing-it.html' title='Measure for measure (why we&apos;re doing it wrong)'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8529334560055305900</id><published>2008-12-01T13:26:00.008Z</published><updated>2008-12-01T15:20:05.739Z</updated><title type='text'>Examples as tests</title><content type='html'>We often talk about tests being documentation but what about using tests for usage examples for APIs? It's something I rarely (if ever) see and yet tests are far more succint and effecient at communicating behaviour.&lt;br /&gt;&lt;br /&gt;To demonstrate this I am going to take a very simple function from MSDN on the &lt;a href="http://msdn.microsoft.com/en-us/library/36x43w8w(VS.80).aspx"&gt;C# ++ operator &lt;/a&gt;. Here is the extract of MS' example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The increment operator (++) increments its operand by 1. The increment operator can appear before or after its operand: &lt;br /&gt;&lt;strong&gt;Remarks&lt;/strong&gt;The first form is a prefix increment operation. The result of the operation is the value of the operand after it has been incremented.&lt;br /&gt;The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.&lt;br /&gt;Numeric and enumeration types have predefined increment operators. User-defined types can overload the ++ operator. Operations on integral types are generally allowed on enumeration.&lt;strong&gt;Example&lt;/strong&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;// cs_operator_increment.cs&lt;br /&gt;using System;&lt;br /&gt;class MainClass&lt;br /&gt;{&lt;br /&gt;    static void Main()&lt;br /&gt;    {&lt;br /&gt;        double x;&lt;br /&gt;        x = 1.5;&lt;br /&gt;        Console.WriteLine(++x);&lt;br /&gt;        x = 1.5;&lt;br /&gt;        Console.WriteLine(x++);&lt;br /&gt;        Console.WriteLine(x);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br /&gt;2.5&lt;br /&gt;1.5&lt;br /&gt;2.5&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Although we are accustomed to these types of examples have a think about how hard you have to work to undertand it. The example on it's own gives no indication of what behaviour it is demonstrating (which is explained in complex english in the preceding text) and the call and the result are nowhere near each other - how often do my eyes have to refocus (look at the first Console.Writeline, then the first line of the output, then the explanation, match them up, look at the second Console.Wr... phew)? And this is just a simple example with a few behaviours.&lt;br /&gt;Here is the same thing using tests (I've tried to closely match MS' own text for test names):&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;using NUnit.Framework;&lt;br /&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class IncrementOperatorBehaviour&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void IncrementAsPostfixIncrementsValueByOne&lt;br /&gt;    {&lt;br /&gt;      double x = 1.5;&lt;br /&gt;      x++;&lt;br /&gt;      Assert.AreEqual(2.5, x);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void IncrementAsPrefixIncrementsValueByOne&lt;br /&gt;    {&lt;br /&gt;      double x = 1.5;&lt;br /&gt;      ++x;&lt;br /&gt;      Assert.AreEqual(2.5, x);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void IncrementAsPrefixGivesResultAfterIncrement&lt;br /&gt;    {&lt;br /&gt;      double x = 1.5;&lt;br /&gt;      Assert.AreEqual(2.5, ++x);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [Test]&lt;br /&gt;    public void IncrementAsPostfixGivesResultBeforeIncrement&lt;br /&gt;    {&lt;br /&gt;      double x = 1.5;&lt;br /&gt;      Assert.AreEqual(1.5, x++);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;How much clearer is that? You even have the satisfaction of seeing it all go green when you run them!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8529334560055305900?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8529334560055305900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8529334560055305900' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8529334560055305900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8529334560055305900'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/12/examples-as-tests.html' title='Examples as tests'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4430200556269979857</id><published>2008-11-23T10:41:00.000Z</published><updated>2008-11-24T07:15:15.570Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Agile welcomes friendly aliens</title><content type='html'>It is a common complaint amongst agilists that teams label themselves as Agile simply because they do all the practices such as TDD etc. yet they are not what they would call agile.  They argue that the practices alone aren't enough, that there is something else, something unquantifiable which agile is all about: the so called 'spirit' of agile, &lt;a href="http://alistair.cockburn.us/Agile+software+development:+the+people+factor"&gt;the 'people factor',&lt;/a&gt; or to quote "[it] may &lt;span class="Apple-style-span" style="font-style: italic;"&gt;look&lt;/span&gt; the same as an agile methodology, but it won’t &lt;span class="Apple-style-span" style="font-style: italic;"&gt;feel&lt;/span&gt; the same”.  What they are trying to describe is a lack of alienation.&lt;br /&gt;&lt;br /&gt;Anyone who did philosophy or sociology - or was simply a sixth form socialist revolutionary - would probably have looked at &lt;a href="http://en.wikipedia.org/wiki/Non-alienated_labor"&gt;Marx's theory of alienation&lt;/a&gt;.  Whilst most people tend to think of Marx's economic theories the problem of alienation was of primary importance to Marx; to quote Ernesto "Che" Guevara:&lt;br /&gt;&lt;br /&gt;"One of the fundamental objectives of Marxism is to remove interest, the factor of individual interest, and gain, from people’s psychological motivations"&lt;br /&gt;&lt;br /&gt;Marx believed that all humans are naturally motivated by the creation of value and self development, thriving on challenges, regardless of class or situation.  For example, take the stereotype of a football obsessed couch potato in a dead end job.  Despite lacking in motivation in their work they seek pleasure from a study of football which is shared and developed with like minded friends.  This study is so intense and focused it would put the most dedicated of academics to shame.  How comes, under his own steam he can achieve so much yet is so despondent in his employment?&lt;br /&gt;&lt;br /&gt;Marx argues the reason is that capitalism's methods of maximizing productivity actually create a system which alienates the worker and therefore fails in its aims.  Inversely an environment without alienation is productive and produces value for all.&lt;br /&gt;&lt;br /&gt;Marx described four types of alienation in labour:&lt;br /&gt;1) From our product: we are separated from what we produce and its value.&lt;br /&gt;2) From our productive activity: the product is outside of our control so work simply becomes a meaningless activity.&lt;br /&gt;3) From other human beings (or other workers): we are isolated from each other, made to work independently, despite the fact that productivity is social in nature.&lt;br /&gt;4) From our species being (or species essence): we are forced to specialize which removes the freedom to develop our capabilities therefore we loose stimulation and fail to be challenged.&lt;br /&gt;&lt;br /&gt;Agile and Lean (though I am not sure if intentionally) recognize the problems of alienation and have strategies for removing them:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;From our product&lt;/span&gt;&lt;br /&gt;The importance of our role in providing value and creating a successful product are fundamental to Agile and Lean.  Many practices focus directly on reducing the gap between the team and the end product such as keeping the customer close, delivering regularly and maintaing constant feedback.  AgileLean is also focused on our role in creating value rather than simply meeting a set of personal objectives.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;From our productive activity&lt;br /&gt;&lt;/span&gt;AgileLean places us in control of the process and the system. Lean emphasis the importance we all have in the productive activity and empowers us to improve the process and eliminate waste.  In Agile we are responsible and involved in all productive activities from planning and estimation, to picking up stories, to delivery and improving the agile process itself.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;From other human beings&lt;br /&gt;&lt;/span&gt;Agilists have always been keen on the social nature of development believing it to be imperative to the success of the project.  Communication, knowledge sharing and working together is actively encouraged with techniques such as pairing, stand-ups etc.  AgiLean environments are made up of people working &lt;a href="http://www.thekua.com/atwork/2008/07/what-do-you-have-more-of/"&gt;closely together as a team rather than individuals in a group&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;From our species being&lt;/span&gt;:&lt;br /&gt;AgileLean is often critical of &lt;a href="http://www.agilemodeling.com/essays/generalizingSpecialists.htm"&gt;specialization&lt;/a&gt;.  Instead  agilean prefers &lt;a href="http://agiletools.wordpress.com/2007/12/22/what-does-it-mean-to-be-a-cross-functional-team/"&gt;cross-functional teams &lt;/a&gt;made up of multi (highly) skilled generalists. This creates an environment were people are challenged and are free to develop, on a day to day basis, in the directions they choose and not reduced to the criteria their performance management chart dictates.&lt;br /&gt;&lt;br /&gt;The S and M labels often make people feel nervous, in some cases to the point of rejecting ideas completely because of the connotations.  Socialism isn't short of its critics but agile and lean prove how we can address some of the most important concerns Marx had with the capitalist system in a way that makes business stronger (just look a Toyota's huge success in a very aggressive capitalist market compared to its more &lt;a href="http://www.telegraph.co.uk/finance/breakingviewscom/3483464/GM-Chrysler-and-Ford-set-for-tough-fight-as-Congress-wises-up-over-bail-out.html"&gt;communist fearing cousins in the States&lt;/a&gt;).  The success of agile and lean prove how much more productive we can be when we tackle the problems of alienation.  This is why many of us find it so frustrating to see teams labelled agile who still operate in an alienated way.&lt;br /&gt;&lt;br /&gt;Agile and lean teaches us that teams who recognize alienation and address it are ultimately more successful.  By explicitly seeking to address alienation we can create healthier working environments which offer greater value at a higher rate of productivity.  Now what right minded capitalist wouldn't want that?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-4430200556269979857?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4430200556269979857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4430200556269979857' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4430200556269979857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4430200556269979857'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/11/agile-welcomes-friendly-aliens.html' title='Agile welcomes friendly aliens'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8850447292051515030</id><published>2008-11-19T19:19:00.005Z</published><updated>2008-11-19T20:18:07.175Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>That's right: blame Agile</title><content type='html'>Before we start a small warning.  This is a rant and as such contains certain properties common to rants such as emotionally overstating unimportant points, glossing over and confusing important ones, over decorative language and taking the odd innocent as victim.  Bearing this in mind please remember though serious my tongue is sometimes placed firmly in cheek for dramatic effect.&lt;br /&gt;&lt;br /&gt;There has been a great debate happening over the airwaves of the blogosphere recently.  Sparked of by James Shore's post &lt;a href="http://jamesshore.com/Blog/The-Decline-and-Fall-of-Agile.html"&gt;The Decline and Fall of Agile&lt;/a&gt; it has gotten to some people declaring the death of agile and others calling for the rejection of the term altogether [link].  It's as if the Nazi party has just announced that the Third Reich was built on Scrum and suddenly everyone is trying to distance themselves: "no we never agreed with that agile stuff, what we were talking about is something completely different".&lt;br /&gt;&lt;br /&gt;Around the same time another debate is picking up steam started by Roy Osherove's post &lt;a href="http://weblogs.asp.net/rosherove/archive/2008/09/20/goodbye-mocks-farewell-stubs.aspx"&gt;Goodbye Mocks, Farewell Stubs&lt;/a&gt;.  Apparently people find testing too difficult to grok so we need to reject terms like mocks and stubs ('cos though accurate they are apparently confusing) and replace it with another: Fakes.  Oh the glaring irony as one side of the movement is rejecting marketing terms because too many people who use it don't know what it means while the other side try to introduce more marketing language to attract the people who don't know what it means.&lt;br /&gt;&lt;br /&gt;Uncle Bob has dropped in like Batman at the Jokers party and delivered his direct, powerful blow: &lt;a href="http://blog.objectmentor.com/articles/2008/11/16/dirty-rotten-scrumdrels"&gt;"the problem is you're all f*ing lazy"&lt;/a&gt;.  Although I feel that Uncle Bob is much closer to the truth than many other commentators he's not really offering a realistic solution out of the mess.&lt;br /&gt;&lt;br /&gt;So what exactly is the problem we've got here?  Both of these posts have something in common.  James Shore's issue stems from teams picking up words like Scrum and Sprint and forgetting that they have to write decent code as well.  Roy Osherove's post stems from the fact that getting teams to even write tests is met with constant failure.  Both posts talk about a general lack of engineering skill in IT.  In reaction different parties are offering up different solutions but they all fail to address the core issue.&lt;br /&gt;&lt;br /&gt;For those jumping the agile ship and getting onto the next coolest speedboat what exactly is that going to prove? Rather than improving the industry it leaves it helpless and sinking.  This is a rotten attitude that resolves nothing: when every PHP and VB programmer converts to Ruby what you gonna do then?  Oh it's OK Ola's writing Ioke and if that doesn't work we've always go Lisp (they'll never get that). Roy Osherove's solution of lowering barriers to entry is more commendable but will achieve just as little and is guilty of another great crime: dumbing down (though he's spot on about tool support).  I don't think the solution to poor engineering skills are to withdraw important technical terms: can you imagine the Bar rebranding legal terms because, y'know Lawyers just find it too difficult to understand this stuff or Doctors calling for less names for the organs 'cos med students these days just can't get the point of having the terms stomach and intestine and they keep operating on the wrong one.  Why can't we just call it the food processor?  Jay Fields' novel idea is to &lt;a href="http://blog.jayfields.com/2008/08/elephant-in-server-room.html"&gt;ask them all to politely leave&lt;/a&gt;  (50% of them in fact).  And if they don't?  Well then I guess we'll all get together and go around with a big seal club and sort it out that way (it's what I refer to as "The Great Culling" - there's those Nazi's marching past again).&lt;br /&gt;&lt;br /&gt;The real problem, the root cause to all this is simple (and on this most agree especially Uncle Bob and Jay): the gross under valuing of the skills which enable you to do your job.  The thing is it's nothing new.  It was there before agile and TDD had the impact they do today (they just laughed then).  Remember those not so long ago days when people thought the solution to delivering software wasn't skills or focus on quality but getting some glorified secretary to type up several hundred pages of requirements and then handing them to some supposed genius to design everything for the monkeys to punch in?  Well we're still there people: it's just they thought the solution to the mess that disaster caused was to do something called iterations, standing up and getting the monkeys to skip around the genius guy wrapping him in his own ribboned UML diagrams chanting "architect, architect, architect".&lt;br /&gt;&lt;br /&gt;Nothing's changed, agile or not.  The majority of the industry still doesn't value the basic, fundamental skills it takes to write software of acceptable quality.    It didn't before and it still doesn't now.  Instead it's obsessed with solving the problem by bringing in the right highly paid manager with the right powerpoint presented methodology.  Until the industry gets that ain't the way it will drag every shining beacon of light (agile, Ruby whatever) down into Hades with it.&lt;br /&gt;&lt;br /&gt;Writing software is about people People!  That's what agile and Lean and all their friends tell you again and again.  The fundamental principles are about people, not iterations, continuous integration and story boards.  Go check out the &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt; and tell me where you see any of that stuff?  This bastard form of agile which only talks about tools and processes is like someone got the manifesto and spun it round (People OVER Process read it Again).  The practices and tools are there to actively encourage developers who are skilled, committed and know what they're doing and make them more empowered and productive and ultimately deliver MORE value and success, they are not there to replace them.&lt;br /&gt;&lt;br /&gt;So what is the solution?  The simple truth is that those of us who understand the problem have got to keep doing a great job, we've got to help those who want to do a great job but aren't sure how to do a great job and we've got help those who don't understand how to do a good job and may never will and may not even want to.  Sure it's depressing sometimes, it's frustrating but we can't just give up on the industry and jump away on the next term or simply dumb the whole thing down so the next generation can get it a little more but ultimately still fail to get it.&lt;br /&gt;&lt;br /&gt;Agile was never, is never going to be an quick, faultless success forever preserving an eternal purity.  Our industry is sick, real sick.  It's a beer guzzling, chain smoking, couch potato who's been told by his doctor to eat healthily, give up smoking and booze and get some exercise but instead just swallows the agile pill and hopes that's enough to save his sorry fat arse. And surprise surprise when the casualties start coming in their gonna blame those pills.&lt;br /&gt;&lt;br /&gt;We have generation after generation bought up on bad practices and incorrect assumptions (smoking isn't bad for you, exercise gives you heart attacks) and what's worse most of them don't even know how bad things are: they think this is NORMAL (sadly because IT IS), they've adjusted to a certain degree of failure.  IT projects are like lifts: sure your pissed off there broken down but your not surprised, you even kinda expected it.&lt;br /&gt;&lt;br /&gt;The mess is big and it's gonna take years to sort it out and a lot of hard work.  And yes, along the way people are going to buy the agile weight loss pill from some dodgy site on the Internet without seeking professional advice, get it wrong.  And why?  Because they're desperate!&lt;br /&gt;&lt;br /&gt;It was totally delusional to think agile was going to result in everyone suddenly rejecting their bad habits and come crawling on their knees and go XP Kosher.  And when that didn't work well there's always the prophesy of the True agile warriors standing in the post-apocolyptic world looking down on the dying as the last breath of those Tragic Lost sigh the now infamous regretful words "we wish we'd read our Domain Driven Designs".  Well don't worry because to become agile all you have to do is close your eyes and say "please Kent forgive us our hacks and deliver us not into Waterfall" and mean it, really mean it, and wait, above the mountain there what's that? is it who I think it is?  It is: the heavens are open and Martin Fowler is ascending into them.&lt;br /&gt;&lt;br /&gt;Let's get real here: developers who have never come across TDD before, who've never experienced it's value first hand, who've spent years doing things a certain way are struggling to grasp the concept and oh sorry that's surprising why?  I guess you were doing TDD from that first Hello World in Pascal?  And those people who go in and try Scrum for the first time and find they are riddled with technical debt because gave into pressure and didn't invest in quality.  Now stand up and be counted all you who never made that mistake.&lt;br /&gt;&lt;br /&gt;I'm not saying that we should just let these things go, hold our noses, ignore the smells and step over the shit.  Quite the opposite.  But we've got to accept that we're not going to walk into a room of professionals and get them to convert overnight (or year or possibly even decade).  How many years did it take before doctors accepted germ theory and started&lt;a href="http://softwarecraftsmanship.oreilly.com/news/2008/9/22/washing-your-hands"&gt; washing their hands&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;Though there is hope: the most effective weapon we have is success.  By being successful and then telling people about why and how we were successful.  That's how this whole agile thing started, that's how it built up it's great reputation and that's how it's going to survive and get better. The more success the more people will start to realize that what they're doing now isn't as good as they think.  Right now not testing, not caring about quality, high technical debt: that's the norm, that's expected.  Keep being successful and people will start asking the others those awkward questions: why does this application crash when my last team were virtually bug free, why does it take a weekend to get a release out when my last team did it in a few minutes?  Why does it take six months to implement a new feature when my last team took a week?  What do you mean there are ramifications and complications?  The more we deliver quality software the less room people will have to worm out of those questions and then the tipping point will come.&lt;br /&gt;&lt;br /&gt;Let's not be mistaken, it's going to be hard work: but isn't that the whole point?  Writing software is hard, agile doesn't change that and at first TDD certainly doesn't.  Yes it's frustrating and somedays you really want to scream and kick in the can but what's the alternative IT ghettos sucking in grads and with no way out?&lt;br /&gt;&lt;br /&gt;If, in the years to come, we want to work in a different industry then we've got to take some responsibility for helping create it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8850447292051515030?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8850447292051515030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8850447292051515030' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8850447292051515030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8850447292051515030'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/11/leave-agile-out-of-it.html' title='That&apos;s right: blame Agile'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8187720143619140946</id><published>2008-11-06T19:37:00.003Z</published><updated>2008-11-06T19:42:20.022Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Refactoring'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Make me Whole</title><content type='html'>&lt;p&gt;This is one of my favourite refactoring patterns and one I find I use a great deal so I thought I'd share it.  The basic premise of this refactoring is to encapsulate logic into its own class using small, easy steps.  The trick is each step should always leave the code in good working order i.e. the tests should always pass.&lt;/p&gt;&lt;p&gt;To help explain I'm going to walk through the refactoring by encapsulating some simple procedural logic and by making the concept explicit by giving it it's own class.  Here's our starting point:&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if @friend == "Jeff" || @friend == "Robert" do&lt;br /&gt;       put "Hello my good friend #friend"&lt;br /&gt;    else&lt;br /&gt;       put "Hello #friend"&lt;br /&gt;    end&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;The first thing we notice is there is some behaviour which depends on the state of &lt;i&gt;friend&lt;/i&gt; (is the value "Jeff" or "Robert").  This is a good sign that there's a concept called &lt;b&gt;Friend&lt;/b&gt; which needs encapsulating.  So here's how:&lt;/p&gt;&lt;h2&gt;Step One: Extract method&lt;/h2&gt;&lt;p&gt;The first step is easy: extract the logic into it's own method like so:&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if is_good_friend do ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def is_good_friend&lt;br /&gt;    @friend == "Jeff" || @friend == "Robert"&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;This is good, now the code is clearer to read and we've encapsulated the logic (albeit only in a method).  That's already a big improvement.&lt;/p&gt;&lt;h2&gt;Step Two: Introduce parameter&lt;/h2&gt;&lt;p&gt;The problem is our method is dependent on its class for the &lt;i&gt;@friend&lt;/i&gt; variable.  We need to sever this connection so the method can stand on its own two feet.  The simple way is to pass &lt;i&gt;friend&lt;/i&gt; through as a parameter.&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if is_good_friend(friend) do ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def is_good_friend(friend)&lt;br /&gt;    friend == "Jeff" || friend == "Robert"&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;That's better: &lt;b&gt;is_good_friend&lt;/b&gt; is decoupled from the class.  Its free!&lt;/p&gt;&lt;p&gt;We still need to get that method onto a new class.  The problem is it can't be done in one easy non-breaking step.  So we're going to have to take a tiny intermediate step to get there:&lt;/p&gt;&lt;h2&gt;Step Three: Make method static&lt;/h2&gt;&lt;p&gt;By making the method static it severs all connections to the original class: it is explicitly non-dependant on any instance variables the original class has.&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if self.is_good_friend(friend) do ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.is_good_friend(friend) ...&lt;/pre&gt;&lt;p&gt;Making the method static is also a good safety check to ensure that you've not got any references to the original class and it is properly isolated before moving it.&lt;/p&gt;&lt;h2&gt;Step Four: Move method&lt;/h2&gt;&lt;p&gt;Now the method is static move it to the new class:&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if Friend.is_good_friend(friend) do ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  class Friend&lt;br /&gt;    def self.is_good_friend(friend) ...&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;Excellent, we're really getting somewhere!  Though now we've got a static method sitting on a helper class.  Yuk: let's get that sorted before someone copies us and that nasty anti-pattern starts to proliferate through our code base:&lt;/p&gt;&lt;h2&gt;Step Five: Create instance&lt;/h2&gt;&lt;p&gt;This is where the real magic starts to happen: we create an instance of our new class and use it to store the value of &lt;i&gt;friend&lt;/i&gt;:&lt;/p&gt;&lt;pre class="code"&gt;  class Friend&lt;br /&gt;    @value&lt;br /&gt;&lt;br /&gt;    def self.is_good_friend(old_friend)&lt;br /&gt;      friend = Friend.new(old_friend)&lt;br /&gt;      friend.value == "Jeff" || friend.value == "Robert"&lt;br /&gt;    end &lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;Still, this is a bit ugly.  What we really need to do is get the client to do the work of creating the instance.&lt;/p&gt;&lt;h2&gt;Step Six: Introduce parameter&lt;/h2&gt;&lt;p&gt;Rather than have our static method new up &lt;b&gt;Friend&lt;/b&gt; get the client to do it and pass it across:&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if(Friend.is_good_friend(@friend, Friend.new(@friend)) ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  class Friend&lt;br /&gt;   ...&lt;br /&gt;    def self.is_good_friend(old_friend, friend)&lt;br /&gt;      friend.value == "Jeff" || friend.value == "Robert"&lt;br /&gt;    end&lt;br /&gt;  end&lt;/pre&gt;&lt;h2&gt;Step Seven: Remove parameter&lt;/h2&gt;&lt;p&gt;The &lt;i&gt;old_friend&lt;/i&gt; parameter is redundant and ugly: let's get rid of it!&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;    if(Friend.is_good_friend(Friend.new(@friend)) ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  class Friend&lt;br /&gt;    ...&lt;br /&gt;    def self.is_good_friend(friend) ...&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;Excellent, this is starting to look a lot better now.  Though look at that repetition: the static method on &lt;b&gt;Friend&lt;/b&gt; passes an instance of it's own class!  Only one way to sort that out:&lt;/p&gt;&lt;h2&gt;Step Eight: Make method non-static&lt;/h2&gt;&lt;p&gt;Now the beauty of this is that if you are using a modern IDE it will work out that the method is being passed an instance of its own type and it will magically do this:&lt;/p&gt;&lt;pre class="code"&gt;  def say_hello()&lt;br /&gt;     if(Friend.new(@friend).is_good_friend) ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  class Friend&lt;br /&gt;     def is_good_friend&lt;br /&gt;         @value == "Jeff" || @value== "Robert" &lt;br /&gt;     end&lt;br /&gt;  end&lt;/pre&gt;&lt;p&gt;Brilliant: &lt;b&gt;Friend&lt;/b&gt; is now nicely encapsulated and ready to grow into a responsible object with a bright future.  From here we can start pushing more behaviour onto the object and eventually make &lt;i&gt;@friend&lt;/i&gt; reference an instance of the &lt;b&gt;Friend&lt;/b&gt; class.&lt;/p&gt;&lt;p&gt;Overall the pattern is very simple: extract the logic into its own method then work to detach it from the class by making in static, then simply move the static method and reattach it to the new class by returning it to an instance.  It  is also possible to handle more complex behaviour with several variables involved, simply pass them through as parameters and then push them onto the new instance.&lt;/p&gt;&lt;p&gt;Although this example is simple the pattern can be repeated again and again to build up classes into a number of methods (sometimes these classes can again be refactored into smaller classes still).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8187720143619140946?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8187720143619140946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8187720143619140946' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8187720143619140946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8187720143619140946'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/11/make-me-whole.html' title='Make me Whole'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-397709751551078557</id><published>2008-10-25T12:07:00.008+01:00</published><updated>2008-10-25T12:29:54.068+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>if(conditional) push.down(to.origin)</title><content type='html'>&lt;p&gt;Conditionals (ifs, switches) are a plague in many code bases and although there are &lt;a href="http://brainscrum.wordpress.com/2007/11/26/the-anti-if-campaign"&gt;campaigns&lt;/a&gt; to prevent their spread many developers are unclear on how to control these pests.   Conditionals are one of the most prevalent, yet tolerated, sources of repetition and bugs.  Why?  Well let's start with one simple yet common example:&lt;/p&gt;&lt;pre class="code"&gt;if(thing.is_valid) do&lt;br /&gt; other_thing.do_something_with(thing)&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;This sort of code spreads like a disease because every time the client calls &lt;b&gt;do_something&lt;/b&gt; it must ensure it checks for validity.  If we look closer at the object in use we find that calling &lt;b&gt;do_something&lt;/b&gt; in an invalid state not only requires the same conditional but also throws an error:&lt;/p&gt;&lt;pre class="code"&gt;def do_something_with(thing)&lt;br /&gt; raise "Thing must be valid" if not thing.is_valid&lt;br /&gt; // do lots of wonderful things with a valid thing&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The repetition is not only in the client code but in tests:&lt;/p&gt;&lt;pre class="code"&gt;def calls_other_thing_when_thing_is_valid&lt;br /&gt; mock_thing.expects(:is_valid).returns(true)&lt;br /&gt; mock_other_thing.expects(:do_something).with(mock_thing)&lt;br /&gt; ...&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def does_nothing_when_thing_is_invalid&lt;br /&gt; mock_thing.expects(:is_valid).returns(false)&lt;br /&gt; ...&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The simplest solution to remove the glut of these conditions (in terms of lines of codes, not calls) is to push it down off the client and to the object who knows his state.  If we go back to the tests and use BDD we find that we would rather define the interactions as such:&lt;/p&gt;&lt;pre class="code"&gt;def tells_thing_to_do_something_when_valid&lt;br /&gt; mock_thing.expects(:when_valid).with(block)&lt;br /&gt;end &lt;/pre&gt;&lt;p&gt;Thing now takes a block (in ruby), delegate (in C#) or anonymous class (in Java):&lt;/p&gt;&lt;pre class="code"&gt;thing.when_valid({other_thing.do_something_with(thing)})&lt;br /&gt;&lt;br /&gt;def when_valid(&amp;amp;block)&lt;br /&gt; &amp;amp;block.call if valid&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;Now the conditional is controlled by the object responsible for its state: we've removed an Ask and replaced it with a Tell.  This is a vast improvement, all the repetition in the clients has gone and the chances of bugs due to accidental calls when in an invalid state are removed.&lt;/p&gt;&lt;p&gt;This presumes that Thing doesn't really do much but chances are it's got lots of behaviour and the chances are that behaviour changes based on being valid or not.  Of course all the methods could delegate to its own &lt;b&gt;when_valid&lt;/b&gt; method but I bet you also need a &lt;b&gt;when_not_valid&lt;/b&gt; and oh boy that code's getting difficult to read.  Also, the repetition, in terms of lines of code may be lower but how many times are conditionals executed during run time?&lt;/p&gt;&lt;pre class="code"&gt;class Thing&lt;br /&gt; def when_valid(&amp;amp;block)&lt;br /&gt;   &amp;amp;block.call if valid&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def other_method&lt;br /&gt;  if valid do&lt;br /&gt;    // do some stuff&lt;br /&gt;  else&lt;br /&gt;    // do some different stuff&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The conditional can still be pushed further down right to its origin: when Thing changes between a valid and invalid state.  This can be achieved by using the &lt;a href="http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html"&gt;Replace Conditional With Polymorphism&lt;/a&gt; refactoring to employ the &lt;a href="http://en.wikipedia.org/wiki/State_pattern"&gt;state pattern&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;&lt;i&gt;NOTE: I want to keep this example clear for developers of other languages though there are &lt;a href="http://blog.jayfields.com/2007/08/ruby-state-pattern-using-modules-and.html"&gt;cleverer ways of achieving this in Ruby&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;&lt;pre class="code"&gt;class Thing&lt;br /&gt; def validate&lt;br /&gt;   valid = // check if valid&lt;br /&gt;   @state_behaviour = valid ? Valid.new : Invalid.new&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def when_valid(&amp;amp;block)&lt;br /&gt;   @state_behaviour.when_valid(&amp;amp;block)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def other_method&lt;br /&gt;   @state_behaviour.other_method&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; class Valid&lt;br /&gt;   def when_valid(&amp;amp;block)&lt;br /&gt;     &amp;amp;block.call&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   def other_method&lt;br /&gt;      // do some stuff&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; class Invalid&lt;br /&gt;   def when_valid(&amp;amp;block)&lt;br /&gt;      // ignore&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   def other_method&lt;br /&gt;      // do some different stuff&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;Now there is only one point where the conditional is called and all of the behaviour for each state (valid or invalid) is in one easy to read place.  Of course, this is just a simple example so just imagine what it would do for more complex solutions (and don't forget: the same can be applied to switches).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-397709751551078557?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/397709751551078557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=397709751551078557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/397709751551078557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/397709751551078557'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/10/ifconditional-pushdowntoorigin.html' title='if(conditional) push.down(to.origin)'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-3565113325382382503</id><published>2008-10-24T10:03:00.003+01:00</published><updated>2008-10-24T10:12:21.766+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>NOJOs are no gos</title><content type='html'>&lt;a href="http://puttingtheteaintoteam.blogspot.com/"&gt;Ivan Moore&lt;/a&gt; gives a specific example (and term) to &lt;a href="http://jupitermoonbeam.blogspot.com/2008/09/faux-oop.html"&gt;Faux OOP&lt;/a&gt; anit-pattern the &lt;a href="http://puttingtheteaintoteam.blogspot.com/2008/10/is-that-pojo-or-nojo.html"&gt;NOJO&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-3565113325382382503?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://puttingtheteaintoteam.blogspot.com/2008/10/is-that-pojo-or-nojo.html' title='NOJOs are no gos'/><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/3565113325382382503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=3565113325382382503' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3565113325382382503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3565113325382382503'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/10/nojos-are-nogos.html' title='NOJOs are no gos'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4018228828364590922</id><published>2008-10-17T08:56:00.006+01:00</published><updated>2008-10-17T09:06:27.219+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Pynchon's Theorem</title><content type='html'>&lt;p&gt;Here's a bit of Agile wisdom from &lt;a href="http://en.wikipedia.org/wiki/Pynchon"&gt;Thomas Pynchon&lt;/a&gt;'s postmodern classic &lt;a href="http://en.wikipedia.org/wiki/Gravity%27s_Rainbow"&gt;Gravity's Rainbow &lt;/a&gt;(page 275 in the Penguin edition):&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;And yet, and yet: there is &lt;a href="http://en.wikipedia.org/wiki/Murphys_law"&gt;Murphy's Law &lt;/a&gt;to consider, that brash Irish proletarian restatement of &lt;a href="http://en.wikipedia.org/wiki/Incompleteness_theorem"&gt;Goedel's Theorem&lt;/a&gt; - when everything has been taken care of, when nothing can go wrong, or even surprise us...something will. [...] when the laws of heredity are laid down, mutants will be born.&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/6794675998088145034-4018228828364590922?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4018228828364590922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4018228828364590922' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4018228828364590922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4018228828364590922'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/10/pynchons-theorem.html' title='Pynchon&apos;s Theorem'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4061482674159016950</id><published>2008-09-18T07:08:00.002+01:00</published><updated>2008-09-18T07:20:02.233+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Faux OOP</title><content type='html'>It may look like OOP and be written in an OOP language and it may have some of the characteristics of OOP such as classes and inheritance but it may, in fact, be Faux OOP.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fortunately Faux OOP is easy to spot as it is actually just procedural code organized into objects.  Tell tale signs of Faux OOP are a separation of data and behaviour with &lt;a href="http://martinfowler.com/bliki/AnemicDomainModel.html"&gt;anemic&lt;/a&gt; data 'objects' manipulated by stateless methods (or procedures) in other classes.  Faux OOP is often littered with classes named with &lt;a href="http://jupitermoonbeam.blogspot.com/2008/09/agent-nouns-are-code-smells.html"&gt;agent nouns&lt;/a&gt; (*Manager, *Helper etc.) or *Service which tend to be stateless (and often singletons or static classes) which hold common variables (better known as global variables).  The rest of the code is built from data classes which consist mainly of getters and setters and no, or rudimentary, behaviour which are poked and prodded by their *Manager counterparts.  The end result is a program consisting of tasks which act upon data structures and use basic program flow (ifs, switches, loops) to execute the tasks in order.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Faux OOP is an anti-pattern promoted by some of the biggest players in the industry:  &lt;a href="http://www.microsoft.com/belux/msdn/nl/community/columns/hyatt/ntier1.mspx"&gt;Microsoft's N-Tier architecture&lt;/a&gt;, popular with VB and early .NET promotes Faux OOP by prescribing a Data layer, &lt;a href="http://msdn.microsoft.com/en-us/library/aa581779.aspx"&gt;Business Layer&lt;/a&gt; and Presentation layer. The presentation layer binds to data objects provided by the data layer which are then validated and actioned via the business layer.  The SOA craze has also helped promote the procedural style where people have reduced their systems to procedural service calls.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Though be careful, you may think you have Faux OOP but really you've got Faux Procedural.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;Faux Procedural&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;It may look like procedural because the program has methods and data structures but if you look closer it may be sequential code organized into methods.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tell tale signs of Faux Procedural are long methods with no distinct separation into common tasks.  These long methods often contain significant repetition and the heavy use of temporary variables.  Common tasks are not abstracted into smaller, reusable methods and common groups of variables have not been abstracted into data structures.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fortunately, with heavy refactoring, Faux Procedural can be refactored into Faux OOP and Faux OOP can be refactored into Real OOP(tm).&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-4061482674159016950?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4061482674159016950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4061482674159016950' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4061482674159016950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4061482674159016950'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/09/faux-oop.html' title='Faux OOP'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-7479931692516110485</id><published>2008-09-12T07:13:00.003+01:00</published><updated>2008-09-12T07:21:12.612+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Code Smells'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Agent nouns are code smells</title><content type='html'>Class names ending in agent nouns are a code smell.  An &lt;a href="http://dictionary.reference.com/browse/agent%20noun"&gt;agent noun&lt;/a&gt; is: &lt;blockquote&gt;any noun that denotes someone or something carrying out the verb's action, typically words ending in -er or -or&lt;/blockquote&gt;Classes with agent nouns are, the majority of the time, a sign of procedural thinking - especially agent nouns such as "manager", "helper" etc.   As the definition says it denotes the class is carrying out the verbs action.   This is contrary to good OOP where the verbs belong to the nouns themselves; classes which represent things are responsible for their own doings, not someone else.  This reflects the real world where I am a Person able to do Programmer tasks, the verbs of programming are executed by me not some CodeProgrammer object which sits next to my desk. &lt;br /&gt;&lt;br /&gt;Agent nouns are useful for describing roles which makes them good for interface names.  A SpellChecker interface on a Dictionary class gives clear definition of the role (to check spelling) and allows the Dictionary to implement the verbs (check_spelling "word"), likewise a SynonymProvider sits well on a Thesaurus class. &lt;br /&gt;&lt;br /&gt;So beware agent nouns; they are a language trick which fools you into believing that a class is a first class concept when really it's stealing someone's verb.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-7479931692516110485?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/7479931692516110485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=7479931692516110485' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7479931692516110485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7479931692516110485'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/09/agent-nouns-are-code-smells.html' title='Agent nouns are code smells'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-7428090711093969025</id><published>2008-08-12T16:02:00.002+01:00</published><updated>2008-08-12T16:12:53.009+01:00</updated><title type='text'>Brain Rules</title><content type='html'>I stumbled across the &lt;a href="http://brainrules.net/"&gt;Brain Rules&lt;/a&gt; website while browsing &lt;a href="http://www.presentationzen.com/presentationzen/2008/05/brain-rules-for.html"&gt;Presentation Zen&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It's a great site and goes through a nice little set of flash slides on how our brains work and how to maximize performance.  I'm sure knowledge based workers (such as developers) could learn a few tricks from this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-7428090711093969025?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://brainrules.net/' title='Brain Rules'/><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/7428090711093969025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=7428090711093969025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7428090711093969025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7428090711093969025'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/08/brain-rules.html' title='Brain Rules'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6666350461814815033</id><published>2008-08-01T07:13:00.004+01:00</published><updated>2008-08-01T07:24:29.704+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Build'/><title type='text'>The Product based build</title><content type='html'>Anyone who has worked on a project of significant size would have grappled with maintaining a build which continuously spins out of control.  It feels like targets become confused, randomly change or seem to be repeated multiple times with only slight variations: "run", "run-without-tests", "run-wth-tests", "redeploy-run" etc. etc. It doesn't take long for the build to become unwieldy.&lt;br /&gt;&lt;br /&gt;People who use the xAnt family or others with XML based languages such as MSBuild will have felt the pain more than those using dynamic language libraries such as Rake as XML is predisposed to becoming quickly unwieldy, is difficult to refactor and expensive to extend (basically XML sucks as a programming language).   Yet, XML or not, most build frameworks share a common flaw: they are task based.  The build becomes defined in terms of a set of steps to be executed and in which order and fairly soon you find you want subtle variations in those steps which result in more tasks.&lt;br /&gt;&lt;br /&gt;But builds aren't linear; we don't always want to run the same dependent steps to achieve the same end result which is why we end up with masses of subtly different targets.  One approach to reduce this is to remove dependancies from targets and have high level targets which simply list a set of steps.  This can lead to flexible systems, as targets can easily be stitched up arbitrarily from the command line as needed, but it requires an intimate knowledge of how the build needs to be executed (which breaks encapsulation) and moves even further down the road of defining a list of steps.&lt;br /&gt;&lt;br /&gt;So how should a build work? In this post I hope to outline what I believe to the be core metaphors and functions of an effective build system.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Product based&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;If we go back to basics and look at the purpose of a build we find it is to produce specific products: a deployable artifact, verification (by running tests), a deployed application, installers etc.  Instead standard build tools promote thinking in terms of linear dependent tasks, for example creating an installer would be defined as "clean, compile, test, create-installer", the build is described in terms of steps, most of which say nothing of the products created.&lt;br /&gt;&lt;br /&gt;A product based build is different: the build is defined in terms of &lt;span class="Apple-style-span" style="font-style: italic;"&gt;products&lt;/span&gt; which are built by &lt;span class="Apple-style-span" style="font-style: italic;"&gt;producers&lt;/span&gt; (or factories to use the GoF pattern).  Products represent the artifacts of the build (binaries, installers, deployed application) and producers contain the logic on how to assemble the products.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Dependancy based&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Similar to task based builds, product based builds are dependancy based.  Where product based builds differ is they view the build process as a factory line where each &lt;span class="Apple-style-span" style="font-style: italic;"&gt;product &lt;/span&gt;is &lt;span class="Apple-style-span" style="font-style: italic;"&gt;produced&lt;/span&gt; from other dependent &lt;span class="Apple-style-span" style="font-style: italic;"&gt;products&lt;/span&gt;.  For example the "installer" &lt;span class="Apple-style-span" style="font-style: italic;"&gt;product&lt;/span&gt; has a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;producer&lt;/span&gt; which packages binaries from the "verified-binaries" &lt;span class="Apple-style-span" style="font-style: italic;"&gt;product&lt;/span&gt; which has a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;producer &lt;/span&gt;which runs tests from a "binaries" &lt;span class="Apple-style-span" style="font-style: italic;"&gt;product&lt;/span&gt; which has a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;producer&lt;/span&gt; that compiles the code from the "fresh-destination" &lt;span class="Apple-style-span" style="font-style: italic;"&gt;product&lt;/span&gt; which has a &lt;span class="Apple-style-span" style="font-style: italic;"&gt;producer&lt;/span&gt; which creates new, clean directories.&lt;br /&gt;&lt;br /&gt;Describing dependancies in terms of products rather than tasks creates a more descriptive build where each product can express its dependancies in a specific way, for example an "acceptance-verified-binaries" product produced from "unit-verified-binaries" expresses a different set of rules from being produced from "binaries".&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Encapsulated&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;When we run the build we shouldn't have to understand the steps required to reach the end result but because of the nature of task based builds they often require an intimate knowledge of their internal workings: for example "run" may depend on "clean, compile, test" but "run-again" may have no dependancies but instead depends on a previous build.  By focusing on products this thinking is broken.  As an example consider the following: in a task based build you can retrieve a set of targets, with their descriptions, from the command line.  To begin to use the build you must understand how the targets relate and what steps are being executed for each target, and from the descriptions (or the task names) work out what the end result may be.  A product based build would give you a list of products but not the steps required to produce them.  This allows the user to quickly understand the goal of the build and how to achieve the desired product without requiring any knowledge of how it is produced.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Non-&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=" font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;repetitive&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Task based build systems are prone to repeating already satisfied dependancies, for example if you ran "build compile, create-installer" and the "create-installer" target had a dependancy on "compile" most build systems would re-execute the "compile" target wasting your time.  To work around this you must create more tasks and again require an intimate knowledge of the build.  Instead when running "produce binaries installer" the product build would be satisfied that it had already produced binaries when it requires them for the input of the installer.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;Order independent&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;As task based builds execute as a series of steps they are order dependent.  Running "build compile test" has different results from "build test compile" (which would either fail or give invalid results depending on whether a previous build had compiled).  As a product based build focuses on products and not steps it is order independent so specifying the following would give equal results:&lt;div&gt;&lt;br /&gt;  &gt; produce binaries verification&lt;br /&gt;  &gt; produce verification binaries&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Presuming that the "verification" product relies on the "binaries" product with the first case the build system would re-use the one produced from the already executed "binaries" request and in the second case it would be satisfied that during the production of the "verification" product it had already been produced.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Polymorphic&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;By focusing on products rather than tasks a product based build system can become polymorphic.  This allows for a very flexible build removing the need for the subtle variations on targets which plague task based builds.  For example you could define a product of "running-application" which is produced from the "binaries" product.  The "binaries" product could be inherited by two other products "verified-binaries" and "unverified-binaries".  By giving the "running-application" product an input of the base "binaries" product it can be produced from both "verified-binaries" and "unverified-binaries".  This allows the user to easily control the build:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &gt; produce verified-binaries running-application&lt;br /&gt;or&lt;br /&gt;  &gt; produce unverified-binaries running-application&lt;br /&gt;or (as we are order independent):&lt;br /&gt;  &gt; produce running-application verified-binaries&lt;br /&gt;or (which would use the default binaries product)&lt;br /&gt;  &gt; produce running-application&lt;br /&gt;&lt;br /&gt;We can also extend "verified-binaries" to "unit-verified-binaries" or "acceptance-verified-binaries" etc. creating support for a build pipeline, or create a "reused-binaries" product to avoid recompiling.  By allowing a build to become polymorphic it becomes both highly flexible and intent is clearer.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Stateful&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Though not absolutely critical state is something most build systems lack.  Every time a build is run the results of the previous build are completely discarded and any valid products are re-created.  State is a difficult concept to implement in task based builds as tasks would have the responsibility of deciding whether the artifacts are still valid, this is further complicated by the fact that multiple tasks may depend on the same artifacts and would therefore have to make the same decision again.  In a product based build each product can decide whether it is valid and the build system would simply reproduce it if it isn't.  Furthermore the build system can analyze the product line and understand that if a product further down the line (say binaries) is invalid then all products produced from it need to be reproduced.&lt;br /&gt;&lt;br /&gt;To conclude by changing the build metaphor from tasks to products we can solve many of the issues around build systems and create clearer, more flexible and more meaningful builds for our applications.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6666350461814815033?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6666350461814815033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6666350461814815033' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6666350461814815033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6666350461814815033'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/08/product-based-build.html' title='The Product based build'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6945235285493829467</id><published>2008-07-27T14:12:00.003+01:00</published><updated>2008-07-27T14:17:26.256+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Decisions, Decisions, Decisions</title><content type='html'>&lt;p&gt;During any development project thousands of decisions will be made.  Every individual in a team will make large numbers of decisions whether about details such as variable names or cross cutting concerns such as architecture.  The success or failure of a project is the sum of all these decisions.&lt;/p&gt;&lt;p&gt;There are two key factors in making decisions: information and risk. The more information we have the better informed the decision is and every decision made - and not made - carries a risk.  Empirical  methodologies (such as Agile and Lean) have contrasting methods to decision making than up-front plan based methodologies such as waterfall.  Fixed-plan methodologies attempt to manage these factors by collecting as much information as possible and then committing to decisions before implementation starts where as empirical methodologies promote delaying decisions until there is enough information available. &lt;/p&gt;&lt;p&gt;Both approaches recognize the importance of information and of managing risk yet they have contradictory views on the best way of dealing with them.  Where fixed-plan methodologies believe that by committing heavily to the informed decision prior to execution you reduce risk empirical methodologies accept that, in reality, every decision that you make ahead of time carries the greatest risk of all: it could be wrong.  The chances of wrong decisions are increased because the information that fixed-plan methods derive their decisions from is essentially highly detailed speculation which in turn is based on a limited amount of real information which carries the risk of being incorrect or out-of-date or even irrelevant.  The strength of commitment increases the impact of a wrong decision even more.  Agile and Lean acknowledge this fact and tackle it head on by managing risk with two techniques: they delay decisions as much as possible until the maximum amount of &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;real&lt;/span&gt; information is available - what Lean calls the last responsible moment (as Lean acknowledges there is also risk in delaying a decision too much) - and they attempt to de-risk decisions by lowering commitment - essentially by allowing change.&lt;/p&gt;&lt;p&gt;Agile and Lean acknowledge that upfront decision making carries the need to cover a great number of hypothetical eventualities than may or may not actually occur.  The crystal ball gazing of fixed-plan methods is an attempt to de-risk the unavoidable gaps in information by trying to account for any possible variation with more pre-made decisions.  Essentially imagine trying to plan out an entire chess game before you play it: every possible move your opponent does or doesn't make would have to be accounted for in the plan.  The end result?  An over complex and convoluted plan (which translates to over engineered, complex software).  Again because Agile doesn't rely on pre-packed decisions, instead acting on the real information, it removes the need to make the "what if" decisions - this is the foundation of the maxim "You Ain't Gonna Need It".&lt;/p&gt;&lt;p&gt;Another aspect that traditional methods fail to tackle is decision paralysis: having one decision to make is hard enough but having to make all decisions infallibly and at once requires omnipotence.  Although some developers believe they are gods Agile recognizes their limitations by giving techniques to allow focus on as few decisions at a time: TDD is a great example of this and so is the maxim "The simplest thing that could &lt;span class="Apple-style-span" style="font-style: italic;"&gt;possibly&lt;/span&gt; work".  &lt;/p&gt;&lt;p&gt;Agile and Lean promote both the overall reduction in decisions and minimizing the number of decisions to be made at one time (essentially by spreading them out across the project).  Pushed to an extreme, decision making can be reduced to being purely reactive.  The purely impractical "URL Driven Development" demonstrates this by only making decisions when the event which creates the need for a decision occurs.  Essentially when someone hits a URL you write just enough HTML to satisfy their request.  Despite being impractical it demonstrates the principles of Just In Time decisions well and should not be used to negate their value within the development cycle where decisions can safely be reduced to being purely reactive.  Test Driven Development uses JIT decisions extensively: you write a test, an event occurs (unsuccessfully) which forces a decision to write just enough code to satisfy that one event, rerunning the test recreates the event and validates your decision and then you move on to add another event forcing another decision.  &lt;/p&gt;&lt;p&gt;Aggressively minimizing the number of decisions which need to be made by simply delaying them or eliminating them altogether has an overall positive effect on a project.  Ensuring that there are few small decisions which require minimum commitment and have the maximum amount of information increases the chances of making good decisions and reduces risk of committing to bad ones.  In short: prefer fewer good decisions than many potentially bad ones.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6945235285493829467?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6945235285493829467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6945235285493829467' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6945235285493829467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6945235285493829467'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/07/decisions-decisions-decisions.html' title='Decisions, Decisions, Decisions'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5391693601327521446</id><published>2008-07-24T07:14:00.004+01:00</published><updated>2008-07-24T07:24:52.895+01:00</updated><title type='text'>Legacy Index</title><content type='html'>&lt;p&gt;A legacy index measures the number of releases a software product has until it becomes legacy.   It can be used to  measure and communicate design quality: the more releases on a code base before change becomes difficult and it gets demoted to a legacy system then the better the design.&lt;/p&gt;&lt;p&gt;The target should be a high legacy index or to reach Legacy Max.  An application that becomes legacy after its first release would be a Legacy Zero app.  The lowest index is awarded to applications which become legacy before they are even released: Legacy minus One! &lt;/p&gt;&lt;p&gt;Applications can still have further releases once they've hit their legacy index: these releases would be identified by consisting mainly of bug fixes and only minor changes, this would be called "pushing the legacy index" as each release would not increase the index.  Also an application may be able to reverse its legacy status by refactoring it to a point where change is again possible. &lt;/p&gt;&lt;p&gt;By measuring and plotting an applications legacy index against time you can clearly see the health and state of an application.  If it has a steady and consistent incline then you know that the design is sound and the application is healthy but if the index has a trend of slowing or is continuously pushing the legacy index then it is clear that there is a problem. &lt;/p&gt;&lt;p&gt;Though quite humorous legacy indexes may have a genuine use in describing the state of an application, you can simply say "this is a Legacy Zero app" or "it's hit its legacy index" and all is clear. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5391693601327521446?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5391693601327521446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5391693601327521446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5391693601327521446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5391693601327521446'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/07/legacy-index.html' title='Legacy Index'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6558543278314971679</id><published>2008-06-11T07:20:00.001+01:00</published><updated>2008-06-11T07:22:56.367+01:00</updated><title type='text'>10 things that should get devs fired</title><content type='html'>Today is the final of The Apprentice and if this years four finalists are representative of Britain's next generation of top business leaders then we have something serious to worry about.  To acknowledge this fact I thought I'd come up with a list of the top ten things that should get developers fired (though please take this in the humorous spirit is is written - I'm not actually advocating firing people).&lt;br /&gt;&lt;br /&gt;So in typical hard-nose, no messing Sir Allen style, here's the list in no particular order (and if you have any good ones please comment):&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. "We're a Microsoft shop we only run Microsoft" (replace with any vendor)&lt;br /&gt;You've limited all design and architectural decisions down to one vendor regardless of suitability, cost effectiveness or productivity pushing up the cost of projects and potentially being left with an unsuitable solution.&lt;br /&gt;&lt;br /&gt;Risking the success of a project by restricting technology choice to one vendor: you're fired!&lt;br /&gt;&lt;br /&gt;2. Prohibiting Open Source Software&lt;br /&gt;Despite the fact that an Open Source product may be the best solution available a prohibition on OS software has prevented its use on projects.&lt;br /&gt;&lt;br /&gt;Dismissing viable solutions with potential benefits to your business: you're fired!&lt;br /&gt;&lt;br /&gt;3. Single language&lt;br /&gt;You've limited the performance of your development by prescribing that all development be done in one single language.  The fact that the language may not be suitable for the job, will perform poorly or be more expensive is ignored over complying with an arbitrary 'strategic' decision to unify all development.&lt;br /&gt;&lt;br /&gt;Running up costs because you can't choose the best tool for the job: you're fired!&lt;br /&gt;&lt;br /&gt;4. "I'm a Java developer I don't do Ruby" (replace with any languages)&lt;br /&gt;Your language defines your role and you only work in that one core language.  You have no interest in other languages and believe your language is the one true language.&lt;br /&gt;&lt;br /&gt;I have no place in my development team for one-trick pony developers: you're fired!&lt;br /&gt;&lt;br /&gt;5. Documented not automated&lt;br /&gt;You'd rather produce a 15 page document with screenshots on how to deploy your application than spend less time automating it.  You place value on creating loads of documentation rather than producing things that actually work.&lt;br /&gt;&lt;br /&gt;Wasting money on something that will be immediately out-of-date and no-one will read: you're fired!&lt;br /&gt;&lt;br /&gt;6. No source control&lt;br /&gt;Projects or critical dependancies have never been added to source control or even worse there's no source control at all.&lt;br /&gt;&lt;br /&gt;This is wholly unacceptable: you're fired!&lt;br /&gt;&lt;br /&gt;7. Artifacts built off of developer boxes&lt;br /&gt;Deployment means opening up Visual Studio, pressing F5, zipping up the dlls and handing them over to IS to install (with a 15 page document).&lt;br /&gt;&lt;br /&gt;You are a cowboy, this is simply unprofessional and amateurish: you're fired!&lt;br /&gt;&lt;br /&gt;8. No automated tests&lt;br /&gt;You never write automated tests and simply rely on the old "run and click about" or the "run the test console and check the results" methods of testing.&lt;br /&gt;&lt;br /&gt;No way of verifying your changes, there's no room for hackers: you're fired!&lt;br /&gt;&lt;br /&gt;9. No CI&lt;br /&gt;There is no visibility of the state of the code base and as long as it runs on your machine then that's OK by you.&lt;br /&gt;&lt;br /&gt;No way of understanding the status of the code base: you're fired!&lt;br /&gt;&lt;br /&gt;10. You're an architect&lt;br /&gt;What more can I say?  You probably disagree with this whole list especially because it doesn't come with a Visio diagram and can't be orchestrated in BizTalk.  You're fired!&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6558543278314971679?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6558543278314971679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6558543278314971679' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6558543278314971679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6558543278314971679'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/06/10-things-that-should-get-devs-fired.html' title='10 things that should get devs fired'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-2476133810158188030</id><published>2008-05-23T22:21:00.002+01:00</published><updated>2008-05-23T22:23:50.509+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Women in IT'/><title type='text'>It's ladies night</title><content type='html'>More on women in IT there's a &lt;a href="http://lifeandhealth.guardian.co.uk/women/story/0,,2281782,00.html"&gt;great article&lt;/a&gt; on the Guardian about the &lt;a href="http://londongirlgeekdinners.co.uk/"&gt;Geek Girl Dinners&lt;/a&gt; movement.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-2476133810158188030?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://londongirlgeekdinners.co.uk/' title='It&apos;s ladies night'/><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/2476133810158188030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=2476133810158188030' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2476133810158188030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2476133810158188030'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/05/its-ladies-night.html' title='It&apos;s ladies night'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6419031900592671783</id><published>2008-04-25T08:32:00.007+01:00</published><updated>2008-04-25T16:50:28.753+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DLR'/><category scheme='http://www.blogger.com/atom/ns#' term='ALT.NET'/><title type='text'>The Snake and The Emerald in The Mesh</title><content type='html'>Back in the first days of the new millenia when &lt;a href="http://www.microsoft.com/Presspass/press/2000/jul00/pdcdeliverspr.mspx"&gt;.NET pamphlets&lt;/a&gt; first hit the desks of Microsoft shops the world over one of the great and exciting features being sold was multilanguage development.  Microsoft &lt;a href="http://support.microsoft.com/kb/315838/en-us?spid=7796&amp;amp;sid=1081"&gt;painted a world&lt;/a&gt; where the UI team could beaver away happily and productively in VB.NET while the back end team got hard core writing business logic in C#.  Microsoft even talked about other vendors writing languages for .NET including Perl (which was actually one of the languages supported by the original ASP through the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms974552.aspx"&gt;Windows Scripting Engine&lt;/a&gt;) and Microsoft Marketing painted a picture of a world blind to the prejudices of different languages.&lt;br /&gt;&lt;br /&gt;Fairly soon the dust settled over the pamphlets and everyone forgot about the great multi-language dream, .NET was as polorized as British politics: there was Labour and Tory, C# and VB, no other language got a look in and those that existed were merley academic exercises of no importance to your MVP.  There were many critics of the importance of multi-language support in .NET and they were feeling proven right.&lt;br /&gt;&lt;br /&gt;At the same time another important trend was occuring: the rise of static languages: Java, C#, VB.NET are all strongly typed.  Now even VB was strongly typed MS developers felt confident to dismiss dynamic typed languages as toys for script kiddies, web designers and network engineers. Grown-up enterprise development required things like type safety and checking.&lt;br /&gt;&lt;br /&gt;So now the world is strongly typed and .NET settles around VB and C# and Java is just Java, the battle lines are clear: who is the king of the strongly typed. Then all of a sudden, out of nowhere, the alpha geeks decide that dynamic languages are the thing: Ruby, Python and Groovy, people are re-realising that dynamic languages can do very, very cool things which strongly typed languages struggle to express.&lt;br /&gt;&lt;br /&gt;A new level starts in the arms race between Sun and Microsoft as people start trying to implement dynamic languages on top of the JVM and &lt;a href="http://msdn2.microsoft.com/en-us/library/ddk909ch(vs.71).aspx"&gt;CLR&lt;/a&gt;.  Java gets Jython and JRuby and a glut of projects attempt dynamic languages on the CLR including Microsoft's own IronPython but then all of a sudden people realize something: the CLR wasn't designed to do dynamic languages: sure you can build languages on top of the CLR but gone is the dream of having C# assemblies seemlessly call Python assemblies without even knowing it.&lt;br /&gt;&lt;br /&gt;Fortunately Microsoft had the guts (or rather Jim Hugunin did) to sort this problem out and get .NET back to where it should be and the Dynamic Language Runtime was born.  The DLR sits &lt;a href="http://msdn2.microsoft.com/en-us/magazine/cc300810.aspx"&gt;ontop of the CLR&lt;/a&gt; and allows all the dynamic goodness of languages like Ruby and Python (and now VB 10) &lt;a href="http://blogs.msdn.com/hugunin/archive/2007/05/02/the-one-true-object-part-1.aspx"&gt;to work as equals&lt;/a&gt; alongside C# and VB.NET code.  The DLR will allow &lt;a href="http://lists.ironpython.com/pipermail/users-ironpython.com/2008-January/006235.html"&gt;a new phase&lt;/a&gt; of the polyglot dream to emerge: C# calling Python calling Ruby calling VB and every combination in between.&lt;br /&gt;&lt;br /&gt;Microsoft are going to start pushing IronPython and dynamic languages hard.  It is one of the main features of &lt;a href="http://silverlight.net/GetStarted/overview.aspx"&gt;Silverlight 2.0&lt;/a&gt; and being expanded to &lt;a href="http://www.asp.net/IronPython/whitepaper/"&gt;ASP.NET&lt;/a&gt;.  Interestingly MS is positioning dynamic languages firmly in the web and UI arena (which makes sence as this is where they are traditionally strong).  In reality dynamic languages aren't restricted to the UI layer and entire applications can be written in them, though I think Microsoft aren't pushing this point because they don't want to scare or alienate their core developer community.  Any how the people who would want to do will try and do it.&lt;br /&gt;&lt;br /&gt;There are a few interesting issues arising out of the dynamic languages race:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;When is Ruby/Python not Ruby/Python?&lt;/span&gt;&lt;br /&gt;As languages run on the the CLR can talk to the .NET framework and other .NET libraries they break compatability between other interpreters: though it's still legal Ruby/Python code it isn't going to run on any other interpreter.  DLR languages can also be compiled to .NET assemblies breaking all compatability with anyone else.  Some see a risk here of MS "restandardising" pointing to HTML as an example.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Why run IronRuby/Python when you could just Ruby/Python?&lt;br /&gt;&lt;/span&gt;Technically there are a few answers about integration with .NET etc. but they are pretty weak when it comes to writing apps in one language.  Leveraging the power of dynamic languages from within a .NET app (i.e. polyglots) is the main selling point, otherwise, for those who are simply going to write pure Ruby/Python code, then the big thing is ratification: for those .NET shops out there who still believe the MS FUD of previous years simply putting MS in front of the language makes it acceptable.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;What about open source?&lt;br /&gt;&lt;/span&gt;Both Python and Ruby are open source languages so isn't this a bit incompatable with MS?  Interestingly both IronPython and IronRuby are open source (under the &lt;a href="http://www.opensource.org/licenses/ms-pl.html"&gt;Microsoft Public License&lt;/a&gt;) and because the DLR came from the work on IronPython it is also open source.  IronPython is hosted on CodePlex but IronRuby - in an attempt to engage the Ruby community - is &lt;a href="http://rubyforge.org/projects/ironruby/"&gt;hosted on RubyForge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6419031900592671783?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6419031900592671783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6419031900592671783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6419031900592671783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6419031900592671783'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/04/snake-and-emerald-in-mesh.html' title='The Snake and The Emerald in The Mesh'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5223868126958457950</id><published>2008-03-18T16:04:00.007Z</published><updated>2008-03-18T16:22:18.084Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='mono'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Polymonoism (AKA the legend of cross platform .NET)</title><content type='html'>&lt;div&gt;After using &lt;a href="http://www.jetbrains.com/idea/index.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;IntelliJ&lt;/span&gt;&lt;/a&gt; for the last nine months or so I have realised how much Visual Studio sucks (even with &lt;a href="http://www.jetbrains.com/resharper/index.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Resharper&lt;/span&gt;&lt;/a&gt;).  The problem I have with VS is the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;IDE&lt;/span&gt; seems to be focused on everything but writing code and I feel there is only ten percent of it I use and that only does ten percent of what I can do with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;IntelliJ&lt;/span&gt;.  I, like many others, really wish there was an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;IntelliJ&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;plugin&lt;/span&gt; for .NET (in particular C#) or even a whole &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;IntelliC&lt;/span&gt;, however the news on the street is despite &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;JetBrains&lt;/span&gt; hinting rather explicitly that such a thing was in the pipe line &lt;a href="http://www.intellij.net/forums/thread.jspa?threadID=266968&amp;amp;tstart=0"&gt;they've shelved the idea &lt;/a&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;BOOO&lt;/span&gt;).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can't blame &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;JetBrains&lt;/span&gt; for wanting to focus their efforts on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Resharper&lt;/span&gt;: MS developers, as a herd, generally keep to the MS straight and narrow and fear wandering from the vendor's path of least wisdom.  It makes no commercial &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;sence&lt;/span&gt; to develop an alternative &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;IDE&lt;/span&gt; from Visual Studio when most MS &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;devs&lt;/span&gt; won't even bother to look beyond the MS brochure.  As a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;plugin&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;Resharper&lt;/span&gt; is going to hit a bigger market.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a shame and a loss for choice: the Java community has healthy competition with its &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;IDEs&lt;/span&gt; and plenty of innovation with it but, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Borland&lt;/span&gt; aside, this culture doesn't exist in the mainstream MS world (hence why Visual Studio's '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;refactoring&lt;/span&gt;' and 'testing' features are a joke). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other issue is that Visual Studio only runs on one platform (Windows) for one vendor (MS funnily enough); from the ground up most Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;IDEs&lt;/span&gt; support multiple platforms and multiple vendors of the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;JDK&lt;/span&gt; and compilers.  Why is this of any relevance for .NET - who would want to develop it on anything else when it only runs on Windows anyway?  Firstly I don't want to develop on Windows: I find it an awful OS for doing development on and I am far more productive on Linux or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;OSX&lt;/span&gt; (like many I have a preference for a different OS which happens not to be Windows: why should that even be a statement?), secondly I don't &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_22"&gt;necessarily&lt;/span&gt; want to run my .NET applications on Windows: after the luxury of working with true &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_23"&gt;multi platform&lt;/span&gt; languages such as Java and Ruby I find it really frustrating to have to ditch everything positive about working cross-platform (and that means working on Windows too) and be shoved into a corner where my choice is simply &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;XP&lt;/span&gt; or one of the 26 variations of Vista. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even though I may not express a preference for working on Windows or with Visual Studio but there are many things about .NET I really like: there are things about the cleanliness of the language and the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;SDK&lt;/span&gt; which trumps Java (generics anyone?).  The real advantage Java has over .NET is the community around it and the way Sun has left people free to contribute to it, there is far more innovation coming from the Java community than from the .NET one (hell, the .NET community is just trying to port as many Java projects as quickly as it can).  However the .NET community is growing (especially with the ALT.NET movement) and it isn't to hard to wriggle out of the MS straight jacket.  All in all there's a real feeling of excitement around .NET at the moment despite &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;MS's&lt;/span&gt; attempts to lump as many bad practices into it as they can.  As a result .NET is a serious contender to Java except it falls flat on its face when it comes to cross platform support.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well there may be some hope out there: mono is &lt;a href="http://www.mono-project.com/Roadmap"&gt;coming along nicely&lt;/a&gt; (with almost full 2.0 compatibility) and comes as part of Gnome (so for Linux it's already there) and there is a version for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;OSX&lt;/span&gt;.  With a bit of support and real world proof mono has the potential to become a real Java killer. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem is you're not going to be able to compile to mono in Visual Studio and even if you could you can still only run VS on Windows solving only half the problem.  The other problem is Mono &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;IDEs&lt;/span&gt; suck: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;monodevelop&lt;/span&gt;, a sterling effort, is like going back in time 15 years.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;SharpDevelop&lt;/span&gt; (from which &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;monodevelop&lt;/span&gt; was originally forked) would be cool but again it only runs on Windows (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;booooo&lt;/span&gt; to you &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;icsharp&lt;/span&gt;).  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A bit of research and I stumbled across a little &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;IDE&lt;/span&gt; from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;Omniture&lt;/span&gt; call &lt;a href="http://www.omnicore.com/en/xdevelop.htm"&gt;X-Develop&lt;/a&gt;.  Not only does it run on Windows, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;OSX&lt;/span&gt; and Linux but it can handle C#, J#, Visual Basic and Java compiling to whatever framework you choose including mono.  The word on the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;blogoshpere&lt;/span&gt; is that X-Develop is a usable, productive &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;UI&lt;/span&gt; and despite not being as feature rich as &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;IntelliJ&lt;/span&gt; (it's &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;refactoring&lt;/span&gt; support is weaker) or Visual Studio (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;UI&lt;/span&gt; designers) is a slick, quick, lightweight, cross platform &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;IDE&lt;/span&gt;, which includes all the essentials including basic r&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;efactoring&lt;/span&gt; (one up on VS), error highlighting (another up on VS) , debugging etc.  The good news for fans of other &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;IDEs&lt;/span&gt; is that you can choose to map &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;keybingins&lt;/span&gt; from Visual Studio, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;IntelliJ&lt;/span&gt;, Eclipse and others.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The downside is you have to pay for it and at $499 per license it isn't the sort of thing you'd buy on a whim.  Naturally I'd prefer it to be open source but I'm going to be realistic that people have to make money though a cut down OS version without the designers etc. for free may be a wise move to get people hooked.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;Omniture&lt;/span&gt; seem to be giving a serious proposition that no other vendor can match in terms of true cross platform, cross framework development and that is a fantastic thing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;Ominiture&lt;/span&gt; are going to have is appealing to the Java and Linux community who do have a preference for free software.  The problem mono has is that without a decent cross platform &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;IDE&lt;/span&gt; it's not going to gain serious ground.  I think both sides need to reach out and touch each other to ensure mono gets the real-estate it deserves.  I for one would be seriously excited about developing true cross platform applications in C# on my Mac or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;Ubuntu&lt;/span&gt;.  Hopefully it may be a future arriving quite soon and not just another broken pipe dream.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5223868126958457950?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5223868126958457950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5223868126958457950' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5223868126958457950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5223868126958457950'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/03/polymonoism-aka-legend-of-cross.html' title='Polymonoism (AKA the legend of cross platform .NET)'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4671538310383180992</id><published>2008-03-17T09:50:00.012Z</published><updated>2008-03-17T11:36:05.491Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Women in IT'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>The rise of the Nu-Geeks</title><content type='html'>At QCon last Thursday &lt;a href="http://www.threeriversinstitute.org/Kent%20Beck.htm"&gt;Kent Beck&lt;/a&gt; gave a keynote on &lt;a href="http://jaoo.dk/london-2008/file?path=/qcon-london-2008/slides/KentBeck_TrendsInAgileDevelopment.pdf"&gt;Trends in Agile Development&lt;/a&gt;.  There were lots of interesting slides about the rise in tests, quick releases and lots of other agileness but the most interesting aspect of the talk for me was the rise of the new generation of tech savvy business professionals.  The old "wizards" detectable by their strange socially inappropriate behaviour are out as a generation of Nu-Geeks with social skills like listening, team work and emotional intelligence are rising to the challenge of making businesses happy.&lt;div&gt;&lt;div&gt;I've never been one for the old skool geek, I'd go as far to say I am a NAG (Not A Geek) and have found myself often frustrated by people trying to tar me with the brush of demeaning stereotypes - the most extreme example being a senior manager who put the IT department in the basement believing we would be more comfortable far from the real world of human interaction (no clients were ever bought to the basement by the way: except if they were techies themselves) - so I identify strongly with this rise.   This is one of the many reasons I was attracted to Agile, listening to Kent Beck talk reminded me that what I found refreshing about &lt;a href="http://www.amazon.co.uk/Extreme-Programming-Explained-Embrace-Change/dp/0321278658"&gt;Extreme Programming Explained&lt;/a&gt; was the focus on the social side of development and the reason I signed the &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt; was the belief in "people over process".&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This all supposes that the stereotype ever existed.  The feminist and existentialist &lt;a href="http://en.wikipedia.org/wiki/Simone_de_Beauvoir"&gt;Simone de Beauvoir&lt;/a&gt; (friend and influencer of &lt;a href="http://en.wikipedia.org/wiki/Jean-Paul_Sartre"&gt;Jean-Paul Sartre&lt;/a&gt;) argued that stereotyping is a form of subjugation and always done in societies by the group higher in the hierarchy to the group lower in the hierarchy so that the lower group became the “other” and had a false aura of mystery around it.  How accurately does that describe the IT industry with the exception that perhaps there is a bi-directional purpose to the stereotype: one from outside the group to keep the geeks in and the other from inside to keep the women out?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully as the geeky male image &lt;a href="http://www.guardian.co.uk/environment/2008/mar/16/glaciers.climatechange"&gt;melts faster than the ice caps&lt;/a&gt; we will start to see more women join the fray.  Recent news seems to offer a strong promise of this trend.&lt;br /&gt;&lt;br /&gt;Girl's found &lt;a href="http://news.bbc.co.uk/1/hi/education/336390.stm"&gt;computers too macho&lt;/a&gt; back before the turn of the millennium and research blamed the strong male images and metaphors such as pirates, ships and planes opposed to softer, feminine images (apparently teddy bears  and flowers).  Now the tables have turned and research by Tesco found that &lt;a href="http://www.computersforschools.co.uk/news.html?id=16" style="text-decoration: none;"&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;girls are more computer &lt;/span&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;savvy&lt;/span&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt; than boys&lt;/span&gt;&lt;/a&gt;.  So as the last bastion of strictly male territory falls so will the old stereotype of the geek-knight on a white mac coming to the rescue of the maiden caught by the evil Word dragons.  Unfortunately this will leave a horde of male geeks without any chance of female contact.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The trend is fierce and girls are not only better at computers than boys but are also more prolific with it.  Apparantly the growth of social networking and blogging is &lt;a href="http://technology.timesonline.co.uk/tol/news/tech_and_web/the_web/article3511863.ece"&gt;"almost entirely fuelled by girls"&lt;/a&gt;.  Gaming is another area which women are conquering with girl gamers being &lt;a href="http://technology.timesonline.co.uk/tol/news/tech_and_web/personal_tech/article2690501.ece"&gt;the fastest growing group in the entertainment industry&lt;/a&gt;.  Not only that but there are more Nintendo DSs sitting snuggly in the hands of the fairer sex (54%) than the soft unworked hands of the coffee crunching, light fearing, cellar dwelling male geek of old (only 46%).  Nintendo's own research show that it "continues to reach more women ... a significant percentage of all Touch Generations software buyers are female".  No wonder the new face of Nintendo is &lt;a href="http://news.bbc.co.uk/2/hi/entertainment/6237020.stm"&gt;Nicole Kidman&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.thoughtworks.co.uk/work-for-us/back-to-IT.html"&gt;ThoughtWorks is taking the challenge on&lt;/a&gt; to help resolve the problem.  My suspicion is that Agile itself may be the greatest weapon in the battle: a development methodology with a more people centric, reality focused approach which values the softer skills and attempts to bridge the gulf between writing code and actually creating real things.   It is those real things I am motivated by and I know that personally, without Agile, I would be struggling to maintain my sanity in the IT industry of old.&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/6794675998088145034-4671538310383180992?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4671538310383180992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4671538310383180992' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4671538310383180992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4671538310383180992'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/03/nu-geeks.html' title='The rise of the Nu-Geeks'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-901707951180146673</id><published>2008-03-10T20:20:00.005Z</published><updated>2008-03-10T20:31:49.052Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Encapsulation'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>"I'll show you mine if you show me yours" vs "You tell me and I'll tell you"</title><content type='html'>&lt;p&gt;Avoiding breaking encapsulation can sometimes be difficult.  The most common &lt;a href="http://jupitermoonbeam.blogspot.com/2007/05/encapsulating-top-trump-objects.html"&gt;encapsulating breaking habit is using field accessors (properties/getters and setters)&lt;/a&gt;, these can break encapsulation as the object looses control over how it's information should be interpreted and also a language is never built up.  Here is an example: in a banking application the system needs to know if the account is overdrawn, it would be common to do:&lt;/p&gt;&lt;pre class="code"&gt;if(account.balance &lt; 0) ... do something&lt;/pre&gt;&lt;p&gt;This code could be scattered across the system: however, what if a new business rule came in to say that if an account is frozen it shouldn't be marked as overdrawn?  All those statements are incorrect and have to be changed.  If behaviour had been put on the account it would have been simpler to do:&lt;/p&gt;&lt;pre class="code"&gt;if(account.is_overdrawn) ... do something&lt;/pre&gt;&lt;p&gt;Then the Account is in complete control over what it considers as being overdrawn.  This is a simple example and easy to solve but what if there is an exchange of information between two objects? Breaking encapsulation seems a hard thing to avoid.  For example:&lt;/p&gt;&lt;pre class="code"&gt;if(loan.amount + account.balance &lt; 0) ... do something&lt;/pre&gt;&lt;p&gt;This is a classic case of "I'll show you mine if you show me yours": the loan exposes it's amount and the account exposes it's balance, both objects have lost control of their data.   In the real world this would create scenarios of ridiculous bureaucratic proportions.  Let's prove this with an application which models a host offering a guest a drink.  Using the non-encapsulated method is the equivilant of having a third party ask both of you for private information and then doing the selection for you.  Here it is in code:&lt;/p&gt;&lt;pre class="code"&gt;class IllShowYouMineIfYouShowMeYours&lt;br /&gt; def main&lt;br /&gt;  host.drinks.eachType | drinkType | do&lt;br /&gt;   if(guest.drinks.containsType(drinkType)) do&lt;br /&gt;    drink = drinks.get(drinkType)&lt;br /&gt;  &lt;br /&gt;    if(drink.is_consumed) do&lt;br /&gt;     throw AlreadyConsumedException.new&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    guest.energy.add(drinks.get(drinkType).calories)&lt;br /&gt;    drinks.remove(drink)&lt;br /&gt;    drink.is_consumed = false&lt;br /&gt;   end   &lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;A better way to solve this is to use "You tell me and I'll tell you".  In the real world the host would ask "what would you like to drink?" and the stock reply is "what have you got?" they would then tell you what drinks they have and you'd tell them which drink you want: neither of you expose any data: there is no case of the guest rummaging through the host's cupboards, the host can select their drinks themselves and the guest is allowed to decide what they'd like.  By telling the Host to offer the drinks the Host can tell the Guest to choose one and encapsulation isn't broken.  Here is the alternative:&lt;/p&gt;&lt;pre class="code"&gt;class YouTellMeAndIllTellYou&lt;br /&gt; def main&lt;br /&gt;  drink = host.give_drinks_to(guest)&lt;br /&gt;&lt;br /&gt;  if(drink.is_consumed) do&lt;br /&gt;  . . .&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Host&lt;br /&gt; def give_drinks_to(guest)&lt;br /&gt;  drink = drinks.get(guest.which_drink(drinks.getTypes))&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Guest&lt;br /&gt;&lt;br /&gt; def which_drink(drinkTypes)&lt;br /&gt;  drinkTypes.each |drinkType| { return drinkType if drinks_i_like.contains(drinkType) }&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;There is room for further encapsulation: the consumption of the drink still relies on outside manipulation, we have another case of "I'll show you mine" but even worse as it's not only showing it but it's letting just about anyone touch it too!  So let's tell the guest to take the drink and tell the drink to give nutrition to the guest.&lt;/p&gt;&lt;pre class="code"&gt;class YouTellMeAndIllTellYou&lt;br /&gt; def main&lt;br /&gt;  drink = host.give_drinks_to(guest)&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Host&lt;br /&gt; def give_drinks_to(guest)&lt;br /&gt;  drink = drinks.get(guest.which_drink(drinks.getTypes))&lt;br /&gt;  guest.give(drink)&lt;br /&gt;  drinks.remove(drink)&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Guest&lt;br /&gt; .&lt;br /&gt; .&lt;br /&gt; .&lt;br /&gt;&lt;br /&gt; def give(drink)&lt;br /&gt;  drink.consume(self)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def increase_energy(increase_by)&lt;br /&gt;  calories = calories + increase_by&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def Drink&lt;br /&gt; def consume(consumer)&lt;br /&gt;  if(is_consumed) do&lt;br /&gt;   throw AlreadyConsumedException.new&lt;br /&gt;  end &lt;br /&gt; &lt;br /&gt;  consumer.increase_energy(calories)&lt;br /&gt;  is_consumed = true&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;By encapsulating the behaviour we have given ourselves a number of advantages.  The first and most obvious of them being testing: the encapsulated code is much easier to test as the behaviour of each class can be independantly tested and verified.  We also stop spread: without those getters and setters it is very difficult to add behavior centric to those classes in any other parts of the application: all behaviour to do with the class is in one place, this means less repetition, less bugs and less maintenance.  We also allow Single Responsibility: if we wanted to change the way the drinks worked (say from a list to a hash) then we can do safelty without breaking any code.  Lastly we have code which supports polymorphism: for example if we wanted to add alcoholic drinks to the system, we can polymorphically add a different type of drink which causes a guests to become drunk:&lt;/p&gt;&lt;pre class="code"&gt;class AlcoholicDrink&lt;br /&gt; def consume(consumer)&lt;br /&gt;  if(is_consumed) do&lt;br /&gt;   . . .&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  consumer.increase_alcohol_levels(units)&lt;br /&gt;    . . . &lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The guest can also be made polymorphic:&lt;/p&gt;&lt;pre&gt;def TeaTotalGuest&lt;br /&gt; def give(drink)&lt;br /&gt;  if(drink.is_alchoholic) throw IDontDrinkException.new&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def LightWeight&lt;br /&gt; def increase_alcohol_levels(units)&lt;br /&gt;  total_units += units&lt;br /&gt;  if(total_units &gt; 3) spew&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def PartyAnimal&lt;br /&gt; def increase_alcohol_levels(units)&lt;br /&gt;  total_units += units&lt;br /&gt;  if(total_units &gt; 10) start_dancing&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;All of the above polymorphic behavior can be easily added without ever changing the code of any consumers, in the non-encapsulated version there would be a nightmare or nested if's and switch statements which would make even our TeaTotalGuest dizzy and want to spew.  Or to quote &lt;a href="www.nealford.com"&gt;Neal Ford&lt;/a&gt;: &lt;br /&gt;&lt;a href="http://www.iasahome.org/web/itarc/atlanta/Agenda?p_p_id=20&amp;p_p_action=1&amp;p_p_state=exclusive&amp;p_p_col_id=null&amp;p_p_col_pos=0&amp;p_p_col_count=1&amp;_20_struts_action=%2Fdocument_library%2Fget_file&amp;_20_folderId=149&amp;_20_name=Neal_Ford-10_Ways_To_Improve_Your_Code-handouts.pdf"&gt; "getters/setters != encapsulation.  It is now a knee-jerk reaction to automatically create getters and setters for every field. Don't create code on auto-pilot!  Create getters and setters only when you need them 10 Ways to Improve Your Code"&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;As a final note to readers: please drink responsibly!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-901707951180146673?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/901707951180146673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=901707951180146673' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/901707951180146673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/901707951180146673'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/03/ill-show-you-mine-if-you-show-me-yours.html' title='&quot;I&apos;ll show you mine if you show me yours&quot; vs &quot;You tell me and I&apos;ll tell you&quot;'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-2648269995606339844</id><published>2008-03-07T14:58:00.002Z</published><updated>2008-03-07T15:11:05.559Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Balancing Greed with Anemia</title><content type='html'>&lt;p&gt;I am many things to many people.  If I go to the doctors I am a patient, when at work I am an employee, when at home, with my wife, I am a husband.  I cannot be all these things at the same time and I need to behave differently with different people and what's more my doctor isn't interested in me as an employee, my employee cares not for my detailed medical history and my wife certainly doesn't care what languages I can program in let alone the content of my blog!&lt;/p&gt;&lt;p&gt;Readers of Domain Driven Design will be familiar with the concept of Aggregates: simply put an aggregate provides a boundary around concepts which are closely related and provides an entry point to those other entities.  If you were modelling people the Person class would be an aggregate, within the person class would be other classes and methods to do with my medical state, languages I can program in and package private methods between my wife and I.  Using a behaviour centric domain finding we can write code like this:&lt;/p&gt;&lt;pre class="code"&gt;class Client &lt;br /&gt; def do&lt;br /&gt;  john = employeeRespotory.find("John")&lt;br /&gt;&lt;br /&gt;  if(john.is_not_skilled_in(:AnyJava)) do&lt;br /&gt;   john.train(:BeginnersJavaCourse)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  john.can_do_job(Job.new(:SqlServer, :DotNet))&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Person &lt; Skilled&lt;br /&gt; skills&lt;br /&gt;&lt;br /&gt;  def is_skilled_in(skill) &lt;br /&gt;  if(skills.not_contains(skill.type)) do&lt;br /&gt;   return false&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  return skills.get(skill.type).is_at_level(skill.level)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def is_not_skilled_in(skill)&lt;br /&gt;  !is_skilled_in(skill)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; boolean train(Training)  &lt;br /&gt;  if(skills.not_contains(Training.skill) do&lt;br /&gt;   skills.add(Training.skill)&lt;br /&gt;  else&lt;br /&gt;   skills.get(Training.skill).upgrade(Training.level)&lt;br /&gt;  end&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt; def can_do_job(Job)&lt;br /&gt;  Job.matches_skills(this)&lt;br /&gt; end &lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Job&lt;br /&gt; def matches_skills(skilled)&lt;br /&gt;  Skills.each | skill | do&lt;br /&gt;   return false if skilled.is_not_skilled_in(skill)&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Test &lt;br /&gt; def can_be_skilled_in_something&lt;br /&gt;  skills = Skills{:BasicJava}&lt;br /&gt;  testPerson = new TestPerson(skills)&lt;br /&gt;&lt;br /&gt;  assert_true(testPerson.is_skilled_in(:BasicJava))&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def can_be_trained_in_something&lt;br /&gt;  testPerson = TestPerson.new(:NoSkills)&lt;br /&gt;  skill = Skill.new(Java, Basic)&lt;br /&gt;&lt;br /&gt;  testPerson.train(Training.new(skill))&lt;br /&gt;  assert_true(testPerson.is_skilled_in(skill))    &lt;br /&gt; end&lt;br /&gt; ... plus all the other tests&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The problem is if we placed all of this behaviour and data in one Person class it will quickly get on the big side.  This is what I call a Greedy Aggregate: in the same way I don't try to be all things to all people a class shouldn't try to be all things to all clients.&lt;/p&gt;&lt;p&gt;The biggest criticism I have heard about placing behaviour on Domain objects is the problem of Greedy Aggregates: huge classes that end up with bags of methods and test classes as long as your arm.  The solution often presented is to move to a Service paradigm instead.  I agree with the complaint of Greedy Aggreates but not the solution as the service paradigm moves code away from being object orientated and towards procedural.  The above in service orientated code would be:&lt;/p&gt;&lt;pre class="code"&gt;class Client &lt;br /&gt; def do&lt;br /&gt;  john = employeeRespotory.find("John")&lt;br /&gt;&lt;br /&gt;  if(employeeService.is_not_skilled_in(john, :Java)) do&lt;br /&gt;   employeeService.train(john, :BeginnersJavaCourse)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  employeeService.can_do_job(john, Job.new(:SqlServer, :DotNet))&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class EmployeeService &lt;br /&gt;        skillsRespository  &lt;br /&gt; def is_skilled_in(person, skill) do&lt;br /&gt;  if(skillsRespository.not_contains(person.id, skill.type)) do&lt;br /&gt;   return false&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  return skillsRespository.get(skill.type).is_at_level(skill.level)&lt;br /&gt;        end&lt;br /&gt;&lt;br /&gt; def is_not_skilled_in(person, skill)&lt;br /&gt;  !is_skilled_in(person, skill)&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def train(person, training) do&lt;br /&gt;  if(skillsRepository.not_contains(person.id, training.skill)) do&lt;br /&gt;   skillsResponsity.add(person.id, Training.skill)&lt;br /&gt;  else&lt;br /&gt;   skillsResponsity.get(prson.id, taining.skill).upgrade(training.level)&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; boolean can_do_job(person, job) {&lt;br /&gt;  job.eachSkill |skill| do &lt;br /&gt;   return false if is_not_skilled_in(person, skill)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  return true&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def Test&lt;br /&gt; def canBeSkilledInSomething&lt;br /&gt;  testPerson = TestPerson.new&lt;br /&gt;  skill = new Skill(Java, Basic)&lt;br /&gt;  MockRepository {&lt;br /&gt;   expect.contains(testPerson.id, skill.type)&lt;br /&gt;    will.return(true)&lt;br /&gt;   expect.get(testPerson.id, skill.type)&lt;br /&gt;    will.return(new Skill(:Java, :Basic))&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  assert_true(employeeService.is_skilled_in(testPerson, :BasicJava))&lt;br /&gt; end&lt;br /&gt;&lt;br /&gt; def can_be_trained_in_something &lt;br /&gt;  testPerson = TestPerson.new&lt;br /&gt;  Skill = Skill.new(:Java, :Beginner)&lt;br /&gt;&lt;br /&gt;  MockRepository {&lt;br /&gt;   expect.contains(testPerson.id, skill.type)&lt;br /&gt;    will.return(false)&lt;br /&gt;   expect.add(testPerson.id, skill.type)&lt;br /&gt;   expect.get(testPerson.id, skill.type)&lt;br /&gt;    will.return(new Skill(:Java, :Basic))&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  employeeService.train(testPerson, Training.new(skill))&lt;br /&gt;  assert_true(employeeService.is_skilled_in(skill))    &lt;br /&gt; end&lt;br /&gt; ... plus all the other tests&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The service client code feels more difficult to read: it flows less as a sentance making the Service the subject and not John who has disapeared somewhere in the parantheses.  The Service code itself is more difficult to read than the behaviour class and the service test class is significantly more complex.  Also the service requires a more complex repository and the Person class is reduced to being nothing more than a data holder.  Another problem with service based is you often have to break encapsulation to get it to work and, as a result, you can end up with a lot of repetation in code.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I believe the issue with Greedy Aggregates mainly stems from making code centric to O/R mapping tools.  To simply model our Person domain we end up with:&lt;br /&gt; &lt;ul&gt;&lt;li&gt;A Person object which maps to a Person table&lt;/li&gt;&lt;br /&gt; &lt;li&gt;A Medical History class with a table with a Person_Id foreign key&lt;/li&gt;&lt;br /&gt; &lt;li&gt;A Skill class with a table with a Person_Id foreign key&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This makes it difficult to split the Person into smaller more specific classes as the O/R mapper requires a definate class to map to. In the above code we may want to split Person into two classes: one which represents the core aspects of a Person (name, age etc.) and another for their skills lets call it PersonWithSkills.  In many O/R mappers this is difficult because we cannot create a mapping for PersonWithSkills as two classes cannot map to the same table.  However we can create a repository which ties them together:&lt;/p&gt;&lt;pre class="code"&gt;class PersonWithSkillsRepository&lt;br /&gt; def get(id)&lt;br /&gt;  person = personRepository.get(id)&lt;br /&gt;  skills = skillsRepostitory.get(person)&lt;br /&gt;  return PersonWithSkills.new(person, skills) &lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;This is how I've tended to advocate it in the past but recently I was playing with Ruby, and using its cool dynamic powers I approached it in a different way: essentially I merley extended the Person class using a module like so:&lt;/p&gt;&lt;pre class="code"&gt;class Person &lt;br /&gt; has_many :skills&lt;br /&gt; &lt;br /&gt; def with_skills&lt;br /&gt;  self.extend PersonWithSkills&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;module PersonWithSkills&lt;br /&gt; def is_skilled_in &lt;br /&gt;        ... # all skills based methods here &lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;The only issue with this method is all of the ActiveRecord declarations have to be on the Person class - there may be a way around this but I don't know Ruby well enough to say for sure.  It also has the disadvantage of not working for any classes outside of the core package (though knowing Ruby there may be a way around this to).  However if you want to do more complex logic between role based aggregates you can.  For example:&lt;/p&gt;&lt;pre class="code"&gt;class Person&lt;br /&gt; def as_traveller&lt;br /&gt;  self.extend PersonAsTraveller&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;module PersonAsTraveller &lt; Locatable ... end&lt;br /&gt;&lt;br /&gt;module TravellingPersonWithSkills &lt; Skilled  &lt;br /&gt; def can_do_job(job)&lt;br /&gt;  job.matches_location(self.as_traveller) &amp;&amp; job.matches_skills(skills) &lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Job&lt;br /&gt; def matches_location(locatable)&lt;br /&gt;  return locatable.matches(location)&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;Dynamic languages such as Ruby make it nice and easy to do the above as it has the ability to mix in methods.  That doesn't mean we can't do something similar in a static langauge such as Java or C# it simply means that we have to jump through a few more hoops and use delegation instead.&lt;/p&gt;&lt;p&gt;So now that we are using behaviour based domain objects and moved away from services and have managed to cut those Greedy Aggregates down to size when is it right to use a service?  A service will need to be introduced when there is something normal domain objects cannot be trusted to deal with something by themselves and require some co-ordination or greater authority to do it for them.  The service must be stateless.  A good example of this is transferring money between accounts: you don't want to leave the accounts to sort it amongst themselves so you will need a service to deal with the interaction:&lt;/p&gt;&lt;pre class="code"&gt;class AccountTransferService&lt;br /&gt; def transfer(account_from, account_to, amount)&lt;br /&gt;  if(account_from.has_funds(amount)) do&lt;br /&gt;   account_from.debit(amount)&lt;br /&gt;   account_to.credit(amount)&lt;br /&gt;  end&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;p&gt;There are a number of ways of dealing with Greedy Aggregates in both dynamic and static langauges.  What is important is being able to clearly identify aggregates and not be to restricted by the O/R mapper or simply give up and rely on services.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-2648269995606339844?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/2648269995606339844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=2648269995606339844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2648269995606339844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2648269995606339844'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/03/balancing-greed-with-anemia.html' title='Balancing Greed with Anemia'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5529323968272799582</id><published>2008-01-19T15:21:00.000Z</published><updated>2008-01-19T15:38:16.704Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>The One Minute Build</title><content type='html'>&lt;p&gt;The project I am working on has a build which used to take under a minute and has slowly crept up to around one minute forty five seconds. Recently I have begun to feel the pain of this longer build; it is surprising just how much a paltry forty-five seconds increases those periods of sitting and waiting.&lt;/p&gt;&lt;p&gt;The build is an essential part of the code base, it is what gives you the developer and the rest of the team feedback on the state of your code. &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;Continous Integration&lt;/a&gt; tell us that we should make as small changes as possible, verify them using the build, then check in (then verify the build on the build server). Under these rules we should probably aim for a optimum integration rate - the frequency of check-ins (per pair). I believe a optimum integration rate should be around once per hour.&lt;/p&gt;&lt;p&gt;A slow build can be a blocker to good CI practice: the longer a build takes to run the less often people will run it, the less they will check in and the bigger the change list they create. Martin Fowler's original article on CI states that &lt;a href="http://martinfowler.com/articles/continuousIntegration.html#KeepTheBuildFast"&gt;"the XP guideline of a ten minute build is perfectly within reason"&lt;/a&gt; however I want to contest that guideline and bring it down to a minute. Why? because the difference between a build that takes under a minute and one that is over a minute is quite considerable in trying to keep your change list down.&lt;/p&gt;&lt;p&gt;On average a developer will run three builds per change, the first being on the change itself - which is usually run in the IDE and will often have some failing tests (though not always) - the second to verify the change and the third to verify the update. So the general rhythm goes: make a change, run the tests, fix the broken tests, verify the build on the command line, update, verify the build again, commit. Of course it is possible to make a change and have no tests failing (meaning two builds per change) but even then most devs will run the testsuite in the IDE and then verify the full build against the command line. &lt;/p&gt;&lt;p&gt;In the case of a merge conflict (either in code or failing tests on update) we add an extra two builds per conflict: the first to verify the fix, the second to verify the fresh update before check-in.&lt;/p&gt;&lt;p&gt;Three changes per build means that the total amount of time spent building is the build time multiplied by three: therefore any build which takes one minute will consume three minutes of developer productivity. If we check-in once every hour that is 3/60 or 5% of your devs time spent building. Take the build up to just two minutes and we have 6/60 or 10%. Take a build of ten minutes and we have 30/60 or 50% of devs time spent building! If there was a merge conflict on a ten minute build it will consume 50/60 or over 80% of that hour.&lt;/p&gt;&lt;p&gt;On a ten minute build a productivity ratio of 1:2 is not acceptable, so to compensate we adjust the optimum integration rate. This is achieved, essentially, by trying to bring the ratio back to an acceptable level, so if 10% loss (equivalent to a two minute build) is acceptable the check-in rate becomes once every five hours. Comparatively 10% on a one minute build is a check-in every 30 minutes verses once every five hours!&lt;/p&gt;&lt;p&gt;Decreasing check-ins is a dangerous game; the longer changed code is out of the repository the more out-of-date it is. The difference between your repository and your code becomes greater (assuming, of course, that you are making changes over that period) and the difference between your code and your fellow developers also becomes greater. By checking in frequently the codebases are constantly re-aligned minimizing the impact of future changes. The most obvious side effect to diverging code bases is the chance of conflict increases - small, frequent check-ins reduce this to an extent where it can become a non-issue - big check-ins mean big conflicts, big conflicts mean loss of productivity, stress, more time your code is out of sync and more times you have to run the build. &lt;/p&gt;&lt;p&gt;To demonstrate this lets create a concept of a "window of opportunity", this window is the space between doing the update and checking in and the opportunity is for another pair to check-in before you do! The size of this window is equivalent to the length of the build; we all know that if we are going to check in we try to grab this window (how often do we say "hang on a minute I've just got to run the tests and check in this build"?). The reason for this is we don't want to find that someone else has checked in between the last update and us running the build. The greater the length of the build, the greater the chance that someone else has committed (which increases based on the size of the team) and the more times you have to run your build.&lt;/p&gt;&lt;p&gt;There are other side-effects to long builds, you can't keep the change list small and people will find ways around running the build; from only running it once out of the three times (increasing the chance of broken builds) or avoiding full runs by only running the tests they believe to be impacted (again increasing the chance of broken builds). None of these is a good practice. Big builds also mean loss of attention: running the build, doing an update, running the build again, then checking in takes just two minutes on a one minute build but twenty on a ten. Two minutes won't disrupt to flow of development and probably works as a nice gap to discuss things with your pair or just give the brain a rest. The ten minute build equals a wait of twenty minutes: enough time to eat lunch! At the end of twenty minutes any focus you had has gone.&lt;/p&gt;&lt;p&gt;A one minute build may sound unrealistic but I believe it is possible. In some ways it is an indication to healthiness of your code base and by that I mean both production and test - poorly written and bad performing test code is equally as bad as poorly written, bad performing production code. It is very easy to be slightly relaxed about build times, treat them as an inevitability and the watch them slowly go from one minute builds to ten.&lt;/p&gt;&lt;p&gt;It's all very easy to preach about one minute builds when I am in the privilliged position to be working on a code base that only takes one minute forty five seconds. The speed of the build is due to the drive, early on in the project, not to tolerate long builds: several times it's been looked at when it started to get a bit overgrown and it's been hacked back down to size. If we had been more relaxed I'm sure it would have crept up a lot higher.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5529323968272799582?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5529323968272799582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5529323968272799582' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5529323968272799582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5529323968272799582'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/01/one-minute-build.html' title='The One Minute Build'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6207383273165328360</id><published>2008-01-10T16:14:00.000Z</published><updated>2008-01-17T09:07:59.116Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='ThoughtWorks'/><title type='text'>Rawhide</title><content type='html'>I found out yesterday that I was being rolled of the project I am currently on.  I was very ill prepared and I had been guilty of kidding myself the project was going on forever.  I had made the classic mistake of inaction believing that denial resolves into desire.  It has been quite a strange experience seeing a project draw to a close.  I have learnt there are two pains to consultancy on a project of this kind: people roll off and you roll off.  It was strange to come back after Christmas to see the team halved.  People you'd worked very closely with - whole days pairing together side by side - good friends who are suddenly not there.  Though it isn't literally here today gone tomorrow the period between finding out someone is going and them being gone is very short - there isn't the one month notice period and the usual "good luck with your next job" as essentially nobody left ThoughtWorks, they've just left the team, but TW being such a vast place it feels as if they get sucked up back into the unseen world of clients.&lt;br /&gt;&lt;br /&gt;The biggest shock is when you yourself get your papers.  It was a moment I was inwardly dreading: I knew I rolled off mid-January but I was hoping that my term would be increased, I was hoping the project would go on but the cogs that do turn leave my assignment end date landing in a void where there is currently no commitment to extend the project meaning I've popped up as a resource to be used somewhere else.  In someways the great Resource Management machine can feel quite heartless and random, as I guess it should be, but the first time you experience it - especially after ten years of in-house employment - you realise how it's dangerous to ignore it.&lt;br /&gt;&lt;br /&gt;It's been a great project: the best I've ever worked on.  It's renewed my faith in development; I've never enjoyed my work as much as I have over the last 5 months.  Although not everything has been perfect - the pace too aggressive, the project too short, a feeling of uncertainty over it's lifespan - it has proven to me how much better agile is especially when you apply all the best practices from stands-ups, story walls, retrospectives, continuous integration, testing and of course pairing (I have developed a terror of having to solo again: back to the days of insoluar, procrastinating, under productive depression). From it's earliest days I wanted to drag old colleagues in and show them how this project has lived and breathed in a way so unlike all the bureaucratic process driven drivel that I have had the unpleasure to work on or the other political chaos zero management departments out there.  The people have renewed my faith in development too: working with people who seem to get *it*; a whole team (QAs, BAs, developers, project managers etc.) who care about what they do, bother to learn and understand and discover, has been mightily refreshing.&lt;br /&gt;&lt;br /&gt;So a farewell to a great project and the great team I have had the please to work with.  I hope I come across your paths and get to work with you again.  A special mention to Sukita and Seema who are not only great role models for that all too rare bread of women in IT but have character of Dickensian proportions and, in the highly unlikely event of media type people reading this, deserve their own TV show (Sukita already has broadcasting experience).  Also special mentions to the other half of the fire team: Greg, and to Alex for all our discussions on Russian literature and the church.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6207383273165328360?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6207383273165328360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6207383273165328360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6207383273165328360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6207383273165328360'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2008/01/rawhide.html' title='Rawhide'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5962180288996886899</id><published>2007-10-29T09:16:00.000Z</published><updated>2007-10-29T09:18:25.857Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Refactoring'/><title type='text'>Your Feet's Too Big</title><content type='html'>Every piece of code written has a refactoring footprint which is essentially its proliferation through the code base and its level of difficulty to refactor.  Some code can have a high proliferation but the refactoring may be simple, for example renaming a variable in modern IDE's is a simple matter regardless of the number of usages.  On the other hand changing a variables return type or changing the signature of a method both create a large refactoring effort, especially if that requires knock-on refactorings of other classes and the greater the consumption of the code the greater the footprint.    There are other things that can have an impact on the ease of refactoring: using libraries that create code that is difficult to refactor (for example having to place variable names etc. in strings), using external libraries directly without encapsulation, having similar routines across code which isn't encapsulated, the number of entry points to a piece of code (the number of different ways of achieving the same thing) all of these can make refactoring difficult and risk the introduction of bugs.  Another area, much neglected when considering ease of refactoring, is test code which very often has a high consumption of production code (sometimes higher than the production code itself) and can make the simplest refactorings painful because large chunks of test code are dependent on your class.&lt;br /&gt;&lt;br /&gt;TDD states that code that is easy to test is good code and the same is true for refactoring: writing code which is easier to refactor leads to cleaner code. Refactoring footprints have, in very real terms, an impact on productivity and therefore managing them is quite important.  There are various techniques - most of them basic OOP principles - that can help keep the refactoring footprint down.  However, due to the natural evolution of code, this can be quite hard to keep track of and unless you have an in-depth knowledge of the codebase - which is increasingly unlikely the bigger and older the codebase is - it can be difficult to 'see' a footprint.&lt;br /&gt;&lt;br /&gt;I think it would be interesting to explore the use of metrics to measure refactoring footprints.  These metrics would give a very interesting and valuable insight into the codebase and its quality.  The interesting thing is that unlike many other code metrics refactoring footprints need to take into account test code as well.  From a very basic level counting the number of usages across both production and test code can give a rudimentary indication to a footprint.  More sophisticated metrics would measure the impact of a refactoring (are there knock-on refactorings).  Different types of refactoring would also require different metrics and some refactorings may be uncommon in certain codebases or may have a degree of acceptable pain (package refactorings for example).    As with most metrics they will be open to a degree of interpretation based on codebase and class but none the less the metrics should be useful - especially in recommending refactorings!&lt;br /&gt;&lt;br /&gt;I haven't done much research on this so I do not know if any tools already exist to calculate such metrics or even what metrics they provide, though I am sure there will be.  I shall try and track some down and have a play to see what sort of data they provide and establish what sort of insight they can give into a codebase.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5962180288996886899?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5962180288996886899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5962180288996886899' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5962180288996886899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5962180288996886899'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/10/your-feets-too-big.html' title='Your Feet&apos;s Too Big'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5209000691809639111</id><published>2007-08-02T15:08:00.000+01:00</published><updated>2007-08-03T09:59:41.561+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='ALT.NET'/><title type='text'>Seperating the Men from the Morts</title><content type='html'>I'm a bit slow on the uptake here (maybe I'm too busy to be a true &lt;a href="http://www.linuxdevcenter.com/pub/a/mac/2002/05/14/oreilly_wwdc_keynote.html"&gt;alpha geek&lt;/a&gt;) but if you're one of those .NET developers who've always felt a little bit uncomfortable sitting in the MS &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Fanboy&lt;/span&gt; Hummer on the way to the latest .NET launch (and secretly was wishing you were at &lt;a href="http://conferences.oreillynet.com/rails/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;RailsConf&lt;/span&gt;&lt;/a&gt;) and because &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;every time&lt;/span&gt; you mentioned test first, agile, a new OS project, regret that a Java library wasn't in .NET - or god forbid you actually deployed open source non-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;MS&lt;/span&gt; certified libraries on a production machine! - you got funny looks, then maybe you are an &lt;a href="http://laribee.com/blog/2007/04/10/altnet/"&gt;ALT.NET&lt;/a&gt;er and never knew it.&lt;br /&gt;&lt;br /&gt;The opposite is MORT.NET: those old VB6&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;ers&lt;/span&gt; or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;VisualC&lt;/span&gt;++&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ers&lt;/span&gt; who just can't shake the habit of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;databound&lt;/span&gt; controls with a business layer of static methods which shuttle anemic data objects to and from the database and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;UI&lt;/span&gt;, and tests by creating a test app of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;datagrids&lt;/span&gt; and command buttons.  The MORT.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;NETer&lt;/span&gt; is a drag-and-drop all star who wouldn't have known what AJAX was until MS released &lt;a href="http://www.asp.net/ajax/"&gt;ATLAS&lt;/a&gt; (but are slightly cautious as it's FREE) and believe &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;NHibernate&lt;/span&gt; is pure evil because it doesn't use stored procedures.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://codebetter.com/blogs/scott.bellware/archive/2007/07/24/166002.aspx"&gt;Join the movement&lt;/a&gt; comrades: if you're the kind of developer that's prepared to try something because it's cool rather than asking if it is MS certified you're already there!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5209000691809639111?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://laribee.com/blog/2007/04/10/altnet/trackback/' title='Seperating the Men from the Morts'/><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5209000691809639111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5209000691809639111' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5209000691809639111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5209000691809639111'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/08/seperating-men-from-morts.html' title='Seperating the Men from the Morts'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-2219131675227073888</id><published>2007-07-18T09:38:00.000+01:00</published><updated>2007-07-18T09:42:14.911+01:00</updated><title type='text'>Blogger: stop stealing my space</title><content type='html'>Does anyone know why Blogger is adamant on removing spaces when you post?  When I post code snippets it always decides to cut down all my spaces making my code snippets look a bit short on the indentation. &lt;br /&gt;&lt;br /&gt;What's more annoying  is that everytime I edit a post it takes a few more spaces away leaving the code without indentation and I have to re-indent everytime I do an edit!&lt;br /&gt;&lt;br /&gt;I've searched the site for options but can find nothing that says "stop stealing my spaces".  Any clues?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-2219131675227073888?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/2219131675227073888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=2219131675227073888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2219131675227073888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/2219131675227073888'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/07/blogger-stop-stealing-my-space.html' title='Blogger: stop stealing my space'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-185363627430882758</id><published>2007-07-17T16:52:00.000+01:00</published><updated>2007-07-18T09:36:32.037+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Encapsulation'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Loopy loops</title><content type='html'>Encapsulation and information hiding tells us that we encapsulate an objects internal data structure and expose methods, a client can see all the methods but none of the data.  &lt;a href="http://c2.com/cgi/wiki?TellDontAsk"&gt;Tell, don't Ask&lt;/a&gt; extends this to say we should always tell an object to do something, not ask it for some information and then do something for it.  &lt;a href="http://c2.com/cgi/wiki?LawOfDemeter"&gt;The Law of Demeter&lt;/a&gt; helps to clarify this by telling us that we should avoid invoking methods of a member object returned by another method.  By employing Demeter we avoid "train-wreck"s e.g. a.B.C.DoSomething().&lt;br /&gt;&lt;br /&gt;I have seen - and written - a lot of code that does this:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;foreach&lt;/span&gt;(Object obj in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;myObject&lt;/span&gt;.Objects)&lt;br /&gt;{&lt;br /&gt; obj.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;DoSomething&lt;/span&gt;();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;But doesn't this break the three rules?  First we are exposing the objects internal structure (the fact that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;myObject&lt;/span&gt; has a collection of Objects inside it).  Secondly we break Demeter in three ways by:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;invoking the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;GetEnumerator&lt;/span&gt; (in C#) method of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;IEnumerable&lt;/span&gt; which was returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;myObject&lt;/span&gt; (via Objects)&lt;/li&gt;&lt;li&gt;invoking the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;MoveNext&lt;/span&gt; (which &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;incidently&lt;/span&gt; breaks Command-Query &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;seperation&lt;/span&gt;) and Current methods of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;IEnumerator&lt;/span&gt; (in C#) which was returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;IEnumerable&lt;/span&gt; which was returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;myObject&lt;/span&gt;&lt;/li&gt;&lt;li&gt;invoking the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;DoSomething&lt;/span&gt;() method of obj which was returned by the Current method of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;IEnumerator&lt;/span&gt; which was returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;IEnumerable&lt;/span&gt; which was returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;myObject&lt;/span&gt; (see why it's called a train wreck?)&lt;/li&gt;&lt;/ol&gt;Lastly we break "Tell, Don't Ask" by asking all the above objects (three in total: &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;myObject&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;IEnumerable&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;IEnumerator&lt;/span&gt;) in the collection for something and then doing something to obj.&lt;br /&gt;&lt;br /&gt;Looping arrays and collections is very common and in most programs exposing the collection is the norm.  But what happens when you need to change the way the collection works?  What if you decide to replace your objects array with a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;HashTable&lt;/span&gt; or a Set?  Thankfully most &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;OOP&lt;/span&gt; languages gives you some sort of iterator so, in C# for example, you can just expose &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;IEnumerator&lt;/span&gt; and you might be alright.  But this still breaks the three rules and what do you do if your underlying data structure doesn't have an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;IEnumerable&lt;/span&gt;?  What if you're dealing with some legacy COM+ object and you have revert back to the old &lt;i&gt;for&lt;/i&gt; or &lt;i&gt;while&lt;/i&gt;?  Or even worse, the data structure doesn't even seem to have a simple structure (not so uncommon)?  Just exposing an enumerator isn't so easy but we still work around it by doing something like this:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;IEnumerator&lt;/span&gt; Objects&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;IList&lt;/span&gt; list;&lt;br /&gt; for(int i = 0; i &amp;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;lt&lt;/span&gt;; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;comObject&lt;/span&gt;.Count; i++)&lt;br /&gt; {&lt;br /&gt;  list.Add(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;comObject&lt;/span&gt;[i]);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; return list.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;GetEnumerator&lt;/span&gt;();&lt;br /&gt;}&lt;/pre&gt;And then in the client we have:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;foreach&lt;/span&gt;(Object obj in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;myObject&lt;/span&gt;.Objects)&lt;br /&gt;{&lt;br /&gt; // here we go again!&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Hang on a second: we loop so we can loop?  Doesn't that sound a bit strange?  To make matters worse we seem to do this as well:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;SaveEverything&lt;/span&gt;()&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;foreach&lt;/span&gt;(Object obj in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;myObject&lt;/span&gt;.Objects)&lt;br /&gt; {&lt;br /&gt;  database.Save(obj);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;... Somewhere else in the program ...&lt;br /&gt;&lt;br /&gt;void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;DisplayEverything&lt;/span&gt;()&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;foreach&lt;/span&gt;(Object obj in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;myObject&lt;/span&gt;.Objects)&lt;br /&gt; {&lt;br /&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;ui&lt;/span&gt;.Display(obj);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;... Again somewhere else ...&lt;br /&gt;&lt;br /&gt;void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;SendEmail&lt;/span&gt;()&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;foreach&lt;/span&gt;(Object obj in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;myObject&lt;/span&gt;.Objects)&lt;br /&gt; {&lt;br /&gt;  email.Send(obj);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;How many times do you want to write that damn loop?  So what's the alternative?  To implement the three rules: hide the collection and stop exposing it and then tell the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;myObject&lt;/span&gt; to loop it for you.  Quite simply:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;public class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;MyObject&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; void Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;IReceiver&lt;/span&gt; receiver)&lt;br /&gt; {&lt;br /&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;foreach&lt;/span&gt;(Object obj in objects)&lt;br /&gt;  {&lt;br /&gt;   receiver.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;Recieve&lt;/span&gt;(obj);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;All you need to do is pass your receiver to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;MyObject&lt;/span&gt; and it will do all the work for you:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;myObject&lt;/span&gt;.Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;databaseSaver&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;public class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;DatabaseSaver&lt;/span&gt; : &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;IReceiver&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; void Receive(Object obj)&lt;br /&gt; {&lt;br /&gt;  database.Save(obj);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Or if you prefer you can use delegates and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;anonoymous&lt;/span&gt; methods:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;myObject&lt;/span&gt;().Loop(delegate(Object obj) { database.Save(obj); });&lt;br /&gt;&lt;br /&gt;public delegate void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;LoopDelegate&lt;/span&gt;(Object obj);&lt;br /&gt;&lt;br /&gt;public class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;MyObject&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; public void Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;LoopDelegate&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;loopDelegate&lt;/span&gt;)&lt;br /&gt; {&lt;br /&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;foreach&lt;/span&gt;(Object obj in objects)&lt;br /&gt;  {&lt;br /&gt;   &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;loopDelegate&lt;/span&gt;(obj);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now if you need to change the objects internal data structure of the way you iterate it (for performance reasons etc.) you can do so with ease and without breaking any of your clients.&lt;br /&gt;&lt;br /&gt;Although with simple loops it all looks straightforward enough, it is with more complex structures that you gain a real advantage.  In a parent child structure for example you may find a loop such as this:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;foreach&lt;/span&gt;(Parent parent in foo.Parents)&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;foreach&lt;/span&gt;(Child child in foo.Children)&lt;br /&gt; {&lt;br /&gt;  // do something&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Writing this loop all over the place can be fairly cumbersome, and what if you don't want to expose the structure in this way?  By using the pattern above you have more control over the semantics of the object.  For example you could present the list flat and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;merle&lt;/span&gt; passes each object across as above (and thus loosing nested loops all over your code) or you could expose some structure:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;public interface &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;ParentReceiver&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;ChildReceiver&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;CreateChildReceiver&lt;/span&gt;();&lt;br /&gt; void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;ReceiveParent&lt;/span&gt;(Parent, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;ChildReceiver&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;ChildReceiver&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt; void &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;ReceiveParent&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;ParentReceiver&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Parents&lt;br /&gt;{&lt;br /&gt; public void Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;ParentReceiver&lt;/span&gt; receiver)&lt;br /&gt; {&lt;br /&gt;  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_72"&gt;foreach&lt;/span&gt;(Parent parent in parents)&lt;br /&gt;  {&lt;br /&gt;   &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_73"&gt;ChildReceiver&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_74"&gt;childReceiver&lt;/span&gt; = receiver.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_75"&gt;CreateChildReceiver&lt;/span&gt;();&lt;br /&gt;   parent.Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_76"&gt;childReceiver&lt;/span&gt;);&lt;br /&gt;   receiver.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_77"&gt;ReceiveParent&lt;/span&gt;(parent, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_78"&gt;childReceiver&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Parent&lt;br /&gt;{&lt;br /&gt; public void Loop(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_79"&gt;ChildReceiver&lt;/span&gt; receiver)&lt;br /&gt; {&lt;br /&gt;  for(int i = 0; i &amp;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_80"&gt;lt&lt;/span&gt;; children.count; i++)&lt;br /&gt;  {&lt;br /&gt;      // don't pass any illegitimate children!&lt;br /&gt;      if(children[i].&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_81"&gt;IsNotIllegitimate&lt;/span&gt;)&lt;br /&gt;      {&lt;br /&gt;    receiver.Receive(children[i]);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;As you can see by following the three rules and telling the object what to do, and only the immediate object what to do, we can not only express the structure of the objects better and force clients to work with that structure, we also &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_82"&gt;loosen&lt;/span&gt; the object couplings.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Tip:&lt;/span&gt;&lt;br /&gt;For those &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_83"&gt;pre&lt;/span&gt; .NET 2.0 people out there, or those who use languages that don't have generics, by using the above pattern you can strongly type your objects even if you can't strongly type the internal collections.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-185363627430882758?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/185363627430882758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=185363627430882758' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/185363627430882758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/185363627430882758'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/07/loopy-loops.html' title='Loopy loops'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-334026590203884610</id><published>2007-06-28T11:59:00.000+01:00</published><updated>2007-06-28T12:13:52.594+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>If only you want to dance to your tune you'll leave an empty dance floor</title><content type='html'>Last year my wife and I were married (hence the fact she is now my wife) and being the independent thinking, creative couple we are, we planned and organised the whole wedding ourselves, right down to the music.  Both of us being passionate and snobbish about our music - and having the luxury of a very large collection - we didn't want some spotty DJ ruining our day by playing some dreadfully cheesy tracks and mumbling his way through the evening.  So we managed what many said was impossible: a completely cheese free wedding playlist which got everyone boogieing the night away (not to blow our own trumpets but we had to hold back drunken protesters when we turned the music off!).&lt;br /&gt;&lt;br /&gt;This weekend was my best man's wedding and so impressed was he with our music he wanted me to emulate it for him; so I accepted and invited him over to peruse my record collection.  Finally, a few days before the wedding, he gave me his list and I looked at it with horror: it was clear he had just given me a list of his favourite personal tracks.  His wedding being a typical big family and friends affair (over 150 guests compared to our 50) I could tell instantly the list wouldn't work, but no matter how much I tried to explain this he was adamant that on &lt;span style="font-style: italic;"&gt;his&lt;/span&gt; wedding he wanted &lt;span style="font-style: italic;"&gt;his&lt;/span&gt; favourite tracks.  So I conceded and took his laptop gave him copies of the tracks I had and installed the latest &lt;a href="http://www.winamp.com/"&gt;WinAmp&lt;/a&gt; and the excellent &lt;a href="http://www.winamp.com/plugins/details/32368"&gt;SqrSoft Advanced Crossfading plugin&lt;/a&gt; to give it that ultimate disco feel and used WinAmp's built in &lt;a href="http://replaygain.hydrogenaudio.org/"&gt;ReplayGain&lt;/a&gt; to level the volumes of the tracks out (to prevent quiet track then sudden loud track).&lt;br /&gt;&lt;br /&gt;The wedding reception went as I had expected: the groom loved every track that came on and a few close friends got up a jumped around the dance floor with him.  But after half and hour or so the groom was off mingling at the bar and the dance floor was empty.  His new bride was soon begging us groomsmen to get people up and dancing to fill the depressingly empty dance floor and although we did drag a few people off the sides, quickly the floor was vacant again.&lt;br /&gt;&lt;br /&gt;About an hour later the groom came running up to me waving his arms and shouting in distress that his new wife had only gone and changed the playlist: she had loaded her emergency backup playlist instead!  Before I could even react she had rushed over, the train of her dress picked up in her hands, shouting at him that she'd changed it because no-one was dancing while he shouted back something to the effect that her girl band music was rubbish (I can't print the exact words) and as I turned to leave them to their first domestic as husband and wife both their eyes looked pleadingly into mine.  So there I stood with both looking to me to take their side; the groom playing to my taste as his wife’s playlist was full of offensively bad music and his wife looking to my reasonable side and the fact that people were now dancing.  It was an easy decision for me to make: I asked them "do you want people to dance?" they both replied instantly "YES", "were people dancing before you changed the playlist?", "no" the wife replies and a sharp look at the groom squeezes out a squeaky "no", "OK then", I firmly state "if we go into the dance room and people are dancing then we leave her playlist on and if they're not then we change it".  So we marched into the dance room to find a mass of badly dancing relatives and the decision was made.&lt;br /&gt;&lt;br /&gt;There is a moral to this humorous story of marital conflict; my friend had placed his personal preferences before his objective: to ensure people dance and have a good time at his wedding.  When my wife and I did our playlist we didn't just dump our favourite tracks down, we made lots of compromises - which included a strict no Smiths or she'll annul our wedding - to ensure that the songs we played people would want to dance to but we used our principles of good taste to guide us. Our principles meant that there would be no cheese at the objective meant that although The Rolling Stones &lt;span style="font-style: italic;"&gt;Beast of Burden&lt;/span&gt; may be on our personal playlist we knew that &lt;span style="font-style: italic;"&gt;Brown Sugar&lt;/span&gt; is the one that get's everyone dancing and that people would bounce around to The Undertones &lt;span style="font-style: italic;"&gt;Teenage Kicks&lt;/span&gt; way before Radiohead's &lt;span style="font-style: italic;"&gt;Exit Music (For a Film)&lt;/span&gt;.  When we put together our playlist we carefully considered whether each track was appropriate (which is why we didn't have Super Furry Animals &lt;span style="font-style: italic;"&gt;Man Don't Give a Fuck&lt;/span&gt;) and listened to the track trying to imagine our guests dancing to it and ultimately remembering that although every song wouldn't please everyone that everyone should be pleased by most of the songs.&lt;br /&gt;&lt;br /&gt;Development is like choosing a playlist: a good developer will always remember the objective.  We've all been there: developing our own little features, the one's we think are really cool, and then getting upset when the customer says they don't like it and they want to change it.  Developers are very guilty of doing what &lt;span style="font-style: italic;"&gt;they&lt;/span&gt; think the application should do, forgetting what they've been asked to deliver and instead of doing the best thing to meet the customer's requirements they end up writing code to solve problems that don't exist or aren't important.  It's a hard thing to avoid and I am as guilty as anyone of doing it: I remember all too clearly arguing that a feature shouldn't be developed the way it was requested as I felt it was functionally incomplete forgetting that what the customer was trying to achieve was to solve a problem quickly but not perfectly (what I call developing Word when all they want is Notepad).&lt;br /&gt;&lt;br /&gt;As developers we find it difficult to compromise the 'perfect solution' for what the customer wants and we get stuck in thinking that to not write a technically or functionally complete solution means writing a technically or functionally bad solution (as my friend believed that not playing his favourite music was to play bad music).  I had a conversation with a developer the other day who, like my friend, didn't want to compromise his design to meet the customer's objective.  He wanted to build the feature in a way that was more generic and technically clever than was required and saw any sacrifice to this principle as bad coding.  So entrenched was he in this view point he was prepared to sacrifice the customer's requirements and the deadline as he couldn't conceive that writing good, flexible code which was specific to the customer's requirements was a good thing.  I struggled to find a way around this loggerhead and in the end I tried to explain the emphasis should be on usability before reusability and not on over-engineering.&lt;br /&gt;&lt;br /&gt;The difference between my friends playlist and ours was that although both of us stuck to our principles of what we believe is "good music" (in the same way as a developer I would stick to mine: Agile, TDD etc.) my wife and I always checked ourselves against the objective and adapted to the situation, where as my friend just hung on to his principles for principles sake, forgetting what he was trying to achieve, and ultimately it was this that separated our full dance floor from his empty one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-334026590203884610?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/334026590203884610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=334026590203884610' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/334026590203884610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/334026590203884610'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/06/if-only-you-want-to-dance-to-your-tune.html' title='If only you want to dance to your tune you&apos;ll leave an empty dance floor'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-3727788863283317835</id><published>2007-06-25T14:46:00.000+01:00</published><updated>2007-06-25T15:13:39.052+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Intelligent design</title><content type='html'>I stumbled across &lt;a href="http://jayflowers.com/"&gt;Jay Flowers&lt;/a&gt; blog today and found his mix of eastern philosophy and Agile development very interesting.  Eastern philosophy appears to be seeping into a lot of western science (in particular psychology and to some extent quantum physics) and it's nice to see these ideas placed to argue the benefits of Agile.&lt;br /&gt;&lt;br /&gt;However I don't want to write so much about the intricacies of eastern philosophy (Jay's blog does a good job already) instead I'd like to expand on a &lt;a href="http://jayflowers.com/WordPress/?p=167"&gt;particular post&lt;/a&gt; of Jay's and specifically on &lt;a href="http://www.erowid.org/culture/characters/watts_alan/watts_alan_article1.shtml"&gt;the quote&lt;/a&gt; he provided from Alan Watts.&lt;br /&gt;&lt;br /&gt;Religion is embedded deep into our cultures: whether you are atheist, agnostic, fundamentalist, conservative or liberal believer our society and culture has been influenced more by religion than it has by science; legal systems, for example, are based on religion: the ten commandments for Christians, Sharia law for Muslims, etc..  After reading Jay's blog it occurred to me how much our approach to development is also influenced by religious culture and to demonstrate this I am going to look to the creationist vs evolution debate.&lt;br /&gt;&lt;br /&gt;I don't want to actually get knee-deep into the creationist vs evolution debate (I am not &lt;a href="http://richarddawkins.net/"&gt;Richard Dawkins&lt;/a&gt;), instead I wish to concentrate on the affect of creationism on our western culture. Though many of us take the theory of evolution for granted less than 150 years ago the main position of the scientific community was a creationist stance.  So ingrained was the creationist viewpoint that &lt;a href="http://en.wikipedia.org/wiki/Charles_Darwin"&gt;Darwin&lt;/a&gt; took twenty years to publish his theory due to the &lt;a href="http://en.wikipedia.org/wiki/Galileo_affair"&gt;Galileo like treatment &lt;/a&gt;resulting in scientists counter to the biblical view being ostracized and attacked as heretics.&lt;br /&gt;&lt;br /&gt;So what does all this have to do with development?  Most of our theories on good development and management methodologies come from those established at the time of the &lt;a href="http://en.wikipedia.org/wiki/Industrial_revolution"&gt;Industrial Revolution&lt;/a&gt; and the rise of Victorian &lt;a href="http://en.wikipedia.org/wiki/Engineering#History"&gt;engineering &lt;/a&gt;as an established discipline in the nineteenth century.  If we look at the rise of engineering and that of evolution we can see clearly that engineering practices were not informed by evolutionary theory but instead from a creationist viewpoint.  To clearly illustrate this consider that as the first copies of Darwin's groundbreaking publication &lt;a href="http://en.wikipedia.org/wiki/The_Origin_of_Species"&gt;The Origin of Species&lt;/a&gt; the great engineer &lt;a href="http://en.wikipedia.org/wiki/Isambard_Kingdom_Brunel"&gt;Isambard Kingdom Brunel&lt;/a&gt;  had been cold in his grave for a good two months.&lt;br /&gt;&lt;br /&gt;Creationists (being &lt;a href="http://en.wikipedia.org/wiki/Theism#Theism"&gt;theists &lt;/a&gt;rather than &lt;a href="http://en.wikipedia.org/wiki/Deism"&gt;deists&lt;/a&gt;) take issue with evolutionary principles that complex biological forms are evolved from simple primitives over numbers of adaptations (dare I say it: &lt;a href="http://en.wikipedia.org/wiki/Iterative_and_incremental_development"&gt;iteratively&lt;/a&gt;); instead creationists argue that something (mainly the &lt;a href="http://en.wikipedia.org/wiki/Abrahamic_God#The_Supreme_Deity"&gt;Abrahamic God&lt;/a&gt;) created all living creatures instantaneously and perfectly.  Culturally we have been indoctrinated with this view point resulting in a populist feeling of common sense that complex systems are only successful if they are designed upfront, created perfect and built to last an indefinable period (&lt;a href="http://en.wikipedia.org/wiki/Big_Design_Up_Front"&gt;Big Design up Front&lt;/a&gt;). This view is expounded as evolution is often misinterpreted (often deliberately by creationists) as being based on &lt;a href="http://www.ebonmusings.org/evolution/evonotchance.html"&gt;pure chance&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As engineering and management theories were established under the creationist view of the the biological world so did they become polluted with it.  After thousands of years of belief in creationism it is not surprising that 150 years later even modern practices such as software development find creationist ideas still embedded in them.  Though &lt;a href="http://www.martinfowler.com/articles/designDead.html#id2249696"&gt;evolutionary design&lt;/a&gt;  is becoming more of a mainstream approach to software development many people still defend the old creationist cause and often argue against Agile methodologies with the cultural preconditioning that unless something is created perfect somehow its overall success is left to chance &lt;a href="http://www.nofluffjuststuff.com/speaker_topic_view.jsp?topicId=512"&gt;as everyone is left to do what they want&lt;/a&gt;.  For many developers moving away from the creationist view is a big step and in the same way the concepts of adaptation in evolution provides answers for a seemingly perfect complex world so it does with Agile, and where evolution emphasis the disciples of natural selection over random chance so Agile has its own &lt;a href="http://www.extremeprogramming.org/rules.html"&gt;disciplines&lt;/a&gt;.  Fortunately software development is aided by the fact that something intelligent is helping it (or at least most of the time)!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-3727788863283317835?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/3727788863283317835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=3727788863283317835' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3727788863283317835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/3727788863283317835'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/06/intelligent-design.html' title='Intelligent design'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6082962456442451284</id><published>2007-06-11T13:22:00.000+01:00</published><updated>2007-06-13T13:59:45.644+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ThoughtWorks'/><title type='text'>Letting Schrödinger's cat out of the bag</title><content type='html'>On Friday I journeyed up to the greatest capital city in the world - London (try searching on Google if you don't agree) - and had the final round of interviews with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.  The end result was I got the job (I'm a very happy &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;JMB&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) - which has already cost me a huge wedge of cash taking my wife out for a celebratory meal in a posh restaurant - and now I am just waiting the official offer before I start the ball rolling (hand in my notice etc.).&lt;br /&gt;&lt;br /&gt;I'd like to say what a great day I had: I have never experienced an interviewing process so thorough but at the same time so incorporating.  There were several points in the day when I had to stop myself just wandering round the office and just going up to people or sitting at a laptop and pretending to be a real &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;ThoughtWorker&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (which I will soon be!).  I have never felt so accommodated and welcome at an interview before, from the moment I walked in the door and despite the normal sweaty palms I felt fairly relaxed (or at least only slightly anxious) and even for the written tests I was made to feel as comfortable as possible.&lt;br /&gt;&lt;br /&gt;What was really evident was the amount of probing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; do to ensure that you are going to be suitable from an &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;environmental&lt;/span&gt;/cultural perspective.  Though this sounds obvious (and I did half-dismiss its relevance when being told about it) there is a real effort from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; that you understand what life as a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;ThoughtWorker&lt;/span&gt;&lt;/span&gt; is like - good and bad.  They try and build up the picture of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; as much as possible with all its warts.  I really appreciated this, not just for its &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;openess&lt;/span&gt;, as working for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; can sound like the development &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_9"&gt;equivalent&lt;/span&gt; of getting to play premiership football or getting a Hollywood part, but you still need to understand that it isn't all red carpets and adoring fans but there is work to do and sometimes that work may not be too glamorous.&lt;br /&gt;&lt;br /&gt;I'd also add that I was surprised at the level of feedback &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; give you; virtually every other company that have offered me a job you get the normal stony faced interview - with a few smiles and laughs at your &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;anecdotes&lt;/span&gt; and Dad jokes - and then the short "we'd like to offer you the position" phone call.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; gave me loads of direct feedback - which I must say was really flattering - and when I walked out of the office - and aimlessly wandered the streets of London for the 30 minutes it took me to come to my &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;senses&lt;/span&gt; and realise I was hungry and needed to get home - I can't honestly say what my head was more full of the excitement of the job offer or the "they said I was...".&lt;br /&gt;&lt;br /&gt;The only downside of the whole thing was, when I finally did pull myself together and get myself home, I had to attempt to excitedly reiterate nearly five hours of information to my friends and family: but hey, if you can't bore your closest and dearest half to death with a detailed breakdown of the logic test - which &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_7"&gt;retrospectively&lt;/span&gt; I &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_8"&gt;perversely&lt;/span&gt; enjoyed - then who can you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6082962456442451284?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6082962456442451284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6082962456442451284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6082962456442451284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6082962456442451284'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/06/letting-schrdingers-cat-out-of-bag.html' title='Letting Schrödinger&apos;s cat out of the bag'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-9168828898769236728</id><published>2007-06-05T13:34:00.000+01:00</published><updated>2007-06-05T14:13:40.427+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ThoughtWorks'/><title type='text'>Schrödinger's cat</title><content type='html'>A couple of weeks ago I closed my eyes and clicked on the submit button on &lt;a href="http://www.thoughtworks.co.uk/apply-online.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; website&lt;/a&gt; and down went my CV, too late to change, into the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; database.  Imagine my excitement as the next day I get an email asking to ring back to organise a phone interview.&lt;br /&gt;&lt;br /&gt;Seemingly the interview went well as I was asked to complete a coding test.  I had to choose one of three tests and I spent hours agonizing over what angle I should tackle this at.  Everyone knows the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; mantra on simplicity, but just how simple is simple?  I believe I've kept my code simple but what if it's too complicated? And if I make it simpler what if it's then too simple?  I can't describe the hours of agonising until I finally came up with a solution I was happy with which I zipped up, closed my eyes a second time, and pressed my shaky finger down onto the mouse button.  I hadn't felt this nervous since jumping off the top diving board or, in my teens, ringing a girl I met in the club!&lt;br /&gt;&lt;br /&gt;As soon as I went to bed that evening the code went round and round in my head and I cursed myself for the hundreds of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;dumb&lt;/span&gt; &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;decisions&lt;/span&gt; I'd made, regretting the fact that I hadn't just slept on it before sending it.  "But hey", I said to myself "this is like the real world: we can always go back over our code improving it -  &lt;span style="font-weight: bold;"&gt;a good artist knows when to stop&lt;/span&gt;" and to my reading &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; is as much about knowing when to stop as it is keeping it simple.&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;Because&lt;/span&gt; of the bank holiday I have been waiting a week or so for the feedback on my code and if I've made it to the next stage.  When I first submitted for the job I &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_8"&gt;genuinely&lt;/span&gt; wanted to work for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;ThoughtWorks&lt;/span&gt;&lt;/span&gt; but was open to the possibility that I may not be &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;successful&lt;/span&gt;&lt;/span&gt; but as the process has gone on I feel a stronger and stronger desire to get this job and as such the potential &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_11"&gt;disappointment&lt;/span&gt; grows &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_12"&gt;exponentially&lt;/span&gt; with it.&lt;br /&gt;&lt;br /&gt;As I face the twin prospects of elation and despair I realised that going for jobs is like &lt;a href="http://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Schrödinger's&lt;/span&gt;&lt;/span&gt; cat&lt;/a&gt;: your life becomes the cat in the box, the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_15"&gt;nucleus&lt;/span&gt; the job.  Until I open the box (i.e. get the final result of the application) there exists two realities: the one in which I get the job and the one in which I don't.  So from now until that time I live with the turmoil of flipping between the belief that my code was the most amazing they've ever seen and I am going to get this job and life's going to be groovy, and desperate self-doubt which tells me they are so disgusted at the poor quality of my work it'll take at least five years for them to scrub the horror from their memories!&lt;br /&gt;&lt;br /&gt;As the French say "&lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;C'est&lt;/span&gt;&lt;/span&gt; la vie"&lt;/span&gt; and the First Noble Truth is &lt;span style="font-style: italic;"&gt;"suffering exists"&lt;/span&gt;.  This is a period in my life with an outcome which, to a certain extent, is outside of my control: there is a reality on whether I have, at this stage in my career, what it takes to be a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;ThoughtWorker&lt;/span&gt;&lt;/span&gt; and no matter how much I may believe I do (which I really, really do) that cat in the box is either alive or dead: it is not both.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-9168828898769236728?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/9168828898769236728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=9168828898769236728' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/9168828898769236728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/9168828898769236728'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/06/schrdingers-cat.html' title='Schrödinger&apos;s cat'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4045479947939673208</id><published>2007-06-05T08:58:00.000+01:00</published><updated>2007-06-07T18:16:52.234+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><title type='text'>Building Cathedrals</title><content type='html'>Within companies, large and small, it is very likely that there is an &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;in-house&lt;/span&gt; development team working on a systems in &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;continuous&lt;/span&gt; development.  In every company I've worked for I have spent the majority of the role developing a highly strategic system, whether website or &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;CMS&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;CRM&lt;/span&gt; (or one of the other many over general three letter &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;acronyms&lt;/span&gt; out there).  These systems are the Cathedrals of software: they are by far the largest projects in the company and are highly important and &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;grandiose&lt;/span&gt; with great architectural vision.&lt;br /&gt;&lt;br /&gt;These systems &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;inevitably&lt;/span&gt; end up the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;bain&lt;/span&gt; of senior managers, project managers and developers lives.  &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_8"&gt;Inevitably&lt;/span&gt; a battle between the business demanding bags of "quick wins" (that phrase which makes many a developer quake in their boots) and the developers who want to "do things properly". Pour on way too much vision from all parties and you end up with the poor old project manager curling into the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_9"&gt;foetal&lt;/span&gt; position and jabbering on about "delivery" as everyone stands around kicking them for whatever failure the business or development team wish to sight for the last release.&lt;br /&gt;&lt;br /&gt;In these circumstances I have found Agile to be a god send: the business gets quick returns, the project managers get to wrap themselves up &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;snuggly&lt;/span&gt; in their &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;Gant&lt;/span&gt; charts and click away happily at MS Project and the developers -  although they still sit their pushing back deadlines and moaning they haven't got enough resource - actually deliver something.  All in all it keeps the whole project off the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_12"&gt;undeliverable&lt;/span&gt; White Elephant which the Business and development team have managed to concoct between them.&lt;br /&gt;&lt;br /&gt;After a couple of years of doing this with success I was shocked to find that a few of the problems of the old waterfall methodology had begun to raise their ugly heads, namely: degradation, fracturing and velocity.  After some careful thought and backtracking through my career I started to notice some startling &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_13"&gt;similarities&lt;/span&gt; between all the developments I had worked on.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Degradation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Degradation is a natural &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_14"&gt;occurrence&lt;/span&gt; of any system.  Software systems are fortunate that - unlike many systems in the natural world - they rarely degrade through use - think the rail network: the more the rails are used the worse their condition becomes and therefore need replacing.  Although external aspects can cause a software system to degrade through use (database size, hardware age etc.) the actual lines of code are in the exact same condition as when written.&lt;br /&gt;&lt;br /&gt;The biggest cause of degradation in software is change: as new features are written or bugs are fixed existing code can become messy, out of date or even completely redundant without anyone actually realising it.  Also existing parts of the system which work perfectly can get used in a manner not originally intended and cause bugs and performance issues.&lt;br /&gt;&lt;br /&gt;There are a number of techniques out there in the Agile world to help minimize &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_15"&gt;degradation&lt;/span&gt; including &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;Refactoring&lt;/span&gt;, Collective Ownership and Test Driven Development.  However &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_17"&gt;heed&lt;/span&gt; the warning: despite the best unit tests in the world and pair programming every hour you've been sent, the absolute prevention of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_18"&gt;degradation&lt;/span&gt; relies on two things: time and human intervention.  Time is required to fix degraded code which increases the length each feature takes to implement and thus affects velocity.  Human intervention requires someone &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_19"&gt;recognising&lt;/span&gt; the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_20"&gt;degradation&lt;/span&gt; and further more being bothered to do anything about it (collective ownership and pair programming do help here but are no way a guarantee).&lt;br /&gt;&lt;br /&gt;The danger of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_21"&gt;degradation&lt;/span&gt; is that a system can degrade so much that it has a severely negative impact on the progress of a project - sometimes even bringing it to a complete halt - and resulting in the development team &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_22"&gt;battling&lt;/span&gt; the business for a "complete rewrite".  Degradation is not good for developers' morale maily due to the fear that it sounds like an admission of writing bad code.  This results in the, all too common, backlash that it's the business' fault for putting too much pressure to deliver "quick wins" and not accepting the need preserve the architectural vision of the developers; and here we are again in the same spot we were with the waterfall method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Fracturing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Fracturing can look very similar to degradation but is actually quite different.  Fracturing occurs all the time in any system which works to standards - which is all systems regardless of whether those standards are documented or are for a team or individual - as they shift and move to account for changes.  One example of this is the naming convention on networks: many companies opt for some kind of convention for naming switches, printers, computers etc. which seems to suit until something comes along which no longer fits.  For example when a hypothetical company starts out they have three offices in the UK so the naming style becomes [OFFICE]-[EQUIPMENT]-[000].  But then the company expands to Mexico and someone decides that the naming convention needs to include the country as well: the convention is now fractured as new machines now have [COUNTRY]-[OFFICE]-[EQUIPMENT]-[000].  Then an auditor comes along and says that you should &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_23"&gt;obfuscate&lt;/span&gt; the name of your servers to make it harder for a hacker (as UK-LON-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;ACCOUNTSSQL&lt;/span&gt; is a nice signpost to what to hack) so the convention has to change causing even more fracturing.&lt;br /&gt;&lt;br /&gt;This happens in code all the time as your standards shift like sand: yesterday you were using constructors for everything and then today you read &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;Gang&lt;/span&gt; Of Four and decide that the Abstract Factory pattern is the way to go.  The next day you read Domain Driven Design and you decide that you should &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_26"&gt;separate&lt;/span&gt; the factory from the class that it creates.  Fracturing, fracturing, fracturing.  And then you read about &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;NHibernate&lt;/span&gt; and decide that ADO is old news and then in a few years &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;LINQ&lt;/span&gt; comes out and you swap to that.  Fracturing, fracturing, fracturing.  Then you discover TDD and start writing the code in tests but the rest of the team doesn't get it yet.  Fracturing, fracturing, fracturing.&lt;br /&gt;&lt;br /&gt;Of course you could stand still and code to strict guidelines which never change, the team leader walking around the floor with a big stick which comes down across your knuckles &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_29"&gt;every time&lt;/span&gt; your code strays slightly in the wrong direction.  But who wants to work in an environment like that?  Fracturing is a result of many things but mostly it is a result of a desire to do better and as such an improvement in quality.  What coders believe is out of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_30"&gt;sync&lt;/span&gt; is rarely their new sparkling code but their old "I'm so &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_31"&gt;embarrassed&lt;/span&gt; I wrote that" code.  As a result their reaction is a desire to knock down the old and rewrite everything from the ground up using their new knowledge and techniques (though most recognise this is not "a good thing").&lt;br /&gt;&lt;br /&gt;Fracturing can also result from negative factors as well: e.g. someone leaves the company taking years of experience with them and you get a new bod in but they've got to get coding quickly so we throw the standards out and we have more fracturing.  Or there's a lot of pressure to get that code out so drop those new advances we proved in the last project and go back to the old safe and sound method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Velocity&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The obvious thing to say is that project velocity is negatively impacted by degradation and fracturing but that would only be half the picture.  The reality is also the reverse: velocity has an affect on degradation and fracturing.  Agile methodologies such as &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;XP&lt;/span&gt; place a great deal of stress on maintaining a realistic velocity and the advice is wise indeed: too much velocity and more code is written than can be maintained creating too much &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_33"&gt;degradation&lt;/span&gt;.  On the other hand too little velocity and so little code is written between the natural shifts that the amount of fracturing per line of code is at a much &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_34"&gt;higher&lt;/span&gt; ratio than it would be if the velocity had been higher.&lt;br /&gt;&lt;br /&gt;Another consideration is that if velocity is not carefully controlled development can end up in high and low periods.  High periods become stressful causing mistakes, less time to fix degraded code, negative fracturing and ultimately burn out.  Low periods create boredom, frustration which cause mistakes etc. or they encourage over-engineering again causing degradation and &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_35"&gt;fracturing&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Getting the velocity correct is a real &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_36"&gt;art form&lt;/span&gt; and requires so many different considerations that they are too many to list.  However one thing that is required to get velocity correct is waste.  Waste is the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;bain&lt;/span&gt; of all businesses and they often spend more money trying to eliminate waste than it's original cost.  Developers are expensive and to have a developer potentially sitting around doing nothing is a no-no for many companies; they want every developer &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_38"&gt;outputting&lt;/span&gt; 100% 100% of the time.  However the inability to run to such tight budgets is a reality that virtually every industry has come to terms with.  Take a builder for example: if he's going to build a house he'll approximate how much sand, bricks, cement, wood and everything else he'll need then he'll add a load on top.  Ninety nine times out of a hundred the builder will end up with a huge load of excess materials which he'll probably end up throwing away (or taking to the next job).  Of course this isn't &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_39"&gt;environmentally&lt;/span&gt; friendly but the principle the builder is working off is that if he ends up just two bricks or half a bag of cement short he's going to have to order more.  Which means a delay of a day, which puts the whole project off track: basically it's going to cost him a lot more than the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_40"&gt;acquisition&lt;/span&gt; and disposal of the excess had he ordered an extra &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_41"&gt;palette&lt;/span&gt; of bricks or bag of cement.  Thus the builder makes the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_42"&gt;decision&lt;/span&gt; that in order to maintain velocity there will be waste.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;What to do&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is an old joke:&lt;br /&gt;&lt;blockquote&gt;"What's the difference between a psychotic and a neurotic? Well, a psychotic thinks 2+2=5. Whereas a neurotic knows that 2+2=4, but it makes him mad.  "&lt;br /&gt;&lt;/blockquote&gt;Developers and businesses risk becoming psychotic about degradation and fracturing, instead believing that by coming up with some amazing architecture or definitive strategy all these problems will go away.  &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_43"&gt;Neurotics&lt;/span&gt; are only slightly less dangerous, as they become over anxious and fearful of degradation and fracturing they introduce processes, architectures and strategies until they become indistinct from the psychotics.&lt;br /&gt;&lt;br /&gt;Eric Evans has many ideas in his book Domain Driven Design and is the very example of a pragmatist.  Evan's accepts that nasty things happen to systems and bad code is written or is evolved.  To Evan's it is not important that all of your code is shiny platinum quality but that code which is most &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_44"&gt;critical&lt;/span&gt; to the business is clean and pure.  This is why Evan's doesn't slate the Smart-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;UI&lt;/span&gt; pattern: because to him there are many situations where they are acceptable: it just isn't realistic to build a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;TVR&lt;/span&gt; when all you need is a 2CV.&lt;br /&gt;&lt;br /&gt;Chapter IV (&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_47"&gt;Strategic&lt;/span&gt; Design) of Domain Driven Design is dedicated to most of the concepts to protecting your system and is &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_48"&gt;unfortunately&lt;/span&gt; the bit which gets least attention.  Concepts such as Bounded Context, Core Domain and Large Scale Structure are very effective in dealing with &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_49"&gt;degradation&lt;/span&gt; and fracturing.  Although the best advise I can give is to read the book one of the ideas which interests me the most is the use of Bounded Contexts with Modules (A.K.A. packages - Chapter 5).  Evan's &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_50"&gt;explains&lt;/span&gt; that although the most common method for packaging tends to be around the horizontal layers (&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_51"&gt;infrastructure&lt;/span&gt;, domain, application, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;UI&lt;/span&gt;) the best approach may be to have vertical layers based around responsibility (see Chapter 16: Large-Scale Structure).  This way loosely coupled packages can be worked on in isolation and bought together within the application: there is almost a little hint of SOA going on.  If an unimportant package starts to degrade or becomes fractured (for example uses &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;NHibernate&lt;/span&gt; rather than ADO.NET) it doesn't require the rewriting of an entire horizontal layer to keep it clean: the layer can stay &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_54"&gt;inconsistent&lt;/span&gt; within it's own &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_55"&gt;boundary&lt;/span&gt; without having any affect on the other parts of the system.  This leaves the development team to concentrate their efforts on &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_56"&gt;maintaining&lt;/span&gt; the core domain and bringing business value.&lt;br /&gt;&lt;br /&gt;This isn't the only solution though: the use of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;DDD&lt;/span&gt; on big systems will only bring benefit when it hits a certain point.  If all your development team is able to do is &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_58"&gt;continuously&lt;/span&gt; build fractured systems which degrade (either due to skill or resource shortages) then it may be best just to bite the bullet and accept it.  A monolithic system takes a lot to keep going and, although &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;DDD&lt;/span&gt; can be applied to prevent many of the issues discussed, if you cannot get the velocity then your domain will not develop rapidly enough to deliver the benefits of a big enterprise system.  If that is the case it may be more realistic to abandon the vision and instead opt for a strategy that accurately reflects the business environment.  This is where I believe Ruby-On-Rails is making headway; it isn't going to be apt for all enterprise systems but it does claim to take most of the pain out of those database-driven web-based applications that are proliferating through companies.  The point is, even when a big-boy enterprise system sounds like the right thing to do, trying to develop one in a business which cannot or will not dedicate time, money and people is going to be a bigger disaster than if you ended up with a half-dozen Ruby-On-Rails projects delivering real business value.  And you never know once you've delivered a critical mass you may find you can move things up to the next level naturally.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you ever visit an old building, especially Cathedrals such as Canterbury, you'd know that they often gone through hundreds of iterations: bits have been damaged by fires, weather, pillaging or &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_60"&gt;deliberately&lt;/span&gt; destroyed, they have been extended in ways sympathetic to the original and in ways originally considered &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_61"&gt;abominations&lt;/span&gt;, some bits have been built by masters others are falling down because of their poor quality.  The fact is these buildings are &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_62"&gt;incredible&lt;/span&gt; not because they are perfect but because of the way they have adapted to use through the ages.  Old buildings face huge &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_63"&gt;challenges&lt;/span&gt; to adapt through all periods of history where architecture must be compromised and the original people, tools and materials change or may no longer be available.  The &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_64"&gt;challenge&lt;/span&gt; for these buildings across the centuries was not to maintain an unrealistic level of &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_65"&gt;architectural&lt;/span&gt; perfection but to ensure that they &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_66"&gt;maintained&lt;/span&gt; their use - the moment that stops the building will &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_67"&gt;disappear&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-4045479947939673208?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4045479947939673208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4045479947939673208' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4045479947939673208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4045479947939673208'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/06/building-cathedrals.html' title='Building Cathedrals'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-616387374244789234</id><published>2007-05-21T10:05:00.000+01:00</published><updated>2007-05-21T10:18:02.012+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Did God use XP or Scrum?</title><content type='html'>I was wandering around my house in a sleepy haze this morning with thoughts gently pulsating into my peripheral consciousness. I switched on the light and said to myself "Let there be light, and there was light" and then two peripheral thoughts blurred into focus at once prompting me to rummage through my wife's academic books (she's a teacher of Religion) and read through the first chapter of the Jeudo-Christian Old Testament.&lt;br /&gt;&lt;br /&gt;Jokes aside about developer's egos it is quite clear that God used iterative development (or creation).  Give the&lt;a href="http://www.cs.williams.edu/%7Elindsey/myths/myths_15.html"&gt; first chapter of Genesis&lt;/a&gt; a read for the compelling evidence.&lt;br /&gt;&lt;br /&gt;In fact I think there is a clear case for claiming God was a YAGNI type of mono-deity as he creates light on day one but doesn't introduce the Sun until day four (verse 16: "God made two great lights--the greater light to govern the day and the lesser light to govern the night.") and though I've personally never worked on a project of that scale I can safely guess that there was some serious refactoring going on there!  This also shows that the Creator has a real talent for deciding what the next most important thing should be.&lt;br /&gt;&lt;br /&gt;Some of the more observant out there may have noticed that God was also using a bit of Behaviour Driven Development but being God he uses "Let there be" rather than "Should" before each one of his tests. &lt;br /&gt;&lt;br /&gt;You may be wary of reading quite so much into the text but I think it's safe to say there was no BUFD going and can you imagine it if there was: on the first day he drew up the requirements, on the second day he wrote the design document, on the third day he finally stared, on the fourth day he realised that he'd forgotten the light and had to submit a change request...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-616387374244789234?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/616387374244789234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=616387374244789234' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/616387374244789234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/616387374244789234'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/05/did-god-use-xp-or-scrum.html' title='Did God use XP or Scrum?'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-1392140785775417840</id><published>2007-05-15T15:56:00.000+01:00</published><updated>2007-05-15T21:08:48.491+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>YAGNI battles the Black Swans</title><content type='html'>There's been a lot of fuss in the economic world about a book called &lt;a href="http://www.sprintbooks.co.uk/scripts/browse.asp?ref=0713999950&amp;source=K84"&gt;The Black Swan: The Impact of the Highly Improbable by Allen Lane&lt;/a&gt;.  Lane uses the metaphor of the discovery of the Black Swan to explain his theory: basically before the discovery of Australia people believed there were only white swans in the world and created a whole set of theories around this 'fact'.  Then a black swan was discovered in Australia junking the theories.&lt;br /&gt;&lt;br /&gt;Using this as a template Lane defines a Blank Swan as a highly improbable event with three principle characteristics: it is unpredictable; it carries a massive impact; and, after the fact, we concoct an explanation that makes it appear less random and more predictable than it was.&lt;br /&gt;&lt;br /&gt;Lane goes onto criticize businesses, markets and politicians for their over confidence in prediction.  Lane even goes to the extent to suggest that it is a cold, hard fact that we cannot predict Black Swans but by preempting the future based on our belief that only White Swans exist we set ourselves up for disaster.  So when a Black Swan does come along - and Lane argues that they come up a lot more than we predict - we've made things a whole lot worse by planning around White Swans.&lt;br /&gt;&lt;br /&gt;Any developer who's every used the phrase &lt;a href="http://c2.com/xp/YouArentGonnaNeedIt.html"&gt;"You Ain't Gonna Need It"&lt;/a&gt; would identify with Lane's theory.  YAGNI tell's us that we should only implement what we need &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; what we foresee we need - no matter how sure you are that you're gonna need it.  By writing code which preempts the future design we are building systems for White Swans and when that Black Swan comes along (and it will) we're going to be running around trying to refactor a load of over-engineered code.  The difference between a Black Swan developer and a White Swan developer is the Black Swan developer accepts this and uses YAGNI to battle it where as a White Swan developer just re-engineers his predictions by turning the latest Black Swan into another White Swan - that is until the next Black Swan rears it's ugly head.&lt;br /&gt;&lt;br /&gt;I think YAGNI developers - either naturally or through experience - think that life is full of Black Swans.  I think that this is why some developers don't get YAGNI: they only believe in white ones.  Maybe a different approach is not to say to them "You ain't gonna need it" but maybe say "Black Swan".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-1392140785775417840?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/1392140785775417840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=1392140785775417840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/1392140785775417840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/1392140785775417840'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/05/yagni-battles-black-swans.html' title='YAGNI battles the Black Swans'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5273084990031368943</id><published>2007-05-13T21:00:00.000+01:00</published><updated>2007-05-13T21:32:17.635+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Encapsulation'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Encapsulating Top Trump objects</title><content type='html'>Many of the objects we design are like Top Trumps: on first inspection it looks like we should be exposing all their information so we can see it but when you look closer you realize it's 100% about behaviour.&lt;br /&gt;&lt;br /&gt;What do I mean? A Top Trump game consists of you looking at your card and choosing what you believe the be the best statistic on your card and challanging your opponent. This leads us to expose the data of our Top Trump object using properties so we can see them clearly. In reality however the Top Trump card should be keeping it's data secret: it is only exposing it's data to you not to your opponent, you merle ask your opponent if your card beats his but you never know what data his card contains.&lt;br /&gt;&lt;br /&gt;If we were to model this in an OO world we would probably have a TopTrump class with various comparison methods. We wouldn't want to do the comparisons ourself. As an example we wouldn't do:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public void ChallangeOnSpeed()&lt;br /&gt;{&lt;br /&gt; if(me.CurrentTrump.Speed &amp;gt; opponent.CurrentTrump.Speed)&lt;br /&gt; {&lt;br /&gt;  me.TakeTrumpFrom(opponent);&lt;br /&gt; }&lt;br /&gt; else if(me.CurrentTrump.Speed &amp;lt; opponent.CurrentTrump.Speed)&lt;br /&gt; {&lt;br /&gt;  me.GiveUpTrumpTo(opponent);&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  // it's a draw&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;Instead we'd have the Trumps make their own desicions:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public void Challange(IStatistic statistic)&lt;br /&gt;{&lt;br /&gt; ChallangeResult challangeResult = myTrump.ChallangeWith(statistic);&lt;br /&gt;&lt;br /&gt; if(challangeResult.Equals(Won))&lt;br /&gt; {&lt;br /&gt;  TakeTrumpFrom(opponent);&lt;br /&gt; }&lt;br /&gt; else if(challangeResult.Equals(Lost))&lt;br /&gt; {&lt;br /&gt;  GiveUpTrumpTo(opponent);&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  // it's a draw&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;So what has this gained us? It is no longer down to the player to compare the information the trumps expose instead the responsibility for comparison is with the trumps themselves. Now the trumps are autonomous in deciding how they should behave: they are encapsulated. "And the point of that was?" To answer that question let's look at the evolution of our model. The first version of our software only supported one type of Trump and that was the Supercars pack. Our players could compare directly by choosing ChallangeOnSpeed etc. but now we've designed a new Marvel Comic Heroes pack which have different categories. We'd have to either add new methods or create new Player classes to handle the new Trump classes and new Game classes to handle the new Player classes. What a load of work! Then what happens when Dinosaurs pack or the Horror pack comes out? Or what if we go global and the speed is worked out in KM/H as well as MPH or dollars as well as sterling? By exposing the data we have overburdened the Player and the Game classes with responsibility causing a maintanance nightmare so now everytime our domain evolves our code breaks.&lt;br /&gt;&lt;br /&gt;This is why properties break encapsulation when they expose data directly. When we put the responsibility to compare data on the class which doesn't own it then any change to the class that own's the data has a ripple effect through your whole code breaking Single Responsibility Principle. If on the other hand the object itself is responsible for carrying out the operations on it's data you only make one change and in turn you strengthen the concepts of your domain.&lt;br /&gt;&lt;br /&gt;"OK" I hear you say "but you have to expose properties so you can render the data on the user interface". Ah but do you? What if the Trump object told the UI what to display? "Surely that would mean putting UI code into the Trump object and that's just wrong and anyway I need that data to save to the database as well does that mean we also end up with data code in the class that's even worse?" Not if we use the Mediator pattern (hey imagine a Design Patterns Top Trumps!).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Mediator to the rescue&lt;br /&gt;&lt;/span&gt;On a side note I'd like to discuss why I said Mediator over Builder. Some people use the Builder pattern (Dave Astels did in his One Expectation Per Test example) which is a construction pattern used to seperate the construction of an object from it's representation. The purpose of the Builder is that at the end you get an object. However when working with a UI you may not have an object as an end product instead you may be just sticking your values into existing objects. The Mediator on the other hand merle acts as an interface which defines the interaction between objects to maintain loose coupling. You could argue that some implementations of Builder are really Mediator with a Factory method (or a combination of both as we shall soon see).&lt;br /&gt;&lt;br /&gt;Well let's start by defining our mediator for our Top Trump. For those who have read my blog before you'd know I'm a big fan of Behaviour/Test Driven Development but for the sake of consisnese I'll deal only with the implementations for these examples.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public class TopTrump&lt;br /&gt;{&lt;br /&gt; int speed;&lt;br /&gt;&lt;br /&gt; public void Mediate(ITopTrumpMediator mediator)&lt;br /&gt; {&lt;br /&gt;  mediator.SetSpeed(speed);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface ITopTrumpMediator&lt;br /&gt;{&lt;br /&gt; void SetSpeed(int speed);&lt;br /&gt;}&lt;/pre&gt;Of course you could use a property (what?) for setting the data if you so wished (I think that's perfectly legitamate as it is a behaviour to change the value) however there are good arguments for using a method one of them being overloading (suppose we wanted SetSpeed(string)).&lt;br /&gt;&lt;br /&gt;Now when we implement our concrete Mediator we tie it to the view:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public class UiTopTrumpMediator : ITopTrumpMediator&lt;br /&gt;{&lt;br /&gt; private readonly ITopTrumView view;&lt;br /&gt;&lt;br /&gt; public UiTopTrumpMediator(ITopTrumView view)&lt;br /&gt; {&lt;br /&gt;  this.view = view;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void SetSpeed(int speed)&lt;br /&gt; {&lt;br /&gt;  view.SpeedTextBox.Speed = speed.ToString();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;That works nicely and of course you could implement a database Mediator as well using one method regardless of the destination (I love OO don't you?). The only thing is our Mediator is a bit too close to the exact representation of the object. If we were to introduce our new packs we'd have to rewrite our mediator interface and all the classes that consume it. What we need to do is get back to our domain concepts and start dealing in those again:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public interface ITopTrump&lt;br /&gt;{&lt;br /&gt; void Mediate(ITopTrumpMediator mediator);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface ITopTrumpMediator&lt;br /&gt;{&lt;br /&gt; void AddStatistic(IStatistic);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SupercarTrump : ITopTrump&lt;br /&gt;{&lt;br /&gt; int speed;&lt;br /&gt; SpeedUnit speedUnit;&lt;/pre&gt;&lt;pre class="code-content"&gt; public void Mediate(ITopTrumpMediator mediator)&lt;br /&gt; {&lt;br /&gt;  mediator.AddStatistic(new SpeedStatistic(speed, speedUnit));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class DinosaursTrump : ITopTrump&lt;br /&gt;{&lt;br /&gt; StrengthStatistic strength;&lt;br /&gt;&lt;br /&gt; public void Mediate(ITopTrumpMediator mediator)&lt;br /&gt; {&lt;br /&gt;  mediator.AddStatistic(strength);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;Then on IStatistic we'd add a ToString method like so:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public interface IStatistic&lt;br /&gt;{&lt;br /&gt; string ToString();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SpeedStatistic&lt;br /&gt;{&lt;br /&gt; public string ToString()&lt;br /&gt; {&lt;br /&gt;  return String.Format("{0}{1}", speed, speedUnit);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;Of course we could go on and on refining and refactoring - adding muli-lingual support to our mediator etc. - but hopefully you get the picture; by encapsulating the data of the object and placing the stress on it's behaviour we protect it's internal representation from being exposed thus decreasing it's coupling and making it more flexible and stable during change.&lt;br /&gt;&lt;br /&gt;Now if I'm honest with you after having all the above revelations there was one scenario I struggled with which I hadn't found any good examples to. Basically everyone talks about displaying data to the UI but never about changing the object from the UI. Changing the data implies breaking encapsulation in someway and if the UI isn't allowed to know about the internal representation how is it supposed to change it? Basically how would our Trump Designer package create new Trump cards and edit existing ones?&lt;br /&gt;&lt;br /&gt;Well creation is easy: we'd use the builder pattern and have a concrete implementation of ITopTrumpBuilder for each type of Top Trump card. The UI would then simply engage the ITopTrumpBuilder and pass it's data across in much the same fashion as with the mediator just in reverse. The builder could even tell us if the resulting Trump is valid before we try and get the product.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Remember memento? (not the film the pattern) &lt;/span&gt;&lt;br /&gt;But still what about editing an object? There's a pattern called Memento which because of the film is probably the catchiest of all the pattern names but it still is quite a rarity to see it used. That's because Memento's core purpose is for undo behaviour which is very rare on enterprise systems but it is handy for general editing scenarios. Basically Memento is either a nested private class which either holds or is allowed to manipulate the state it's container (the originator) or an internal class which the originator loads and extracts it's values from. Therefore Mementos offer a very nice way of encapsulating edit behaviour if we combine it with Mediator to create a public interface which objects external to the domain can use.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;public interface ITopTrumpMemento&lt;br /&gt;{&lt;br /&gt; void UpdateStatistic(IStatistic);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class SupercarTrump : ITopTrump&lt;br /&gt;{&lt;br /&gt; private State state;&lt;br /&gt;&lt;br /&gt; private class State&lt;br /&gt; {&lt;br /&gt;  internal int Speed;&lt;br /&gt;  internal SpeedUnit speedUnit;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private class SupercarTrumpMemento : ITopTrumpMemento&lt;br /&gt; {&lt;br /&gt;  private State state;&lt;br /&gt;&lt;br /&gt;  private SupercarTrumpMemento(State state)&lt;br /&gt;  {&lt;br /&gt;   this.state = state;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private State GetState()&lt;br /&gt;  {&lt;br /&gt;   return state;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void UpdateStatistic(IStatistic statistic)&lt;br /&gt;  {&lt;br /&gt;   speedStatistic = statistic as SpeedStatistic;&lt;br /&gt;   if(speedStatistic != null)&lt;br /&gt;   {&lt;br /&gt;    state.Speed = speedStatistic.Speed;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public ITopTrumpMemento CreateMemento()&lt;br /&gt; {&lt;br /&gt;  return new SupercarTrumpMemento(state);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void Update(ITopTrumpMemento memento)&lt;br /&gt; {&lt;br /&gt;  this.state = memento.GetState();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;So there you go: now your UI (or database or webservice) can work with the ITopTrumpMemento interface for editing ITopTrump objects and you can add new TopTrump classes which store their internal data with varying different methods to your hearts content without every breaking any code!&lt;br /&gt;&lt;br /&gt;There are advantages to this too numerous to mention; loose coupling is promoted as the UI never gets near the domain, testing is made far easier as you can use mocks of the IMediator, IBuilder and IMemento instead of working with the domain objects direct and also reusability is increased as the mediators take the responsibility away from your presenters.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Tip:&lt;br /&gt;&lt;/span&gt;The trick with maintaining your encapsulation as neatly as possible is to try and ensure that your IMediators, IBuilders and IMementos all deal with the concepts of their domain (for example IStatistic) and not the structure of the data (e.g. int speed).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5273084990031368943?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5273084990031368943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5273084990031368943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5273084990031368943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5273084990031368943'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/05/encapsulating-top-trump-objects.html' title='Encapsulating Top Trump objects'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8780721486248413710</id><published>2007-05-11T11:25:00.000+01:00</published><updated>2007-05-11T11:32:09.374+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Eric Evans: Hear his voice</title><content type='html'>DotNetRocks have published a podcast of an Eric Evans interview discussing Domain Driven Design (Show #236).&lt;br /&gt;&lt;br /&gt;There's about 11 minutes of irrelevant chatter at the beginning so just skip forward.&lt;br /&gt;&lt;br /&gt;Have a listen and enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8780721486248413710?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8780721486248413710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8780721486248413710' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8780721486248413710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8780721486248413710'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/05/eric-evans-hear-his-voice.html' title='Eric Evans: Hear his voice'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-584142690516683300</id><published>2007-05-10T16:15:00.000+01:00</published><updated>2007-05-15T21:18:42.683+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='Mocks'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Don't Expect too much</title><content type='html'>A long while ago (well over two years) there was a lot of fuss made on the &lt;a href="http://tech.groups.yahoo.com/group/testdrivendevelopment/"&gt;testdrivendevelopment Yahoo group&lt;/a&gt; about having only one assertion per test.  &lt;a href="http://www.blogger.com/www.daveastels.com"&gt;Dave Astels&lt;/a&gt; wrote a great &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=35578"&gt;little article&lt;/a&gt; and a little more fuss was made.  It was one of those things you knew made sence but sounded a lot of work.  I played with one assertion per test anyway and suddenly felt my code developing more fluidly as I focused on only one thing at a time and my tests looked clearer (more behavoir orientated) and refactoring became a lot simpler too.&lt;br /&gt;&lt;br /&gt;Then Dave Astels came along and pushed the envelope further with &lt;a href="http://www.daveastels.com/articles/2006/08/26/one-expectation-per-example-a-remake-of-one-assertion-per-test"&gt;One Expectation per Example&lt;/a&gt;.  This really grabbed my attention as I had been enjoying the benefits of keeping my test code clean with one assertion per test but anything with mocks in it just turned into out of control beasts (especially some of the more complex logic such as MVP).  Even simple four liners such as below would end up with four expectations:&lt;pre class="code-content"&gt;public AddOrder(OrderDto)&lt;br /&gt;{&lt;br /&gt;Customer customer = session.GetCurrentCustomer();&lt;br /&gt;customer.AddOrder(OrderFactory.CreateOrder(OrderDTO));&lt;br /&gt;&lt;br /&gt;workspace.Save(customer);&lt;br /&gt;}&lt;/pre&gt;Then everytime I needed to add new functionality I had to add more expectations and anyone who read the work (including myself after 24 hours) would struggle to make head or tale out of the monster.  And if tests failed it would take a day to find which expectation went wrong.  If you're not careful you end up with the TDD anti-pattern The Mockery.&lt;br /&gt;&lt;br /&gt;I had read Dave Astels article several times but couldn't fathom out how it worked especially seeing it was written in Ruby with the behaviour driven RSpec.  In the end I had to write it out into .NET myself before I got it.&lt;br /&gt;&lt;br /&gt;So here is a break down of how I got Dave's One expectation per example to work for me:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;One Expectation Per Example (C#)&lt;/span&gt;&lt;br /&gt;One of the first things to note is Dave uses the builder pattern in his example.  The idea is that the &lt;span style="font-weight: bold;"&gt;Address &lt;/span&gt;object interacts with a builder to pass it's data to rather than allowing objects to see it's state directly thus breaking encapsulation.  I would like to go into this technique in more detail in another article but to deliver the point quickly think that you may create an HTML builder to display the address on the web.&lt;br /&gt;&lt;br /&gt;Well let's start with Dave's first test:&lt;br /&gt;&lt;pre class="code-content"&gt;[TestFixture]&lt;br /&gt;public class OneExpectationPerExample&lt;br /&gt;{&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureStreetInformation()&lt;br /&gt;{&lt;br /&gt;    Address addr = Address.Parse("ADDR1$CITY IL 60563");&lt;br /&gt;&lt;br /&gt;    Mockery mocks = new Mockery();&lt;br /&gt;    IBuilder builder = mocks.NewMock&amp;lt;IBuilder&amp;gt;();&lt;br /&gt;&lt;br /&gt;    Expect.Once.On(builder).SetProperty("Address1").To("ADDR1");&lt;br /&gt;&lt;br /&gt;    addr.Use(builder);&lt;br /&gt;&lt;br /&gt;    mocks.VerifyAllExpectationsHaveBeenMet();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You may have noticed that I've changed a few things maily to make it look consistant with .NET design practices.  Basically I've introduced a &lt;span style="font-style: italic;"&gt;Parse &lt;/span&gt;method rather than the &lt;span style="font-style: italic;"&gt;from_string&lt;/span&gt; method Dave uses.&lt;br /&gt;&lt;br /&gt;Now we need to get this baby to compile.  First we need to create the &lt;span style="font-weight: bold;"&gt;Address &lt;/span&gt;class like so:&lt;br /&gt;&lt;pre class="code-content"&gt;public class Address&lt;br /&gt;{&lt;br /&gt;public static Address Parse(string address)&lt;br /&gt;{&lt;br /&gt;  throw new NotImplementedExpection();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Use(IBuilder builder)&lt;br /&gt;{&lt;br /&gt;  throw new NotImplementedExpection();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And the &lt;span style="font-weight: bold;"&gt;IBuilder &lt;/span&gt;interface:&lt;br /&gt;&lt;pre class="code-content"&gt;public interface IBuilder {}&lt;/pre&gt;Now it compiles but when we run it we get the following:&lt;br /&gt;&lt;pre class="code-content"&gt;   mock object builder does not have a setter for property Address1&lt;br /&gt;&lt;/pre&gt;So we need to add the &lt;span style="font-weight: bold;"&gt;Address1 &lt;/span&gt;property to the &lt;span style="font-weight: bold;"&gt;IBuilder&lt;/span&gt;.  Then we run and we get:&lt;br /&gt;&lt;pre class="code-content"&gt;    TestCase 'OneExpectationPerExample.ShouldCaptureStreetInformation'&lt;br /&gt;failed: NMock2.Internal.ExpectationException : not all expected invocations were performed&lt;br /&gt;Expected:&lt;br /&gt;1 time: builder.Address1 = (equal to "ADDR1") [called 0 times]&lt;br /&gt;&lt;/pre&gt;Let's implement some working code then:&lt;br /&gt;&lt;pre class="code-content"&gt;public class Address&lt;br /&gt;{&lt;br /&gt;private readonly string address1;&lt;br /&gt;&lt;br /&gt;private Address(string address1)&lt;br /&gt;{&lt;br /&gt;  this.address1 = address1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static Address Parse(string address)&lt;br /&gt;{&lt;br /&gt;    string[] splitAddress = address.Split('$');&lt;br /&gt;&lt;br /&gt;    return new Address(splitAddress[0]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Use(IBuilder builder)&lt;br /&gt;{&lt;br /&gt;    builder.Address1 = address1;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Run the tests again and they work!  So let's move onto the second part of implementing the &lt;span style="font-weight: bold;"&gt;Csp&lt;/span&gt;.  Here's the new test:&lt;br /&gt;&lt;pre class="code-content"&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureCspInformation()&lt;br /&gt;{&lt;br /&gt;    Address addr = Address.Parse("ADDR1$CITY IL 60563");&lt;br /&gt;&lt;br /&gt;    Mockery mocks = new Mockery();&lt;br /&gt;    IBuilder builder = mocks.NewMock&amp;ltIBuilder%gt;();&lt;br /&gt;&lt;br /&gt;    Expect.Once.On(builder).SetProperty("Csp").To("CITY IL 60563");&lt;br /&gt;&lt;br /&gt;    addr.Use(builder);&lt;br /&gt;&lt;br /&gt;    mocks.VerifyAllExpectationsHaveBeenMet();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Now a little refactoring to get rid off our repeated code we turn it into this:&lt;br /&gt;&lt;pre class="code-content"&gt;[TestFixture]&lt;br /&gt;public class OneExpectationPerExample&lt;br /&gt;{&lt;br /&gt;private IBuilder builder;&lt;br /&gt;private Address addr;&lt;br /&gt;private Mockery mocks;&lt;br /&gt;&lt;br /&gt;[SetUp]&lt;br /&gt;public void SetUp()&lt;br /&gt;{&lt;br /&gt;    mocks = new Mockery();&lt;br /&gt;&lt;br /&gt;    builder = mocks.NewMock&amp;lt;ibuilder&amp;gt;();&lt;br /&gt;&lt;br /&gt;    addr = Address.Parse("ADDR1$CITY IL 60563");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[TearDown]&lt;br /&gt;public void TearDown()&lt;br /&gt;{&lt;br /&gt;mocks.VerifyAllExpectationsHaveBeenMet();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureStreetInformation()&lt;br /&gt;{&lt;br /&gt;    Expect.Once.On(builder).SetProperty("Address1").To("ADDR1");&lt;br /&gt;&lt;br /&gt;    addr.Use(builder);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureCspInformation()&lt;br /&gt;{&lt;br /&gt;    Expect.Once.On(builder).SetProperty("Csp").To("CITY IL 60563");&lt;br /&gt;&lt;br /&gt;    addr.Use(builder);&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;Looking good! We run the new test and we get the usual error for having no &lt;span style="font-weight: bold;"&gt;Csp &lt;/span&gt;property on the &lt;span style="font-weight: bold;"&gt;IBuilder &lt;/span&gt;so we add that:&lt;br /&gt;&lt;pre class="code-content"&gt;public interface IBuilder&lt;br /&gt;{&lt;br /&gt;string Address1 { set; }&lt;br /&gt;string Csp { set; }&lt;br /&gt;}&lt;/pre&gt;Then we run the test again and we get:&lt;br /&gt;&lt;pre class="code-content"&gt;   TestCase 'OneExpectationPerExample.ShouldCaptureCspInformation'&lt;br /&gt;failed: NMock2.Internal.ExpectationException : unexpected invocation of builder.Address1 = "ADDR1"&lt;br /&gt;Expected:&lt;br /&gt;1 time: builder.Csp = (equal to "CITY IL 60563") [called 0 times]&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="font-weight: bold;"&gt;Oh no.  This is where Dave's article falls apart for .NET.  &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Basically RSpec has an option to create Quite Mocks which quitely ignore any unexpected calls.  Unfortunately I know of no .NET mock libaries that have such behaviour (though I have since been &lt;a href="http://tech.groups.yahoo.com/group/testdrivendevelopment/message/24281"&gt;reliably informed&lt;/a&gt; by &lt;/span&gt;&lt;/span&gt;John Donaldson on the tdd yahoo group that it is possible with the NUnit mock library) &lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;.  Though there is a way out: stub the whole thing out by using &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(0, 0, 0);"&gt;Method(Is.Anything)&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;pre class="code-content"&gt;[Test]&lt;br /&gt;public void ShouldCaptureCspInformation()&lt;br /&gt;{&lt;br /&gt;Expect.Once.On(builder).SetProperty("Csp").To("CITY IL 60563");&lt;br /&gt;&lt;br /&gt;// stub it as we're not interested in any other calls.&lt;br /&gt;Stub.On(builder).Method(Is.Anything);&lt;br /&gt;&lt;br /&gt;addr.Use(builder);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Just be careful to put the &lt;span style="font-style: italic;"&gt;Stub&lt;/span&gt; AFTER the &lt;span style="font-style: italic;"&gt;Expect &lt;/span&gt;and not before as NMock will use the &lt;span style="font-style: italic;"&gt;Stub &lt;/span&gt;rather than the &lt;span style="font-style: italic;"&gt;Expect &lt;/span&gt;and your test will keep failing.&lt;br /&gt;&lt;br /&gt;So now we run the tests and we get:&lt;br /&gt;&lt;pre class="code-content"&gt;   TestCase 'OneExpectationPerExample.ShouldCaptureCspInformation'&lt;br /&gt;failed:&lt;br /&gt;TearDown : System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.&lt;br /&gt;----&gt; NMock2.Internal.ExpectationException : not all expected invocations were performed&lt;br /&gt;Expected:&lt;br /&gt;1 time: builder.Csp = (equal to "CITY IL 60563") [called 0 times]&lt;br /&gt;&lt;/pre&gt;Excellent NMock is now behaving correctly we can finish implementing the code:&lt;br /&gt;&lt;pre class="code-content"&gt;public class Address&lt;br /&gt;{&lt;br /&gt;private readonly string address1;&lt;br /&gt;private readonly string csp;&lt;br /&gt;&lt;br /&gt;private Address(string address1, string csp)&lt;br /&gt;{&lt;br /&gt;    this.address1 = address1;&lt;br /&gt;    this.csp = csp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static Address Parse(string address)&lt;br /&gt;{&lt;br /&gt;    string[] splitAddress = address.Split('$');&lt;br /&gt;&lt;br /&gt;    return new Address(splitAddress[0], splitAddress[1]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Use(IBuilder builder)&lt;br /&gt;{&lt;br /&gt;    builder.Address1 = address1;&lt;br /&gt;    builder.Csp = csp;&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;Run the test and it works!  Now if we run the whole fixture we get:&lt;br /&gt;&lt;pre class="code-content"&gt;   TestCase 'OneExpectationPerExample.ShouldCaptureStreetInformation'&lt;br /&gt;failed: NMock2.Internal.ExpectationException : unexpected invocation of builder.Csp = "CITY IL 60563"&lt;br /&gt;&lt;/pre&gt;All we need to do do is go back and add the &lt;span style="font-style: italic;"&gt;Stub &lt;/span&gt;code to the street test.  That's a bit of a bummer but we could refactor our tests to do the call in the tear down like so:&lt;br /&gt;&lt;pre class="code-content"&gt;[TearDown]&lt;br /&gt;public void UseTheBuilder()&lt;br /&gt;{&lt;br /&gt;Stub.On(builder).Method(Is.Anything);&lt;br /&gt;&lt;br /&gt;addr.Use(builder);&lt;br /&gt;&lt;br /&gt;mocks.VerifyAllExpectationsHaveBeenMet();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureStreetInformation()&lt;br /&gt;{&lt;br /&gt;Expect.Once.On(builder).SetProperty("Address1").To("ADDR1");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void ShouldCaptureCspInformation()&lt;br /&gt;{&lt;br /&gt;Expect.Once.On(builder).SetProperty("Csp").To("CITY IL 60563");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This approach comes across as slightly odd because the expectations are set in the test but the test is run in the tear down.  I actually think this is neater in some ways as it ensures you have one test class for each set of behaviours the only off putting thing is the naming convention of the attributes.&lt;br /&gt;&lt;br /&gt;I won't bother continuing with the rest of Dave's article as it's just more of the same from here.  The only thing I'd add is he does use one class per behaviour set (or context) so when he tests the behaviour of a string with ZIP code he uses a whole new test fixture.  This can feel a little extreme in some cases as you get a bit of test class explosion but all in all it does make your life a lot easier.&lt;br /&gt;&lt;br /&gt;I hope the translation helps all you .NET B/TDDers out there to free you from The Mockery.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Tip:&lt;/span&gt;&lt;br /&gt;In more complex behaviours you may need to pass a value from one mock to another.  In those instances you can do:&lt;br /&gt;&lt;pre class="code-content"&gt;   Stub.On(x).Method(Is.Anything).Will(Return.Value(y));&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-584142690516683300?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/584142690516683300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=584142690516683300' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/584142690516683300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/584142690516683300'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/05/dont-expect-too-much.html' title='Don&apos;t Expect too much'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5855956119203928594</id><published>2007-04-27T12:41:00.000+01:00</published><updated>2007-05-15T21:08:09.826+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interface'/><title type='text'>Being more Fluent with Equals</title><content type='html'>A lot of .NET developers don't realise that there is a difference between the &lt;a href="http://msdn2.microsoft.com/en-us/library/53k8ybth%28VS.80%29.aspx"&gt;==&lt;/a&gt; operator and the &lt;a href="http://msdn2.microsoft.com/en-us/library/bsc2ak47%28VS.80%29.aspx"&gt;Equals&lt;/a&gt; method.  Even fewer developers realise there is a difference between the == operator and the == operator.  Confused?  That's because == will behave differently depending on whether you apply it to a reference type or a value type.  More confusingly some .NET classes override == and will behave differently again.  To explain MS made this attempt:&lt;br /&gt;&lt;blockquote&gt;For predefined value types, the equality operator (&lt;b&gt;==&lt;/b&gt;) returns true if the values of its operands are equal, &lt;b&gt;false&lt;/b&gt; otherwise. For reference types other than &lt;a onclick="javascript:Track('ctl00_LibFrame_ctl08|ctl00_LibFrame_ctl09',this);" href="http://msdn2.microsoft.com/en-us/library/362314fe%28VS.80%29.aspx"&gt;string&lt;/a&gt;, &lt;b&gt;==&lt;/b&gt; returns &lt;b&gt;true&lt;/b&gt; if its two operands refer to the same object. For the &lt;b&gt;string&lt;/b&gt; type, &lt;b&gt;==&lt;/b&gt; compares the values of the strings.&lt;/blockquote&gt;Except that's not entirey true.  The == operator on string only works if they are both strings.  Confused even more?  Then read &lt;a href="http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx"&gt;this post from the C# FAQ&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So are you clear now?  If not then MS sums it up quite nicely in their &lt;a href="http://msdn2.microsoft.com/en-us/library/ms173147%28VS.80%29.aspx"&gt;Guildelines for overloading:&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;To check for reference equality, use &lt;span class="linkTerms"&gt;&lt;a onclick="javascript:Track('ctl00_LibFrame_ctl07|ctl00_LibFrame_ctl09',this);" href="http://msdn2.microsoft.com/en-us/library/system.object.referenceequals%28VS.80%29.aspx"&gt;ReferenceEquals&lt;/a&gt;&lt;/span&gt;. To check for value equality, use &lt;span class="linkTerms"&gt;&lt;a onclick="javascript:Track('ctl00_LibFrame_ctl07|ctl00_LibFrame_ctl10',this);" href="http://msdn2.microsoft.com/en-us/library/bsc2ak47%28VS.80%29.aspx"&gt;Equals&lt;/a&gt;&lt;/span&gt; or &lt;span class="linkTerms"&gt;&lt;a onclick="javascript:Track('ctl00_LibFrame_ctl07|ctl00_LibFrame_ctl11',this);" href="http://msdn2.microsoft.com/en-us/library/w4hkze5k%28VS.80%29.aspx"&gt;Equals&lt;/a&gt;&lt;/span&gt;.&lt;/blockquote&gt;So why don't developers have it drummed into them to follow the above advice and just dump ==?  Because they believe that == is easier to read.  Let's think about it for a moment.  How is it easier to read? Using == risks making buggy code and goes against every rule about intention revealing interfaces and maintaining encapsulation.  How the hell do you know what the developer intended when she did &lt;span style="font-style: italic;"&gt;x == y&lt;/span&gt;?  Were they checking for value equality or reference equality?  Or had they overloaded == to always do value equality (as string does)?  Basically you don't know (breaking intent) and you'd have to open up the class to see (breaking encapsulation) and still you won't know for sure.  Then of course there is just plain = now did they mean to do that or did they just miss the second =?  So == is definitely &lt;span style="font-style: italic;"&gt;not &lt;/span&gt;easier to read from an intent or encapsulation point of view.&lt;br /&gt;&lt;br /&gt;So they must mean that == is better style.  This I believe is flawed because sometimes you end up doing a bit of == here and a bit of &lt;span style="font-weight: bold;"&gt;Equals  &lt;/span&gt;&lt;span&gt;there &lt;/span&gt;and what's more all objects have Equals but structs do not have ==.  So having a style which prefers == except when == doesn't do the same thing as Equals (or == doesn't even exist) throws all consistency and style out of the window and you end up with a style guide that says "use == except when or when or when" rather than just placing a total ban on ==.&lt;br /&gt;&lt;br /&gt;Then it must just be that &lt;span style="font-style: italic;"&gt;==&lt;/span&gt; &lt;span style="font-style: italic;"&gt;looks&lt;/span&gt; better.  I think this is just habit.  Lets take the following lines:&lt;pre class="code-content"&gt;if(x == y)&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;if(x = y)&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;if(x.Equals(y))&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;/pre&gt;If you took a group of people who knew little about development (or C# for that matter) and ask them what each line means I can guarantee everyone of them will always get the last line right (they'd probably think that the double equals meant equals twice and that would confuse them on the single one).  The Equals method is the most explicit and clear and readable of all of them (it actually reads as x equals y).  To further prove my point grab your same person and ask them what this means:&lt;br /&gt;&lt;pre class="code-content"&gt;if(x)&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;if(!x)&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Then ask them what this means:&lt;br /&gt;&lt;pre class="code-content"&gt;if(x.Equals(true))&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;if(x.Equals(false))&lt;br /&gt;{&lt;br /&gt;// do something&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Those second examples look far clearer and you'd be an idiot to not know what the intent was.  What's more they make their own mini fluent interfaces.  Also you eliminate all those "oh there's a bang at the beginning" bugs.  However I think it is fair to say that x.Equals(true) is a bit overkill though I do find that x.Equals(false) is somewhat clearer than the using the logical negation operator.&lt;br /&gt;&lt;br /&gt;So after knowing that technically it's the right thing to do, that it's better for showing intent, that it is more consistent, that is reduces risk of bugs and everything else, if you &lt;span style="font-style: italic;"&gt;still &lt;/span&gt;need convincing because you still think that == &lt;span style="font-style: italic;"&gt;looks&lt;/span&gt; better then justify it by saying you're using a  fluent interface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5855956119203928594?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5855956119203928594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5855956119203928594' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5855956119203928594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5855956119203928594'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/04/being-more-fluent-with-equals.html' title='Being more Fluent with Equals'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-6214373666221424067</id><published>2007-04-27T09:49:00.000+01:00</published><updated>2007-05-15T21:13:39.795+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>TDD Anti-Patterns</title><content type='html'>It's a bit old now but I picked up a piece of code from a supplier that had the &lt;span style="font-weight: bold;"&gt;Generous Leftovers&lt;/span&gt; anti-pattern and it reminded me that every developer should have this list printed off and study it regularly.&lt;br /&gt;&lt;br /&gt;Check out &lt;a href="http://blog.james-carr.org/?p=44"&gt;James Carr's TDD Anti-Patterns.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Free Ride&lt;/span&gt; is probably the most common one and developers need to refer to &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=35578"&gt;"one assertion per test"&lt;/a&gt; to try and avoid this.&lt;br /&gt;&lt;br /&gt;I think &lt;span style="font-weight: bold;"&gt;The Mockery&lt;/span&gt; is quite possibly the hardest anti-pattern to avoid mainly because we need a leap forward in the way Mock libaries work (what I call Quite Mocks).  This will allow "&lt;a href="http://www.daveastels.com/articles/2006/08/26/one-expectation-per-example-a-remake-of-one-assertion-per-test"&gt;one expectation per example&lt;/a&gt;".   &lt;a href="http://rspec.rubyforge.org/index.html"&gt;RSpec&lt;/a&gt; (used in the tutorial) has its &lt;a href="http://rspec.rubyforge.org/documentation/mocks/mocks.html"&gt;own mock libary&lt;/a&gt; that supports Quite Mocks by passing a null_object argument.  Unfortunately for us .NET developers out there such support doesn't exist.  I have requested it on the &lt;a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1702889&amp;amp;amp;amp;group_id=66591&amp;atid=515020"&gt;NMock feature requests board&lt;/a&gt; but in the mean time you can create a helper class which uses reflection to stub out all the methods/properties you are not testing.&lt;br /&gt;&lt;br /&gt;I am planning to 'translate' &lt;a href="http://www.daveastels.com/"&gt;Dave Astels&lt;/a&gt; article to C# 'cos Ruby can be a bit tough on the eyes if you aren't used to it and as I mentioned already you need Quite Mocks (which don't exist) to really get it to work.&lt;br /&gt;&lt;br /&gt;In the mean time I made my own contribution to the TDD Anti-Patterns with:&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Mad Hatter’s Tea Party&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;This is one of those test cases that seems to test a whole party of objects without testing any specific one. This is often found in poorly designed systems that cannot use mocks or stubs and as a result end up testing the state and behaviour of every peripheral object in order to ensure the object under test is working correctly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-6214373666221424067?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/6214373666221424067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=6214373666221424067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6214373666221424067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/6214373666221424067'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/04/tdd-anti-patterns.html' title='TDD Anti-Patterns'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-5972707795939917099</id><published>2007-04-20T15:58:00.000+01:00</published><updated>2007-04-20T16:04:15.894+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='london marathon'/><category scheme='http://www.blogger.com/atom/ns#' term='chariry'/><category scheme='http://www.blogger.com/atom/ns#' term='breaks4kids'/><category scheme='http://www.blogger.com/atom/ns#' term='sponsor'/><title type='text'>Sponsor Me</title><content type='html'>I'm doing the &lt;a href="http://www.london-marathon.co.uk/"&gt;London Marathon&lt;/a&gt; this Sunday.  If anyone falls across this post and wishes to sponsor me and give some money to the &lt;a href="http://www.yha.org.uk/about-yha/challenges/flora-london-marathon.aspx"&gt;breaks4kids &lt;/a&gt;charity I'm running for then please do.&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;iframe src="http://www.justgiving.com/rss/getfundraisingPage2.asp?EventGivingGroupId=529364" frameborder="0" height="322" scrolling="no" width="195"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;Sorry: no more non-geeky activity on this blog (though it's for a good cause).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-5972707795939917099?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/5972707795939917099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=5972707795939917099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5972707795939917099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/5972707795939917099'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/04/sponsor-me.html' title='Sponsor Me'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-837630845355810928</id><published>2007-04-17T13:27:00.000+01:00</published><updated>2007-04-17T13:35:17.899+01:00</updated><title type='text'>Don't override the back button</title><content type='html'>Have Google developers forgotton the number 1 of the &lt;a href="http://www.useit.com/alertbox/990530.html"&gt;The Top Ten Web Design Mistakes&lt;/a&gt;: namely don't break the back button?&lt;br /&gt;&lt;br /&gt;I was just working on a great post, clicked on preview, found an error, clicked back to go back to the form and accidently (honest) clicked OK and now the post I just spent 45 minutes working on is gone because Google have messed with the way the back button works.&lt;br /&gt;&lt;br /&gt;I know why this happened: because we're in a DHTML/AJAX world now and I didn't really submit anything (as the form gives the appearance of) just flipped a little javascript and switched some styles and layers about but for the sake of the Web are we really back to the 1999 world of DHTML abuse or could this be the first signs of Google's Microsoftization and they're now making the standards?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-837630845355810928?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/837630845355810928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=837630845355810928' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/837630845355810928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/837630845355810928'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/04/dont-override-back-button.html' title='Don&apos;t override the back button'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-325922024970821401</id><published>2007-04-11T13:03:00.000+01:00</published><updated>2007-04-11T14:16:57.804+01:00</updated><title type='text'>Whole Values</title><content type='html'>I read a post the other day that said one of the commonest mistakes made by newbie OOP programmers was to do this:&lt;pre class="code-content"&gt;PostCode postCode = "SW1 1EQ";&lt;/pre&gt;Then a spurt of experienced programmers hailed down their fury on this common misconception amongst newbies and how they had to bash out of them that they shouldn't waste their lives abstracting strings.&lt;br /&gt;&lt;br /&gt;I also heard a MS qualified trainer tell all he knew and respected him that you should avoid the &lt;a href="http://msdn2.microsoft.com/en-us/library/z5z9kes2%28VS.71%29.aspx"&gt;implicit operator overload&lt;/a&gt; at all costs because "if your type were meant to be a string MS would have made it one".&lt;br /&gt;&lt;br /&gt;Unfortunately this is one of those places where the MS fan boys have been bought up badly by nasty VB.  The concepts that are being so frowned upon by leagues of MVPs is not only a corner stone of OOP (to mix data and behaviour) but a wonderful concept called &lt;a href="http://c2.com/ppr/checks.html#1"&gt;Whole Value&lt;/a&gt; and implicit overloading is C#'s gift to you to make it happen.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thom.org.uk/blog/Trackback.aspx?guid=c8be0389-f69d-446e-bc19-5fff55f3fa06"&gt;Thom Lawrence&lt;/a&gt; has a lovely short post on how to do whole values with implicit operators &lt;a href="http://thom.org.uk/blog/SafetyImplicitOperator.aspx"&gt;here&lt;/a&gt;&lt;br /&gt;so I won't repeat his good work (though I will add that Martin Fowler recommends using structs) but what I will do is try and explain why whole values are a wonderful thing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Because a PostCode isn't a Surname&lt;br /&gt;&lt;/span&gt;One of the first and most basic things a Whole Value will give you is a level of type safety that you may never have realised existed.  Have you ever had that annoying bug pop up in an application because someone accidently did this:&lt;pre class="code-content"&gt;FindPerson(form.PostCode, form.Surname)&lt;br /&gt;// somewhere else far, far away:&lt;br /&gt;public ReadOnlyCollection&lt;person&gt; FindPerson(string surname, string postCode);&lt;/person&gt;&lt;/pre&gt;In this simple example it's pretty obvious you've got it round the wrong way but when you've got a few extra variables to play with it's really easy to get it wrong.  Well what if I said there's a way to prevent this ever happening?  Use a Whole Value like so:&lt;pre class="code-content"&gt;&lt;br /&gt;FindPerson(form.PostCode, form.Surname)&lt;br /&gt;&lt;br /&gt;interface Form&lt;br /&gt;{&lt;br /&gt;Surname Surname {get{}};&lt;br /&gt;PostCode PostCode {get{}};&lt;br /&gt;}&lt;br /&gt;// somewhere else far, far away:&lt;br /&gt;public ReadOnlyCollection&lt;person&gt; FindPerson(Surname surname, PostCode postCode);&lt;/person&gt;&lt;/pre&gt;Now when you go to compile you will get an error because tpye PostCode cannot be assigned to type Surname.  You'll also find it helps when you do overloading.  You can turn nasty code like this:&lt;pre class="code-content"&gt;FindByPostCodeAndSurname(string postCode, string surname);&lt;br /&gt;FindByPostCode(string postCode);&lt;br /&gt;FindBySurname(string surname);&lt;/pre&gt;Into this:&lt;pre class="code-content"&gt;Find(PostCode postCode, Surname surname);&lt;br /&gt;Find(PostCode postCode);&lt;br /&gt;Find(Surname surname);&lt;/pre&gt;How much cleaner is that?  Of course there are other ways to skin that cat but you will still find that those ugly method names dissapear (especially in factories etc.).&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;Because a PostCode was born of string&lt;br /&gt;&lt;/span&gt;The other thing is PostCode will start his life out as a string of some form.  Either from a web form or a database but somewhere he was made out of a string.  This is where the implicit overloading comes in: we can allow PostCode to easily start out as a string and handle like a string when he needs to (because he's gonna need to):&lt;pre class="code-content"&gt;PostCode postCode = Form["PostCode"];&lt;br /&gt;&lt;/pre&gt;Then somewhere far away:&lt;pre class="code-content"&gt;&lt;br /&gt;Parameter["PostCode"] = Address.PostCode;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;Because a PostCode isn't a string&lt;br /&gt;&lt;/span&gt;The other thing is PostCode isn't a string. Sure somewhere he starts life as a string  and somewhere you've got to have a string with the real post code in it but somewhere even further down that ain't a string at all it's a char array and somewhere further down...  The point of OOP is to abstract real world things and encapsulate them and if you let PostCode wander around your system as a string he's never gonna reach his full potential (and he might just wander where he shouldn't).  All the other bigger grown up objects are going to have to do everything for him: deciding whether he's valid, chop him up to find out what his area code is, compare him to other postcodes to see if they're in the same area.  The poor old postcode will never reach his potential and instead will be pushed and shoved around by all the bigger boys.&lt;br /&gt;&lt;br /&gt;You are a cruel, cruel programmer to let this happen: you are just as bad as those parents who never give their children any responsibility and then moan at them for being incapable of doing anything for themselves.  But there is still hope: give your PostCode some responsibility and start by making him a Whole Value:&lt;pre class="code-content"&gt;struct PostCode&lt;br /&gt;{&lt;br /&gt;Area {get;}&lt;br /&gt;District {get;}&lt;br /&gt;Sector {get;}&lt;br /&gt;InwardCode {get;}&lt;br /&gt;OutwardCode {get;}&lt;br /&gt;}&lt;/pre&gt;Doesn't that look better?  Now instead of this:&lt;pre class="code-content"&gt;string postCode = "SQ1 1EQ";&lt;br /&gt;if(LondonPostCodes.Contains(postCode.Substring... yuk I can't go on!&lt;/pre&gt;You can do something beautiful like this:&lt;pre class="code-content"&gt;postCode = "SQ1 1EQ";&lt;br /&gt;if(LondonPostCodes.Contains(postCode.Area)) ...&lt;/pre&gt;This of course goes even further because Area is a whole value too and you may decide that it should know what city it is.  So the code now becomes:&lt;br /&gt;&lt;pre class="code-content"&gt;if(postCode.Area.City.Equals(City.London))&lt;/pre&gt;Now PostCode can take all of that nasty horrible code that all the bigger boys had (and probably duplicated) and deal with it himself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Because a PostCode should be a legitimate PostCode&lt;/span&gt;&lt;br /&gt;Validation is also a good responsibility of a whole value so you can make the thing blow up if you try and put something bad in it (just the same as a DateTime will).  For extra safety you can add &lt;span style="font-weight: bold;"&gt;Parse &lt;/span&gt;and &lt;span style="font-weight: bold;"&gt;TryParse &lt;/span&gt;methods to your Whole Value (I have them as standard).&lt;br /&gt;&lt;br /&gt;So not only does your code become more type safe, more powerful and flexible but it also becomes more stable.  No longer does every other object have to keep checking whether the postcode is in good shape or reference some nasty function library to find out the area; our little PostCode string has grown up into a real object at last and can now go out into the big wide world knowing he can shoulder the responsibility of keeping himself valid and answer all the questions people want to know of him.&lt;br /&gt;&lt;br /&gt;So now whenever you see a simple type like a string or an int sittting on the outside of one your classes take a close look at it and ask youself what could have been if you'd only let it become a whole value.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-325922024970821401?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/325922024970821401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=325922024970821401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/325922024970821401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/325922024970821401'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/04/whole-values.html' title='Whole Values'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-7702893036586582132</id><published>2007-03-13T16:35:00.000Z</published><updated>2007-03-13T17:08:20.516Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interface'/><category scheme='http://www.blogger.com/atom/ns#' term='specification pattern'/><title type='text'>Fluent Specification Part 4: Prepacked Questions</title><content type='html'>I went to my client and demo'd the Bouncer application to him and he was happy so we rolled it out immediately but he did say that the direction of his business had changed recently and we needed to make a few changes.&lt;br /&gt;&lt;br /&gt;A week later we met up and he excitedly told me all about how his entertainment service was doing really well but he was not getting the most potential out of his business as he was only open at weekends. What he wanted to do was be open 7 nights a week with different events each night. The problem is that on different events the rules around who to let in will change and my Bouncer isn't flexible enough to handle that at the moment. He really needs me to update the app as soon as to start ramping up his business.&lt;br /&gt;&lt;br /&gt;So what we need to do is allow an event class to supply the questions which the bouncer will ask the clubbers. So we need some code like this:&lt;pre class="code-content"&gt;Event tonightsEvent = new Event(new QuestionToAsk(IsClubber.YoungEnough(16), "under sixteens only mate")&lt;br /&gt;  .AndNot(IsClubber.WearingFancyDress(), "fancy dress only tonight");&lt;/pre&gt;&lt;pre class="code-content"&gt;foreach(Clubber clubber in queue.Clubbers)&lt;br /&gt;{&lt;br /&gt;  Answer answer = clubber.Ask(tonightsEvent.EntryQuestions);&lt;br /&gt;  if(answer.IsFalse) ...&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;To achieve this we have to introduce a new class called a &lt;em&gt;QuestionToAsk&lt;t&gt;&lt;/em&gt;. This looks almost identical to the &lt;em&gt;IQuestionSyntax&lt;/em&gt; except it has an &lt;em&gt;Ask(T obj)&lt;/em&gt; method which returns a &lt;em&gt;IQuestionSyntax&lt;/em&gt; instead of &lt;em&gt;an Answer&lt;/em&gt; property (this is because the other question is being answered where as this one needs to be given to the clubber). This meant overriding the &lt;em&gt;Ask() &lt;/em&gt;method of the clubber to look like this:&lt;/p&gt;&lt;pre class="code-content"&gt;public IQuestionSyntax Ask(QuestionToAsk questionToAsk)&lt;br /&gt;{&lt;br /&gt;  return questionToAsk.Ask(this);&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;So I implemented the new parts to my framework and checked that all my existing tests and new tests passed and rolled out the Bouncer to the client.&lt;/p&gt;&lt;p&gt;I'm sorry if I rushed the last couple of posts but there should be enough info to get the pattern off the ground.  What I like is that I can use the fluent style to make sentances up which are easy to read and apply to objects.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-7702893036586582132?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/7702893036586582132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=7702893036586582132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7702893036586582132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/7702893036586582132'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/03/fluent-specification-part-4-prepacked.html' title='Fluent Specification Part 4: Prepacked Questions'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4556612532702291469</id><published>2007-03-10T11:54:00.002Z</published><updated>2007-03-13T16:44:13.712Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interface'/><category scheme='http://www.blogger.com/atom/ns#' term='specification pattern'/><title type='text'>Fluent Specification Part 3: Giving feedback</title><content type='html'>There are a few things still left to be done to improve the Fluent Specification.&lt;br /&gt;&lt;br /&gt;I’d like to make a couple of points about TDD and iterative development before I go on . Using TDD I have managed to get to a point where I’ve solved one problem at a time and using refactoring I have improved upon my original design and without deviating from my original goal. I have managed to roll out my existing functionality and give real value to my clients.  Now I am in a good position to use this proven functionality elsewhere. If I had sat down and said “I’m going to create this great framework for specifications” I would probably have got myself in a complete mess and ended up taking longer to make something unwieldy and over-engineered.&lt;br /&gt;&lt;br /&gt;Fluent Specification has been very succesfuly with my customer class so I decide to use it with other objects. I need to employ the power of generics. I don’t think I need to go into detail here so basically I now have the following interfaces:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;IQuestionSyntax&lt;t&gt;&lt;t&gt;&lt;/li&gt;&lt;li&gt;ISpecification&lt;t&gt;&lt;t&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As I was working on another domain I realised that my I realized that I really liked my Fluent Specification with my customer object and so I decided that I should harvest it &lt;a href="http://www.martinfowler.com/bliki/HarvestedFramework.html"&gt;http://www.martinfowler.com/bliki/HarvestedFramework.html&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;The new domain was for a bouncer application which worked through a queue of clubbers and checked if they were allowed in. So I had some nice code which went something like this:&lt;/p&gt;&lt;pre class="code-content"&gt;foreach(Clubber clubber in Queue)&lt;br /&gt;{&lt;br /&gt;  if(clubber.Ask(IsClubber.OldEnough().AndNot(IsClubber.BreakingDressCode().And(IsClubber.NameDown(guestList))&lt;br /&gt;  {&lt;br /&gt;    clubber.RefuseEntry();&lt;br /&gt;  )&lt;br /&gt;  clubber.ComeIn(event);&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;So we rolled out our bouncer application and my client was very impressed. The number of dodgy clubbers getting in went down and everything was good. A few weeks later my client comes back and says he is getting a large number of complaints because my bouncer is just refusing clubbers without telling them why. I bit my tounge about this implementing standard bouncer behaviour as he likes to operate a customer friendly adult evening enterntainment service. So I went back to my code and tried to find a way of making my bouncer give some feedback.&lt;/p&gt;&lt;p&gt;I had to start introducing some new concepts. For a start my &lt;em&gt;Anwser&lt;/em&gt; property became a full fledged object with a &lt;em&gt;Feedback&lt;/em&gt; property and an &lt;em&gt;IsTrue&lt;/em&gt; and &lt;em&gt;IsFalse &lt;/em&gt;properties. I then created a &lt;em&gt;IQuestion&lt;t&gt;&lt;/em&gt; interface and a standard &lt;em&gt;Question&lt;t&gt;&lt;/em&gt; class which wrapped &lt;em&gt;ISpecification&lt;t&gt;&lt;/em&gt;s and &lt;em&gt;Feedback &lt;/em&gt;(note how I've used &lt;a href="http://fit.c2.com/wiki.cgi?WholeValue"&gt;whole value&lt;/a&gt; for &lt;em&gt;Feedback&lt;/em&gt;)&lt;em&gt;. &lt;/em&gt;&lt;/p&gt;&lt;pre class="code-content"&gt;public class Question&lt;t&gt; : IQuestion&lt;t&gt;&lt;br /&gt;{&lt;br /&gt;  private readonly ISpecification&lt;t&gt; spec;&lt;br /&gt;  private readonly Feedback feedback;&lt;br /&gt;&lt;br /&gt;  public Question(ISpecification&lt;t&gt; spec, Feedback feedback)&lt;br /&gt;  {&lt;br /&gt;   this.spec = spec;&lt;br /&gt;   this.feedback = feedback;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Answer Ask(T obj)&lt;br /&gt;  {&lt;br /&gt;   return new Answer(spec.IsSatisfiedBy(obj), feedback);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;I then had to upgraded my &lt;em&gt;Or/AndSpecification&lt;/em&gt; classes to become &lt;em&gt;Or/AndCompositeQuestion&lt;t&gt; : IQuestion&lt;t&gt;&lt;/em&gt; classes. I then added feedback logic into the composite questions like so:&lt;/p&gt;&lt;pre class="code-content"&gt;public class OrCompositeQuestion&lt;t&gt; : IQuestion&lt;t&gt;&lt;br /&gt;{&lt;br /&gt; IQuestion&lt;t&gt; question1;&lt;br /&gt; IQuestion&lt;t&gt; question2;&lt;br /&gt;&lt;br /&gt; public OrCompositeQuestion(IQuestion&lt;t&gt; question1, IQuestion&lt;t&gt; question2)&lt;br /&gt; {&lt;br /&gt;  this.question1 = question1;&lt;br /&gt;  this.question2 = question2;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Answer Ask(T obj)&lt;br /&gt; {&lt;br /&gt;  Answer result1 = question1.Ask(obj);&lt;br /&gt;  Answer result2 = question2.Ask(obj);&lt;br /&gt;&lt;br /&gt;  Feedback feedback = string.Empty;&lt;br /&gt;&lt;br /&gt;  if(!result1.IsTrue)&lt;br /&gt;  {&lt;br /&gt;   feedback = feedback.Append("or", result1.Feedback);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if(!result2.IsTrue)&lt;br /&gt;  {&lt;br /&gt;   feedback = feedback.Append("or", result2.Feedback);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return new Answer(result1.IsTrue  result2.IsTrue, feedback);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;I then walked through my code refactoring in my new classes and adding the &lt;em&gt;Feedback&lt;/em&gt; paramater to my &lt;em&gt;Ask&lt;/em&gt; method. Now I could do this:&lt;pre class="code-content"&gt;Answer answer = clubber.Ask(IsClubber.OldEnough(), "over eighteens only mate")&lt;br /&gt;  .AndNot(IsClubber.BreakingDressCode(), "trainers aren't allowed")&lt;br /&gt;  .And(IsClubber.NameDown(guestList), "if you're names not down you're not coming in");&lt;br /&gt;if(answer.IsFalse)&lt;br /&gt;{&lt;br /&gt;  clubber.Refuse(answer.Feedback);&lt;br /&gt;}&lt;br /&gt;clubber.ComeIn();&lt;/pre&gt;&lt;p&gt;I have left alot of code out there but I think you should get the picture. There is a bit of cleaning up needed to do and maybe a little refactoring on the structure of my classes but still I've got something that works, it passes my tests, I can demo it to the client and make sure he's happy with my new enhanced Bouncer application.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-4556612532702291469?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4556612532702291469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4556612532702291469' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4556612532702291469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4556612532702291469'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/03/fluent-specification-part-3-giving.html' title='Fluent Specification Part 3: Giving feedback'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-4586307843884629646</id><published>2007-03-10T11:54:00.001Z</published><updated>2007-03-13T11:46:39.482Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interface'/><category scheme='http://www.blogger.com/atom/ns#' term='specification pattern'/><title type='text'>Fluent Specification Part 2: Becoming more fluent</title><content type='html'>Last post we went through combining the two patterns &lt;a href="http://www.martinfowler.com/bliki/FluentInterface.html"&gt;Fluent Interface&lt;/a&gt; and &lt;a href="http://www.martinfowler.com/apsupp/spec.pdf"&gt;Specification&lt;/a&gt; to make a Fluent Specification and ended up with something like this:&lt;br /&gt;&lt;pre class="code-content"&gt;customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods))&lt;/pre&gt;OK this all looks pretty good. Now I can ask my customer any question I like but I can only ask them one at a time so I would still have to do:&lt;br /&gt;&lt;pre class="code-content"&gt;customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods)) &amp;&amp;amp; customer.Ask(IsCustomer.AbleToAffordGoods(goods)) &lt;/pre&gt;Wouldn't it be better if we could extend our fluent interface to make it more, well, fluent?&lt;br /&gt;&lt;pre class="code-content"&gt;customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods)).And(IsCustomer.AbleToAffordGoods(goods))&lt;/pre&gt;This starts looking more like predicates now (where you can join logical rules together easily).&lt;br /&gt;To achieve this we need a new object called a Question:&lt;br /&gt;&lt;pre class="code-content"&gt;public class CustomerQuestion&lt;br /&gt;{&lt;br /&gt; readonly bool answer;&lt;br /&gt; readonly Customer customer;&lt;br /&gt;&lt;br /&gt; public CustomerQuestion(bool answer, Customer customer)&lt;br /&gt; {&lt;br /&gt;  this.answer = answer;&lt;br /&gt;  this.customer = customer;&lt;br /&gt; }&lt;br /&gt; public CustomerQuestion And(ISpecification spec)&lt;br /&gt; {&lt;br /&gt;  return new CustomerQuestion(answer &amp;&amp;amp; spec.IsSatisfiedBy(customer), customer);&lt;br /&gt; }&lt;br /&gt; public bool Answer&lt;br /&gt; {&lt;br /&gt;  get{return answer;}&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;And we need to update our &lt;em&gt;Customer Ask()&lt;/em&gt; method to look like this:&lt;br /&gt;&lt;pre class="code-content"&gt;public CustomerQuestion Ask(ISpecification spec)&lt;br /&gt;{&lt;br /&gt;  return new CustomerQuestion(spec.IsSatisfiedBy(this), this);&lt;br /&gt;}&lt;/pre&gt;Now we can link Questions together easily and by simply extending the Question we can add methods for &lt;em&gt;Or&lt;/em&gt;, &lt;em&gt;OrNot&lt;/em&gt; and &lt;em&gt;AndNot&lt;/em&gt; allowing us to make nice little statements like:&lt;br /&gt;&lt;pre class="code-content"&gt;customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods)).AndNot(IsCustomer.GivingMeFakeId())&lt;/pre&gt;There are a few advantages to the Fluent Specification which I’d just like to go over before wrapping up this post; they are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It is easy to join specifications together. &lt;/li&gt;&lt;li&gt;Clients can easily apply specifications to objects.&lt;/li&gt;&lt;li&gt;It makes the codes intent clearer. &lt;/li&gt;&lt;li&gt;Common specifications can be gathered together in a Factory making a clear API of business rules. &lt;/li&gt;&lt;li&gt;Unlike some Fluent Interfaces it doesn’t break Query and Command. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Next post I’d like to go over extending the Fluent Specification even further.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-4586307843884629646?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/4586307843884629646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=4586307843884629646' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4586307843884629646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/4586307843884629646'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/03/fluent-specification-part-2-becoming.html' title='Fluent Specification Part 2: Becoming more fluent'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6794675998088145034.post-8959280126459169039</id><published>2007-03-10T09:15:00.000Z</published><updated>2007-03-13T11:45:56.183Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interface'/><category scheme='http://www.blogger.com/atom/ns#' term='specification pattern'/><title type='text'>Fluent Specification Part 1: Combining patterns</title><content type='html'>Two patterns which are really quite nice are &lt;a href="http://www.martinfowler.com/bliki/FluentInterface.html"&gt;Fluent Interface&lt;/a&gt; and &lt;a href="http://www.martinfowler.com/apsupp/spec.pdf"&gt;Specification&lt;/a&gt;. Both are fairly simplistic compared to most patterns. Fluent Interface is more of a style where you wire objects together in a walk the dot fashion to make them work like sentances. A common fluent interface is NMock2:&lt;br /&gt;&lt;pre class="code-content"&gt;Expect.Once.On(object).Method("Name").With(value).Will(Return.Value(returnValue)) &lt;/pre&gt;Compared to the old non-fluent interface of:&lt;br /&gt;&lt;pre class="code-content"&gt;mockObject.ExpectAndReturn("Name", returnValue, value);&lt;/pre&gt;At first it looks like more code but as expectations become more complex and to anyone reading the code the fluent interface is a lot clearer and easier to work with.&lt;br /&gt;&lt;br /&gt;The specification pattern comes from Eric Evans and is found in detail in his book &lt;a href="http://domaindrivendesign.org/books/index.html"&gt;Domain Driven Design&lt;/a&gt;. The idea of the specification pattern is to break your business rules into small self contained, reusable objects called specifications. The specification has an bool IsSatisfiedBy(object) method. The idea is to give some sort of &lt;a href="http://en.wikipedia.org/wiki/Predicate_(logic)"&gt;predicate &lt;/a&gt;style to OOP languages. So rather than:&lt;br /&gt;&lt;pre class="code-content"&gt;if(customer.Age &gt;= goods.MinimumAge)&lt;/pre&gt;You replace it with a LegalAgeSpecification which looks like the following:&lt;br /&gt;&lt;pre class="code-content"&gt;if(new LegalAgeSpecification(goods).IsSatisfiedBy(customer))&lt;/pre&gt;Which again, although may look like more stuff going on once you've got a few of these scattered about your class soon becomes clearer and easier to use. The added bonus is specifications can be reused all over the place: for example for validation, searching collections or within other specifications and they keep all of your business rules in the domain where they belong. What you'll soon discover is you will build up a rich set of business rules in your domain you can call upon at will.&lt;br /&gt;&lt;br /&gt;So how about we take this a step further, create some synergy between some patterns (which is undoubtably where patterns get their greatest power) and create a Fluent Specification? The idea behind a Fluent Specification is to make your specifications look more fluent. The above code is rather ugly so why can't we do something like this instead:&lt;br /&gt;&lt;pre class="code-content"&gt;if(customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods)))&lt;/pre&gt;Isn't that a lot clearer already? The goods object now flows with the sentance of the interface rather than trying to hide its role by sitting in a constructor. Already we have made our intent clearer.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So how would we write something like this? Well there are three main components to this example: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Question (the Ask() method) &lt;/li&gt;&lt;li&gt;A specification factory (the IsCustomer singleton) &lt;/li&gt;&lt;li&gt;A specification (the OldEnoughToBuyGoods object returned from the factory) &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Normally I would do this TDD and set up a test which looks like the following:&lt;br /&gt;&lt;pre class="code-content"&gt;Customer customer = new Customer();&lt;br /&gt;customer.Age = 14;&lt;br /&gt;Goods goods = new Alchohol();&lt;br /&gt;Assert.IsFalse(customer.Ask(IsCustomer.OldEnoughToBuyGoods(goods))) &lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;And of course test &lt;em&gt;IsTrue&lt;/em&gt; as well but I don't want to make this post 100 pages long so you'll just have to take my word for the TDD. So the first thing to do (TDD style) would be to write a test for the specification itself and test it. So my specification looks like:&lt;br /&gt;&lt;pre class="code-content"&gt;public class LegalAgeSpecification&lt;br /&gt;{&lt;br /&gt;  readonly Goods goods;&lt;br /&gt;  public LegalAgeSpecification(Goods goods)&lt;br /&gt;  {&lt;br /&gt;    this.goods= goods;&lt;br /&gt;  }&lt;br /&gt;  public bool IsSatisfiedBy(Customer customer)&lt;br /&gt;  {&lt;br /&gt;    return customer.Age &gt;= goods.MinimumAge;&lt;br /&gt;  }&lt;br /&gt;} &lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I want to just draw attention to a few things about this specification: I have been very specific about passing the goods object and through rather than making a more generic OlderThanSpecification. The reason is that I may wish to expand this specification in the future to include more business rules as they come up: for example the business rule may say that for certain goods we must check for ID, so the rule may expand to this: &lt;/p&gt;&lt;pre class="code-content"&gt;public bool IsSatisfiedBy(Customer customer)&lt;br /&gt;{&lt;br /&gt;  if(goods.RequireId)&lt;br /&gt;  {&lt;br /&gt;    return customer.Id.DateOfBirth.CurrentAge &gt;= goods.MinimumAge&lt;br /&gt;  }&lt;br /&gt;  return customer.Age &gt;= goods.MinimumAge;&lt;br /&gt;} &lt;/pre&gt;&lt;p&gt;Of course you may wish to factor out that rule into a seperate &lt;em&gt;ValidIdForMinimumAgeSpecifcation&lt;/em&gt; and call it within this one.&lt;br /&gt;Does this go against YAGNI (You Ain't Gonna Need It)? No: because you are making the object more specific and more flexible by making a very simple design desicion. To have created a more generic &lt;em&gt;OlderThanSpecification&lt;/em&gt; is more YAGNI as there is no requirement for that just yet. You may find that as time goes on you will refactor out the rule into a seperate spec but on first pass keep your objects specific to the business rule and inline with the &lt;a href="http://domaindrivendesign.org/discussion/messageboardarchive/UbiquitousLanguage.html"&gt;ubiquitous language&lt;/a&gt;.&lt;br /&gt;So now we have a specification and its up and running so how do we make this fluent? Well I'm going to rush forward and dump the Factory and the Question out in one go (though I was a little more structured using TDD). &lt;/p&gt;&lt;pre class="code-content"&gt;public class Customer&lt;br /&gt;{&lt;br /&gt;  ...&lt;br /&gt;  public bool Ask(ISpecification spec)&lt;br /&gt;  {&lt;br /&gt;    return spec.IsSatisfiedBy(this);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;public static class IsCustomer&lt;br /&gt;{&lt;br /&gt;  public static ISpecification OldEnoughToBuyGoods(Goods goods)&lt;br /&gt;  {&lt;br /&gt;    return new LegalAgeSpecification(goods);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;During my TDD to achieve my goal of a fluid and flexible interface I needed some refactoring and created an interface for the specification. Now my old specifaction implements the &lt;em&gt;ISpecifcation&lt;/em&gt; interface making the &lt;em&gt;Ask()&lt;/em&gt; method polymorphic. &lt;/p&gt;&lt;p&gt;Next post I’ll go through making this even more fluent. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6794675998088145034-8959280126459169039?l=jupitermoonbeam.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jupitermoonbeam.blogspot.com/feeds/8959280126459169039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6794675998088145034&amp;postID=8959280126459169039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8959280126459169039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6794675998088145034/posts/default/8959280126459169039'/><link rel='alternate' type='text/html' href='http://jupitermoonbeam.blogspot.com/2007/03/fluent-specification.html' title='Fluent Specification Part 1: Combining patterns'/><author><name>Peter Gillard-Moss</name><uri>http://www.blogger.com/profile/10275408277486693139</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_u7QiKCBQVE0/SMJysX5t1EI/AAAAAAAAAAM/tbEL9ITv9ts/S220/Political+012.jpg'/></author><thr:total>0</thr:total></entry></feed>
