<?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:blogger='http://schemas.google.com/blogger/2008' 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-516084884258004070</id><updated>2024-08-29T00:22:27.366+01:00</updated><category term="Agile"/><category term="C#"/><category term="LINQ"/><category term="BDD"/><category term="F#"/><category term="TDD"/><category term="Work Environment"/><category term=".Net 4.0"/><category term="Code Style"/><category term="Concurrency"/><category term="DDD"/><category term="Deep Earth"/><category term="Deep Zoom"/><category term="Dependency Injection"/><category term="Graph Theory"/><category term="IRepository"/><category term="IoC"/><category term="LINQ to SQL"/><category term="MEF"/><category term="NBehave"/><category term="PLINQ"/><category term="Parallel"/><category term="Silverlight"/><category term="Single Responsibility Pattern"/><category term="Spec#"/><category term="Unit of Work"/><category term="VS2010"/><category term="Virtual Earth"/><title type='text'>Stu&#39;s Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-7626910069021640135</id><published>2010-06-28T22:28:00.001+01:00</published><updated>2010-06-28T22:28:35.824+01:00</updated><title type='text'>New Blog</title><content type='html'>&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCIF-IbfYCPfXa75IPCvFmDUUbB8haFrSlVKe7hce9oCaCaUllFP4MkG-z36fW0lEsDeNQASQpHBhsqbm_zjT27rbiIw231sTPbMEcRiQloc5W0AdOE1kx4EHBN0InnLIdeA76BHq6iFE/s1600-h/logo%5B4%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; margin: 0px 0px 0px 10px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;logo&quot; border=&quot;0&quot; alt=&quot;logo&quot; align=&quot;right&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOVcIIRghSsC3WBuSMWvxagD_C6Icq2ZfqoyobnVIoaTVkTf6oDuFuIYnbyrowqXSm3O8v0GK4k-6hCSd_qzgwyJXqbjpM_L8UKIsL1JT5-RtFE6MG6yC2lawx8vnZKk_7Em4LC9pNeqc//?imgmax=800&quot; width=&quot;240&quot; height=&quot;41&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I’ve recently set up &lt;a href=&quot;http://red-badger.com/&quot;&gt;Red Badger Consulting&lt;/a&gt; with 2 highly esteemed colleagues and have been blogging on &lt;a href=&quot;http://red-badger.com/blog&quot;&gt;Red Badger’s blog&lt;/a&gt;, so come on over and take a look.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/7626910069021640135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2010/06/new-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/7626910069021640135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/7626910069021640135'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2010/06/new-blog.html' title='New Blog'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOVcIIRghSsC3WBuSMWvxagD_C6Icq2ZfqoyobnVIoaTVkTf6oDuFuIYnbyrowqXSm3O8v0GK4k-6hCSd_qzgwyJXqbjpM_L8UKIsL1JT5-RtFE6MG6yC2lawx8vnZKk_7Em4LC9pNeqc/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-8238186482717100474</id><published>2009-05-16T10:42:00.001+01:00</published><updated>2009-05-16T11:02:29.240+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 4.0"/><category scheme="http://www.blogger.com/atom/ns#" term="MEF"/><category scheme="http://www.blogger.com/atom/ns#" term="VS2010"/><title type='text'>Addicted to MEF</title><content type='html'>&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; height=&quot;224&quot; alt=&quot;blocks.png&quot; src=&quot;http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=MEF&amp;amp;DownloadId=42484&quot; width=&quot;181&quot; align=&quot;right&quot; /&gt;   &lt;p&gt;Be careful of &lt;a href=&quot;http://mef.codeplex.com/&quot;&gt;MEF&lt;/a&gt;.&amp;#160; It’s pure and potent.&amp;#160; Use it once and you’ll be hooked!&lt;/p&gt;  &lt;p&gt;I’m fashionably late to the party (I got distracted by XNA) because the &lt;a href=&quot;http://mef.codeplex.com/&quot;&gt;Managed Extensibility Framework&lt;/a&gt; (MEF) is already in Preview 5, but my god of a coding partner (&lt;a href=&quot;http://blogs.conchango.com/davidwynne/&quot;&gt;David Wynne&lt;/a&gt;) and I have recently been building apps using MEF.&amp;#160; It’s stunning – nothing short of a revolution (and a revelation) in application architecture.&lt;/p&gt;  &lt;p&gt;You could say that MEF is just IOC/DI on steroids, but it makes a leap that changes the way you build applications forever.&amp;#160; It’s probably as big a leap as Dependency Injection itself.&amp;#160; And it’s great that it’ll be part of .Net 4.0 so maybe there’s some hope that this is really the beginning of a great world-wide clean-up in the way we write applications.&lt;/p&gt;  &lt;p&gt;In the application we’re currently building we needed to simulate plugging electrical devices into a wall socket at home.&amp;#160; A kettle is dumb and just draws power from the house circuit and you can just buy one, plug it in and it works.&amp;#160; You don’t have to re-wire the house every time you plug a new appliance in. &lt;/p&gt;  &lt;p&gt;So it is with MEF.&amp;#160; We wrote a Kettle class and started the application and there it was!&amp;#160; The Kettle even provides its own UI so that we can switch it on and off.&amp;#160; Hardly rocket science I know, but the simple fact that the application doesn’t know anything about my kettle means that I can write a Television class in 2 seconds, start my app and it’ll be there – plugged in and complete with its own UI (this time the switch will need to include a stand-by mode).&lt;/p&gt;  &lt;p&gt;What’s more, if I put my Kettle and Television into a separate assembly I can just drop it into a directory that the app is watching and they will just appear in my app straight away.&amp;#160; I can switch them on and start using them immediately.&lt;/p&gt;  &lt;p&gt;That’s a plug-in architecture to die for.&amp;#160; And it couldn’t be easier to use.&lt;/p&gt;  &lt;p&gt;Back in 2000 I was blown away by how .Net itself blurred the boundaries between components and classes.&amp;#160; It made building components a doddle.&amp;#160; Prior to that you had to use COM and it was a complete nightmare.&amp;#160; Now, with MEF, building a component that quite literally just plugs into your app is easier than ever.&lt;/p&gt;  &lt;p&gt;They call it Dynamic Composition and it promotes the most loosely coupled architecture I’ve ever seen.&lt;/p&gt;  &lt;p&gt;Visual Studio 2010 should be fully WPF.&amp;#160; Unfortunately only the code editor has been built in WPF.&amp;#160; But the great thing is that it uses MEF.&amp;#160; So when it launches next year there will be an explosion of (hopefully) great productivity plug-ins simply because it’s now so easy to write them.&amp;#160; Imagine how cool it will be to drop the plug-in into the relevant directory and start using it in Visual Studio without even restarting it. Try doing that in Outlook 2003! &lt;/p&gt;  &lt;p&gt;That’s a revolution!&lt;/p&gt;  &lt;p&gt;So how is it done?&amp;#160; It’s as simple as annotating your classes and class members to indicate what constitutes the “Imports” and “Exports” that the Composable Part needs and provides.&amp;#160; A Catalog discovers these at runtime and works with the CompositionContainer which acts like a dating agency, matching the Imports and Exports together by their contract (internally a string, which usually represents the exchanged Type).&amp;#160; Optionally, you can provide metadata that can be used to finely tune the match-making process.&amp;#160; The result is a set of instantiated components that have all their Imports satisfied (if you implement IPartImportsSatisfiedNotification an event is raised when this happens).&amp;#160; You can ask the Container to re-Compose itself at any time.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://blogs.conchango.com/davidwynne/&quot;&gt;David’s blogging&lt;/a&gt; about how we used MEF to create a really simple, clean Model-View-ViewModel architecture for WPF applications that beats the traditional Dependency Injection / Service Locator pattern hands down.&amp;#160; Go to his &lt;a href=&quot;http://blogs.conchango.com/davidwynne/&quot;&gt;blog&lt;/a&gt; and see how nice it is. &lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/8238186482717100474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2009/05/addicted-to-mef.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/8238186482717100474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/8238186482717100474'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2009/05/addicted-to-mef.html' title='Addicted to MEF'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-3609037480204714384</id><published>2008-11-29T15:25:00.001+00:00</published><updated>2008-11-29T15:27:56.405+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="LINQ"/><title type='text'>Getting all functional</title><content type='html'>&lt;p align=&quot;left&quot;&gt;&lt;img title=&quot;clip_image001&quot; height=&quot;141&quot; alt=&quot;clip_image001&quot; hspace=&quot;12&quot; src=&quot;http://blogs.msdn.com/blogfiles/dan_fay/WindowsLiveWriter/FSeptCTPavailableandunitsofmeasurechecki_8E55/clip_image001_3.jpg&quot; width=&quot;196&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;Having done Biology at University rather than Computer Science, I regret having spent most of my career not really understanding why functional programming is so important.&amp;#160; I knew it was the oldest paradigm around, but assumed that it was just for mathematicians and scientists – business software needed something far better: imperative programming and object-orientation.&amp;#160; How naive was I?&lt;/p&gt;  &lt;p&gt;Firstly through JavaScript, and then through delegates, anonymous delegates and Lambda expressions in C#, I was gradually introduced to a new world where you can pass functions around as though they are data.&amp;#160; Now that C# has an elegant and concise syntax for Lambdas, I feel rude if I don’t use it as much as I can!&amp;#160; I got to like this approach so much that I was easily seduced by the even more elegant functional syntax of F#.&lt;/p&gt;  &lt;p&gt;F# has a really nice balance between the functional and the imperative, channelling you toward the former.&amp;#160; Whilst C# channels you toward the latter, it’s ever-increasing push towards being able to specify the “what” rather than having to manage the “how” has led it to embrace functional styles as well.&amp;#160; &lt;a href=&quot;http://en.wikipedia.org/wiki/Monad_(functional_programming)&quot;&gt;Monads&lt;/a&gt;, &lt;a href=&quot;http://research.microsoft.com/~emeijer/Papers/LINQ20.pdf&quot;&gt;for example&lt;/a&gt;, in LINQ.&lt;/p&gt;  &lt;p&gt;But why learn another language?&amp;#160; Certainly, if C# is getting all functional why bother with F#?&amp;#160; Surely there’s enough to keep up with besides learning a new language that might only come in useful every now and then.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Edward_Sapir&quot;&gt;Edward Sapir&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Benjamin_Whorf&quot;&gt;Benjamin Whorf&lt;/a&gt; &lt;a href=&quot;http://en.wikipedia.org/wiki/Sapir-Whorf_hypothesis&quot;&gt;hypothesised&lt;/a&gt; that we think only in the terms defined by our languages:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;We cut nature up, organize it into concepts, and ascribe significances as we do, largely because we are parties to an agreement to organize it in this way—an agreement that holds throughout our speech community and is codified in the patterns of our language [...] all observers are not led by the same physical evidence to the same picture of the universe, unless their linguistic backgrounds are similar, or can in some way be calibrated.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Several people including &lt;a href=&quot;http://en.wikipedia.org/wiki/Kenneth_E._Iverson&quot;&gt;Iverson&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Paul_Graham&quot;&gt;Graham&lt;/a&gt; have argued that this also applies to programming languages. Its difficult to understand how we can frame a computing problem except in the terms of the languages available to us.&amp;#160; I do know that learning Spanish helped &lt;em&gt;me&lt;/em&gt; think differently – and it certainly helped me understand English better.&amp;#160; I believe that learning F# helps you understand C# better – and between them they form a more complete framework for approaching software development.&amp;#160; Especially since they’re so interoperable.&lt;/p&gt;  &lt;p&gt;So even if its just an academic exercise – its worth it.&amp;#160; Let’s expand our minds!&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.amazon.co.uk/Foundations-F-Experts-Voice-Net/dp/1590597575/ref=sr_1_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1227969796&amp;amp;sr=8-2&quot;&gt;&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; alt=&quot;&quot; src=&quot;http://www.apress.com/resource/bookcover/9781590597576?size=medium&quot; align=&quot;left&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.amazon.co.uk/Expert-Hardback-Experts-Voice-Net/dp/1590598504/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1227969796&amp;amp;sr=8-1&quot;&gt;&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; alt=&quot;&quot; src=&quot;http://www.apress.com/resource/bookcover/9781590598504?size=medium&quot; align=&quot;left&quot; /&gt;&lt;/a&gt;We’ll leave a discussion about why functional programming is so good for a future post.&amp;#160; In the meantime, I can recommend both these books.&amp;#160; “Foundations” is more readable, and “Expert” more thorough (neither assume any previous F# knowledge).&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.amazon.co.uk/Foundations-F-Experts-Voice-Net/dp/1590597575/ref=sr_1_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1227969796&amp;amp;sr=8-2&quot;&gt;&amp;#160;&lt;/a&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/3609037480204714384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/11/getting-all-functional.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/3609037480204714384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/3609037480204714384'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/11/getting-all-functional.html' title='Getting all functional'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-8030327186812905889</id><published>2008-11-18T18:34:00.001+00:00</published><updated>2008-11-18T18:34:38.774+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Concurrency"/><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="LINQ"/><category scheme="http://www.blogger.com/atom/ns#" term="Parallel"/><category scheme="http://www.blogger.com/atom/ns#" term="PLINQ"/><title type='text'>The elephant in the room</title><content type='html'>&lt;p&gt;&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; title=&quot;There&amp;#39;s an elephant in the room&quot; alt=&quot;There&amp;#39;s an elephant in the room&quot; align=&quot;right&quot; src=&quot;http://strumpette.com/uploads/june06/elephant.jpg&quot; /&gt;There was lots of talk at Tech-Ed last week&amp;#160; about concurrency and parallel programming.&amp;#160; It’s becoming a real issue because we’re in the middle of a shift in the way &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Moore&#39;s_law&quot;&gt;Moore’s Law&lt;/a&gt; works for us.&amp;#160; Up until around 2002, we were getting a “free lunch” because processors were getting faster and more powerful and our software would just run faster without us having to do anything.&amp;#160; Recently, however, physical limits are being approached which slow down this effect.&amp;#160; Nowadays we increase processing power by adding more and more “cores”.&amp;#160; In order to take advantage of these, our programs must divide their workload into tasks that can be executed in parallel rather than sequentially.&lt;/p&gt;  &lt;p&gt;We’ve got a big problem on our hands, though, because writing concurrent programs is not easy, even for experts, and we, as mere software developers are not trained to do it well.&amp;#160; The closest that a lot of developers get is to manage the synchronisation of access to shared data by multiple threads in a web application.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib4hvwJeYtn9d3khjHc1wzyN2GT8NtQ0sqy1S02iJhXteVJsIiHVo2pM0tjN82qo36w3FXH4gtippJyUtYL2lK_CyJdjWnaDtTLwqx7-m2JfWmrUBQCHWIFtI2HrNruiEjqrT2Il6J7CA/s1600-h/64Core2TBTaskManager%5B5%5D.png&quot;&gt;&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; title=&quot;64 Core, 2 TB TaskManager&quot; alt=&quot;64 Core, 2 TB TaskManager&quot; align=&quot;left&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfvQP_WJ-ImPwRdkrO29tQryS1-vYUbJcgSj75vcFQ4Hmjbp20NZMbwkxvshQyOmHUfBtQvDdyUhAghXSwGF992cRcikw2-P0nzmuBG_DRsnFSr4mRy6UFexeQNMDa41lp8KcNPX6HbZM//?imgmax=800&quot; width=&quot;240&quot; height=&quot;191&quot; /&gt;&lt;/a&gt; This is a real screen shot of Windows Task Manager on a machine with 64 Cores and 2TB Memory.&amp;#160; I wouldn’t be surprised if we have entry level 8-core machines next year.&amp;#160; If we don’t do anything to take advantage of these extra cores, we may as well just have a single core machine.&lt;/p&gt;  &lt;p&gt;There have been thread synchronisation and asynchronous primitives in the .Net framework since the beginning, but using these correctly is notoriously difficult.&amp;#160; Having to work at such a low level means that you typically have to write a huge amount of code to get it working properly.&amp;#160; That code gets in the way of, and detracts from, what the program is really trying to do.&lt;/p&gt;  &lt;p&gt;Not anymore!&amp;#160; There is a whole range of new technologies upon us that are designed to help us write applications that can take advantage of multi-core and many-core platforms.&amp;#160; These include new parallel extensions for both managed and unmanaged code (although I won’t go into the unmanaged extensions), and a new language (F#) for the .Net Framework.&lt;/p&gt;  &lt;h4&gt;Parallel FX (PFX)&lt;/h4&gt;  &lt;p&gt;The first of these technologies is collectively known as &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Parallel_FX_Library&quot;&gt;Parallel FX&lt;/a&gt; (PFX) and is now on its 3rd CTP drop.&amp;#160; It’s deeply integrated into the .Net Framework 4.0 which is scheduled for release with Visual Studio 2010, and consists of Parallel LINQ (PLINQ) and the Task Parallel Library (TPL).&amp;#160; The latest CTP (including VS2010 and .Net 4.0) was released on 31st October and a VPC image of it can be downloaded &lt;a target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyId=922B4655-93D0-4476-BDA4-94CF5F8D4814&amp;amp;displaylang=en&quot;&gt;here&lt;/a&gt; (although it’s 7GB so you may want to check out &lt;a target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/briankel/archive/2007/09/06/a-more-reliable-and-faster-download-experience-for-rosario-vs08-vpc-s.aspx&quot;&gt;Brian Keller’s post&lt;/a&gt; for a suggestion on how to ease the pain!).&lt;/p&gt;  &lt;p&gt;This is all part of an initiative by Microsoft to allow developers to concentrate more on the “what” of software development than on the “how”.&amp;#160; It means that a developer should be able to declaratively specify &lt;em&gt;what&lt;/em&gt; needs to be done and not to worry too much about &lt;em&gt;how &lt;/em&gt;that actually happens.&amp;#160; LINQ was a great step in that direction and PLINQ takes it further by letting the framework know that a query can be run in parallel.&amp;#160; Before we talk about PLINQ, though, lets look at the TPL.&lt;/p&gt;  &lt;h4&gt;Task Parallel Library (TPL)&lt;/h4&gt;  &lt;p&gt;The basic unit of parallel execution in the TPL is the Task which can be constructed around a lambda. The static Parallel.For() and Parallel.ForEach() methods create a Task for each member of the source IEnumerable and distribute execution of these across the machine’s available processors using User Mode Scheduling.&amp;#160; Similarly, Parallel.Invoke() does the same for each of it’s lambda parameters.&lt;/p&gt;  &lt;p&gt;A new TaskManager class allows full control over how the Tasks are constructed, managed and scheduled for execution, with multiple instances sharing a single scheduler in an attempt to throttle over-subscription.&lt;/p&gt;  &lt;p&gt;The TPL helps developers write multi-threaded applications by providing assistance at every level.&amp;#160; For instance, LazyInit&amp;lt;T&amp;gt; helps you to manage the lazy initialisation of (potentially shared) data within your application.&lt;/p&gt;  &lt;p&gt;Additionally, a bunch of thread-safe collections (such as BlockingCollection&amp;lt;T&amp;gt;, ConcurrentDictionary&amp;lt;T&amp;gt;, ConcurrentQueue&amp;lt;T&amp;gt; and ConcurrentStack&amp;lt;T&amp;gt;) help with various parallelisation scenarios including multiple producer and consumer (parallel pipeline) paradigms.&lt;/p&gt;  &lt;p&gt;Finally, there’s an amazing debugger experience with all of this.&amp;#160; You can view (in a fancy WPF tool window) all of your Tasks and the route they take through your application.&amp;#160; Moving around Tasks is no longer a game of Thread hide-and-seek!&lt;/p&gt;  &lt;h4&gt;Parallel LINQ (PLINQ)&lt;/h4&gt;  &lt;p&gt;Setting up a query for parallel execution is easy – you just wrap the IEnumerable&amp;lt;T&amp;gt; in an IParallelEnumerable&amp;lt;T&amp;gt; by calling the AsParallel() extension method.&lt;/p&gt;  &lt;pre&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkS0hkJG9_wbP-gettgSg4rsuZ-p5VNSH3AvGlS5o7KPe-UnyTaLkwiMPlLvcTXOoi4z9rZHA7K3JJE0IVQxpFBITciYrJ1k0E4jphTxlzDbK1bleerRYT655yhve8HqtZsrdxmENGcts/s1600-h/AsParallelExtensionMethod%5B4%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;AsParallelExtensionMethod&quot; border=&quot;0&quot; alt=&quot;AsParallelExtensionMethod&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ3JCJJjGsZMVTJhlsGHtcdBESx6C9ulotfcdkPgfC-Poa0x6vBHrFzGas_ROznhcg3Tv4CVMTegRFH5sT-4a9mIjPDDXKxxCKR0iRwR68SE7bEhmIwzd4zgGNcI2JPsSrxmOkHmdnkXA//?imgmax=800&quot; width=&quot;733&quot; height=&quot;122&quot; /&gt;&lt;/a&gt; &lt;/pre&gt;

