Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

Getting started with BDD style Context/Specification base naming
Updated BDD Naming Macro
Setting The Record Straight - My Thoughts On The MVP Variants (for web applications)
code.google.com/p/jpboodhoo!!!
Alternative To ALT-INS For ReSharper Junkies
Update To VS2008 Issue
VS2008 - Bringing Attention To An Issue
Static Gateway - Part 2
Stop Reading - Start Doing
Downloading VS2008
Amendment - Nothin But .Net, College Station Texas
The Expert Mind
You know as much as you know "right now"
A tale of two brothers
Building a culture of integrity
Nothin But .Net Fundametals- College Station , TX ( January 7th - 11th, 2008 )
Leading by multiplicity
Reflecting on an amazing week (People over process)
Updated - Macro For Test Naming
ReSharper Templates
Huge Code Drop Coming!!!!!!!
They can steal your code, but they can't steal your creativity!!
Software Developers vs. Software Artists
TDD is like snowboarding (or learning any new skill)

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 337
This Year: 62
This Month: 13
This Week: 3
Comments: 889

 Thursday, November 29, 2007
Thursday, November 29, 2007 10:36:09 AM (Mountain Standard Time, UTC-07:00) ( Agile | Programming )

I have received a number of good responses from people who have a couple of aesthetic issues with the BDD style naming that I am starting to use. Let me clarify, I have been using the natural sentence style test naming since Scott introduced me to it in earlier in the year. I have not used the context/specification style test naming on a project yet, though it is my intent to write each successive test from this point forward in that style and if I feel pain points I will let you know.

From my experience so far here are some tips that I think will resolve the issues that the people who are trying to use it will find:

Issue 1 – “I ended up really not liking those fixture names because I felt it was hard to find fixtures for specific classes, and navigate with Resharper Type navigation.  Was wondering what naming convention you came up with for fixtures?”

A: My recommendation for this is to create a single test class in your test project called $SystemUnderTest$Specs. Where SystemUnderTest corresponds to the name of the class that you will be testing. This is just a grouping construct for all of the “Contexts” that will be run against that fixture. Inside the “Specs” class, you will create classes for each of the different contexts. Here is an example of one that I just rewrote the tests for the ShoppingCart class is the nothinbutdotnetweb.app project using this new style and I personally have to say that it was an awesome experience. One of the things that I found was that I could copy the body of one fixture and change the name to reflect the new context and I could focus solely on the interactions and behaviour that is pertinent to that particular context. Take a look at the Report that is generated when run against the specs in the ShoppingCartSpecs class:

  • When a product is added that is not already in the cart
    • The cart item factory should be used to create a cart item for the product being added.
  • When an item is added
    • The item count should be incremented
    • The item should be added to the underlying list
  • When the same product is added again
    • The item factory should not be leveraged
    • The quantity of the item should be incremented
  • When changing the quantity of a product in the cart
    • The item should be updated with the new quantity
  • When changing the quantity of a product causes the item to be empty
    • The item should be removed from the cart
  • When changing the quantity of a product that is not in the cart
    • Nothing should happen
  • When a product is removed from the cart
    • The item representing the product should be removed
    • The number of items in the cart should decrease
  • When asked to remove a product that is not already in the cart
    • Nothing should happen
  • When the cart is emptied
    • There should be no more items
  • When asked for the quantity of a product
    • The cart item representing the product should be asked for its quantity
    • The result should be the quantity of the item for the product
  • When asked to calculate the total cost
    • Should be the sum of the total cost for all items

 

One of the things you will notice about the tests in these fixtures compared to the others in the rest of the project (so far) is the use of Setup to stress the context setup. I added a virtual method to the AutoMockingTest base called because, which calls out the action being invoked on the SUT.

This actually resulted is some tests that contained no body whatsoever, and the ones with assertions actually only needed one assertion.

This is a learning experience for me to, but so far, I am loving the expressiveness and focus this style of testing brings to the table.

By grouping all of the fixtures into the ShoppingCartSpecs class, you can solve the navigability issue.

 

The second issue I received was:

“Quick question ... while the idea is great, it doesn;t flow for me, as ReSharper keeps cutting in and completing my words for me - Intellisence is great, but in this context is is annoying as hell ...

 

How do you avoid this problem?”

 

 

A – This is actually a ReSharper setting that I have had turned off pretty much since I started using ReSharper:

  • Go to ReSharper – Options
  • Select the Intellisense item in the left nav bar
  • Uncheck Letters and Digits in the Completion Behaviour pane on the right!!

