<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Design Patterns</title>
        <link>http://geekswithblogs.net/bcaraway/category/6960.aspx</link>
        <description>Design Patterns</description>
        <language>en-US</language>
        <copyright>Blake Caraway</copyright>
        <managingEditor>blake@caraways.net</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>Decouple Your Code For Testability</title>
            <link>http://geekswithblogs.net/bcaraway/archive/2007/08/12/114591.aspx</link>
            <description>&lt;p&gt;&lt;font size="2" face="Verdana"&gt;I've received a handful of comments/questions surrounding part of the code sample from my &lt;/font&gt;&lt;a href="http://geekswithblogs.net/bcaraway/archive/2007/06/02/112942.aspx"&gt;&lt;font size="2" face="Verdana"&gt;previous post&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Verdana"&gt;.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;The comments I received have to do with the few lines of code in the Authentication WebService that included a custom interface and a call to a third party tool. Here's the code in question:&lt;/font&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Authentication : WebService&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; IWebContext _webContext = ObjectFactory.GetInstance&amp;lt;IWebContext&amp;gt;();&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsLoggedIn()&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;._webContext.IsUserAuthenticated;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;/font&gt; &lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;font face="Verdana"&gt;Create An Abstraction&lt;/font&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;IWebContext is an interface I created for use within my web site that abstracts calls to lower level ASP.Net stuff like QueryString, Session, and Identity thru the HTTPContext object. Often I want to have a testable object in an ASP.Net web project that will depend on something at the ASP.Net lower level. The way to put a seam in my code that decouples the object I want to test from the ASP.Net stuff is to abstract it away...into something like IWebContext. Here's the IWebContext interface definition:&lt;/font&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IWebContext&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsUserAuthenticated { get; }&lt;br /&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear();&lt;br /&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; Save(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;    &lt;span class="kwrd"&gt;object&lt;/span&gt; Get(&lt;span class="kwrd"&gt;string&lt;/span&gt; key);&lt;br /&gt;    &lt;span class="kwrd"&gt;string&lt;/span&gt; GetQuerystringValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; key);&lt;br /&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; Set(&lt;span class="kwrd"&gt;string&lt;/span&gt; s, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;pre class="csharpcode"&gt; &lt;/pre&gt;