&lt;p&gt;In the latest CTP the overloads of AsParallel() have changed slightly making it even simpler to use.&amp;#160; In the example above I’ve specified a degree of parallelism indicating that I want the query to execute over 2 processors, but you can leave that up to the underlying implementation by not specifying any parameters.&lt;/p&gt;

&lt;p&gt;The ForAll() extension method, shown above, allows you to specify a (thread-safe) lambda that is also executed in parallel – allowing for pipelined parallelism in both the running of the query and the processing of the results. &lt;/p&gt;

&lt;p&gt;Running the example above produces the output below.&amp;#160; Although it’s running on a single proc VPC, you can still see that it’s using 2 threads (hash codes 1 &amp;amp; 3).&amp;#160; What’s interesting is that each item is both selected and enumerated on the same thread – this is really going to help performance by reducing the amount of cross thread traffic.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGg_xce5IX37PAVeBMVC-0URpMTn4xnT8stxI11iUWrJyUFycVQ2tAW1oBDf0X2wtUUrykQI5A43PXhX5FnhqUTOvwCrlCHWjAFLB88blhaBMPYQVgBAX_98uRe2vebeC-lsr023EoldM/s1600-h/AsParallelOuput%5B4%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto&quot; title=&quot;AsParallelOuput&quot; border=&quot;0&quot; alt=&quot;AsParallelOuput&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUrqLytqmOs8hUU0ZJLNF9FJgyePM9bjNI_7J_cHdQBlFFG7pno_NmdbDv9GMZfXgzJSIap9arJTjUsBvllzYL_eAter32liYXNBMzCn90vZQEiLRzj6VjzGreOMhb0t33BmqYTjkDKno//?imgmax=800&quot; width=&quot;297&quot; height=&quot;265&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exception handling in the latest CTP is also slightly different from earlier releases.&amp;#160; Tasks have a Status property which indicates how the task completed (or if it was cancelled) and potentially holds an exception that may have been thrown from the Task’s lambda.&amp;#160; Any unhandled &lt;em&gt;and &lt;/em&gt;unobserved exceptions will get marshalled off the thread before garbage collection and are allowed to propagate up the stack.&lt;/p&gt;

&lt;p&gt;Daniel Moth did an excellent presentation on PFX at Tech-Ed which you can watch &lt;a target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/emea/teched2008/developer/tv/default.aspx?vid=63 &quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;F#&lt;/h4&gt;

&lt;p&gt;So what about &lt;a target=&quot;_blank&quot; href=&quot;http://msdn.microsoft.com/en-gb/fsharp/default.aspx&quot;&gt;F#&lt;/a&gt; then?&amp;#160; Well, it’s a multi-paradigm language that has roots in &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/ML_(programming_language)&quot;&gt;ML&lt;/a&gt; (it’s &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Objective_Caml&quot;&gt;oCAML&lt;/a&gt; compatible if you omit the #light directive).&amp;#160; So it’s very definitely a first-class Functional language – but it also has Type semantics allowing it to integrate fully with the .Net Framework.&amp;#160; If C# is imperative with some functional thrown in, then F# is functional with some imperative thrown in (both languages can exhibit Object Orientation).&lt;/p&gt;

&lt;p&gt;Data and functions are equivalent and can be passed around by value.&amp;#160; This, coupled with immutability by default, means that side-effect free functions can be easily composed together in both synchronous and asynchronous fashion and executed in parallel with impunity.&amp;#160; All-in-all this makes it very powerful for addressing some of the modern concurrent programming problems.&amp;#160; It’s not for every problem that’s for sure – C# is often a better choice – but the fact that it can be called seamlessly from any .Net language makes it easy to write an F# library for some specialised tasks.&lt;/p&gt;