That’s it. Now you can write you natural sentences without ReSharper getting in your way. Since I have been without this setting since ReSharpers inception, I have gotten quick at using ALT-SPACE/CTRL-ALT-SPACE a lot, this may take a bit of getting used to for the people who were use to the Letters and Digits autocompletion behaviour.

 

Again, as far as quickly navigating to the tests for a sut, you can just go CTRL-SHIFT-N and then start typing in the significant letters for the Spec class, in this case it would be:

 

CTRL-SHIFT-N -> SCS

 

Because all of the fixtures will be contained in the file but there will be no ShoppingCartSpecs type. I guess you could create one as a nesting construct, but that is what the file is for.

 

Again, let me stress that this Context/Specification style naming is a little new for me, and there is a possibility that the tests in the ShoppingCartSpecs that have no assertions could be a smell (I’ll get that verified by Scott in a little while), I already see the benefits from both the documentation perspective as well as the ability to truly only focus on one specific context at a time.

 

Develop With Passion.

 

Comments [3] | | # 
Thursday, November 29, 2007 2:15:16 AM (Mountain Standard Time, UTC-07:00) ( Agile )

After an awesome session pair programming with Scott the other day, I am going to start taking advantage of natural sentence style naming for not just my test method names, but the names of the test fixtures themselves.

The name of the fixture will now become the context for the tests inside of that fixture. It is actually surprising what level of detail this allows you to express yourself.

I had to change my test naming macro to support classes also. Here is the fix:

 

Imports System Imports System.Windows.Forms Imports EnvDTE Imports EnvDTE80 Imports System.Diagnostics Public Module CodeEditor Sub ReplaceSpacesInTestNameWithUnderscores() If DTE.ActiveDocument Is Nothing Then Return Dim wrCS As Boolean = DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value Try DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = False Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection) Dim index As Integer selection.SelectLine() If selection.Text = "" Then Return Dim methodIndex As Integer = selection.Text.IndexOf("public void ") Dim classIndex As Integer = selection.Text.IndexOf("public class ") index = CType(IIf(methodIndex >= 0, methodIndex, classIndex), Integer) Dim prefix As String = CType(IIf(methodIndex >= 0, "public void ", "public class "), String) prefix = selection.Text.Substring(0, index) + prefix Dim description As String = selection.Text.Replace(prefix, String.Empty).Trim selection.Text = prefix + description.Replace(" ", "_").Replace("'", "_") + vbCrLf selection.LineDown() selection.EndOfLine() Catch ex As Exception MsgBox(ex.Message) Finally DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = wrCS End Try End Sub End Module

Develop With Passion

Comments [1] | | # 
 Wednesday, November 28, 2007
Wednesday, November 28, 2007 11:59:42 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | Agile | C# | Programming )

Having received a bunch of emails in the past couple of weeks from people who have been asking me questions with regards to Passive View/Supervising controller patterns for web applications. I needed to let people know that for the last couple of months I have been developing web apps in a completely MVC style which eliminates the need for patterns like Passive View/ Supervising Controller.

For the people who are using the MVP pattern in their (web) applications I personally would now lean to the Supervising Controller style as it eliminates a lot of necessary chattiness between the view and the presenter. It also lends itself to much more simple unit tests.

Having gotten back into the Smart Client realm, I am once again reminded of the importance of patterns like Supervising Controller and presentation model as becoming essential to ensuring correct separation of responsibilities.

For my web applications, however, all I use now is a:

  • Front Controller
  • Commands
  • View Templates (ASPX style!!)

Here is an example of what I mean, for the nothinbutdotnetstore.web.app project that is currently hosted on google code, here is the Command that processes getting a list of the main departments in the store for viewing:

 

using NothinButDotNetStore.Infrastructure; using NothinButDotNetStore.Infrastructure.Container.Common; using NothinButDotNetStore.Tasks; using NothinButDotNetStore.Web.FrontController; namespace NothinButDotNetStore.Web.DepartmentBrowser { public class ViewMainDepartments : ICommand { private ICatalog catalog; private IRequestContext requestContext; private IViewEngine viewEngine; public ViewMainDepartments(IHttpContext context) : this(context, DependencyResolver.GetImplementationOf<IRequestContextFactory>().CreateFrom(context), DependencyResolver.GetImplementationOf<IViewEngine>(), DependencyResolver.GetImplementationOf<ICatalog>()) { } public ViewMainDepartments(IHttpContext context, IRequestContext requestContext, IViewEngine viewEngine, ICatalog catalog) { this.catalog = catalog; this.viewEngine = viewEngine; this.requestContext = requestContext; } public void Execute() { requestContext.AddToStateBag(ViewBagItem.Departments, catalog.GetMainDepartments()); viewEngine.Display(Views.ViewDepartments); } } }
 
