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
  • My Topic Proposals for ALT.NET Seattle '09

    ALT.NET Seattle is 6-7 weeks away, but it's not too early to think about what we want on the agenda. I enjoyed KaizenConf, but I'm looking forward to skewing the sessions back toward more technical content. 

    My Topics:

    • Using Language Oriented Programming in .Net
    • Convention over Configuration in Real World .Net Projects and Tools 
    • Wringing more productivity out of MVC web development
    • Open Source alternatives to WF and WCF (or at least tools that aid in WCF usage)
    What's yours?

     

     

  • Choosing the Constructor Function in StructureMap without Attributes

    A longstanding complaint with StructureMap is that the way StructureMap selects a constructor function can only be overridden with an attribute.  Using attributes is now frowned upon, and other times is impossible.  StructureMap 2.5.2 (the version in the trunk that, knock on wood, I get released no later than Saturday) introduces a quick programmatic way to select the constructor function using the magic of Expressions.  This is an excerpt from the new StructureMap documentation I’m working up.  It will be much more readable on the website (next week hopefully):

     

     

    StructureMap has always allowed you to override the constructor choice with an attribute, but increasingly, many people are unwilling to use attributes in their code for infrastructure concerns.  Other times you may want to override the constructor choice of a class that you don't control.  Either way, it would be useful to select the constructor function used by StructureMap to build a concrete code in the Registry DSL.  The syntax to do just that is shown below:

    Let's say that you have this class (from the unit tests):

        public class ClassWithTwoConstructors

        {

            public ClassWithTwoConstructors(int age, string name)

            {

            }

     

            public ClassWithTwoConstructors(int age)

            {

            }

        }

    By default, StructureMap would choose the "greediest" constructor.  In this case, it would be the constructor that takes in "age" and "name."  To force StructureMap into using the other constructor, use the SelectConstructor() method on the Registry:

                var container = new Container(x =>

                {

                    x.SelectConstructor<ClassWithTwoConstructors>(()=>new ClassWithTwoConstructors(0));

                    x.ForConcreteType<ClassWithTwoConstructors>().Configure

                        .WithCtorArg("age").EqualTo(34);

                });

    The argument to the SelectConstructor is an Expression of type Expression<Func<T>> where T is the concrete class.  StructureMap parses the Expression to find the constructor function in the Expression object.

  • A Challenge to the VB.Net Community at Large on OSS

    I had a 3-4 way Twitter conversation with Roy Osherove today that left me hot under the collar even several hours later.  The conversation basically played out like this:

    1. Roy:  Boo hoo, new .Net OSS projects are using advanced features in C# that might make those tools hard to use in VB.Net
    2. Me:  Maybe, but I'm optimizing the user experience of these tools for C#.  I'm not going to sacrifice user experience in favor of a little extra reach.  Besides, VB.Net devs are a very small percentage of OSS users.
    3. Roy:  Jeremy is an anti-VB bigot!  Who's with me VB guys?  VB guys can't use or participate in OSS because they're actively turned away by guys like Jeremy!

    and then Roy proceeded to present himself as the champion of all those poor dispossessed VB.Net developers with some cheap theatrics.

     

    To you Mr. VB.Net Dev:

    Stand up if you don't like the way things are.  I have never once gotten any kind of specific suggestion about how to make StructureMap more palatable for VB.Net usage.  I've gotten complaints, and some questions (which I have answered), but not one single specific suggestion or patch that I recall.  Mr. VB.Net developer, if there's something you want or lack in an OSS framework that would make it easier/better to use that tool with idiomatic VB.Net, you know who's probably most qualified and able to write that patch?  You are!  I don't write software in VB.Net, and haven't used VB.Net in anger since .Net was in and early beta.  I'm not going to get VB.Net idioms, and I don't have visibility into VB specific issues.

    And you know what?  There isn't a major OSS project on earth that doesn't like getting patches.  I would love to get real, useful contribution from the VB.Net community in regards to an improved user experience with StructureMap -- but I'm not going to pay attention to empty complaints, and I'm certainly not putting up with vilification.

    I'll go a step farther, give me a usable patch for StructureMap for better VB.Net usage, and I'll have it released within 48 hours on Sourceforge.

    Actually, now that I'm a bit calmer, take this to heart.  OSS projects are owned by the community -- meaning that you can pick up the reins and do something about a tool that lacks something you need or want.  Don't be passive.  Heck, you could even write your own.  You don't think that OSS projects are a friendly place for VB'ers?  Start your own and make the .Net ecosystem even richer.  Hell, it's not rocket science after all.

    And p.s,. you really need to get the VB.Net team to give you multiline Lambda functions in the next version of VB.  Trust me, once you have them, you'll never want to code in a language that lacks them ever again.

     .



     

  • AutoWiring in StructureMap 2.5+

    Getting the StructureMap docs a going.  Here’s an excerpt:

     

     

    The best way to use an IoC container is to allow "Auto Wiring" to do most of the work for you.  IoC Containers like StructureMap are an infrastructure concern, and as such, should be isolated from as much of your code as possible.  Before examining Auto Wiring in depth, let's look at a common anti pattern of IoC usage:

    IoC Container Anti-Pattern

    One of the worst, but sadly  most common, usages of an IoC container is shown below:

            // This is the way to write a Constructor Function with an IoC tool

            // Let the IoC container "inject" services from outside, and keep

            // ShippingScreenPresenter ignorant of the IoC infrastructure

            public ShippingScreenPresenter(IShippingService service, IRepository repository)

            {

                _service = service;

                _repository = repository;

            }

     

            // FAIL!

            // This is the wrong way to use an IoC container.  Do NOT invoke the container from

            // the constructor function.  This tightly couples the ShippingScreenPresenter to

            // the IoC container in a harmful way.  This class cannot be used in either

            // production or testing without a valid IoC configuration.  Plus, you're writing more

            // code

            public ShippingScreenPresenter()

            {

                _service = ObjectFactory.GetInstance<IShippingService>();

                _repository = ObjectFactory.GetInstance<IRepository>();

            }


    Example

    Typically, you’ll try to minimize the number of Service Locator (Container.Get*****) 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 feature to some extent or another. 


    StructureMap's Policies for Auto Wiring

    By default, as long as an object is being created by invoking its constructor function, StructureMap will try to create/resolve/find an object for each non-primitive dependency in the requested concrete type.  If StructureMap doesn't "know" how to find a requested dependency, it will throw an exception.  By design, StructureMap cannot auto wire primitive arguments like strings and numbers.  The Auto Wiring can be overriden by explicit configuration (this might actually be easier with Xml configuration):

                    registry.InstanceOf<Rule>()

                        .Is.OfConcreteType<WidgetRule>()

                        .WithName("TheWidgetRule")

                        .CtorDependency<IWidget>().Is(i => i.TheInstanceNamed("Yellow"));

    In the example above, the IWidget dependency of the WidgetRule class is overriden.


    Object Identity within a Single Request

    Within a single object request, StructureMap will only create a single object for a single Instance configuration.  What that means in effect is that if two or more objects in a single request need the same dependency, those two objects will get the exact same instance of that dependency.  Let's immediately jump into code to demonstrate this.

    This auto wiring policy was intended for objects that need to be shared by lots of other objects.  A common example of this is some sort of DataContext class:

            public class DataContext

            {

                private Guid _id = Guid.NewGuid();

     

                public override string ToString()

                {

                    return string.Format("Id: {0}", _id);

                }

            }

    Now, let's say that I have a hierarchy of classes that all need to work on a DataContext:

            public class Class1

            {

                public Class1(DataContext context){}

     

                public override string ToString()

                {

                    return string.Format("Class1 has Context: {0}", _context);

                }

            }

     

            public class Class2

            {

                public Class2(Class1 class1, DataContext context) {}

     

                public override string ToString()

                {

                    return string.Format("Class2 has Context: {0}\n{1}", _context, _class1);

                }

            }

     

            public class Class3

            {

                 public Class3(Class2 class2, DataContext context) {}

     

                public override string ToString()

                {

                    return string.Format("Class3 has Context: {0}\n{1}", _context, _class2);

                }

            }

    When you request an object of Class3 with a call to Container.GetInstance<Class3>() like this:

            [Test]

            public void demonstrate_session_identity()

            {

                var class3 = container.GetInstance<Class3>();

                Debug.WriteLine(class3);

            }

    The output is:

    Class3 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f
    Class2 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f
    Class1 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f

    In the sample above, when we write out the Class3, Class2, and Class1 objects to Debug.WriteLine, we find that each of these objects have a reference to the same DataContext. If we were to run this test again, the output might be:

    Class3 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7
    Class2 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7
    Class1 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7

    We see the exact same behavior, but it was a different object instance of DataContext for the new object graph.

    This behavior also applies to objects passed in to the Container as an explicit argument:

            [Test]

            public void demonstrate_session_identity_with_explicit_argument()

            {

                DataContext context = new DataContext();

                Debug.WriteLine("The context being passed in is " + context);

     

                var class3 = container.With(context).GetInstance<Class3>();

                Debug.WriteLine(class3);

            }

    The output of this unit test is:

    The context being passed in is Id: 87ddccfd-a441-41fd-a86d-3f32987496ba
    Class3 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba
    Class2 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba
    Class1 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba

    The point of the sample above is just to show that the object instance of DataContext passed into the Container is used to create the Class3, Class2, and Class1 objects.


    Injecting Arrays of Services

    StructureMap has always supported Dependency Injection of arrays of dependency objects.  New in StructureMap 2.5+ is a policy that if any array of dependencies is not explicitly specified, StructureMap will inject all possible instances of that dependency type.  The sample below illustrates this auto wiring policy.  I have a class called "ClassThatUsesValidators" that needs an array of IValidator objects.  Below, I've configured two different Instances of ClassThatUsesValidator, one that explicitly configures its children IValidator and another Instance that is just going to let auto wiring inject the IValidator's.

        public interface IValidator

        {

        }

     

        public class Validator : IValidator

        {

            private readonly string _name;

     

            public Validator(string name)

            {

                _name = name;

            }

     

            public override string ToString()

            {

                return string.Format("Name: {0}", _name);

            }

        }

     

        public class ClassThatUsesValidators

        {

            private readonly IValidator[] _validators;

     

            public ClassThatUsesValidators(IValidator[] validators)

            {

                _validators = validators;

            }

     

            public void Write()

            {

                foreach (IValidator validator in _validators)

                {

                    Debug.WriteLine(validator);

                }

            }

        }

     

        [TestFixture]

        public class ValidatorExamples

        {

            private Container container;

     

            [SetUp]

            public void SetUp()

            {

                container = new Container(x =>

                {

                    x.ForRequestedType<IValidator>().AddInstances(o =>

                    {

                        o.OfConcreteType<Validator>().WithCtorArg("name").EqualTo("Red").WithName("Red");

                        o.OfConcreteType<Validator>().WithCtorArg("name").EqualTo("Blue").WithName("Blue");

                        o.OfConcreteType<Validator>().WithCtorArg("name").EqualTo("Purple").WithName("Purple");

                        o.OfConcreteType<Validator>().WithCtorArg("name").EqualTo("Green").WithName("Green");

                    });

     

                    x.ForRequestedType<ClassThatUsesValidators>().AddInstances(o =>

                    {

                        // Define an Instance of ClassThatUsesValidators that depends on AutoWiring

                        o.OfConcreteType<ClassThatUsesValidators>().WithName("WithAutoWiring");

     

                        // Define an Instance of ClassThatUsesValidators that overrides AutoWiring

                        o.OfConcreteType<ClassThatUsesValidators>().WithName("ExplicitArray")

                            .TheArrayOf<IValidator>().Contains(y =>

                            {

                                y.TheInstanceNamed("Red");

                                y.TheInstanceNamed("Green");

                            });

                    });

                });

            }

     

            [Test]

            public void what_are_the_validators()

            {

                Debug.WriteLine("With Auto Wiring");

                container.GetInstance<ClassThatUsesValidators>("WithAutoWiring").Write();

                Debug.WriteLine("=================================");

                Debug.WriteLine("With Explicit Configuration");

                container.GetInstance<ClassThatUsesValidators>("ExplicitArray").Write();

            }

        }

    The output of what_are_the_validators() is:

    With Auto Wiring
    Name: Red
    Name: Blue
    Name: Purple
    Name: Green
    =================================
    With Explicit Configuration
    Name: Red
    Name: Green

  • 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
More Posts Next page »

Our Sponsors

Proudly Partnered With