&lt;p&gt;Luke Hoban and Bart de Smet did some great talks at Tech-Ed on parallel programming using F#, and it blew me away how appropriate F# is for problems like these.&amp;#160; I’m really getting into the whole F# thing so I’ll save it for another post next week.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/8030327186812905889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/11/elephant-in-room.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/8030327186812905889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/8030327186812905889'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/11/elephant-in-room.html' title='The elephant in the room'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfvQP_WJ-ImPwRdkrO29tQryS1-vYUbJcgSj75vcFQ4Hmjbp20NZMbwkxvshQyOmHUfBtQvDdyUhAghXSwGF992cRcikw2-P0nzmuBG_DRsnFSr4mRy6UFexeQNMDa41lp8KcNPX6HbZM/s72-c/?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-1787009803790769115</id><published>2008-10-02T11:34:00.001+01:00</published><updated>2008-11-16T08:10:20.329+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Deep Earth"/><category scheme="http://www.blogger.com/atom/ns#" term="Deep Zoom"/><category scheme="http://www.blogger.com/atom/ns#" term="Graph Theory"/><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight"/><category scheme="http://www.blogger.com/atom/ns#" term="Virtual Earth"/><title type='text'>National Rail Enquiries / Microsoft PoC (Part 1)</title><content type='html'>&lt;p&gt;&lt;font color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;Updated (20/10/08)– removed IP addresses and other minor edits&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Wow - great fun!&amp;#160; I was dev lead on a Proof-of-Concept project for &lt;a target=&quot;_blank&quot; href=&quot;http://nationalrail.co.uk&quot;&gt;National Rail Enquiries&lt;/a&gt; (NRE) at the &lt;a target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/mtc/locations/ThamesValley.mspx&quot;&gt;Microsoft Technology Centre&lt;/a&gt; (MTC) in Reading.&amp;#160; Jason Webb (NRE) and I demonstrated it yesterday at a &lt;a target=&quot;_blank&quot; href=&quot;http://msevents.microsoft.com/cui/EventDetail.aspx?culture=en-GB&amp;amp;EventID=1032386599&quot;&gt;Microsoft TechNet event&lt;/a&gt; (I’ll post the webcast link when it’s available – &lt;font color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;Update: you can watch the presentation at &lt;/font&gt;&lt;a title=&quot;http://technet.microsoft.com/en-gb/bb945096.aspx?id=396&quot; href=&quot;http://technet.microsoft.com/en-gb/bb945096.aspx?id=396&quot;&gt;&lt;font color=&quot;#ff0000&quot; size=&quot;1&quot;&gt;http://technet.microsoft.com/en-gb/bb945096.aspx?id=396&lt;/font&gt;&lt;/a&gt;&lt;font color=&quot;#ff0000&quot; size=&quot;1&quot;&gt; – then click the link “National Rail Enquires” beneath the video&lt;/font&gt;) so it’s not confidential.&amp;#160; 700 attendees (including Steve Ballmer – although he’d left before we were on) – there was no pressure!&lt;/p&gt;  &lt;p&gt;At the MTC it was cool to work with a strong, focused team in such a productive environment.&amp;#160; I decided to do a series of posts on what I found interesting about the experience.&amp;#160; In this post I’ll give a short overview of the PoC’s output, with links to some screen captures.&amp;#160; Then I’ll dive into some detail about how we used &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Graph_theory&quot;&gt;graph theory&lt;/a&gt; to pull together some meaningful data.&lt;/p&gt;  &lt;p&gt;In just 3 weeks we delivered 5 pieces: &lt;/p&gt;  &lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot;&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign=&quot;top&quot;&gt;&lt;a href=&quot;http://lh4.ggpht.com/stuartharris4/SOSjYguhldI/AAAAAAAAAGk/c6b0B-6UUVU/s1600-h/image31.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px&quot; title=&quot;Departures and Arrivals&quot; border=&quot;0&quot; alt=&quot;Departures and Arrivals&quot; align=&quot;right&quot; src=&quot;http://lh6.ggpht.com/stuartharris4/SOSjZG4xGBI/AAAAAAAAAGo/EtKX8BS2dF0/image3_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;234&quot; /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;         &lt;p align=&quot;justify&quot;&gt;1. A &lt;a target=&quot;_blank&quot; href=&quot;http://Silverlight.net&quot;&gt;Silverlight&lt;/a&gt; 2.0 (beta 2) web-site app for viewing Live Train Departures and Arrivals, using Silverlight Deep Zoom, &lt;a target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/VIRTUALEARTH/&quot;&gt;Virtual Earth&lt;/a&gt;, and &lt;a target=&quot;_blank&quot; href=&quot;http://www.codeplex.com/deepearth&quot;&gt;Deep Earth&lt;/a&gt;.             &lt;br /&gt;(You can zoom in and see trains moving on tracks, click a train for live train journey information or click a station for arrivals and departures.             &lt;br /&gt;You can also see disruptions and late running trains.)&lt;/p&gt;       &lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;&lt;a href=&quot;http://lh5.ggpht.com/stuartharris4/SOSjbLwMGxI/AAAAAAAAAGs/gh9BbgboVn0/s1600-h/image13.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px&quot; title=&quot;Train details popup&quot; border=&quot;0&quot; alt=&quot;Train details popup&quot; align=&quot;left&quot; src=&quot;http://lh4.ggpht.com/stuartharris4/SOSjbtvtewI/AAAAAAAAAGw/mu6Zb5qmwt8/image_thumb7.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;193&quot; /&gt;&lt;/a&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign=&quot;top&quot;&gt;&lt;a href=&quot;http://lh3.ggpht.com/stuartharris4/SPxI_xir1AI/AAAAAAAAAHo/Db9zUnPgiZQ/s1600-h/NRE-Incidents%5B5%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;NRE-Incidents&quot; border=&quot;0&quot; alt=&quot;NRE-Incidents&quot; src=&quot;http://lh4.ggpht.com/stuartharris4/SPxJAnn5xOI/AAAAAAAAAHs/XdF6jhk8ODQ/NRE-Incidents_thumb%5B1%5D.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;207&quot; /&gt;&lt;/a&gt; &lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;         &lt;p align=&quot;justify&quot;&gt;2. A variant of the above showing live Incidents and Disruptions - basically a concept application for rail staff.&amp;#160; You can also see engineering works.&lt;/p&gt;          &lt;p align=&quot;justify&quot;&gt;3. A Kiosk application that rotates around current incidents zooming in to show the location of the disruption. It also shows high-level rail network overview and performance statistics.            &lt;br /&gt;&amp;#160;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;&lt;a href=&quot;http://lh5.ggpht.com/stuartharris4/SPxJBAikHjI/AAAAAAAAAHw/LA8PUSs9LcU/s1600-h/NRE-Kiosk1%5B2%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;NRE-Kiosk1&quot; border=&quot;0&quot; alt=&quot;NRE-Kiosk1&quot; src=&quot;http://lh4.ggpht.com/stuartharris4/SPxJB5ykP6I/AAAAAAAAAH0/60EbpjYi-XQ/NRE-Kiosk1_thumb.png?imgmax=800&quot; width=&quot;204&quot; height=&quot;244&quot; /&gt;&lt;/a&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign=&quot;top&quot;&gt;&lt;a href=&quot;http://lh3.ggpht.com/stuartharris4/SOSjo6vLbxI/AAAAAAAAAH4/-2CtkJteCIU/s1600-h/image192.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px&quot; title=&quot;Outlook plugin&quot; border=&quot;0&quot; alt=&quot;Outlook plugin&quot; align=&quot;right&quot; src=&quot;http://lh3.ggpht.com/stuartharris4/SOSjqERyD3I/AAAAAAAAAHQ/4p8eNtuTr5I/image19_thumb1.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;233&quot; /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;         &lt;p align=&quot;justify&quot;&gt;4. A Microsoft Office Outlook plug-in that helps you plan a journey for the selected calendar appointment.            &lt;br /&gt;You can choose an outgoing and a returning train and it will mark out time in your calendar for the journeys.&lt;/p&gt;          &lt;p align=&quot;justify&quot;&gt;5. And finally, a Windows Smart Phone application (see screen capture below) that shows live arrivals and departures for the selected leg of a journey. &lt;/p&gt;       &lt;/td&gt;        &lt;td valign=&quot;top&quot; width=&quot;266&quot;&gt;&lt;a href=&quot;http://lh3.ggpht.com/stuartharris4/SPxJDJM2eRI/AAAAAAAAAH8/hmuENI4yg3g/s1600-h/NRE-Kiosk2%5B2%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;NRE-Kiosk2&quot; border=&quot;0&quot; alt=&quot;NRE-Kiosk2&quot; src=&quot;http://lh4.ggpht.com/stuartharris4/SPxJDmINifI/AAAAAAAAAIA/aGax0tmGWlM/NRE-Kiosk2_thumb.png?imgmax=800&quot; width=&quot;232&quot; height=&quot;244&quot; /&gt;&lt;/a&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p align=&quot;left&quot;&gt;View &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Camtasia_Studio&quot;&gt;Camtasia&lt;/a&gt; screen captures:&lt;/p&gt;  &lt;p&gt;&lt;iframe style=&quot;border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px&quot; marginheight=&quot;0&quot; src=&quot;http://cid-876e01e637f9afd1.skydrive.live.com/embedrowdetail.aspx/Public/Outlook.wmv&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;The outlook piece.&lt;/p&gt;  &lt;p&gt;&lt;iframe style=&quot;border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px&quot; marginheight=&quot;0&quot; src=&quot;http://cid-876e01e637f9afd1.skydrive.live.com/embedrowdetail.aspx/Public/Departure%20Boards.wmv&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;This is the Silverlight 2.0 web page app. (starts 00:30 seconds in)&lt;/p&gt;  &lt;p&gt;&lt;iframe style=&quot;border-bottom: #dde5e9 1px solid; border-left: #dde5e9 1px solid; padding-bottom: 0px; background-color: #ffffff; margin: 3px; padding-left: 0px; width: 240px; padding-right: 0px; height: 66px; border-top: #dde5e9 1px solid; border-right: #dde5e9 1px solid; padding-top: 0px&quot; marginheight=&quot;0&quot; src=&quot;http://cid-876e01e637f9afd1.skydrive.live.com/embedrowdetail.aspx/Public/Mobile.wmv&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;This is the Windows Smart Phone application.&lt;/p&gt;  &lt;p align=&quot;left&quot;&gt;It&#39;s amazing what a great team can do in such a short time using today&#39;s extremely productive development tools!&lt;/p&gt;  &lt;p&gt;So (every sentence at Microsoft starts with “So”) the team consisted of contingents from:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://Conchango.com&quot;&gt;Conchango&lt;/a&gt;: A user experience consultant (Tony Ward), a couple of great designers (Felix Corke and Hiia Immonen), a couple of C#/Silverlight developers (myself and David Wynne) and a data expert (Steve Wright); &lt;/li&gt;    &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://microsoft.com&quot;&gt;Microsoft&lt;/a&gt;: Project Manager (Andy Milligan), and Architect (Mark Bloodworth) and developers (Rob &amp;amp; Alex); &lt;/li&gt;    &lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://nationalrail.co.uk&quot;&gt;National Rail Enquiries&lt;/a&gt; (including Ra Wilson).&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Eleven of us in total, some for the full 3 weeks and some for less.&lt;/p&gt;  &lt;p&gt;We faced some big challenges.&amp;#160; One of the more significant of which was obtaining good data to play with.&amp;#160; We wanted geographic data for the UK rail network.&amp;#160; We already had the latitude and longitude of each station and some coordinates for tracks, but didn’t know how the stations connected up!&amp;#160; Also the track data was really just a collection of short lines, each of which passed through a handful of coordinates.&amp;#160; There was no routing information or relationship with any of the stations!&amp;#160; So we had to imbue the data with some meaning.&lt;/p&gt;  &lt;p&gt;&lt;img style=&quot;display: inline; margin-left: 0px; margin-right: 0px&quot; alt=&quot;quickgraph.banner.png&quot; align=&quot;left&quot; src=&quot;http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=quickgraph&amp;amp;DownloadId=10930&quot; /&gt;Enter &lt;a target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Graph_theory&quot;&gt;Graph Theory&lt;/a&gt;.&amp;#160; It was straightforward to load all the little lines from the KML file into a graph using Jonathan &#39;Peli&#39; de Halleux’s great library for C# called &lt;a target=&quot;_blank&quot; href=&quot;http://www.codeplex.com/quickgraph&quot;&gt;QuickGraph&lt;/a&gt;.&amp;#160; Each coordinate became a vertex in the graph and the KML showed us, roughly, where the edges were.&amp;#160; It didn’t work perfectly as there was no routing information – no data about what constitutes legal train movements.&amp;#160; Also the data wasn’t particularly accurate so our graph ended up with little gaps where the vertices didn’t quite line up.&amp;#160; But it was easy to find the closest of the 90,000 vertices to each of the 2,500 stations using WPF Points and Vectors:&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;&lt;font size=&quot;1&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;private &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;GetCloserVertex(&lt;span style=&quot;color: #2b91af&quot;&gt;Station &lt;/span&gt;station, &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;vertex1, &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;vertex2)
{
    &lt;span style=&quot;color: #2b91af&quot;&gt;Vector &lt;/span&gt;vector1 = station.Location - vertex1.Point;
    &lt;span style=&quot;color: #2b91af&quot;&gt;Vector &lt;/span&gt;vector2 = station.Location - vertex2.Point;
    &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;vector1.Length &amp;lt; vector2.Length ? vertex1 : vertex2;
}&lt;/font&gt;&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/stuartharris4/SOSjxiRDx4I/AAAAAAAAAHg/K_yBGnqcC0A/s1600-h/image30.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; align=&quot;right&quot; src=&quot;http://lh5.ggpht.com/stuartharris4/SOSjxyCJKnI/AAAAAAAAAHk/IN1h93ac528/image_thumb16.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;176&quot; /&gt;&lt;/a&gt;We had some timetable data that we used to extrapolate train routes and validate legal edges in our graph.&amp;#160; One problem is trying to determine what constitutes a valid train move.&amp;#160; In the diagram on the right it’s obvious to a human that whilst you can go from A to B and A to C you can’t go from B to C without changing trains.&amp;#160; The graph however, doesn’t know anything about walking across to another platform to catch a different train!&lt;/p&gt;

&lt;p&gt;Once we’d validated all the edges in the graph we could do all sorts of clever things like running algorithms to calculate the shortest route between any 2 stations!&amp;#160; But the first thing we needed to do was validate the track “segments”.&amp;#160; This was relatively straight forward using Peli’s excellent library, although there isn’t much documentation or many examples out there so I’ve attached a code snippet… &lt;/p&gt;