Here is the complete ASPX (View Template) that gets rendered for that command executing:
 
 
<%@ MasterType VirtualPath="~/Store.master" %> <%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" MasterPageFile="~/Store.master" %> <%@ Import namespace="NothinButDotNetStore.Web.FrontController"%> <%@ Import namespace="NothinButDotNetStore.Web"%> <%@ Import namespace="NothinButDotNetStore.Infrastructure"%> <%@ Import namespace="NothinButDotNetStore.DTO"%> <asp:Content ID="content" runat="server" ContentPlaceHolderID="childContentPlaceHolder"> <p class="ListHead">Select An Isle</p> <table> <% int rowIndex = 0; %> <% foreach (DepartmentDisplayItem dto in ViewBag.GetItem(ViewBagItem.Departments)) { %> <tr class='<%=(rowIndex++ %2 ==0 ? "nonShadedRow" : "shadedRow" ) %>'> <td> <a href='<%= Url.ToBeProcessedBy(CommandNames.ViewSubDepartments) .AddPayloadValue(PayloadKeys.DepartmentId,dto.Id).Build() %>'> <%=dto.DepartmentName %> </a> </td> </tr> <% } %> </table> </asp:Content>

There is no code behind for this aspx page. The logic in the aspx file is there because it is rendering related logic. This aspx page does not talk to a service layer or domain objects or even a data access layer. It reaches into a ViewBag looking for information that it can render, and then it proceeds to do exactly what it should, render the information. What may not be immediately obvious is that this is a plain aspx file with no codebehind file. The page inherits from System.Web.UI.Page.

As far as testability of this style of development, here is a sample test for one behaviour of the ViewMainDepartments command:

[RunInUnitTestContainer] [Test] public void Should_populate_the_context_with_the_departments_to_display() { ICommand sut = CreateSUT<ViewMainDepartments>(); IEnumerable<DepartmentDisplayItem> results = CreateMock<IEnumerable<DepartmentDisplayItem>>(); using (Mocks.Record()) { Expect.Call(mockCatalog.GetMainDepartments()).Return(results); mockRequestContext.AddToStateBag(ViewBagItem.Departments, results); } using (Mocks.Playback()) { sut.Execute(); } }
 
 
 

In the next little while I am going to shed some more light on this approach to web application development. IMHO, the separation of concerns for web applications written in this style is much greater than when trying to stuff in a pattern that (again IMHO) did not fit well for the technology, and was leveraged for the sake of increased testability.

Comments [1] | | # 
Wednesday, November 28, 2007 11:01:52 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | .Net 3.0 | Agile | C# | Continuous Integration | Patterns | Programming | Tools )

I finally set up a googlecode project to host source code for the various things I have been doing over the last year. The first major significant contribution is of course the code drop that I promised a week ago now!!

The application is the start of what I hope will evolve to be a great learning resource for lots of things related to .Net development. The application does not currently cover any of the “extra” topics that I did not have time to get covered in the course. This is perfect because as request come in from people (including past students) asking how to tackle a certain problem, I will use this application as the demonstration area where I can tackle the problem, and update the code base, and you will be able to update your local copy and carry on.

I am currently in the midst of a large Smart Client application that I am hoping to be able to harvest pieces of code out and do the exact same thing except for the smart client realm. I have much more experience developing in the smart client realm and that is where I feel most comfortable, so I am looking forward to be able to do another code drop (for a different application) in a couple of months.

I am going to write up another post about the Web Application as it is built very differently from traditional .Net based web applications. In following with the theme for my courses, there are currently no 3rd party frameworks (other than log4net) that have come into play. My goal with this web app is to demonstrate to people how far we can push raw .Net. The goal being that expanding their knowledge of how to creatively leverage .Net, they will be better prepared to jump into frameworks that they may currently feel daunted by. As time goes by, I will swap pieces of the application out with components that people are asking to see meaningful samples on:

  • NHibernate
  • Castle
  • Prototype
  • JQuery
  • ..*

As the app stands right now I see it as the beginning of what will shape up to be a pretty mean machine!!

