tag:blogger.com,1999:blog-49001514970871386272018-03-06T22:37:50.915+01:00Information is kingThoughts on my work and professionRune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.comBlogger63125tag:blogger.com,1999:blog-4900151497087138627.post-66734291399274799792011-04-03T23:23:00.007+02:002011-04-04T01:30:39.869+02:00Ønsker du å jobbe med meg?<p>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?</p><br /><p>Kort oppsummert har jeg<br /><ul><li>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.</li><br /><li>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.</li><br /><li>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).</li></ul></p><br /><p>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. </p><br /><p>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 <a href="http://bit.ly/CVRune" target="_blank">CV (pdf)</a>. 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: <a href="http://bit.ly/BlogQualityInSoftware" target="_blank">link</a>.</p> <br /><p>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<a href="http://www.google.com/recaptcha/mailhide/d?k=01En1ryLw2LolvJ1fSqSdpxQ==&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">...</a>@gmail.com, telefon: se CV, <a href="http://www.linkedin.com/in/runesundling" target="_blank">LinkedIn</a> og <a href="http://twitter.com/RuneSundling" target="_blank">Twitter</a>.</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com1tag:blogger.com,1999:blog-4900151497087138627.post-82585234317101094732011-03-20T19:06:00.002+01:002011-04-03T22:31:38.351+02:00Quality in software – a summary<p>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.</p> <p>&#160;</p> <p>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.</p> <p>&#160;</p> <p> 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: </p> <p>&#160;</p> <blockquote> <p><em>The pure and simple truth is rarely pure and never simple.</em></p> </blockquote> <blockquote> <p>- Oscar Wilde</p> </blockquote> <p>&#160;</p> <p>&#160;</p> <h3>Process</h3> <p>IT projects are complex. The Standish Group’s Chaos Report has attempted to cover this over many years (<a href="http://bit.ly/ChaosReport2009" target="_blank">2009 report in pdf</a>).&#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 <a href="http://agilemanifesto.org/" target="_blank">manifesto for Agile Software Development</a> devised in early 2001: </p> <p>&#160;</p> <blockquote> <p><em><strong>Individuals and interactions</strong> over processes and tools <br /><strong>Working software</strong> over comprehensive documentation <br /><strong>Customer collaboration</strong> over contract negotiation <br /><strong>Responding to change</strong> over following a plan</em></p> <p><em>That is, while there is value in the items on <br />the right, we value the items on the left more.</em></p> </blockquote> <p>&#160;</p> <p>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 <a href="http://rune-sundling.blogspot.com/2010/01/walking-on-water-and-developing.html" target="_blank">never know everything in advance</a>, and <a href="http://rune-sundling.blogspot.com/2010/01/changes-in-software-one-of-biggest.html" target="_blank">unexpected changes will occur</a>.</p> <p>&#160;</p> <p>The process within IT consists of both the main methodology used and the more technical practices followed. </p> <p>&#160;</p> <h2>Overall process</h2> <p>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. </p> <p>&#160;</p> <p>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?)</p> <p>&#160;</p> <p>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 <a href="http://rune-sundling.blogspot.com/2009/01/essential-project-practices.html" target="_blank">communication</a>. 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.</p> <p>&#160;</p> <p>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, <a href="http://www.infoq.com/articles/many-levels-planning-agile-project" target="_blank">this</a> is a good article explaining the importance of it, and at what levels planning should occur.</p> <p>&#160;</p> <h2>Technical process</h2> <p>The technical process is pretty much anything that directly relates to what is produced; estimation, tasks, quality assurance, and releasing new versions. </p> <p>&#160;</p> <p>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!: </p> <p>&#160;</p> <blockquote> <p><em>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.</em></p> </blockquote> <p>&#160;</p> <p>The quote, and significantly more, can be found in <a href="http://www.amazon.com/Agile-Estimating-Planning-Mike-Cohn/dp/0131479415" target="_blank">Agile Estimating and Planning</a> by Mike Cohn.</p> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p>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. <a href="http://martinfowler.com/articles/continuousIntegration.html" target="_blank">Continuous integration</a> 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. </p> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p>A lot more can be said about improving the release and deployment process. I recommend reading the book <a href="http://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912" target="_blank">Continuous Delivery</a> to get a better overview. </p> <p>&#160;</p> <p>&#160;</p> <h3>Technology</h3> <p>Beyond the general practices, what is important in technical development?</p> <p> <br />At both higher and lower levels, having a good overview of alternatives is necessary to select the right technology or solution (Never forget the <a href="http://en.wikipedia.org/wiki/Law_of_the_instrument" target="_blank">hammer nail analogy</a>). 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. </p> <p> <br />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? <a href="http://en.wikipedia.org/wiki/Code_refactoring" target="_blank">Refactor</a> 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? </p> <p> <br />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 <a href="http://pragprog.com/titles/mnee/release-it" target="_blank">Release It!</a>. </p> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p> <br /></p> <h3>People and roles</h3> <p>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). </p> <p> <br />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. </p> <p> <br /><a href="http://www.management30.com/book/" target="_blank">Management 3.0</a> has a lot to say about leading people in IT projects. As the author says</p> <blockquote> <p><em>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. </em></p> </blockquote> <p> <br /> </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-29800868570623374272010-08-01T23:28:00.009+02:002010-08-02T12:16:39.808+02:00Converting WCF WSDL to single file (FlatWSDL) - correctly!<p>Note! This post is slightly different than most FlatWSDL posts, and fixes the bug with removing the &lt;XS-import&gt;’s.</p> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p>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). </p> <p>&#160;</p> <p>The only problem is that both solutions emit a WSDL file without appropriate &lt;XS:Import&gt;’s for the schemas. Many tools are able to resolve the references without the import, but not all are as forgiving. This <a href="http://wcfextras.codeplex.com/Thread/View.aspx?ThreadId=49904" target="_blank">post</a> describes a code change to WCFExtras that will fix it, but I’ll add mine here as well. </p> <p>&#160;</p> <p>What you need to do is to download one of the FlatWSDL approaches (This <a href="http://weblogs.asp.net/pglavich/archive/2010/03/16/making-wcf-output-a-single-wsdl-file-for-interop-purposes.aspx" target="_blank">post</a> 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. </p> <p>&#160;</p> <pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)<br />{<br /> XmlSchemaSet generatedXmlSchemas = exporter.GeneratedXmlSchemas;<br /><br /> <span class="kwrd">foreach</span> (ServiceDescription generatedWsdl <span class="kwrd">in</span> exporter.GeneratedWsdlDocuments)<br /> {<br /> var referencedXmlSchemas = FindAllReferencedXmlSchemasRecursively(generatedWsdl, generatedXmlSchemas);<br /> ClearWsdlOfExistingSchemas(generatedWsdl);<br /> AddAllReferencedSchemas(generatedWsdl, referencedXmlSchemas);<br /> }<br /><br /> RemoveSchemaLocationFromXmlSchemaImports(exporter, generatedXmlSchemas);<br />}</pre><br /><style type="text/css"><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br /><pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">static</span> IEnumerable&lt;XmlSchema&gt; FindAllReferencedXmlSchemasRecursively(ServiceDescription wsdl, XmlSchemaSet generatedXmlSchemas)<br />{<br /> var referencedXmlSchemas = <span class="kwrd">new</span> List&lt;XmlSchema&gt;();<br /> <span class="kwrd">foreach</span> (XmlSchema schema <span class="kwrd">in</span> wsdl.Types.Schemas)<br /> {<br /> AddReferencedXmlSchemasRecursively(schema, generatedXmlSchemas, referencedXmlSchemas);<br /> }<br /> <span class="kwrd">return</span> referencedXmlSchemas;<br />}<br /><br /><span class="rem">/// &lt;summary&gt;</span><br /><span class="rem">/// Recursively extract all the list of imported</span><br /><span class="rem">/// schemas</span><br /><span class="rem">/// &lt;/summary&gt;</span><br /><span class="rem">/// &lt;param name=&quot;schema&quot;&gt;Schema to examine&lt;/param&gt;</span><br /><span class="rem">/// &lt;param name=&quot;generatedXmlSchemas&quot;&gt;SchemaSet with all referenced schemas&lt;/param&gt;</span><br /><span class="rem">/// &lt;param name=&quot;referencedXmlSchemas&quot;&gt;List of all referenced schemas&lt;/param&gt;</span><br /><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddReferencedXmlSchemasRecursively(<br /> XmlSchema schema,<br /> XmlSchemaSet generatedXmlSchemas,<br /> List&lt;XmlSchema&gt; referencedXmlSchemas<br /> )<br />{<br /> <span class="kwrd">foreach</span> (XmlSchemaImport import <span class="kwrd">in</span> schema.Includes)<br /> {<br /> ICollection realSchemas = generatedXmlSchemas.Schemas(import.Namespace);<br /> <span class="kwrd">foreach</span> (XmlSchema ixsd <span class="kwrd">in</span> realSchemas)<br /> {<br /> <span class="kwrd">if</span> (!referencedXmlSchemas.Contains(ixsd))<br /> {<br /> referencedXmlSchemas.Add(ixsd);<br /> AddReferencedXmlSchemasRecursively(ixsd, generatedXmlSchemas, referencedXmlSchemas);<br /> }<br /> }<br /> }<br />}<br /><br /><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> ClearWsdlOfExistingSchemas(ServiceDescription wsdl)<br />{<br /> wsdl.Types.Schemas.Clear();<br />}<br /><br /><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddAllReferencedSchemas(ServiceDescription wsdl, IEnumerable&lt;XmlSchema&gt; referencedXmlSchemas)<br />{<br /> <span class="kwrd">foreach</span> (XmlSchema schema <span class="kwrd">in</span> referencedXmlSchemas)<br /> {<br /> wsdl.Types.Schemas.Add(schema);<br /> }<br />}<br /><br /><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> RemoveSchemaLocationFromXmlSchemaImports(WsdlExporter exporter, XmlSchemaSet schemaSet)<br />{<br /> var mySchemaSet = <span class="kwrd">new</span> XmlSchemaSet();<br /> mySchemaSet.Add(schemaSet);<br /> <span class="kwrd">foreach</span> (XmlSchema schema <span class="kwrd">in</span> mySchemaSet.Schemas())<br /> {<br /> exporter.GeneratedXmlSchemas.Remove(schema);<br /> }<br />}</pre><br /><style type="text/css"><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com4tag:blogger.com,1999:blog-4900151497087138627.post-42525709789708856032010-07-28T18:00:00.005+02:002010-07-30T20:30:07.457+02:00Generating sample data for objects using AutoFixture, extending it with collections support, and using it as Silverlight sample data generator<p>This blog post consists of three parts</p> <p>- On generating sample data in general</p> <p>- Extending AutoFixture with automatic collections generation support</p> <p>- Adding a sample data generator in Silverlight for Visual Studio/Blend screen previews</p><p><br /></p><p>[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]<br /></p><p><br /></p> <h3>Generating sample data in general</h3> <p>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 <a href="http://blogs.msdn.com/b/ploeh/archive/2008/11/17/anonymous-variables.aspx" target="_blank">anonymous variable</a>). </p><br /><p>I’ve seen and used various solutions for this. Often you see it either done manually, by an <a href="http://martinfowler.com/bliki/ObjectMother.html" target="_blank">object mother</a>, with <a href="http://elegantcode.com/2008/04/26/test-data-builders-refined/" target="_blank">test data builders</a>, 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.</p><p><br /></p> <p>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 <a href="http://autofixture.codeplex.com/" target="_blank">AutoFixture</a>, 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:</p><br /><p><em>- Creating an anonymous string</em></p> <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"> <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"> <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;">var anonymousText = fixture.CreateAnonymous&lt;<span style="color: rgb(0, 0, 255);">string</span>&gt;();</pre><br /><!--CRLF--></div></div><p>Result:</p>- anonymousText: aa48c714-6c6a-4ac4-9c27-3658c9e78d5f<br /><br /><br /><p><em>- Creating an anonymous object</em><br /></p> <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"><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"><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;"><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> Person<br /></pre><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;">{</pre> <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;"> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">string</span> Name { get; set; }</pre> <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;"> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">int</span> Age { get; set; }</pre> <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;">}</pre><br /><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;">..</pre><br /><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;">var personWithAnonymousData = <span style="color: rgb(0, 0, 255);">new</span> Fixture().CreateAnonymous&lt;Person&gt;();</pre><br /><!--CRLF--></div></div>Result:<p>- Name: Nameb7c2a9fc-a5b0-4836-83d9-be1b057e0ff1</p><p>- Age: 1</p><br /><br /><p>Take a look a the AutoFixture <a href="http://autofixture.codeplex.com/wikipage?title=CheatSheet&amp;referringTitle=Home" target="_blank">cheat sheat</a> for a number of good examples. There’s many things you can do to customize the behavior and output.</p><p><br /></p><p>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. </p><br /><br /><br /><h3>Extending AutoFixture with automatic collections generation support</h3><p>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.<br /></p><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"><br /><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"><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;"><span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> Person</pre> <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;">{</pre> <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;"> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">string</span> Name { get; set; }</pre> <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;"> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">int</span> Age { get; set; }</pre> <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;"> <span style="color: rgb(0, 0, 255);">public</span> List&lt;<span style="color: rgb(0, 0, 255);">string</span>&gt; PhoneNumbers { get; set; }</pre> <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;">}</pre><br /><!--CRLF--></div></div><p><br /></p><p>AutoFixture have functionality to handle this. If you run the line below first..</p> <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"><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"><br /><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;">fixture.Register(() =&gt; fixture.CreateMany&lt;<span style="color: rgb(0, 0, 255);">string</span>&gt;().ToList());</pre><br /><!--CRLF--></div></div><p>..then the output of PhoneNumbers will be something similar to: </p><p>[0]: 635bc212-8d16-4029-8423-1f45016fe020</p><p>[1]: fcbed54b-94f6-4eea-b773-e7ec5e75b6dd</p><p>[2]: 814c120a-7e9c-487a-b99e-9e23d9d511b0</p><br /><br /><p>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&lt;string&gt;, I would be forced to define it since it causes a runtime exception of: </p><blockquote><p>“AutoFixture was unable to create an instance from System.Collections.Generic.IList`1[System.String], most likely because it has no public constructor.”</p><p><br /></p></blockquote><p>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. </p><br /><br /><p>First how to use it (Only the second line is new):</p><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"><br /><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"><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;">var fixture = <span style="color: rgb(0, 0, 255);">new</span> Fixture();</pre> <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;">fixture.Customizations.Add(<span style="color: rgb(0, 0, 255);">new</span> CollectionsGenerator(fixture));</pre> <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;">var personWithAnonymousData = fixture.CreateAnonymous&lt;Person&gt;();</pre><br /><!--CRLF--></div></div><p>The new CollectionsGenerator:</p><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"><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"><br /><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;"><span style="color: rgb(96, 96, 96);" id="lnum1"> 1:</span> <span style="color: rgb(0, 128, 0);">/// &lt;summary&gt;</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum2"> 2:</span> <span style="color: rgb(0, 128, 0);">/// Support for handling automatic generation of anonymous data for collections</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum3"> 3:</span> <span style="color: rgb(0, 128, 0);">/// &lt;/summary&gt;</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum4"> 4:</span> <span style="color: rgb(0, 0, 255);">internal</span> <span style="color: rgb(0, 0, 255);">class</span> CollectionsGenerator : ISpecimenBuilder</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum5"> 5:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum6"> 6:</span> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">readonly</span> Fixture _parentFixture;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum7"> 7:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum8"> 8:</span> <span style="color: rgb(0, 128, 0);">/// &lt;param name="parentFixture"&gt;Requires parentFixture to ensure existing options are used.&lt;/param&gt;</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum9"> 9:</span> <span style="color: rgb(0, 0, 255);">public</span> CollectionsGenerator(Fixture parentFixture)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum10"> 10:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum11"> 11:</span> _parentFixture = parentFixture;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum12"> 12:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum13"> 13:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum14"> 14:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">object</span> Create(<span style="color: rgb(0, 0, 255);">object</span> request, ISpecimenContext context)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum15"> 15:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum16"> 16:</span> <span style="color: rgb(0, 0, 255);">if</span> (!ReflectionHelper.IsGenericDotNetCollectionOrInterface(request))</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum17"> 17:</span> <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">new</span> NoSpecimen(request);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum18"> 18:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum19"> 19:</span> Type collectionType;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum20"> 20:</span> <span style="color: rgb(0, 0, 255);">if</span> (ReflectionHelper.ObjectIsADotNetCollectionInterface(request))</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum21"> 21:</span> collectionType = ReflectionHelper.GetConcreteCollectionTypeToMatchInterface(request);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum22"> 22:</span> <span style="color: rgb(0, 0, 255);">else</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum23"> 23:</span> collectionType = ReflectionHelper.GetUnderlyingSystemType(request);</pre><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;"><span style="color: rgb(96, 96, 96);" id="lnum24"> 24:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum25"> 25:</span> var returnCollection = (IList)Activator.CreateInstance(collectionType);<span style="color: rgb(96, 96, 96);" id="lnum26"><br />26:</span> <span style="color: rgb(96, 96, 96);" id="lnum27"><br />27:</span> AddAnonymousValuesToCollection(returnCollection, _parentFixture);<span style="color: rgb(96, 96, 96);" id="lnum28"><br />28:</span> <span style="color: rgb(96, 96, 96);" id="lnum29"><br />29:</span> <span style="color: rgb(0, 0, 255);">return</span> returnCollection;<span style="color: rgb(96, 96, 96);" id="lnum30"><br />30:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum31"> 31:</span> <span style="color: rgb(96, 96, 96);" id="lnum32"><br />32:</span> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">void</span> AddAnonymousValuesToCollection(IList collection, Fixture parentFixture)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum33"> 33:</span> {<span style="color: rgb(96, 96, 96);" id="lnum34"><br />34:</span> Type genericType = collection.GetType().GetGenericArguments()[0];</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum35"> 35:</span> var createAnonymousMethod = <span style="color: rgb(0, 0, 255);">typeof</span>(SpecimenFactory).GetMethod(<span style="color: rgb(0, 96, 128);">"CreateAnonymous"</span>, <span style="color: rgb(0, 0, 255);">new</span> Type[] { <span style="color: rgb(0, 0, 255);">typeof</span>(ISpecimenBuilderComposer) }).MakeGenericMethod(<span style="color: rgb(0, 0, 255);">new</span>[] { genericType });</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum36"> 36:</span> <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">int</span> i = 0; i &lt; parentFixture.RepeatCount; i++)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum37"> 37:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum38"> 38:</span> collection.Add(createAnonymousMethod.Invoke(<span style="color: rgb(0, 0, 255);">null</span>, <span style="color: rgb(0, 0, 255);">new</span> ISpecimenBuilderComposer[] { parentFixture }));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum39"> 39:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum40"> 40:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum41"> 41:</span> }</pre><!--CRLF--></div><br /></div><br />And an accompanying ReflectionHelper:<br /><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"><br /><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"><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;"><span style="color: rgb(96, 96, 96);" id="lnum1"> 1:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">class</span> ReflectionHelper</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum2"> 2:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum3"> 3:</span> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">const</span> <span style="color: rgb(0, 0, 255);">string</span> UnderlyingSystemTypeString = <span style="color: rgb(0, 96, 128);">"UnderlyingSystemType"</span>;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum4"> 4:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum5"> 5:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> CanRetrieveUnderlyingSystemTypeFromObject(<span style="color: rgb(0, 0, 255);">object</span> input)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum6"> 6:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum7"> 7:</span> <span style="color: rgb(0, 0, 255);">return</span> (input != <span style="color: rgb(0, 0, 255);">null</span>)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum8"> 8:</span> &amp;&amp; (input.GetType().GetProperty(UnderlyingSystemTypeString) != <span style="color: rgb(0, 0, 255);">null</span>)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum9"> 9:</span> &amp;&amp; (input.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(input, <span style="color: rgb(0, 0, 255);">null</span>) != <span style="color: rgb(0, 0, 255);">null</span>);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum10"> 10:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum11"> 11:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum12"> 12:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> InputIsAssignableFrom(<span style="color: rgb(0, 0, 255);">object</span> request, Type ofType)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum13"> 13:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum14"> 14:</span> <span style="color: rgb(0, 0, 255);">return</span> (request != <span style="color: rgb(0, 0, 255);">null</span>)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum15"> 15:</span> &amp;&amp; (request.GetType().GetProperty(UnderlyingSystemTypeString) != <span style="color: rgb(0, 0, 255);">null</span>)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum16"> 16:</span> &amp;&amp; (request.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(request, <span style="color: rgb(0, 0, 255);">null</span>) != <span style="color: rgb(0, 0, 255);">null</span>)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum17"> 17:</span> &amp;&amp; (ofType.IsAssignableFrom((Type)request.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(request, <span style="color: rgb(0, 0, 255);">null</span>)));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum18"> 18:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum19"> 19:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum20"> 20:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> Type GetUnderlyingSystemType(<span style="color: rgb(0, 0, 255);">object</span> input)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum21"> 21:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum22"> 22:</span> <span style="color: rgb(0, 0, 255);">return</span> (Type)input.GetType().GetProperty(UnderlyingSystemTypeString).GetValue(input, <span style="color: rgb(0, 0, 255);">null</span>);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum23"> 23:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum24"> 24:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum25"> 25:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> ObjectHasGenericTypeSpecified(<span style="color: rgb(0, 0, 255);">object</span> input)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum26"> 26:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum27"> 27:</span> <span style="color: rgb(0, 0, 255);">return</span> GetUnderlyingSystemType(input).IsGenericType &amp;&amp; GetUnderlyingSystemType(input).GetGenericArguments().Length &gt; 0;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum28"> 28:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum29"> 29:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum30"> 30:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> IsGenericDotNetCollectionOrInterface(<span style="color: rgb(0, 0, 255);">object</span> request)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum31"> 31:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum32"> 32:</span> <span style="color: rgb(0, 0, 255);">if</span> (!CanRetrieveUnderlyingSystemTypeFromObject(request))</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum33"> 33:</span> <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">false</span>;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum34"> 34:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum35"> 35:</span> <span style="color: rgb(0, 0, 255);">return</span> (ObjectIsADotNetCollection(request) || ObjectIsADotNetCollectionInterface(request)) </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum36"> 36:</span> &amp;&amp; (ObjectHasGenericTypeSpecified(request));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum37"> 37:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum38"> 38:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum39"> 39:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> ObjectIsADotNetCollection(<span style="color: rgb(0, 0, 255);">object</span> request)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum40"> 40:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum41"> 41:</span> <span style="color: rgb(0, 0, 255);">return</span> InputIsAssignableFrom(request, <span style="color: rgb(0, 0, 255);">typeof</span>(IList));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum42"> 42:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum43"> 43:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum44"> 44:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">bool</span> ObjectIsADotNetCollectionInterface(<span style="color: rgb(0, 0, 255);">object</span> request)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum45"> 45:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum46"> 46:</span> var objectTypeName = GetUnderlyingSystemType(request).ToString();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum47"> 47:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum48"> 48:</span> var dotNetCollectionTypes = <span style="color: rgb(0, 0, 255);">new</span> List&lt;<span style="color: rgb(0, 0, 255);">string</span>&gt; <span style="color: rgb(0, 128, 0);">//.NET Collections</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum49"> 49:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum50"> 50:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.IList"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum51"> 51:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.IEnumerable"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum52"> 52:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.IEnumerator"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum53"> 53:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.ICollection"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum54"> 54:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.ISet"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum55"> 55:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.IList"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum56"> 56:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.IEnumerable"</span>,</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum57"> 57:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.IEnumerator"</span>,<span style="font-family:Georgia,serif;"></span><span style="color: rgb(96, 96, 96);" id="lnum58"> 58:</span> <span style="color: rgb(0, 96, 128);">"System.Collections.ICollection"</span>, </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum59"> 59:</span> };</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum60"> 60:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum61"> 61:</span> <span style="color: rgb(0, 0, 255);">return</span> dotNetCollectionTypes.Any(objectTypeName.Contains);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum62"> 62:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum63"> 63:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum64"> 64:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> Type GetConcreteListTypeToMatchInterface(<span style="color: rgb(0, 0, 255);">object</span> request)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum65"> 65:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum66"> 66:</span> Type genericType = GetUnderlyingSystemType(request).GetGenericArguments()[0];</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum67"> 67:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum68"> 68:</span> <span style="color: rgb(0, 0, 255);">string</span> genericListTypeName = <span style="color: rgb(0, 96, 128);">"System.Collections.Generic.List`1"</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum69"> 69:</span> + <span style="color: rgb(0, 96, 128);">"[["</span> + genericType.AssemblyQualifiedName + <span style="color: rgb(0, 96, 128);">"]]"</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum70"> 70:</span> + <span style="color: rgb(0, 96, 128);">","</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum71"> 71:</span> + Type.GetType(<span style="color: rgb(0, 96, 128);">"System.Collections.IList"</span>).Assembly.FullName;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum72"> 72:</span> <span style="color: rgb(0, 0, 255);">return</span> Type.GetType(genericListTypeName);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum73"> 73:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum74"> 74:</span> }</pre><!--CRLF--></div><br /></div><p> </p><br /><br />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.<br /><br /><br /><br /><p> </p><p> </p><h3>Adding a sample data generator in Silverlight for Visual Studio/Blend screen previews</h3>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.<br /><br /><br /><p> </p><p>Note that AutoFixture doesn’t support Silverlight just yet, but there is a <a href="http://autofixture.codeplex.com/SourceControl/network" target="_blank">fork</a> 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).<br /></p><p style="text-align: left;"><br /></p><p> </p><p>I wanted a more natural interface for the sample data, so I created a SampleDataGenerator class:</p><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"><br /><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"><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;"><span style="color: rgb(96, 96, 96);" id="lnum1"> 1:</span> <span style="color: rgb(0, 128, 0);">/// &lt;summary&gt;</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum2"> 2:</span> <span style="color: rgb(0, 128, 0);">/// Creates sample data for object or collection of objects recursively</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum3"> 3:</span> <span style="color: rgb(0, 128, 0);">/// &lt;/summary&gt;</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum4"> 4:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> <span style="color: rgb(0, 0, 255);">class</span> SampleDataGenerator</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum5"> 5:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum6"> 6:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> T GenerateObjectWithData&lt;T&gt;()</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum7"> 7:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum8"> 8:</span> <span style="color: rgb(0, 0, 255);">return</span> CreateFixtureWithDefaultSetup&lt;T&gt;().CreateAnonymous&lt;T&gt;();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum9"> 9:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum10"> 10:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum11"> 11:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> T GenerateObjectWithData&lt;T&gt;(<span style="color: rgb(0, 0, 255);">int</span> collectionItemAmount)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum12"> 12:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum13"> 13:</span> var fixture = CreateFixtureWithDefaultSetup&lt;T&gt;();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum14"> 14:</span> fixture.RepeatCount = collectionItemAmount; <span style="color: rgb(0, 128, 0);">//Object count generated per list</span></pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum15"> 15:</span> <span style="color: rgb(0, 0, 255);">return</span> fixture.CreateAnonymous&lt;T&gt;();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum16"> 16:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum17"> 17:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum18"> 18:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> IEnumerable&lt;T&gt; CreateMany&lt;T&gt;()</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum19"> 19:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum20"> 20:</span> <span style="color: rgb(0, 0, 255);">return</span> CreateFixtureWithDefaultSetup&lt;T&gt;().CreateMany&lt;T&gt;();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum21"> 21:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum22"> 22:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> IEnumerable&lt;T&gt; CreateMany&lt;T&gt;(T seed)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum23"> 23:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum24"> 24:</span> <span style="color: rgb(0, 0, 255);">return</span> CreateFixtureWithDefaultSetup&lt;T&gt;().CreateMany(seed);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum25"> 25:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum26"> 26:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum27"> 27:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> IEnumerable&lt;T&gt; CreateMany&lt;T&gt;(<span style="color: rgb(0, 0, 255);">int</span> count)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum28"> 28:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum29"> 29:</span> <span style="color: rgb(0, 0, 255);">return</span> CreateFixtureWithDefaultSetup&lt;T&gt;().CreateMany&lt;T&gt;(count);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum30"> 30:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum31"> 31:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum32"> 32:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">static</span> IEnumerable&lt;T&gt; CreateMany&lt;T&gt;(T seed, <span style="color: rgb(0, 0, 255);">int</span> count)</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum33"> 33:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum34"> 34:</span> <span style="color: rgb(0, 0, 255);">return</span> CreateFixtureWithDefaultSetup&lt;T&gt;().CreateMany&lt;T&gt;(seed, count);</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum35"> 35:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum36"> 36:</span> </pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum37"> 37:</span> <span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">static</span> Fixture CreateFixtureWithDefaultSetup&lt;T&gt;()</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum38"> 38:</span> {</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum39"> 39:</span> var fixture = <span style="color: rgb(0, 0, 255);">new</span> Fixture();</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum40"> 40:</span> fixture.Customizations.Add(<span style="color: rgb(0, 0, 255);">new</span> StringGenerator(() =&gt; <span style="color: rgb(0, 96, 128);">""</span>));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum41"> 41:</span> fixture.Customizations.Add(<span style="color: rgb(0, 0, 255);">new</span> CollectionsGenerator(fixture));</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum42"> 42:</span> <span style="color: rgb(0, 0, 255);">return</span> fixture;</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum43"> 43:</span> }</pre> <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;"><span style="color: rgb(96, 96, 96);" id="lnum44"> 44:</span> }</pre><!--CRLF--></div></div><p> </p><p> </p><p>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.<br /></p><p><br /></p><p> </p><p> </p><p>You can then use it in a sample object that inherits the ViewModel:</p><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"><br /><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"> <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;"><span style="color: rgb(96, 96, 96);" id="lnum1"> 1:</span> <span style="color: rgb(0, 0, 255);">public</span> <span style="color: rgb(0, 0, 255);">class</span> EditPersonSampleData : EditPersonViewModel<span style="color: rgb(96, 96, 96);" id="lnum2"><br />2:</span> {<span style="color: rgb(96, 96, 96);" id="lnum3"><br />3:</span> <span style="color: rgb(0, 0, 255);">public</span> EditPersonSampleData()<span style="color: rgb(96, 96, 96);" id="lnum4"><br />4:</span> {<span style="color: rgb(96, 96, 96);" id="lnum5"><br />5:</span> Person = SampleDataGenerator.GenerateObjectWithData&lt;Person&gt;();<span style="color: rgb(96, 96, 96);" id="lnum6"><br />6:</span> }<span style="color: rgb(96, 96, 96);" id="lnum7"><br />7:</span> }</pre><br /><!--CRLF--></div></div><p> </p><br />And then in the EditPersonView.xaml, include:<br /><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"><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"><br /> <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;"><span style="color: rgb(96, 96, 96);" id="lnum1"> 1:</span> xmlns:vm=<span style="color: rgb(0, 96, 128);">"clr-namespace:SomeNamespace.EditPerson"</span> <span style="color: rgb(96, 96, 96);" id="lnum2"><br />2:</span> <span style="color: rgb(96, 96, 96);" id="lnum3"><br />3:</span> ...<span style="color: rgb(96, 96, 96);" id="lnum4"><br />4:</span> <span style="color: rgb(96, 96, 96);" id="lnum5"><br />5:</span> &lt;Grid x:Name=<span style="color: rgb(0, 96, 128);">"LayoutRoot"</span> Background=<span style="color: rgb(0, 96, 128);">"White"</span> d:DataContext=<span style="color: rgb(0, 96, 128);">"{d:DesignInstance Type=vm:EditPersonSampleData, IsDesignTimeCreatable=True}"</span>&gt;<span style="color: rgb(96, 96, 96);" id="lnum6"><br />6:</span> </pre><!--CRLF--></div><br /></div><p> </p><p> </p><p> </p><p> </p><p><br /></p><p>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.<br /></p><p><br /></p><p> </p><p>Vote <a href="http://autofixture.codeplex.com/workitem/4199" target="_blank">here</a> to get similar support in the actual AutoFixture product. </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com2tag:blogger.com,1999:blog-4900151497087138627.post-89408604713684494072010-01-23T18:32:00.001+01:002010-01-23T18:32:19.811+01:00Changes in software – Different developers over time for a long-running project<p>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? </p> <p> <br />Once you have a &quot;long-running project&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. </p> <p> <br />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). </p> <p> <br />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 &quot;me versus they&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.</p> <p> <br />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? </p> <p> <br />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.</p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-12990691484775133482010-01-17T21:05:00.017+01:002010-01-17T21:24:01.965+01:00Changes in software - One of the biggest challenges of software development<p>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. </p><img src='http://img11.imageshack.us/img11/6510/changemanagement1.jpg' border='0' width='512' height='384'/> <p> <br />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.</p> <p> <br />Here's a number of things that affects and complicates changes in software: <br /><br /></p> <p>Project </p> <ul><li>Many different developers over time</li><li>Legacy codebase</li><li>External system dependencies</li></ul> <p>Person</p> <ul> <li>Developer with limited understanding of code in general</li> <li>Developer with limited understanding of the projects code and architecture</li> <li>Unmotivated developer</li> <li>Changes done just before end of day/end of week/end of year</li> <li>Different quality of developers</li> <li>Misunderstanding the time it takes to write quality code</li> <li>Not thoroughly understanding a problem</li> </ul> <p>Code</p> <ul> <li>The danger of quick fixes/hacks </li> <li>Lack of understanding of how software rot </li> <li>Unreadable code. </li> <li>High coupling in the system. Making a change in code that is used many places has a higher risk. </li> <li>Complex architecture (Hard to understand or wrong for the problem at hand)</li> <li>Duplicate code</li> </ul> <p>Business</p> <ul> <li>Illogical business logic </li> <li>Unavailable business people <br /></li> </ul> <p>Process</p> <ul> <li> Time (Quality - if time permits)</li> <li>Bug acceptance</li> <li>Developer not feeling the pain of fixing production bugs</li> <li>Task-switching developer</li> <li>Picking up problems caused by changes</li> <li>Lack of testing</li> <li>Big bang releases / seldom releases</li> <li>Individual code ownership</li> <li>Refactoring / Not refactoring <br /></li><li>Adding additional features at end of test/iteration/project</li> </ul> <br/><p>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.</p> <p>&#160;</p> <p>Did you miss something on the list? </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-88304536230883178282010-01-14T23:06:00.001+01:002010-01-14T23:06:33.380+01:00Real programmers don't comment their code. If it was hard to write, it should be hard to understand<p>Now that's just a plain lie. Real programmers do comment their code - though only certain parts of it. <br /></p> <p>First of all, an important rule: Your code should be so readable that you don't need comments to understand what it does. <br /></p> <p>Comments are a problem because they <br />- might not get get updated when the code changes. <br />- become an excuse to write unreadable code. <br /></p> <p>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. <br /></p> <p>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 <a href="http://www.industriallogic.com/xp/refactoring/" target="_blank">Refactoring to Patterns</a>: <br /></p> <blockquote> <p>&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.&quot; </p> </blockquote> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p>When are comments appropriate? <br />- At major boundaries, for instance with libraries or at service contracts, giving context or similar. <br />- Clarification or expressing intent, if you fail to do it in code <br />- Warnings or particular notifications <br />- Regular expressions, if you have to use them <br />- TODO's, sparingly. <br />- When you have no other options. <br /></p> <p>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. <br /></p> <p>I think Uncle Bob says it well in <a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882" target="_blank">Clean Code</a>: <br /></p> <blockquote> <p>&quot;The proper use of comments is to compensate for our failure to express ourself in code. Note that I used the word <i>failure</i>. 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.&quot;</p></blockquote> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-5700637877590336992010-01-10T23:38:00.008+01:002010-01-11T12:58:59.962+01:00Object Orientation revisited – Business layer patterns<p>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? </p> <p> <br />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. </p> <p> <br />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. </p> <p> <br />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: </p> <ul> <li>Create an architecture that meets all technical and operational demands </li> <li>AND that solves all quality attributes like performance, security and maintainability well </li> </ul> <p> <br />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.</p> <p>&#160;</p> <h3>Introducing OO</h3> <p>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 <br /></p> <blockquote> <p>”<b>Division of responsibilities </b>for an application or system into individual reusable and self-sufficient objects, each containing the <b>data and the behavior </b>relevant to the object.”</p> <p> <br />”An objectoriented design views a system as a series of <b>cooperating objects</b>, instead of a set of routines or procedural instructions.”</p> </blockquote> <p> <br />In general it can be said that Object Orientation should be considered when:</p> <blockquote> <p> <br />”You want to model your application based on <b>real world objects and actions</b>, 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 <b>encapsulate logic and data together</b> in reusable components or you have <b>complex business logic</b> that requires abstraction and dynamic behavior.”</p> </blockquote> <p> <br />(All quotes from <a href="http://msdn.microsoft.com/en-us/library/dd673617.aspx" target="_blank">Microsoft Application Architecture Guide, 2nd Edition</a>)</p> <p> <br />And you continuously work to </p> <ul> <li>find the right abstraction of the real world for your problem </li> <li>find fitting objects </li> <li>find the right place to put code </li> <li>rework the code at all times to make sure it is correct based on your current understanding </li> <li>favor low coupling </li> <li>limit duplication </li> <li>make each object work on one thing only - ensuring high cohesion </li> <li>work to have a test friendly design&#160; </li> <li>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 :) ) </li> <li>and certainly much more than this.. </li> </ul> <p> <br />How you structure your business layer certainly has a say in how well and how easily you can achieve these things. <br />You traditionally have four main ways of structuring this logic: </p> <p> <br />Procedurally oriented with <b>Transaction script</b> or <b>Table module</b>. <br />or <br />Object oriented with <b>Active record</b> or <b>Domain model</b>. <br /></p> <p>Let's take a closer look at each.. </p> <p>&#160;</p> <p>&#160;</p><br/> <h3>Transaction script </h3> <p>&#160;</p> <blockquote> <p>”Organizes business logic by procedures where each procedure handles a single request from the presentation.” </p> <p>Martin Fowler, <a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank">Patterns of Enterprise Application Architecture</a></p> </blockquote> <p> <br /> <br />Transaction script follows the current structure: </p> <p> <br /> <a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img3.imageshack.us/i/transactionscript.png/'><img src='http://img3.imageshack.us/img3/7636/transactionscript.png' border='0' width='324' height='187' /></a></p> <p> <br />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. </p> <p> <br />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. </p> <p> <br />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. <br />Being popular in general, it the .NET world it was quickly replaced in popularity by....</p> <h5>&#160;</h5><br/> <h3>Table module</h3> <p>&#160;</p> <blockquote> <p>”A single instance that handles the business logic for all rows in a database table or view.”</p> <p>Martin Fowler, <a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank">Patterns of Enterprise Application Architecture</a></p> </blockquote> <p> <br /> <a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/tablemodule.png/'><img src='http://img36.imageshack.us/img36/1720/tablemodule.png' border='0' width='338' height='430'/></a></p> <p> <br />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. <br />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. </p> <p> <br />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. </p> <p> <br /><b></b></p> <h4>A history lesson</h4> <p>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. </p> <p> <br />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; 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. </p> <p> <br />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). </p> <p> <br />So the tide has to some extent turned in the Microsoft community, certainly the support for the two remaining patterns are continuously improving. </p> <p> <br />But less take a closer look at the object oriented patterns: </p> <p>&#160;</p><br/> <h3>Active Record</h3> <p>&#160;</p> <blockquote> <p>”An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.”</p> <p>Martin Fowler, <a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank">Patterns of Enterprise Application Architecture</a></p> </blockquote> <p>&#160;</p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/activerecord1.png/'><img src='http://img36.imageshack.us/img36/462/activerecord1.png' border='0' width=’300’ height=’184’ /></a> &#160;&#160; <br /><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img13.imageshack.us/i/activerecord2.png/'><img src='http://img13.imageshack.us/img13/5911/activerecord2.png' border='0' width='324' height='507' /></a> </p> <p> <br />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. </p> <p> <br />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. </p> <p> <br />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. </p> <p> <br />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 <a href="http://stackoverflow.com/questions/1974735/what-exactly-is-persistence-ignorance" target="_blank">Persistence Ignorant (PI)</a>. </p> <p> <br />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. <br />If&#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: </p> <p>&#160;</p><br/> <h3>Domain Model</h3> <p>&#160;</p> <blockquote> <p>”An object model of the domain that incorporates both behavior and data”</p> <p>Martin Fowler, <a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420" target="_blank">Patterns of Enterprise Application Architecture</a></p> </blockquote> <p> <br /> <a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img36.imageshack.us/i/domainmodeltop.png/'><img src='http://img36.imageshack.us/img36/2196/domainmodeltop.png' border='0' width='341' height='177' /></a></p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img689.imageshack.us/i/domainmodelbottomleft.png/'><img src='http://img689.imageshack.us/img689/2090/domainmodelbottomleft.png' border='0' width='380' height='319' /></a></p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img94.imageshack.us/i/domainmodelbottomright.png/'><img src='http://img94.imageshack.us/img94/5420/domainmodelbottomright.png' border='0' width='346' height='189' /></a></p> <p> <br />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. </p> <p> <br />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. <br /></p> <p>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. </p> <p> <br />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. </p> <p> <br />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. </p> <p>&#160;</p><br/> <h3>Centralized or delegated control</h3> <p>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. </p> <p> <br />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. </p> <p> <br />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.</p> <p> <br />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 <a href="http://portal.acm.org/citation.cfm?id=1018384" target="_blank">research paper</a> was published in IEEE Transactions on Software Engineering, called &quot;Evaluating the Effect of a Delegated versus Centralized Control Style on the Maintainability of Object-Oriented Software&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:</p> <blockquote> <p> <br />&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&quot;.</p> </blockquote> <p> <br />And then concluding:</p> <blockquote> <p> <br />&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.&quot;</p> </blockquote> <p> <br />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. </p> <p>&#160;</p> <br/><h3>Have I covered everything then? </h3> <p>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. </p> <p> <br />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.</p> <p>&#160;</p><br/> <h3>Anemic Domain Model</h3> <p>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. </p> <p> <br /> <a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img193.imageshack.us/i/anemictopleft.png/'><img src='http://img193.imageshack.us/img193/6594/anemictopleft.png' border='0' width='342' height='179' /></a></p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img199.imageshack.us/i/anemictopright.png/'><img src='http://img199.imageshack.us/img199/3745/anemictopright.png' border='0'/ width='393' height='215' ></a></p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img19.imageshack.us/i/anemicbottomleft.png/'><img src='http://img19.imageshack.us/img19/3664/anemicbottomleft.png' border='0' width='410' height='233' /></a></p> <p><a target='_blank' title='ImageShack - Image And Video Hosting' href='http://img193.imageshack.us/i/anemicbottomright.png/'><img src='http://img193.imageshack.us/img193/9020/anemicbottomright.png' border='0' width='275' height='88' /></a></p> <p>&#160;</p> <p> <br />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. </p> <p> <br />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. </p> <p>&#160;</p><br/> <h3>Conclusion</h3> <p>None of these patterns is never right. That's part of the <em>fun</em> 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. </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com2tag:blogger.com,1999:blog-4900151497087138627.post-38540068808847496412010-01-06T10:06:00.000+01:002010-01-06T10:06:00.603+01:00The technical laws of December<p>Throughout December I had the pleasure of collecting more or less clever statements about computers and software development in general. My <a href="http://bit.ly/90E8Wx" target="_blank">twitter account</a>&#160; had a steady flow of these up until Christmas. </p> <p>&#160;</p> <p>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. </p> <p>&#160;</p> <p>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.</p> <p>&#160;</p> <p>Dec1 tech law: Walking on water and developing software to specification are easy as long as both are frozen </p> <p>Dec2 tech law: In theory, there is no difference between theory and practice, but in practice there is </p> <p>Dec3 tech law: Real programmers don't comment their code. If it was hard to write, it should be hard to understand </p> <p>Dec4 tech law: Computers are unreliable, but humans are even more unreliable. Any system which depends on human reliability is unreliable. </p> <p>Dec5 tech law: There is never time to do it right, but always time to do it over </p> <p>Dec6 tech law: Adding manpower to a late software project makes it later </p> <p>Dec7 tech law: The degree of technical competence is inversely proportional to the level of management. </p> <p>Dec8 tech law: The probability of bugs appearing is directly proportional to the number and importance of people watching </p> <p>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. </p> <p>Dec10 tech law: Good enough isn't good enough, unless there is a deadline </p> <p>Dec11 tech law: An expert is someone brought in at the last minute to share the blame </p> <p>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 </p> <p>Dec13 tech law: profanity is the one language all computer users know </p> <p>Dec14 tech law: All's well that ends. </p> <p>Dec15 tech law: No matter how hard you work, the boss will only appear when you access the Internet. </p> <p>Dec16 tech law: A meeting is an event at which the minutes are kept and the hours are lost. </p> <p>Dec17 tech law: An expert is one who knows more and more about less and less until he knows absolutely everything about nothing. </p> <p>Dec 18 tech law: it's not a bug, it's an undocumented feature </p> <p>Dec19 tech law: A complex system that works is invariably found to have evolved from a simple system that works </p> <p>Dec20 tech law: The documented interfaces between standard software modules will have undocumented quirks </p> <p>Dec21 tech law: Bugs will appear in one part of a working program when another 'unrelated' part is modified </p> <p>Dec22 tech law: When designing a program to handle all possible dumb errors, nature creates a dumber user </p> <p>Dec23 tech law: Build a system that even a fool can use and only a fool will want to use it </p> <p>Dec24 tech law: The cleverness of&#160; technical laws is inversely proportional to the number of laws</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-27897464298550368462010-01-03T19:11:00.001+01:002010-01-03T23:13:05.575+01:00Walking on water and developing software to specification are easy as long as both are frozen<p>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? </p> <p> <br />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!</p> <p> <br />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 <br /></p> <ul> <li>You've got one shot at coming up with the features for the system. Now guess what happens -&gt; You will try to come up with as much as humanly possible, important or not </li> <li>You have little idea how the system is actually going to look or feel or just how it can be used -&gt; You will try to make the requirements cover everything. This isn't really a bad thing, but can be quite a complex process. </li> <li>Price the project beforehand, to move the risk of development to a software company -&gt; Do you think those requirements change sessions will be fun? </li> <li>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 -&gt; Will change! </li> </ul> <p> <br />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 &quot;<a href="http://agilemanifesto.org/">Manifesto for Agile Software Development</a>&quot;, and a number of <a href="http://agilemanifesto.org/principles.html">principles</a> behind it. </p> <p> <br />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 <a href="http://bit.ly/4X7LlY">original paper</a> 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&#160; in software besides working software. </p> <p> <br />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.</p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-74958128711075877492009-02-10T23:00:00.001+01:002009-02-10T23:00:42.241+01:00#GEEKBEER starting this Thursday (in Oslo)<p><a href="http://tore.vestues.no/" target="_blank">Tore Vestues</a>, <a href="http://twitter.com/sverrehundeide" target="_blank">Sverre Hundeide</a>, 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.&#160; No free beer, no surprises, just fellow developers/IT people. </p> <p>&#160;</p> <p>We'll start up this Thursday (the 12) , 7pm, at Asylet (Gr&#248;nland). Come along! </p> <p>&#160;</p> <p>We hope to make it into a monthly thing, so don't despair if you can't make it this time. </p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-82702087558144825102009-01-21T23:59:00.001+01:002009-01-22T00:07:18.052+01:00Essential Project Practices: Communication and close customer collaboration<p>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 &quot;make or break&quot; characteristics of a project. </p> <p> <br />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.</p> <p> <br />Working on communication at all times is important. The various roles in a project or organization has different responsibilities here. </p> <p>&#160;</p> <p><img src="http://www.processdevelopers.com/images/PM_Build_Swing.gif" /> </p> <p> <br /><b>Upper management and project champion</b> <br />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.&#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. </p> <p> <br />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. </p> <p> <br /><b>Project manager -&gt; developers</b> <br />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. </p> <p>&#160;</p> <p>Organizational requirements and processes is the primary one, but trust has no less importance. <br />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. </p> <p>&#160;</p> <p>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 <a href="http://www.manager-tools.com/2008/08/rolling-out-the-manager-tools-trinity-part-1" target="_blank">here</a>. </p> <p>&#160;</p> <p><b>Project -&gt; Business expert and users</b> <br />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? </p> <p>&#160;</p> <p><b>Developer -&gt; Developer</b> <br />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 <a href="http://en.wikipedia.org/wiki/Groupthink" target="_blank">groupthink</a>, that is certainly not good to have to much of. </p> <p>&#160;</p> <p><b>In conclusion</b> <br />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.</p> <p>&#160;</p> <p>If you find the topic interesting it's not hard to find sources talking about it. It is slightly harder to find interesting sources. <br />The podcast mentioned above has interesting topics, but it is mostly related to managerial behaviours. You can access it <a href="http://www.manager-tools.com/podcasts/manager-tools" target="_blank">here</a> <br />If teams and communication is interesting, you'll find Peopleware's <a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-Second/dp/0932633439 " target="_blank">Productive Projects and Teams</a> great. <br />If other aspects of communication seems interesting, I'll be happy to recommend books on the subject. </p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com1tag:blogger.com,1999:blog-4900151497087138627.post-86578929833410371312009-01-20T23:29:00.004+01:002009-01-20T23:31:54.650+01:00NNUG: Tonight's meeting<p>Jimmy Nilsson and Tore Vestues was the speakers on todays <a href="http://nnug.no/Avdelinger/Oslo/Moter/Brukergruppemote-januar-2009/" target="_blank">NNUG-meeting</a>. </p> <p> <br /><a href="http://jimmynilsson.com/blog/" target="_blank">Jimmy Nilsson</a> is most known for having written <a href="http://www.amazon.com/exec/obidos/ASIN/0321268202" target="_blank">&quot;Applying Domain Driven Design and Patterns&quot;</a>, 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 &quot;En ny era f&#246;r data&#229;tkomst?&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. </p> <p> <br /><a href="http://tore.vestues.no/" target="_blank">Tore Vestues</a> 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. </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-83582392533571703862009-01-19T23:04:00.004+01:002009-01-19T23:09:03.858+01:00Interesting Old Stuff: Management tutorial<p>I&#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.&#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 :)</p> <p>&#160;</p> <p>An interesting read out of a sort of sentimental fashion for me. I'll post it here just for fun</p> <p>&#160;</p> <p><em>You are the IT project manager of an organisation developing innovative &#8216;leading-edge&#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&#8217;s threat to withhold staged payments that are required to be made as part of the contract terms.</em></p> <p>&#160;</p> <p><b>How might this type of client behaviour affect the type of development methodology you employ?</b> </p> <p>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. </p> <p>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. </p> <p>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. </p> <p>&#160;</p> <p><b>Why do you believe the client might be so insistent on receiving regular &#8216;proof of progress&#8217; updates?</b> </p> <p>There are many possible reasons for why a client would insist on receiving regular &#8220;proof of progress&#8221; updates. We believe that such an insistent client&#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&#8217;t used as planned in the organisation. </p> <p>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. </p> <p>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.<br /></p> <p><br /><b></b></p> <p><b>You discuss the issue with your own executive management and they make a suggestion that you merely &#8216;fake&#8217; the demonstrations without making any genuine attempt to provide a genuine product. What are some of the implications here?</b> </p> <p>If you were to &#8220;fake&#8221; the demonstration of a product we believe that there can be both positive and negative implications to this.</p> <p>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.</p> <p>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.</p> <p>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. </p> <p>All of these negative implications are risks that can lead to economical consequences. Therefore it&#8217;s important that you consider the implications thoroughly before making a decision to fake such a presentation.</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-62443918098182603672009-01-19T20:20:00.001+01:002009-01-19T20:29:47.073+01:00Interesting Blog Posts: NHibernate and Entity Framework Battle it Out in the Real World<p>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.</p> <p>&#160;</p> <p>Note: Look, I am saying OR-mapper here, so don't get me started with the &quot;they are impossible to compare since EF is supposed to be a persistence-, object-, view-, query-, dataservices&quot;-discussion. That is so 2008. </p> <p>&#160;</p> <p><img src="http://img527.imageshack.us/img527/3153/dilbertmauvech9.jpg" /></p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-90917666163098782932009-01-18T23:59:00.003+01:002009-01-19T08:30:49.222+01:00Interesting Software Thoughts: 8 Things We Hate About IT<p>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.</p> <p> <br />A <a href="http://discussionleader.hbsp.com/cramm/" target="_blank">management guru</a>&#160; has a <a href="http://discussionleader.hbsp.com/cramm/2008/06/8-things-we-hate-about-it.html" target="_blank">blog post</a>&#160; titled the same as the header. </p> <p> <br />The points listed are the following, as well as a few thoughts I formed while reading them: </p> <p><strong>1. IT Limits Managers' Authority.</strong> <br /><strong>2. They're Missing Adult Supervision: </strong>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. <br /><strong>3. They're Financial Extortionists:</strong> 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. <br /><strong>4. Their Projects Never End:</strong> Setting deadlines, having milestones and defining Done is essential in any task. <br /><strong>5. The Help Desk is Helpless:</strong> Software has bugs. Especially since it is often a conscious decision to release something when it's &quot;good enough&quot;. I don't envy the help desk personnel in IT in general. <br /><strong>6. They Let Outsourcers Run Amok:</strong> I strongly doubt IT is the main driver in outsourcing! <br /><strong>7. IT is Stocked with Out-of-Date Geeks:</strong> 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. <br /><strong>8. IT Never Has Good News:</strong> Too seldom, that's for sure! <br /></p> <p><br />So what do we need to succeed with IT projects? </p> <ul> <li>We need close customer collaboration. </li> <li>We need projects with short feedback loops. </li> <li>We need sane requirements engineering. </li> <li>We need to know what Done means. </li> <li>We need the business side to be active in the entire process to deliver what they need. </li> <li>We need quality in the development force. Such a simple task :) </li> <li>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. </li> <li>We need to be careful with new technologies. If it's new and you don't run a spike, then shame on you. </li> <li>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. </li> <li>We need to build trust. Now that's a big one! </li> <li>We need a hell of a lot more than I have listed here, but these just came from the top of my mind. <br /></li> </ul> <p>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.</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-58231529617255892582009-01-17T13:50:00.002+01:002009-01-17T13:50:50.325+01:00Interesting .NET Bugs: Object Initializers and using-statements<p>Ayende posted about <a href="http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx" target="_blank">this bug</a>, but it's one hard to spot bug, so I felt it was valid to pass on. </p> <p> <br />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. </p> <p> <br /><img src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Avoidobjectinitializerstheusingstatement_11B04/image_6.png" /> <br /></p> <p><br />However, object initializers are compiled in an unexpected way here: <br /></p> <p><img src="http://ayende.com/Blog/images/ayende_com/Blog/WindowsLiveWriter/Avoidobjectinitializerstheusingstatement_11B04/image_4.png" /> e</p> <p> <br />Beware. </p> <p> <br />(Both images stolen from Ayende. No harm intended.)</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-29489567888399378532009-01-16T23:57:00.001+01:002009-01-16T23:57:58.582+01:00Interesting Software Resources: Domain Driven Design Quickly<p>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. </p> <p>&#160;</p> <p>Order <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" target="_blank">the book</a> now, and read <a href="http://www.infoq.com/minibooks/domain-driven-design-quickly" target="_blank">the resource</a> until you get it. This is ESSENTIAL. </p> <p>&#160;</p> <p>Why it is needed, an except:</p> <blockquote> <p>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. <br /></p> <p>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.</p></blockquote> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-48528814355380318132009-01-15T23:46:00.005+01:002009-01-15T23:49:53.711+01:00Essential Project Practices: Throwing more programmers at a project<p>Fredrick Brooks Jr. made an interesting and in time very well known statement when he coined Brooks's Law in 1975: </p> <blockquote> <p>&quot;adding manpower to a late software project makes it later&quot; <br /></p> </blockquote> <p>He himself said it was an &quot;outrageous oversimplification&quot;, but it is an observation that has had value in all these years. </p> <p> <br />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. <br /></p> <p>The Law is based on a few main points:</p> <ul> <li>New programmers will have to learn about the project. </li> <li>Communication overhead will increase <br /></li> </ul> <br /> <p>So what can you do to avoid fulfilling Brooks's Law? It's not like its gravity we're talking about here. <br />There's many factors involved:</p> <ul> <li>How skilled are the new developers?</li> <li>How well do they know the domain?</li> <li>How many are they?</li> <li>At what time do they come into the project. Early or late?</li> <li>How well do they fit into the culture?</li> <li>Are they team players that can accept the current process, or will they fight it?</li> <li>How well can the work be segregated?</li> <li>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. </li> <li>...</li> </ul><br /><p> Pretty obvious, but I doesn't hurt to have a law for it. </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-11372825864273534152009-01-14T23:41:00.002+01:002009-01-14T23:42:11.960+01:00Essential Software Practices: Favor composition over inheritance<p></p> 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. <p> <br />In OO design you have two common ways of dealing with duplication and reuse: composition and inheritance. </p> <p> <br /><strong>Composition</strong>: Assembling objects. &quot;Has a&quot; relationships. Black box reuse (No internals visible) <br /><strong>Inheritance</strong>: Defined in terms of the parents implementation. &quot;Is a&quot; relationships. (Don't forget Liskov) White-box reuse (Access to parent internals).</p> <p> <br />As stated in the definition above, you use inheritance for &quot;is a&quot; relationships (that are substitutable).&#160; </p> <p> <br />The are several problems with using inheritance for anything else</p> <ul> <li>You're not supposed to use inheritance for code reuse. </li> <li>You can (sort of) break encapsulation since the sub-class is so tightly coupled to the parent's implementation. </li> <li>Inheritance is set in stone at runtime, so no dynamic fun. </li> <li>A subclass can easily make assumptions about the context the method it overrides is called.</li> </ul> <p>&#160;</p> <p>Composition has other strengths than inheritance</p> <ul> <li>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.</li> <li>You can &quot;just plug in behavior&quot; with composition. A small object can help decide how a bigger object works.</li> <li>It is the better approach when you want to reuse functionality.</li> </ul> <p>&#160;</p> <p>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. <br /></p> <p>If you want to have a look at what Grady Booch defines as the &quot;prototypical example of the flexibility of composition over inheritance&quot;, take a look at the strategy pattern. <br /></p> <p>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. </p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-59109335882982086742009-01-13T23:43:00.003+01:002009-01-14T07:49:31.507+01:00Essential Software Concepts: Static methods<p>Static methods<b> </b>is a<b> </b>common functionality in many languages. Whereas instance methods work on instantiated objects, static methods work on types or instantiated objects.</p> <p> <br />The big question is - when is it appropriate to use static methods?&#160; <br /></p> <p>&#160;</p> <p>First the naive positives. These are the positives that often comes up, but which aren't really true. </p> <ul> <li>Makes it more obvious which methods works on internal state. If it doesn't have state, it should be static. </li> <li>Great for Factory Methods (See real negative). <br /></li> </ul> <p>&#160;</p> <p>And then the real pros and cons: </p> <p>Real positive</p> <ul> <li>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. </li> <li>Can be good for simple and effective, fire and forget functions. <br /></li> </ul> <p>Real negative</p> <ul> <li>Is hard to refactor away from. </li> <li>Doesn't work with inheritance, polymorphism and interfaces. </li> <li>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. </li> <li>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. </li> <li>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? </li> </ul> <p>&#160;</p> <p>What you potentially can read from a static method</p> <ul> <li>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. <br /></li> </ul> <p>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. <br /></p> <p>&#160;</p> <p>There is use for static methods. Just be sure that it outweighs the potential negative issues!</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-92048361598887445852009-01-13T21:04:00.001+01:002009-01-13T21:04:04.653+01:00Windows 7 useful stuff (link)<p>Tim Sneath, director of the Windows and Silverlight technical evangelism team, has an interesting <a href="http://blogs.msdn.com/tims/archive/2009/01/12/the-bumper-list-of-windows-7-secrets.aspx" target="_blank">post</a> about 30 windows 7 &quot;secrets&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.</p> <p> <br />note to self: download windows 7 beta shortly</p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-68243614312514633182009-01-12T22:54:00.001+01:002009-01-12T22:54:48.662+01:00Essential Software Principles: Don't Repeat Yourself (DRY)<p>Don't Repeat Yourself, also called the Single Point of Truth, is about representing any and every piece of information in a single representation. </p> <p> <br />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 &quot;database schemas, test plans, the build system, even documentation&quot;. They further refer to various techniques for achieving this, like code generation, automatic build systems and scripting languages. </p> <p> <br />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. </p> <p> <br />The Pragmatic Programmer defines for reasons for duplication:</p> <ul> <li>Imposed duplication: You feel you have no other choice </li> <li>Inadvertent duplication: You don't realize you are duplicating </li> <li>Impatient duplication: Duplication seems like the simplest option </li> <li>Interdeveloper duplication: Multiple people duplicate</li> </ul> <p> <br />All are common cases for duplication. Being aware of each and working to avoid them are essential.</p> <p> <br />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. </p> <p> <br />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. </p> <p> <br />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.</p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-39658569491496756262009-01-11T21:09:00.001+01:002009-01-11T21:09:12.546+01:00Essential Testing Practices: Arrange, Act, Assert (AAA)<p>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. </p> <p> <br />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!). </p> <p> <br />The structure of unit tests matter because it makes it <br />- easier to understand the usage of the code under test <br />- easier to change <br />- easier to fix <br />- easier to write. You should be able to do it in the natural way you think about it. </p> <p> <br />The Arrange, Act, Assert unit testing structure pattern is an old way of solving this. The concept is utterly simple to understand: </p> <blockquote> <p> <br />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. </p> </blockquote> <p> <br />Note: Both Typemock and RhinoMocks support the AAA syntax. That means you don't need to/shouldn't use the record/replay mode anymore. </p> Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com0tag:blogger.com,1999:blog-4900151497087138627.post-70436196493268699882009-01-10T13:20:00.000+01:002009-01-10T13:20:00.459+01:00Interesting Software Practices: Code in non-English<p>Which language to write code and comments in can sometimes come up as a question in countries where English isn't the native language.</p> <p> <br />There's both good and bad things with doing this, and I thought I'd list a few thoughts about it. <br /></p> <p>The bad things about writing code and comments in your own language is:</p> <ul> <li>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.&#160; </li> <li>There will always be mix of languages involved. Any external libraries/frameworks/components will use a different language. </li> <li>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. </li> </ul> <br />The good things about using your own language is: <ul> <li>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. </li> <li>You might use less time finding the correct words. </li> </ul> <p>&#160;</p> <p>Did I forget anything obvious? What do you think?</p>Rune Sundlinghttp://www.blogger.com/profile/10334374587401199926noreply@blogger.com2