&lt;p&gt;In the snippet we find each station’s nearest neighbour stations so that we can create track segments between them and exclude those that don’t correspond to legal train moves (from the timetable):&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;font size=&quot;1&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;private void &lt;/span&gt;CreateFinalGraph()
{
    &lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt; vertices = _graph.Vertices.Where(v =&amp;gt; v.Station != &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;);
    &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;vertex &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;vertices)
    {
        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;neighbours = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt;&amp;gt;();
        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;algorithm = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DijkstraShortestPathAlgorithm&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt;(_graph, edge =&amp;gt; 1);
        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;predecessors = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt;();
        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;observer = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;VertexPredecessorRecorderObserver&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt;(predecessors);
        &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;vertex1 = vertex;
        algorithm.DiscoverVertex
            += (sender, e) =&amp;gt;
                   {
                       &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(e.Vertex.Station == &lt;span style=&quot;color: blue&quot;&gt;null &lt;/span&gt;|| e.Vertex.Station == vertex1.Station)
                           &lt;span style=&quot;color: blue&quot;&gt;return&lt;/span&gt;;
                       neighbours.Add(e.Vertex, GetEdges(vertex1, e.Vertex, predecessors));
                       &lt;/font&gt;&lt;font size=&quot;1&quot;&gt;&lt;span style=&quot;color: green&quot;&gt;// found a neighbour so stop traversal beyond it
                       &lt;/span&gt;&lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;edge &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;_graph.OutEdges(e.Vertex))
                       {
                           &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(edge.Target != vertex1)
                               algorithm.VertexColors[edge.Target] = &lt;span style=&quot;color: #2b91af&quot;&gt;GraphColor&lt;/span&gt;.Black;
                       }
                   };
        &lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;ObserverScope&lt;/span&gt;.Create(algorithm, observer))
            algorithm.Compute(vertex);
        &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;neighbour &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;neighbours)
        {
            &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;segment = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Segment&lt;/span&gt;(vertex.Station, neighbour.Key.Station,
                                      GetPoints(neighbour.Value));
            &lt;span style=&quot;color: blue&quot;&gt;bool &lt;/span&gt;isLegal = !vertex.Station.IsMissing &amp;amp;&amp;amp;
                           &lt;span style=&quot;color: #2b91af&quot;&gt;SegmentLoader&lt;/span&gt;.ValidSegments[vertex.Station.Crs]
                               .Contains(neighbour.Key.Station.Crs);
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(isLegal)
                _finalGraph.AddVerticesAndEdge(segment);
        }
    }
}

&lt;span style=&quot;color: blue&quot;&gt;private static &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Point&lt;/span&gt;[] GetPoints(&lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt; edges)
{
    &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;points = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Point&lt;/span&gt;&amp;gt;();
    &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;edge &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;edges)
    {
        &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(points.Count == 0)
            points.Add(edge.Source.Point);
        points.Add(edge.Target.Point);
    }
    &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;points.ToArray();
}&lt;/font&gt;&lt;/pre&gt;

&lt;pre class=&quot;code&quot;&gt;&lt;font size=&quot;1&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;private static &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt; GetEdges(
    &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;from,
    &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;to,
    &lt;span style=&quot;color: #2b91af&quot;&gt;IDictionary&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt; predecessors)
{
    &lt;span style=&quot;color: #2b91af&quot;&gt;Vertex &lt;/span&gt;current = to;
    &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;edges = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt;&amp;gt;();
    &lt;span style=&quot;color: blue&quot;&gt;while &lt;/span&gt;(current != from &amp;amp;&amp;amp; predecessors.ContainsKey(current))
    {
        &lt;span style=&quot;color: #2b91af&quot;&gt;Edge&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Vertex&lt;/span&gt;&amp;gt; predecessor = predecessors[current];
        edges.Add(predecessor);
        current = predecessor.Source;
    }
    edges.Reverse();
    &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;edges;
}&lt;/font&gt;&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;p&gt;First we iterated around all the vertices (coordinates) in the graph that have a station associated with them and walked along the edges until we found another vertex with a station attached.&amp;#160; That’s a neighbouring station so we can stop the algorithm traversing further in that direction by colouring all the successive vertices black (marks them as finished).&lt;/p&gt;

&lt;p&gt;We attached an observer that records the predecessor edge for each vertex as we’re moving through the graph.&amp;#160; Because we’re using a shortest path algorithm, each vertex has a leading edge that forms the last leg of the shortest path to that vertex.&amp;#160; These predecessors are stored in the dictionary and are used to build a list of edges for each segment.&amp;#160; Although we’re creating 2,500 graphs, QuickGraph algorithms run extremely fast and the whole thing is over in seconds.&lt;/p&gt;

&lt;p&gt;Finally we check that the segment is valid against the timetable and store it in the database.&amp;#160; The database is SQL Server 2008 and we’re storing all the coordinates as geo-spatial data using the new native GEOGRAPHY data type.&amp;#160; This allows us to query, for example, all stations within a specified bounding area. &lt;/p&gt;

&lt;p&gt;In the next posts I’ll cover some of the detail around the back-end and the Silverlight front-end, sharing some experiences with Deep Zoom and Deep Earth.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/1787009803790769115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/10/national-rail-enquiries-microsoft-poc.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1787009803790769115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1787009803790769115'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/10/national-rail-enquiries-microsoft-poc.html' title='National Rail Enquiries / Microsoft PoC (Part 1)'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/stuartharris4/SOSjZG4xGBI/AAAAAAAAAGo/EtKX8BS2dF0/s72-c/image3_thumb.png?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-4022284059011582704</id><published>2008-08-07T12:49:00.001+01:00</published><updated>2008-08-26T20:16:51.778+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="BDD"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Work Environment"/><title type='text'>Early and continuous feedback - ftw</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/stuartharris4/SJrhLQ7KmFI/AAAAAAAAAGM/xdLHOjzQHMU/s1600-h/feedback-779099%5B7%5D.jpg&quot;&gt;&lt;img title=&quot;Feedback&quot; style=&quot;border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;228&quot; alt=&quot;Feedback&quot; src=&quot;http://lh3.ggpht.com/stuartharris4/SJrhLrwOG-I/AAAAAAAAAGQ/xqIDS58Ix-E/feedback-779099_thumb%5B5%5D.jpg?imgmax=800&quot; width=&quot;324&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; We&amp;#8217;re having a beautiful summer here in London.&amp;#160; &lt;font color=&quot;#ff0000&quot;&gt;(Update: Typical!&amp;#160; That jinxed it!&amp;#160; Sorry.)&lt;/font&gt; It seemed like I would have been wasting it to rush back to work.&amp;#160; But feet get itchy.&amp;#160; So I&amp;#8217;m very excited to be starting at &lt;a href=&quot;http://conchango.com&quot; target=&quot;_blank&quot;&gt;Conchango&lt;/a&gt; on Monday as a Senior Technical Consultant.&amp;#160; I&amp;#8217;ve known about Conchango for a while and theirs was the first name that came to me when I was thinking about who I&amp;#8217;d like to work with.&amp;#160; Agile, modern, pragmatic, talented people etc.&amp;#160; &lt;/p&gt;  &lt;p&gt;One thing that&amp;#8217;s really impressed me is the feedback that I&amp;#8217;ve been getting during the recruitment process (thanks &lt;a href=&quot;http://blogs.conchango.com/michelleflynn/default.aspx&quot;&gt;Michelle&lt;/a&gt;).&amp;#160; At both interviews I was given immediate feedback (including from a technical test).&amp;#160; That&amp;#8217;s something that&amp;#8217;s never happened to me before!&amp;#160; I&amp;#8217;ve probably only been for a dozen interviews in my career but I&amp;#8217;ve interviewed lots more candidates.&amp;#160; Always the feedback has been something that happens after the event &amp;#8211; I&amp;#8217;ve been as guilty of it myself. Usually over the phone or in an email a few days later. But &lt;strong&gt;early&lt;/strong&gt; feedback is very important.&amp;#160; It makes everything clear, transparent, honest.&amp;#160; It prevents time being wasted and gets things moving much quicker.&lt;/p&gt;  &lt;p&gt;In Agile we &lt;em&gt;depend&lt;/em&gt; on early feedback.&amp;#160; We can&amp;#8217;t work without it.&amp;#160; The whole thing breaks down if the customer is not available to let us know what&amp;#8217;s good and bad about what we&amp;#8217;re doing.&amp;#160; It helps prevent us making speculative assumptions and wasting our time.&amp;#160; &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot; target=&quot;_blank&quot;&gt;Test-Driven Development&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior_driven_development&quot; target=&quot;_blank&quot;&gt;Behaviour-Driven Development&lt;/a&gt; give us early feedback &amp;#8211; green lights everywhere for that nice fuzzy feeling.&amp;#160; Make it &lt;strong&gt;fail &lt;/strong&gt;--&amp;gt; Make it &lt;strong&gt;pass &lt;/strong&gt;--&amp;gt; Make it &lt;strong&gt;right &lt;/strong&gt;--&amp;gt; Feel good.&amp;#160; Feedback makes us feel good.&amp;#160; Early feedback makes us feel good sooner.&lt;/p&gt;  &lt;p&gt;At &lt;a href=&quot;http://www.tfl.gov.uk&quot;&gt;London Underground&lt;/a&gt; we used a product from &lt;a href=&quot;http://jetbrains.com&quot;&gt;JetBrains&lt;/a&gt; called &lt;a href=&quot;http://www.jetbrains.com/teamcity/index.html&quot;&gt;TeamCity&lt;/a&gt; for &lt;a href=&quot;http://www.martinfowler.com/articles/continuousIntegration.html&quot;&gt;Continuous Integration&lt;/a&gt; (CI).&amp;#160; A lot of people use &lt;a href=&quot;http://cruisecontrol.sourceforge.net/&quot;&gt;CruiseControl&lt;/a&gt;.&amp;#160; I found TeamCity easier to set up (it has loads of features and the professional edition is free).&amp;#160; Whatever tool we use, the reason we do CI is to give us early feedback &amp;#8211; we know immediately when the build is broken or the tests start failing.&amp;#160; Why?&amp;#160; So that we can fix it straight away.&amp;#160; That keeps the team working and the software quality high.&lt;/p&gt;  &lt;p&gt;All these feedback mechanisms help prevent us from introducing bugs (or going off on tangents) &amp;#8211; or at least they help us catch problems early &amp;#8211; and we know how quickly the cost of fixing stuff rises the longer it takes to discover it.&amp;#160; The feedback helps us get it right.&amp;#160; Everyone wins.&lt;/p&gt;  &lt;p&gt;Feedback should be something we do &lt;strong&gt;all&lt;/strong&gt; the time.&amp;#160; In every conversation we ever have.&amp;#160; I know one thing - I&amp;#8217;ll never interview anyone ever again without giving them honest and immediate feedback at every stage.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/4022284059011582704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/08/early-and-continuous-feedback-ftw.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/4022284059011582704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/4022284059011582704'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/08/early-and-continuous-feedback-ftw.html' title='Early and continuous feedback - ftw'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/stuartharris4/SJrhLrwOG-I/AAAAAAAAAGQ/xqIDS58Ix-E/s72-c/feedback-779099_thumb%5B5%5D.jpg?imgmax=800" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-1056065775966280693</id><published>2008-07-22T13:32:00.001+01:00</published><updated>2008-07-22T14:00:57.215+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="BDD"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><category scheme="http://www.blogger.com/atom/ns#" term="NBehave"/><category scheme="http://www.blogger.com/atom/ns#" term="Spec#"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><title type='text'>The Language of Behavior</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/stuartharris4/SIXTWdX1qNI/AAAAAAAAAEY/3OzqXDSiXb4/s1600-h/image%5B24%5D.png&quot;&gt;&lt;img title=&quot;Software quality is directly proportional to the quality of communication that takes place between the business and the developers&quot; style=&quot;border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;184&quot; alt=&quot;Software quality is directly proportional to the quality of communication that takes place between the business and the developers&quot; src=&quot;http://lh3.ggpht.com/stuartharris4/SIXTXspre4I/AAAAAAAAAEc/g9LZQHKmLi8/image_thumb%5B10%5D.png?imgmax=800&quot; width=&quot;244&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; My mother researched our genealogy back several centuries and I’m just about as English as they come – so I decided to spell “Behavior” &lt;em&gt;without&lt;/em&gt; a “u”.&amp;#160; That’s the correct way to spell it – at least it was before we changed it to please the French!&amp;#160; Plus it Googles better.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Why is this important?&amp;#160; Well, the spelling’s not.&amp;#160; But the &lt;em&gt;language&lt;/em&gt; of behavior is.&amp;#160; Eric Evans in his book “&lt;a href=&quot;http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1216731588&amp;amp;sr=8-1&quot; target=&quot;_blank&quot;&gt;Domain-Driven Design&lt;/a&gt;” coined the term “ubiquitous language” meaning that the domain model should form a language which means as much to the business as it does to the software developer.&amp;#160; &lt;strong&gt;Software quality is directly proportional to the quality of communication that takes place between the business and the developers&lt;/strong&gt; – and speaking the same language is essential.&amp;#160; How the software &lt;em&gt;behaves&lt;/em&gt; should be described in terms that have meaning to everyone.&lt;/p&gt;  &lt;p&gt;Enter “&lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior_driven_development&quot; target=&quot;_blank&quot;&gt;Behaviour-Driven Development&lt;/a&gt;” (BDD) which takes “&lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot; target=&quot;_blank&quot;&gt;Test-Driven Development&lt;/a&gt;” (TDD) to the next level using the language from the “&lt;a href=&quot;http://en.wikipedia.org/wiki/Domain_driven_design&quot; target=&quot;_blank&quot;&gt;Domain-Driven Design&lt;/a&gt;” (DDD).&amp;#160; It’s the holy grail.&amp;#160; To be able to describe what an application is required to do, in the ubiquitous language of the domain, but in an executable format.&lt;/p&gt;  &lt;p&gt;Developers hate testing.&amp;#160; They even hate the &lt;em&gt;word&lt;/em&gt; “Test”.&amp;#160; Loads of developers just don’t get TDD. It’s because the language is wrong.&amp;#160; Take the T-word out of the equation and it suddenly makes more sense.&amp;#160; Replace it with the S-word.&amp;#160; Specification.&amp;#160; We’re going to specify what the application is going to do (using the vocabulary) in an executable format that will let us know when the specified behavior is broken.&amp;#160; Suddenly it all makes sense.&lt;/p&gt;  &lt;p&gt;So in BDD we have the user story expressed in the following way:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;As a &lt;/strong&gt;&lt;em&gt;&amp;lt;role&amp;gt;&lt;/em&gt;       &lt;br /&gt;&lt;strong&gt;I want &lt;/strong&gt;&lt;em&gt;&amp;lt;to do something&amp;gt;&lt;/em&gt;       &lt;br /&gt;&lt;strong&gt;So that &lt;/strong&gt;&lt;em&gt;&amp;lt;it benefits the business in this way&amp;gt;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Then the story can feed the specification using Scenarios:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;With &lt;/strong&gt;&lt;em&gt;&amp;lt;this Scenario&amp;gt;:&lt;/em&gt;       &lt;br /&gt;&lt;strong&gt;Given&lt;/strong&gt; &lt;em&gt;&amp;lt;these preconditions&amp;gt;&lt;/em&gt;       &lt;br /&gt;&lt;strong&gt;When&lt;/strong&gt; &lt;em&gt;&amp;lt;the behavior is exercised&amp;gt;&lt;/em&gt;       &lt;br /&gt;&lt;strong&gt;Then&lt;/strong&gt; &lt;em&gt;&amp;lt;these post-conditions are valid&amp;gt;&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Which is effectively the &lt;a href=&quot;http://weblogs.java.net/blog/wwake/archive/2003/12/&quot; target=&quot;_blank&quot;&gt;Arrange, Act and Assert (3-A’s) pattern&lt;/a&gt; ( Given == Arrange, When == Act, Then == Assert) for writing &lt;del&gt;tests&lt;/del&gt; specifications.&lt;/p&gt;  &lt;p&gt;And, don’t forget, the specification needs to be executable.&amp;#160; For this we would love to have a language enhancement – we actually need &lt;a href=&quot;http://research.microsoft.com/SpecSharp/&quot; target=&quot;_blank&quot;&gt;Spec#&lt;/a&gt; &lt;strong&gt;right now&lt;/strong&gt;.&amp;#160; But we won’t get that for a while (although I encourage you to check it out, and &lt;a href=&quot;http://codebetter.com/blogs/gregyoung/archive/2008/04/28/i-want-spec.aspx&quot; target=&quot;_blank&quot;&gt;petition Microsoft&lt;/a&gt; to get C# enhanced with &lt;a href=&quot;http://en.wikipedia.org/wiki/Design_by_contract&quot; target=&quot;_blank&quot;&gt;DbC&lt;/a&gt; goodness).&amp;#160; So in the meantime, we need a framework.&amp;#160; In the .Net space several frameworks (NSpec, Behave#) came together to form &lt;a href=&quot;http://www.codeplex.com/NBehave&quot; target=&quot;_blank&quot;&gt;NBehave&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Now you can write code like this:&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;[&lt;span style=&quot;color: #2b91af&quot;&gt;Theme&lt;/span&gt;(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;Account transfers and deposits&amp;quot;&lt;/span&gt;)]
&lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;AccountSpecs
&lt;/span&gt;{
    [&lt;span style=&quot;color: #2b91af&quot;&gt;Story&lt;/span&gt;]
    &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;Transfer_to_cash_account()
    {
        &lt;span style=&quot;color: #2b91af&quot;&gt;Account &lt;/span&gt;savings = &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;;
        &lt;span style=&quot;color: #2b91af&quot;&gt;Account &lt;/span&gt;cash = &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;;

        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;story = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Story&lt;/span&gt;(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;Transfer to cash account&amp;quot;&lt;/span&gt;);

        story
            .AsA(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;savings account holder&amp;quot;&lt;/span&gt;)
            .IWant(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;to transfer money from my savings account&amp;quot;&lt;/span&gt;)
            .SoThat(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;I can get cash easily from an ATM&amp;quot;&lt;/span&gt;);

        story.WithScenario(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;Savings account is in credit&amp;quot;&lt;/span&gt;)
            .Given(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance is&amp;quot;&lt;/span&gt;, 100,
                 accountBalance =&amp;gt; { savings = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Account&lt;/span&gt;(accountBalance); })
            .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance is&amp;quot;&lt;/span&gt;, 10,
                 accountBalance =&amp;gt; { cash = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Account&lt;/span&gt;(accountBalance); })
            .When(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;I transfer to cash account&amp;quot;&lt;/span&gt;, 20,
                 transferAmount =&amp;gt; savings.TransferTo(cash, transferAmount))
            .Then(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance should be&amp;quot;&lt;/span&gt;, 80,
                 expectedBalance =&amp;gt; savings.Balance.ShouldEqual(expectedBalance))
            .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance should be&amp;quot;&lt;/span&gt;, 30,
                 expectedBalance =&amp;gt; cash.Balance.ShouldEqual(expectedBalance))

            .Given(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance is&amp;quot;&lt;/span&gt;, 400)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance is&amp;quot;&lt;/span&gt;, 100)
            .When(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;I transfer to cash account&amp;quot;&lt;/span&gt;, 100)
            .Then(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance should be&amp;quot;&lt;/span&gt;, 300)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance should be&amp;quot;&lt;/span&gt;, 200)

            .Given(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance is&amp;quot;&lt;/span&gt;, 500)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance is&amp;quot;&lt;/span&gt;, 20)
            .When(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;I transfer to cash account&amp;quot;&lt;/span&gt;, 30)
            .Then(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance should be&amp;quot;&lt;/span&gt;, 470)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance should be&amp;quot;&lt;/span&gt;, 50);

        story.WithScenario(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;Savings account is overdrawn&amp;quot;&lt;/span&gt;)
            .Given(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance is&amp;quot;&lt;/span&gt;, -20)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance is&amp;quot;&lt;/span&gt;, 10)
            .When(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;I transfer to cash account&amp;quot;&lt;/span&gt;, 20)
            .Then(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my savings account balance should be&amp;quot;&lt;/span&gt;, -20)
              .And(&lt;span style=&quot;color: #a31515&quot;&gt;&amp;quot;my cash account balance should be&amp;quot;&lt;/span&gt;, 10);
    }
}&lt;/pre&gt;
&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;