I am going to post a screencast that will show people how to get started working with the web application. For people who are eager to get going right now, here are the quick and simple steps without a lot of explanation (that will come in the next post):

  • Anonymously checkout the trunk from the google code repository using the following svn command line:
    svn checkout http://jpboodhoo.googlecode.com/svn/trunk/ jpboodhoo-read-only
  • Navigate to the checkout folder
  • Go into the build folder
  • Copy local.properties.xml.template and paste it into the same directory, then rename the copied file to local.properties.xml
  • Open up the local.properties.xml file with your favourite text editor.
  • Modify any of the settings in the file that are different on your machine.
  • Open up a command prompt and navigate to the build directory of the code.
  • type: build load.data and hit enter.
  • type: build test.all.woc
  • type: build run
  • The last task should fail (I haven’t automated everything yet)
  • Create a virtual directory called nothinbutdotnetstore that points at the following location (this location is created after you attempt to run the build run task) : ${checkoutfolder)\build\deploy\web\app
  • After successfully creating the virtual directory try the build run task again.
  • If the web browser pops up pointed at a web page (for the app) you are in business. Feel free to click through the first set of pages that are implemented (only 3 pages are currently implemented).

As far as what I have planned to implement in the web app (that is currently not implemented):

  • Build out a more extensive domain model that encompasses some more advanced scenarios of the application (especially around order processing).
  • Unit Of Work for the service layer
  • Implement a lightweight OR/M layer
  • Integrate some UI frameworks like prototype
  • Eliminate Master Pages completely and switch to a much more elegant template view pattern.
  • Introduce a more robust container (as the current one is a simple dictionary wired up in a simple procedural fashion).
  • Introduce the concepts of lifecycles for the items in the container. Right now, everything wired into the container is essentially a singleton.
  • Introduce CSS based layout for the web pages (working with a designer on this one).
  • Bring security concerns into play
  • Demonstrate how to effectively manage sessions
  • ……lots,lots,lots more!!!

Obviously I will be leaning on people checking out the code and playing around with it and submitting requests for things they would like to see.

There are a couple of things that you will immediately notice about the application:

  • Clean front controller implementation with ASPX pages as the template views. There are no code behind pages in this web application. All web requests are handled by command objects that interact with the service layer, push the details into a “ViewBag” and then choose which view to render.
  • Logical layers in the project are separated using simple folders and namespaces (not full blown projects)
  • Build automation is its own project in the solution (props to Jay Flowers for this inspiration)
  • The current container implements (CustomDependencyContainer) is very simple and is handled by a big procedural application startup task.
  • Compile time support for the database layer. A couple of classes ago I introduced the concept of a generic TableColumn<T> type. In England after introducing this concept Scott Cowan leveraged his knowledge of MyGeneration to automatically generate strongly typed table definitions that we could leverage to do mapping (trust me when I say, this is nothing like datasets). Until moving into OR/M concepts deeper this gives a good place to start as the generation of the TableDefinitions is linked to whenever the SQL files change, so you will get compile errors if column types are now mismatched etc…

There are lots of other things I could talk about, but this code really is the start of what I see being a long running conversation between myself and other people wanting to learn. In all honesty for all of the emails I have not paid attention to this year, hosting code through google will allow me to answer peoples questions in a much more meaningful way as I can point them at this site to see the implementation of the code they had questions about.

I am going to be placing all of the code for presentations that I have done for the last year as well as continue to update it with the source code that comes out of new courses that will be coming out in the new year, and the DNRTv episodes.

Once again, the application is currently in its infancy, but as people start sending in the requests I now will have a venue and example to add upon to answer questions in a much more timely fashion!!!

 

Develop With Passion!!!

 

 

Comments [6] | | # 
 Sunday, November 25, 2007
Sunday, November 25, 2007 3:23:32 PM (Mountain Standard Time, UTC-07:00) ( General )

Everyone who knows me knows what a big keyboard junkie I am. When I am typing on my MacBook keyboard and not my natural (or datahand). There is not Insert key that I can use when in ReSharper.

I know that there are utilities to remap keys to emulate the insert key, but I am not going to get into those.

Here is the keyboard sequence to get to the Generate Code dialog (normally accessed by pressing ALT-INS):

ALT – R – C – G

Now here is the funny thing. After just using this sequence for a couple of hours I find it much faster than ALT-INS. I think this is because even though there are more keys to hit, the flight path of my hands on the natural keyboard is greatly decreased because I don’t have to move my right hand off home row. When I want to hit the insert key on my natural keyboard I have to move my right hand (this could also be due to poor keyboard technique on my part).

