<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4900151497087138627</id><updated>2012-02-16T13:13:58.617+01:00</updated><category term='Threading'/><category term='Service Locator'/><category term='Entity Framework V2.00'/><category term='Dependency Injection'/><category term='Regular Expressions'/><category term='Database access'/><category term='OR-Mapper'/><category term='IoC Containers'/><category term='Refactoring'/><category term='XSD-import'/><category term='Boo AOP'/><category term='Agile persistance-solution OR-mapper refactoring'/><category term='type-safety'/><category term='regex'/><category term='Visual Studio Add-in'/><category term='SCRUM'/><category term='Cloud-computing'/><category term='Sealed classes'/><category term='Castle Windsor'/><category term='XS-import'/><category term='.NET 4.0'/><category term='Type-safe strings'/><category term='FlatWSDL'/><category term='Parallel Extensions'/><category term='NHibernate'/><category term='Windows Azure'/><category term='Patterns'/><category term='Persistance'/><category term='Domain model - database communication'/><category term='Code generation'/><category term='Factory'/><title type='text'>Information is king</title><subtitle type='html'>Thoughts on my work and profession</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>63</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6673429139927479979</id><published>2011-04-03T23:23:00.007+02:00</published><updated>2011-04-04T01:30:39.869+02:00</updated><title type='text'>Ønsker du å jobbe med meg?</title><content type='html'>&lt;p&gt;Har du krevende utfordringer, og jobber i et firma eller skal sette sammen et prosjekt, med behov for en engasjert, positiv og konkurranseinnstilt tech lead/utvikler/arkitekt? Som forventer og stiller krav, som kontinuerlig jobber mot forbedring, og som vil utvikle seg innen både teknologi og ledelse? Og som ikke minst alltid har et sterkt fokus på målet?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Kort oppsummert har jeg&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prosjekterfaring fra alle tekniske hovedområder av et IT-system. Dette er oppnådd gjennom alt fra korte utviklings- og rådgivningsoppdrag, til to og et halvt år på et større forsikringssystem.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Organisasjonserfaring gjennom halvannet år som fagsjef i Objectware/Itera Consulting med arbeidsoppgaver rundt fagledelse, fagplanlegging, arrangering av fagdager og -kvelder, intervjuer, tilbudsarbeid og kundemøter.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ekstern erfaring som tidligere leder og nåværende styremedlem av NNUG Oslo, samt foredragsholder hos NNUG, ved XP- og Smidig-konferansene, og på årets kommende Norwegian Developer Conference (NDC).&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Etter over fire meget lærerike år i Objectware/Itera Consulting har jeg nå tatt en beslutning om å bytte arbeidsgiver. Tiden i Itera er noe jeg ser svært positivt tilbake på. Jeg har fått jobbe med utrolig dyktige kolleger, fått rikelig med utfordringer internt og i prosjekter, og i det hele tatt lært veldig mye. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;For meg er det svært viktig å fortsette utviklingen. Jeg tror det gjøres best gjennom krevende utfordringer, og har du det så håper jeg du tar kontakt. Ønsker du å se mer detaljer om mine prosjekterfaringer, så er det tilgjengelig i min &lt;a href="http://bit.ly/CVRune" target="_blank"&gt;CV (pdf)&lt;/a&gt;. I tillegg forsøker følgende bloggpost å gi et innblikk i hva jeg mener er viktig i IT-prosjekter, vel og merke fra et høyt perspektiv: &lt;a href="http://bit.ly/BlogQualityInSoftware" target="_blank"&gt;link&lt;/a&gt;.&lt;/p&gt; &lt;br /&gt;&lt;p&gt;Rent praktisk er jeg i oppsigelsestid frem til 31 mai. Jeg satser derfor på at noe av det første jeg gjør for ny arbeidsgiver blir å gå på scenen på NDC i starten av juni. Ønsker du å ta nærmere kontakt er jeg tilgjengelig på mail: rune&lt;a href="http://www.google.com/recaptcha/mailhide/d?k=01En1ryLw2LolvJ1fSqSdpxQ==&amp;amp;c=hfDHveW2m49t9ZY2jODsqI8qsLFB1GxJqr3ObxB5T8I=" onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501En1ryLw2LolvJ1fSqSdpxQ\75\75\46c\75hfDHveW2m49t9ZY2jODsqI8qsLFB1GxJqr3ObxB5T8I\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Reveal this e-mail address"&gt;...&lt;/a&gt;@gmail.com, telefon: se CV, &lt;a href="http://www.linkedin.com/in/runesundling" target="_blank"&gt;LinkedIn&lt;/a&gt; og &lt;a href="http://twitter.com/RuneSundling" target="_blank"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6673429139927479979?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6673429139927479979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6673429139927479979' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6673429139927479979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6673429139927479979'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2011/04/nsker-du-jobbe-med-meg.html' title='Ønsker du å jobbe med meg?'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8258523431710109473</id><published>2011-03-20T19:06:00.002+01:00</published><updated>2011-04-03T22:31:38.351+02:00</updated><title type='text'>Quality in software – a summary</title><content type='html'>&lt;p&gt;Who should read this: Software developers or other participants in IT projects who want a high level overview of what is needed to make projects succeed, with a technical bias.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;All work in a project must be done to increase the likelihood of success. The process imposed, the roles involved, the people chosen and the technologies used should all work towards this goal.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt; For the record, I apologize for simplifying, not covering and simply forgetting important areas. I am trying to give you the pure and simple truth, however: &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;The pure and simple truth is rarely pure and never simple.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;- Oscar Wilde&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Process&lt;/h3&gt;  &lt;p&gt;IT projects are complex. The Standish Group’s Chaos Report has attempted to cover this over many years (&lt;a href="http://bit.ly/ChaosReport2009" target="_blank"&gt;2009 report in pdf&lt;/a&gt;).&amp;#160; To handle the complexities of software, the industry appears to move towards streamlining project processes in increasingly agile ways. A common denominator for this work is the well known &lt;a href="http://agilemanifesto.org/" target="_blank"&gt;manifesto for Agile Software Development&lt;/a&gt; devised in early 2001: &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;Individuals and interactions&lt;/strong&gt; over processes and tools        &lt;br /&gt;&lt;strong&gt;Working software&lt;/strong&gt; over comprehensive documentation        &lt;br /&gt;&lt;strong&gt;Customer collaboration&lt;/strong&gt; over contract negotiation        &lt;br /&gt;&lt;strong&gt;Responding to change&lt;/strong&gt; over following a plan&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;em&gt;That is, while there is value in the items on       &lt;br /&gt;the right, we value the items on the left more.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As anyone involved in real projects know, you need to adapt to changes and challenges, deliver and receive feedback on a variety of levels, and continuously work to reduce waste. You’ll &lt;a href="http://rune-sundling.blogspot.com/2010/01/walking-on-water-and-developing.html" target="_blank"&gt;never know everything in advance&lt;/a&gt;, and &lt;a href="http://rune-sundling.blogspot.com/2010/01/changes-in-software-one-of-biggest.html" target="_blank"&gt;unexpected changes will occur&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The process within IT consists of both the main methodology used and the more technical practices followed. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Overall process&lt;/h2&gt;  &lt;p&gt;The industry today is steadily working towards being agile, solving problems through iterations and improving continuously. From a developers perspective, this is usually something you will have to accept. Even if it’s not your responsibility, it doesn’t mean you couldn’t or shouldn’t influence the process. Being part of a project team means you have a responsibility for the project’s success. Communicate your concerns. Help inform your coworkers and management. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Within agile there are many different processes; Lean, Scrum, Kanban, and many more. Which is the right one? The choice depends on experience, your organization and the challenge ahead. But never forget: mix and match what works for you - being agile certainly apply to both the product created and the process used. (And be wary of certified [process]-masters. Are you sure it means what you think it does?)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Whenever you care about the results of what you are doing, skilled people are a must. But even the brightest people fail because of misunderstandings or general problems with &lt;a href="http://rune-sundling.blogspot.com/2009/01/essential-project-practices.html" target="_blank"&gt;communication&lt;/a&gt;. One very import point to focus on is to improve the feedback loop. Have the customer and business experts work close with you throughout the process, and increase the frequency of releases tenfold (At least to test environments). Training on and delivering new releases reduces the risks involved, increases the feedback from users, and enables you to deliver the right functionality at the right time.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Before moving on, I thought it proper to address a common misconception with agile - that agile equals little or no planning. I have to insist that this is a false claim, and the reality is quite the opposite. If you want to learn more, &lt;a href="http://www.infoq.com/articles/many-levels-planning-agile-project" target="_blank"&gt;this&lt;/a&gt; is a good article explaining the importance of it, and at what levels planning should occur.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Technical process&lt;/h2&gt;  &lt;p&gt;The technical process is pretty much anything that directly relates to what is produced; estimation, tasks, quality assurance, and releasing new versions. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In project and sprint planning, estimation is usually considered an important practice. Estimation is useful to consider what is involved in producing a feature, visualizing the cost of implementing it, and ensuring that everyone has a similar understanding of the scope. How estimation, planning and tasks are handled varies, and you should experiment with what method works for you. Do ensure that you work to build transparency and trust, as described in this quote from Gabrielle Benefield, Director of Agile Product Development in Yahoo!: &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;Keeping everything transparent, and letting the business know of any changes as they come up, means that the business can adapt quickly to make the best decisions. At my last company I saw us go from a state of permanent chaos, where we had an extremely ambitious roadmap but couldn’t deliver products, to a predictable state where we could genuinely sign up for projects that we could deliver. The business said they might not always like the answers (they always want things tomorrow, after all), but at least they believed our answers and were not frustrated from feeling that they were being consistently lied to.&lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The quote, and significantly more, can be found in &lt;a href="http://www.amazon.com/Agile-Estimating-Planning-Mike-Cohn/dp/0131479415" target="_blank"&gt;Agile Estimating and Planning&lt;/a&gt; by Mike Cohn.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;There will often be doubt when planning something; which technology is right, what main flow of logic is appropriate, and so on. Don’t be afraid to use prototyping to verify assumptions. Creating an end to end working example and/or ensuring that the toughest problems can be solved can save you a lot of time in the future. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I mentioned feedback earlier as a key principle. Within the technical process, this should be supported through a few good practices. Code reviews, pair programming and static code analysis are tools useful to get quick feedback on quality. Automated tests are another, with unit, integration and acceptance tests (and sometimes a few more) as common categories. &lt;a href="http://martinfowler.com/articles/continuousIntegration.html" target="_blank"&gt;Continuous integration&lt;/a&gt; is another practice that helps increase feedback and quality. By automating compilation and running of all tests for each check-in, you add another step for ensuring quality, increasing feedback and helping visualize the current state of the code. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The practices mentioned above are often introduced more from the technical personnel in the project. But to support the overall process need of more frequent releases to test and production, a number of practices are key: automating deployments, including moving code, configuring machine and web servers, handling environment specific configuration settings and setting up the database. It won’t come free of charge, but can bring about great benefits. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;A lot more can be said about improving the release and deployment process. I recommend reading the book &lt;a href="http://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912" target="_blank"&gt;Continuous Delivery&lt;/a&gt; to get a better overview. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Technology&lt;/h3&gt;  &lt;p&gt;Beyond the general practices, what is important in technical development?&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;At both higher and lower levels, having a good overview of alternatives is necessary to select the right technology or solution (Never forget the &lt;a href="http://en.wikipedia.org/wiki/Law_of_the_instrument" target="_blank"&gt;hammer nail analogy&lt;/a&gt;). It is impossible to know the details of everything, but learning of qualities plus pros and cons of alternatives enables you to better select the correct one. Subsequent tests might find your initial knowledge about the technology was wrong, but that’s why you use prototyping anyway. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;When it comes to code, I am a strong supporter of simplicity and readability. If what you’re creating can’t be understood without hassle, how is anyone going to be able to maintain it? &lt;a href="http://en.wikipedia.org/wiki/Code_refactoring" target="_blank"&gt;Refactor&lt;/a&gt; as your understanding improves or changes occur, or be aware that you will end up with code that in near or distant future will take time to understand, even more energy to change and will undoubtedly create bugs. And automate testing of anything moderately complex. Pretty please? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Beyond mastering the technologies chosen, what more is there? Never forget that your system will go into production one day. Security, logging, monitoring, error handling, integrations, multithreading, scalability, hardware and firewall issues are areas you need to focus on. Now is the time to go ahead and read &lt;a href="http://pragprog.com/titles/mnee/release-it" target="_blank"&gt;Release It!&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So much more can be said about technology and technical development, but it is hard to generalize. Find the right people and all will be good with the world. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;h3&gt;People and roles&lt;/h3&gt;  &lt;p&gt;A software project can consist of a variety of people. You can have software developers, UI specialists, database administrators, operations, business experts, testers, project leader, project owner (and a variety of other project something roles). &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;No matter what roles exist, make sure the communication is frequent between all related parties. If you can co-locate it will help reduce misunderstandings. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;a href="http://www.management30.com/book/" target="_blank"&gt;Management 3.0&lt;/a&gt; has a lot to say about leading people in IT projects. As the author says&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;I think that people are the most important parts of an organization and that managers must do all they can to keep people active, creative and motivated. &lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;     &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8258523431710109473?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8258523431710109473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8258523431710109473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8258523431710109473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8258523431710109473'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2011/03/quality-in-software.html' title='Quality in software – a summary'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-2980086857062337427</id><published>2010-08-01T23:28:00.009+02:00</published><updated>2010-08-02T12:16:39.808+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XSD-import'/><category scheme='http://www.blogger.com/atom/ns#' term='XS-import'/><category scheme='http://www.blogger.com/atom/ns#' term='FlatWSDL'/><title type='text'>Converting WCF WSDL to single file (FlatWSDL) - correctly!</title><content type='html'>&lt;p&gt;Note! This post is slightly different than most FlatWSDL posts, and fixes the bug with removing the &amp;lt;XS-import&amp;gt;’s.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The team behind WCF chose to split all generated WSDL-definitions into multiple files, one for each namespace, schema, etc. That’s a valid approach, and most modern tools support that out of the box, it’s done correctly after the WSDL standard. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;However, not all tools support it. Various blog posts discuss different tools, and in my case it was a mainframe integration that caused the problem. I needed to get WCF to output it as one file. The good news is that’s really simple. You can use either FlatWSDL by Thinktecture or FlatWSDL in WCFExtras (They’re almost identical). &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The only problem is that both solutions emit a WSDL file without appropriate &amp;lt;XS:Import&amp;gt;’s for the schemas. Many tools are able to resolve the references without the import, but not all are as forgiving. This &lt;a href="http://wcfextras.codeplex.com/Thread/View.aspx?ThreadId=49904" target="_blank"&gt;post&lt;/a&gt; describes a code change to WCFExtras that will fix it, but I’ll add mine here as well. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;What you need to do is to download one of the FlatWSDL approaches (This &lt;a href="http://weblogs.asp.net/pglavich/archive/2010/03/16/making-wcf-output-a-single-wsdl-file-for-interop-purposes.aspx" target="_blank"&gt;post&lt;/a&gt; describes it, as well as a host of others), then change the code in ExportEndpoint in FlatWsdl.cs to what I’ve included below, and you’re good to go. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)&lt;br /&gt;{&lt;br /&gt;    XmlSchemaSet generatedXmlSchemas = exporter.GeneratedXmlSchemas;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ServiceDescription generatedWsdl &lt;span class="kwrd"&gt;in&lt;/span&gt; exporter.GeneratedWsdlDocuments)&lt;br /&gt;    {&lt;br /&gt;    var referencedXmlSchemas = FindAllReferencedXmlSchemasRecursively(generatedWsdl, generatedXmlSchemas);&lt;br /&gt;        ClearWsdlOfExistingSchemas(generatedWsdl);&lt;br /&gt;        AddAllReferencedSchemas(generatedWsdl, referencedXmlSchemas);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    RemoveSchemaLocationFromXmlSchemaImports(exporter, generatedXmlSchemas);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IEnumerable&amp;lt;XmlSchema&amp;gt; FindAllReferencedXmlSchemasRecursively(ServiceDescription wsdl, XmlSchemaSet generatedXmlSchemas)&lt;br /&gt;{&lt;br /&gt;    var referencedXmlSchemas = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;XmlSchema&amp;gt;();&lt;br /&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XmlSchema schema &lt;span class="kwrd"&gt;in&lt;/span&gt; wsdl.Types.Schemas)&lt;br /&gt;    {&lt;br /&gt;        AddReferencedXmlSchemasRecursively(schema, generatedXmlSchemas, referencedXmlSchemas);&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; referencedXmlSchemas;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// Recursively extract all the list of imported&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// schemas&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;schema&amp;quot;&amp;gt;Schema to examine&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;generatedXmlSchemas&amp;quot;&amp;gt;SchemaSet with all referenced schemas&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="rem"&gt;/// &amp;lt;param name=&amp;quot;referencedXmlSchemas&amp;quot;&amp;gt;List of all referenced schemas&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddReferencedXmlSchemasRecursively(&lt;br /&gt;   XmlSchema schema,&lt;br /&gt;   XmlSchemaSet generatedXmlSchemas,&lt;br /&gt;   List&amp;lt;XmlSchema&amp;gt; referencedXmlSchemas&lt;br /&gt;   )&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XmlSchemaImport import &lt;span class="kwrd"&gt;in&lt;/span&gt; schema.Includes)&lt;br /&gt;    {&lt;br /&gt;        ICollection realSchemas = generatedXmlSchemas.Schemas(import.Namespace);&lt;br /&gt;        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XmlSchema ixsd &lt;span class="kwrd"&gt;in&lt;/span&gt; realSchemas)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!referencedXmlSchemas.Contains(ixsd))&lt;br /&gt;            {&lt;br /&gt;                referencedXmlSchemas.Add(ixsd);&lt;br /&gt;                AddReferencedXmlSchemasRecursively(ixsd, generatedXmlSchemas, referencedXmlSchemas);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ClearWsdlOfExistingSchemas(ServiceDescription wsdl)&lt;br /&gt;{&lt;br /&gt;    wsdl.Types.Schemas.Clear();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddAllReferencedSchemas(ServiceDescription wsdl, IEnumerable&amp;lt;XmlSchema&amp;gt; referencedXmlSchemas)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XmlSchema schema &lt;span class="kwrd"&gt;in&lt;/span&gt; referencedXmlSchemas)&lt;br /&gt;    {&lt;br /&gt;        wsdl.Types.Schemas.Add(schema);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RemoveSchemaLocationFromXmlSchemaImports(WsdlExporter exporter, XmlSchemaSet schemaSet)&lt;br /&gt;{&lt;br /&gt;    var mySchemaSet = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSchemaSet();&lt;br /&gt;    mySchemaSet.Add(schemaSet);&lt;br /&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XmlSchema schema &lt;span class="kwrd"&gt;in&lt;/span&gt; mySchemaSet.Schemas())&lt;br /&gt;    {&lt;br /&gt;        exporter.GeneratedXmlSchemas.Remove(schema);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-2980086857062337427?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/2980086857062337427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=2980086857062337427' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2980086857062337427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2980086857062337427'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/08/converting-wcf-wsdl-to-single-file.html' title='Converting WCF WSDL to single file (FlatWSDL) - correctly!'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4252570978970885603</id><published>2010-07-28T18:00:00.005+02:00</published><updated>2010-07-30T20:30:07.457+02:00</updated><title type='text'>Generating sample data for objects using AutoFixture, extending it with collections support, and using it as Silverlight sample data generator</title><content type='html'>&lt;p&gt;This blog post consists of three parts&lt;/p&gt;  &lt;p&gt;- On generating sample data in general&lt;/p&gt;  &lt;p&gt;- Extending AutoFixture with automatic collections generation support&lt;/p&gt;    &lt;p&gt;- Adding a sample data generator in Silverlight for Visual Studio/Blend screen previews&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;[Note: Windows Live Writer did a horrible job in transferring the post to the blog. I've fixed quite a bit on the formatting, but it's still in poor quality. Apologies for that. Let me know if you want the code samples without the formatting]&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;    &lt;h3&gt;Generating sample data in general&lt;/h3&gt;  &lt;p&gt;Creating objects with sample data is a challenge developers often need to handle. The most common use case is for testing purposes, where you need an object with various values set. Some might be important, but many just need to be set to anything (Also called an &lt;a href="http://blogs.msdn.com/b/ploeh/archive/2008/11/17/anonymous-variables.aspx" target="_blank"&gt;anonymous variable&lt;/a&gt;).   &lt;/p&gt;&lt;br /&gt;&lt;p&gt;I’ve seen and used various solutions for this. Often you see it either done manually, by an &lt;a href="http://martinfowler.com/bliki/ObjectMother.html" target="_blank"&gt;object mother&lt;/a&gt;, with &lt;a href="http://elegantcode.com/2008/04/26/test-data-builders-refined/" target="_blank"&gt;test data builders&lt;/a&gt;, or by loading existing objects from a database. Many people start out writing a simple reflection tool to handle it, but stops a few hours down the road once the actual complexity involved becomes apparent.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;I had a new use case for it this time, and wanted to avoid many of the problems with the solutions above. After searching for and trying various reflection based tools, I found &lt;a href="http://autofixture.codeplex.com/" target="_blank"&gt;AutoFixture&lt;/a&gt;, and was impressed from the get-go. It pretty much does exactly what you’d expect, and has a clean interface as well. Some examples:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;- Creating an anonymous string&lt;/em&gt;&lt;/p&gt;  &lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;   &lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;     &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;var anonymousText = fixture.CreateAnonymous&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Result:&lt;/p&gt;- anonymousText: aa48c714-6c6a-4ac4-9c27-3658c9e78d5f&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;- Creating an anonymous object&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;    &lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; height: 164px; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; Person&lt;br /&gt;&lt;/pre&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;{&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt; Name { get; set; }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; Age { get; set; }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;..&lt;/pre&gt;&lt;br /&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;var personWithAnonymousData = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; Fixture().CreateAnonymous&amp;lt;Person&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;Result:&lt;p&gt;- Name: Nameb7c2a9fc-a5b0-4836-83d9-be1b057e0ff1&lt;/p&gt;&lt;p&gt;- Age: 1&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Take a look a the AutoFixture &lt;a href="http://autofixture.codeplex.com/wikipage?title=CheatSheet&amp;amp;referringTitle=Home" target="_blank"&gt;cheat sheat&lt;/a&gt; for a number of good examples. There’s many things you can do to customize the behavior and output.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;That covers the introduction to AutoFixture. If you need a sample data creator, for test data or other purposes, I advice you to check it out. Over to the next point. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Extending AutoFixture with automatic collections generation support&lt;/h3&gt;&lt;p&gt;There was one feature I was missing in AutoFixture that I really wanted. If an object has a collection (, list, or any other sort of .NET collection) of something, that collection will only be initialized to an empty collection automatically. If I do a change to the Person object and rerun, the PhoneNumbers list below will be an empty list of strings.&lt;br /&gt;&lt;/p&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; Person&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;{&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt; Name { get; set; }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; Age { get; set; }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; List&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt; PhoneNumbers { get; set; }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;AutoFixture have functionality to handle this. If you run the line below first..&lt;/p&gt;  &lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;br /&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;fixture.Register(() =&amp;gt; fixture.CreateMany&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt;().ToList());&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;..then the output of PhoneNumbers will be something similar to: &lt;/p&gt;&lt;p&gt;[0]: 635bc212-8d16-4029-8423-1f45016fe020&lt;/p&gt;&lt;p&gt;[1]: fcbed54b-94f6-4eea-b773-e7ec5e75b6dd&lt;/p&gt;&lt;p&gt;[2]: 814c120a-7e9c-487a-b99e-9e23d9d511b0&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;However, I would like this to be handled automatically. Doing it the AutoFixture-way you’ll need to know the internal structure of a class to define that it should handle a certain collection. Another problem is collection interfaces. If PhoneNumbers was defined as IList&amp;lt;string&amp;gt;, I would be forced to define it since it causes a runtime exception of: &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;“AutoFixture was unable to create an instance from System.Collections.Generic.IList`1[System.String], most likely because it has no public constructor.”&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So I set out to see if I could extend AutoFixture to handle collections automatically. Seemed like a fun enough way of getting to know AutoFixture better as well as some good reflection fun. The requirements I set was to handle generic collections and interfaces to collections automatically. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;First how to use it (Only the second line is new):&lt;/p&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;var fixture = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; Fixture();&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;fixture.Customizations.Add(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; CollectionsGenerator(fixture));&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;var personWithAnonymousData = fixture.CreateAnonymous&amp;lt;Person&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The new CollectionsGenerator:&lt;/p&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;br /&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// Support for handling automatic generation of anonymous data for collections&lt;/span&gt;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; CollectionsGenerator : ISpecimenBuilder&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum5"&gt;   5:&lt;/span&gt; {&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;readonly&lt;/span&gt; Fixture _parentFixture;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum7"&gt;   7:&lt;/span&gt;  &lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: rgb(0, 128, 0);"&gt;/// &amp;lt;param name="parentFixture"&amp;gt;Requires parentFixture to ensure existing options are used.&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; CollectionsGenerator(Fixture parentFixture)&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum11"&gt;  11:&lt;/span&gt;         _parentFixture = parentFixture;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum13"&gt;  13:&lt;/span&gt;  &lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; Create(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request, ISpecimenContext context)&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum15"&gt;  15:&lt;/span&gt;     {&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum16"&gt;  16:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt; (!ReflectionHelper.IsGenericDotNetCollectionOrInterface(request))&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum17"&gt;  17:&lt;/span&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; NoSpecimen(request);&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum18"&gt;  18:&lt;/span&gt;  &lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum19"&gt;  19:&lt;/span&gt;         Type collectionType;&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt; (ReflectionHelper.ObjectIsADotNetCollectionInterface(request))&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum21"&gt;  21:&lt;/span&gt;             collectionType = ReflectionHelper.GetConcreteCollectionTypeToMatchInterface(request);&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum22"&gt;  22:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;else&lt;/span&gt;&lt;/pre&gt;        &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum23"&gt;  23:&lt;/span&gt;             collectionType = ReflectionHelper.GetUnderlyingSystemType(request);&lt;/pre&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum24"&gt;  24:&lt;/span&gt;  &lt;/pre&gt;                    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum25"&gt;  25:&lt;/span&gt;         var returnCollection = (IList)Activator.CreateInstance(collectionType);&lt;span style="color: rgb(96, 96, 96);" id="lnum26"&gt;&lt;br /&gt;26:&lt;/span&gt;  &lt;span style="color: rgb(96, 96, 96);" id="lnum27"&gt;&lt;br /&gt;27:&lt;/span&gt;         AddAnonymousValuesToCollection(returnCollection, _parentFixture);&lt;span style="color: rgb(96, 96, 96);" id="lnum28"&gt;&lt;br /&gt;28:&lt;/span&gt;         &lt;span style="color: rgb(96, 96, 96);" id="lnum29"&gt;&lt;br /&gt;29:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; returnCollection;&lt;span style="color: rgb(96, 96, 96);" id="lnum30"&gt;&lt;br /&gt;30:&lt;/span&gt;     }&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum31"&gt;  31:&lt;/span&gt;  &lt;span style="color: rgb(96, 96, 96);" id="lnum32"&gt;&lt;br /&gt;32:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; AddAnonymousValuesToCollection(IList collection, Fixture parentFixture)&lt;/pre&gt;    &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum33"&gt;  33:&lt;/span&gt;     {&lt;span style="color: rgb(96, 96, 96);" id="lnum34"&gt;&lt;br /&gt;34:&lt;/span&gt;         Type genericType = collection.GetType().GetGenericArguments()[0];&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum35"&gt;  35:&lt;/span&gt;         var createAnonymousMethod = &lt;span style="color: rgb(0, 0, 255);"&gt;typeof&lt;/span&gt;(SpecimenFactory).GetMethod(&lt;span style="color: rgb(0, 96, 128);"&gt;"CreateAnonymous"&lt;/span&gt;, &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; Type[] { &lt;span style="color: rgb(0, 0, 255);"&gt;typeof&lt;/span&gt;(ISpecimenBuilderComposer) }).MakeGenericMethod(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt;[] { genericType });&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum36"&gt;  36:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; i = 0; i &amp;lt; parentFixture.RepeatCount; i++)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum37"&gt;  37:&lt;/span&gt;         {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum38"&gt;  38:&lt;/span&gt;             collection.Add(createAnonymousMethod.Invoke(&lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;, &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; ISpecimenBuilderComposer[] { parentFixture }));&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum39"&gt;  39:&lt;/span&gt;         }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum40"&gt;  40:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum41"&gt;  41:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;And an accompanying ReflectionHelper:&lt;br /&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; ReflectionHelper&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;const&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt; UnderlyingSystemTypeString = &lt;span style="color: rgb(0, 96, 128);"&gt;"UnderlyingSystemType"&lt;/span&gt;;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum4"&gt;   4:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; CanRetrieveUnderlyingSystemTypeFromObject(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; input)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum6"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum7"&gt;   7:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; (input != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum8"&gt;   8:&lt;/span&gt;                &amp;amp;&amp;amp; (input.GetType().GetProperty(UnderlyingSystemTypeString) != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum9"&gt;   9:&lt;/span&gt;                &amp;amp;&amp;amp; (input.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(input, &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;) != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum10"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum11"&gt;  11:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; InputIsAssignableFrom(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request, Type ofType)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum13"&gt;  13:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum14"&gt;  14:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; (request != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum15"&gt;  15:&lt;/span&gt;                &amp;amp;&amp;amp; (request.GetType().GetProperty(UnderlyingSystemTypeString) != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum16"&gt;  16:&lt;/span&gt;                &amp;amp;&amp;amp; (request.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(request, &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;) != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum17"&gt;  17:&lt;/span&gt;                &amp;amp;&amp;amp; (ofType.IsAssignableFrom((Type)request.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(request, &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;)));&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum18"&gt;  18:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum19"&gt;  19:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum20"&gt;  20:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; Type GetUnderlyingSystemType(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; input)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum21"&gt;  21:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum22"&gt;  22:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; (Type)input.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(input, &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum23"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum24"&gt;  24:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum25"&gt;  25:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; ObjectHasGenericTypeSpecified(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; input)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum26"&gt;  26:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum27"&gt;  27:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; GetUnderlyingSystemType(input).IsGenericType &amp;amp;&amp;amp; GetUnderlyingSystemType(input).GetGenericArguments().Length &amp;gt; 0;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum28"&gt;  28:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum29"&gt;  29:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum30"&gt;  30:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; IsGenericDotNetCollectionOrInterface(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum31"&gt;  31:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum32"&gt;  32:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt; (!CanRetrieveUnderlyingSystemTypeFromObject(request))&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum33"&gt;  33:&lt;/span&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum34"&gt;  34:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum35"&gt;  35:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;    (ObjectIsADotNetCollection(request) || ObjectIsADotNetCollectionInterface(request)) &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum36"&gt;  36:&lt;/span&gt;                &amp;amp;&amp;amp; (ObjectHasGenericTypeSpecified(request));&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum37"&gt;  37:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum38"&gt;  38:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum39"&gt;  39:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; ObjectIsADotNetCollection(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum40"&gt;  40:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum41"&gt;  41:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; InputIsAssignableFrom(request, &lt;span style="color: rgb(0, 0, 255);"&gt;typeof&lt;/span&gt;(IList));&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum42"&gt;  42:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum43"&gt;  43:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum44"&gt;  44:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt; ObjectIsADotNetCollectionInterface(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum45"&gt;  45:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum46"&gt;  46:&lt;/span&gt;         var objectTypeName = GetUnderlyingSystemType(request).ToString();&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum47"&gt;  47:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum48"&gt;  48:&lt;/span&gt;         var dotNetCollectionTypes = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;&amp;gt; &lt;span style="color: rgb(0, 128, 0);"&gt;//.NET Collections&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum49"&gt;  49:&lt;/span&gt;                     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum50"&gt;  50:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.IList"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum51"&gt;  51:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.IEnumerable"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum52"&gt;  52:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.IEnumerator"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum53"&gt;  53:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.ICollection"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum54"&gt;  54:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.ISet"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum55"&gt;  55:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.IList"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum56"&gt;  56:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.IEnumerable"&lt;/span&gt;,&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum57"&gt;  57:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.IEnumerator"&lt;/span&gt;,&lt;span style="font-family:Georgia,serif;"&gt;&lt;/span&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum58"&gt;  58:&lt;/span&gt;                     &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.ICollection"&lt;/span&gt;, &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum59"&gt;  59:&lt;/span&gt;                     };&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum60"&gt;  60:&lt;/span&gt;         &lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum61"&gt;  61:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; dotNetCollectionTypes.Any(objectTypeName.Contains);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum62"&gt;  62:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum63"&gt;  63:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum64"&gt;  64:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; Type GetConcreteListTypeToMatchInterface(&lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt; request)&lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum65"&gt;  65:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum66"&gt;  66:&lt;/span&gt;         Type genericType = GetUnderlyingSystemType(request).GetGenericArguments()[0];&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum67"&gt;  67:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum68"&gt;  68:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt; genericListTypeName = &lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.Generic.List`1"&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum69"&gt;  69:&lt;/span&gt;                                      + &lt;span style="color: rgb(0, 96, 128);"&gt;"[["&lt;/span&gt; + genericType.AssemblyQualifiedName + &lt;span style="color: rgb(0, 96, 128);"&gt;"]]"&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum70"&gt;  70:&lt;/span&gt;                                      + &lt;span style="color: rgb(0, 96, 128);"&gt;","&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum71"&gt;  71:&lt;/span&gt;                                      + Type.GetType(&lt;span style="color: rgb(0, 96, 128);"&gt;"System.Collections.IList"&lt;/span&gt;).Assembly.FullName;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum72"&gt;  72:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; Type.GetType(genericListTypeName);&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum73"&gt;  73:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum74"&gt;  74:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Note that this isn’t release quality. There’s a few issues, like with recursion if a complex type contains an instance of itself, and the way .NET collections are identified.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;h3&gt;Adding a sample data generator in Silverlight for Visual Studio/Blend screen previews&lt;/h3&gt;The actual  use case I was trying to solve was creating automatic sample data for XAML pages in Silverlight. This would enable me to better see how pages looked in Visual Studio and Blend, and a way of testing data bindings as well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Note that AutoFixture doesn’t support Silverlight just yet, but there is a &lt;a href="http://autofixture.codeplex.com/SourceControl/network" target="_blank"&gt;fork&lt;/a&gt; available that supports it (If you want to use a newer version, you only need to do a couple of changes to trunk to make it work).&lt;br /&gt;&lt;/p&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;I wanted a more natural interface for the sample data, so I created a SampleDataGenerator class:&lt;/p&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// Creates sample data for object or collection of objects recursively&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: rgb(0, 128, 0);"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; SampleDataGenerator&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum5"&gt;   5:&lt;/span&gt; {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; T GenerateObjectWithData&amp;lt;T&amp;gt;()&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum7"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum8"&gt;   8:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;().CreateAnonymous&amp;lt;T&amp;gt;();&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum9"&gt;   9:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum10"&gt;  10:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; T GenerateObjectWithData&amp;lt;T&amp;gt;(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; collectionItemAmount)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum12"&gt;  12:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum13"&gt;  13:&lt;/span&gt;         var fixture = CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;();&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum14"&gt;  14:&lt;/span&gt;         fixture.RepeatCount = collectionItemAmount; &lt;span style="color: rgb(0, 128, 0);"&gt;//Object count generated per list&lt;/span&gt;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum15"&gt;  15:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; fixture.CreateAnonymous&amp;lt;T&amp;gt;();&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum16"&gt;  16:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum17"&gt;  17:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; CreateMany&amp;lt;T&amp;gt;()&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum19"&gt;  19:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;().CreateMany&amp;lt;T&amp;gt;();&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum21"&gt;  21:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum22"&gt;  22:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; CreateMany&amp;lt;T&amp;gt;(T seed)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum23"&gt;  23:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum24"&gt;  24:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;().CreateMany(seed);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum25"&gt;  25:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum26"&gt;  26:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum27"&gt;  27:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; CreateMany&amp;lt;T&amp;gt;(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; count)&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum28"&gt;  28:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum29"&gt;  29:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;().CreateMany&amp;lt;T&amp;gt;(count);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum30"&gt;  30:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum31"&gt;  31:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum32"&gt;  32:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; CreateMany&amp;lt;T&amp;gt;(T seed, &lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; count)&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum33"&gt;  33:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum34"&gt;  34:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;().CreateMany&amp;lt;T&amp;gt;(seed, count);&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum35"&gt;  35:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum36"&gt;  36:&lt;/span&gt;  &lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum37"&gt;  37:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; Fixture CreateFixtureWithDefaultSetup&amp;lt;T&amp;gt;()&lt;/pre&gt;   &lt;pre style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible; font-family: 'Courier New',courier,monospace; font-size: 8pt; color: black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum38"&gt;  38:&lt;/span&gt;     {&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum39"&gt;  39:&lt;/span&gt;         var fixture = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; Fixture();&lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum40"&gt;  40:&lt;/span&gt;         fixture.Customizations.Add(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; StringGenerator(() =&amp;gt; &lt;span style="color: rgb(0, 96, 128);"&gt;""&lt;/span&gt;));&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum41"&gt;  41:&lt;/span&gt;         fixture.Customizations.Add(&lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; CollectionsGenerator(fixture));&lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum42"&gt;  42:&lt;/span&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; fixture;&lt;/pre&gt;   &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum43"&gt;  43:&lt;/span&gt;     }&lt;/pre&gt;   &lt;pre face="'Courier New',courier,monospace" size="8pt" color="black" style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum44"&gt;  44:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;At the bottom of the code above I have included use of the CollectionsGenerator class. I also changed the default behavior of StringGenerator, so it only outputs the property name instead of property name + guid.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;You can then use it in a sample object that inherits the ViewModel:&lt;/p&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;br /&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;                  &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: white; margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum1"&gt; 1:&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; EditPersonSampleData : EditPersonViewModel&lt;span style="color: rgb(96, 96, 96);" id="lnum2"&gt;&lt;br /&gt;2:&lt;/span&gt; {&lt;span style="color: rgb(96, 96, 96);" id="lnum3"&gt;&lt;br /&gt;3:&lt;/span&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; EditPersonSampleData()&lt;span style="color: rgb(96, 96, 96);" id="lnum4"&gt;&lt;br /&gt;4:&lt;/span&gt;     {&lt;span style="color: rgb(96, 96, 96);" id="lnum5"&gt;&lt;br /&gt;5:&lt;/span&gt;         Person = SampleDataGenerator.GenerateObjectWithData&amp;lt;Person&amp;gt;();&lt;span style="color: rgb(96, 96, 96);" id="lnum6"&gt;&lt;br /&gt;6:&lt;/span&gt;     }&lt;span style="color: rgb(96, 96, 96);" id="lnum7"&gt;&lt;br /&gt;7:&lt;/span&gt; }&lt;/pre&gt;&lt;br /&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;And then in the EditPersonView.xaml, include:&lt;br /&gt;&lt;div   style="border: 1px solid silver; text-align: left; padding: 4px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 20px 0px 10px; width: 97.5%; direction: ltr; max-height: 200px; overflow: auto; cursor: text;font-family:'Courier New',courier,monospace;font-size:8pt;" id="codeSnippetWrapper"&gt;&lt;div    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;" id="codeSnippet"&gt;&lt;br /&gt;       &lt;pre    style="border-style: none; text-align: left; padding: 0px; line-height: 12pt; background-color: rgb(244, 244, 244); margin: 0em; width: 100%; direction: ltr; overflow: visible;font-family:'Courier New',courier,monospace;font-size:8pt;color:black;"&gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum1"&gt; 1:&lt;/span&gt; xmlns:vm=&lt;span style="color: rgb(0, 96, 128);"&gt;"clr-namespace:SomeNamespace.EditPerson"&lt;/span&gt; &lt;span style="color: rgb(96, 96, 96);" id="lnum2"&gt;&lt;br /&gt;2:&lt;/span&gt;  &lt;span style="color: rgb(96, 96, 96);" id="lnum3"&gt;&lt;br /&gt;3:&lt;/span&gt; ...&lt;span style="color: rgb(96, 96, 96);" id="lnum4"&gt;&lt;br /&gt;4:&lt;/span&gt;  &lt;span style="color: rgb(96, 96, 96);" id="lnum5"&gt;&lt;br /&gt;5:&lt;/span&gt; &amp;lt;Grid x:Name=&lt;span style="color: rgb(0, 96, 128);"&gt;"LayoutRoot"&lt;/span&gt; Background=&lt;span style="color: rgb(0, 96, 128);"&gt;"White"&lt;/span&gt; d:DataContext=&lt;span style="color: rgb(0, 96, 128);"&gt;"{d:DesignInstance Type=vm:EditPersonSampleData, IsDesignTimeCreatable=True}"&lt;/span&gt;&amp;gt;&lt;span style="color: rgb(96, 96, 96);" id="lnum6"&gt;&lt;br /&gt;6:&lt;/span&gt;  &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&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;br /&gt;&lt;/p&gt;&lt;p&gt;That’s all you need to get sample data visible in a XAML viewer. Good way of checking that the interface looks OK and that the binding is set up correctly.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;Vote &lt;a href="http://autofixture.codeplex.com/workitem/4199" target="_blank"&gt;here&lt;/a&gt; to get similar support in the actual AutoFixture product. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4252570978970885603?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4252570978970885603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4252570978970885603' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4252570978970885603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4252570978970885603'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/07/generating-sample-data-for-objects.html' title='Generating sample data for objects using AutoFixture, extending it with collections support, and using it as Silverlight sample data generator'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8940860471368449407</id><published>2010-01-23T18:32:00.001+01:00</published><updated>2010-01-23T18:32:19.811+01:00</updated><title type='text'>Changes in software – Different developers over time for a long-running project</title><content type='html'>&lt;p&gt;To do changes to software you need to understand it. You need to understand the exact piece of code you are changing, you need an overview of the system to be aware of any dependent parts, and you need to understand the technologies in use. In the real world you can also end up with a few more difficulties. You need to understand why things work the way they do. Will the changes you are imposing break existing logic? Does any clear documentation of how things work exist, or that you'll need to update? Can you trust the documentation that does exist? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Once you have a &amp;quot;long-running project&amp;quot; you get the added difficulty of handling information stored only in a developers or business specialists head. Your best option is to have the same developers working on the project for its lifetime. That can be challenging in terms of getting the right people in on it. When that's not possible you need to make sure you don't end up in a situation where the knowledge is lost. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The state of the actual code is perhaps the most important. Documentation will always be hard to keep up to date, and the best description of what you have is your code. It's essential that it is well structured and readable to make changes possible. Do refactorings when it helps clarify code, or when your understanding of the problem or domain changes. Write small and well named automatic tests that each verify a single piece of behavior and explains why and in what context. For this context, the tests will help clarify how a piece of code works and is intended to be used (Do you know what AAA is? If not, it's about time you do). &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Consider increasing the truck factor of your code - meaning, how many people must be hit by a truck before a piece of information is lost. This has a lot to do with how you handle code ownership. Does individuals only make changes in their piece of the code, are there module leaders that supervise changes to parts of the system, or do you have a form of collective code ownership (XP's view on collective ownership: http://www.extremeprogramming.org/rules/collective.html)? Like every part of software development, there is no answer that is correct in every situation, but strong individual ownership is most likely to cause problems in my view. The truck factor is extremely low, a sort of &amp;quot;me versus they&amp;quot; mentality can lead to things falling between two chairs. Few developers knowing a piece of code means fewer can do changes to it if problems arise, and different parts of a system can end up being developed quite differently.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Documentation is another area. Do you document at all? Only high level requirements? Sequence or collaboration diagrams? Is the documentation kept up to date? No business decisions hidden in mail discussions or in developer or business users heads? In meeting minutes? This is such a tough area. I haven't quite made up my mind about this yet - but I do know one thing - keeping documentation truly up to date is extremely challenging. You can certainly try to document everything, but is it worth it in terms of ROI? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;When a developer do choose to leave a project, make sure you work to capture as much knowledge as possible. Hopefully most of the knowledge of the developer is already shared with the team, but try to capture the rest as much as possible. It will cost a lot more to try and understand something later on.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8940860471368449407?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8940860471368449407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8940860471368449407' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8940860471368449407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8940860471368449407'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/changes-in-software-different.html' title='Changes in software – Different developers over time for a long-running project'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1299069148477513348</id><published>2010-01-17T21:05:00.017+01:00</published><updated>2010-01-17T21:24:01.965+01:00</updated><title type='text'>Changes in software - One of the biggest challenges of software development</title><content type='html'>&lt;p&gt;Changes to software has been a problem since the dawn of computers, and it still is a challenge with every piece of software developed. Perhaps the biggest part of creating software is changing or expanding existing code. So handling changes is something we have to deal with all the time. It's the maintainability aspect of software development. The problem is that there are so many challenges involved, so many things that can go wrong. But do you know what the worst problem is? The fact that a lot of developers have very little focus on the issue in general, including the reasons behind it. &lt;/p&gt;&lt;img src='http://img11.imageshack.us/img11/6510/changemanagement1.jpg' border='0' width='512' height='384'/&gt;  &lt;p&gt;   &lt;br /&gt;I tried to come up with a few of the top of my head, and listed almost thirty easily (Even without going into nitty gritty coding issues). No wonder it's hard to handle. There's no silver bullet to fix many of these issues, but as with everything else in life - you need to know about it to be able to do something with it.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Here's a number of things that affects and complicates changes in software:     &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Project &lt;/p&gt; &lt;ul&gt;&lt;li&gt;Many different developers over time&lt;/li&gt;&lt;li&gt;Legacy codebase&lt;/li&gt;&lt;li&gt;External system dependencies&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;Person&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Developer with limited understanding of code in general&lt;/li&gt;    &lt;li&gt;Developer with limited understanding of the projects code and architecture&lt;/li&gt;    &lt;li&gt;Unmotivated developer&lt;/li&gt;    &lt;li&gt;Changes done just before end of day/end of week/end of year&lt;/li&gt;    &lt;li&gt;Different quality of developers&lt;/li&gt;    &lt;li&gt;Misunderstanding the time it takes to write quality code&lt;/li&gt;    &lt;li&gt;Not thoroughly understanding a problem&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Code&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The danger of quick fixes/hacks &lt;/li&gt;    &lt;li&gt;Lack of understanding of how software rot &lt;/li&gt;    &lt;li&gt;Unreadable code. &lt;/li&gt;    &lt;li&gt;High coupling in the system. Making a change in code that is used many places has a higher risk. &lt;/li&gt;    &lt;li&gt;Complex architecture (Hard to understand or wrong for the problem at hand)&lt;/li&gt;    &lt;li&gt;Duplicate code&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Business&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Illogical business logic &lt;/li&gt;    &lt;li&gt;Unavailable business people     &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Process&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt; Time (Quality - if time permits)&lt;/li&gt;    &lt;li&gt;Bug acceptance&lt;/li&gt;    &lt;li&gt;Developer not feeling the pain of fixing production bugs&lt;/li&gt;    &lt;li&gt;Task-switching developer&lt;/li&gt;    &lt;li&gt;Picking up problems caused by changes&lt;/li&gt;    &lt;li&gt;Lack of testing&lt;/li&gt;    &lt;li&gt;Big bang releases / seldom releases&lt;/li&gt;    &lt;li&gt;Individual code ownership&lt;/li&gt;    &lt;li&gt;Refactoring / Not refactoring     &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Adding additional features at end of test/iteration/project&lt;/li&gt; &lt;/ul&gt;  &lt;br/&gt;&lt;p&gt;This post would get way too long if I were to cover all the reasons in detail, so I'm rather going to cover various individual ones in separate posts.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Did you miss something on the list? &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1299069148477513348?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1299069148477513348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1299069148477513348' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1299069148477513348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1299069148477513348'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/changes-in-software-one-of-biggest.html' title='Changes in software - One of the biggest challenges of software development'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8830453623088317828</id><published>2010-01-14T23:06:00.001+01:00</published><updated>2010-01-14T23:06:33.380+01:00</updated><title type='text'>Real programmers don't comment their code. If it was hard to write, it should be hard to understand</title><content type='html'>&lt;p&gt;Now that's just a plain lie. Real programmers do comment their code - though only certain parts of it.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;First of all, an important rule: Your code should be so readable that you don't need comments to understand what it does.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Comments are a problem because they    &lt;br /&gt;- might not get get updated when the code changes.     &lt;br /&gt;- become an excuse to write unreadable code.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;If you can't trust that the comment is correct, you'll have to go into a method to understand what it does. Once you do that you might have to step even further down into other methods, and soon you'll forget what you were doing initially.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Justifying unreadable code with comments is heresy. You should not need to write comments to explain what a piece of code does. What do you need to do if you have code that does need additional comments? Refactor! Often the text you would put in comments can be used as method names instead. Don't forget Joshua Kerievsky's tip in &lt;a href="http://www.industriallogic.com/xp/refactoring/" target="_blank"&gt;Refactoring to Patterns&lt;/a&gt;:    &lt;br /&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;What is the preferred size of small methods? I would say ten lines of code or fewer, with the majority of your methods using one to five lines of code. If you make the vast majority of a system's methods small, you can have a few methods that are larger, as long as they are simple to understand and don't contain duplication.&amp;quot; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Don't be afraid of small methods with a readable signature. You have intellisense to help finish method names, and the performance hit of having many methods is negligible, so none of those arguments hold any value. Does it feel like your classes end up with too many methods? There's a good change they're doing too much. Remember to use the Single Responsibility Principle on both classes and methods - they should be responsible for doing only one thing, and should have one, and only one, reason to change. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;When are comments appropriate?   &lt;br /&gt;- At major boundaries, for instance with libraries or at service contracts, giving context or similar.     &lt;br /&gt;- Clarification or expressing intent, if you fail to do it in code    &lt;br /&gt;- Warnings or particular notifications    &lt;br /&gt;- Regular expressions, if you have to use them    &lt;br /&gt;- TODO's, sparingly.     &lt;br /&gt;- When you have no other options.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;There is always a need for comments in you code. The rule should be to not use them, but if you have a good reason - go right ahead.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;I think Uncle Bob says it well in &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882" target="_blank"&gt;Clean Code&lt;/a&gt;:     &lt;br /&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;The proper use of comments is to compensate for our failure to express ourself in code. Note that I used the word &lt;i&gt;failure&lt;/i&gt;. I meant it. Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration. [...] Every time you express yourself in code, you should pat yourself on the back. Every time you write a comment, you should grimace and feel the failure of your ability of expression.&amp;quot;&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8830453623088317828?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8830453623088317828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8830453623088317828' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8830453623088317828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8830453623088317828'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/real-programmers-don-comment-their-code.html' title='Real programmers don&amp;#39;t comment their code. If it was hard to write, it should be hard to understand'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-570063787759033699</id><published>2010-01-10T23:38:00.008+01:00</published><updated>2010-01-11T12:58:59.962+01:00</updated><title type='text'>Object Orientation revisited – Business layer patterns</title><content type='html'>&lt;p&gt;Object orientation is a fascinating topic. It is one of the core concepts for a major part of developers today, yet the understanding and the inclusion of it in our day to day work varies greatly. Even though many believe they do the same. 'Cause everyone is working object oriented with an object oriented language, right? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;We had a day back in December at Objectware where we revisited object orientation, and its implications for our work. The day was structured with some presentations first, a good deal of group work, a reflection on the work, followed by a general discussion in the end. We had a continuous focus on discussions and experience sharing throughout. I started of with a session on general everyone-should-know information, more of a recap or introduction if you will, and then brought the focus to the use of object orientation in structuring our business logic, centralized or delegated design, and so on. A few colleagues of me followed on with topics concerning cohesion and coupling, information hiding and composition vs inheritance. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I thought I'd share some of the content of my presentation here. It's certainly not a new topic, it has been blogged and written about countless times, but still I meet a lot of variation on the knowledge in this area. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;First of all - how is this valuable to you? Knowing how to structure your business logic both in various forms of applications, but also varying internally in an application, is paramount in ending up with an application that doesn't fight you continuously. In designing every application we want to: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Create an architecture that meets all technical and operational demands &lt;/li&gt;    &lt;li&gt;AND that solves all quality attributes like performance, security and maintainability well &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;The architect should set standards concerning the business logic layer, but I've seen more than one architecture transform into something very different because of varying knowledge on this. It's always important to know the main differences so you can take informed decisions. This is one of those areas that most software developers should know - especially those that work on applications containing more than a trivial amount of business logic.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Introducing OO&lt;/h3&gt;  &lt;p&gt;Object orientation is about core principles like abstraction, composition, inheritance, encapsulation, polymorphism and decoupling. Several things can be said about this style of programming, like    &lt;br /&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;”&lt;b&gt;Division of responsibilities &lt;/b&gt;for an application or system into individual reusable and self-sufficient objects, each containing the &lt;b&gt;data and the behavior &lt;/b&gt;relevant to the object.”&lt;/p&gt;    &lt;p&gt;     &lt;br /&gt;”An objectoriented design views a system as a series of &lt;b&gt;cooperating objects&lt;/b&gt;, instead of a set of routines or procedural instructions.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;In general it can be said that Object Orientation should be considered when:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;br /&gt;”You want to model your application based on &lt;b&gt;real world objects and actions&lt;/b&gt;, or you already have suitable objects and classes that match the design and operational requirements. The object-oriented style is also suitable if you must &lt;b&gt;encapsulate logic and data together&lt;/b&gt; in reusable components or you have &lt;b&gt;complex business logic&lt;/b&gt; that requires abstraction and dynamic behavior.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;(All quotes from &lt;a href="http://msdn.microsoft.com/en-us/library/dd673617.aspx" target="_blank"&gt;Microsoft Application Architecture Guide, 2nd Edition&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;And you continuously work to &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;find the right abstraction of the real world for your problem &lt;/li&gt;    &lt;li&gt;find fitting objects &lt;/li&gt;    &lt;li&gt;find the right place to put code &lt;/li&gt;    &lt;li&gt;rework the code at all times to make sure it is correct based on your current understanding &lt;/li&gt;    &lt;li&gt;favor low coupling &lt;/li&gt;    &lt;li&gt;limit duplication &lt;/li&gt;    &lt;li&gt;make each object work on one thing only - ensuring high cohesion &lt;/li&gt;    &lt;li&gt;work to have a test friendly design&amp;#160; &lt;/li&gt;    &lt;li&gt;and generally try to keep your code as to-the-point as possible, all the time ensuring that adding further behavior and extending the current functionality is as painless as possible (without over engineering of course :) ) &lt;/li&gt;    &lt;li&gt;and certainly much more than this.. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;How you structure your business layer certainly has a say in how well and how easily you can achieve these things.     &lt;br /&gt;You traditionally have four main ways of structuring this logic: &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Procedurally oriented with &lt;b&gt;Transaction script&lt;/b&gt; or &lt;b&gt;Table module&lt;/b&gt;.     &lt;br /&gt;or     &lt;br /&gt;Object oriented with &lt;b&gt;Active record&lt;/b&gt; or &lt;b&gt;Domain model&lt;/b&gt;.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Let's take a closer look at each.. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Transaction script &lt;/h3&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;”Organizes business logic by procedures where each procedure handles a single request from the presentation.” &lt;/p&gt;    &lt;p&gt;Martin Fowler, &lt;a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;    &lt;br /&gt;Transaction script follows the current structure: &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt; &lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img3.imageshack.us/i/transactionscript.png/'&gt;&lt;img src='http://img3.imageshack.us/img3/7636/transactionscript.png' border='0' width='324' height='187' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Note that this is an extremely simplified example. Using transaction script you certainly utilize all you know about class design and move logic into where it fits best, the main point I'm trying to make is that you have a central place to control the flow. The CreateOrder method controls what logic will happen from start to end. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;If you use this all the way, the business layer will consist of a number of procedures that each implements one action from the user interface. Good design in this context is about minimizing duplication at the same time as meeting all demands. This has nothing to do with a database transaction, but refers to one monolithic logical operation. It is not uncommon to create one business component per database table. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The positive sides with it is that it's easy to understand and maps well to the flow of a user story/use case. But it breaks down on complicated logic, can be hard to test as it does many things, and can lead to duplicated code.     &lt;br /&gt;Being popular in general, it the .NET world it was quickly replaced in popularity by....&lt;/p&gt;  &lt;h5&gt;&amp;#160;&lt;/h5&gt;&lt;br/&gt;  &lt;h3&gt;Table module&lt;/h3&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;”A single instance that handles the business logic for all rows in a database table or view.”&lt;/p&gt;    &lt;p&gt;Martin Fowler, &lt;a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;  &lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/tablemodule.png/'&gt;&lt;img src='http://img36.imageshack.us/img36/1720/tablemodule.png' border='0' width='338' height='430'/&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The Table module is built around a table of data. Its perspective is similar to that of Table script, except the focus is on a group of data. Operations are often designed as methods on an object that represents a table of rows. Because of that you always use a key or index to indicate the row in use. It is procedural, but has more of an object oriented focus than Transaction script.     &lt;br /&gt;Note that you don't need to encapsulate the DataSet in a custom class, it is common to just work directly with the DataSet as well. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Table Module quickly became a success in .NET because of the great tool support existing. Putting together a simple read-only application that shows data in grid form literally takes no time because of the focus Microsoft has had on the tooling aspect. Everything from GUI to database works smoothly for this. Generally you can say that RAD applications work great with this approach. And it's a fair compromise if you have little logic and don't need much abstraction over you data model - because there will be a very tight coupling between your data model and every part of the application. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;h4&gt;A history lesson&lt;/h4&gt;  &lt;p&gt;The Table module pattern has many downsides though - even in .NET. If you have complex business logic, it won't cope with that very well. It's very data driven, and doesn't focus on the business side of things. You will end up with an application that is very tightly coupled to the database. It is poor at indicating relationships between objects, and polymorphism isn't exactly available. As long as you keep to the code generation and wizard support available, you'll be all right, but it can get complicated if you can't rely on that. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Microsoft had for many years an almost exclusive focus on this pattern - by their way of action basically saying that you could solve any problem with a dataset. Object bigots found various ways around it, often by creating mappers that converted datasets to objects, by cleverly encapsulating datasets or by creating custom data mappers using the data reader directly. The focus since Visual Basics heyday was on RAD applications, supporting novice developers, and not all that much more (Patterns &amp;amp; Practices shipped Enterprise Library 1.0 in 2005 though). The Microsoft community didn't seem to mature much more either, as there was an almost sole focus on software and tools that Microsoft shipped. From what I have come to understand this made the whole community much less used to object orientation than for instance the Java community became. And that is likely the main reason why the general Microsoft community is still so procedurally oriented still. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Luckily things have changed, both in terms of third party tools and to some extent Microsoft's focus. Tools like NHibernate and the Castle Project led the way with support for good object relational mapping and dependency injection tools, as well as MonoRail as an early MVC framework. Microsoft has supported enterprise applications through the work of Patterns and Practices on Enterprise Library. However, simplicity and enterprise library has never been used in the same sentence. In recent times though, Microsoft begun focusing on object relational mapping through LINQ To SQL and Entity Framework, an own MVC framework, ASP .NET MVC and their own IoC container, Unity, and the continuing support for composite UI applications with PRISM for WPF and Silverlight (Following the Composite UI Application Block for Winforms). &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;So the tide has to some extent turned in the Microsoft community, certainly the support for the two remaining patterns are continuously improving. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;But less take a closer look at the object oriented patterns: &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Active Record&lt;/h3&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;”An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.”&lt;/p&gt;    &lt;p&gt;Martin Fowler, &lt;a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/activerecord1.png/'&gt;&lt;img src='http://img36.imageshack.us/img36/462/activerecord1.png' border='0' width=’300’ height=’184’ /&gt;&lt;/a&gt;  &amp;#160;&amp;#160; &lt;br /&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img13.imageshack.us/i/activerecord2.png/'&gt;&lt;img src='http://img13.imageshack.us/img13/5911/activerecord2.png' border='0' width='324' height='507' /&gt;&lt;/a&gt;  &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The example above uses Castle Active Record. As you can see, the object encapsulates one database row in principle, and the object contains both data and domain logic. It includes logic to directly manipulate the database, like Save or Delete, and also includes static methods that work on the entire collection, like Get, or GetOrdersCount. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The flow of logic is different in Active Record than in the two previous patterns in that the object contains the logic internally, making use of encapsulation and achieving higher cohesion. Instead of having the service dictate how the logic should flow, you ask the object to perform some domain logic, and although not shown here, it typically delegates responsibility to other objects. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Active Record is a useful framework for two reasons: simplicity and tooling support. It's quite easy to understand, and as long as you use frameworks like Castle Active Record or LINQ to SQL, it's also fairly easy to use. For simple object models it works great, and as long as it's OK to have the object model closely mimic the data model, Active Record is a good choice. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;There's a few things you should consider before choosing Active Record though. Because of it's close connection to the data model, you have very limited support for designing your object model separate of the database. If you have a need for that, you should skip ahead to the next pattern. It's also a problem that it mixes responsibilities. The objects holds domain data and methods, but in addition you have attributes for mapping to the database, CRUD operations and static methods that work on the entire collection. And it sure isn't &lt;a href="http://stackoverflow.com/questions/1974735/what-exactly-is-persistence-ignorance" target="_blank"&gt;Persistence Ignorant (PI)&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;This is a popular pattern as well, and even though it seemed Microsoft tried to kill (http://bit.ly/8VkYnW) LINQ to SQL to avoid supporting it in addition to Entity Framework (more on this tool later), it's popularity seems to have saved it for now.     &lt;br /&gt;If&amp;#160; Active Record doesn't quite do it for you, and your complexity is high enough, you should take a closer look at the next pattern: &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Domain Model&lt;/h3&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;”An object model of the domain that incorporates both behavior and data”&lt;/p&gt;    &lt;p&gt;Martin Fowler, &lt;a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;  &lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/domainmodeltop.png/'&gt;&lt;img src='http://img36.imageshack.us/img36/2196/domainmodeltop.png' border='0' width='341' height='177' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img689.imageshack.us/i/domainmodelbottomleft.png/'&gt;&lt;img src='http://img689.imageshack.us/img689/2090/domainmodelbottomleft.png' border='0' width='380' height='319' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img94.imageshack.us/i/domainmodelbottomright.png/'&gt;&lt;img src='http://img94.imageshack.us/img94/5420/domainmodelbottomright.png' border='0' width='346' height='189' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The domain model pattern is the one that best supports object orientation. The point is to separate the domain logic into classes that are only concerned with modeling the domain and the corresponding rules well. The model classes should not know how to persist themselves (as in Active Record) and shouldn't be coupled to infrastructure logic. The classes should be POCO (Plan Old CLR Object), enabling a higher abstraction from the data model. This also means that the business logic of the domain model is simple to test, and you can easily get high coverage on this most important area without worrying about infrastructure and the like. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Domain model is the most complex to use, mostly because of the cost relating to mapping to the database (because of the impedance mismatch), and complexity regarding new ways of having to think about disconnected objects, lazy loading, less direct SQL to tweak and converning the next major point of this blogpost, not being familiar with delegated control. This complexity is biggest on first usage, and drops in subsequent projects.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Domain model shouldn't be used in all scenarios. Use it when you have a complex domain with complex business rules and when you want to be able to model the domain model free from database limitations. It is more complex to master than the other patterns, but in the right scenarios has great strengths. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;To handle the persistence of your domain model you use an Object Relational Mapper (OR/M). This includes an API for CRUD operations, mapping between the database and the data and domain model and a query model and associated language. The modeling is usually done either via external XML mapping files or some kind of fluent interface, where you state how the model maps to the database. A lot can be said about Object Relational Mappers, but this is not the place. One thing though - various people have objections against using domain model and object relational mapping for the wrong reasons. Be skeptical about objections concerning security, performance and SQL injection. More on that another time. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Much has been said about domain models. In recent years, the most influential books on the topic have been Martin Fowler's Patterns of Enterprise Application Architecture and Eric Evans' Domain Driven Design. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Centralized or delegated control&lt;/h3&gt;  &lt;p&gt;If you take a look at sequence diagrams of logic designed as the two procedural patterns, transaction script and table module, compared to the object oriented ones, active record and domain model, you will see two quite different information flows. The procedural ones uses a centralized control style, whereas the object oriented ones use a delegated one. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The logic for transaction script or table module is controlled from one location. The script knows which steps the transaction needs to take to perform the task, and asks appropriate helper classes to solve each step. A sequence diagram will show you information going into helper classes, often with single parameters or a form of DTOs, and back again, then into new classes, and so on. You have a central point of control. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Active record and domain model works in a different way. Here the responsibility is typically delegated to one or more objects, which again delegates responsibility to other objects. A sequence diagram will show you a flow going into an object, then delegated into other objects, and so on, instead of going back and forth from the central location. In this way you have a delegated form of control.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I think the procedural, or centralized control style, is more common in .NET than in Java. The main reason is the support and focus that Microsoft has had.A &lt;a href="http://portal.acm.org/citation.cfm?id=1018384" target="_blank"&gt;research paper&lt;/a&gt; was published in IEEE Transactions on Software Engineering, called &amp;quot;Evaluating the Effect of a Delegated versus Centralized Control Style on the Maintainability of Object-Oriented Software&amp;quot;, where about 150 senior, intermediate and junior developers, including a number of students, participated. The developers had to make various changes in both a delegated and a centralized design. The results:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;br /&gt;&amp;quot;The results show that the most skilled developers, in particular, the senior consultants, require less time to maintain software with a delegated control style than with a centralized control style. However, more novice developers, in particular, the undergraduate students and junior consultants, have serious problems understanding a delegated control style, and perform far better with a centralized control style&amp;quot;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;And then concluding:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;br /&gt;&amp;quot;Thus, the maintainability of object-oriented software depends, to a large extent, on the skill of the developers who are going to maintain it. These results may have serious implications for object-oriented development in an industrial context: Having senior consultants design object-oriented systems may eventually pose difficulties unless they make an effort to keep the designs simple, as the cognitive complexity of 'expert' designs might be unmanageable for less skilled maintainers.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;I think the conclusions with the delegated style of control also has a lot to do with familiarity. Since many .NET developers, including senior ones as well, have limited experience with this, imposing a delegated style can take some time getting used to. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;br/&gt;&lt;h3&gt;Have I covered everything then? &lt;/h3&gt;  &lt;p&gt;Since I put the heading in here, I'm sure you already know the answer to the question. There is one pattern I haven't mentioned yet, or an anti-pattern anyway. And a common one, that is. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I've mentioned several times in this post how the .NET community often have had a procedural focus. I think that is the reason why this pattern seem to be so popular in .NET-land. Let's have a closer look at what I'm talking about.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Anemic Domain Model&lt;/h3&gt;  &lt;p&gt;The Anemic Domain Model looks like a domain model, has a rich structure of objects, but there's almost no behavior in the objects. The logic is typically controlled via a transaction script, with the model being simply data containers. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;  &lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img193.imageshack.us/i/anemictopleft.png/'&gt;&lt;img src='http://img193.imageshack.us/img193/6594/anemictopleft.png' border='0' width='342' height='179' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img199.imageshack.us/i/anemictopright.png/'&gt;&lt;img src='http://img199.imageshack.us/img199/3745/anemictopright.png' border='0'/ width='393' height='215' &gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img19.imageshack.us/i/anemicbottomleft.png/'&gt;&lt;img src='http://img19.imageshack.us/img19/3664/anemicbottomleft.png' border='0' width='410' height='233' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img193.imageshack.us/i/anemicbottomright.png/'&gt;&lt;img src='http://img193.imageshack.us/img193/9020/anemicbottomright.png' border='0' width='275' height='88' /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The examples are Hello World in complexity, but hopefully still captures the main difference between this and a regular domain model. As you can see, the logic has mostly been moved out of the domain model, and into a different class. It's quite common that these are referred to as xxHelper, xxManager, xxHandler, or other general terms. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;This (anti-)pattern can be easier to understand for those struggling with delegated control, but this is a benefit with a cost. Other benefits is that you can brag about having a domain model to your friends (which you don't), and any other benefits you get with transaction script. The problem is that you get the same problems as with transaction script - a challenge with complex code, duplication of code and logic that is harder to unit test. In addition you get the complexity of using an OR/M on top of that. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br/&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;None of these patterns is never right. That's part of the &lt;em&gt;fun&lt;/em&gt; of software development. You need to take a close look at what you need to build and then take an informed guess. Take into account the positive and negative sides, and when you have made the choice - make real effort to diminish the effects of the negative sides. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-570063787759033699?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/570063787759033699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=570063787759033699' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/570063787759033699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/570063787759033699'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/object-orientation-revisited-business.html' title='Object Orientation revisited – Business layer patterns'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-3854006880884749641</id><published>2010-01-06T10:06:00.000+01:00</published><updated>2010-01-06T10:06:00.603+01:00</updated><title type='text'>The technical laws of December</title><content type='html'>&lt;p&gt;Throughout December I had the pleasure of collecting more or less clever statements about computers and software development in general. My &lt;a href="http://bit.ly/90E8Wx" target="_blank"&gt;twitter account&lt;/a&gt;&amp;#160; had a steady flow of these up until Christmas. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In today’s society, we have to use so much of our energy filtering out knowledge, and it is interesting how cleverly written sentences can capture so much information. I’m going to elaborate on several of them in the time to come, but for now, here they are again. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Disclaimer: These aren't my quotes - they've been collected from a variety of places and people, and thus credit is due in many places. I apologize for not quoting correctly.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Dec1 tech law: Walking on water and developing software to specification are easy as long as both are frozen &lt;/p&gt;  &lt;p&gt;Dec2 tech law: In theory, there is no difference between theory and practice, but in practice there is &lt;/p&gt;  &lt;p&gt;Dec3 tech law: Real programmers don't comment their code. If it was hard to write, it should be hard to understand &lt;/p&gt;  &lt;p&gt;Dec4 tech law: Computers are unreliable, but humans are even more unreliable. Any system which depends on human reliability is unreliable. &lt;/p&gt;  &lt;p&gt;Dec5 tech law: There is never time to do it right, but always time to do it over &lt;/p&gt;  &lt;p&gt;Dec6 tech law: Adding manpower to a late software project makes it later &lt;/p&gt;  &lt;p&gt;Dec7 tech law: The degree of technical competence is inversely proportional to the level of management. &lt;/p&gt;  &lt;p&gt;Dec8 tech law: The probability of bugs appearing is directly proportional to the number and importance of people watching &lt;/p&gt;  &lt;p&gt;Dec9 tech law: If a program is useful, it will have to be changed. If a program is useless, it will have to be documented. &lt;/p&gt;  &lt;p&gt;Dec10 tech law: Good enough isn't good enough, unless there is a deadline &lt;/p&gt;  &lt;p&gt;Dec11 tech law: An expert is someone brought in at the last minute to share the blame &lt;/p&gt;  &lt;p&gt;Dec12 tech law: The chances of a program doing what it's supposed to do is inversely proportional to the num lines of code used to write it &lt;/p&gt;  &lt;p&gt;Dec13 tech law: profanity is the one language all computer users know &lt;/p&gt;  &lt;p&gt;Dec14 tech law: All's well that ends. &lt;/p&gt;  &lt;p&gt;Dec15 tech law: No matter how hard you work, the boss will only appear when you access the Internet. &lt;/p&gt;  &lt;p&gt;Dec16 tech law: A meeting is an event at which the minutes are kept and the hours are lost. &lt;/p&gt;  &lt;p&gt;Dec17 tech law: An expert is one who knows more and more about less and less until he knows absolutely everything about nothing. &lt;/p&gt;  &lt;p&gt;Dec 18 tech law: it's not a bug, it's an undocumented feature &lt;/p&gt;  &lt;p&gt;Dec19 tech law: A complex system that works is invariably found to have evolved from a simple system that works &lt;/p&gt;  &lt;p&gt;Dec20 tech law: The documented interfaces between standard software modules will have undocumented quirks &lt;/p&gt;  &lt;p&gt;Dec21 tech law: Bugs will appear in one part of a working program when another 'unrelated' part is modified &lt;/p&gt;  &lt;p&gt;Dec22 tech law: When designing a program to handle all possible dumb errors, nature creates a dumber user &lt;/p&gt;  &lt;p&gt;Dec23 tech law: Build a system that even a fool can use and only a fool will want to use it &lt;/p&gt;  &lt;p&gt;Dec24 tech law: The cleverness of&amp;#160; technical laws is inversely proportional to the number of laws&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-3854006880884749641?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/3854006880884749641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=3854006880884749641' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3854006880884749641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3854006880884749641'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/technical-laws-of-december.html' title='The technical laws of December'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-2789746429855036846</id><published>2010-01-03T19:11:00.001+01:00</published><updated>2010-01-03T23:13:05.575+01:00</updated><title type='text'>Walking on water and developing software to specification are easy as long as both are frozen</title><content type='html'>&lt;p&gt;Developing software is pretty complex, but it’s not exactly rocket science, right? You find out what you want created, you get a number of software developers that has studied how the technicalities work, and after a time you end up with a good, working piece of software. Correct? &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;It's a shame how few reading this can actually agree with it. Why is that? And can anything be done about it? If you have a few decent developers (they don't have to be that good), a small set of requirements, a business expert they can discuss those requirements with... You know what - you just got yourself the perfect recipe for a good working system. Fingers crossed!&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Unfortunately the previous description doesn't map to many real systems. One of the biggest problems is that requirements change. This affects all parts of software development, but no other part can influence the result of this like the process used. Back in the days, and still in practice quite a few places today, they tried to scale the previously described way of solving software development no matter the size of the project. You just collect and analyze all the requirements, find a number of developers to implement the system, get one or more architects based on some measure of experience to help design the structure, plan and discuss the requirements, implement it, test it and release it. That works to a certain extent, to a certain size, for certain organizations, but it has many limitations. I'm not going to try to cover those extensively now, but it includes    &lt;br /&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You've got one shot at coming up with the features for the system. Now guess what happens -&amp;gt; You will try to come up with as much as humanly possible, important or not &lt;/li&gt;    &lt;li&gt;You have little idea how the system is actually going to look or feel or just how it can be used -&amp;gt; You will try to make the requirements cover everything. This isn't really a bad thing, but can be quite a complex process. &lt;/li&gt;    &lt;li&gt;Price the project beforehand, to move the risk of development to a software company -&amp;gt; Do you think those requirements change sessions will be fun? &lt;/li&gt;    &lt;li&gt;Your understanding of what the system can bring you, what you really need it to do, and just how it can do that the best -&amp;gt; Will change! &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;The whole point of this post has become very well understood in the industry - requirements change, and you'll have to cope with that one way or another. If you want a useful system that is. A number of smart people put their heads together back in 2001 and came up with the &amp;quot;&lt;a href="http://agilemanifesto.org/"&gt;Manifesto for Agile Software Development&lt;/a&gt;&amp;quot;, and a number of &lt;a href="http://agilemanifesto.org/principles.html"&gt;principles&lt;/a&gt; behind it. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;What was the cure they came up with? Besides a few other good points, it was the formalization of an old principle - tackle complexity by dividing a problem into smaller, manageable pieces. (Note: The &lt;a href="http://bit.ly/4X7LlY"&gt;original paper&lt;/a&gt; on the Waterfall model did cover the importance of a certain amount of iterative behavior, but I guess it was lost to quite a few people on the way.) If you’re trying to tackle all problems at once – or in other words not developing software in an iterative manner, make sure you have very good reasons for it. Unless the project is small, with clearly defined knowledge and boundaries, you’re going to have a hard time producing the system you really need. Do you do it for control? There is no real form of control&amp;#160; in software besides working software. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Is process the only thing you have to think about when handling change in software development? Not by a long shot, but it is an important part of it. I will cover more areas soon.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-2789746429855036846?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/2789746429855036846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=2789746429855036846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2789746429855036846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2789746429855036846'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2010/01/walking-on-water-and-developing.html' title='Walking on water and developing software to specification are easy as long as both are frozen'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-7495812871107587749</id><published>2009-02-10T23:00:00.001+01:00</published><updated>2009-02-10T23:00:42.241+01:00</updated><title type='text'>#GEEKBEER starting this Thursday (in Oslo)</title><content type='html'>&lt;p&gt;&lt;a href="http://tore.vestues.no/" target="_blank"&gt;Tore Vestues&lt;/a&gt;, &lt;a href="http://twitter.com/sverrehundeide" target="_blank"&gt;Sverre Hundeide&lt;/a&gt;, myself and more thought it was about time we got a regular social developer-night together. The purpose is simply to socialize and have a good time.&amp;#160; No free beer, no surprises, just fellow developers/IT people. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;We'll start up this Thursday (the 12) , 7pm, at Asylet (Gr&amp;#248;nland). Come along! &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;We hope to make it into a monthly thing, so don't despair if you can't make it this time. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-7495812871107587749?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/7495812871107587749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=7495812871107587749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7495812871107587749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7495812871107587749'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/02/geekbeer-starting-this-thursday-in-oslo.html' title='#GEEKBEER starting this Thursday (in Oslo)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8270208755814482510</id><published>2009-01-21T23:59:00.001+01:00</published><updated>2009-01-22T00:07:18.052+01:00</updated><title type='text'>Essential Project Practices: Communication and close customer collaboration</title><content type='html'>&lt;p&gt;I'm a firm believer in the need for close customer collaboration in projects, a high degree of communication and continual status updates to best manage basically anything. I think I would define it as one of the major &amp;quot;make or break&amp;quot; characteristics of a project. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I remember being asked during an interview with my current employer what I believed was the biggest reasons projects fail. Communication was the big thing that came to mind. Projects fail for a myriad of reasons, but not the least because of a lack of communication between a number of involved parties. I thought I'd try to get in to a few of those aspects here.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Working on communication at all times is important. The various roles in a project or organization has different responsibilities here. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.processdevelopers.com/images/PM_Build_Swing.gif" /&gt; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;b&gt;Upper management and project champion&lt;/b&gt;    &lt;br /&gt;First of all, any project, and especially those related to organizational changes, needs upper management support. If the project needs to communicate, integrate or in other ways depend on other parts of the organization, it is hard to do it without the support from the top. The unofficial networks built by social interaction within an organization are one way it can work.&amp;#160; But management support is extremely important, so you better find out how to get it - even if it is not your direct responsibility, pull some strings to find out if something can be done about it. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Another role of extreme importance is the project champion. A project champion is a person highly dedicated to see the project through from inception to success. Not completely about the topic, but this is a person that will help make sure that the needs of the project are taken care of throughout the organization. Communication is tool number one here. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;b&gt;Project manager -&amp;gt; developers&lt;/b&gt;    &lt;br /&gt;The project manager and the development group also need to communicate. I use project manager here to mean several possible positions, both project manager in the traditional meaning, and for instance product owners in Scrum tongue, or even in part Scrum masters. The two sides has different needs for communication. The project manager has the primary responsibility of delivering the project on time, within budget and according to specification. There's many ways of handling this. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Organizational requirements and processes is the primary one, but trust has no less importance.    &lt;br /&gt;Organizational requirements and processes is something you have to live with in some form. If you are able to build trust in what you deliver outside of the project scope as well, you'll most likely have more control of what you need to deliver. The major reason behind many of the demands and project artifacts found today is a lack of trust. The lack of trust is compensated for by putting in a myriad of artifacts, processes and control points. Even though that is often a false sense of security, I generally completely agree with the approach - if you don't have trust, the next best thing is to monitor the progress. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So how do you build trust? First and foremost you need to deliver (Hopefully on time, within budget, and according to specification :) ). Communication is tool number two. When problems arise they need to be communicated up the ladder as needed. If you have trust that problems once discovered will be taken through the right channels, you have a good basis for being able to solve any problem once they arise. To build trust, you need to communicate continuously. People are different, but little and often is often better than much and seldom. Manager Tools (brilliant podcast-series) has a podcast describing how humans relate to trust and relationships &lt;a href="http://www.manager-tools.com/2008/08/rolling-out-the-manager-tools-trinity-part-1" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Project -&amp;gt; Business expert and users&lt;/b&gt;    &lt;br /&gt;An essential step in delivering a product that fulfills needs is close collaboration with the business experts and users. It cannot be a single iteration waterfall-thing, it needs to be a continuous collaborative effort. You do something, then you verify what is done. You wonder about something, you contact the business expert or user. And how much easier is it to get both attention and clear answers if you have someone within the same room than over phone or email? &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Developer -&amp;gt; Developer&lt;/b&gt;    &lt;br /&gt;Developers are certainly not excluded from the communication effort. Developers need to continuously communicate within the group to ensure everyone has a clear understanding of the problem at hand, to build project ownership, to share project knowledge, and to notify and get help for problems. And if you are a developer, what better way is there to increase your skill-set than to communicate with other developers? And try to be aware of &lt;a href="http://en.wikipedia.org/wiki/Groupthink" target="_blank"&gt;groupthink&lt;/a&gt;, that is certainly not good to have to much of. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;In conclusion&lt;/b&gt;    &lt;br /&gt;Writing about something like this is impossible to do well without references and ahead planning, so I'll easily admit that the above text is heavily flawed. However, the concept is very important, and that's why I wanted to share a few disconnected thoughts on it.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you find the topic interesting it's not hard to find sources talking about it. It is slightly harder to find interesting sources.    &lt;br /&gt;The podcast mentioned above has interesting topics, but it is mostly related to managerial behaviours. You can access it &lt;a href="http://www.manager-tools.com/podcasts/manager-tools" target="_blank"&gt;here&lt;/a&gt;     &lt;br /&gt;If teams and communication is interesting, you'll find Peopleware's &lt;a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-Second/dp/0932633439 " target="_blank"&gt;Productive Projects and Teams&lt;/a&gt; great.     &lt;br /&gt;If other aspects of communication seems interesting, I'll be happy to recommend books on the subject. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8270208755814482510?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8270208755814482510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8270208755814482510' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8270208755814482510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8270208755814482510'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-project-practices.html' title='Essential Project Practices: Communication and close customer collaboration'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8657892983341037131</id><published>2009-01-20T23:29:00.004+01:00</published><updated>2009-01-20T23:31:54.650+01:00</updated><title type='text'>NNUG: Tonight's meeting</title><content type='html'>&lt;p&gt;Jimmy Nilsson and Tore Vestues was the speakers on todays &lt;a href="http://nnug.no/Avdelinger/Oslo/Moter/Brukergruppemote-januar-2009/" target="_blank"&gt;NNUG-meeting&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;a href="http://jimmynilsson.com/blog/" target="_blank"&gt;Jimmy Nilsson&lt;/a&gt; is most known for having written &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0321268202" target="_blank"&gt;&amp;quot;Applying Domain Driven Design and Patterns&amp;quot;&lt;/a&gt;, one of the few good books on DDD, as well as having a practical focus on for instance TDD. Jimmy was nice enough to speak for us tonight after having held a LEAP course today. I haven't heard him live before, but if you can say anything about Jimmy, besides being very skilled, is that he is a really nice guy to listen to. Good stuff :) For those that missed it, his speech &amp;quot;En ny era f&amp;#246;r data&amp;#229;tkomst?&amp;quot; (A new era of data access) took on the history and general approaches about data access, as well as more general info about TDD. Please remind me that we must have a topic with a more close look at the data access options soon. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;a href="http://tore.vestues.no/" target="_blank"&gt;Tore Vestues&lt;/a&gt; had a speech about about Code Quality. (In the interest of full disclosure: we are colleagues.) The speech was well worth the time, and the topic should be on the absolute top of your list of priorities. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8657892983341037131?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8657892983341037131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8657892983341037131' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8657892983341037131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8657892983341037131'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/nnug-tonight-meeting.html' title='NNUG: Tonight&amp;#39;s meeting'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8358239253357170386</id><published>2009-01-19T23:04:00.004+01:00</published><updated>2009-01-19T23:09:03.858+01:00</updated><title type='text'>Interesting Old Stuff: Management tutorial</title><content type='html'>&lt;p&gt;I&amp;#160; browsed through an old mailbox I used long ago today, and stumbled upon an old weekly tutorial for a project management class I attended.&amp;#160; That week's tutorial seems like it was about methodologies, continuous feedback and client demonstration. I know I would have a lot to say about that now :)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;An interesting read out of a sort of sentimental fashion for me. I'll post it here just for fun&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;You are the IT project manager of an organisation developing innovative &amp;#8216;leading-edge&amp;#8217; warehousing solutions. Although a number of individual software components have yet to be completed your clients are insisting on regular updates of your progress, backed up by demonstrations of the latest versions of the individual software components. Their insistence is being reinforced by the client&amp;#8217;s threat to withhold staged payments that are required to be made as part of the contract terms.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;How might this type of client behaviour affect the type of development methodology you employ?&lt;/b&gt; &lt;/p&gt;  &lt;p&gt;With any project we believe it is important to supply the client with regular updates and demonstrations of the latest versions of the individual software components. When dealing with a very insistent client, as in this case, we believe that there is a need to use a methodology that incorporates user/client involvement throughout the project. &lt;/p&gt;  &lt;p&gt;The development methodology type that is most suited for these requirements is one based on prototyping. By using such a methodology the project will focus on and deliver working prototypes, and show early efforts of integrating the different parts of the project. An example of a methodology that could be suitable for this type of project is Extreme Programming (XP). XP is a spiral type methodology with short iterations and close customer contact. It has a strong focus on integrating early and creating working prototypes. Since the customer will be updated on the progress of the project at short intervals and are able to change direction due to problems or new requirements they will be able to do real-time planning with the project. &lt;/p&gt;  &lt;p&gt;Generally we believe that it is important to know and understand any development methodology, and not use any aspect of it without considering the consequences. Often you need to use parts of different methodologies, or change part of the one you are using, as it does not necessarily work perfect in your organisation. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Why do you believe the client might be so insistent on receiving regular &amp;#8216;proof of progress&amp;#8217; updates?&lt;/b&gt; &lt;/p&gt;  &lt;p&gt;There are many possible reasons for why a client would insist on receiving regular &amp;#8220;proof of progress&amp;#8221; updates. We believe that such an insistent client&amp;#8217;s main reason for behaving like that is the risk of project failure. It is well known that many IT projects fail to complete at all, complete far over time or budget, or just isn&amp;#8217;t used as planned in the organisation. &lt;/p&gt;  &lt;p&gt;During a project there are many problems that occur. A client wants to see that everything is going as planned, that the project milestones are met, and that the contracted agreements are fulfilled. &lt;/p&gt;  &lt;p&gt;If a project develops away from the project specifications and the project plan agreed upon with the client, then the client can demand corrections according to the contract or even bail out. The earlier this is discovered, the better it is for the client.&lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;You discuss the issue with your own executive management and they make a suggestion that you merely &amp;#8216;fake&amp;#8217; the demonstrations without making any genuine attempt to provide a genuine product. What are some of the implications here?&lt;/b&gt; &lt;/p&gt;  &lt;p&gt;If you were to &amp;#8220;fake&amp;#8221; the demonstration of a product we believe that there can be both positive and negative implications to this.&lt;/p&gt;  &lt;p&gt;Firstly, it might be positive for the project to do this if you are having a slow start to the project but you are still very confident that you will be able to finish the section in question on time.&lt;/p&gt;  &lt;p&gt;Another reason might be if you are up to date on the coding, but you might still have problems showing visual proof of progress. By faking the demonstration you can avoid problems you might get by not producing visual results. In other words you will not be picking the low hanging fruits first just to have something to demonstrate.&lt;/p&gt;  &lt;p&gt;On the other hand there are some negative implications too. You can risk giving the client false hopes about the probability of project success. If the client detects the faking of the demonstration you will have to take the consequences. This can range from the client loosing trust in you, a loss of reputation and a loss of the contract to possible lawsuits. &lt;/p&gt;  &lt;p&gt;All of these negative implications are risks that can lead to economical consequences. Therefore it&amp;#8217;s important that you consider the implications thoroughly before making a decision to fake such a presentation.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8358239253357170386?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8358239253357170386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8358239253357170386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8358239253357170386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8358239253357170386'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-old-stuff-management.html' title='Interesting Old Stuff: Management tutorial'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6244391809818260367</id><published>2009-01-19T20:20:00.001+01:00</published><updated>2009-01-19T20:29:47.073+01:00</updated><title type='text'>Interesting Blog Posts: NHibernate and Entity Framework Battle it Out in the Real World</title><content type='html'>&lt;p&gt;If an OR-mapper is what you need, here's a short and interesting real life example of how a showdown between EF and NH went.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Note: Look, I am saying OR-mapper here, so don't get me started with the &amp;quot;they are impossible to compare since EF is supposed to be a persistence-, object-, view-, query-, dataservices&amp;quot;-discussion. That is so 2008. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://img527.imageshack.us/img527/3153/dilbertmauvech9.jpg" /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6244391809818260367?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6244391809818260367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6244391809818260367' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6244391809818260367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6244391809818260367'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-blog-posts-nhibernate-and.html' title='Interesting Blog Posts: NHibernate and Entity Framework Battle it Out in the Real World'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-9091766616309878293</id><published>2009-01-18T23:59:00.003+01:00</published><updated>2009-01-19T08:30:49.222+01:00</updated><title type='text'>Interesting Software Thoughts: 8 Things We Hate About IT</title><content type='html'>&lt;p&gt;It's interesting to step a bit back from the daily technical crunch and see how the world of IT is viewed from the outside at times.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;A &lt;a href="http://discussionleader.hbsp.com/cramm/" target="_blank"&gt;management guru&lt;/a&gt;&amp;#160; has a &lt;a href="http://discussionleader.hbsp.com/cramm/2008/06/8-things-we-hate-about-it.html" target="_blank"&gt;blog post&lt;/a&gt;&amp;#160; titled the same as the header. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The points listed are the following, as well as a few thoughts I formed while reading them: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1. IT Limits Managers' Authority.&lt;/strong&gt;    &lt;br /&gt;&lt;strong&gt;2. They're Missing Adult Supervision: &lt;/strong&gt;IT needs close supervision. Short feedback loops through iterations that produce results are the way to get it. Milestones and a kill switch is another requirement.     &lt;br /&gt;&lt;strong&gt;3. They're Financial Extortionists:&lt;/strong&gt; It's scary to think about all the money wasted on the appalling track record of IT in general. But there's undoubtedly a shared responsibility there, both on the IT and general business side.     &lt;br /&gt;&lt;strong&gt;4. Their Projects Never End:&lt;/strong&gt; Setting deadlines, having milestones and defining Done is essential in any task.     &lt;br /&gt;&lt;strong&gt;5. The Help Desk is Helpless:&lt;/strong&gt; Software has bugs. Especially since it is often a conscious decision to release something when it's &amp;quot;good enough&amp;quot;. I don't envy the help desk personnel in IT in general.     &lt;br /&gt;&lt;strong&gt;6. They Let Outsourcers Run Amok:&lt;/strong&gt; I strongly doubt IT is the main driver in outsourcing!     &lt;br /&gt;&lt;strong&gt;7. IT is Stocked with Out-of-Date Geeks:&lt;/strong&gt; With the rate IT is changing, this is a most truthful and dangerous statement. It takes a lot of effort to stay up to date on the technologies and practices of IT. The number of years a person has been in IT doesn't necessarily add up to the skill level of the person.     &lt;br /&gt;&lt;strong&gt;8. IT Never Has Good News:&lt;/strong&gt; Too seldom, that's for sure!    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;br /&gt;So what do we need to succeed with IT projects? &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We need close customer collaboration. &lt;/li&gt;    &lt;li&gt;We need projects with short feedback loops. &lt;/li&gt;    &lt;li&gt;We need sane requirements engineering. &lt;/li&gt;    &lt;li&gt;We need to know what Done means. &lt;/li&gt;    &lt;li&gt;We need the business side to be active in the entire process to deliver what they need. &lt;/li&gt;    &lt;li&gt;We need quality in the development force. Such a simple task :) &lt;/li&gt;    &lt;li&gt;We need companies that dare to change. Running IT the old fashioned waterfall-way didn't work very well, did it? Time to try something new. &lt;/li&gt;    &lt;li&gt;We need to be careful with new technologies. If it's new and you don't run a spike, then shame on you. &lt;/li&gt;    &lt;li&gt;We need developers with a vested interest in the projects success. Not just their own. The project must have priority over individuals. Heroic individuals is not the best approach for a project. &lt;/li&gt;    &lt;li&gt;We need to build trust. Now that's a big one! &lt;/li&gt;    &lt;li&gt;We need a hell of a lot more than I have listed here, but these just came from the top of my mind.      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;One thing is for sure. The challenge is not only on our side of the table. But we should help educate the business people we work with every day on how we can more readily succeed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-9091766616309878293?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/9091766616309878293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=9091766616309878293' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9091766616309878293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9091766616309878293'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-software-thoughts-8-things.html' title='Interesting Software Thoughts: 8 Things We Hate About IT'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-5823152961725589258</id><published>2009-01-17T13:50:00.002+01:00</published><updated>2009-01-17T13:50:50.325+01:00</updated><title type='text'>Interesting .NET Bugs: Object Initializers and using-statements</title><content type='html'>&lt;p&gt;Ayende posted about &lt;a href="http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx" target="_blank"&gt;this bug&lt;/a&gt;, but it's one hard to spot bug, so I felt it was valid to pass on. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;If you use object intializers in the definition of a using statement it is normal to expect that if an exception occurs the dispose method will be called. After all that is the point of the pattern. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;img src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Avoidobjectinitializerstheusingstatement_11B04/image_6.png" /&gt;     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;br /&gt;However, object initializers are compiled in an unexpected way here:    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Avoidobjectinitializerstheusingstatement_11B04/image_4.png" /&gt; e&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Beware. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;(Both images stolen from Ayende. No harm intended.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-5823152961725589258?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/5823152961725589258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=5823152961725589258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5823152961725589258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5823152961725589258'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-net-bugs-object.html' title='Interesting .NET Bugs: Object Initializers and using-statements'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-2948956788839937853</id><published>2009-01-16T23:57:00.001+01:00</published><updated>2009-01-16T23:57:58.582+01:00</updated><title type='text'>Interesting Software Resources: Domain Driven Design Quickly</title><content type='html'>&lt;p&gt;If you haven't had time to get into any literature about Domain Driven Design yet, InfoQ has created a free online short version of the Domain Driven Design bible which is well worth the time. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Order &lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" target="_blank"&gt;the book&lt;/a&gt; now, and read &lt;a href="http://www.infoq.com/minibooks/domain-driven-design-quickly" target="_blank"&gt;the resource&lt;/a&gt; until you get it. This is ESSENTIAL. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Why it is needed, an except:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Is it possible to create complex banking software without good domain knowledge? No way. Never. Who knows banking? The software architect? No. He just uses the bank to keep his money safe and available when he needs them. The software analyst? Not really. He knows to analyze a given topic, when he is given all the necessary ingredients. The developer? Forget it. Who then? The bankers, of course. The banking system is very well understood by the people inside, by their specialists. They know all the details, all the catches, all the possible issues, all the rules. This is where we should always start: the domain.     &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;When we begin a software project, we should focus on the domain it is operating in. The entire purpose of the software is to enhance a specific domain. To be able to do that, the software has to fit harmoniously with the domain it has been created for. Otherwise it will introduce strain into the domain, provoking malfunction, damage, and even wreak chaos.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-2948956788839937853?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/2948956788839937853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=2948956788839937853' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2948956788839937853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2948956788839937853'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-software-resources-domain.html' title='Interesting Software Resources: Domain Driven Design Quickly'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4852881435538031813</id><published>2009-01-15T23:46:00.005+01:00</published><updated>2009-01-15T23:49:53.711+01:00</updated><title type='text'>Essential Project Practices: Throwing more programmers at a project</title><content type='html'>&lt;p&gt;Fredrick Brooks Jr. made an interesting and in time very well known statement when he coined Brooks's Law in 1975: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;adding manpower to a late software project makes it later&amp;quot;     &lt;br /&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;He himself said it was an &amp;quot;outrageous oversimplification&amp;quot;, but it is an observation that has had value in all these years. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I think its primary value lie in the simplicity of the statement. It's a law that can be used to easily argue against common sense: that doubling the amount of developers should double the productivity. And even more, it's a statement which can easily catch the interest to find out why it was stated. One thing is that adding developers to a project won't double the productivity, quite another is to say that it won't increase productivity at all, and it sounds really absurd to say that I will make it later.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The Law is based on a few main points:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;New programmers will have to learn about the project. &lt;/li&gt;    &lt;li&gt;Communication overhead will increase     &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt; &lt;br /&gt; &lt;p&gt;So what can you do to avoid fulfilling Brooks's Law? It's not like its gravity we're talking about here.    &lt;br /&gt;There's many factors involved:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How skilled are the new developers?&lt;/li&gt;    &lt;li&gt;How well do they know the domain?&lt;/li&gt;    &lt;li&gt;How many are they?&lt;/li&gt;    &lt;li&gt;At what time do they come into the project. Early or late?&lt;/li&gt;    &lt;li&gt;How well do they fit into the culture?&lt;/li&gt;    &lt;li&gt;Are they team players that can accept the current process, or will they fight it?&lt;/li&gt;    &lt;li&gt;How well can the work be segregated?&lt;/li&gt;    &lt;li&gt;What practices are in place to ensure the quality of the work produced? Automated testing, Continuous Integration, close customer collaboration, code reviews and lot's more can help to ensure that things don't get out of hand. &lt;/li&gt;    &lt;li&gt;...&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;p&gt; Pretty obvious, but I doesn't hurt to have a law for it. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4852881435538031813?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4852881435538031813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4852881435538031813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4852881435538031813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4852881435538031813'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-project-practices-throwing.html' title='Essential Project Practices: Throwing more programmers at a project'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1137282586427353415</id><published>2009-01-14T23:41:00.002+01:00</published><updated>2009-01-14T23:42:11.960+01:00</updated><title type='text'>Essential Software Practices: Favor composition over inheritance</title><content type='html'>&lt;p&gt;&lt;/p&gt; This is an old and important principle that people seem to forget at times. So time to refresh your memory of this one as well. &lt;p&gt;   &lt;br /&gt;In OO design you have two common ways of dealing with duplication and reuse: composition and inheritance. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;strong&gt;Composition&lt;/strong&gt;: Assembling objects. &amp;quot;Has a&amp;quot; relationships. Black box reuse (No internals visible)    &lt;br /&gt;&lt;strong&gt;Inheritance&lt;/strong&gt;: Defined in terms of the parents implementation. &amp;quot;Is a&amp;quot; relationships. (Don't forget Liskov) White-box reuse (Access to parent internals).&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;As stated in the definition above, you use inheritance for &amp;quot;is a&amp;quot; relationships (that are substitutable).&amp;#160; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The are several problems with using inheritance for anything else&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You're not supposed to use inheritance for code reuse. &lt;/li&gt;    &lt;li&gt;You can (sort of) break encapsulation since the sub-class is so tightly coupled to the parent's implementation. &lt;/li&gt;    &lt;li&gt;Inheritance is set in stone at runtime, so no dynamic fun. &lt;/li&gt;    &lt;li&gt;A subclass can easily make assumptions about the context the method it overrides is called.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Composition has other strengths than inheritance&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Any object with the same type can be replaced at runtime. This is important for many things, for instance testing - as we want to test in isolation.&lt;/li&gt;    &lt;li&gt;You can &amp;quot;just plug in behavior&amp;quot; with composition. A small object can help decide how a bigger object works.&lt;/li&gt;    &lt;li&gt;It is the better approach when you want to reuse functionality.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;It is also erroneous that composition does not use inheritance. It is typically done through implementing smaller interfaces rather than inheriting from a big class.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;If you want to have a look at what Grady Booch defines as the &amp;quot;prototypical example of the flexibility of composition over inheritance&amp;quot;, take a look at the strategy pattern.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;To sum up a short text: This is really a no-brainer. Think for a couple of seconds before choosing an approach, and just use your gut feeling. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1137282586427353415?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1137282586427353415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1137282586427353415' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1137282586427353415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1137282586427353415'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-practices-favor.html' title='Essential Software Practices: Favor composition over inheritance'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-5910933588298208674</id><published>2009-01-13T23:43:00.003+01:00</published><updated>2009-01-14T07:49:31.507+01:00</updated><title type='text'>Essential Software Concepts: Static methods</title><content type='html'>&lt;p&gt;Static methods&lt;b&gt; &lt;/b&gt;is a&lt;b&gt; &lt;/b&gt;common functionality in many languages. Whereas instance methods work on instantiated objects, static methods work on types or instantiated objects.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The big question is - when is it appropriate to use static methods?&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;First the naive positives. These are the positives that often comes up, but which aren't really true. &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Makes it more obvious which methods works on internal state. If it doesn't have state, it should be static. &lt;/li&gt;    &lt;li&gt;Great for Factory Methods (See real negative).      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And then the real pros and cons: &lt;/p&gt;  &lt;p&gt;Real positive&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Don't need to initialize an object. This can be good in the case of small and discrete methods. Some utility classes are good examples, for instance Math. &lt;/li&gt;    &lt;li&gt;Can be good for simple and effective, fire and forget functions.      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Real negative&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Is hard to refactor away from. &lt;/li&gt;    &lt;li&gt;Doesn't work with inheritance, polymorphism and interfaces. &lt;/li&gt;    &lt;li&gt;Makes it hard to test (Some test-frameworks can). For those that can't it's impossible to mock the behavior, since there is no natural way of substituting the implementation at runtime. &lt;/li&gt;    &lt;li&gt;Static Factory Methods makes implementers bound to the concrete implementation. Impossible to replace during test. Handling object graph wiring this way makes it even worse. &lt;/li&gt;    &lt;li&gt;Simple static methods can evolve into larger (still, possibly, untestable) beasts, which are not only a hassle to refactor away from, but do they really give the advantage of risking it? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;What you potentially can read from a static method&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Unless global state exists, the static method can only work on the input parameters. It is often more natural to move the method to one of these. Remember to keep logic as close to where it belongs as possible.      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Just a note. Untestable in the points above isn't necessarily true. I'm talking about the possibility of switching implementations with stubs/mocks to be able to isolate what we are testing. It depends what dependencies it has of course.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;There is use for static methods. Just be sure that it outweighs the potential negative issues!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-5910933588298208674?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/5910933588298208674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=5910933588298208674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5910933588298208674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5910933588298208674'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-static.html' title='Essential Software Concepts: Static methods'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-9204836159888744585</id><published>2009-01-13T21:04:00.001+01:00</published><updated>2009-01-13T21:04:04.653+01:00</updated><title type='text'>Windows 7 useful stuff (link)</title><content type='html'>&lt;p&gt;Tim Sneath, director of the Windows and Silverlight technical evangelism team, has an interesting &lt;a href="http://blogs.msdn.com/tims/archive/2009/01/12/the-bumper-list-of-windows-7-secrets.aspx" target="_blank"&gt;post&lt;/a&gt; about 30 windows 7 &amp;quot;secrets&amp;quot;. Certainly served as a good reminder to myself that I need to get the Windows 7 beta. The fact that they have spent much more time preparing 7 for power users is a great. I despise using things I can't customize.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;note to self: download windows 7 beta shortly&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-9204836159888744585?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/9204836159888744585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=9204836159888744585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9204836159888744585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9204836159888744585'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/windows-7-useful-stuff-link.html' title='Windows 7 useful stuff (link)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6824361431251463318</id><published>2009-01-12T22:54:00.001+01:00</published><updated>2009-01-12T22:54:48.662+01:00</updated><title type='text'>Essential Software Principles: Don't Repeat Yourself (DRY)</title><content type='html'>&lt;p&gt;Don't Repeat Yourself, also called the Single Point of Truth, is about representing any and every piece of information in a single representation. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;It is usually used only for code, but was meant to have a broader meaning. According to the authors of The Pragmatic Programmer it should include &amp;quot;database schemas, test plans, the build system, even documentation&amp;quot;. They further refer to various techniques for achieving this, like code generation, automatic build systems and scripting languages. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;It is an important principle to focus on. Whatever it is you do, if it's described in two places one is going to get out of sync from the other. Other issues come as well. Duplication will make it harder to do changes, it reduces clarity and is perfect for creating inconsistencies in logic. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The Pragmatic Programmer defines for reasons for duplication:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Imposed duplication: You feel you have no other choice &lt;/li&gt;    &lt;li&gt;Inadvertent duplication: You don't realize you are duplicating &lt;/li&gt;    &lt;li&gt;Impatient duplication: Duplication seems like the simplest option &lt;/li&gt;    &lt;li&gt;Interdeveloper duplication: Multiple people duplicate&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;All are common cases for duplication. Being aware of each and working to avoid them are essential.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The prime example of imposed duplication is documentation vs code. Often this is something you cannot avoid. It can also bring value. For instance can different views of a system be terribly helpful in simplifying and understanding issues. But as we all know, these things quickly get out of sync. And the effort of keeping documentation up to date is seldom a funny effort. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Often when you have an example of Imposed Duplication, other ways exist to solve it. Code is often duplicated into documentation because it is not available externally in a concise form. Perhaps you could get away with the BDD form of doing it, having running pieces of business rules. That would in many ways remove duplication. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I don't have much to concrete to say about it concerning our prime artifact: the code. Except one thing. You don't duplicate unless you have a really, really good reason for it. Duplication leads to anger, anger leads to hate...hate leads to suffering.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6824361431251463318?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6824361431251463318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6824361431251463318' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6824361431251463318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6824361431251463318'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-principles-don.html' title='Essential Software Principles: Don&amp;#39;t Repeat Yourself (DRY)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-3965856949149675626</id><published>2009-01-11T21:09:00.001+01:00</published><updated>2009-01-11T21:09:12.546+01:00</updated><title type='text'>Essential Testing Practices: Arrange, Act, Assert (AAA)</title><content type='html'>&lt;p&gt;Unit testing is an important practice for developing a system. There's many things to it, and many reasons behind it, things I'll probably get into at a later time. One of the aspects about HOW tests are written is the structure of the tests. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Since unit testing was introduced, there has been many ways of specifying unit tests. The usefulness of mocking frameworks has been more and more acknowledged, but the structure of tests have often suffered under immature frameworks (and languages!). &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The structure of unit tests matter because it makes it    &lt;br /&gt;- easier to understand the usage of the code under test    &lt;br /&gt;- easier to change    &lt;br /&gt;- easier to fix    &lt;br /&gt;- easier to write. You should be able to do it in the natural way you think about it. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The Arrange, Act, Assert unit testing structure pattern is an old way of solving this. The concept is utterly simple to understand: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;     &lt;br /&gt;First you arrange the state of the test. The you act by executing the code that is tested. At last you assert by checking that what you expect to happen actually has. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;   &lt;br /&gt;Note: Both Typemock and RhinoMocks support the AAA syntax. That means you don't need to/shouldn't use the record/replay mode anymore. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-3965856949149675626?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/3965856949149675626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=3965856949149675626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3965856949149675626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3965856949149675626'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-testing-practices-arrange-act.html' title='Essential Testing Practices: Arrange, Act, Assert (AAA)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-7043619649326869988</id><published>2009-01-10T13:20:00.000+01:00</published><updated>2009-01-10T13:20:00.459+01:00</updated><title type='text'>Interesting Software Practices: Code in non-English</title><content type='html'>&lt;p&gt;Which language to write code and comments in can sometimes come up as a question in countries where English isn't the native language.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;There's both good and bad things with doing this, and I thought I'd list a few thoughts about it.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The bad things about writing code and comments in your own language is:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;People that don't speak the language can't easily work with the system. This involves both professionals moving to a foreign country and concerning outsourcing.&amp;#160; &lt;/li&gt;    &lt;li&gt;There will always be mix of languages involved. Any external libraries/frameworks/components will use a different language. &lt;/li&gt;    &lt;li&gt;Any characters not present in the English language will have to be converted somehow. If there's no match, this can lead to various translations. &lt;/li&gt; &lt;/ul&gt;  &lt;br /&gt;The good things about using your own language is:   &lt;ul&gt;   &lt;li&gt;You might have an easier time with your ubiquitous language. Speaking in a mixture of languages or trying to translate could lead to misunderstandings and loss of important distinctions. &lt;/li&gt;    &lt;li&gt;You might use less time finding the correct words. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Did I forget anything obvious? What do you think?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-7043619649326869988?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/7043619649326869988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=7043619649326869988' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7043619649326869988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7043619649326869988'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-software-practices-code-in.html' title='Interesting Software Practices: Code in non-English'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8026178682501196353</id><published>2009-01-09T16:10:00.000+01:00</published><updated>2009-01-09T16:10:00.382+01:00</updated><title type='text'>Interesting Software Books: Dreaming in Code</title><content type='html'>&lt;p&gt;Dreaming in Code is a novel best described by the author himself: &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&amp;quot;&lt;i&gt;Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software&lt;/i&gt; ... I spent three years following the work of the Chandler developers as they scaled programming peaks and slogged through software swamps. In &lt;i&gt;Dreaming in Code&lt;/i&gt; I tell their stories.&amp;quot;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;This is not a book meant for the general developer, at least not so much to learn about software development. It is not supposed to be either. I'd recommend it for a developer as an interesting story only. But the main reason I'm mentioning it here is that I think it could have value for an outsider to learn many things about software development. And doing it through an interesting story. It does so partly by telling a story, and with that showing (an example) of a software process (granted quite different from many non-open source projects), and partly by getting into important information and characteristics about our industry. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Here's one of the less informative but quite funny jokes about our profession (I'm copying it since he said himself it could be found a myriad of places) &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;A Software Engineer, a Hardware Engineer, and a Departmental Manager were on their way to a meeting in Switzerland. They were driving down a steep mountain road when suddenly the brakes on their car failed. The car careened almost out of control down the road, bouncing off the crash barriers, until it miraculously ground to a halt scraping along the mountainside. The car's occupants, shaken but unhurt, now had a problem: They were stuck halfway down a mountain in a car with no brakes. what were they to do?    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;I know&amp;quot;, said the Departmental Manager. &amp;quot;Let's have a meeting, propose a Vision, formulate a Mission Statement, define some Goals, and by a process of Continuous Improvement find a solution to the Critical Problems, and we can be on our way.&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;No, no&amp;quot;, said the Hardware Engineer. &amp;quot;That will take far too long, and, besides, that method has never worked before. I've got my Swiss Army knife with me, and in no time at all I can strip down the car's braking system, isolate the fault, fix it, and we can be on our way.&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Well&amp;quot;, said the Software Engineer, &amp;quot;before we do anything, I think we should push the car back up the road and see if it happens again.&amp;quot;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8026178682501196353?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8026178682501196353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8026178682501196353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8026178682501196353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8026178682501196353'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-software-books-dreaming-in.html' title='Interesting Software Books: Dreaming in Code'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6375665375755291831</id><published>2009-01-08T23:15:00.003+01:00</published><updated>2009-01-08T23:18:24.673+01:00</updated><title type='text'>Essential Software Refactorings: Compose Method</title><content type='html'>&lt;p&gt;Joshua Kerievsky introduced a refactoring in his (great) book &lt;a href="http://www.amazon.com/Refactoring-Patterns-Addison-Wesley-Signature-Kerievsky/dp/0321213351" target="_blank"&gt;Refactoring to Patterns&lt;/a&gt;, which involves a practice I believe strongly in. The refactoring is called Compose Method. (Spoiler: It is really all about using short and descriptive methods.)&lt;/p&gt; &lt;p&gt;   &lt;br /&gt;The technique is to transform complex logic into a number of self-explanatory methods. The whole point is to increase understandability, and by that also maintainability. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Here's a simple example taken from the &lt;a href="http://www.industriallogic.com/xp/refactoring/composeMethod.html" target="_blank"&gt;industrial logic catalog page&lt;/a&gt; for this refactoring. You have a complex method. To increase clarity, you refactor out the individual parts into smaller methods, making the logic easier to understand (I don't fully agree with the coding standard though):&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;img src="http://www.industriallogic.com/xp/refactoring/images/composeMethod.jpg" /&gt;     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The main advantage with this approach is that core logic will be more readable and maintainable. A disadvantage is that classes will be very fragmented, which can be annoying. It can also affect debugging, since logic is so decentralized. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;In terms of length of methods, Joshua defines composed methods as usually being about five lines long, rarely over ten.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Long methods have many undesirable properties, like being harder to understand, harder to refactor and containing duplicated logic.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6375665375755291831?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6375665375755291831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6375665375755291831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6375665375755291831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6375665375755291831'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-refactorings-compose.html' title='Essential Software Refactorings: Compose Method'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-7563476464403027869</id><published>2009-01-07T22:30:00.001+01:00</published><updated>2009-01-07T22:30:09.814+01:00</updated><title type='text'>Essential Software Concepts: Liskov Substitution Principle (LSP)</title><content type='html'>&lt;p&gt;The original definition of the principle is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is all about substitution. Any place where a base class is used in the code, you should be able to use a subclass as well.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;A few implications come from this:     &lt;br /&gt;- You shouldn't do runtime checks for which subtype a certain object is. That means it is not automatically extendable and must be modified each time a new subclass is added.     &lt;br /&gt;- You shouldn't do less in a derived class. That means for instance that you shouldn't override a certain method and just leave it empty. That's not always a violation of LSP, but it can be.     &lt;br /&gt;- You shouldn't hide the implemention of a base class method (by using new). If you have a method that takes in an object of the type of the base class and calls such a method, only the base class method will be called.     &lt;br /&gt;- Even if it is often said that IS A means inheritance is the right approach, that not really true.&amp;#160; Substitutability should be taken into account.     &lt;br /&gt;- You can't simply look at the implementation of the model in isolation and decide if it is correct or not. You need to take into account the natural assumptions users will have about them. KISS still applies though.     &lt;br /&gt;- Not following this can bring out some hard to find bugs if someone else believes the implementation follows LSP. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-7563476464403027869?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/7563476464403027869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=7563476464403027869' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7563476464403027869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7563476464403027869'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-liskov.html' title='Essential Software Concepts: Liskov Substitution Principle (LSP)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-5957470056208815850</id><published>2009-01-06T23:05:00.002+01:00</published><updated>2009-01-06T23:07:01.012+01:00</updated><title type='text'>Essential Software Concepts: The Open/Closed Principle (OCP)</title><content type='html'>&lt;p&gt;Another essential software concept is what is known as the Open/Closed Principle. It's again a simple concept that is important to follow. The definition is as follows:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.&amp;quot; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The whole point is that in places where you expect to extend the functionality you should work to make sure that you don't need to change existing code to solve it. The code should be designed in a way that enables you to extend the behavior by for instance adding new classes that automatically works with the current model. This is usually solved through abstractions and polymorphism, and a number of patterns can help solve this. A common mantra for code that is expected to change is nonetheless followed: code to abstractions, not implementations. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;What the principle tries to achieve is to make sure that changes have as little as possible effect on the current implementation. If you need to modify existing code you need to identify the various parts needing change and you impose the risk of making breaking changes. Extending the behavior can often be a lot easier and can enable a more flexible solution. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Does this mean that every piece of code should be written using abstractions to allow extensions more easily? Certainly not! Abstractions can add unnecessary code, can make the parts that are supposed to change less obvious and can add to the complexity of the solution. Unless you know that something is expected to change, an old childhood rule is nice to follow: Trick me once, shame on you, trick me twice, shame on me. Don't do the extra work up front unless you know it is necessary. But once you need it, don't hesitate to put it in. Uncle Bob has a wise quote about this: &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;Resisting premature abstraction is as important as abstraction itself&amp;quot;.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-5957470056208815850?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/5957470056208815850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=5957470056208815850' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5957470056208815850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5957470056208815850'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-openclosed.html' title='Essential Software Concepts: The Open/Closed Principle (OCP)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4999263049184825104</id><published>2009-01-05T21:46:00.003+01:00</published><updated>2009-01-05T21:50:00.020+01:00</updated><title type='text'>Essential Software Concepts: The Single Responsibility Principle (SRP)</title><content type='html'>&lt;p&gt;&lt;/p&gt; The Single Responsibility Principle defines that a class should have only one responsibility, also defined as only one reason to change. (Defined by Uncle Bob in Agile Principles, Patterns, and Practices in C#. A book well worth reading.)  &lt;p&gt;   &lt;br /&gt;In other words, it should only be responsible for one thing. Do only one thing. Handle only one area. Potato, Potato.&amp;#160; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The principle is really simple in concept, yet it can be difficult to follow at times. It is an important principle to follow because it will make your classes more robust to change. Coupled responsibilities can lead to code that breaks more easily, changes that are more expensive to implement, tests that are harder to make concrete, less readable code and more code to step through when debugging.    &lt;/p&gt;  &lt;p&gt;&lt;br /&gt;That doesn't mean you _always_ need to follow it. The cost of separating things can be higher than the cost of holding them together. If you expect no change, then stay with that. Possibly separate the concepts by creating separate interfaces. That way the implementation stays coupled, but at least the rest of the system is not coupled to the mess. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4999263049184825104?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4999263049184825104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4999263049184825104' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4999263049184825104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4999263049184825104'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-single.html' title='Essential Software Concepts: The Single Responsibility Principle (SRP)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1945148920322137008</id><published>2009-01-04T22:14:00.001+01:00</published><updated>2009-01-04T22:14:00.495+01:00</updated><title type='text'>Essential Management Practices: Don't micro manage</title><content type='html'>&lt;p&gt;Do you like to micro manage, or are you being micro managed?&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;That has really got to stop. It is one of the most annoying practices I know about, and one which makes no sense in our industry. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Software development is a form of knowledge management. Developers (obviously) use their heads as their tools. If there is one thing knowledge management professionals despise, it is being told at a low level exactly what to do.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;In essence this just tells someone that you don't trust their work or judgment. Not exactly a good way to get motivated employees that feels ownership for the project. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I'm not advocating that you shouldn't follow up work. Absolutely not. In fact, code reviews should be a part of any development organization. I think that is quite different though. Verifying and sharing a solution is different from closely managing how to solve an issue. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1945148920322137008?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1945148920322137008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1945148920322137008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1945148920322137008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1945148920322137008'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-management-practices-don.html' title='Essential Management Practices: Don&amp;#39;t micro manage'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4322417334964571689</id><published>2009-01-03T16:50:00.001+01:00</published><updated>2009-01-04T21:18:37.604+01:00</updated><title type='text'>Essential Software Concepts: Side-Effect-Free Functions</title><content type='html'>&lt;p&gt;I'll start of with a section about naming and understanding of the concepts involved. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Side-Effect-Free Functions is a name that will mean different things to different people. The explanation in common English is &amp;quot;a function without unintentional consequences&amp;quot;. If you use Side effects as explained in software science (&lt;a href="http://en.wikipedia.org/wiki/Side_effect_(computer_science)" target="_blank"&gt;wikipedia&lt;/a&gt;), a side-effect means any state change in the system. The explanation will then change to &amp;quot;a function without state changes&amp;quot;. Eric Evans in his Domain Driven Design (DDD) book further narrows the side-effect concept to mean &amp;quot;any change in the state of the system that will affect future operations&amp;quot;. So we have a situation where we have a common expression which is supposed to be understandable, but you need to be aware that that people can think of three different things when you talk about this. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Another concept we need to define is Functions. Functions is another concept with different meanings in different settings. In some languages, functions and methods means different things, which means you'll have two separate concepts. In .NET you only have methods, but in my experience functions and methods are used as synonyms in .NET realm. In DDD functions are explained as being operations that return results with no observable side effects. In DDD it is further explained that methods that result in modifications to observable state are called commands. I think that's a definition that is lost on most developers. I think it is more important to focus on the concept rather than that, so I won't pay more attention to that.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;(Just a stupid observation: If Functions as defined in DDD means &amp;quot;operations that return results with no observable side effects&amp;quot;, then coining an expression called &amp;quot;Side-Effect-Free Functions&amp;quot; does in fact not make any sense, since you can't have side effects in DDD Functions.) &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;There is a reason why we would want to separate operations that will change state and operations that only queries for information. Queries for information is in essence safe to use at any given moment, whereas state-changing operations, even if perceived safe, can be very hard to be certain about in a complex system. By separating them completely, you'll have an easier job handling that complexity. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I'm not so sure that this should be applied in every situation. But what I believe is an absolute demand is that you should be able to trust that a given method/function/operation does exactly what it says it does. Trust is the big thing here. If you have a method called GetBills(), and you in fact do a call to a GenerateBills() method within, we have a big trust issue! Let's not focus on the fact that these don't belong together, but you should at least have followed the concepts behind &lt;a href="http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-intention.html" target="_blank"&gt;Intention-Revealing Interfaces&lt;/a&gt;, and named it as GenerateAndGetBills() or such. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I believe the biggest issue here is the same as I came into in Intention-Revealing Interfaces; If you can't be sure that the parts of the system you are working with are behaving the way you think they should, then you'll use all your focus making sure they do, and not on the problem at hand. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;DDD also has a conclusion worth reading: &amp;quot;Place as much of the logic of the program as possible into functions, operations that return results with no observable side effect. Strictly segregate commands into very simple operations that do not return domain information.&amp;quot;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Update&lt;/h2&gt;  &lt;p&gt;Have a look at the link provided in Morten's comment below for more info on commands and queries. Thanks :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4322417334964571689?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4322417334964571689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4322417334964571689' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4322417334964571689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4322417334964571689'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-side-effect.html' title='Essential Software Concepts: Side-Effect-Free Functions'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6002127628336442612</id><published>2009-01-02T17:17:00.001+01:00</published><updated>2009-01-02T17:17:01.497+01:00</updated><title type='text'>Essential Software Concepts: Intention-Revealing Interfaces</title><content type='html'>&lt;p&gt;Donald Knuth famously said &amp;quot;Software is hard&amp;quot;. And that is an absolute truth. But that doesn't mean we shouldn't always strive to make things as simple as possible. One concept that is easy to understand that can help in that is Intention-Revealing Interfaces. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The interface comprises all the publicly visible parts. Together they should combine to an Intention-Revealing Interface. That means an interface where the intent and usage pattern is clear. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;One of the largest costs of software development is understanding and changing code. That certainly involves the maintenance phase of the project, but living in the increasingly agile world we do, it most certainly is a continuous factor throughout the initial development of the system. If the code you need to work with is poorly described, you'll have to keep digging into code all the time, trying to get a full understanding of how everything works before you dare to do changes. Unfortunately, since our brain can only hold _so_ much information at a time, this severely limits our ability to to work efficiently. Instead of using our focus on the problem at hand, all is wasted on the surroundings. Like Eric Evans said, &amp;quot;If a developer must consider the implementation of a component in order to use it, the value of encapsulation is lost&amp;quot;.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;So work continuously to be as clear as possible in how you name your classes, methods, properties, etc. That means describing what they do, and not how they do it. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;And a last thing. Don't be afraid of long method names. Use as long a name you need to describe what a particular part does. If you need to use many words to describe it, chances are you should start thinking about a refactoring.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6002127628336442612?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6002127628336442612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6002127628336442612' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6002127628336442612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6002127628336442612'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/essential-software-concepts-intention.html' title='Essential Software Concepts: Intention-Revealing Interfaces'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4836485648280091274</id><published>2009-01-01T20:35:00.002+01:00</published><updated>2009-01-01T20:37:15.592+01:00</updated><title type='text'>Interesting General Knowledge - Pareto's principle</title><content type='html'>&lt;p&gt;&lt;/p&gt; I don't remember when I first heard of Pareto's principle, but I've always been fond of it. It was originally used to state that 80 percent of Italian income went to only 20 percent of the population, but has since been used as a rule of thumb for a myriad of other cases.  &lt;p&gt;   &lt;br /&gt;I think it fits very well in the software domain. The exact numbers are not the important fact, but rather as a guiding principle of what takes more time than the other. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;It is not hard to think of a few examples that could follow the principle: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Creating demo-ware software will take 20% of the time, creating production grade software will take 80%. &lt;/li&gt;    &lt;li&gt;Creating 80% of a system will take 20% of the time. &lt;/li&gt;    &lt;li&gt;20% of a systems functionality will be used 80% of the time. &lt;/li&gt;    &lt;li&gt;Resolving 80% of the defects will take 20% of the time. &lt;/li&gt;    &lt;li&gt;Once you have done the 80% normal cases, fitting in the last 20% exceptional cases will take 80% percent of the time.&amp;#160; &lt;/li&gt;    &lt;li&gt;20% percent of a systems developers create 80% percent of the working functionality (Hopefully not :) )&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;   &lt;br /&gt;I know these are crazy numbers. And I know this is certainly not true in a lot of cases. But still, you'll benefit if you keep Pareto's principle in mind. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4836485648280091274?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4836485648280091274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4836485648280091274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4836485648280091274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4836485648280091274'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2009/01/interesting-general-knowledge-pareto.html' title='Interesting General Knowledge - Pareto&amp;#39;s principle'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1379283973737223790</id><published>2008-12-31T01:12:00.001+01:00</published><updated>2008-12-31T01:14:33.237+01:00</updated><title type='text'>Essential Software Concepts: Fail fast</title><content type='html'>&lt;p&gt;Software development is hard. Not only is development hard, the environment and hardware is not exactly fault proof. Let's not forget the users either, you can be sure they will do something you didn't think about. Or even the human factor in terms of deployment, database-updates and the like. So one of the few truths about software is that things will fail, the question is what you do about the failures.&amp;#160; &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;You generally have two (three) options in dealing with errors: you can try to make the system recover, or you can fail at once (Or you can try to swallow the error, and cross your fingers that it will work out in the end).&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Unless it is essential that the system shouldn't fail, I like to fail things fast. By that I mean, if something doesn't work properly then fail the operation as soon as possible. Failing doesn't mean crashing the application, you should provide an informative message to the user. Failing like this has, as usual, both advantages and disadvantages. The main advantage is related to tracking and fixing bugs. One of the major efforts in fixing bugs is understanding where and why it happened. If you fail early rather than late, you'll most likely have an easier task tracking the bug down. You don't have to worry about the system having worked in an inconsistent state and there's a larger chance that the stack trace actually shows where the problem is located. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The main disadvantage, or rather question to ask yourself is &amp;quot;is failing early fine in production?&amp;quot;. If you can't say yes to this, then know that you'll have a much more complex bug-tracking time ahead of you. It's not an easy question though. Failing early can sometimes mean that users are unable to use important functionality because of a strict policy of failing early. Furthermore, a system that keeps failing is not good for building customer trust. Perhaps it is better to fix it in the background in some cases. Whatever you choose, it is certainly not a black or white question.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1379283973737223790?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1379283973737223790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1379283973737223790' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1379283973737223790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1379283973737223790'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/12/essential-software-concepts-fail-fast.html' title='Essential Software Concepts: Fail fast'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4189256986424827784</id><published>2008-12-30T00:17:00.001+01:00</published><updated>2008-12-30T00:17:40.120+01:00</updated><title type='text'>Essential Software Concepts: Broken windows</title><content type='html'>&lt;p&gt;The concept of broken windows is one of the concepts I remember best from the Pragmatic Programmer book. It is one of those simple concepts that you need to be aware of as a developer. But even though it is known to most developers (at least in principle), it is still violated all over the place - just to try to crank out a little more functionality. The technical debt you build up there you will pay for a long time. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;I'll explain the concept, but if you don't know it, you really should go ahead and read the Pragmatic Programmer book. A quick and good read. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The concept can be explained like this: Say you have a house. As long as the house stands firm, there's a good chance it will keep that way. But as soon as a window is broken, and nothing is done about it, the downward spiral begins. Another window is broken, vandals run free, and eventually you get to the point where restoring the house it's former self is more costly than just replacing it. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;This certainly holds true for software projects as well. If you keep the architecture sound and continuously work to hold the implementation maintainable; by separating concerns, avoiding duplication, and so forth and so on, and if you fix problems once you find them, you'll have a much larger chance of keeping things maintainable than if you don't. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Taking the time to implement something properly will benefit you in the long run (and I'm talking weeks and months here, not years). The additional time it will take to implement something properly cannot be compared to the cost of being bogged down in a poorly architected code. Doing changes (again, we're talking weeks and months here) will be more costly, and you don't need to pay that price. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4189256986424827784?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4189256986424827784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4189256986424827784' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4189256986424827784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4189256986424827784'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/12/essential-software-concepts-broken.html' title='Essential Software Concepts: Broken windows'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-5086520901676595616</id><published>2008-12-29T01:17:00.002+01:00</published><updated>2008-12-29T01:20:22.255+01:00</updated><title type='text'>Essential Database Practices: Parameterized queries</title><content type='html'>&lt;p&gt;When you access a relational database the old-fashioned way (not ORM's and LINQ), you generally have three options; you can call stored procedures, you can send queries manually as a concatenated text block or you can send queries manually as a parameterized query.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Option one and three are both valid ways of doing it, but if you ever create queries as concatenated text block WITHOUT parameters you need to stop. I'll explain why by explaining why parameterized queries are good for you.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;You should use parameterized queries for three reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;SQL injection &lt;/li&gt;    &lt;li&gt;Query plan caching &lt;/li&gt;    &lt;li&gt;Query plan cache size &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;SQL injection&lt;/h2&gt;  &lt;p&gt;This is the most obvious. It is hopefully known to all, as much focus has been put on it in recent years. If not, have a look in &lt;a href="http://en.wikipedia.org/wiki/SQL_injection" target="_blank"&gt;wikipedia&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Query plan caching&lt;/h2&gt;  &lt;p&gt;Every time a query is executed in SQL Server, it goes through two main steps: parsing/compilation and execution. During the parsing/compilation step, SQL Server creates a plan for how it will run the query. Once this is completed, the query is put in the query plan cache and executed. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;In the parsing/compilation step, before doing anything, SQL Server will look in the cache to see if the query plan has already been created. If it has, there is no need to create the plan again. Depending on the query and how many times the query is run, you can save a significant amount of time if the query is cached. &lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;The cache check is done by a look up in a hash table where the form of entry is the entire SQL query, formatting included. The reason I listed query plan caching for parameterized queries, is that the contents of the parameters does not matter, thus running the same query with a number of different parameters will result in using the same plan each time. If you concatenate your queries manually, a new plan will be made for each call. Note that this is important to remember also for the queries you create in your stored procedures. Use sp_executesql instead of just using exec to execute your queries, then you can also add parameters to your dynamic SQL. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Query plan cache size&lt;/h2&gt;  &lt;p&gt;For each query plan created the cache increases in size. The queries go out of the cache when they are not reused, but this can take some time on a busy server. I don't think this usually has a big impact, but creating a large amount of query plans does fill up the cache size. That means they use up an unneccessary amount of your server's ram. Shame on you.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you want to have a look at how much time the parsing/compilation step takes for a given query, run SET STATISTICS TIME ON before running the query. The actual cache can be accessed via the sys.dm_exec_cached_plans view. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-5086520901676595616?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/5086520901676595616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=5086520901676595616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5086520901676595616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/5086520901676595616'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/12/essential-database-practices.html' title='Essential Database Practices: Parameterized queries'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1728890905630959269</id><published>2008-12-29T01:09:00.002+01:00</published><updated>2009-01-03T12:34:58.380+01:00</updated><title type='text'>New blog series: Essential this, Interesting that</title><content type='html'>&lt;p&gt;I recently got the idea of a new form of blog posts I think will be interesting. Basically it involves covering topics that I find to be either essential or interesting within a particular area, and labeling&amp;#160; them visibly as such. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I hope you'll find value in it. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Happy holidays :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1728890905630959269?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1728890905630959269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1728890905630959269' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1728890905630959269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1728890905630959269'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/12/new-blog-series-essential-this.html' title='New blog series: Essential this, Interesting that'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1262503846169250037</id><published>2008-12-15T22:01:00.002+01:00</published><updated>2008-12-15T22:03:11.971+01:00</updated><title type='text'>Good stuff on Botnets, DDos and Scripting</title><content type='html'>&lt;p&gt;Rob Conery has a nice &lt;a href="http://blog.wekeroad.com/blog/the-perfect-storm-botnet/"&gt;blogpost&lt;/a&gt; titled &amp;quot;The Perfect Storm Botnet&amp;quot;. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;A good, fairly short read - a bit like kids horror stories for computer geeks, except for the fact that these are true of course. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So just watch out for all those *-injection attacks kids, it's seldom pretty&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1262503846169250037?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1262503846169250037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1262503846169250037' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1262503846169250037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1262503846169250037'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/12/good-stuff-on-botnets-ddos-and.html' title='Good stuff on Botnets, DDos and Scripting'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1605072669912726230</id><published>2008-11-30T18:28:00.002+01:00</published><updated>2008-11-30T18:40:15.505+01:00</updated><title type='text'>Another "fagdag" done</title><content type='html'>We once again had another "fagdag" yesterday, and I went away really pleased. The contents was good, but more than that, the discussions are really fruitful. I think we have some good things going there..&lt;br /&gt;&lt;br /&gt;It was on a Saturday, so it didn't last into eternity, but here's what was covered if anyone cares:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code Quality&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Claims-based identity&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Project demo: xxx Silverlight&lt;/li&gt;&lt;br /&gt;&lt;li&gt;BDD/TDD&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Testing legacy code&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Microsoft ORM Futures: Entity Framework V1/2, LINQ To SQL (lightning talk)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Powershell (lightning talk)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Parallell computing in .NET 4.0/VS2010 (lightning talk)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ninject (lightning talk)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;XAML Power Toys (lightning talk)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Onion Architecture (lightning talk)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1605072669912726230?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1605072669912726230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1605072669912726230' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1605072669912726230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1605072669912726230'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/11/another-fagdag-done.html' title='Another &quot;fagdag&quot; done'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4346727575216733844</id><published>2008-11-29T22:03:00.001+01:00</published><updated>2008-11-29T22:04:19.038+01:00</updated><title type='text'>@Twitter</title><content type='html'>Need to find out what all the buzz is about... You can find me at twitter.com/RuneSundling&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4346727575216733844?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4346727575216733844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4346727575216733844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4346727575216733844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4346727575216733844'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/11/twitter.html' title='@Twitter'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-3491854423893826556</id><published>2008-11-13T22:25:00.004+01:00</published><updated>2008-11-13T22:33:49.717+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCRUM'/><title type='text'>SCRUM in 5 minutes</title><content type='html'>Want to get the gist of SCRUM, but have only got 5 minutes?&lt;br /&gt;&lt;br /&gt;Check out &lt;a href="http://www.softhouse.se/Uploades/Scrum_eng_webb.pdf"&gt;this pdf.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-3491854423893826556?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/3491854423893826556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=3491854423893826556' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3491854423893826556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/3491854423893826556'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/11/supershort-scrum-introduction.html' title='SCRUM in 5 minutes'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8909117462249160989</id><published>2008-11-13T22:22:00.003+01:00</published><updated>2008-11-13T22:34:04.552+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET 4.0'/><title type='text'>.NET 4.0 poster</title><content type='html'>Want a fancy poster showing you the contents of .NET 4.0?&lt;br /&gt;&lt;br /&gt;If you haven't seen it yet, you can get it &lt;a href="http://blogs.msdn.com/brada/archive/2008/10/29/net-framework-4-poster.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://blogs.msdn.com/blogfiles/brada/WindowsLiveWriter/55ff37220b2c.NETFramework4Poster_67A1/PDC2008-NETFX4.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 640px; height: 427px;" src="http://blogs.msdn.com/blogfiles/brada/WindowsLiveWriter/55ff37220b2c.NETFramework4Poster_67A1/PDC2008-NETFX4.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8909117462249160989?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8909117462249160989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8909117462249160989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8909117462249160989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8909117462249160989'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/11/net-40-poster.html' title='.NET 4.0 poster'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1233492104864137563</id><published>2008-10-29T23:42:00.009+01:00</published><updated>2008-11-13T22:34:51.973+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Threading'/><category scheme='http://www.blogger.com/atom/ns#' term='Parallel Extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET 4.0'/><title type='text'>.NET and Parallelism</title><content type='html'>I attended a really interesting &lt;a href="http://channel9.msdn.com/pdc2008/TL26/" target="out"&gt;session&lt;/a&gt; today about the current work being done with parallelism for the .NET framework 4.0.  &lt;br /&gt;&lt;br /&gt;And the future is bright! :)&lt;br /&gt;&lt;br /&gt;You should see the session yourself, but I'll try to summarize what I got out of it anyway.&lt;br /&gt;&lt;br /&gt;Threading and parallelism are important now, but will become ever more important in the future. Our processors have stopped getting noticeably faster, but they are continuing to become smaller and more efficient, which enables to have more and more of them. Currently most of us are running with two cores, and quite a few with four. Hardware producers are saying that 80-100 cores are withing reach within a not too distant future for regular machines. We absolutely need to design for this.  &lt;br /&gt;&lt;br /&gt;So we need to start taking threads ever more into account. But it is such a complicated field, with locking, contention etc. &lt;br /&gt;&lt;br /&gt;The current implemenation of threads aren't helping either. Create a thread and it takes 1 mb of committed memory. Try to manage them, follow them with current debugger support in VS, etc etc - it's not easy. &lt;br /&gt;&lt;br /&gt;First of all, the annoying Thread will be replaced by much more enjoyable Task in 4.0(The thread will live on, but the Task should take over in terms of being used.).&lt;br /&gt;&lt;br /&gt;The much improved (compared to threads) Task API, their internal handling, and the new tools to support them and parallelism (in VS2010) looks really cool. &lt;br /&gt;&lt;br /&gt;I can't tell you how tasks differs from threads yet, except that they are similar, but that tasks has a more advanced API accompanying them, and a different internal handling. &lt;br /&gt;&lt;br /&gt;Consider the scenario of running a program on a two or four (or something else) core computer. What's the best number of threads you could possibly have then? The answer is of course two on the two-core, four on the four-core, and so on. (Don't design your app to run with two parallel execution paths if you have a two-core computer, you want these things to scale when you them on much more powerful servers.) &lt;br /&gt;&lt;br /&gt;When you create a myriad of threads, you get the problem with the constant fight for resources and time. With tasks this is handled in a different way. Consider this simple scheme:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;One global queue where all your tasks are created&lt;/li&gt;&lt;br /&gt;&lt;li&gt;One local queue for each of your processors&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Once a task is created it is put into the global queue, and then moved into one of the processors local queue. &lt;br /&gt;&lt;br /&gt;Each individual processor then processes each of the queued tasks in a LIFO fashion, as the last one added is the one most likely to have information cached. Once it is done with its tasks, it steals (stealing is good here) in a FIFO fashion from the other lists, attaining a few things: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;None of your processes are standing lazily around&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You will get into much less contention issues, since you grab tasks from different sides&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Everything is executed in an orderly, efficient manner&lt;/li&gt;&lt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So how do we use these tasks?&lt;br /&gt;&lt;br /&gt;You create tasks much in the same fashion as you created threads. The difference is you have quite a few more options in how they are handled: if you want them to work together with the parent thread, if you want to crash the main thread if there is an unhandled exception on a child-thread, in creating generic versions to return a particular type of data (+++++++). Check it out yourself. &lt;br /&gt;&lt;br /&gt;You also get more structured assistance, which looks really nice. Instead of running for instance a standard ForEach which runs through each item sequentially, you can use a new Parallel.ForEach which runs each task in parallel. This will work great if each step can be run in isolation and don't depend on each other, but even if they do, you can use the API to say stop, and then for each task run it check whether stop has been set, in practice stopping much more prematurely. With lists you can just add ToParallel() to create a paralell version of the handling of for instance a LINQ query. &lt;br /&gt;&lt;br /&gt;I really should go on and on. &lt;br /&gt;&lt;br /&gt;And I have forgotten to mention the new Visual Studio tools, haven't I? There are a couple of new debugger-windows which seem extremely helpful in visualising which tassk are currently running, which tasks have been created, what values the tasks have, how the stack trace of each task is, and what methods any and every tasks have hit. Hard to explain, but you'll like it!&lt;br /&gt;&lt;br /&gt;This is just emerging, but this will make parallel life much easier in the future. I'll surely be looking much into this!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1233492104864137563?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1233492104864137563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1233492104864137563' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1233492104864137563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1233492104864137563'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/10/points-of-interest-net-and-parallelism.html' title='.NET and Parallelism'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1117684797720918653</id><published>2008-10-29T22:57:00.008+01:00</published><updated>2008-11-13T22:35:14.785+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows Azure'/><category scheme='http://www.blogger.com/atom/ns#' term='Cloud-computing'/><title type='text'>Windows Azure</title><content type='html'>As you've bound to have heard by now, Microsoft recently announced Windows Azure at the PDC08, the new Cloud operating system. &lt;br /&gt;&lt;br /&gt;I must say I'm really intreagued by this. &lt;br /&gt;&lt;br /&gt;The possibilities are big. Think of the extreme costs you have for running and maintaining an application. For instance:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You need to be able to scale according to user interest&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You need to be highly responsive - which means a server in Norway might work pretty bad when accessed from US or Asia&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You need to have a server park in at the very least one place to just host the applications (if you can afford the downtime a electricity failure would cause, or possibly the loss of data and hardware a fire/earthquake could cause) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;You need failover database solutions (If manually recreating a backup won't do)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Some data might not be allowed to be stored in some countries, you need to be sure that whatever solution you choose will handle this properly&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Instead of these options you could get into some sort of external hosting solution. And this is in many regards what MS is offering with Azure, but I bet a fair bit of hosting-providers are literally shaking now after the new plans of MS have been introduced. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.microsoft.com/azure/images/servicesPlatform.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 490px; height: 226px;" src="http://www.microsoft.com/azure/images/servicesPlatform.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We are talking big, big scale investsments in this. The tight integration with the current MS software and process of doing things (Visual studio for instance) doesn't hurt in the process of making this popular. And it's not like they don't have quite a bit of internal expertise in this already; for instance through running the Live services.&lt;br /&gt;&lt;br /&gt;One of the most important things are the continous expectations of ever more interactive and graphics-heavy software delivered at the blink of an eye over the internet. You can do this yourself, but I doubt the cost/value calculation will be on your size. &lt;br /&gt;&lt;br /&gt;Another things is scaling. With Azure, or the cloud service offering, you can scale up or down according to user interest. An application with user peaks that vary over time can be tough financially, since you can end up with much more hardware set up than you usually need. &lt;br /&gt;&lt;br /&gt;One big issue is privacy. If you host this in the cloud, you put you data in Microsofts hands. Are you cool with that? &lt;br /&gt;&lt;br /&gt;As you have noticed, my detailed understand of Azure is lacking, to be honest I haven't bothered focusing too much on it, so much else which is intersting here at PDC! I do believe though that this can become such a big thing, and I'm expecting to have to consider it much more in the future - but for now I'll leave it to someone else. &lt;br /&gt;&lt;br /&gt;Check out Azure &lt;a href="http://www.microsoft.com/azure/default.mspx" target="out"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1117684797720918653?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1117684797720918653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1117684797720918653' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1117684797720918653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1117684797720918653'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/10/points-of-interest-windows-azure.html' title='Windows Azure'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-2611100313398031042</id><published>2008-10-08T16:47:00.005+02:00</published><updated>2008-10-09T09:01:07.393+02:00</updated><title type='text'>Microsoft completely miss the point of Agile Development?</title><content type='html'>Slightly annoyed about a &lt;a href="http://www.cio.com/article/451622/Microsoft_Announces_Visual_Studio_._Developers_Respond.?page=1"&gt;post&lt;/a&gt; in CIO about Visual Studio 2010. The contents of the article is not so interesting, but a user comment annoyed me. &lt;br /&gt;&lt;br /&gt;"Microsoft, unfortunately, continues to show that they in fact completely miss the point of agile software development. Agility is about simplicity of design, of process, of feedback mechanisms. It is also about open, community-based tools, frameworks, and standards. MS keeps offering hilariously bloated, complex, monolithic, closed, and expensive IDE "solutions" that worsen every problem they attempt to solve. Visual Studio is now, at more than 43 million lines of code (and counting), so counter to agile development practices that I must question its architects' sanity or motives. Is all of this bureaucratic bloat forced upon the VS team by clueless marketing drones? That might explain the continuing madness." &lt;br /&gt;&lt;br /&gt;This guy has just completely missed the point. A few things: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Agile = open, community-based tools, frameworks, and standards. &lt;/span&gt;&lt;br /&gt;Why?? Agile is (a lot more than this, but also is) about using agile methodologies and practices to drive a project to success. Any software that can help in this endavour is great, but all I care about is using the best software. Whether it is Microsoft or Thoughtworks that delivers my CI system is unimportant to me, as long as I get to make the choice. I can use an open source IDE, CI, source control, build tool, test tool, etc. if I want to (and I often do), and that's all that matters. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt; MS keeps offering hilariously bloated, complex, monolithic, closed, and expensive IDE "solutions" that worsen every problem they attempt to solve.&lt;/span&gt;&lt;br /&gt;Dude, Visual Studio is a great tool! Together with Resharper it really is a tool that rocks :) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;That might explain the continuing madness&lt;/span&gt;&lt;br /&gt;Keep up the madness! I, for one, can't wait to see what comes next. &lt;br /&gt;&lt;br /&gt;Admittedly Microsoft wants as big a part of the pie as possible, and that can certainly lead to situations that is less than optimal, but just because everything isn't good about Microsoft certainly doesn't make everything wrong.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-2611100313398031042?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/2611100313398031042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=2611100313398031042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2611100313398031042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/2611100313398031042'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/10/microsoft-completely-miss-point-of.html' title='Microsoft completely miss the point of Agile Development?'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-331145855713066565</id><published>2008-09-26T11:34:00.005+02:00</published><updated>2008-09-26T11:48:27.064+02:00</updated><title type='text'>NNUG Oslo</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://tbn0.google.com/images?q=tbn:xwSKfCC3EBZ82M:http://www.ut24.no/admin/upics/img_980.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 130px;" src="http://tbn0.google.com/images?q=tbn:xwSKfCC3EBZ82M:http://www.ut24.no/admin/upics/img_980.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Just wanted to note that I've just been elected into the board of the &lt;a href="http://www.nnug.no/Avdelinger/Oslo/"&gt;Norwegian .NET User Group (NNUG) - Oslo&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;I'm looking forward to the experience! Hopefully something good will come out of it for you too :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-331145855713066565?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/331145855713066565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=331145855713066565' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/331145855713066565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/331145855713066565'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/09/nnug-oslo.html' title='NNUG Oslo'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1839690806709489802</id><published>2008-09-23T20:52:00.005+02:00</published><updated>2008-09-25T14:36:42.207+02:00</updated><title type='text'>Beware the enum-compilation!</title><content type='html'>I was recently made aware of a real eye-opener when it comes to how enums are compiled by the c# compiler. &lt;br /&gt;&lt;br /&gt;When you compile a c# project, each enum is internally replaced with the corresponding value of the enum. What that mean is that in the IL code the reference to the enum is replaced by the integer value in the enum. &lt;br /&gt;&lt;br /&gt;This could give you a problem if you redefine an enum that is used across multiple dlls. Say you have an enum with two values, and you decide to switch their place in the enum definition. If you only compile the dll with the enum definition, the other dll will work the opposite of what is fairly natural to expect!&lt;br /&gt;&lt;br /&gt;The enum tip of the day is thus: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Always specify the value of the enum in the defintion rather than using the default order. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Never replace a value with another, always add new values to a number higher than the current top&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Always follow the points above. Would you like try to debug a patch creating that problem?&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1839690806709489802?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1839690806709489802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1839690806709489802' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1839690806709489802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1839690806709489802'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/09/beware-enum-compilation.html' title='Beware the enum-compilation!'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-556332477988830330</id><published>2008-09-18T16:12:00.006+02:00</published><updated>2008-09-18T16:17:44.537+02:00</updated><title type='text'>Definition of good quality solutions</title><content type='html'>Recently I heard a new definition for what a good quality solution should be like: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;robust and stable&lt;/li&gt;&lt;br /&gt;&lt;li&gt;easily maintainable&lt;/li&gt;&lt;br /&gt;&lt;li&gt;good performance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;good user experience&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If asked I would have listed this somewhat differently, but my point is rather: &lt;br /&gt;&lt;br /&gt;This must be the most obvious thing. Could this possibly be necessary to say? &lt;br /&gt;(Note: Was not directed at me :))&lt;br /&gt;&lt;br /&gt;Could someone possibly try to create ..&lt;br /&gt;&lt;ul&gt;&lt;li&gt;nonrobust&lt;/li&gt;&lt;br /&gt;&lt;li&gt;unstable&lt;/li&gt;&lt;br /&gt;&lt;li&gt;hard to maintain&lt;/li&gt;&lt;br /&gt;&lt;li&gt;lousy performance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;poor user experience&lt;/li&gt;&lt;/ul&gt;.. code deliberately? &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I doubt it. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You won't always be able to do it - there's always compromises (maintainability+performance, time-contraints, etc), but still. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There's not really much point to this post. I just wanted to make a point. Or something.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-556332477988830330?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/556332477988830330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=556332477988830330' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/556332477988830330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/556332477988830330'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/09/definition-of-good-quality-solutions.html' title='Definition of good quality solutions'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8737917074038224323</id><published>2008-09-17T22:44:00.005+02:00</published><updated>2008-09-17T23:58:40.101+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Boo AOP'/><title type='text'>Boo... Worth the time?</title><content type='html'>One of my colleagues, &lt;a href="http://tore.vestues.no"&gt;Tore Vestues&lt;/a&gt;, has recently sparked an interest in Boo internally. &lt;br /&gt;&lt;br /&gt;Boo is, for those who don't know it, just another .NET language. I like &lt;a href="http://ayende.com/Blog/archive/2007/12/17/The-Boo-Language.aspx"&gt;Ayendes&lt;/a&gt; definition: &lt;br /&gt;&lt;blockquote&gt;Boo is an object oriented, statically typed language for the common language runtime with a Python inspired syntax and focused on language and compiler extensibility. &lt;/blockquote&gt;&lt;br /&gt;Today we had a voluntary Boo-night, which meant about 15 developers having a go at Boo for a while. Good stuff :) &lt;br /&gt;&lt;br /&gt;First of all, I really don't know Boo (at least not yet), but there's one thing I totally dig about it - the way anything and everything can be put together at compile-time. You got code generation at compile-time, without all the runtime hazards of standard code-generation. It really just rocks compared to the everyday c#-code. &lt;br /&gt;&lt;br /&gt;For instance you can define what a singleton is one place, then just add a [singleton]-attribute around your class to define for the compiler to compile this as a singleton. Or a better example Tore came up with: INotifyPropertyChanged. Anyone like writing that code over and over again? How sweet is it to get to write it once, and use it over and over again? I can think of lot's of examples were I keep rewriting annoying boring code, which isn't just boring to write, it provokes errors, and it makes the code much harder to read than a declarative style possibly could. &lt;br /&gt;&lt;br /&gt;So what's the negative things then? &lt;br /&gt;&lt;br /&gt;First of all, Boo is a separate .NET language. It will compile to IL-code, but you need to use it fully in it's own assembly. You can of course not mix and match. In other words, you won't get C#-code with Boo compile-time code-generation. Unfortunately :( &lt;br /&gt;&lt;br /&gt;Number 1 once again. This is the biggest problem the way I see it. The language in itself seems really cool. But what's the chances for mainstream development? Will you implement part of your application in Boo, or everything? Can you justify the cost of learning up all developers on the project to the Boo way of doing things? (I don't know, so I'm really just asking questions) Is it mature enough or has proper tool-support? (not yet) &lt;br /&gt;&lt;br /&gt;I guess most of the initial issues with Boo comes from the fact that it's just new (of sorts) - with the standard problems you have when something is new. There is not enough documention, tool-support, or followers. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But isn't many of the concepts I just mentioned possible in C# for instance? It is, to some extent. You have AOP-support through for instance PostSharp, which does it's magic after your code has compiled. Now I don't really know just how big a difference these two approaches make (Can someone please educate me?), but since it gets in after you compile, at least all your code needs to compile already - which removes the possibility for defining your own keywords for instance, like "print" or something.  &lt;br /&gt;&lt;br /&gt;In conclusion, Boo seems exciting, but I need more time to conclude properly. Is it worth the time? Might be. I know I definitely need to have a closer look.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8737917074038224323?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8737917074038224323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8737917074038224323' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8737917074038224323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8737917074038224323'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/09/boo-worth-time.html' title='Boo... Worth the time?'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8949110303801817340</id><published>2008-08-31T14:15:00.016+02:00</published><updated>2008-11-17T17:28:30.201+01:00</updated><title type='text'>Handling the object-database-problem (Presentation)</title><content type='html'>A few days ago we once again had a "fagdag" - a full day dedicated to learning (and a splendid evening building team spirit afterwards of course). &lt;br /&gt;&lt;br /&gt;I held a presentation about the different ways to handle the object-database issue, focusing mainly on the positives and negatives of the various approaches, thus, I believe, providing more value than giving any sort of tutorial on tools or approaches which can easily be googled. &lt;br /&gt;&lt;br /&gt;The goal of the talk was to make sure that all my colleagues were up to speed on what is available in this area today, and what should be used when. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here's a brief overview of what I talked about. &lt;br /&gt;&lt;br /&gt;The issue is the difference between objects and relational databases. Databases focuses mainly on storage and (more or less) normalized relationships through keys, while objects focus mostly on the interaction between objects in a business domain. They typically have the concepts of inheritance and polymorphism close at hand, while databases only handles these if they must, and definitely not naturally. the approaches from the object or database side certainly don't go hand in hand, neither technically nor conceptually.&lt;br /&gt;&lt;br /&gt;So which options do we have for handling the object-relational impedance mismatch, and what's the pros and cons of each approach?&lt;br /&gt;&lt;br /&gt;I covered the following approaches:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Manual SQL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stored procedures/views&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Dataset&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Active Record&lt;/li&gt;&lt;br /&gt;&lt;li&gt;OR-mapper (self-made)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;OR-mapper (open source/commercial)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Code generation&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;As well as a few concrete implementations of active record and OR-mapper:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NHibernate&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Linq To SQL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Entity Framework&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Castle Active Record&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;One concept important to have in mind when comparing many of these options is Persistence Ignorance. This means the degree of which your domain model is freed from having any reference or concerns about how the entity should be persisted. A large degree of Persistence Ignorance means you can model your domain model without any restrictions or interruptive information. Note that this does not correlate with how easy the solution is to use in general.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Manual SQL&lt;/h2&gt;Often used with datasets or "manual" OR-mapping. &lt;br /&gt;&lt;br /&gt;Pros&lt;br /&gt;- Easy to use&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Can be hard to handle / loose overview&lt;br /&gt;- You need to write lot's of code &lt;br /&gt;- No indication to the DBA what accesses the database&lt;br /&gt;- SQL-injection&lt;br /&gt;- Query plan caching - if you run a query against SQL Server without using parameters properly, the entire query will be cached, whereas if you use proper parameters the query excluding the parameters will be cached - meaning you can reuse the cached query plan with any number of queries with different parameters. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Stored procedures / Views&lt;/h2&gt;Often used with datasets or "manual" OR-mapping. &lt;br /&gt;&lt;br /&gt;Pros&lt;br /&gt;- Easier for the DBA to know what accesses the database&lt;br /&gt;- Well known&lt;br /&gt;- Great for batches and reports&lt;br /&gt;- Could be used well as a layer of abstraction&lt;br /&gt;- Security if you can't handle it on the application layer or when several applications must access the database and you need a central handling of it. You should have a good reason for doing this. &lt;br /&gt;- Tuning of queries&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Can be time-consuming to specify everything as stored procedures&lt;br /&gt;- If business logic starts leaking into your stored procedures you're in problems&lt;br /&gt;- Switch database type. Not usually an issue, but if you are planning on changing databases anytime soon, don't model everything in stored procedures.&lt;br /&gt;- I believe it's more hostile to change than many other options. &lt;br /&gt;- Error messages and debugging is less clear&lt;br /&gt;- (Testing. This is being used by many as a reason against stored procedures. I don't agree with this, becuase stored procedures are really quite easy to unit test, as long as you keep them clear and concise and don't go superdynamic on them) &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Dataset&lt;/h2&gt;Pros&lt;br /&gt;- Rapid Application Development(RAD) support&lt;br /&gt;- Very quick to get up&lt;br /&gt;- Support throughout the .NET framework&lt;br /&gt;- Microsoft product. Easy to get a customer into&lt;br /&gt;- Quick to get going, can be sure that everyone involved in a project will know of it. &lt;br /&gt;Cons&lt;br /&gt;- Scales very poorly with complexity&lt;br /&gt;- Often need to live with utility-classes for functionality&lt;br /&gt;- The database schema often leaks down into the code, frequently even into the GUI-binding. Try changing anything there.. &lt;br /&gt;- Not exactly an object oriented approach&lt;br /&gt;- Everything must be casted (stored as object)&lt;br /&gt;- String-based access to table and column-names (Unless you're using typed datasets)&lt;br /&gt;- Since they're so easy to use and can be filled anywhere, some solutions even fills them in the codebehind. Oh beware&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Active Record&lt;/h2&gt;Row object (entity) with domain logic and knowledge of how to persist itself. 1-1 mapping towards a database table. &lt;br /&gt;&lt;br /&gt;Pros&lt;br /&gt;- Easy to get started&lt;br /&gt;- Not duplicated mapping of property names as in OR-mapping with mapping files&lt;br /&gt;- Mapping against database in object. Nice to have everything in one spot&lt;br /&gt;- Centralised connection to the database in one layer&lt;br /&gt;- Always works with entities. Automagic queries to the database&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Works well with a uncomplicated schema (1:1). As soon as your domain model won't map well with the database schema, Active Record won't do for you. &lt;br /&gt;- Data centric. Active Record says your objects need to be the same as your database tables. In simple approaches this works well. But as I mentioned briefly in the beginning, what you care about when you model the database is often very different from what you want and need when you model the domain model. Thus an active record approach can produce a domain model which is unclear and bothersome to work with. &lt;br /&gt;- Hard for the DBA to tune queries&lt;br /&gt;- Not big on Persistence Ignorance (PI)&lt;br /&gt;- Testing can be an issue because of the point above&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;OR-mapper&lt;/h2&gt;Automatic mapping between database and objects through mapping files or attributes&lt;br /&gt;&lt;br /&gt;General &lt;br /&gt;-------&lt;br /&gt;Pros&lt;br /&gt;- Domain centric approach. Can model the domain separately from the database (to some extent)&lt;br /&gt;- Dynamic SQL-generation&lt;br /&gt;- Support multiple databases (At the same time or simplify switching at a point in time)&lt;br /&gt;- Good solutions have support for stored procedures and/or manual SQL in the cases where you need to do things on your own&lt;br /&gt;- Fast development-time once up and running&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Complexity (will get back to it)&lt;br /&gt;- Performance (will get back to it)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With mapping-files &lt;br /&gt;------------------&lt;br /&gt;Pros&lt;br /&gt;- Separated object and mapping&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Must duplicate class name, property names etc.&lt;br /&gt;- XML and pure text (Help with GUI-support, advanced plugins)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;OR-mapper developed in-house &lt;br /&gt;----------------------------&lt;br /&gt;Pros&lt;br /&gt;- Own functionality&lt;br /&gt;- Debugging can be easier / possible&lt;br /&gt;- Know that everything that affects a project is internal&lt;br /&gt;- Cool for the one doing it&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Time-consuming&lt;br /&gt;- Need to redevelop something already developed a myriad of times&lt;br /&gt;- Noone will continue development and testing of your solution outside of the project/organisation&lt;br /&gt;- Anyone new to the project won't know the solution&lt;br /&gt;&lt;br /&gt;OR-mapper - commercial/open source&lt;br /&gt;----------------------------------&lt;br /&gt;Pros&lt;br /&gt;- Relatively short startup time (compared to creating it yourself, not compared with most other approaches)&lt;br /&gt;- Advanced functionality available&lt;br /&gt;- Well tested in projects and scenarios&lt;br /&gt;- Free bugfixing and new releases&lt;br /&gt;- New project members might know the solution&lt;br /&gt;- User group with knowledge of its use &lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Does take time&lt;br /&gt;- Can't debug on errors (Might be possible) &lt;br /&gt;- (Generally) limited by the products limits&lt;br /&gt;- Learning curve&lt;br /&gt;- If it's not Microsoft, it might be an issue in your organisation (hope not)&lt;br /&gt;- What if the product go out of production/stops further development?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Code generation&lt;/h2&gt;Generate data access and domain objects from database&lt;br /&gt;&lt;br /&gt;I don't know this area too well myself, so I'll be short here&lt;br /&gt;&lt;br /&gt;Pros&lt;br /&gt;- Advanced generation scrips&lt;br /&gt;- With so many solutions available, there must be something good?&lt;br /&gt;Cons&lt;br /&gt;- Data-centric&lt;br /&gt;- Many of the same cons as with OR-mapper, in terms of complexity etc. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And then it's the concrete implementations:&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;NHibernate&lt;/h2&gt;- Most known and mature&lt;br /&gt;- Port from Hibernate, well known and have existed for a long time&lt;br /&gt;- Large crowd of followers&lt;br /&gt;- Domain centric&lt;br /&gt;- Functionality&lt;br /&gt;-- Mapping files&lt;br /&gt;-- Inheritance (all three approaches)&lt;br /&gt;-- Stored procedure support&lt;br /&gt;-- All types of relationships (1-1, 1-*, *-*)&lt;br /&gt;-- Caching&lt;br /&gt;-- Support multiple databases&lt;br /&gt;-- LINQ to NHibernate&lt;br /&gt;-Persistence Ignorance (PI). Only need to set everything virtual and have a default (any visibility) constructor&lt;br /&gt;&lt;br /&gt;I believe it's the de-facto OR-mapper in .NET at the moment.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Entity Framework&lt;/h2&gt;MSDN: "Designed to provide strongly typed LINQ access for applications requring a more flexible object-relational mapping, across Microsoft SQL Server and third-party databases"&lt;br /&gt;&lt;br /&gt;- Enterprise solution&lt;br /&gt;- Several layers of mapping (Conceptual, Storage, Mapping)&lt;br /&gt;- Is supposed to be more than an OR-mapper (Don't deliver on this in V1)&lt;br /&gt;- Poor in terms of Persistence Ignorance&lt;br /&gt;- Not very mature&lt;br /&gt;&lt;br /&gt;But I'm positive to Microsofts entry into this arena. The fact that they don't believe datasets can solve every problem in the world anymore is a big step forward. Also, they have taken all the criticism to heart, and have started fixing many of the shortcomings for v2. They also have a blog describing the work and asking for feedback, as well as an expert group following the progress. That is good stuff. Still hope I don't have to work with it yet becuase of some fancy marketing slide though. But hopefully it does become a good contender for the OR-mapping crown, what could be better than better tools?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;LINQ to SQL&lt;/h2&gt;MSDN: "Designed to provide strongly typed LINQ access for raplidly developed applications across the Microsoft SQL Server family of databases."&lt;br /&gt;- Good for RAD-development&lt;br /&gt;- Support only direct 1:1 mapping towards the database&lt;br /&gt;- Only table-per-hierarchy inheritance&lt;br /&gt;- Only attribute-mapping when you use the 08 designer&lt;br /&gt;- Only SQL Server (Though this apparently wasn't becuase of any technical challenge.)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Castle Active Record&lt;/h2&gt;Pros&lt;br /&gt;- Simple to get started&lt;br /&gt;- Created on top of NHibernate, taking advantage of all it has to offer, as well as making it much simpler to get started&lt;br /&gt;- Don't need to specify column name in the attribute if it is the same as the property name&lt;br /&gt;&lt;br /&gt;Cons&lt;br /&gt;- Standard problems with PI for Active Record&lt;br /&gt;- Common to inherit from base class (although you don't have to)&lt;br /&gt;- Data-centric&lt;br /&gt;- 1:1&lt;br /&gt;&lt;br /&gt;I created a couple of diagrams to help compare the four approaches in terms of Peristence Ignorance and OR-mapping in general:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20081002_ObjectDatabase/PI.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20081002_ObjectDatabase/ORM-qualities.JPG" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8949110303801817340?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8949110303801817340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8949110303801817340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8949110303801817340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8949110303801817340'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/08/handling-object-database-problem.html' title='Handling the object-database-problem (Presentation)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6345943485416816517</id><published>2008-08-22T14:31:00.007+02:00</published><updated>2008-08-22T15:03:22.936+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Refactoring'/><title type='text'>When is refactoring unappropriate?</title><content type='html'>In a recent meeting, our own self-proclaimed agile guru (not saying I disagree!), &lt;a href="http://www.linkedin.com/in/oddhelgegravalid"&gt;Odd Helge Gravalid&lt;/a&gt;, came up with a good suggestion on when refactoring can be really troublesome. &lt;br /&gt;&lt;br /&gt;If you are working on a "legacy project", a system in production, lot's of ugly code, no structure - in other words refactoring heaven, refactoring can actually be dangerous. Say you do refactor lot's and lot's of the code, and at the same time, someone else need to do a fix and they bring in a bug in the code. If this is patched into the live system, and you try to find out what went wrong, you have a problem. &lt;br /&gt;&lt;br /&gt;Why? Often you can simply start out by doing a code-comparison in these cases, to see what has been changed. Try doing that after a big refactoring (Refactoring here normally includes removing unused code, etc. Not really refactoring, but for lack of a more complete word....) &lt;br /&gt;&lt;br /&gt;I'm not saying that you shouldn't refactor in these cases. Just be aware of the risks involved. And hopefully you do write a complete test suite for the code before you refactor it, making it a lot easier to track down any problems with both the refactoring and any new functionality.. (Remember: Typemock + legacy code testing = true)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6345943485416816517?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6345943485416816517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6345943485416816517' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6345943485416816517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6345943485416816517'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/08/when-is-refactoring-unappropriate.html' title='When is refactoring unappropriate?'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-9182611962633502452</id><published>2008-08-21T13:36:00.002+02:00</published><updated>2008-08-21T13:42:58.312+02:00</updated><title type='text'>MSTest ExpectedException doesn't support System.Exception</title><content type='html'>This isn't an informative post, as I like to keep it, but MS just got me really annoyed. &lt;br /&gt;&lt;br /&gt;The MSTests ExpectedException attribute, where you put in the exception you expect will be thrown, does not support System.Exception, only derived exceptions! &lt;br /&gt;&lt;br /&gt;How crazy is that?&lt;br /&gt;&lt;br /&gt;Obviously you should try to have as specific an exception as possible (And I follow that, must be why I haven't seen it before), but it's perfectly right to throw a System.Exception if a more detailed is not possible. Hey, it's even the one MS praises in every .NET 2.0-&gt; certification... (ApplicationException earlier)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-9182611962633502452?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/9182611962633502452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=9182611962633502452' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9182611962633502452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/9182611962633502452'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/08/mstest-expectedexception-doesnt-support.html' title='MSTest ExpectedException doesn&apos;t support System.Exception'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-8267747919892878395</id><published>2008-08-19T08:46:00.003+02:00</published><updated>2008-08-19T11:43:44.010+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile persistance-solution OR-mapper refactoring'/><title type='text'>Refactoring of the persistance-solution in agile projects</title><content type='html'>I invited my fellow colleagues to a discussion today about a topic I felt could make for some interesting learning: Refactoring of a persistance-solution in an agile project. &lt;br /&gt;&lt;br /&gt;By that I mean, when/how/if do you refactor away the solution you have for communicating with the database. The general possibilities we reached was &lt;br /&gt;&lt;ul&gt;&lt;li&gt;You can drop the whole solution and create a new one after a few years. Evidently this happens a lot more often than you’d expect. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;You hide the refactoring in a new big task, often accompanied by some cool buzzword&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You try to isolate the old solution away, and start fresh with new functionality&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A few more I’ll cover  below&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I was surprised that few had been in the situation where replacing the persistance-solution was deemed necessary. I don’t have the illusions that any non-developer (-strong) organization could see the real value in doing something like that, but I thought I’d get more examples of projects where that was the only solution. Say you run the msdn-friendly dataset-strong application which works great in the beginning, gets the GUI up quickly, and have a few initial iterations delivering great functionality and a GUI which rapidly fills with functions. Great stuff! Until you reach a level of complexity which just breaks the design completely down. What do you do then? A few possible solutions:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Explain to the customer that you need an iteration or two to redesign the application to accommodate the newfound complexity. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Quietly include the refactoring within the subsequent iterations tasks, far lowering the work delivered to the customer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Postpone everything, plan instead to get around to it once everything quiets down&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Have separated things properly, making it easier to change from one solution to another&lt;/li&gt;&lt;br /&gt;&lt;li&gt;From the initial phase of the project, settling where we are going and the time it will take, using your experience to choose a better solution, perhaps NHibernate or Castle Active Record, and hopefully your domain-model will never got into this extreme a situation (with contant refactoring) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hah, the object-relational impedance mismatch is obsolete; object databases will save the world!&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;First of all, there so no single answer to any of this, as with everything in our business – it depends. It depends very much on what kind of solution you are working on and what kind of environment you are working in. &lt;br /&gt;&lt;br /&gt;Obviously number 1 isn’t going to go down well with the customer – “you’ve had such a good flow so far, just keep it going” is not a surprising answer. And that’s quite understandable, and really correct in many cases. You should have applied constant refactoring to your solution, enabling you to steer clear of that situation. Of course, if you make a msdn-friendly dataset-app in the first place, you probably know that it isn’t going to handle the most complex of tasks, so you’ll never get into this situation. I bet it does happen though, and has happened more than I can imagine (I hope not). &lt;br /&gt;&lt;br /&gt;Number 2 is the one you should have been doing all along, except now it will far halt the current work. Perhaps that is okay. You could get to an 80% finished solution quickly, and ask if that is ok. If it is, then the customer will have gotten his money worth of application quickly. If not, you can be clear to the customer that to get this and this, it will cost exponentially more than it did before. Cause we all (should) know the Pareto principle, or 80-20 rule, 80 percent of the job takes 20 percent of the time (or cost), and vice versa. Again, the customer might not be too happy about that either. &lt;br /&gt;&lt;br /&gt;Number 3: postpone doing anything until later. You’re already in a pretty dire situation, so postponing is not likely to do much to improve on that. If you don’t know what to do, then I guess just keep doing the same is probably the best – but if you get to that point, I don’t want to have anything to do with you anyway :) &lt;br /&gt;&lt;br /&gt;Having separated things properly (4) will give you a good basis when you get into this situation. Hopefully it won’t be too costly to make the change to tougher concurrency-issues, more advanced business logic, etc. &lt;br /&gt;&lt;br /&gt;As long as you didn’t go with a big design up front, but leveraged experience to choose a clever framework to start on, good for you. I currently fall very easily into the Domain Driven Design with NHibernate/Active record-camp (5), using a proper domain model and everything. Not nearly as fast as the dataset approach, but more applicable in the situations I’m usually in (The dataset-approach can be great though, don’t overdesign a simple application – there’s nothing ¬with more framework support from top to bottom in .NET than datasets!)&lt;br /&gt;&lt;br /&gt;Slightly sarcastic with the object database-title here, I just have a feeling someone who falls for one without having much experience with the other side of the table (relational), could possibly proclaim it as the new(ish) silver bullet. Now I’d love to try using an object database, because it seems you do get around many of the issues you need to consider and constantly work on with the traditional relational database approach. However, being in the real world, you mostly have to live in an existing business environment, where relational databases are the big G. Converting the object database at the end of the development cycle is a possibility, but beware of pitfalls, some intelligent colleagues found quite a few (Perhaps they could write about it soon?). &lt;br /&gt;&lt;br /&gt;You should always be aware of the total cost of ownership (TCO) of course, knowing that the initial development of an application is only a small part of the entire cost of it, maintenance being the biggest thief. But you know, in the real world, the one funding or driving the application development isn’t necessarily the one paying for the maintenance, so… Hopefully you’ll have someone who has a bit more professional integrity than that, but it’s no wonder shortcuts on that side are taken. &lt;br /&gt;&lt;br /&gt;One of my colleagues, Sverre Hundeide, came up with a nice suggestion. The contents should be clear to all, but the conclusion has value. An OR-solution has a few possibilities in how it interferes with your system&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Persistance ignorance  - Nothing in your domain-model assembly references anything concerning the persistance solution used&lt;/li&gt;&lt;br /&gt;&lt;li&gt;POCO – For me, this is the same as above, but he means this has been defined as almost the same, except there can be some references in the assembly, extra metadata, etc. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;IPOCO – The domain classes can inherit from a base class used for persistance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Code-generation – The domain and persistance code is generated from the database, often highly coupled. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Basically, the higher you are on the list, the easier it is to change to another solution. Simple, but an important thing to have in mind.&lt;br /&gt;&lt;br /&gt; I guess it’s time for the conclusion now. Or it should have been anyway, except I’m not quite sure what I covered. Just Another blog post with a lack of well arranged contents. You’ll have to make do for now :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-8267747919892878395?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/8267747919892878395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=8267747919892878395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8267747919892878395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/8267747919892878395'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/08/refactoring-of-persistance-solution-in.html' title='Refactoring of the persistance-solution in agile projects'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4342770284528181390</id><published>2008-08-15T21:25:00.002+02:00</published><updated>2008-08-15T21:39:35.642+02:00</updated><title type='text'>SQL: Convert list of values to comma-separated list</title><content type='html'>Ever had a list of values in SQL, but wanting them in a comma(or anything)-separated list? &lt;br /&gt;&lt;br /&gt;Just do something like this:&lt;br /&gt;&lt;br /&gt;SELECT c.co_companyName, &lt;br /&gt;       substring(List, 1, datalength(List)/2 - 1) AS 'Employees'&lt;br /&gt;FROM co_Company c&lt;br /&gt;     CROSS APPLY (&lt;br /&gt;            SELECT e.em_employeeName + ',' AS [text()]&lt;br /&gt;            FROM em_Employee e&lt;br /&gt;              INNER JOIN co_Company c2&lt;br /&gt;                ON c2.co_Id = e.em_co_Id&lt;br /&gt;    ORDER BY 1&lt;br /&gt;    FOR XML PATH('')&lt;br /&gt;  ) AS Dummy(List)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you had a a company-table and an employee-table, you'd end up with a list of the companies in the table, with a column with a comma-separated list of all the employees. &lt;br /&gt;&lt;br /&gt;By the way, apologies for how absurdly ugly this looks as plain text.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4342770284528181390?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4342770284528181390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4342770284528181390' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4342770284528181390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4342770284528181390'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/08/sql-convert-list-of-values-to-comma.html' title='SQL: Convert list of values to comma-separated list'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-741844444543326292</id><published>2008-07-23T02:40:00.025+02:00</published><updated>2008-09-04T15:53:58.655+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio Add-in'/><category scheme='http://www.blogger.com/atom/ns#' term='Sealed classes'/><category scheme='http://www.blogger.com/atom/ns#' term='Code generation'/><title type='text'>VS Add-in: Extending Sealed Classes (without Extension methods)</title><content type='html'>If you are ever in the situation when you have a .NET Framework class with most of the functionality you want, but not really doing everything to the extent you need, you have a few options:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You can inherit from the class and extend as you see fit&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can create a utility class to perform the extra functionality&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can use extension methods to add functionality to the class&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can create a new wrapper class which holds the class as an internal variable and create wrapper-methods for whatever methods you need from the class you are extending, and add any extra functionality you need.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Inheriting from the class is likely the best approach. Unfortunately, about 40% of the .NET 2.0 Framework classes are sealed, which of course means you can't inherit from them. &lt;br /&gt;&lt;br /&gt;The second approach is becoming somewhat obsolete, as it can lead to a sort of functional programming which takes you away from proper object-oriented programming. It makes things just a bit harder to find and understand. &lt;br /&gt;&lt;br /&gt;Number three, extension methods, is the new cool kid on the block. Add new methods just like magic to any class. The possibilities are enormous! The problem is that you can't do anything with the internals of the class, you can only add new isolated methods. &lt;br /&gt;&lt;br /&gt;The last approach can be the way to go if extension methods won't do. This way you'll have complete control over what you want to be public and you can extend and improve on existing and new functionality. There are two problems with this approach. Number one is clarity and number two is identity. If you create an extension of the DataSet for instance, it never is a dataset. You can, in a way, get around the issue by inheriting from one of it's base classes or interfaces though (Using that as a common base). &lt;br /&gt;&lt;br /&gt;Be sure only to use it when no other approach is better. The clarity/identity issues can be confusing for someone seeing the class at first. But I do think the wrapper/composition approach have some merit, especially considering the extreme amount of sealed classes that exist. I made it because I was annoyed to find that there was no support for doing something like that besides typing it in manually. And if you have a lot of methods to wrap, that means a whole lot of time typing nonsense methods, not to forget the comments you should add if you want it understandable. No way I'm doing that unless I'm really keen on wasting a lot of time. &lt;br /&gt;&lt;br /&gt;That's why I've created a code-generation add-on for the last approach. It's a Visual Studio Add-in to help extend sealed classes. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I’ll begin with showing some results, and then I’ll get to how and why it works/makes sense/you should use it. In this example, I'd like to extend the StringBuilder class. To do that I need to write something like:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/img1_ClassInitial.JPG" /&gt;&lt;br /&gt;   &lt;br /&gt;Once I press SPACE or TAB while at the end of this line, the add-in starts its work on using this StringBuilderExtender class to extend System.Text.StringBuilder. The result is this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/img2_StringBuilderExtender1.JPG" /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/img3_StringBuilderExtender2.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;More examples &lt;a href="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/example2.JPG" target="_out"&gt;here&lt;/a&gt; and &lt;a href="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/example3.JPG" target="_out"&gt;here&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;What happened is this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Added an internal StringBuilder instance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Recreated all public constructors, methods, properties and fields, and made sure all of them use the internal StringBuilder instance. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added any available comment from the StringBuilder class.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Changed returntypes from StringBuilder to StringBuilderExtender where necessary. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added the Serializable-attribute, since StringBuilder is serializable.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Listed the interfaces StringBuilder implements in a comment next to the class, in case you'd like to implement the same. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Added the System.Data namespace to the using statements if it did not exist. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Why would you want to do this? &lt;/h2&gt;&lt;ul&gt;&lt;li&gt;You really want to extend one of the sealed classes. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;You need new functionality in a sealed class, and you either only have .NET 2.0, or extension methods just won’t do it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You reuse existing functionality, making a quick browse of the code enough to understand the majority of what the extended class does. Compare that to reimplementing a larger part of the functionality of a sealed class.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Why would you not want to do this? &lt;/h2&gt;&lt;ul&gt;&lt;li&gt;You are somewhat pretending to extend a class you cannot. This can get you into problems with equality and comparison. The commented interfaces do make it simple to extend any common interfaces though. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Potential performance hit. You do add some overhead, and internal performance tweaks through for instance Win32 code could have has less effect.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;More on the internals&lt;/h2&gt;In terms of what you can visually do&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You need to specify the keywords for the add-in on the class line. The input must always be in the form specified above: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;public class StringBuilderExtender SealedClassExtender(System.Text.StringBuilder) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;or in other words&lt;/li&gt;&lt;br /&gt;&lt;li&gt; [visibility] class ClassName SealedClassExtenderKeyword(TypeFullName) &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can use both SealedClassExtender and the short form scx/SCX as keywords. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The TypeFullName is, obviously, the full name of the type. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can also extend a class by specifying the path to the assembly. The form is then&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;public class StringBuilderExtender scx(System.Text.StringBuilder, C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;or&lt;/li&gt;&lt;br /&gt;&lt;li&gt; [visibility] class ClassName SealedClassExtenderKeyword(TypeFullName,FullAssemblyPath) &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Apart from the list above it does a few more things in the background&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Adds a default constructor if one isn’t specified in the base class.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;With any method, property or field that returns the base type (StringBuilder), it returns the extended type instead (StringBuilderExtender).  A new private constructor with the base type is added if necessary to fulfill this. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Static classes does not get an internal instance but just point directly at the class. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lots more fun things to fix every special case.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;If you do not specify a path it will try to resolve where to load it from by itself. It will currently do this by first trying to load the type from memory, then specifically checking all assemblies in the current application domain, and then trying to resolve the name of the assembly from the types full name. It will first try to look in the current runtime directory, then in the executing assembly path. &lt;br /&gt;&lt;br /&gt;The comments are loaded by using the XML-document corresponding to most framework dlls, as comments are not part of the information retrievable through reflection. &lt;br /&gt;&lt;br /&gt;Be aware though, the add-on will rewrite the entire document, so only add using-, class- and potentially namespace-declarations, anything else will be overwritten.&lt;br /&gt;&lt;br /&gt;It doesn’t handle everything though. Specifically it doesn’t do:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Generics &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Events &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Identity-handling (Trying to guess how you want the identity-part handled will probably just end up with a bad guess, you’ll have to do this however you want it. Methods for equals, GetHashCode etc. are thus not created.) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Limited attribute support.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It also currently loads all assemblies into the current app domain while running. This is just because of a time-constraint on my part, and I’ll fix that. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;If you have gotten this far, send me a note if you see a use for it, just don't get it, or have any comments.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Usage&lt;/h2&gt;To use this, you first need to install it like any other add-in. Copy the files in the zip to the correct Addins folder, for instance \My Documents\Visual Studio XXXX\Addins. (If the Addins folder does not exist, just create it yourself) Once this is done, restart visual studio, and you can enable the add-in in the "Tools-&gt;Add-in Manager"-dialog.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Downloads&lt;/h2&gt;Download the 2005 version from &lt;a href="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/SealedClassExtender_2005.zip" target="_out"&gt;here&lt;/a&gt;.&lt;br /&gt;Download the 2008 version from &lt;a href="http://www.rammeland.com/blogpics/20080723_SealedClassExtender/SealedClassExtender_2008.zip" target="_out"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-741844444543326292?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/741844444543326292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=741844444543326292' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/741844444543326292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/741844444543326292'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/07/vs-add-in-extending-sealed-classes.html' title='VS Add-in: Extending Sealed Classes (without Extension methods)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-7094906800906005818</id><published>2008-06-25T14:26:00.004+02:00</published><updated>2008-06-30T09:48:07.168+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework V2.00'/><title type='text'>Entity Framework V2.0</title><content type='html'>Microsoft has started the work on Entity Framework V2.00 &lt;a href="http://blogs.msdn.com/efdesign/archive/2008/06/23/transparency-in-the-design-process.aspx"&gt;now&lt;/a&gt;. Apparently, this version will have a great deal more transparency during the process, making sure it ends up as something the users want. &lt;br /&gt;&lt;br /&gt;Good stuff. &lt;br /&gt;&lt;br /&gt;NHibernate, beware?&lt;br /&gt;&lt;br /&gt;Update: &lt;br /&gt;&lt;br /&gt;A &lt;a href="http://efvote.wufoo.com/forms/ado-net-entity-framework-vote-of-no-confidence/"&gt;petition&lt;/a&gt; against the current quality of Entity Framework has begun. Read it to get a brief overview of the issues, and add your signature if you agree.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-7094906800906005818?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/7094906800906005818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=7094906800906005818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7094906800906005818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/7094906800906005818'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/06/entity-framework-v20.html' title='Entity Framework V2.0'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4541677605152978357</id><published>2008-06-10T23:46:00.006+02:00</published><updated>2008-06-11T12:03:53.857+02:00</updated><title type='text'>PropertyNamesGenerator (source)</title><content type='html'>I recently wrote the post &lt;a href="http://rune-sundling.blogspot.com/2008/06/type-safe-property-names.html"&gt;Replace strings for property names with type-safe version&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is the source code for the project it describes. I'm posting it because of a request, so hopefully you'll have use for it. &lt;br /&gt;&lt;br /&gt;PropertyNamesGenerator&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Generates type-safe versions of property/field names.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Generates C# or VB files&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The only parser implemented is for parsing NHibernate mapping-files&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The NHibernate parser handles regular classes as well as subclasses. &lt;br /&gt;Another parser which will probably get there is for regular domain classes.&lt;br /&gt;&lt;br /&gt;Warning: This is not production-grade software, but a simple project I made for myself to handle a current need! This should not be used as a guideline for good design, nor expected to work flawlessly. No such thing have been attempted. &lt;br /&gt;&lt;br /&gt;You can download it &lt;a href="http://www.rammeland.com/software/PropertyNamesGenerator/PropertyNamesGenerator.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The zip includes the source, the current binary, and a sample bat-file to use it. &lt;br /&gt;&lt;br /&gt;How to use it: &lt;br /&gt;To run the generator, start it with something like: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;"C:\path\PropertyNamesGenerator.exe" /lang:cs /files:"../../source/Domain/*.hbm.xml" /out:"Output"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;An explanation of the various params can be found by running it with a -? switch. It prints: &lt;br /&gt;Run like: PropertyNamesGenerator.exe /files:"path/*.hbm.xml" /out:"path/PropertyNames/" /lang:cs&lt;br /&gt;Parameters:&lt;br /&gt;/Files [Mandatory] - Must have both a directory and a search string.&lt;br /&gt;/Out [Mandatory] - Must specify an output directory.&lt;br /&gt;/lang [Optional] - Output-language. C# or VB. (C# is default)&lt;br /&gt;-V - Verbose output.&lt;br /&gt;Note: All directories can be relative.&lt;br /&gt;&lt;br /&gt;It currently only supports searching for files in the directories explicitly specified, i.e. not subdirectories. This is a concious choice. &lt;br /&gt;&lt;br /&gt;To integrate it with your build, typically use a bat-file in the same manner as the Generate.bat example file included in the zip. &lt;br /&gt;&lt;br /&gt;To integrate it with your build, you can add something like the line below to your Domain Pre-build event: (Project/Build Events)&lt;br /&gt;call "$(SolutionDir)\..\Tools\PropertyNamesGenerator\Generate.bat"&lt;br /&gt;Note that you will need a full path to the PropertyNamesGenerator.exe-file in the bat-file to use it like this.&lt;br /&gt;&lt;br /&gt;It will generate files on the form [ClassName].[lang] in the output directory specified. Using a PropertyNames folder to put all of these in is recommended.&lt;br /&gt;&lt;br /&gt;You will of course have to include these file in your solution to integrate them. Do this every time you have added and parsed a new hbm-file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4541677605152978357?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4541677605152978357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4541677605152978357' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4541677605152978357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4541677605152978357'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/06/propertynamesgenerator-source.html' title='PropertyNamesGenerator (source)'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-6697593955309396026</id><published>2008-06-05T00:00:00.011+02:00</published><updated>2008-06-25T14:35:00.606+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework V2.00'/><category scheme='http://www.blogger.com/atom/ns#' term='Database access'/><category scheme='http://www.blogger.com/atom/ns#' term='OR-Mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='Persistance'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain model - database communication'/><category scheme='http://www.blogger.com/atom/ns#' term='Code generation'/><title type='text'>Persistance-solutions and characteristics</title><content type='html'>The other day I invited my colleagues to a discussion about persistance solutions. The goal was to cover the various options for persistance in a software project, the pros and cons of each approach, and to increase everyone’s knowledge about it. &lt;br /&gt;&lt;br /&gt;The approach planned was to identify the possible solutions, identify important characteristics to help compare each solution, and to go through each possibility. &lt;br /&gt;&lt;br /&gt;The different types we identified were:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code generation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Object relational mapper (custom made) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Object relational mapper (commercial/open source) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Row data gateway (Which would be active record with domain logic) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Table data gateway (Dataset) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stored procedures/views &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Manual SQL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Object database&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;And the characteristics in no particular order: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Development time&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Flexibility&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Performance&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stability&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Complexity&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Refactoring&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Expertise&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Effect/limitation/intrusion on system&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rapid Application Development (RAD)-support&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attachment to data type&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Amount of developers&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Company demands/guidelines&lt;/li&gt;&lt;br /&gt;&lt;li&gt;What you are creating&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I think it is best to start off by defining the characteristics; what they are and why they are important. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Development time&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The time it takes to get your persistance solution ready to use and understood. This can either be the time it takes to configure and use an existing solution or the time it takes to develop your own. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Flexibility&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The flexibility of the system in terms of handling the various storage challenges in a project. This also includes handling a system which inevitably grows and changes. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Performance&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Obviously performance is important, right? This includes how the system performs in general, how it scales, how it can help handle special cases. A word of caution though: Even though performance is essential, don’t optimize prematurely. In any system of reasonable size, you will have special cases that will become bottlenecks. However, with a profiler and the possibility of fine-tuning those cases, you should be quite alright. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stability&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You need to know that the system won’t break down under normal usage or high peaks. Testing is essential for this. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Complexity&lt;ul&gt;&lt;br /&gt;&lt;li&gt;How complex is it to use and understand? How much help do you get with error messages? What do you when you need to debug? Is it too complex for the average developer on the project, making people take (eventually unmanageable) shortcuts?  &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Refactoring&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What sort of help do you get when the need for refactoring appears (often)? How hard is it to do changes? &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Expertise&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You always need to take into account the expertise and skill level of the people on the project. This is more important that selecting “the best” solution. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Effect/limitation/intrusion on system&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What does it take to integrate the persistance solution with your overall system? Will your domain model be POCO? Do you need to inherit from a base class? Implement an interface? &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rapid Application Development (RAD)-support&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What kind of GUI-support does the solution have? If you need something quick and dirty, what do you do? The winner here should be pretty clear (If not, you’ll soon find out) &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Attachment to database data type&lt;ul&gt;&lt;br /&gt;&lt;li&gt;How close is it tied to database data types? Can it for instance handle the types of several databases? &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Amount of developers&lt;ul&gt;&lt;br /&gt;&lt;li&gt;How many developers the project has. This could influence the complexity of the solution, or the time available to get it up and running. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Company demands/guidelines/policy&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Company policies/limitations are a part of normal life for a consultant, and often there is little you can do about it. The company might have policies against using anything open source, demand that all database access should go through stored procedures, etc. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;What can you do about this? Unless you have a small project or are able to influence the architecture group, chances are you’ll have to manage. I guess you can pray that the architecture group doesn’t consist of a bunch of non-coding architects that selects technologies out of marketing slides. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Another point I need to raise here: If your company still live in the “don’t use open source”-world, chances are that most decision-makers are a bit out of sync with what is happening in the .NET world today. Agreed, just a few years ago things were pretty thin in terms of open source projects on .NET, but today things have most definitely turned to the better. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;What you are creating&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The most important point! Make sure whatever you choose will work for your project. Unneeded complexity is expensive! But remember that going from one solution to the other is often hard, so beware the danger of a project growing on a bad solution; you’ll have a tough time getting out of it&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;That should cover the basics of what is important to think about before choosing a persistance solution. Let’s get to the actual solutions! &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Code generation&lt;/h2&gt;This involves generating the data access and potentially partly the domain model from your database schema.  You specify rules for how you want things generated. There are a couple of potential problems with this approach. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;If the software has a binary solution specifying the mapping, you’ll have no way to map two differing changes, which in effect means you can only have exclusive checkout. In a multi-person project this is highly unproductive, and don’t forget that you’ll be unable to use branches, as you can’t merge them later.&lt;/li&gt; &lt;br /&gt;&lt;li&gt;The other is that once you want to add a field or property to a domain object, you’ll have to update the database structure and generate the files before you can use it. This does take some time. I’m not saying that most other approaches are must faster; the annoying thing is that you can’t simply add properties etc. during testing for instance. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I have to admit that I have limited knowledge of this type of persistance-solution, but I believe this approach could be successful. There is no reason why the general mapping solution between the database and domain objects should be any poorer than with a general OR-Mapper. It depends what extra functionality is available and how everything is implemented (works). By this I mean the SQL generated, how the session is handled, lazy loading, how it affects the domain model and system, if it supports queries or SQL/stored procedures for special cases, type safe support for anything and everything, maintainable/understandable script files, and a few more I probably forget at the moment. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Object relational mapper (custom made) &lt;/h2&gt;An OR-Mapper is a piece of software that handles the problem of transforming your domain objects data into its equivalent form in the database. Your domain model is made of objects and pointers; the database model is made of rows, columns, keys and relationships. These are very different ways of handling data. &lt;br /&gt;&lt;br /&gt;By creating your own OR-Mapper you will have to handle the problem of mapping from the domain model to the database for starter. This is just a small part of what you need to handle though, and to make it clear =&gt; There are slim chances that creating your own OR-Mapper will be beneficial for your project. Doing it will be time-consuming and error-prone, you will reinvent the wheel without need (See Object relational mapper (commercial/open source)), you will tie up your best resources for a substantial amount of time, you will have to implement a lot of added functionality to make it functional. Oh, and I doubt any project will wait before the mapper is finished before starting the rest of the development - which means some other form of temporary solution must be created.. (An object database might be the best choice in such a scenario.)&lt;br /&gt;&lt;br /&gt;However, as a colleague commented, it is probably a dream for most developers to do it. Why? First, it’s complex, so you’ll learn heaps by doing it. Second, you don’t have to relate to the business side, so you really just define most of the tasks yourself. Perfect or what? &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Object relational mapper (commercial/open source)&lt;/h2&gt;This is the same as above, except you use an already existing solution from a vendor or open source project. I recommend this approach.  &lt;br /&gt;&lt;br /&gt;Why create your own OR-Mapper when great solutions already exist? If you choose a premade mapper you will (potentially) get:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Shorter development time – You will need time to configure, use and understand the solution. This is time-consuming as well, but far easier than creating your own. Getting started should also be fairly easy, even though the tougher concepts need more time. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;There’s a chance that present/new developers have used the solution before&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A solution tested in many projects, which means less bugs and more working features.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;New versions at no development cost. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;You need to live with a few risks though:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Harder to customize and debug. You’ll have to use time on strange error messages which can make little sense. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The company might stop development and support, or the developer base of an open source project could die out. If you create your own OR-Mapper, the main developer(s) could quit as well. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In general, getting something of the shelf is far cheaper than building it yourself, as long as your requirements are met. I believe that this solution most of the time far surpasses any positive effects of building it yourself.&lt;br /&gt;&lt;br /&gt;Picking a mapper at random just by browsing some marketing slides are not the way to go. Make sure you thoroughly read specs and user feedback, or the best thing if possible: talk to people that has experience with what you are considering, if it is a popular solution they shouldn’t be too hard to find. &lt;br /&gt;&lt;br /&gt;There are a &lt;a href="http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software"&gt;range of solutions&lt;/a&gt; in this field, but personally I’ve had the pleasure of working with perhaps the most known of them: NHibernate.  NHibernate is an open source OR-mapper, which is a port of the well known OR-Mapper Hibernate from the Java world. NHibernate is a great piece of software, it has been used on numerous projects, and quite a lot of information is available through blogs and forum.&lt;br /&gt;&lt;br /&gt;I’m not going to list all the reasons to use NHibernate, a quick search on the web should give you that, but a few things: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;NHibernate lets you have (almost) POCO objects (You need to mark all persistable fields/properties as virtual. NHibernate subclasses your objects with the virtual proxy pattern, to give you lazy loading etc.) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;NHibernate has mapping files to map between your domain object and database. These enable easy modeling of inheritance, collections, etc. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;It is mostly type safe (with NHibernate Query Generator at least), except when you need to write advanced queries. (You could use something like my PropertyNamesGenerator though) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can use Hibernate Query Language to create special queries in the cases where performance isn’t good enough. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Automatic lazy loading&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A few bad things as well:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There is some overhead involved, and performance has been noted as an issue on several occasions. I think this is more of a design issue with your average developer though. If you try to retrieve gazillions of data from lots of tables, you can’t expect it to be lightning fast. Proper table and index design, as well as good use of lazy loading should get you well under way. For the special cases where you do get a performance issue – use a profiler to see what the issue is, use query analyser to look at the SQL, use HQL or use manual SQL behind a well designed layer to access the data, use DTO’s to limit the data loaded and sent…. There are plenty of possibilities&lt;/li&gt;&lt;br /&gt;&lt;li&gt;NHibernate has some strange error messages. Before you get to know it enough, you’re bound to use a few hours trying to figure out error messages which doesn’t make much sense. I base this on experience with the 1.2 version, not the new 2.0 release.  &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If you don’t want to go down the open source way, you’ve probably been (or will be) introduced to Microsofts new OR-Mapper Entity Framework. It’s Microsoft, so it’s bound to be good, right? (…)&lt;br /&gt;Note: I have only read about Entity Framework, and thus my experience (both good and bad) are of questionable quality, so make sure you do your own research before making any conclusions. &lt;br /&gt;The pros: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Integrates nicely with LINQ (But Ayende has a &lt;a href="http://www.ayende.com/Blog/archive/2007/03/17/Implementing-Linq-for-NHibernate-A-How-To-Guide--Part.aspx"&gt;project &lt;/a&gt; going to bring this to NHibernate as well&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Microsoft helps bring the concept of an OR-Mapper to public knowledge, which really is good&lt;/li&gt;&lt;br /&gt;&lt;li&gt;With Microsoft’s size, there’s a good chance that the project will continue. This depends upon how many uses it of course; it might get shut down like Microsoft’s music service did. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Developers versed exclusively in the Microsoft world have something besides datasets and manual ADO.NET to use. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The cons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;They’ve built a completely new product - which means you should think they should be able to leverage the experience of already existing OR-mappers. You’ll need a good amount of resources to do this though. For some reason it doesn’t like Microsoft has quite lived up to this. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Having read quite a few blogs about Entity Framework and spoken to Microsoft employees about it, I must say I’m initially skeptical. At least for enterprise development. According to one Microsoft employee, Entity Framework is only believed to have a third of its user group in the enterprise software world; the rest is your simple application developers. The needs are quite different. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;One of the aspects that alarms me quite a bit relating to enterprise development and Entity Framework (or really any modern type of development – read: with source control), is that until recently the mapping files were unmergable.  (The XML created were put in a “random” order. A small change could lead to big changes in a document) I can’t for the life of it understand that Entity Framework could be designed as anything but a play version if that wasn’t an important design point from the beginning. Ayende had a &lt;a href=” http://www.ayende.com/Blog/archive/2008/04/17/Source-control-is-not-a-feature-you-can-postphone-to.aspx”&gt;post &lt;/a&gt;  about a meeting he had with Microsoft about this point, and based on his reactions it seems likely that the team defended this decision.  It seems Microsoft has improved this feature after the range of reactions on it, as mentioned &lt;a href=” http://www.ayende.com/Blog/archive/2008/05/19/Reviewing-the-Entity-Framework-Source-Control-Support.aspx”&gt;here &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Explicit lazy loading. You have to explicitly say that you want to load a lazy-loadable collection. I think this sounds mostly annoying, as you need to fill your code with logic of testing if a collection has been loaded, and then explicitly loading it, compared to the NHibernate way of automatic lazy loading by simply using it. There is a good thing about it - the fact that you won’t get unexpected database calls from the GUI-layer because you forgot to load everything you needed. This could lead to a performance hit and other problems. I don’t believe that merits this solution. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Even though I’m skeptical about the current quality of Entity Framework, and would recommend using NHibernate instead, I’m positive to Microsoft’s general move into this realm. With their funds, future versions have the potential of becoming really useful, with hopefully seamless integration with the rest of the framework. &lt;br /&gt;&lt;br /&gt;For now I’m mostly scared that I’ll be put on a project where its use will be mandatory. Unfortunately, we’re still in a world were non-Microsoft software is looked at with skepticism from many of the decision makers in companies.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Row data gateway (Which is Active Record if you have domain logic)&lt;/h2&gt;This is the same as having a gateway which gives you objects per row in the database. If you add domain logic to these objects you have what is called Active Record. I’m going to concentrate on the Active Record approach, as I can’t see a good reason why you’d want to have a simple row data gateway in .NET. Active record is a domain object which handles persisting itself. &lt;br /&gt;&lt;br /&gt;Active Record has the advantage of being simple and quick to implement. It is not hard to understand, and is a good way to make a quick prototype while retaining a domain model. It breaks down once your database gets complicated, and once you don’t have a one to one mapping between an Active Record object and a database table. &lt;br /&gt;&lt;br /&gt;You can use &lt;a href=” www.castleproject.org/activerecord/index.html “&gt;Castle Active Record&lt;/a&gt; to do this. It is built on top of NHibernate. In terms of refactoring away from Active Record if the complexity increases, apparently there is a way to automatically go from Active Record to a full OR-Mapper NHibernate solution automatically. I haven’t tested this though. &lt;br /&gt;(You’ll probably end up with a NHibernate solution through Castle then as well. This is not a bad thing! Castle integrates very well with NHIbernate through its NHibernateFacility, and easily allows for instance a Dependency Injection approach as well. I’ve written about it in a previous post)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Table data gateway (Dataset)&lt;/h2&gt;In the .NET world, table data gateway is the same as the dataset-approach. &lt;br /&gt;&lt;br /&gt;The major benefit of using datasets is the unmatched framework support for it, where creating a datagridview and datasource, using databinding, adding a navigator to handle paging, etc., is extremely simple and powerful. For quick demos, or Rapid Application Development (RAD), nothing can match it. &lt;br /&gt;&lt;br /&gt;There are two main problems with this approach&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It really doesn’t scale. Once you start adding business logic, you’ll have problems with the lack of object orientation, with the lack of type safety, with duplication of logic, and lots more. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Expectations, if you use it with prototypes. If you give the business side a quickly running demo with this approach, you’ll get into problems when you try to explain to them how long it will really take to build. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If you know you are creating a very isolated, not to be extended, solution, by all means use the dataset approach – nothing can match it in speed or simplicity. If there’s a chance you need to add more to it later, opt for another alternative. You’ll have a hard time refactoring it later on. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Stored procedures/views &lt;/h2&gt;Putting everything in stored procedures/views is another approach that has been used. I’m not going to bother saying much about it, as it’s not really a viable alternative. You’ll be better of using this approach than manually concatenating information into SQL queries though (Like avoiding SQL Injection attacks)&lt;br /&gt;&lt;br /&gt;It is a possible approach if you have special cases where you just can’t make the performance demands without using stored procedures.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Manual SQL&lt;/h2&gt;Don’t bother. But if you have to, at least limit its use to a database layer. And make sure you remove hazardous characters so you avoid SQL Injection. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Object database&lt;/h2&gt;An alternative quite unlike the rest. Whereas the previous sections concentrated on ways of working with a relational database, you also have the option of using an object database. If you choose this approach you can just pass your objects to and from the database.&lt;br /&gt;Again, I haven’t tested this, but I have very experienced colleagues who have little but positive things to say about this approach. &lt;br /&gt;The pros of this approach includes&lt;br /&gt;&lt;ul&gt;&lt;li&gt;No need to map between a relational design and a domain model&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Don’t need to update a schema several places&lt;/li&gt;&lt;br /&gt;&lt;li&gt;According to some benchmarks, they can be superior for certain kind of tasks. It has been said that they are very efficient at specific queries, while they are slower at more general queries. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Most of the object databases also support some sort of query language when the need arises&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Some even fully support SQL, but I have no idea how this works in practice. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The cons&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Practical knowledge of these are still fairly limited&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hard to access from other parts of the company network, for reporting purposes for instance&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;One approach some of my colleagues took was to go through the whole development period with an object database before converting to a NHibernate solution before going live. The conversion into a relational database was only done because of company demands. This was still a success, but if you do this you have the danger of not quite knowing how long it will take to set up the final solution or exactly how the data will perform. &lt;br /&gt;&lt;br /&gt;I look forward to testing this in a real world project, you should too. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Conlusive thoughts&lt;/h2&gt;In summary I’d say that you should&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use the table data gateway/dataset approach if you have a short and sweet application&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use Active Record if you need to get results fairly quickly, and have a close relationship between your table and domain structure&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Find out whether a commercial/open source OR-Mapper or code generation tool or an object database suits your needs best - if you need a somewhat complex application&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Build your own OR-mapper if you’re forced to, it’s not good for the project, but you’re lucky :)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-6697593955309396026?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/6697593955309396026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=6697593955309396026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6697593955309396026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/6697593955309396026'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/06/persistance-solutions-and.html' title='Persistance-solutions and characteristics'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-4808617153513278342</id><published>2008-06-04T23:19:00.008+02:00</published><updated>2008-06-25T14:33:38.456+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Type-safe strings'/><category scheme='http://www.blogger.com/atom/ns#' term='type-safety'/><category scheme='http://www.blogger.com/atom/ns#' term='Code generation'/><title type='text'>Replace strings for property names with type-safe version</title><content type='html'>At times you have the misfortune of having to write property/field (I’ll just call it properties from now on) names as strings, for instance in advanced NHibernate queries. (In general, NHibernate Query Generator avoids this for you in most cases, but there are still some times it cannot be used. Say inheritance for instance). If you’re a bit slow on progressing in mocking tools, this might be a problem as well (It shouldn’t still be though…) &lt;br /&gt;&lt;br /&gt;The big problem with non-type safe strings is refactoring, which should happen all the time on your projects. Property names will change, and when these are used as non-typesafe strings in your system it has a few unfortunate consequences:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You could break something without knowing it. Worst case is you won’t find it until production &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The knowledge above could restrain you from doing refactorings.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You will have to spend time doing text-searches in the system to find out if and where it is used.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So for a personal project I’m currently playing with, I figured I wanted to do something about it. So I created a small generator project which generates static classes where you have access to the domain objects property names in a type safe manner.  What this does for me is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If I do changes to a property of a domain object, and that has been used as a (previously) non-type safe identifier, my compiler will complain. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;I can do refactorings all the time without worry. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;For now it looks for instance like this in use:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080604_PropertyNames/img1_PropertyName.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;This will return “Text”, which is the name of a property in the Resource class or a base class. &lt;br /&gt;&lt;br /&gt;I’ll be the first to admit that this is not ideal. Property names as strings are not something you want to deal with, but at times you have no choice, and this feels like the better of the two options. &lt;br /&gt;&lt;br /&gt;For those interested in how I chose to solve it:&lt;br /&gt;The generator takes in an input path, a search string and an output path. This is put in a bat-file which is called from the domain projects build.  Currently I’ve only implemented a parser for NHibernate mapping files (HBM), which for each class creates a file with each property listed for that class. (I can see situations where you would want to use properties not just used in persistance, but that’s all I need for now). Inheritance is handled by duplicating the properties of the base class in the subclasses. &lt;br /&gt;In short, the file created for the example above looks like: &lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080604_PropertyNames/img2_Class.JPG" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-4808617153513278342?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/4808617153513278342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=4808617153513278342' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4808617153513278342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/4808617153513278342'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/06/type-safe-property-names.html' title='Replace strings for property names with type-safe version'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1094211891609292525</id><published>2008-04-09T22:20:00.010+02:00</published><updated>2008-06-25T14:33:08.824+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Regular Expressions'/><category scheme='http://www.blogger.com/atom/ns#' term='regex'/><title type='text'>Regular Expressions in Visual Studio – the top-down approach</title><content type='html'>Basically every approach to regular expressions I’ve seen uses the technique of learning all the symbols first, then using that to create various regular expressions. Let’s call that the bottom-up approach. I figured I could add some value by doing it the other way around – by showing specific strategies where regular expressions make sense, showing the regular expressions needed, and then explaining how it works. In other words, the top-down approach. &lt;br /&gt;&lt;br /&gt;Once you’ve read this post you should be able to use regular expressions to do pattern matching and extraction in Visual Studio. I’ve kept the number of regular expression meta-characters to a minimum, (hopefully) making it easily understandable as well. You’ll be far from an expert on regular expressions after reading this, but hopefully I can either help get you interested in regular expressions (You should!) or learn some tips about using it with Visual Studio.&lt;br /&gt;&lt;br /&gt;I’ve tried to divide the contents into logical sections, so just skip whatever doesn’t sound useful.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;On Visual Studio&lt;/h2&gt;The built in regular expression support in Visual Studio (2005) is fairly strange – it doesn’t quite follow conventional regular expression syntax, it doesn’t follow the .NET Framework syntax, and irregular behavior has been found. It’s not better that it seems extremely slow once you give it fairly large files either. &lt;br /&gt;&lt;br /&gt;Besides its drawbacks, it has become the place I use Regular Expressions the most. And trust me, I like using Regular Expressions. So why use Visual Studio? The probable reason is that I use it on a day to day basis, and since it’s not uncommon that I use it for searching, I guess it just became natural to start using it for other tasks as well.&lt;br /&gt;&lt;br /&gt;Oh, and by the way: There’s lots of regular expression software out there you should give a try. Free, good software, with somewhat more standards-based meta-characters, probably faster, likely to have more functionality related to regular expressions, and various other improvements. &lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Enabling Regular Expressions&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Regular expressions are used from the “Find and Replace” dialog&lt;/li&gt;&lt;br /&gt;&lt;li&gt;”Match case” also applies to your regular expressions&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The "Find in files" "Find and Replace" dialog (ctrl-shift-f) enables you to search only certain file types&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The "Find in files" "Find and Replace" dialog shows all results in the Find window, instead of just finding the next, as with the "Quick Find" dialog. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The most used regular expression meta-characters are available in the button next to find once you enable regular expressions.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I’ll add the actual dialog Visual Studio displays here just for reference. It describes each meta-character fairly well.&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080410_RegularExpressions/img1_CharacterList.JPG" /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Regular Expression Strategies&lt;/h1&gt;&lt;h2&gt;General&lt;/h2&gt;Ever after learning regular expressions I seem to always find good places to use them. Here’s the list of strategies(or common situations) I’ve covered in this post:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Extract content from lines with a common pattern &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remove empty lines (optionally with whitespace) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remove lines not following the pattern you are looking for&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add characters around each line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Retrieve the contents of all lines containing a pattern&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Regex strategy #1 - Extract content from lines with a common pattern&lt;/h2&gt;Since this is the first example, I’ll walk through this one extra slowly &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Description:&lt;/span&gt; You have a number of lines of contents that have some sort of similar text you want to extract. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example: &lt;/span&gt; We have two lines of text, and want to extract the value in the target part of the xml. &lt;br /&gt;&lt;br /&gt;&amp;lt;xml target="test" /&amp;gt;&lt;br /&gt;&amp;lt;xml info="" target="test2"/ &amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Steps: &lt;/span&gt; &lt;br /&gt;&lt;ol&gt;&lt;li&gt;Identify a unique string in the lines straight before the content you want to extract&lt;ul&gt;&lt;br /&gt;&lt;li&gt;target="&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Identify a unique string or character on the other side of the content&lt;/li&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;"&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The major part of the job is done; just create the regular expression to use the two first points :) &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;The regular expression we begin with to match the parts we identified above (Don’t test it yet, I’m skipping some important details still):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;target=" [^"]*"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Splitting this up we get three parts: target=", and " are just plain text matching. [^"]* is different though. If we take a look at the picture above, we can recognize two meta-characters:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;[^] – Any one character not in the set&lt;/li&gt;&lt;br /&gt;&lt;li&gt;* - Zero or more&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So [^"]* means match a character which is not a ", zero or more times. All regular expressions are greedy by default, so it will try to match as many characters as possible. &lt;br /&gt;&lt;br /&gt;To try to show this clearly I will differentiate the different parts of the regex and what it will match by using font styles. &lt;br /&gt;The regex:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;target="&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; [^"]*&lt;/span&gt;&lt;span style="font-style: italic;"&gt;"&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Will match:&lt;br /&gt;&lt;br /&gt;&amp;lt;xml &lt;span style="font-style: italic;"&gt;target="&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;test&lt;/span&gt;&lt;span style="font-style: italic;"&gt;"&lt;/span&gt; /&amp;gt;&lt;br /&gt;&amp;lt;xml info="" &lt;span style="font-style: italic;"&gt;target=”&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;test2&lt;/span&gt;&lt;span style="font-style: italic;"&gt;"&lt;/span&gt;/ &amp;gt;&lt;br /&gt;&lt;br /&gt;We’re not quite there yet. First of all we need to escape all non-letter and non-number characters with a \ to make sure they are interpreted as plain text characters. I didn’t do that above as it would have made it harder to understand at first. We get: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;target\=\"[^\"]*\"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Harder to read, but necessary. You’ll get used to it. &lt;br /&gt;&lt;br /&gt;We’re now able to match the text we want in both lines. However, we’re still unable to retrieve the information from the fields. To do that we first need to match the entire line, so that we can remove the parts we don’t want. To do that we add .* to the beginning and end of the expression:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;.*target\=\"[^\”]*\".*&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The . (dot) is a special character which is interpreted as "Any single character" (Except line break). The regular expression will then read: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;.* - Match as many characters as possible (Up until the (last) target\=\" part of the text&lt;/li&gt;&lt;br /&gt;&lt;li&gt; target\=\" - Match the plain text target=", &lt;/li&gt;&lt;br /&gt;&lt;li&gt;[^\"]* - Match as many characters as possible until we reach a "-character&lt;/li&gt;&lt;br /&gt;&lt;li&gt;" - Match the "-character.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;.* - Match as many characters as possible. (Since this is the last one, it means to the end of the line)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;With the above expression we match the entire line. The final part we need is a way of extracting the information we want. We’ll do that by adding { and }. This is basically a grouping construct, and you can have any number of them in your expression.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;.*target\=\"&lt;span style="font-weight: bold;"&gt;{&lt;/span&gt;[^\"]*&lt;span style="font-weight: bold;"&gt;}&lt;/span&gt;\".*&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;We now have the entire regular expression we need! Let’s test it. Copy the example xml text into a text document and open it in Visual Studio. Open a "Find and Replace" dialog, and add the regular expression. Then add \1 in the "Replace with: " part. \1 means the part you have between your first { and }. In other words:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt;  .*target\=\"{[^\"]*}\".*&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt; \1&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The result is:&lt;br /&gt;&lt;br /&gt;test&lt;br /&gt;test2&lt;br /&gt;&lt;br /&gt;Success! :) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final comments:&lt;/span&gt; &lt;br /&gt;Interested in how the regular expression engine actually does the matching? Let’s see what it matches for each part of the expression, until we reach the final match. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;.* - Match as many characters as possible. &lt;/span&gt;This will actually match the entire line. Since the .-character doesn’t match a line break it stops at the end of the line (in other programs with other options, it is possible to make it match line breaks as well.) Remember, it is greedy, so it wants to match as much as possible.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;target\=\" - Match the plain text: target=",.&lt;/span&gt; Now, to be able to fulfill this requirement, it has to "let go" of some of the matched characters. So it let’s go of one and one character until it finds that it can match the string. That’s why, if there had been several target="-parts in the line, it would have matched the last one. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt; [^\"]* - Match as many characters as possible until we reach a "-character. &lt;/span&gt; Match one and one character, until it reaches a "-character. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;" - Match the "-character. &lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;.* - Match as many characters as possible.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In fact, different regular expression engines do the matching in a different way, but this is all you need to know to understand how it works.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Regex strategy #2 - Remove empty lines (optionally with whitespace)&lt;/h2&gt;&lt;span style="font-weight: bold;"&gt; Description: &lt;/span&gt; You have a document with several empty lines you want to remove.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example: &lt;/span&gt;: We want to get rid of the empty line between the two words. &lt;br /&gt;&lt;br /&gt;SomeText&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SomeOtherText&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Steps:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;All you really need is the following: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt;  ^:b*$\n&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt; &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;The meta-characters used here means: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;^ - Beginning of line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;$ - End of line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;:b – Space or tab&lt;/li&gt;&lt;br /&gt;&lt;li&gt;\n – Line break &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;When splitting the regular expression into parts it can be read like this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;^ - The match must start from the beginning of the line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;:b* - It will be followed by zero or more (as many as possible) whitespace characters. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;$ - The match must end at the end of the line. In other words, the line must contain either no characters or only whitespace characters to give a match.  &lt;/li&gt;&lt;br /&gt;&lt;li&gt;\n – Finally we match the line break for the line as well. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;This regular expression will match empty lines, including the line break. By replacing them with nothing you get the effect of removing the lines. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final comments:&lt;/span&gt; &lt;br /&gt;Make sure you have a line break after your last line, or it won’t match the regular expression, as the regular expression requires a line break. Optionally you could have appended a * to the \n, making the expression *:b*$\n*. This would have removed the need for the final line break. &lt;br /&gt;&lt;br /&gt;Using Excel to sort the data is a good alternative to remove empty lines. That won’t work if you don’t want the data sorted of course. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;Regex strategy #3 - Remove lines not following the pattern you are looking for&lt;/h2&gt;&lt;span style="font-weight: bold;"&gt;Description:&lt;/span&gt; With the apparent weakness of regular expression matching in Visual Studio, in that you need to replace the entire line to retain the information you want (instead of getting the matches in a separate window), it is not uncommon to get into the situation where you have lines that you need to remove to be able to focus on the lines containing the information you want. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt; We got some more XML, this time with comments we want to get rid of:&lt;br /&gt;&lt;br /&gt;&amp;lt;!—xml comment --&amp;gt;&lt;br /&gt;&amp;lt;element&amp;gt;&lt;br /&gt; &amp;lt;!—another comment --&amp;gt;&lt;br /&gt; &amp;lt;subelement /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Steps:&lt;/span&gt;&lt;br /&gt;The general strategy here is to do a (preferably) two-step action to &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Mark the lines you don’t want with a special identifier&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remove all lines with the special identifier&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The actual steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Identify a unique string or recurring pattern in the lines you want to remove&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&amp;lt;!&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Write the regular expression to identify and then add the identifier to the line&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt;  ^.*\&amp;lt;\!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt;  #\0&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remove the lines containing the special identifier&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt; ^\#.*$\n&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt; &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;With point 2, you want to single out all the lines you don’t need (Preferably in one operation, but not always possible). If you have a unique identifier across the entire document, then where you match in the string and add the identifier is unimportant. Often, placing it in the beginning or end of the line is a good starting point. &lt;br /&gt;&lt;br /&gt;The first find operation (^.*\&amp;lt;\!) should be easy to read now, as there are no new characters. But for the sake of it: Match start of line, match as many characters as possible until we match the last set of &amp;lt;! in the line. &lt;br /&gt;&lt;br /&gt;The replace operation is slightly different. # is the special unique identifier we have used here. It has no special meaning – you could have used an x, or three x-es for that matter, as long as it is unique for the entire line or position throughout the document. Whereas \1 meant the first specified match we found (marked by { and } on each side), \0 holds a copy of the entire line that had a match in it. In effect this means that we simply add a # to the beginning of each line matched. &lt;br /&gt;&lt;br /&gt;With point 3, we want to remove all lines with the identifier. So we find each line with the special identifier in the beginning, match the rest of the line with .*$\n, just as before, and then replace it with an empty string.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final comments:&lt;/span&gt;&lt;br /&gt;Another possibility is matching the lines you want to keep, tagging them with the special identifier, and then removing the lines not containing the identifier. Of course you will have to remove the special identifier in the end, so there’s one more replace involved. Not a big thing though. &lt;br /&gt;&lt;br /&gt;A third possibility is to use strategy #5 – Retrieve the contents of all lines containing a pattern. This is most useful when you need to match across several documents. &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;Regex strategy #4 – Add characters around each line&lt;/h2&gt;&lt;span style="font-weight: bold;"&gt;Description:&lt;/span&gt; At times I seem to end up in the situation where I have lines of information that I need to surround with information or characters. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt; We have a number of lines of information which need to be used in an SQL in-query as strings, and thus need the necessary surrounding characters. The SQL query is: SELECT * FROM something WHERE name in (…). For those unfamiliar with SQL syntax, we want to add a ‘ to the left of the expression and ‘, on the right side.  The information:&lt;br /&gt;&lt;br /&gt;Test1&lt;br /&gt;Test2&lt;br /&gt;Test3&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Steps:&lt;/span&gt;&lt;br /&gt; As long as none of the lines involved already has the necessary characters and no characters that will invalidate the statement, all we need to do is: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt; ^.*$&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt; ‘\0’,&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The find simply matches everything on each line, from start to end character. &lt;br /&gt;The replace puts our plain text characters on each side of the expression. The result is:&lt;br /&gt;&lt;br /&gt;‘Test’,&lt;br /&gt;‘Test2’,&lt;br /&gt;‘Test3’,&lt;br /&gt;&lt;br /&gt;You’ll need to remove the last ,-character yourself, and paste it into the SQL query, making it:&lt;br /&gt;&lt;br /&gt;SELECT * FROM something WHERE name in (‘Test’,&lt;br /&gt;‘Test2’,&lt;br /&gt;‘Test3’)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final comments:&lt;/span&gt;&lt;br /&gt;Another common usage is creating SQL inserts. The logic is just the same; just add some other information around.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Regex strategy #5 - Retrieve the contents of all lines containing a pattern&lt;/h2&gt;&lt;span style="font-weight: bold;"&gt;Description:&lt;/span&gt; You want to get the contents of all lines matching a certain pattern, either because the lines make sense for themselves, or because you want to do further work on the lines. This can of course be for one or multiple documents.&lt;br /&gt;&lt;br /&gt;This is an alternative to using strategy #3 (Removing lines not following the pattern you are looking for). Strategy #3 is probably faster when you work on a single document. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt;  Reusing a previous example contents. This time we want to retrieve all of our XML-comments:&lt;br /&gt;&lt;br /&gt;&amp;lt;!--xml comment --&amp;gt;&lt;br /&gt;&amp;lt;element&amp;gt;&lt;br /&gt; &amp;lt;!--another comment --&amp;gt;&lt;br /&gt; &amp;lt;subelement /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Steps:&lt;/span&gt; &lt;br /&gt;&lt;ol&gt;&lt;li&gt;The regular expression needed to find the correct lines aren’t really the important part here, as what we wan’t to show is how we go from there. We don’t even need to use a regular expression in this case, just search for &amp;lt;!--. The important part here is to do this search in the “Find in Files”-dialog (ctrl-shift-f). The results listed should be:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;C:\aPath\file.txt(1): &amp;lt;!--xml comment --&amp;gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;C:\aPath\file.txt(3): &amp;lt;!--another comment --&amp;gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now copy the results from the “Find Results”-window and paste them into a document. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;We need to remove the path information. Use the following:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Find:&lt;/span&gt;  ^[^\:]*.[^\:]*.  &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;^ - The match must start from the beginning of the line&lt;/li&gt;&lt;br /&gt;&lt;li&gt;[^\:]* - Match zero or more (as many as possible) non-:-characters. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;.  - Match the :-character&lt;/li&gt;&lt;br /&gt;&lt;li&gt;[^\:]*- Match zero or more (as many as possible) non-:-characters. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;.  - Match the :-character&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Replace:&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now we remain with only the lines we’re interested in. &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Where do you go from here?&lt;/h1&gt;If you really want to learn about regular expressions, you’ll need to get &lt;a href=”http://www.oreilly.com/catalog/regex/”&gt;Mastering Regular Expressions (Jeffrey Friedl)&lt;/a&gt;. The book is THE book on regular expressions. &lt;br /&gt;&lt;br /&gt;If you for some reason don’t want to get the book, a series of 10 videocasts from &lt;a href=" http://blogs.msdn.com/zainnab/pages/regular-expression-webcast-series.aspx" target="_out"&gt;Zain Naboulsi (Is this thing on)&lt;/a&gt; should be your second choice. Besides being well made, it focuses only on .NET, which Mastering Regular Expressions only does partly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1094211891609292525?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1094211891609292525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1094211891609292525' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1094211891609292525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1094211891609292525'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/04/regular-expressions-in-visual-studio.html' title='Regular Expressions in Visual Studio – the top-down approach'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1944300030547274777</id><published>2008-02-22T19:44:00.034+01:00</published><updated>2008-02-26T18:12:29.742+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='IoC Containers'/><category scheme='http://www.blogger.com/atom/ns#' term='Castle Windsor'/><title type='text'>IoC Containers generally, Castle Windsor specifically</title><content type='html'>First I’ll have a go at reinventing the wheel by trying to give my own definition of an IoC Container&lt;br /&gt;&lt;blockquote&gt;An Inversion of Control (IoC) Container is a non-invasive configurable intelligent factory-component &lt;/blockquote&gt;&lt;br /&gt;Splitting this definition in parts, we get&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Factory, because it is responsible for creating objects for you. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Intelligent, because it understands what dependencies you have, and create them for you recursively. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Configurable, because you can configure the usage through code or configuration files. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Non-invasive, because the objects used doesn’t need to know about the container. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;An IoC Container really makes the Dependency Injection pattern a lot better. Why? I’ll look more into that throughout this post.&lt;br /&gt;&lt;br /&gt;My previous post is a foundation for this one, as it explains the Dependency Injection pattern, and gives it a place in the world. I’ll use no time on that here. This post exists to build on that content, and show what more benefits you can achieve by using the dependency injection pattern with an IoC Container. This isn’t meant to be a comprehensive introduction to IoC Containers or Castle Windsor, but should give you a good idea of what it can do for you. Once you’ve read it, just continue on with what I’ve added in “References and further reading”.&lt;br /&gt;&lt;br /&gt;I’ll use a simple example to help explain how it works. We have a client, which uses a service, which again depends on &lt;span style="font-style: italic;"&gt;IStorageObject&lt;/span&gt;, which have two specific implementations. This is not meant as a real world example, but bear with me. The dependencies and sample implementation are shown below:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img1_diagram.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img2_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img3_serviceimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img4_databaseimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img5_cacheimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;My &lt;a href="http://rune-sundling.blogspot.com/2008/02/purpose-of-this-post-is-to-pass-on.html" target="_out"&gt;previous post&lt;/a&gt; shows how we can handle this manually, and the pros and cons with the different solutions. We would like to get an instance of client, but we need to handle all the dependencies it has as well. If we have to write this manually, it will turn out as something like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img6a_manual.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;This doesn’t look too bad, and the dependency injection approach is often better than a lot of alternatives. But think of it. As soon as this starts expanding, I can bet you that you’ll have a mouthful.&lt;br /&gt;&lt;br /&gt;Now to do the same with an IoC Container, you can typically write:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img6_iocresolvae.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;For the container to create &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt;, it needs to create an instance of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt;, but also an instance of both &lt;span style="font-style: italic;"&gt;IService &lt;/span&gt; and &lt;span style="font-style: italic;"&gt;IStorageObject&lt;/span&gt;. The container will understand that it needs to create both, and does so depending on how you have configured it. More on that later.&lt;br /&gt;&lt;br /&gt;What if we add another dependency to the service implementation? The manual code would have to change to something like this (Each and every place service is created in the code. Resharper could help you quite a bit, but it’s far from a solution to the real issue.):&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img6b_manual.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;Already guessed how it would look with the container approach?&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img6_iocresolvae.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;You are right, just the same :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This has a number of advantages:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Easy to swap the implementation of an interface - just change the configuration. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you find that &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; suddenly needs another dependency, you don’t have to rewrite any of the &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; creation code. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Removes explicit dependency-handling throughout the system&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Single point to find out how objects are instantiated and connected&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easy to begin using &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in other places. (Less boilerplate code to write) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Additional benefits of tunneling dependencies through one source: Decorators, Interceptors, Proxies, as well as handling object lifestyle. Have a look &lt;a href="http://msdn2.microsoft.com/en-us/library/aa973811.aspx" target="_out"&gt;here&lt;/a&gt; for a very good example. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;See my &lt;a href="http://rune-sundling.blogspot.com/2008/02/purpose-of-this-post-is-to-pass-on.html" target="_out"&gt;previous post&lt;/a&gt; for more on the general benefits of dependency injection. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I am going to have a look at an IoC Container called Castle Windsor now. There are many other alternatives as well. I can’t speak too much about the others as I only have real life experience with this. If we talk only about the general dependency injection problem/solutions, the different projects have a lot of similarities, with some differences in support for config vs code, need for attributes etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuration and use - with XML &lt;/h2&gt;You can use a separate configuration file, or add the castle definitions to your app/web.config.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img7_xmlconfig.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;The configuration above states:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The string identifier of our only component is “storageobject” &lt;/li&gt;&lt;br /&gt;&lt;li&gt;The service (or interface) the container will create (if any - you don't need to specify one), is &lt;span style="font-style: italic;"&gt;IStorageObject&lt;/span&gt;, from &lt;span style="font-style: italic;"&gt;TheNamespace&lt;/span&gt; namespace&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The specific implementation of this interface is &lt;span style="font-style: italic;"&gt;DatabaseObject&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In practice, this means that if the container is ever asked for an implementation of “storageobject” or the &lt;span style="font-style: italic;"&gt;IStorageObject &lt;/span&gt; interface, directly or through resolving dependencies, it will return an instance of &lt;span style="font-style: italic;"&gt;DatabaseObject&lt;/span&gt;..&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img8_xmlconfigstart.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;This code simply shows how the container would be started with this approach.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuration and use - with code&lt;/h2&gt;You can define everything in code:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img9_codeconfig.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The pros and cons of using XML versus code is that you can do changes without recompiling with the XML approach, while it is type safe when you specify it in code. Use whatever is best for your situation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Lifestyle&lt;/h2&gt;Advanced handling of the lifestyle of objects has never been so easy. By adding a keyword, you can specify how your object lifestyle will be:&lt;br /&gt;&lt;br /&gt;&lt;img style="width: 413px; height: 111px;" src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img10_lifestyle.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;The previous configuration updated with specification of lifestyle:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_IoCContainer/img11_xmllifestyle.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Facilities&lt;/h2&gt;Adds integration with other tools&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NHibernate&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ActiveRecord&lt;/li&gt;&lt;br /&gt;&lt;li&gt;WCF integration&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remoting&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Logging&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Startable&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Custom&lt;/li&gt;&lt;br /&gt;&lt;li&gt;+++&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Other&lt;/h2&gt;Castle has a number of other possibilities as well, like specifying what to do when objects are created and destroyed (Commision and Decomission).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Note&lt;/h2&gt;The last couple of points feels kind of pointless without giving them much extra attention, but I'll leave that to other people who have described it much better. A good starting point would be &lt;a href="http://dotnetslackers.com/articles/designpatterns/InversionOfControlAndDependencyInjectionWithCastleWindsorContainerPart1.aspx" target="_out"&gt;this&lt;/a&gt; or &lt;a href="http://wiki.bittercoder.com/Default.aspx?Page=ContainerTutorials" target="_out"&gt;this&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;References and further reading&lt;/h1&gt;&lt;a href="http://dotnetslackers.com/articles/designpatterns/InversionOfControlAndDependencyInjectionWithCastleWindsorContainerPart1.aspx" target="_out"&gt;Inversion of Control and Dependency Injection with Castle Windsor Container - Part I (Simone Busoli)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/aa973811.aspx" target="_out"&gt;Inversion of Control and Dependency Inject: Working with Windsor Container (Ayende)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://beust.com/weblog/archives/000262.html" target="_out"&gt;A not so interesting post, with much more interesting comments.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.bittercoder.com/Default.aspx?Page=ContainerTutorials" target="_out"&gt;Castle Windsor tutorials (BitterCoder's Wiki)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/articles/injection.html" target="_out"&gt;Inversion of Control Containers and the Dependency Injection pattern (Martin Fowler)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.castleproject.org/" target="_out"&gt;Castle Project&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Conclusive thoughts&lt;/h1&gt;Although a short introduction, I hope I have captured enough information to get you interested. I’ve been using Castle for quite some time on my last project, and I am very happy with the results. I advise you to give it a try!&lt;br /&gt;&lt;br /&gt;_&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1944300030547274777?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1944300030547274777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1944300030547274777' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1944300030547274777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1944300030547274777'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/02/ioc-containers-generally-castle-windsor.html' title='IoC Containers generally, Castle Windsor specifically'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4900151497087138627.post-1797035453102671403</id><published>2008-02-19T20:44:00.033+01:00</published><updated>2008-02-26T18:11:56.292+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='Service Locator'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='Factory'/><title type='text'>Objects, dependencies and  patterns to manage it</title><content type='html'>The purpose of this post is to pass on knowledge about an important aspect of software development, with the hopes that someone else can have use for it. It is a presentation I held at work changed into written form.&lt;br /&gt;&lt;br /&gt;The topic is managing dependencies between objects; how it affects the systems we build, and a few thoughts on different ways to handle it. We are going to look at three patterns: Factory, Service Locator and Dependency Injection, which in various ways help us control the dependencies. The purpose here is not to explore all the details of the various patterns, but rather to capture how the patterns handle these situations in general.&lt;br /&gt;&lt;br /&gt;As a way of comparing the patterns, I’ve put together a few well known principles that has important things to say on the quality of software.&lt;br /&gt;&lt;br /&gt;Simplicity&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Complexity is so important to handle. Complex code is hard to read, change and manage. The challenge is to write code that people understand, not just code that compiles.&lt;/li&gt;&lt;/ul&gt;Separation of concerns (SoC) / High cohesion&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Software that separates its different parts well is easier to understand and manage. The more a unit of code,which from now on should be understood as either a module, class or method, handles only a separate piece of the puzzle, the better. The Single Responsibility Principle fits well here: One unit of code should do only one thing, and do it very well.&lt;/li&gt;&lt;/ul&gt;Loose coupling&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How much your unit of code depends on other parts of the system. Less coupling means code that is easier to understand, maintain and reuse in different contexts.&lt;/li&gt;&lt;/ul&gt;Ease of change&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Highly related to all of the points above. We want code that is easy to change. The reason for this is of course that there are few environments were things change more often, be it because of business or technological needs, or really just realizing the nature of most software projects.&lt;/li&gt;&lt;/ul&gt;Encapsulation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Design choices that are not important to know of outside of your unit of code, should not be visible there either. It only increases complexity, makes things harder to change, and removes focus from what is really important.&lt;/li&gt;&lt;/ul&gt;Testability&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Highly testable code has a number of benefits for the quality of your system, and is an important principle to live up to for the vast majority of projects.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I have created an example we will use throughout the post. It consists of two elements, a client and a service. The simplicity makes it impossible not to understand, as well as hopefully easier to relate to a number of situations, though making it harder to show real world problems and their solutions directly.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img1_clientservice.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;The service could be anything from an in-process calculator to an expensive web service or database service. The context has a lot to say for the conclusions, and it is vital that you relate the examples that will follow to the many similar situations you see on a daily basis. Depending on whether we would expect change here, we might or might not include an interface.&lt;br /&gt;&lt;br /&gt;This is an example of the implementation of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; (in C#):&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img2_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;Potential problems with this code&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It is hard to change, because it is connected to a concrete implementation of the service in the constructor.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;You need to read the &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; code to find that it has a dependency to &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Testability would be hurt if this was a resource-expensive or unreliable service.&lt;/li&gt;&lt;/ul&gt;Potential advantages of this code&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It might do exactly what it needs to do - If it seems natural that &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; should be responsible for creating &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt;, if there is no benefit of changing the implementation of &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt; in different situations, if testing isn’t hurt by not accessing it, then by all means keep it as simple as you can. YAGNI (You ain’t gonna need it) and KISS (Keep it simple, stupid) are important principles to follow.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As a side note concerning testing: It is possible to test this with TypeMock.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;What if we increase the complexity of this example? Let's add an &lt;span style="font-style: italic;"&gt;IStorageObject&lt;/span&gt;, which is a common interface for two ways of storing data, &lt;span style="font-style: italic;"&gt;DatabaseObject&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;CacheObject&lt;/span&gt;. As the diagram below shows, &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt; now has a dependency towards &lt;span style="font-style: italic;"&gt;DatabaseObject&lt;/span&gt; (And to IStorageObject, though not shown explicitly).&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img3_diagram.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;And the implementation:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img4_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img5_serviceimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;As simple as this example is, we already have a potential for tight coupling. Even though we are coding to interfaces, this is not that easy to change. Reusing &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt; in a different context is very hard. Replacing the implementation with a mock or stub during testing is in most cases impossible. And even though this example hides it, both &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; is now responsible for both creating and using the dependency, responsibilities we often want to separate (e.g. because of complex initialization). In real life, the complexities and couplings are often increased tenfold, and only then can you see the true value of these principles.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Pattern #1 - Factory&lt;/h2&gt;The factory pattern is one of the &lt;a href="http://en.wikipedia.org/wiki/Design_Patterns" target="_out"&gt;GoF&lt;/a&gt; patterns, a creational pattern, responsible only for creating objects.  I have created a dead simple implementation of the factory pattern, where you have a &lt;span style="font-style: italic;"&gt;ServiceFactory&lt;/span&gt; class with a static method to give you the concrete instance you want.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img6_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;The dependencies can be modeled like this:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img7_diagram.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Advantages&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; only has a direct dependency on &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt; now, not the concrete initialization.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The code is more testable, if we have a factory where we can switch the concrete instance with a mock object.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The usage of &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt; will be clearer and easier to start using as all creational logic has been separated.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Having a single place to get instances of a service means you have more general possibilities, like the transparent handling of instances (always new or singleton). I will look at others throughout this and the &lt;a href="http://rune-sundling.blogspot.com/2008/02/ioc-containers-generally-castle-windsor.html" target="_out"&gt; next post&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;We have separated the responsibility of creating and using the service. If creating a service means several manual steps to configure it, then this is even more valuable.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The Factory could return a different implementation based on input, a common reason to use a factory.&lt;/li&gt;&lt;/ul&gt;Problems&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In our situation, we still have a compile time dependency on the specific &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt; implementation. The dependency has only moved a step out.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Reuse of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in different contexts is hard, because of the still tight coupling to &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If we look back at the example with the deeper dependencies. Should we make another factory to handle this creation?  Has this really loosened the coupling that much, and do we want to use all our time writing boilerplate factory-code?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;We still have to read the implementation of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; to find that it has a dependency towards &lt;span style="font-style: italic;"&gt;Service&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;That being said, let’s look at how it lives up to the different principles listed in the beginning&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Simplicity&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The factory pattern is easy to use, and is one of the most known patterns. Thus, using it will help give clarity to what you try to achieve, even to developers less versed in the "patterns world". Though it is not correct in every situation, and too many factories is not necessarily a good thing either.&lt;/li&gt;&lt;/ul&gt;Separation of concerns (SoC) / High cohesion&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The creation and use of a dependency is separated.&lt;/li&gt;&lt;/ul&gt;Loose coupling&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The example still has a compile time dependency on the concrete implementation of &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt;. In many cases the factory pattern can help with the coupling, for instance by sending in some form of input.&lt;/li&gt;&lt;/ul&gt;Ease of change&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Reusing &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in a different context is hard because of the still tight coupling.&lt;/li&gt;&lt;/ul&gt;Testability&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If the implementation of the factory allows you to switch implementations, then yes, it is more testable.  You need to initialize the factory with every test however, and even switch back again to the previous implementation to make sure that you don’t break other tests.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Pattern #2 – Service Locator&lt;/h2&gt;An (potentially global) object that gives access to services the application needs.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The example changes to:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img8_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img9_sldiagram.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;Instead of the factory class we now have the service locator that creates and/or returns the service. The biggest change here is that you now have an assembler class which typically configures the Service Locator with the correct instances.&lt;br /&gt;&lt;br /&gt;Two points concerning the implementation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In the example above I have used a string to get the correct type of service. This might as well have been solved with sending in a type or using generics if you want type safety and support for refactoring, at the cost of some flexibility though.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The example uses a Service Locator interface to separate the &lt;span style="font-style: italic;"&gt;LocateService&lt;/span&gt; method from the methods &lt;span style="font-style: italic;"&gt;Assembler&lt;/span&gt; uses to register services. The implementation is still a singleton, and could be changed to not use GetInstance first.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Advantages&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Encapsulates the logic to find services.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A separate interface to deal with.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A central point of control. Easier to do similar things with the services you get, like handling instances and caching.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Can add a mock implementation during testing.&lt;/li&gt;&lt;/ul&gt;Problems&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Hard to handle deeper dependencies well.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Advanced initialization of objects, which the factory does so well, is hard.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Possibly code to reset the service locator to make sure that one test does not break others.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;And onto the principles:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Simplicity&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Easy to use. A single method to call.&lt;/li&gt;&lt;/ul&gt;Separation of concerns (SoC) / High cohesion&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The creation and use of a dependency is separated.&lt;/li&gt;&lt;/ul&gt;Loose coupling&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If you have an implementation that uses an XML file to configure up the specific instances, then there is no compile time dependency.&lt;/li&gt;&lt;/ul&gt;Ease of change&lt;br /&gt;&lt;ul&gt;&lt;li&gt;As there is less coupling, it is easier to change as well. Reusing &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in a different context is still often troublesome though.&lt;/li&gt;&lt;/ul&gt;Testability&lt;br /&gt;&lt;ul&gt;&lt;li&gt;This pattern does make it even easier to test than Factory, but you still have to write extra code to create and change the service locator.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Pattern #3 – Inversion of Control / Dependency Injection&lt;/h2&gt;A fancy word for a really simple principle: it simply means injecting dependencies.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img10_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img11_didiagram.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see in the images above, &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; now receives the specific implementation of &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt; from the outside.&lt;br /&gt;&lt;br /&gt;Before going further, I think it is necessary to write a couple of lines about the confusion concerning the two concepts Inversion of Control and Dependency Injection. Inversion of Control is a common concept in computing. It relates to a situation where you instead of taking the active approach and asking for something, the framework is the active part that calls you. (i.e. events, the startup method of an application, etc) Dependency Injection is a specific form of Inversion of Control, where instead of asking for a specific dependency (As was done with Factory and Service Locator), the dependency is handed to you.&lt;br /&gt;&lt;br /&gt;There are three types of Dependency Injection: Constructor, Setter and Interface injection.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Constructor injection&lt;/span&gt;&lt;br /&gt;- what is shown above, injecting the dependencies in the constructor.&lt;br /&gt;&lt;br /&gt;Advantages&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Any user of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; will see that it has a dependency on &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Unlike the other injection approaches, &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; is completely initialized once created, as you can’t create it without giving it an instance of &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You can set &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt; as ReadOnly, since it is set in the constructor.&lt;/li&gt;&lt;/ul&gt;Problems&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If you have optional dependencies, especially if they are resource-intensive to create, then it is not a good idea to initialize them in the constructor.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If you have many optional dependencies, and want to give a separate constructor for each valid case, then you soon end up with a lot of constructors.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Setter injection&lt;/span&gt;&lt;br /&gt;- Injecting the dependency through a property.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img12_clientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;Advantages&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Good way to handle optional dependencies, especially if they are resource-intensive.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Support for Dependency Injection in legacy code without having to change the constructor, for instance to improve testing, or to add new functionality.&lt;/li&gt;&lt;/ul&gt;Problems&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Harder to know what you need to do to use the object, which can lead to surprises.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Somewhat harder to track down exceptions.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Interface injection&lt;/span&gt;&lt;br /&gt;– a special form of setter injection: Specifying injector methods in an interface.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.rammeland.com/blogpics/20080218_Dependencies/img13_injectorclientimpl.JPG" /&gt;&lt;br /&gt;&lt;br /&gt;As this is almost identifcal to Setter injection, there isn’t much else to say about it. The only difference is that it can help separate out what are really dependencies that must be filled. However, this seems to be the least used form of dependency injection.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Advantages of using Dependency Injection in general&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Easier to test: You can simply inject a mock.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Potential for less coupling, as it doesn’t ask for a specific implementation.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Easy to reuse &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in different contexts, because of the point above.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Not necessarily compile time binding. And even if so, different implementations of &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; can easily be bound to different implementation of &lt;span style="font-style: italic;"&gt;IService&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;Problems&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You’re not supposed to inject everything. One problem is that you can break encapsulation, another that you should take care not to create interfaces for all objects in your system. Coding to interfaces is a good thing, but making interfaces where you don’t expect change or testing isn’t a good enough reason, will make it hard to see where you truly expect change in the system.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It can be cumbersome to do Dependency Injection manually. I look at a solution for that in my &lt;a href="http://rune-sundling.blogspot.com/2008/02/ioc-containers-generally-castle-windsor.html" target="_out"&gt; next post&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So how does Dependency Injection live up to the initial principles?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Simplicity&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Simple to write and understand. But writing manually can be time-consuming.&lt;/li&gt;&lt;/ul&gt;Separation of concerns (SoC) / High cohesion&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The creation and use of a dependency is separated. Also, &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; only uses the dependency now. Compared to the other patterns, &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; doesn’t even need to ask for an implementation.&lt;/li&gt;&lt;/ul&gt;Loose coupling&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The code has a potential for even less coupling, as it only uses it's dependencies.&lt;/li&gt;&lt;/ul&gt;Ease of change&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Easy to change in terms of using &lt;span style="font-style: italic;"&gt;Client&lt;/span&gt; in different contexts, but manual dependency injection code isn’t any easier to change.&lt;/li&gt;&lt;/ul&gt;Encapsulation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Don’t break encapsulation where it’s not natural.&lt;/li&gt;&lt;/ul&gt;Testability&lt;br /&gt;&lt;ul&gt;&lt;li&gt;By far the easiest way of testing objects where you need to add a mock implementation.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;References and further reading&lt;/h1&gt;&lt;a href="http://martinfowler.com/articles/injection.html" target="_out"&gt;Inversion of Control Containers and the Dependency Injection pattern&lt;/a&gt; [Martin Fowler]&lt;br /&gt;&lt;br /&gt;A few of the posts on a longer discussion of Dependency Injection: (You can find more from each)&lt;br /&gt;&lt;a href="http://scruffylookingcatherder.com/archive/2007/08/07/dependency-injection.aspx" target="_out"&gt;Dependency Injection&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ayende.com/Blog/archive/2007/08/18/Dependency-Injection-More-than-a-testing-seam.aspx" target="_out"&gt;Dependency Injection: More than a testing seam&lt;/a&gt;&lt;br /&gt;&lt;a href="http://kohari.org/2007/08/15/defending-dependency-injection/" target="_out"&gt;Defending Dependency Injection&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.elilopian.com/2007/08/19/dependency-injection-keep-your-privates-to-yourself/" target="_out"&gt;Dependency Injection - Keep your privates to yourself&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/05/09/DesignPatterns/default.aspx" target="_out"&gt;Dependency Injection - MSDN Magazine&lt;/a&gt;&lt;br /&gt;&lt;a href="http://crazybob.org/2007/06/introduction-to-guice-video-redux.html" target="_out"&gt;Guice video. Some good general points as well, if you're bored with reading. &lt;/a&gt;&lt;br /&gt;&lt;a href="http://books.google.com/books?id=RZXGAAAACAAJ&amp;dq=applying+domain+driven+design" target="_out"&gt;Applying Domain-Driven Design and Patterns (Book) - On Dependency Injection and Service Locator&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Design_Patterns" target="_out"&gt;GoF (Book) - On Factory&lt;/a&gt;&lt;br /&gt;&lt;a href="http://books.google.com/books?id=LjJcCnNf92kC" target="_out"&gt;Head First Design Patterns (Book) - On Factory&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Conclusive thoughts&lt;/h1&gt;At the outset of creating this presentation, I was planning to only write about the Dependency Injection pattern. However, I felt that putting it in a bigger context, and trying to present the different patterns in a more uncommon way would be more helpful. This is by far perfect, but if it can help anyone better see the usage of these patterns and part of their place in the world, then it was worth rewriting this for the web. Not the least, if anyone can further educate me as well, what could be better?&lt;br /&gt;&lt;br /&gt;This was part 1 of the presentation. Part 2 handles IoC Containers, and how you can do Dependecy Injection without having to do it manually.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4900151497087138627-1797035453102671403?l=rune-sundling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rune-sundling.blogspot.com/feeds/1797035453102671403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4900151497087138627&amp;postID=1797035453102671403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1797035453102671403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4900151497087138627/posts/default/1797035453102671403'/><link rel='alternate' type='text/html' href='http://rune-sundling.blogspot.com/2008/02/purpose-of-this-post-is-to-pass-on.html' title='Objects, dependencies and  patterns to manage it'/><author><name>Rune Sundling</name><uri>http://www.blogger.com/profile/10334374587401199926</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