&lt;p&gt;And you can run that in a test runner like &lt;a href=&quot;http://www.gallio.org/&quot; target=&quot;_blank&quot;&gt;Gallio&lt;/a&gt; (which even has &lt;a href=&quot;http://jetbrains.com/resharper&quot; target=&quot;_blank&quot;&gt;ReSharper&lt;/a&gt; plug-in).&amp;#160; Just like you would run your &lt;a href=&quot;http://nunit.org&quot; target=&quot;_blank&quot;&gt;NUnit&lt;/a&gt;/&lt;a href=&quot;http://www.mbunit.com/&quot; target=&quot;_blank&quot;&gt;MbUnit&lt;/a&gt;/&lt;a href=&quot;http://www.codeplex.com/xunit&quot; target=&quot;_blank&quot;&gt;xUnit&lt;/a&gt; tests.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.lostechies.com/blogs/jimmy_bogard/default.aspx&quot; target=&quot;_blank&quot;&gt;Jimmy Bogard&lt;/a&gt;, one of the authors of NBehave, wrote a &lt;a href=&quot;http://www.lostechies.com/blogs/jimmy_bogard/archive/2007/09/04/authoring-stories-with-nbehave-0-3.aspx&quot; target=&quot;_blank&quot;&gt;great post&lt;/a&gt; about writing stories using the &lt;a href=&quot;http://www.codeplex.com/NBehave/Release/ProjectReleases.aspx?ReleaseId=6849&quot; target=&quot;_blank&quot;&gt;latest version&lt;/a&gt; (0.3).&lt;/p&gt;

&lt;p&gt;NBehave is young.&amp;#160; But I love the &lt;a href=&quot;http://en.wikipedia.org/wiki/Fluent_interface&quot; target=&quot;_blank&quot;&gt;fluent interface&lt;/a&gt;.&amp;#160; And the caching of the delegates.&amp;#160; And the console runner outputs a formatted (more readable) specification that you can give to the business.&amp;#160; It makes for really readable specs.&lt;/p&gt;

&lt;p&gt;What about the granularity of these specs?&amp;#160; There’s definitely more than one thing being asserted.&amp;#160; But they’re much more than tests.&amp;#160; They are unit &lt;strike&gt;tests&lt;/strike&gt; specs and acceptance &lt;strike&gt;tests&lt;/strike&gt; specs combined. They define the behavior and check that the software conforms to that behavior, at the story and scenario level.&amp;#160; That’s good enough for me.&amp;#160; I’d much rather have this explicit alignment with atomic units of &lt;strong&gt;behaviour&lt;/strong&gt; (OK, the English spelling just looks better).&lt;/p&gt;

&lt;p&gt;Also, it reduces the coupling between the behaviour specification and it’s implementation, which means you can alter the implementation (refactor) without having to change the &lt;strike&gt;tests&lt;/strike&gt; specs.&amp;#160; At least not as much as you might with traditional TDD.&lt;/p&gt;