Nonetheless, the nice thing about this sequence is now I am using the exact same key sequence when I am on my natural keyboard and my macbook pro keyboard!!

 

Develop With Passion

Comments [4] | | # 
 Friday, November 23, 2007
Friday, November 23, 2007 10:02:01 AM (Mountain Standard Time, UTC-07:00) ( Tools )

Thanks to everyone for all of the feedback. In the end, the first response that I tried was to install the latest copy of VisualSVN (I was running a slightly older version).

After installing the latest version of VisualSVN everthing is functioning as expected.

Comments [3] | | # 
 Thursday, November 22, 2007
Thursday, November 22, 2007 11:00:26 PM (Mountain Standard Time, UTC-07:00) ( Tools )

Well, today I installed VS2008 on my machine. Setup went great and completed with no errors.

This was a fresh install on a machine that had no prior beta bits installed whatsoever. So I did not anticipate anything weird happening.

Fired up VS2008 for the first time and  it went through its normal first time setup deal. So there I was, in a blank IDE with my C# RSS Feed showing from the help page.

I go to add a new project and I’m presented with this wonderful dialog:

Ok…. So I try a few (lot) more menu items and the same thing happens. So, I think to myself, just exercise the standard Windows remedy. Get out, get back in, and see if it is better!!

I would do that, if I could exit Studio!! Even hitting the big red x in the top right corner of VS2008 pops up this dialog. The only way to shut this down is to kill the devenv process.

I am currently running XP with SP2 and an existing installation of VS2005. Again, let me stress that I have not installed any beta bits of VS2008.

After un installing and reinstalling to no success (same result) I quickly googled. I happened to stumble into an MSDN forum where people are having the same issue and are also not sure how to go about resolving it.

Has anyone else ran into this issue? How did you fix it?

Comments [4] | | # 
 Wednesday, November 21, 2007
Wednesday, November 21, 2007 9:02:06 AM (Mountain Standard Time, UTC-07:00) ( )

In the last installment I left off with a class that served as a Static Gateway for Logging functionality. The nature of the members being accessed statically allowed for pure syntactic sugar for clients who wanted to consume logging functionality. I got a lot of feedback from people who made comments about why I could not make use of a IOC container to accomplish the same thing. This post is my answer to those questions as that is exactly what I do on my own projects.

When I get to the point that I need to introduce IOC into my codebase I drive it out in a test first manner. In the last implementation that I did here was the first test that I wrote:

 

[Test] public void Should_leverage_container_to_resolve_an_implementation_of_an_interface() { Provide<IDependencyContainer>(CreateMock<IDependencyResolver>()); IDbConnection mockDbConnection = CreateMock<IDbConnection>(); using (Mocks.Record()) { Expect.Call(mockDependencyResolver.GetImplementationOf<IDbConnection>()).Return(mockDbConnection); } using (Mocks.Playback()) { DependencyResolver.InitializeWith(mockDependencyResolver); IDbConnection result = DependencyResolver.GetImplementationOf<IDbConnection>(); Assert.AreEqual(mockDbConnection, result); } }

I am making use of the automocking container in this test so try not to get hung up on the semantics of what the Provide<IDependencyResolver> call is doing.

All this test demonstrates is that I am going to have a class called DependencyResolver that will serve as the Static Gateway, to IOC functionality. I have also show that it is not necessarily going to do the work, but rather it will delegate to an IDependencyResolver implementation (mocked out in this test) to accomplish the work on its behalf. The implementation code to get this test passing is as follows: 

public class DependencyResolver { private static IDependencyResolver resolver; public static void InitializeWith(IDependencyResolver resolver ) { DependencyResolver.resolver = resolver; } public static Interface GetImplementationOf<Interface>() { return resolver.GetImplementationOf<Interface>(); } }
 
public interface IDependencyResolver { Interface GetImplementationOf<Interface>(); }

So far so good. I continued to write one more test (based on my prior experience with leveraging containers) to ensure that I had better error messages if a dependency could not get resolved properly. This is most often caused by the underlying container not being configured with an implementation of a particular contract: 

[ExpectedException(typeof(InterfaceResolutionException))] [Test] public void Should_report_more_detail_if_unable_resolve_an_implementation_of_an_interface() { Provide<IDependencyResolver>(CreateMock<IDependencyResolver>()); using (Mocks.Record()) { Expect.Call(mockDependencyResolver.GetImplementationOf<IDbConnection>()).Throw(new Exception()); } using (Mocks.Playback()) { DependencyResolver.InitializeWith(mockDependencyResolver); DependencyResolver.GetImplementationOf<IDbConnection>(); } }

