CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff
  • It’s been years since I’ve gone on an Anti-Singleton rant

    So apparently it’s time again:

    See:

    TDD Design Starter Kit - Static Methods and Singletons May Be Harmful

    and

    Chill out on the Singleton Fetish

     

    TypeMock will make singletons and statics “testable” now, but you’ll still get screwed over with very tight coupling. 

  • Quickie StructureMap Update for Jan ‘09

     

     

    Before the holidays I more or less promised the stuff below (and status in bold red).  The short status is that I’m going to post a completely new StructureMap website with *complete* documentation and examples by the end of the week.  I will also be making a small 2.5.2 release by Friday the 9th (I just want to finish the documentation and do more dogfooding at work first).

     

    1. A Silverlight ready version (i.e. a cutdown StructureMap) Not started.  Targeting late January
    2. Finish the Mono support.  It's very close, but I want to make sure. Tobias Grimm has sent me several patches for this to me and says that StructureMap is compiling, running, and passing all unit tests on Mono.
    3. The *#%$ "BuildUp" functionality that allows you to do setter injection on an object that's created somewhere else.  Thank you ASP.Net. Done in Trunk (will release in 2.5.2)
    4. Convention based setter injection (low hanging fruit) Done in Trunk (will release in 2.5.2).  Shamelessly stole this idea from Ninject.
    5. A guarantee that StructureMap will function in partially trusted environments, or at least real guidance on what it can and cannot do  Not Started.  I’m going to put my current project into Medium Trust and just see what happens.
    6. "Missing Instance" handlers Done in Trunk (will release in 2.5.2)
    7. A "ConditionalInstance" that will give you easier ways to do conditional construction Done in Trunk (will release in 2.5.2)
    8. Improved diagnostics.  The error output and the output from StructureMapDoctor and ObjectFactory.AssertConfigurationIsValid() could be a lot better Putting off to a 2.5.3 release

     

    Plus:

    1. Idiomatic StructureMap Prism Bootstrapper I have preliminary notes on this, and it isn’t big.  I expect to have this released by 1/9/09 in 2.5.2. 
    2. Complete Documentation 75% done.  See here for the docs in Subversion.  Feedback on the docs would be much appreciated.

     

     

    For the record, I typed ‘09 the first time I had to write down a date this year.  First time ever to get it right.

  • Happy New Year!

    Everyone else is doing a 2008 to 2009 post, so why not.  2008 was a very rough year for me personally, but I learned some good life lessons last year:

    • One door closing might just lead to another door opening.  I started what I thought was going to be my dream job in January and was unemployed by the first week of April.  Dejected and discouraged, I took the job at Dovetail because I knew Chad and some of the other crew there and figured it would be stable.  A half year later I can easily say that this is the best job I’ve ever had in terms of my job satisfaction.  I love the people I work with, I love the environment, and the work has been interesting.  I’m even charged up for a couple upcoming months of crunch time.
    • If you know you need to make a life change, get over the fear and do it.  Said life change basically ruined my 2008, but it gives me some reason to look forward to ‘09 and beyond.  In retrospect, I should have done it years earlier.

     

    My Software Development Plans for 2009

    • I just got renewed as an MVP for C#
    • I’m planning on cranking out a couple more little releases of StructureMap by the end of January.  Between creating (75% done) full documentation, getting StructureMap running on all major .Net Frameworks (3.5, Mobile/Compact, Silverlight, Mono), and adding some requested features, I’m hoping to get StructureMap into more or less a maintenance mode for the rest of the year. 
    • Write my Presentation Patterns book for Addison Wesley.  It’s been 2 years in the making, and it’ll be almost 3 before it’s published.  I hope to blog about it as I go much the way Ayende did with his Boo DSL book. 
    • Make an initial release of the rebooted StoryTeller.  My team is dogfooding it now, so the engine is in good shape.  I’m going to rewrite the UI from scratch in WPF and use a lot of the UI infrastructure as sample code for my book.
    • Continue writing the Patterns in Practice column in MSDN Magazine.  I’m enjoying it so far (and it’s paying for my new car ;-) );  Please send me any subject requests or article ideas!
    • Contribute a little tiny bit to other OSS projects like Fluent NHibernate, FubuMVC, and MassTransit
    • I’m committed to speaking at the Norwegian Developers Conference in Oslo (the city, not the DSL tool) in June, and I’m pretty excited about it.  Assuming it’s ok with work, I’ll be at the Seattle ALT.Net Open Spaces in March, but I just can’t miss a week of work this spring to attend the MVP Summit this time around.  Other than that, I’m hoping to do one more conference in the fall and maybe another Open Spaces event here and there.
    • Blogging?  Well, not so much.  I’d like to finish the “First Causes” series I started last year.  Other than that, it’ll probably just be StructureMap, StoryTeller, and Presentation Patterns stuff.  I’d like to stay away from any new “Vote of No Confidence” / Oxite / “Billy Hollis doesn’t like Agile” arguments and focus on doing my own things first. 

     

    Personal Plans and Resolutions

    • Respond to email correspondence and StructureMap questions much quicker
    • I just turned 35, so this is just about the last chance for me to get in shape, lose some weight, and have a couple more good years on the basketball court (plus take some weight off of my reconstructed knees)
    • Cook more at home
    • Get out of the house more often.  See Toni Price play this year before she retires altogether.
    • Catch a bass bigger than 1lb this year
    • Finish my book with enough time to spare so that I can reread the entire Wheel of Time series before A Memory of Light comes out!
  • StructureMap 2.5.1 is Released

    I just uploaded a new incremental release of StructureMap with a bunch of bugfixes and a few new features.  Download it here.

    From the release notes:

    * Fixed issue with With<T>(object).GetInstance<U>() functionality.  This is now much more robust.
    * Bug fix for Hybrid scoping
    * TryGetInstance() and TryGetNamedInstance(). 
    * Ignore setter emitting for indexer properties -- fixed a bug reported on the forum
    * Multithreading lock problem fixed by Josh
    * Patch for session lifetime.  There is now an option for "CacheBy(InstanceScope.HttpSession)"
    * Fixed Public IDictionary setter injection in xml : http://groups.google.com/group/structuremap-users/browse_thread/thread/21265544d73cd395?hl=en
    * Pete Johnson's fix for ObjectFactory.Configure() setting policy.  You can now set the scoping/lifecycle of a PluginType from Configure()
    * EjectAllInstances<T>() clears out Singleton objects now (and calls Dispose() if appropriate)
    * Josh has added an experimental debugger visualizer for StructureMap Container's

    * The AutoMocker isn't as whiny about RhinoMocks versions.  There is also an AutoMocker strategy for Moq now as well 

    * A minor performance enhancement that stops StructureMap from doing a scan of all types on the StructureMap assembly itself.

     

    Please send all questions to the StructureMap Google list.

     

    The Future

    I'm hoping to complete the new StructureMap website and documentation over the holidays, and that's the next priority.  After that, I'd like to get a new 2.6 release out in the early quarter of '09.  Here's what I'm thinking about in no particular order:

    1. A Silverlight ready version (i.e. a cutdown StructureMap)
    2. Finish the Mono support.  It's very close, but I want to make sure
    3. The *#%$ "BuildUp" functionality that allows you to do setter injection on an object that's created somewhere else.  Thank you ASP.Net.
    4. Convention based setter injection (low hanging fruit)
    5. A guarantee that StructureMap will function in partially trusted environments, or at least real guidance on what it can and cannot do
    6. "Missing Instance" handlers
    7. A "ConditionalInstance" that will give you easier ways to do conditional construction
    8. Improved diagnostics.  The error output and the output from StructureMapDoctor and ObjectFactory.AssertConfigurationIsValid() could be a lot better

    Now's a good time to ask for things.

     

    Ok, that's it for me this year.  Merry Christmas and Happy Holidays, and I'll see you in January.

     

     

  • In case you didn't already know this...

    If TestDriven.Net or the ReSharper test runner crater violently, you need to think about where you could be getting a StackOverflowException.

  • Improvements in the StructureMap AutoMocker

    Josh just checked some stuff into the trunk last night to address some versioning conflict issues we've had with RhinoMocks.  There is also an AutoMocker strategy for Moq as well.

  • My “Best Of” for 2008

    I haven’t been nearly as prolific a blogger as I used to be this year, so this one is going to be short.  Below is a list of my blog posts from the last year and change that I thought were the best.  Also check out:

     

    Oct. ‘07 – Dec ‘08

  • Design and Testability

    EDIT 12/23/2008:  I believe this post has been massively misconstrued in the comments.  Apparently, my analogy here was terrible from the way so many people are distorting what I was trying to say.  For the record, 

    I DID NOT SAY DON'T WRITE TESTS

    I DID NOT SAY YOU MUST BE A MASTER OF ALL DESIGN LORE BEFORE YOU GET TO WRITE A TEST

    I DID NOT SAY THAT YOU MUST HAVE A PERFECT, PURIST DESIGN FIRST

    I DID NOT SAY DO NOT WRITE TESTS FOR LEGACY CODE

     

    I said, or attempted to say, that testing and testability cannot be decoupled from design, and any effort towards automated testing / unit testing / TDD is probably not going to be successful until the team has a good understanding of the basics ( and I did say basics here) of fundamental software design.

     

    My most recent Patterns in Practice article entitled Design for Testability is available in this month's issue of MSDN Magazine. This time around, I tried to tackle some of the design issues around supporting testability.  I’ve written four articles so far for MSDN on design fundamentals.  If you look at the whole body of work, there’s a very common theme:  good, fundamental design is being able to do one thing at a time.  I want to decompose the system so that I can change one thing at a time with less risk of destabilizing other parts of the system.  I want to be able to understand one element of the system at a time.  I want to solve one little problem at a time instead of tackling the whole mess in one try. 

    Testability as a design concept is right in line with this kind of thinking.  Testability means being able to easily create rapid, effective, and focused feedback cycles against your code with automated tests.  Testability isn’t some strange and unnatural new way to shape code.  For the most part (ok, it might be if you cut your programming teeth with Microsoft’s RAD tools), Testability goes hand in hand with the same structural qualities like cohesion and coupling that we use to create code that’s easier to write, change, and understand.  On the other hand, we can use Testability within design techniques like Test Driven Development and/or Behavioral Driven Development to inform and help guide our design decisions.

     

    Unit Testing – Solid Design == PAIN!

    A couple months back Roy Osherove wrote a post entitled Unit Testing decoupled from Design == Adoption that posited the theory that things will work out better for the larger community if we drop all this hard design theory and TDD discipline and just get developers to write unit tests first.  The theory being that more developers would be more likely to adopt some sort of unit testing, fail, then naturally circle back to learning about design or try out TDD after they get started. 

    I couldn’t possibly disagree more with Roy on this.  I would describe Roy’s suggestion as akin to telling an out of shape 30 something with no prior athletic experience to start playing competitive basketball by just walking onto the court and getting into a pickup game.  That out of shape 30 something fellow isn’t going to be able to compete, and he’s likely to limp off too discouraged and humiliated to continue.  After all, why would the average person sign up for another beating?  Likewise, a developer with little foundational knowledge about good design principles will be very unlikely to succeed in any way with unit testing because it’ll be just too hard with poorly structured code (and no, I don’t think any “Isolation” framework will change that).  I would tell the 30 something to work on his cardiovascular conditioning (and his jumpshot) before he steps onto that basketball court for the first time.  I’d tell that developer to focus on his understanding (not rote knowledge, but understanding) of good design first and be ready to succeed upfront. 

    I guess to summarize and beat the analogy into the ground, cardiovascular health is beneficial for more than just playing pickup basketball after work and good design is valuable for more things than making unit testing and acceptance testing easier.  In short, good design is far more beneficial and important than the practice of unit testing.  However, good design + TDD/Behavioral Driven Development/Acceptance Test Driven Development?  That’s where the real rewards happen.  Don’t settle for mediocre efforts.  Do both and reap the rewards.

    A couple years ago I was reading some writing from older guys like Steve McConnell and Robert Glass that stated that Test Driven Development couldn’t work because unit testing was proven to be only marginal cost effective – and they based those statements on studies that dated back to COBOL developers in the ‘70s and ‘80s writing purely procedural code.  TDD with well factored OOP or Functional code compared to unit testing tightly coupled structured programming is apples and oranges.  I have consistently found that the cost effectiveness of unit testing and Test Driven Development is almost entirely based on the structural design of the class structure of the system being built. 

     

    Other Reading

    I think this is a huge topic, and one measly 3500 word article isn’t going to cover the topic adequately.  Learning xUnit tools and even mock object frameworks is a piece of cake compared to learning how to design and write code that enables efficient testing.  Here are some of my older writings from the time when I had just gotten over the hump and started to figure out how to compose code to enable Test Driven Development.

     

  • TDD Design Starter Kit: It’s All about Assigning Responsibilities
  • TDD Design Starter Kit - State vs. Interaction Testing
  • TDD Design Starter Kit - Dependency Inversion Principle
  • TDD Design Starter Kit – Responsibilities, Cohesion, and Coupling
  • TDD Design Starter Kit - Static Methods and Singletons May Be Harmful
  • Succeed with TDD by designing with TDD
  • Unit Testing Business Logic without Tripping Over the Database

     

  • Jeremy's First Rule of TDD
  • Jeremy's Second Law of TDD: Push, Don't Pull
  • Achieve Better Results by following Jeremy's Third Law of TDD: Test Small Before Testing Big - I think this is the most important lesson for making TDD work for you
  • Jeremy's Fourth Law of Test Driven Development: Keep Your Tail Short

     

  • Mock Objects and Stubs: The Bottle Brush of TDD
  • Why and When to Use Mock Objects
  • Best and Worst Practices for Mock Objects
  • Mock Objects are your Friend

     

  • Testing Granularity, Feedback Cycles, and Holistic Development

     

    The Future

    The next article is already in editing.  For February I’m discussing Ruby on Rails inspired design ideas like convention over configuration, opinionated software, sensible defaults, and once and only once.  For April I’m going to write about data access and persistence patterns to fit in with the theme of that month’s issue.  After that?

    • Patterns for Testability – I missed a lot of important topics in this month’s article.  I’d like to hit separated presentation patterns and Inversion of Control as a design pattern maybe.
    • Designing an Internal DSL
    • Some kind of post on Composition and IoC
    • Patterns for Client/Server Communication

    Any requests?  Thoughts?  I’m bypassing (D)DDD for the most part because there are articles on the way on those very topics from more qualified folks (Don’t tell anyone, but I’m not entirely sure I completely buy off on DDD).

     

    Self Reflection

    The first three articles in this series are effectively tributes to my software design heroes (Fowler, Rebecca Wirfs-Brock, Uncle Bob Martin, and the Pragmatic Programmers).  This last one was largely based on my own prior writings on testability and design.  It’s also the one I’m least happy with.  Back to hero tributes after this;)

     

  • I'm demo-ing StoryTeller online tomorrow night (10/10/08)

    Since Chad is putting me on the spot for this, I'll be doing a demo and leading a discussion on the StoryTeller reboot for the ALT.NET Online Open meeting tomorrow night.

    StoryTeller is my attempt at creating a new FIT analog for automated acceptance testing.  At this point, it's just the engine without any UI.  I will show how we're using StoryTeller so far at Dovetail.  Chad is recording the session for later as well.

    Here's a bit of example usage:  http://codebetter.com/blogs/jeremy.miller/archive/2008/10/27/a-quick-storyteller-update.aspx

  • I can respect a good riposte

    http://davesbox.com/archive/2008/12/09/quot-i-can-t-believe-microsoft-didn-t-make-enter-api-name-here-public-quot.aspx

    A.)  I'm a bit embarrassed by the backwards compatibility issue in StructureMap 2.5, but then again, breaking backwards compatibility cleaned a lot of crap up and made for a better user experience.  Most of the things I eliminated were features that probably did more harm than good.

    B.)  The ExpressionVisitor thing would be a very handy thing to have in the public with solid documentation.  How 'bout we just make that a feature request for the BCL team?

     

  • Stuff I do like

    So Brad Wilson basically said on Twitter today that I was being too negative.  Since that's like Debbie Downer asking you to be a little more upbeat, I thought I'd balance that with some stuff that I do like:

    • The new architectural guidance coming from Patterns and Practices.  I raised one huge objection and they quickly changed it . 
    • The general direction of xUnit.Net in regards to the no SetUp/TearDown thing, and that's not just a sop to Brad
    • The new AAA syntax and mocking style in both Rhino Mocks and Moq
    • Nate Kohari's approach to convention based setter injection in Ninject (I'm going to copy the idea into StructureMap)
    • Autofac's extensibility model (also going to copy some of that)
    • I really, really like getting patches for StructureMap, and I've got a couple to incorporate this week
    • Love the new language features in .Net 3.5.  I bitch about generics a lot, but that comes from pushing the envelope on usage and banging into edge cases.  It's really generics within Fluent Interface code that gives me the most heartburn, and that's not typical usage.
    • The magic of expressions, and Daniel Cazzulino for blazing a trail on using Expressions
    • The jQuery ecosystem.  And I thought Microsoft's official blessing and support for jQuery was huge
    • MassTransit (I think the new service bus tools like nServiceBus & MassTransit basically become a sort of a "Distributed IoC" tool
    • Linq to NHibernate and Linq in general of course
    • The more powerful auto mapping and convention support in Fluent NHibernate (I didn't write that part)
    • Bellware's SpecUnit assertion extensions
    • The fluent fixture stuff we stole from the Eleutian guys
    • The way P&P did the Prism project out in the open
    • The common service locator initiative
    • The way MS is doing the MVC project out in the open
    • The fact that MS does much more to acknowledge the value of Separated Presentation patterns and encourage their usage than they did just a few years ago
    • The fact that MEF is open sourced
    • The fact that MEF exists I think will help open up and decouple the BCL in some advantageous ways.  I think DI-friendly code will make it easier for us to use better composition based design instead of nasty inheritance structures
    • Yes, I gripe about some details of the MVC, but I made some huge, valuable customizations to our MVC pipeline in the past two days that were possible because the MVC classes are pretty cohesive and well structured
    • Basically any tool written by JetBrains
    • JP's keyboard macro stuff for BDD
    • I do like the general concept behind StackOverflow, I'm just dubious about the veracity and wisdom of some of its content
    • Auto Mockers and InteractionContext base classes that make interaction style unit tests much easier than a few years ago
    • Rake as a build tool
    • Rob Conery's MVC Storefront podcasts
    • The HerdingCode podcasts
    • Elegant Code and Los Techies as blogging communities
    • You have to look for it a bit, but the fact that many more .Net authors/INETA speakers/gurus from outside the little ALT.NET echo chamber are addressing design fundamentals and unit testing concerns in their writing and speaking.  Don't read any sarcasm or anything negative into that, I really do think it's a good thing because those folks have much more reach.  I'm thinking specifically about some recent MSDN articles
    • The fact that we're finally getting some well supported alternative languages for .Net.  VB.Net and C# are essentially Country and Western.  F#, IronRuby, and IronPython gives us Jazz, Blues, and Opera.
    • I was surprisingly impressed with Dino Esposito's latest book on .Net architecture
    • The DotNetRocks guest list.  Yes, I tend to grumble at some of things that get said on DNR a fair amount, but it's astounding that they've gotten so many of my heros to come onto the show in the last couple months
    • Ben Scheirman's new fluent API for testing routes in MVC
  • I love Ayende (and OSS)

     From one of Ayende's many OSS projects.

        /// This class actually already exists in the System.Core assembly...as an internal class.

        /// I can only speculate as to why it is internal, but it is obviously much too dangerous

        /// for anyone outside of Microsoft to be using...

    And dear MS BCL team, since so many people are already using Reflector to go get the ExpressionVisitor code, would you just make this public?  'K, thx.

  • Question of the Day -- What's Worse?

    From Twitter yesterday, I was griping about how once you use a Generics Constraint once and suddenly that same constraint has to immediately ripple through the call stack.  Scott Allen posed me a stumper of a question:

    What's worse: generic constraints, or checked exceptions [in java]?

    Oh wow, that's a nasty choice.  Can I have neither?  I'd call both things Noise Code.  Smelly, useless, noise code.

    • Generics Constraints:  90% of the time it's just to make the compiler shut up and let my code work.  Dear C# team, could you deemphasize all the COM interop work in C# and making C# do kloogey dynamic typing, and GIVE ME FAR BETTER TYPE INFERENCE ON GENERICS SO I CAN GET SOMETHING DONE (contra/covariance makes your little academic hearts go pitter patter, but that won't really help me much)!!!!!    Anyway, ReSharper can mostly figure out how to propogate the generic constraints, but it gets confused easily and sometimes the constraints will conflict and...  Human intervention is usually necessary.  Andy Sherwood calls this  "the where tentacles."  Nice.
    • Checked Exceptions.  Much more pervasive, but IntelliJ can handle adding the "throws blah" stuff without any trouble.  The problem is that checked exceptions are so much more common and pervasive.  Needless to say, I don't find checked exceptions to be the slightest bit useful.
    I guess I'd rather live with the generics constraints than waste time with checked exceptions.  Now, keep checked exceptions out of the language, give me F#/OCaml style type inference instead of a nanny compiler (are you sure it's okay for this object to do this?  Confirm or deny), and make ALL methods and properties virtual by default, and I'm  a happy camper.  If I want dynamic typing, I'll use IronRuby.  If I need office integration, I'll get a contracter to write VB.Net.

     

  • A Gentle Quickstart for StructureMap 2.5

    The most general question I get with StructureMap is “how do I get started?”  Personally, I’d recommend that you first get comfortable with some concepts and the basic patterns of Dependency Injection and Inversion of Control first.  Assuming that you’re already familiar with those concepts, or you’d really rather skip the pedantry and jump right into concrete code, the first thing to do is go download StructureMap and jump into usage (then come back to the patterns and pedantry). 

    Some Salient Facts:

    • The latest release is 2.5.0.0, available for download on SourceForge at http://sourceforge.net/projects/structuremap
      • The only DLL that you need for doing basic Service Locator and/or Dependency Injection is the StructureMap.DLL file.
    • There is a google group for StructureMap support at http://groups.google.com/group/structuremap-users?hl=en
    • StructureMap is released under the Apache 2.0 license, meaning that you can use it in any application or even modify the source in any way you see fit without restriction.
    • StructureMap is actually the oldest, original IoC tool for .Net with the first production release coming in June of 2004
    • I’m no longer the only person maintaining StructureMap
    • The source code is accessible here via Subversion in case you’re curious.  No credentials are required to access the source code.
    • Right now, StructureMap 2.5 will run on .Net 3.5 only.  I will most likely NOT be backporting the new version to 2.0 because of extensive usage of 3.5 features like Expressions
    • I swear that StructureMap 2.5 will run in medium trust on .Net 3.5 – but please post any problems that you do find with medium trust.
    • A 2.5.1 release is planned for the first week of December with bug fixes, a few new little features, Mono support, and a Silverlight-ready version (it’ll be a subset of the main library).

     

    The Simplest Possible Usage of StructureMap

    Your interaction with StructureMap is going to mostly consist of two activities:

    1. Asking StructureMap for an instance of a service or dependency (the easy part)
    2. Registering “what” and “how” StructureMap should build or find those requested services (the tedious part, but it’s gotten much better over the years)

    In our system we use a service called “IValidator” to exercise validation rules on our domain model objects (I talked about the approach here).  By default, we want any consumer of the IValidator interface to use the concrete class named Validator.  Since we use StructureMap for resolving dependencies and services, we need to first tell StructureMap to use Validator anytime somebody asks for an IValidator.  You configure StructureMap by initializing the container with this code below:

        public static class ContainerBootstrapper

        {

            public static void BootstrapStructureMap()

            {

                // Initialize the static ObjectFactory container

                ObjectFactory.Initialize(x =>

                {

                    x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

                });

            }

        }

    Now that that code is called somewhere in the application initialization, we can get an IValidator object from StructureMap like in this sample code by calling ObjectFactory.GetInstance<IValidator>():

        public class ClassThatGetsAnIValidator

        {

            public void SaveObject(object objectToSave)

            {

                // Go get the proper IValidator from StructureMap

                IValidator validator = ObjectFactory.GetInstance<IValidator>();

     

                var notification = validator.Validate(objectToSave);

                if (notification.IsValid())

                {

                    // save the object

                }

            }

        }

    That’s it, your first usage of StructureMap.  No messy Xml configuration, no attributes scattered through your code, just a couple lines of bootstrapping code.   Of course, if that’s all StructureMap did, it wouldn’t be worth your time to download it.  Let’s look at a bit more advanced example.

     

    Primitive Arguments

    I actually like to use StructureMap as a generic configuration tool (which was actually its original purpose).  Let’s say you’re moving to the data access code.  You come up with some sort of Repository pattern class like this:

        public interface IRepository

        {

            void Save(object target);

        }

     

        public class Repository : IRepository

        {

            public Repository(string connectionString)

            {

                // set up the persistence infrastructure using the connectionString

                // from the constructor argument

            }

     

            public void Save(object target)

            {

                // save the object

            }

        }

    The Repository class needs to be supplied with the “connectionString” in its constructor.  No problem, just set up the value of the constructor argument in the bootstrapping:

                ObjectFactory.Initialize(x =>

                {

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                        .WithCtorArg("connectionString").EqualTo("a connection string");

     

                    // Or, since it's smelly to embed a connection string directly into code,

                    // we could pull the connection string from the AppSettings

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                        .WithCtorArg("connectionString").EqualToAppSetting("CONNECTION-STRING");

                });

    With the bootstrapping out of the way, when we ask StructureMap for an IRepository in this code:

                var repository = ObjectFactory.GetInstance<IRepository>();

    StructureMap will look up the “CONNECTION-STRING” value in the AppSettings portion of the App.config file, and use that string value to invoke the constructor function of the Repository class, then hand back that new Repository object.  Woo hoo.  We can build an object that doesn’t depend on anything, and we can build an object that needs some strings in its constructor function.  How about objects that need other non-primitive objects?

     

    Auto wiring

    In the code samples above, I used StructureMap as a Service Locator in the ClassThatGetsAnIValidator.SaveObject() method.  Typically, you’ll try to minimize the number of service locator usages in your system to a bare minimum (I found 8 in my current system, but I think I’ll find a way to prune half of those later).  Most of the value of an IoC tool is in automatically doing Dependency Injection.  I’m working with the new MVC framework at the moment, so it’s a handy sample.  Let’s say that we have a Controller class for a typical CRUD screen.  That Controller class will generally need to interact with both validation services and the data access functionality of the Repository.  Here’s a representative Controller class:

        public class SomeScreenController : IController

        {

            private readonly IRepository _repository;

            private readonly IValidator _validator;

     

            // SomeScreenController depends on both IRepository and IValidator

            public SomeScreenController(IRepository repository, IValidator validator)

            {

                _repository = repository;

                _validator = validator;

            }

     

        }

    So let’s get StructureMap set up for this SomeScreenController class:

                ObjectFactory.Initialize(x =>

                {

                    // Set up the IValidator

                    x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

     

                    // Set up the IRepository

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                        .WithCtorArg("connectionString").EqualToAppSetting("CONNECTION-STRING");

                });

    You’ll notice that we didn’t make any explicit configuration for the SomeScreenController class, but yet we could now call:

               var controller = ObjectFactory.GetInstance<SomeScreenController>();

    and StructureMap will happily create a new instance of the SomeScreenController class by invoking its constructor and passing in a new Validator object and a new Repository object created with the connection string from the App.config file.  We didn’t need to tell StructureMap how to construct SomeScreenController because:

    • StructureMap can look at the constructor function of SomeScreenController and see that it depends on IValidator and IRepository
    • StructureMap “knows” about the default way to create and return an IValidator and an IRepository

    This feature is known as “auto wiring,” and all the mainstream IoC containers support this to some extent or another. 

     

     

    What to do when things go wrong?

    StructureMap, and any other IoC tool for that matter, is configuration intensive – which means that their will be problems in that configuration.  We’re all moving to more convention based type registration – which means that more stuff is happening off stage and out of your sight, making debugging the configuration even trickier.  Not to worry (too much), StructureMap has some diagnostic abilities to help you solve configuration problems.  The quickest tool is to ask a Container object or ObjectFactory (which is just a static wrapper around a Container) “what do you have?” with the Container.WhatDoIHave() method like this below:

                var container = new Container(x =>

                {

                    x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

     

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                        .WithCtorArg("connectionString").EqualToAppSetting("CONNECTION-STRING");

                });

     

     

                Debug.WriteLine(container.WhatDoIHave());

    Which would spit out this text into your output window:

    ===========================================================================================================
    Configuration Sources:
    
    0)   Registry:  StructureMap.ConfigurationExpression,StructureMap
    
    
    ===============================================================================================================================================================================================================================================================================================================================
    PluginType                                                                                                                Name                                                                                                 Description                                                                                     
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ShadeTree.Validation.IValidator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null                         ShadeTree.Validation.Validator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null     ShadeTree.Validation.Validator, ShadeTree, Version=0.8.0.0, Culture=neutral, PublicKeyToken=null
    Built by:  StructureMap.Pipeline.BuildPolicy
    
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    StructureMapSample.IRepository, DovetailCRM.IntegrationTesting, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null     27fdf13e-8adc-4f8f-9f53-cf7b35ada80c                                                                 Smart Instance for StructureMapSample.Repository                                                
    Built by:  StructureMap.Pipeline.BuildPolicy
    
    ===============================================================================================================================================================================================================================================================================================================================

    which is admittedly, not the prettiest looking thing in the world.

    You can also “assert” that the configuration for a Container or ObjectFactory is complete by calling the Container.AssertConfigurationIsValid() method like this sample below:

                var container = new Container(x =>

                {

                    x.ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();

     

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>()

                        .WithCtorArg("connectionString").EqualToAppSetting("CONNECTION-STRING");

                });

     

     

                container.AssertConfigurationIsValid();

    This method will analyze every thing in the Container configuration and:

    1. Look for any missing constructor or mandatory setter arguments
    2. Look for any unknown dependency types
    3. Look for any errors in the Xml configuration (if you’re using Xml configuration)
    4. Try to build each and every type and named instance in the configuration – i.e. this is a complete, but relatively expensive operation
    5. Run any environment tests configured with the [ValidationMethod] attribute (a feature that is unique to StructureMap as far as I know)

    The previous sample is a valid configuration, but let’s look at an invalid configuration.  Let’s omit the configuration of the “connectionString” constructor argument for the Repository class and try AssertConfigurationIsValid():

            [Test]

            public void lets_see_if_the_container_is_valid()

            {

                var container = new Container(x =>

                {

                    x.ForRequestedType<IRepository>().TheDefault.Is.OfConcreteType<Repository>();

                        //.WithCtorArg("connectionString").EqualToAppSetting("CONNECTION-STRING");

                });

     

     

                container.AssertConfigurationIsValid();

            }

    When I run the unit test above, this is part of the output:

     

    Build Error on Instance '73b7f21b-bbfd-462c-854d-5b2a2f98ba50' (Smart Instance for StructureMapSample.Repository)
        for PluginType StructureMapSample.IRepository, DovetailCRM.IntegrationTesting, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null
    
    StructureMap.StructureMapException: StructureMap Exception Code:  205
    Missing requested Instance property "connectionString" for InstanceKey "73b7f21b-bbfd-462c-854d-5b2a2f98ba50"

     

    which again, isn’t the prettiest thing in the world, but it does tell me that the “connectionString” argument is missing for the Repository class.  After seeing this output, I think that this output and error wording will get improved in an upcoming release.

     

     

    Why are you still rolling your own IoC tool?

    Something that bothers me pretty is when I see bloggers frequently say that “StructureMap/Windsor/Ninject/Unity/Spring.Net/Autofac” is way too heavy for my project, so I just rolled my own.  Why?  Why would you do that?  Bootstrapping StructureMap for the very simplest cases, i.e. the only cases you can handle with the “roll your own IoC container in 30 lines of code solution,” takes 1 line of code for the call to ObjectFactory.Initialize() plus another line of code for each individual type.  

     

    Related Links:

    By no possible means was this a complete guide to using StructureMap or IoC tools in general.  Try these other links for more on StructureMap:

  • Agile .Net Developer Opportunity in Atlanta

    My friend and former colleague Paul Gale is looking to build a strong Agile .Net team in Atlanta.  If you're interested, here are the details from the man himself:

    • I am looking to build a team of up to 6 (including myself) experienced agile .NET developers by the end of 2009.  However, we're trying to hire in a more opportunistic mode, i.e., if a decent developer is available we'll take a look at them, rather than spread it out just to fit a hiring program.
    • The company is called Cint. We're HQ'd in Stockholm (It will be easier to explain the exact relationship between the Atlanta dev group and our Stockholm dev group to candidates directly).
    • Candidates should have a strong background in TDD ideally in an XP environment. We'll be pairing too.
    • More to the point this is NOT the type of position where someone who fancies trying their hand at TDD, say, should apply. You will be tested!  We're looking for strong players who will bring their game with them.
    • Skills aren't everything though; they must be a good social fit for the team that's already in place.
    • We're currently renting space in downtown Atlanta. However, we're looking to move very soon to Alpharetta, GA close to G400.  (Local folks will know what that means. Others can ask).

    See http://www.cint.com/Cpx/About.aspx for more details.

More Posts Next page »

Our Sponsors

Proudly Partnered With