&lt;p&gt;To me it brings a great perspective to software development.&amp;#160; I’ve always believed in unit tests and in TDD.&amp;#160; This is just better.&amp;#160; By far.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/1056065775966280693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/07/language-of-behavior.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1056065775966280693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1056065775966280693'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/07/language-of-behavior.html' title='The Language of Behavior'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/stuartharris4/SIXTXspre4I/AAAAAAAAAEc/g9LZQHKmLi8/s72-c/image_thumb%5B10%5D.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-4810891107444456808</id><published>2008-07-14T15:51:00.001+01:00</published><updated>2008-07-14T15:51:37.876+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="Work Environment"/><title type='text'>Trust the experts</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://lh5.ggpht.com/stuartharris4/SHtn9n1X-NI/AAAAAAAAAEI/IrKTmehJ0go/s1600-h/n603790756_668277_2930%5B3%5D.jpg&quot;&gt;&lt;img title=&quot;Our home in Betty&amp;#39;s Bay&quot; style=&quot;border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;184&quot; alt=&quot;Our home in Betty&amp;#39;s Bay&quot; src=&quot;http://lh3.ggpht.com/stuartharris4/SHtn-UauULI/AAAAAAAAAEM/aRUqfpg_KQI/n603790756_668277_2930_thumb%5B1%5D.jpg?imgmax=800&quot; width=&quot;244&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;What better way to while away a 12-hour day-flight than to add a blog entry.&amp;#160; I’m off to Cape Town (actually Betty’s Bay where we have a small holiday home) for a week as I’m in-between jobs.&amp;#160; I just spent 4 years at &lt;a href=&quot;http://www.tfl.gov.uk/&quot; target=&quot;_blank&quot;&gt;London Underground&lt;/a&gt; (not a terrorist movement as US Immigration once thought I belonged to!).&amp;#160; It was by far the most challenging and rewarding role in my career.&amp;#160; It was there that I learned the most about writing great software. &lt;/p&gt;  &lt;p&gt;I discovered what’s important.&amp;#160; I’ve always paid attention to detail and that’s important.&amp;#160; I’ve always made sure that I know my languages and tools inside-out and that’s important.&amp;#160; Communication with the customer (and the team) has got to be right up there.&amp;#160; The most important thing, though, to help a team write the best software, has got to be trust.&amp;#160; Not &lt;em&gt;just&lt;/em&gt; trusting each other in the team – I already understood that.&amp;#160; Not &lt;em&gt;just &lt;/em&gt;trusting the customer and having her trust us – also understood.&amp;#160; What I learnt at LU was that our &lt;em&gt;management &lt;/em&gt;has to trust us.&amp;#160; Total trust.&amp;#160; Especially when we’re delivering. And delivering quality. Regularly, on time and in budget.&amp;#160; (I promise that this post is not going to turn into a rant because I’m actually grateful that I’ve learned this now, and that I can pursue the rest of my career without ever having to work again in an environment where management don’t trust and respect software development teams.)&lt;/p&gt;  &lt;p&gt;It’s incredibly hard for people that don’t get software to get software.&amp;#160; The corollary is also true – it’s incredibly hard to &lt;em&gt;help&lt;/em&gt; people that don’t get software to understand what it is all about.&amp;#160; To them it’s just magic.&amp;#160; All they can see (if they’re interested) is what the software does.&amp;#160; Not what it is.&amp;#160; Or what it takes to create it.&lt;/p&gt;  &lt;p&gt;We do have an incredibly powerful tool in our arsenal.&amp;#160; Being ¨Agile¨ is the only way I know of breaking down the divide between those that understand and those that don’t.&amp;#160; Although even being agile is not enough if you’re labouring under bad management.&lt;/p&gt;  &lt;h4&gt;Upward Spiral&lt;/h4&gt;  &lt;p&gt;The first 3 years at LU were like a dream.&amp;#160; We were getting more and more agile by the day.&amp;#160; Everybody was winning.&amp;#160; The business were getting exactly what they wanted.&amp;#160; When they wanted it.&amp;#160; The team was strong.&amp;#160; And happy.&amp;#160; And very productive.&amp;#160; I’m not saying we were perfect – that doesn’t happen – there’s always further to go than you’ve already come.&amp;#160; But the management were excellent – they believed in us and that was the key.&lt;/p&gt;  &lt;h4&gt;Downward Spiral&lt;/h4&gt;  &lt;p&gt;Then, a year ago, new management came in and took over.&amp;#160; By stealth.&amp;#160; Crony appointments for unqualified people who subsequently protect their positions using Mugabe-esque power tactics.&amp;#160; Tarring everyone with the lowest-common-denominator brush.&amp;#160; Simply because they don’t understand software and are scared (actually terrified) that everything will collapse in a heap if they trust anyone.&amp;#160; So don’t trust anyone, don’t let anyone have any responsibility or let them make any decisions.&amp;#160; Even if they’re the only ones qualified to do so.&amp;#160; Bind everyone up with rules, process and &lt;a href=&quot;http://en.wikipedia.org/wiki/Bureaucracy&quot; target=&quot;_blank&quot;&gt;bureaucracy&lt;/a&gt;.&amp;#160; Watch them with a hawk’s eye.&amp;#160; Control them and they’ll never put a foot wrong.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Wrong, wrong, wrong!&lt;/strong&gt; Trust them and let them fly.&amp;#160; Trust the experts.&amp;#160; They’ve spent more time and effort learning their trade than the management have theirs.&amp;#160; They know what they’re doing (most of the time!).&amp;#160; Engage with them and let them help you understand software.&amp;#160; Get the best people you can afford.&amp;#160; No, get better people than you can afford.&amp;#160; Let them be agile.&amp;#160; Remove the weight of process. Respect their knowledge and watch the results.&amp;#160; It takes brave management to do that.&amp;#160; But its the only way to get great software and to keep the best developers.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/4810891107444456808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/07/trust-experts.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/4810891107444456808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/4810891107444456808'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/07/trust-experts.html' title='Trust the experts'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/stuartharris4/SHtn-UauULI/AAAAAAAAAEM/aRUqfpg_KQI/s72-c/n603790756_668277_2930_thumb%5B1%5D.jpg?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-1985355578014894751</id><published>2008-06-29T15:29:00.001+01:00</published><updated>2008-06-30T11:56:13.868+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Code Style"/><category scheme="http://www.blogger.com/atom/ns#" term="Single Responsibility Pattern"/><title type='text'>C# regions, inline comments and blank lines are not harmless</title><content type='html'>&lt;p&gt;I didn’t want to call this “C# regions considered harmful” because &lt;a href=&quot;http://www.evilrob.org/journal/archives/2006/08/09/c-regions-consi.html&quot; target=&quot;_blank&quot;&gt;that article&lt;/a&gt; has already been written – and even though there’s a backlash against articles with titles like this (&lt;a href=&quot;http://meyerweb.com/eric/comment/chech.html&quot; target=&quot;_blank&quot;&gt;¨Considered harmful¨ essays considered harmful&lt;/a&gt;), &lt;a href=&quot;http://www.evilrob.org/journal/archives/2006/08/09/c-regions-consi.html&quot; target=&quot;_blank&quot;&gt;Rob Meyer’s article&lt;/a&gt; is spot on and should be read by every C# developer that uses regions in their code.&lt;/p&gt;  &lt;p&gt;I don’t understand why regions were introduced into C#.&amp;#160; I guess they were meant to allow tools to hide generated code before partial classes were introduced.&amp;#160; Now they&#39;re just in the way.&amp;#160; I think I dislike them so much because they appear to be benign – you would think that a keyword that does nothing couldn’t do any harm.&amp;#160; But hiding code, without abstracting it away using proper OO techniques, encourages developers to write poorly structured code. &lt;/p&gt;  &lt;p&gt;The default settings in Visual Studio that cause regions to be collapsed when you open a file don’t help (although you can change that: &lt;strong&gt;Tools –&amp;gt; Options –&amp;gt; Text Editor –&amp;gt; C# –&amp;gt; Advanced –&amp;gt; Enter outlining mode when files open&lt;/strong&gt;).&amp;#160; If a file has collapsed regions in it I can press &lt;strong&gt;Ctrl-ML &lt;/strong&gt;to expand them all in one go. Even better, I can take the regions out.&amp;#160; &lt;a href=&quot;http://jetbrains.com/resharper&quot; target=&quot;_blank&quot;&gt;ReSharper&lt;/a&gt; has a File Structure tool window (&lt;strong&gt;Ctrl-F11&lt;/strong&gt;) where you can delete a region by clicking the “x” in its top right corner.&amp;#160; To stop ReSharper adding regions when you format code: &lt;strong&gt;ReSharper –&amp;gt; Options –&amp;gt; C# –&amp;gt; Type Members Layout –&amp;gt;&lt;/strong&gt; uncheck &lt;strong&gt;Use Default Patterns&lt;/strong&gt;, then remove all &lt;strong&gt;&amp;lt;Group /&amp;gt;&lt;/strong&gt; tags from the XML.&lt;/p&gt;  &lt;p&gt;It’s not only regions that are used to delineate chunks of code.&amp;#160; Often inline comments, and even blank lines, are used in a similar way.&amp;#160; The comment’s text often describes what the chunk of code does.&amp;#160; Horrible.&amp;#160; Extract a method.&amp;#160; Or move the responsibility to another (maybe new) class.&amp;#160; Every time I find myself adding a blank line or an inline comment, I ask myself why?&amp;#160; Am I dividing up code?&amp;#160; Should I be calling a (new) method?&amp;#160; I&#39;m not saying that inline comments are necessarily bad - they should just be reserved for stating the non-obvious.&amp;#160; Nor are blank lines necessarily bad - they should just be used to improve readability, not to divide a monolith.&lt;/p&gt;  &lt;p&gt;A method should do one thing, and one thing only (&lt;a href=&quot;http://www.codinghorror.com/blog/archives/000805.html&quot; target=&quot;_blank&quot;&gt;Jeff’s post&lt;/a&gt; on this is great).&amp;#160; I should be able to grok what a method does instantly.&amp;#160; The first (major) clue to a method’s functionality is it’s name (which is really a Pascal cased sentence with a verb and everything!).&amp;#160; The name (and signature) tells me what I should expect the method to do. Then the body of the method confirms that.&amp;#160; A few lines of code that I can see in one glance and understand quickly.&amp;#160; A few lines of code that do one thing.&amp;#160; TDD/BDD helps keep our methods short and to the point.&lt;/p&gt;  &lt;p&gt;A class should do one thing, and one thing only. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot; target=&quot;_blank&quot;&gt;Single Responsibility Pattern (SRP)&lt;/a&gt; should keep our classes focused and cohesive.&amp;#160; No room for regions.&amp;#160; No need for regions.&amp;#160; If we adhere to the SRP then our classes should be fairly short – with not too many members.&amp;#160; That means that wrapping members in regions (with names like “.ctors”, “fields”, “properties”, “methods” etc.) is totally unnecessary, obstructive and thus counterproductive (although ordering the members within the class &lt;em&gt;is &lt;/em&gt;essential).&amp;#160; The goal here has got to be: “I want other developers to be able to read and understand my code as quickly and as easily as possible” – meaning that I don’t want them to have to lift up all these region &amp;quot;carpets&amp;quot; to see what’s been swept underneath.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/1985355578014894751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/06/c-regions-inline-comments-and-blank.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1985355578014894751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1985355578014894751'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/06/c-regions-inline-comments-and-blank.html' title='C# regions, inline comments and blank lines are not harmless'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-516084884258004070.post-1432934887203604954</id><published>2008-06-25T19:36:00.001+01:00</published><updated>2009-06-14T14:51:09.077+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection"/><category scheme="http://www.blogger.com/atom/ns#" term="IoC"/><category scheme="http://www.blogger.com/atom/ns#" term="IRepository"/><category scheme="http://www.blogger.com/atom/ns#" term="LINQ"/><category scheme="http://www.blogger.com/atom/ns#" term="LINQ to SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="Unit of Work"/><title type='text'>Working together: LINQ to SQL, IRepository&amp;lt;T&amp;gt;, Unit Of Work and Dependency Injection</title><content type='html'>&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9bd2562e-7a3b-44bb-8640-92ed931b16a8&quot; class=&quot;wlWriterSmartContent&quot;&gt;Technorati Tags: &lt;a href=&quot;http://technorati.com/tags/Unit+of+Work&quot; rel=&quot;tag&quot;&gt;Unit of Work&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/Dependency+Injection&quot; rel=&quot;tag&quot;&gt;Dependency Injection&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/IRepository&quot; rel=&quot;tag&quot;&gt;IRepository&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/LINQ+to+SQL&quot; rel=&quot;tag&quot;&gt;LINQ to SQL&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/LINQ&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;&lt;/div&gt; &lt;p&gt;I want to be able to write code like this: &lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IRepository&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;User&lt;/span&gt;&amp;gt; repository = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Repository&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;User&lt;/span&gt;&amp;gt;();
repository.GetById(userId).Username = &lt;span style=&quot;color: #a31515&quot;&gt;&quot;Stuart&quot;&lt;/span&gt;;
repository.SubmitChanges();&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;and like this: 
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;return new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Repository&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;User&lt;/span&gt;&amp;gt;()
                .Where(u =&amp;gt; u.Username == username)
                .Select(u =&amp;gt; Map(u));&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;I want the Repository to work with an underlying &lt;font face=&quot;Courier New&quot;&gt;DataContext&lt;/font&gt; that follows a Unit of Work pattern.&amp;nbsp; The UoW has to be aware of the context in which it is running (e.g. HTTP Web request or thread local).&amp;nbsp; That way change tracking has a lifetime that matches my Request/Thread and my &lt;font face=&quot;Courier New&quot;&gt;DataContext&lt;/font&gt; gets disposed for me when we’re done.&lt;/p&gt;