&lt;h4&gt;&lt;strong&gt;&lt;font face="Verdana"&gt;Dependency Inversion / Inversion of Control&lt;/font&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;Regarding the ObjectFactory.GetInstance&amp;lt;IWebContext&amp;gt;(); line of code -- to help with decoupling, I use the Dependency Inversion Principle (DIP). Another name for DIP is Inversion of Control (IoC). The DIP has been proposed by Robert C. Martin. It states that:&lt;/font&gt; &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;font size="2"&gt;High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. &lt;/font&gt;&lt;/strong&gt;&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;In short, strive to make your classes depend upon abstractions, not concretions. When you see the keyword 'new' - that's a tight coupling to a specific concrete type. If you cannot easily isolate an object from it's dependencies, and if this makes it more difficult to test, then that's a tight coupling that needs to be addressed. You need to &lt;em&gt;invert &lt;/em&gt;the dependencies.&lt;/font&gt; &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;  &lt;/font&gt; &lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;font face="Verdana"&gt;The Flavors of DIP - Inverting with StructureMap&lt;/font&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;There are two main flavors of Dependency Inversion - Dependency Injection and Service Location. Beyond that, Dependency Injection has two main forms - Constructor Injection and Setter Injection. Constructor Injection is when an object is instantiated with a dependency. Setter Injection is when a dependency is provided through some sort of setting method/property.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;The other main form of Dependency Injection is Service Location. Using a method like StructureMap's ObjectFactory.GetInstance() is another way to locate a service/dependency. In the code sample, the ObjectFactory object lives in a third party tool called StructureMap ( &lt;a href="http://structuremap.sourceforge.net"&gt;http://structuremap.sourceforge.net&lt;/a&gt; ). We ask StructureMap.ObjectFactory to return an instance of a certain type (i.e. IWebContext). This effectively inverts the control of resolving dependencies from the object needing to use the dependency to a third party, adhering to the DIP, and promoting looser object coupling.&lt;/font&gt;&lt;font size="2" face="Verdana"&gt; &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;If you are interested in learning more about the open source project StructureMap, visit the project page on SourceForge at &lt;/font&gt;&lt;a href="http://structuremap.sourceforge.net/"&gt;&lt;font size="2" face="Verdana"&gt;http://structuremap.sourceforge.net/&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Verdana"&gt;. I won't try and detail all of the implementation details of StructureMap, but here's a quick rundown of the basic usage. &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;StructureMap allows us to decorate abstractions with a [PluginFamily] attribute, as well as a [Pluggable] attribute on the types that implement the abstraction. When a call is made to ObjectFactory.GetInstance&amp;lt;IWebContext&amp;gt;(), StructureMap finds the classes that implement the type being requested and resolves, instantiates, and returns the correct concrete instance. Let's look at an example: &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;strong&gt;Interface:&lt;/strong&gt; This is the IAccountRepository interface, decorated with the &lt;em&gt;PluginFamily&lt;/em&gt; attribute and key name of 'Default'. &lt;/font&gt;&lt;/font&gt; &lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[PluginFamily(&lt;span class="str"&gt;"Default"&lt;/span&gt;)]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IAccountRepository&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    BillToAccount[] GetBillingAccountsForUser(User user);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    ShipToAccount GetShipToAccount(AccountIdentifier accountIdentifier);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    BillToAccount GetBillToAccount(AccountIdentifier accountIdentifier);&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;strong&gt;Default Implementation:&lt;/strong&gt; Here we have an implementation of the IAccountRepository interface decorated with the &lt;em&gt;Pluggable&lt;/em&gt; attribute and a key name of 'Default'. &lt;/font&gt;&lt;/font&gt; &lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[Pluggable(&lt;span class="str"&gt;"Default"&lt;/span&gt;)]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AccountRepository : AccountRepositoryBase&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    ...&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;strong&gt;Cached Implementation:&lt;/strong&gt; Here we have another implementation of the IAccountRepository interface decorated with the &lt;em&gt;Pluggable&lt;/em&gt; attribute and a key name of 'Cached'. &lt;/font&gt;&lt;/font&gt; &lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[Pluggable(&lt;span class="str"&gt;"Cached"&lt;/span&gt;)]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CachedAccountRepository : IAccountRepository&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    ...&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;pre&gt; &lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;When code needs to make use of a dependency like IAccountRepository, it can ask ObjectFactory for the default instance in this way: &lt;/font&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;_accountRepository = ObjectFactory.GetInstance&amp;lt;IAccountRepository&amp;gt;();&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;You can have StructureMap return specific implementations of IAccountRepository in a couple easy ways: you can set the &lt;em&gt;PluginFamily &lt;/em&gt;attribute's key on the interface to match that of the desired "default" &lt;em&gt;Pluggable&lt;/em&gt; instance like this: &lt;/font&gt; &lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;[PluginFamily(&lt;span class="str"&gt;"Cached"&lt;/span&gt;)]&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IAccountRepository&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    ...&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;...Or you may ask for a particular instance by name, like this: &lt;/font&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font size="2" face="consol"&gt;_cachedAccountRepository = ObjectFactory.GetNamedInstance&amp;lt;IAccountRepository&amp;gt;(&lt;span class="str"&gt;"Cached"&lt;/span&gt;);&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;   &lt;/p&gt;
&lt;p&gt;&lt;font size="3" face="Verdana"&gt;&lt;strong&gt;Dynamic Behavior / Configuration&lt;/strong&gt;&lt;/font&gt;  &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;StructureMap also allows you to specify type configurations (and all sorts of other behaviors your system might need) in a config file. Some may prefer the config file method because it's a little more obvious (in a file, rather than living inside the code at various locations) as to what objects implement certain interfaces and what the default behavior is for a particular abstraction. Having these settings in a config file can also be helpful when you have an automated build that might require different system behavior (i.e. different implementation of various abstractions) based on the particular environment you are deploying to or maybe the state of an entire subsystem.&lt;/font&gt;  &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;When deploying your system, behavior can be switched around by having your build tool like NAnt issue an 'XMLPoke' command to change key names inside the StructureMap.config file. Also, your application may need to behave differently based on some runtime situations like database or service availability (think 'offline mode'). This can easily be achieved by using a tool like StructureMap. Simply request a different implementation of a type using the '&lt;em&gt;ObjectFactory.GetNamedInstance'&lt;/em&gt; method as shown above and your system can gracefully adapt to any unexpected environmental situation. &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;  &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;Hopefully I've shown here the importance of abstracting away the factors that can make code more difficult to get under test, as well as a couple mechanics on how to approach the problem. &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;  &lt;/font&gt; &lt;/p&gt;
&lt;p&gt;&lt;font size="2" face="Verdana"&gt;/bc&lt;/font&gt;  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;font size="2" face="Consolas"&gt;&lt;/font&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=114591"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=114591" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/bcaraway/aggbug/114591.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Blake Caraway</dc:creator>
            <guid>http://geekswithblogs.net/bcaraway/archive/2007/08/12/114591.aspx</guid>
            <pubDate>Sun, 12 Aug 2007 17:30:45 GMT</pubDate>
            <comments>http://geekswithblogs.net/bcaraway/archive/2007/08/12/114591.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/bcaraway/comments/commentRss/114591.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/bcaraway/services/trackbacks/114591.aspx</trackback:ping>
        </item>
    </channel>
</rss>