The accompanying implementation is fairly trivial:

 

public static Interface GetImplementationOf<Interface>() { try { return resolver.GetImplementationOf<Interface>(); } catch (Exception e) { throw new InterfaceResolutionException(e,typeof(Interface)); } }

The custom exception is as follows:

 

public class InterfaceResolutionException : Exception { public const string ExceptionMessageFormat = "Failed to resolve an implementation of an {0}"; public InterfaceResolutionException(Exception innerException, Type interfaceThatCouldNotBeResolvedForSomeReason):base(string.Format(ExceptionMessageFormat,interfaceThatCouldNotBeResolvedForSomeReason.FullName),innerException) { } }

Having used this technique on my last couple of projects, it did not matter if the underlying implementation of IDependencyResolver was a Spring adapter, a Castle adapter, or a StructureMap adapter, if the real container framework had trouble resolving a dependency, I would get a nice line in my log file that read:

(omitting tracing information**) – Failed to resolve an implementation of an (Whatever the contract is).

This helped me quickly go to the container configuration and deal with the errors as they were always to do with the way I was wiring things up.

Now that I have this gateway for Dependency resolution in place, I should be able to leverage this from the Logging static gateway. I do this by changing my Logger test as follows: 

[Test] public void Should_ask_dependency_resolver_for_a_logger_factory_that_can_be_used_to_return_a_logger_to_the_client() { ILog mockLog = CreateMock<ILog>(); ILogFactory mockLogFactory = CreateMock<ILogFactory>(); Provide<IDependencyResolver>(mockDependencyResolver); using (Mocks.Record()) { Expect.Call(mockDependencyResolver.GetImplementationOf<ILogFactory>()).Return(mockLogFactory); Expect.Call(mockLogFactory.CreateFor(typeof (LogTest))).Return(mockLog); } using (Mocks.Playback()) { DependencyResolver.InitializeWith(mockDependencyResolver); ILog log = Log.For(this); Assert.AreEqual(mockLog, log); } }

This turns my implementation of the Log static gateway into the following: 

public class Log { public static ILog For(object itemThatRequiresLoggingServices) { return For(itemThatRequiresLoggingServices.GetType()); } public static ILog For(Type type) { return DependencyResolver.GetImplementationOf<ILogFactory>().CreateFor(type); } }

This means that from this point on, when I want to introduce another static gateway for some other piece of, typically, cross cutting functionality such as logging. The Static Gateway for that functionality can make use of the dependency resolver to resolve its dependency and it completely eliminates the need for static fields and initialization method in everything but the main DependencyResolver Static Gateway itself.

I like to keep classes like Log kicking around because in my code that consumes Logging functionality I would much rather have a line of code in a client class that reads:

Log.For(this).InformationalMessage(“Blah”)

As opposed to:

DependencyResolver.GetImplementationOf<ILogFactory>().CreateFor(this).InformationalMessage(“Blah”)

The Log Static Gateway still shields the consumer from the details of how to go about logging so the consumer can carry on it its happy simple world.

Develop With Passion!!

Comments [4] | | # 
Wednesday, November 21, 2007 1:30:10 AM (Mountain Standard Time, UTC-07:00) ( Agile | Programming )

I had to laugh when I read “TDD Ain’t No Snowboarding from Alessandro Burrato. It is a direct counter to my TDD is Like Snowboarding post!!

His experience of TDD is very different than the experience I documented based off of my experience introducing it to clients. And I feel that his recollection of the experience is definitely one that I would like to see more in the clients that I engage and the people that I talk to

He makes one very good point that I can’t stress enough to people who spend their days reading blogs about the great stuff that people are doing, to quote him:

“If, and only if, you stop seeking pre-cooked answers from those who already tried it and start friggin’ DOING something.”

At one point or another, practical knowledge of a topic far outweighs any theories you may have built up in your head!!

Nice post Alessandro.

 

Comments [1] | | # 
 Monday, November 19, 2007
Monday, November 19, 2007 2:39:19 PM (Mountain Standard Time, UTC-07:00) ( General | Tools )

The title says it all. Looks like I will be prepping a new VMWare image in a couple of hours!!

Now the JetBrains people have a good target to aim at with getting a release out that supports the RTM of VS2008!!

Develop With Passion

Comments [2] | | #