&lt;p&gt;I also want the Repository to be auto-magically set up for me, with either an underlying SQL database or an in-memory data store (for my tests).&amp;nbsp; Oh, and the in-memory store must track changes too!&amp;nbsp; It’ll be no good for tests if it doesn’t work the same way.&lt;/p&gt;
&lt;p&gt;Finally (and most importantly) the Repository &lt;em&gt;has&lt;/em&gt; to support IQueryable so that we can work all that LINQ magic.&amp;nbsp; I’ll also want to derive specialized Repositories from Repository&amp;lt;T&amp;gt; to encapsulate a bunch of canned queries – including some fluent DSL-like methods that work as filters.&lt;/p&gt;
&lt;h4&gt;I guess I don’t want too much!&lt;/h4&gt;
&lt;p&gt;We’re going to need the &lt;a href=&quot;http://martinfowler.com/eaaCatalog/repository.html&quot; target=&quot;_blank&quot;&gt;Repository pattern&lt;/a&gt;, the &lt;a href=&quot;http://martinfowler.com/eaaCatalog/unitOfWork.html&quot; target=&quot;_blank&quot;&gt;Unit of Work pattern&lt;/a&gt;, the &lt;a href=&quot;http://martinfowler.com/articles/injection.html&quot; target=&quot;_blank&quot;&gt;Dependency Injection pattern&lt;/a&gt; and the &lt;a href=&quot;http://en.wikipedia.org/wiki/Inversion_of_Control&quot; target=&quot;_blank&quot;&gt;Inversion of Control pattern&lt;/a&gt;.&amp;nbsp; (Thanks Martin.)&lt;/p&gt;
&lt;p&gt;This could all be improved substantially so please make suggestions in the comments.&amp;nbsp; It makes a long first post – but ¨Hey!¨ It’ll be worthwhile, hopefully.&amp;nbsp;&amp;nbsp; I’ll also post all the code as a VS project but for now I’ll just list it here:&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Let’s start with the interfaces.&amp;nbsp; The Repository uses the Unit Of Work to manage the Data Source.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lh5.ggpht.com/stuartharris4/SGJm4_THAII/AAAAAAAAABk/fpbZ_PPDYHY/s1600-h/image%5B14%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh6.ggpht.com/stuartharris4/SGJQMPs_b1I/AAAAAAAAABo/Z4vZBQxgXhE/image_thumb%5B8%5D.png?imgmax=800&quot; width=&quot;532&quot; height=&quot;133&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;IDataSource&amp;lt;T&amp;gt; implements IQueryable&amp;lt;T&amp;gt; and adds the DataContext methods InsertOnSubmit() and DeleteOnSubmit() (the ones I use most).&amp;nbsp; I also added a GetById() method for convenience.&amp;nbsp; All the other useful stuff comes from IQueryable&amp;lt;T&amp;gt; …&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;IQueryable&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
{
    T GetById(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;id);
    &lt;span style=&quot;color: blue&quot;&gt;void &lt;/span&gt;InsertOnSubmit(T entity);
    &lt;span style=&quot;color: blue&quot;&gt;void &lt;/span&gt;DeleteOnSubmit(T entity);
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It’s the IUnitOfWork implementation that’s responsible for pushing the changes back down to the store:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork &lt;/span&gt;: &lt;span style=&quot;color: #2b91af&quot;&gt;IDisposable
&lt;/span&gt;{
    &lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; GetDataSource&amp;lt;T&amp;gt;() &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;();
    &lt;span style=&quot;color: blue&quot;&gt;void &lt;/span&gt;SubmitChanges();
    &lt;span style=&quot;color: blue&quot;&gt;void &lt;/span&gt;SubmitChanges(&lt;span style=&quot;color: #2b91af&quot;&gt;ConflictMode &lt;/span&gt;conflictMode);
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;h4&gt;The DataSource&lt;/h4&gt;
&lt;p&gt;I was really impressed with &lt;a href=&quot;http://mikehadlow.blogspot.com/2008/04/repositorygetbyid-using-linq-expression.html&quot; target=&quot;_blank&quot;&gt;Mike Hadlow’s implementation&lt;/a&gt; of GetById() – it saves you having to know what the “primary key” property is.&amp;nbsp; So I abstracted a base class for it.&amp;nbsp; The method generates a lambda expression on the fly that is used in a Where() method to find objects where the primary key has the specified value.&amp;nbsp; (An extension method on System.Type finds me the property that is marked with Column.IsPrimaryKey).&amp;nbsp; Here’s the extension method …&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;public static &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;PropertyInfo &lt;/span&gt;GetPrimaryKey(&lt;span style=&quot;color: blue&quot;&gt;this &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type &lt;/span&gt;entityType)
{
    &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;PropertyInfo &lt;/span&gt;property &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;entityType.GetProperties())
    {
        &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;attributes = (&lt;span style=&quot;color: #2b91af&quot;&gt;ColumnAttribute&lt;/span&gt;[]) property.GetCustomAttributes(
                                                 &lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;ColumnAttribute&lt;/span&gt;), &lt;span style=&quot;color: blue&quot;&gt;true&lt;/span&gt;);
        &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(attributes.Length == 1)
        {
            &lt;span style=&quot;color: #2b91af&quot;&gt;ColumnAttribute &lt;/span&gt;columnAttribute = attributes[0];
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(columnAttribute.IsPrimaryKey)
            {
                &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(property.PropertyType != &lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;int&lt;/span&gt;))
                {
                    &lt;span style=&quot;color: blue&quot;&gt;throw new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ApplicationException&lt;/span&gt;(
                        &lt;span style=&quot;color: blue&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;Primary key, &#39;{0}&#39;, of type &#39;{1}&#39; is not int&quot;&lt;/span&gt;,
                                      property.Name, entityType));
                }
                &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;property;
            }
        }
    }
    &lt;span style=&quot;color: blue&quot;&gt;throw new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ApplicationException&lt;/span&gt;(
        &lt;span style=&quot;color: blue&quot;&gt;string&lt;/span&gt;.Format(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;No primary key defined for type {0}&quot;&lt;/span&gt;, entityType.Name));
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;And now here’s the implementation of DataSource&amp;lt;T&amp;gt; – including &lt;a href=&quot;http://mikehadlow.blogspot.com&quot; target=&quot;_blank&quot;&gt;Mike’s&lt;/a&gt; GetById():&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq.Expressions;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;Library.Extensions;&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;public abstract class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DataSource&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
{
    &lt;span style=&quot;color: blue&quot;&gt;protected &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IQueryable&lt;/span&gt;&amp;lt;T&amp;gt; _source;
    &lt;span style=&quot;color: blue&quot;&gt;public abstract &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Expression &lt;/span&gt;Expression { &lt;span style=&quot;color: blue&quot;&gt;get&lt;/span&gt;; }
    &lt;span style=&quot;color: blue&quot;&gt;public abstract &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type &lt;/span&gt;ElementType { &lt;span style=&quot;color: blue&quot;&gt;get&lt;/span&gt;; }
    &lt;span style=&quot;color: blue&quot;&gt;public abstract &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IQueryProvider &lt;/span&gt;Provider { &lt;span style=&quot;color: blue&quot;&gt;get&lt;/span&gt;; }

    &lt;span style=&quot;color: blue&quot;&gt;public virtual &lt;/span&gt;T GetById(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;id)
    {
        &lt;span style=&quot;color: #2b91af&quot;&gt;ParameterExpression &lt;/span&gt;itemParameter = &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;.Parameter(&lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(T), &lt;span style=&quot;color: #a31515&quot;&gt;&quot;item&quot;&lt;/span&gt;);

        &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Func&lt;/span&gt;&amp;lt;T, &lt;span style=&quot;color: blue&quot;&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; whereExpression =
            &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;.Lambda&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Func&lt;/span&gt;&amp;lt;T, &lt;span style=&quot;color: blue&quot;&gt;bool&lt;/span&gt;&amp;gt;&amp;gt;(
                &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;.Equal(
                    &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;.Property(
                        itemParameter,
                        &lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(T).GetPrimaryKey().Name),
                    &lt;span style=&quot;color: #2b91af&quot;&gt;Expression&lt;/span&gt;.Constant(id)),
                &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;[] {itemParameter});

        &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Where(whereExpression).Single();
    }

    &lt;span style=&quot;color: blue&quot;&gt;public abstract void &lt;/span&gt;InsertOnSubmit(T entity);
    &lt;span style=&quot;color: blue&quot;&gt;public abstract void &lt;/span&gt;DeleteOnSubmit(T entity);

    &lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator IEnumerable&lt;/span&gt;.GetEnumerator()
    {
        &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;GetEnumerator();
    }

    &lt;span style=&quot;color: blue&quot;&gt;public abstract &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; GetEnumerator();
}
&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;pre class=&quot;code&quot;&gt;&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;So now we need 2 subclasses of DataSource – one for the SQL store and one for the in-memory store.&amp;nbsp; The &lt;a href=&quot;http://www.martinfowler.com/articles/injection.html&quot; target=&quot;_blank&quot;&gt;IoC container&lt;/a&gt; will build the Repository with the relevant DataSource and DataContext when the time comes (more later).&lt;/p&gt;
&lt;p&gt;Firstly the DatabaseDataSource really just delegates to the relevant Table&amp;lt;T&amp;gt; (which is IQueryable) from the underlying DataContext:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Data.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq.Expressions;

&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DatabaseDataSource&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;DataSource&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
    {
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DataContext &lt;/span&gt;_dataContext;

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;DatabaseDataSource(&lt;span style=&quot;color: #2b91af&quot;&gt;DataContext &lt;/span&gt;dataContext)
        {
            _dataContext = dataContext;
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(dataContext == &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;)
                &lt;span style=&quot;color: blue&quot;&gt;throw new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ArgumentNullException&lt;/span&gt;(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;dataContext&quot;&lt;/span&gt;);

            _source = _dataContext.GetTable&amp;lt;T&amp;gt;();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type &lt;/span&gt;ElementType
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.ElementType; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Expression &lt;/span&gt;Expression
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Expression; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IQueryProvider &lt;/span&gt;Provider
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Provider; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; GetEnumerator()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.GetEnumerator();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override void &lt;/span&gt;InsertOnSubmit(T entity)
        {
            ((&lt;span style=&quot;color: #2b91af&quot;&gt;Table&lt;/span&gt;&amp;lt;T&amp;gt;) _source).InsertOnSubmit(entity);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override void &lt;/span&gt;DeleteOnSubmit(T entity)
        {
            ((&lt;span style=&quot;color: #2b91af&quot;&gt;Table&lt;/span&gt;&amp;lt;T&amp;gt;) _source).DeleteOnSubmit(entity);
        }
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;Then the InMemoryDataSource does a similar thing but with a Dictionary of TrackedObjects – each of which can accept changes.&amp;nbsp; (This is what I want for my Unit Tests.)&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq.Expressions;

&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;InMemoryDataSource&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;DataSource&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;ITrackingContainer &lt;/span&gt;&lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
    {
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDictionary&lt;/span&gt;&amp;lt;T, &lt;span style=&quot;color: #2b91af&quot;&gt;TrackedObject&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt; _trackedObjects
            = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Dictionary&lt;/span&gt;&amp;lt;T, &lt;span style=&quot;color: #2b91af&quot;&gt;TrackedObject&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;InMemoryDataSource() : &lt;span style=&quot;color: blue&quot;&gt;this&lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;())
        {
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;InMemoryDataSource(&lt;span style=&quot;color: #2b91af&quot;&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; source)
        {
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(source == &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;)
                &lt;span style=&quot;color: blue&quot;&gt;throw new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ArgumentNullException&lt;/span&gt;(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;source&quot;&lt;/span&gt;);

            source.ForEach(Track);
            _source = _trackedObjects.Keys.AsQueryable();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type &lt;/span&gt;ElementType
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.ElementType; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Expression &lt;/span&gt;Expression
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Expression; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IQueryProvider &lt;/span&gt;Provider
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Provider; }
        }

        &lt;span style=&quot;color: #2b91af&quot;&gt;IDictionary ITrackingContainer&lt;/span&gt;.Data
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_trackedObjects; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; GetEnumerator()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.GetEnumerator();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override void &lt;/span&gt;InsertOnSubmit(T entity)
        {
            Track(entity);
            _trackedObjects[entity].ChangeState(&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState&lt;/span&gt;.Added);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public override void &lt;/span&gt;DeleteOnSubmit(T entity)
        {
            Track(entity);
            _trackedObjects[entity].ChangeState(&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState&lt;/span&gt;.Deleted);
        }

        &lt;span style=&quot;color: blue&quot;&gt;private void &lt;/span&gt;Track(T entity)
        {
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(!_trackedObjects.ContainsKey(entity))
                _trackedObjects.Add(entity, &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedObject&lt;/span&gt;&amp;lt;T&amp;gt;(entity));
        }
    }&lt;font color=&quot;#0000ff&quot;&gt;&lt;br&gt;&lt;/font&gt;
    &lt;span style=&quot;color: blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ITrackingContainer
    &lt;/span&gt;{
        &lt;span style=&quot;color: #2b91af&quot;&gt;IDictionary &lt;/span&gt;Data { &lt;span style=&quot;color: blue&quot;&gt;get&lt;/span&gt;; }
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;The TrackedObject (listed below) could definitely be improved – currently it just does some basic change tracking using the enum TrackedState:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;internal class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedObject&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;ITrackedObject &lt;/span&gt;&lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
    {
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;T _inner;
        &lt;span style=&quot;color: blue&quot;&gt;private &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState &lt;/span&gt;_state;

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;TrackedObject(T trackedObject)
        {
            _inner = trackedObject;
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;T Inner
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_inner; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState &lt;/span&gt;State
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_state; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ITrackedObject&lt;/span&gt;.Inner
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_inner; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;ChangeState(&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState &lt;/span&gt;state)
        {
            _state = state;
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;AcceptChanges()
        {
            _state = &lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState&lt;/span&gt;.Undefined;
        }
    }&lt;br&gt;
    &lt;span style=&quot;color: blue&quot;&gt;internal enum &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;TrackedState
    &lt;/span&gt;{
        Undefined,
        Added,
        Modified,
        Deleted
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;Here’s the class diagram for the DataSource side of things:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/stuartharris4/SGJm58YAY-I/AAAAAAAAABs/lhWiNsGAk18/s1600-h/image%5B13%5D.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh4.ggpht.com/stuartharris4/SGJm61Ra9hI/AAAAAAAAABw/dCDbk2wAtCw/image_thumb%5B7%5D.png?imgmax=800&quot; width=&quot;537&quot; height=&quot;431&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I was going to divide this into 2 posts but couldn’t really see the point as we’re nearly there (and it&amp;nbsp; get’s much better from here on), so on we go.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;h4&gt;The Unit Of Work&lt;/h4&gt;
&lt;p&gt;First the classes derived from IUnitOfWork.&amp;nbsp; We’re going to need one for the real database and one for the tests.&amp;nbsp; The DatabaseUnitOfWork also has a dependency on the LINQ DataContext – but the &lt;a href=&quot;http://www.martinfowler.com/articles/injection.html&quot; target=&quot;_blank&quot;&gt;IoC container&lt;/a&gt; will take care of that.&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Data.Linq;

&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DatabaseUnitOfWork &lt;/span&gt;: &lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork
    &lt;/span&gt;{
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DataContext &lt;/span&gt;_dataContext;

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;DatabaseUnitOfWork(&lt;span style=&quot;color: #2b91af&quot;&gt;DataContext &lt;/span&gt;dataContext)
        {
            &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(dataContext == &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;)
                &lt;span style=&quot;color: blue&quot;&gt;throw new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ArgumentNullException&lt;/span&gt;(&lt;span style=&quot;color: #a31515&quot;&gt;&quot;dataContext&quot;&lt;/span&gt;);

            _dataContext = dataContext;
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; GetDataSource&amp;lt;T&amp;gt;() &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;DatabaseDataSource&lt;/span&gt;&amp;lt;T&amp;gt;(_dataContext);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;SubmitChanges()
        {
            _dataContext.SubmitChanges();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;SubmitChanges(&lt;span style=&quot;color: #2b91af&quot;&gt;ConflictMode &lt;/span&gt;conflictMode)
        {
            _dataContext.SubmitChanges(conflictMode);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;Dispose()
        {
            _dataContext.Dispose();
        }
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The InMemoryUnitOfWork is more interesting as it manages each InMemoryDataSource&amp;lt;T&amp;gt; (like the DataContext manages each Table&amp;lt;T&amp;gt;):&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Data.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq;

&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;InMemoryUnitOfWork &lt;/span&gt;: &lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork
    &lt;/span&gt;{
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDictionary&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;IQueryable&lt;/span&gt;&amp;gt; _dataSources
            = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;IQueryable&lt;/span&gt;&amp;gt;();
        &lt;span style=&quot;color: blue&quot;&gt;private readonly object &lt;/span&gt;_lock = &lt;span style=&quot;color: blue&quot;&gt;new object&lt;/span&gt;();

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; GetDataSource&amp;lt;T&amp;gt;() &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
        {
            &lt;span style=&quot;color: blue&quot;&gt;lock &lt;/span&gt;(_lock)
            {
                &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(!_dataSources.ContainsKey(&lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(T)))
                    _dataSources.Add(&lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(T), &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;InMemoryDataSource&lt;/span&gt;&amp;lt;T&amp;gt;());
                &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_dataSources[&lt;span style=&quot;color: blue&quot;&gt;typeof &lt;/span&gt;(T)] &lt;span style=&quot;color: blue&quot;&gt;as &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;InMemoryDataSource&lt;/span&gt;&amp;lt;T&amp;gt;;
            }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;SubmitChanges()
        {
            SubmitChanges(&lt;span style=&quot;color: #2b91af&quot;&gt;ConflictMode&lt;/span&gt;.FailOnFirstConflict);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;SubmitChanges(&lt;span style=&quot;color: #2b91af&quot;&gt;ConflictMode &lt;/span&gt;conflictMode)
        {
            &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;pair &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;_dataSources)
            {
                &lt;span style=&quot;color: blue&quot;&gt;var &lt;/span&gt;trackingContainer = (&lt;span style=&quot;color: #2b91af&quot;&gt;ITrackingContainer&lt;/span&gt;) pair.Value;
                &lt;span style=&quot;color: blue&quot;&gt;foreach &lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;ITrackedObject &lt;/span&gt;trackedObject &lt;span style=&quot;color: blue&quot;&gt;in &lt;/span&gt;trackingContainer.Data.Values)
                    trackedObject.AcceptChanges();
            }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;Dispose()
        {
        }
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;h4&gt;The Repository&lt;/h4&gt;
&lt;p&gt;Finally the Repository&amp;lt;T&amp;gt; implementation which coordinates the IUnitOfWork and IDataSource&amp;lt;T&amp;gt;.&amp;nbsp; Note that we’re introducing the IoC (or more correctly ¨DI¨) container here.&amp;nbsp; This example uses &lt;a href=&quot;http://www.pnpguidance.net/Category/Unity.aspx&quot; target=&quot;_blank&quot;&gt;Unity&lt;/a&gt; but any DI container will do exactly the same job.&amp;nbsp; Unity is great, simple, quick and perfectly good for the job.&amp;nbsp; (I’m also getting into &lt;a href=&quot;http://structuremap.sourceforge.net/Default.htm&quot; target=&quot;_blank&quot;&gt;StructureMap&lt;/a&gt; right now which looks great – &lt;a href=&quot;http://sourceforge.net/project/showfiles.php?group_id=104740&amp;amp;package_id=112685&amp;amp;release_id=608958&quot; target=&quot;_blank&quot;&gt;version 2.5&lt;/a&gt; is very modern (!) and it gets you away from the traditionally over-used XML config).&amp;nbsp; In &lt;a href=&quot;http://www.castleproject.org/container/index.html&quot; target=&quot;_blank&quot;&gt;Windsor&lt;/a&gt; and StructureMap you can specify that your object’s lifetime follows the web request (StructureMap even has a hybrid mode that gives you a web request lifetime if there is an HttpContext and a ThreadLocal if not) – with Unity I had to jump through a few hoops.&amp;nbsp; In the meantime (please contain your excitement) here’s the Repository listing…&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Collections.Generic;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Data.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;System.Linq.Expressions;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;Library.IoC;
&lt;span style=&quot;color: blue&quot;&gt;using &lt;/span&gt;Microsoft.Practices.Unity;

&lt;span style=&quot;color: blue&quot;&gt;namespace &lt;/span&gt;Library.Linq
{
    &lt;span style=&quot;color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Repository&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style=&quot;color: #2b91af&quot;&gt;IRepository&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&quot;color: blue&quot;&gt;where &lt;/span&gt;T : &lt;span style=&quot;color: blue&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: blue&quot;&gt;new&lt;/span&gt;()
    {
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; _source;
        &lt;span style=&quot;color: blue&quot;&gt;private readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork &lt;/span&gt;_unitOfWork;

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;Repository()
        {
            _unitOfWork = ((&lt;span style=&quot;color: #2b91af&quot;&gt;IContainerAccessor&lt;/span&gt;) &lt;span style=&quot;color: #2b91af&quot;&gt;Context&lt;/span&gt;.Current).Container.Resolve&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork&lt;/span&gt;&amp;gt;();
            _source = _unitOfWork.GetDataSource&amp;lt;T&amp;gt;();
        }

        [&lt;span style=&quot;color: #2b91af&quot;&gt;InjectionConstructor&lt;/span&gt;]
        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;Repository(&lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork &lt;/span&gt;unitOfWork)
        {
            _unitOfWork = unitOfWork;
            _source = _unitOfWork.GetDataSource&amp;lt;T&amp;gt;();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T&amp;gt; Source
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source; }
        }

        &lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;.GetEnumerator()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.GetEnumerator();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IEnumerator &lt;/span&gt;GetEnumerator()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.GetEnumerator();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Expression &lt;/span&gt;Expression
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Expression; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Type &lt;/span&gt;ElementType
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.ElementType; }
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IQueryProvider &lt;/span&gt;Provider
        {
            &lt;span style=&quot;color: blue&quot;&gt;get &lt;/span&gt;{ &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.Provider; }
        }

        &lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T1&amp;gt; &lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork&lt;/span&gt;.GetDataSource&amp;lt;T1&amp;gt;()
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;IDataSource&lt;/span&gt;&amp;lt;T1&amp;gt;) _source;
        }

        &lt;span style=&quot;color: blue&quot;&gt;public virtual void &lt;/span&gt;SubmitChanges()
        {
            _unitOfWork.SubmitChanges();
        }

        &lt;span style=&quot;color: blue&quot;&gt;public virtual void &lt;/span&gt;SubmitChanges(&lt;span style=&quot;color: #2b91af&quot;&gt;ConflictMode &lt;/span&gt;conflictMode)
        {
            _unitOfWork.SubmitChanges(conflictMode);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public &lt;/span&gt;T GetById(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;id)
        {
            &lt;span style=&quot;color: blue&quot;&gt;return &lt;/span&gt;_source.GetById(id);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;InsertOnSubmit(T entity)
        {
            _source.InsertOnSubmit(entity);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;DeleteOnSubmit(T entity)
        {
            _source.DeleteOnSubmit(entity);
        }

        &lt;span style=&quot;color: blue&quot;&gt;public void &lt;/span&gt;Dispose()
        {
            _unitOfWork.Dispose();
        }
    }
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;The constructor finds the relevant Container and gets it to resolve the current Unit of Work.&amp;nbsp; It does this because you don’t want to.&amp;nbsp; At point of use – you really don’t care about IoC, UoW, or any other TLAs. &lt;/p&gt;
&lt;h4&gt;Dependency Injection&lt;/h4&gt;
&lt;p&gt;So how &lt;em&gt;do&lt;/em&gt; we use all this?&amp;nbsp; Well, there’s no more to it than I alluded to at the beginning of the post.&amp;nbsp; Every time you construct a new Repository, the IoC container will connect it to the relevant Unit Of Work and DataSource for you.&amp;nbsp; Automatically. You can just use it and all will be just fine.&amp;nbsp; In your app with the real DB or in your tests with an in-memory store.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Here’s how I configured Unity to set it up for me (obviously in your test assemblies you would register the in-memory equivalents).&amp;nbsp; This is in Global.asax:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;private static readonly &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;IUnityContainer &lt;/span&gt;_container = &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;UnityContainer&lt;/span&gt;();

&lt;span style=&quot;color: blue&quot;&gt;protected void &lt;/span&gt;Application_Start(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;sender, &lt;span style=&quot;color: #2b91af&quot;&gt;EventArgs &lt;/span&gt;e)
{
    _container
        .RegisterType&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;DataContext&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;MyDataContext&lt;/span&gt;&amp;gt;()
        .Configure&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;InjectedMembers&lt;/span&gt;&amp;gt;()
        .ConfigureInjectionFor&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;MyDataContext&lt;/span&gt;&amp;gt;(
        &lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;InjectionConstructor&lt;/span&gt;(&lt;span style=&quot;color: #2b91af&quot;&gt;ConfigurationManager&lt;/span&gt;.ConnectionStrings[&lt;span style=&quot;color: #a31515&quot;&gt;&quot;MyConnStr&quot;&lt;/span&gt;].ConnectionString));

    ((&lt;span style=&quot;color: #2b91af&quot;&gt;IContainerAccessor&lt;/span&gt;)Library.IoC.&lt;span style=&quot;color: #2b91af&quot;&gt;Context&lt;/span&gt;.Current).Container = _container;
}

&lt;span style=&quot;color: blue&quot;&gt;protected void &lt;/span&gt;Application_BeginRequest(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;sender, &lt;span style=&quot;color: #2b91af&quot;&gt;EventArgs &lt;/span&gt;e)
{
    &lt;span style=&quot;color: #2b91af&quot;&gt;IUnityContainer &lt;/span&gt;childContainer = _container.CreateChildContainer();
    childContainer
        .RegisterType&amp;lt;&lt;span style=&quot;color: #2b91af&quot;&gt;IUnitOfWork&lt;/span&gt;, &lt;span style=&quot;color: #2b91af&quot;&gt;DatabaseUnitOfWork&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;ContainerControlledLifetimeManager&lt;/span&gt;());

    ((&lt;span style=&quot;color: #2b91af&quot;&gt;IContainerAccessor&lt;/span&gt;) Library.IoC.&lt;span style=&quot;color: #2b91af&quot;&gt;Context&lt;/span&gt;.Current).Container = childContainer;
}

&lt;span style=&quot;color: blue&quot;&gt;protected void &lt;/span&gt;Application_EndRequest(&lt;span style=&quot;color: blue&quot;&gt;object &lt;/span&gt;sender, &lt;span style=&quot;color: #2b91af&quot;&gt;EventArgs &lt;/span&gt;e)
{
    &lt;span style=&quot;color: #2b91af&quot;&gt;IUnityContainer &lt;/span&gt;container = ((&lt;span style=&quot;color: #2b91af&quot;&gt;IContainerAccessor&lt;/span&gt;) Library.IoC.&lt;span style=&quot;color: #2b91af&quot;&gt;Context&lt;/span&gt;.Current).Container;
    &lt;span style=&quot;color: blue&quot;&gt;if &lt;/span&gt;(container != &lt;span style=&quot;color: blue&quot;&gt;null&lt;/span&gt;)
        container.Dispose();
}&lt;/pre&gt;&lt;a href=&quot;http://11011.net/software/vspaste&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The interesting things to note here are related to the life-time management of the Unit of Work.&amp;nbsp; The parent Unity Container has application scope and will be used to resolve anything that the child container (which has request scope) cannot.&amp;nbsp; This involves resolving the DataContext and injecting the DB connection string into its constructor. &lt;/p&gt;
&lt;p&gt;A new child container is created for each incoming HTTP request and is instructed to create a new DataBaseUnitOfWork for the lifetime of the child container (which happens to equal the lifetime of the request because the child container is disposed at the end of the request).&amp;nbsp; When a container is disposed, any objects to which it holds a reference will also get disposed, so the UnitOfWork, which implements IDisposable, gets disposed and any outstanding change tracking is lost.&amp;nbsp; That’s exactly what we want – it’s up to you to decide when to call SubmitChanges() on the Repository and you can do that as often and whenever you want – each one encapsulating an atomic transaction with the DB.&amp;nbsp; You can even call SubmitChanges() like this:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span style=&quot;color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color: #2b91af&quot;&gt;Repository&lt;/span&gt;&amp;lt;User&amp;gt;().SubmitChanges();&lt;/pre&gt;
&lt;p&gt;and any outstanding changes will get flushed inside a new transaction.&amp;nbsp; The point is that it doesn’t matter how many times you “new up” a Repository, you’re still working with the same underlying DataContext.&lt;/p&gt;
&lt;p&gt;Creating child Unity Containers doesn’t seem to be expensive – and it doesn’t seem to matter how many of them you create.&amp;nbsp; Let me know if you find anything &lt;em&gt;bad&lt;/em&gt; about this though!&amp;nbsp; The Context implementation is not listed here&lt;em&gt; (but see update below)&lt;/em&gt;, but it’s reasonably trivial and is in the downloadable project (if I can find somewhere to host it!).&lt;/p&gt;
&lt;p&gt;I’m really interested in your comments.&amp;nbsp; I know we can make this better.&amp;nbsp; At point of use, it seems to me, it’s nice and simple.&amp;nbsp; The implementation, though, can always be improved.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: The Context class is simply a static class with one property (called Current) whose backing field is marked as ThreadStatic.&amp;nbsp; At the start of each web request (in Global.asax) a reference to the child container is stored in this field which remains local to the thread that the request is running on – each new request will get a thread from the thread pool and have it’s obsolete reference replaced with one to the newly created child Container specific to the incoming request.&lt;/em&gt;&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://stuartharris4.blogspot.com/feeds/1432934887203604954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://stuartharris4.blogspot.com/2008/06/working-together-linq-to-sql.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1432934887203604954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/516084884258004070/posts/default/1432934887203604954'/><link rel='alternate' type='text/html' href='http://stuartharris4.blogspot.com/2008/06/working-together-linq-to-sql.html' title='Working together: LINQ to SQL, IRepository&amp;lt;T&amp;gt;, Unit Of Work and Dependency Injection'/><author><name>Stuart Harris</name><uri>http://www.blogger.com/profile/14746343706143223441</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0nu2PcScUGjwjORdSzI20OChAzTIzMjs2FAJOkCixlaUfF-bkNMpJwdDL6hoNW5iy3fwqghb5CfKVR5gCOCkxdIf9DbK8a6Sj68-8rPpNiexc5Zd50Lt0tNpBMm95y_4/s220/Face.png'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/stuartharris4/SGJQMPs_b1I/AAAAAAAAABo/Z4vZBQxgXhE/s72-c/image_thumb%5B8%5D.png?imgmax=800" height="72" width="72"/><thr:total>7</thr:total></entry></feed>