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

January 2008 - Posts

  • Jeremy hearts C# 3.0

    Never let it be said that I can't say something nice about a Microsoft product.  I'm not enthusiastic about VS2008 itself until ReSharper 4.0 is here and stable, but the new language features rock!  I haven't even touched any of the LINQ dialects yet, but all those little features that Anders and co added to support LINQ are already making my life easier.

    • Extension Methods:  I'm mostly using Bellware's nunit-spec extensions for RSpec-style assertions in unit tests like someObject.SomeMethod().ShouldEqual(expected);  I've also used them very sparingly to extend a fluent interface from an external assembly.  It's working, but let's call that an experiment in progress
    • Object Initializers:  These make test data setup code soooo much more compact.  Especially the initializers for collections.  As silly as it sounds, I'd almost call this the single best thing about .Net 3.5 just because of the mechanical savings.
    • Lambda Expressions:  Besides being so much tighter than anonymous delegates, I'm digging the ability to get at the expression tree.  My old MicroControllers idea in C# 3.0 looks like this:  _binder.Bind(x => x.QuoteDate).To(quoteDateField).WithLabel(quoteDateLabel);  See the little Lambda trick in bold?  Gotta love the compiler safe reflection goodness.  The tighter syntax is also making it easier to utilize some functional-lite programming that cuts down on code here and there.
    What do you like about C# 3?  What are you doing that wasn't possible in C# 2?
  • I've got the Iteration #1 Blues

    I saw somebody else complaining about how rough iteration 1 is.  Experience has taught me to be very, very pessimistic about how much recognizable business value gets created in Iteration #1, but I'm still surprised by how slow it's going for me.  It's exhausting because everything you do you're doing for the very first time.  It's like an iceberg.  You're setting up a lot of development ecosystem and infrastructure below the surface just to get that first dram of business functionality peeking out above water where the non-developers can see progress. 

    Progress is also slow in early iterations because the ratio of design time to code is much higher than any other time in the project.  I think that if you were able to chart the productivity of a development team through the first couple iterations you'd see an S-curve.  Productivity rises very slowly, then suddenly hits an inflection point and darts upwards before hitting a second inflection point and settling into a plateau.  That first inflection point is what I think of as the "this is the way we do it" moment -- that magical moment where the team understands how the pieces fit together and has the answers for the most common development tasks.  At this point it's a matter of how fast you can work.  My goal as the team lead is to get to the "this is the way we do it" moment as quickly as possible.

    Iteration 1 is critical because I think early momentum is so crucial to the success of a project.  All of the best projects I've been on started very strongly out of the gates.  The projects where things were muddled early on never completely recovered.  I've always thought that one of the advantages of Agile processes is simply being able to feel momentum so much earlier instead of slogging through extended upfront analysis and design phases.

    It's important to work purposely, but I don't want to cut corners on the development ecosystem because I think there's so much efficiency to be gained from solid project automation.  I don't want the code to get too far ahead of the infrastructure because you never really stop to retrofit things later.  To that end, just to do a couple story points worth of work, I've had to:

    1. Create a Subversion repository
    2. Set up a code tree, and downloaded or installed all the tools we're going to use for now
    3. Create a build script (Rake)
    4. Install and configure CC.Net and CCTray
    5. Installed Mingle and entered the first batch of stories.  I know there are some performance problems, but it's been a joy to work with so far.
    6. Figuring out how I want to organize unit tests, and how to incorporate more BDD elements to write better tests -- excuse me, specifications. 
    7. Getting used to using an "AutoMocking Container" to make interaction tests a bit more readable
    8. Created a DataMother to put together object structures in unit tests
    9. Started creating a StoryTeller infrastructure this morning to express acceptance tests.  I desperately want automated "executable requirements" from day one and unfortunately, I still think Fit style tests are the best answer in the .Net world.  At least until IronRuby is ready enough to use RBehave on .Net code.
    10. Figured out how the StructureMap configuration would be bootstrapped in the application
    11. Figured out how I could run the app in "Stubbed" mode sans database and build the stubs.  I've often found it useful to run the GUI without any backend to deal with UI coding.
    12. Build out an ApplicationShell, ApplicationController, IPresenter interface, and basic screen activation code.  I'm trying to avoid BDUF, but it's leaking in anyway.
    13. Get used to a different set of 3rd party controls.  Collectively, the worst API's ever created by man.  Note that I'm not being specific about any particular control maker, because they're all bad!
    14. I haven't even touched NHibernate usage or configuration management and build processes for the database, but it's coming soon
    15. Write a coding standard (TODO)
    16. Extend the build so that my tester and customer proxies can retrieve a numbered build at any time (TODO)

     

    I might be bordering on a new development Antipattern, "Big Infrastructure Upfront."  But then, like a ray of light, I was suddenly able to just write code.  With the Super Bowl coming up, there's a football related analogy I like to make:  "Broken Field Coding."  The ability to code without impediment because you've got what you need, the tooling is right we're you need it, and the only thing you have to do is sprint for all your worth.

    Anyway, here's looking forward to the smoother iterations ahead.  And ReSharper 4.0.

  • Interception techniques in StructureMap 2.5

    The 2.5 release of StructureMap is at least 6 weeks away, but I'd like to throw some more stuff out to get some feedback while I've got plenty of time to deviate.  I'm building in much more interception capabilities into StructureMap to support runtime AOP and other scenarios.  I don't have a good background in AOP, so I'm guessing as much as anything about what I need.  Here's a rundown of what I've got so far.  The code is targeted to .Net 2.0.  My plan is to release for 2.0, then immediately turn around and do a .Net 3.5 release.  So please mentally substitute in lambda expressions for the anonymous delegates.  All of this code is in the StructureMap trunk, and I'm running my development project off of the current revision.

     

    Intercept a particular instance being created

    When a particular instance is created you want to do something with that instance before it's returned from StructureMap.  The configuration code is below:

     

                registry.ForRequestedType<IService>()
                    .AddInstance(
                    Instance<IService>().UsingConcreteType<ColorService>()
                        .OnCreation<ColorService>(delegate(ColorService s) { _lastService = s; })
                    );

    You just pass a delegate or lambda expression to the OnCreation() method like this:

        public delegate void StartupHandler<T>(T target);

    I envision this being used mostly to run extra bootstrapping or register objects with event brokers.  Now, if you want to enrich the object with some sort of runtime AOP or wrap it with a decorator, you would do this:

     

                registry.ForRequestedType<IService>()
                    .AddInstance(
                    Instance<IService>().UsingConcreteType<ColorService>()
                        .EnrichWith<IService>(delegate(IService s) { return new DecoratorService(s); })
                    )

     

    Again, you just pass in a delegate or lambda into the EnrichWith() method, but this time you're required to return an object.  The delegate signature is this:

        public delegate T EnrichmentHandler<T>(T target);

    It might be tedious to define these handlers per instance, so let's move on to broader categories.

     

    Intercept every instance of a requested type

    It's basically the same mechanics, except that you register the EnrichmentHandler or StartupHandler on the ForRequestedType<T> (BuildInstancesOf<T>) expression like these examples:

                _registry.ForRequestedType<IService>()
                    .OnCreation(delegate(IService s) { _lastService = s; })
                    .AddInstance(
                    ConstructedBy<IService>(delegate { return new ColorService("Green"); })
                        .WithName("Green"))
                    ;
     
     
                _registry.ForRequestedType<IService>()
                    .EnrichWith(delegate(IService s) { return new DecoratorService(s); })
                    .AddInstance(
                    ConstructedBy<IService>(delegate { return new ColorService("Green"); })
                        .WithName("Green"))
                    ;

     

    The first snippet directs StructureMap to execute a delegate against every new instance of IService created.  The second snippet would give you the ability to replace any new instance of type IService created with an enriched type or decorator.

    All of these examples so far have worked on an object created by StructureMap shortly after it was created.  Now, what if you want to intercept the request itself and return something entirely different depending on circumstances?  For a couple years, StructureMap has an extensibility mechanism called an InstanceFactoryInterceptor that acts much as an IHttpModule in ASP.Net to decorate the normal InstanceFactory object that builds a given family of instances.  I've used that mechanism to create the "scoping" feature that allows you to make instances either singleton's or thread local or HttpContext specific.  As I said, it's been a feature for awhile, but never documented and got cut from the original release of the fluent interface.  I'm fixing that with the 2.5 release like so:

                AnInstanceFactoryInterceptor factoryInterceptor = new AnInstanceFactoryInterceptor();
     
                PluginGraph pluginGraph = new PluginGraph();
                using (Registry registry = new Registry(pluginGraph))
                {
                    registry.BuildInstancesOf<IGateway>().InterceptConstructionWith(factoryInterceptor);
                }
     

    I suppose you could use this to register an AOP handler, but I see this primarily as a way to do instance caching or switch out the actual instances returned by some sort of security rules.  You might use this to return a read only implementation of IView for some roles, and an editable implementation of IView for other roles.

    Intercept any instance of any type that meets this criteria

    Okay, now we come to the feature that's very specifically intended for AOP.  What if you want your runtime AOP engine to intercept any type that's decorated with the magic AOP attributes?  You could implement a new class that implements the TypeInterceptor interface shown below:

        public interface InstanceInterceptor
        {
            object Process(object target);
        }
     
        public interface TypeInterceptor : InstanceInterceptor
        {
            bool MatchesType(Type type);
        }

    You just need to implement two methods.  MatchesType(Type) can look at a .Net Type and determine if the TypeInterceptor can act upon an instance.  The Process() method acts as the EnrichmentHandler delegate to return any kind of decorator or runtime AOP proxy instead of the original instance.  You would register TypeInterceptor like this:

     

                MockTypeInterceptor interceptor = new MockTypeInterceptor();
                registry.RegisterInterceptor(interceptor);
     
                // or
     
                StructureMapConfiguration.RegisterInterceptor(interceptor);

    You can register more than one TypeInterceptor.  The result of MatchesType() is cached by Type, so subsequent creations of a concrete class will not have to call expensive reflective calls to match the types.

     

     

    Well, waddaya think?  Useful, or do you need something else entirely?

  • I'm feeling a little bit old

    I've never felt like one of the hoary old veteran developers that prattle on about coding on some sort of hardware I've never even heard of.  I do feel a little bit old today though.  I just saw a post explaining Hungarian notation written for .Net and Java developers that have never seen it -- just in case they ever have to work with a legacy codebase.  Granted, it's been awhile since I've used Hungarian notation personally, but come on!  I'm not that old!  That was *the* way to name variables just a little bit ago!

    I do still use underscores to denote a class field, but that's it.  I know that offends some people, but we all have our individual oddities.  I can't say that I miss seeing p_strVariable and m_objInstanceOfAClass in my code though.   

  • Should I Blog?

    I've been asked several times over the past month "Should I start a blog?  What if...?"  The answer is yes, you should.  Or more accurately, if you're interested in blogging you shouldn't feel afraid to blog.  Here's a rundown of the good and bad things that will happen to you when you blog:

     

    The Good

    • You publish something that helps somebody.  You've used a lot of tutorials, newsgroups, and other people's posts in your career.  Think of your blog as a way to pay it forward.
    • By writing out your position on anything, you'll be forced to crystallize your thoughts on a subject.  I very frequently use my blog as a way to "pre-can" arguments and explanations for later.  I've used my blogging material in consulting roles.  I think that the simple act of expressing yourself is a good way to learn.  What do you think about a subject, and why?  Can you defend that statement?
    • It's a way to practice communication
    • You'll get noticed in a positive way and turn it into professional gain.  Arguably, writing a blog is the best thing I've ever done for my career.
    • It'll be funny to go back over old posts and see how your ideas have changed

     

    The Bad

    • You end up being wrong.  Somebody will write a comment that tells you why your approach is wrong and they'll often say "just do this..."  Cool, you just learned a new trick.  You end up being wiser for the experience.
    • You look like an idiot.  Again, you've learned something;)
    • "foobar" or another BlogCoward is going to call you a name.  Nothing nearly as bad as what my wife says about me.  Sticks and stones...
    • You're going to make a very opinionated, inflammatory post and get criticized for it.  Oh my gosh, somebody might disagree with you!  It's okay, just keep it cool.  One of our former CodeBetter mates used to make inflammatory statements on his blog, then get really bent out of shape when people wrote in to criticize his position and poke holes in his arguments.  If you say something that you know is going to make people mad, expect the flames.  Saying that though, I've been surprised several times by the reaction to a post.  You might just want to reread your drafts and tone down the language (believe it or not, I do this but things still leak through).  Besides, you might have deserved the flames in the first place.

     

    The Ugly

    • You'll get fired.  It's happened occasionally.  A senior consultant at my previous employer was terminated for blogging client information.  That's an extreme case, and one that's very easy to avoid.  You simply need to know what your company's policy is towards blogging and stay within the lines.  If you don't know what the policy is, you don't mention your employer's name at all.  That simple.  I've had 4 employers since starting this blog with wildly varying policies.  Just play nice.

     

    Reasons Not to Blog

    • There are so many good blogger's out there, how could I compete?  It's not a competition.  Besides, good blogger's come and go.  There's often a trajectory of writing a flurry of really great stuff, then flatlining.  When I was first aware of the blogosphere one of the best blogger's around was Joel Spolsky, but when was the last time he wrote anything worth reading?  Maybe one good post a year?  Your favorite blogger is going to fall off any day now.  Anyway, fresh perspectives are always a valuable addition to the conversation.
    • I don't write well.  Practice makes perfect.  Blogging is usually an attempt to explain or demonstrate some technique, or a persuasive essay.  Both types of writing and communication are important for our careers.
    • It's all been said.  I doubt that's true, and even if it was, not everything said has been read.  People don't read old posts, and there's always a whole new generation of developers on the way up that didn't read the past masterpieces.  Just because I wrote a bunch of posts on the do's and don'ts of mock objects three years ago doesn't mean there isn't a lot of value in you writing a brand new post on mock object usage.  Heck, a lot of what I've written the last three years was originally discussed on Ward's Wiki in the late 90's, but that didn't, and shouldn't have, stopped me.

     

    And finally, if you're really, really lucky and good, you can become a cultural force like Justice Gray.

  • You want examples for Build your own CAB? Here they are.

    Rob Kitson has put together a set of code examples that demonstrate the screen patterns mentioned in the BYOC series.  Read more about it at Keeping UI construction DRY.

     

    Thanks Rob! 

  • Some new ways to build objects in StructureMap with less configuration

    I'm getting close to code complete on the forthcoming 2.5 release of StructureMap and I'm focusing on ease of use features and fullblown interception support for AOP tooling (runtime AOP to be provided by something else though).  StructureMap has had some support in the last couple releases to "fill" a concrete class with dependencies by calling ConcreteClass concreteClass = ObjectFactory.FillDependencies<ConcreteClass>().  The advantage being that you didn't have to explicitly register ConcreteClass with the configuration. 

    After

    1. Having somebody ask me how to do it
    2. Seeing a demo of another container do this (I'm not sure about my "NDA" on this, so I'm not gonna say which)
    3. Basically wanting a better way to do this for my current project

    I decided to just add it. 

    As of today (in the trunk at least) you can simply request a concrete class through the normal ObjectFactory.GetInstance<T>() method, and if StructureMap can resolve the dependencies, ObjectFactory will happily return the class requested.  Taking it a step farther, say you have a class with this constructor:  public TradePresenter(Trade trade, ITradeView view, ITradeRepository repository).  You can also do this now:  TradePresenter presenter = ObjectFactory.With<Trade>(someTradeVariable).GetInstance<TradePresenter>() and you can get a TradePresenter object built with all of its dependencies (an ITradeView & ITradeRepository) plus pass the exact instance of the Trade class into the TradePresenter's constructor function.

    All of this is in the Subversion trunk.  If you feel like downloading it out of SVN and playing with it, I'd appreciate the feedback.  Below is the unit test I'm using to prove out the implicit configuration:

            [Test]
            public void CanBuildConcreteTypesThatAreNotPreviouslyRegistered()
            {
                // Create a new InstanceManager that has a default instance configured for only the
                // IProvider interface.  InstanceManager is the real "container" behind ObjectFactory
                Registry registry = new Registry();
                registry.ForRequestedType<IProvider>().TheDefaultIsConcreteType<Provider>();
                InstanceManager manager = (InstanceManager) registry.BuildInstanceManager();
     
                // Now, have that same InstanceManager create a ClassThatUsesProvider.  StructureMap will
                // see that ClassThatUsesProvider is concrete, determine its constructor args, and build one 
                // for you with the default IProvider.  No other configuration necessary.
                ClassThatUsesProvider classThatUsesProvider = manager.CreateInstance<ClassThatUsesProvider>();
                Assert.IsInstanceOfType(typeof(Provider), classThatUsesProvider.Provider);
            }
     

    Here's another example of using the new explicit arguments functionality.  The relevant code is bolded:

            [Test]
            public void NowDoItWithObjectFactoryItself()
            {
                StructureMapConfiguration.ForRequestedType<ExplicitTarget>().TheDefaultIs(
                    Registry.Instance<ExplicitTarget>()
                        .UsingConcreteType<ExplicitTarget>()
                        .Child<IProvider>().IsConcreteType<RedProvider>()
                        .WithProperty("name").EqualTo("Jeremy")
                    );
     
                ObjectFactory.Reset();
     
                // Get the ExplicitTarget without setting an explicit arg for IProvider
                ExplicitTarget firstTarget = ObjectFactory.GetInstance<ExplicitTarget>();
                Assert.IsInstanceOfType(typeof (RedProvider), firstTarget.Provider);
     
                // Now, set the explicit arg for IProvider
                BlueProvider theBlueProvider = new BlueProvider();
                ExplicitTarget secondTarget = ObjectFactory.With<IProvider>(theBlueProvider).GetInstance<ExplicitTarget>();
                Assert.AreSame(theBlueProvider, secondTarget.Provider);
            }

    Feedback on the syntax and/or usefulness of these features would be very appreciated.

  • Interviewing thread on altdotnet

    There's yet another thread going on the altdotnet list about interview questions and techniques.  This message in particular caught my attention because I think it's so true:

    One risk of questions like these is that they lead you to candidates
    who are clones of yourself - who know the same things, who agree with
    you, who have the same experiences.

    Since we all know that we are the best programmers in the world, we
    may not see this as a problem. However, hiring clones of me is the
    mono-culture risk - if we all approach problems the same, how are we
    to approach problems in different ways?

     

    I've been on both sides of the "I want another me" interview style.  Once I realized that I was guilty of the "clone me" attitude, I've tried to dial back questions on patterns, OO trivia, and Agile practices a bit.  I ask more open ended questions to try to bring out what they're good at instead of just asking questions to find out if they know the same things I do.  I can't say that it's foolproof and it's terribly unscientific, but I try to remember to look for skills that would expand the team instead of settling for more of the same.  One of the more frustrating interviews I've done was being interviewed by a C++ and SOA guru a couple years back.  I didn't get a single chance to talk about anything that I did know or had done.

    Besides, for me communication and the ability to explain themselves trumps almost everything else in an interview.  Facts can be learned.  Expressing yourself and thinking logically are a bit harder. 

  • Lord Jim is blogging about Test Automation

    If you're interested in test automation or testing in an Agile world, Jim Mathews has started a new blog at http://jimhmatthews.wordpress.com.  The first post up is:  How to start writing web test scripts with Ruby and Watir.  Jim was the tester on my previous team in Austin when we were pushing (and finding) the limits of Fit testing and knows his stuff.

  • TypeMock isn't too powerful, and "Designing for Testability" is much more than merely mocking anyway

    Roy has a post up today about TypeMock, testability, and DI.  The age old (ok, it just seems like we've been arguing over this for decades) question comes up again "is TypeMock too powerful?"  First, let's go pro-TypeMock because the attraction of TypeMock is pretty easy to understand.  I'm sick of fighting with C#'s static typing just to write unit tests with mock objects.  Pulling interfaces out just for unit testing is a bit tedious (ReSharper makes both creating the interfaces and bouncing around the code easy enough that that's not a real problem to me).  It is code noise that's there for no other reason than to make the compiler shut up.

    The fear that TypeMock will "allow" people to write bad designs is partially bogus.  Part of the reason that I think TDD leads to better designs because it's painful to write tests for bad code (and by bad, I mean code with poor cohesion and poor separation of concerns).  TypeMock will deaden some "pain nerves" that detect bad design by making it possible and even efficient to unit test tightly coupled code (remember that coupling is important for other reasons besides "testability").  TypeMock usage could easily lead to less reusability and extensibility in the code that may turn out to be harmful in the end.  All the same though, I'm not too worried about people using TypeMock because TypeMock won't do all that much to help you test bad code.  Let me repeat that again.  TypeMock won't do all that much to help you test bad code.  Testability is more than just being able to mock interfaces.  Heck, coupling is quite a bit more than mere interfaces. 

    If a caller has too much intimate knowledge about the innards of a dependency (tight coupling), setting up the mocking expectations on TypeMock is going to hurt and inform the experienced TDD'er that something is wrong with his or her design.  If a class or method is not cohesive, the test setup will still be too arduous for what you're trying to test (does the class do only one thing that's quick to test, or does the thing you want to test only happen in the middle of a bunch of other things).

    So, to wrap up:  TypeMock does not end the idea of designing for with testability, and is not going to let you get away with a bad design anyway.
     

    As an aside, Dependency Injection and Inversion of Control containers have far more usages than simply pushing in mock objects.  The existence of TypeMock doesn't even remotely eliminate the need or desire for DI/IoC tools (especially since I very rarely use the container in a unit test anyway).  Dynamic Languages might signal the upcoming death of the DI tooling, but TypeMock doesn't (if StructureMap becomes irrelevant, I just get to move on to new challenges).
     


     

  • The lamest way to try to win an argument

    "Well, I just always use whatever is best for the situation." or "I'm more pragmatic than that" or "you're just a zealot"

    Lame.  And useless.  All those statements are is an admission that you're tired of arguing and you refuse to change your mind.  Arguments, assuming that they stay cordial of course, are valuable.  We're a young profession that's still finding its way.  Any idea that we have about the best way to write software should be challenged (see Roy on TypeMock, DI, and testability today because TypeMock is a subject that I've had to reevaluate *my* opinion on).  What is the best thing for that situation?  Don't you think that maybe the other guy with the differing opinion thinks that *his* approach is pragmatic?  Why does he think his approach *is* good?  "A" is what you know, but is "B" potentially a better way for that situation?  And if you're really right, shouldn't it be relatively easy to defend your position?  You'll never know any of this stuff if you just shut down and disengage.  Even if you still end up believing that the way you do it now is better, at least you've been forced to reconsider that way.


     

  • Spiking a new syntax for integration tests. Whaddaya think?

    Hello, my name is Jeremy, and I sometimes write unit tests specifications that are uglier than sin.  Specifically, when I started to look back at the interaction style tests I've been writing over the past couple years I'm finding a bunch of unit tests that are indecipherable to me, the author of those very tests.  I came to the conclusion that I needed to start writing my interaction tests in a different fashion to promote readability -- and hence better maintainability. 

    I was really concerned about readability more than anything else, but a quicker way to write integration tests would be nice to.  To that end, I've been following the Eleutian guys' posts on their AutoMockingContainer strategy.  Honestly, I've been dubious about the value of the AutoMockingContainer idea.  I get the mechanical savings, but worried that it was too much magic that would obfuscate the unit tests somewhat.  I've got the StructureMap code open for its upcoming 2.5 release, so I decided to stick in some facility for "AutoMocking." 

    The auto mocking stuff was easy enough to do, but I wanted to go farther in terms of readability.  I've found that one of the factors related to integration tests being confusing to newbies and hard to read for anyone is simply the order in which things happen.  In the traditional RhinoMocks record/replay model I call a bunch of expectations on the mock objects, then perform the actual action on the class under test, then call VerifyAll().  It's Yoda syntax.  Instead, what if we could express the tests in a more natural order of Given blah, when I execute blah, this stuff should happen.

    Here's what I came up with in my spike.  This is working code, but I don't want to talk about the mechanics of the underlying code.  I'm mostly interested in what y'all think about the syntax and flow of the test.  I'm purposely leaving out comments or trying to explain the grammar upfront because I want to see how "soluble" this syntax is if you're looking at it cold.

    This is a rewrite of an existing unit test in StoryTeller.  Upon looking at the code, I think there was a simpler way to write the code, but that's a refactoring for another day.  The new and old code effectively express the exact same unit test.  The auto mocking does do a lot to cut down on monotonous setup code.  I definitely think this code is going to be smoother in C# 3.0, but I want to release a 2.0 version before I do that.

    The New Code

            [Test]
            public void Execute_the_command()
            {
                string theFragmentName = "Fragment1";
                Fragment theNewFragment = new Fragment(theFragmentName);
                
                GivenThatThe<Suite>().Is(new Suite());
    
                Given = delegate {
                    That.Calling(Service<IInputCommand>().PropertyValue).Return(theFragmentName);              
                };
    
                WhenExecuting = delegate  {
                    AddNamedFragmentCommand.Execute();
                };
    
                TheInteractionShouldBe = delegate {
                    Call<ISystemUnderTest>().Save(theNewFragment);
                    Call<ILeafNode>().RefreshNodes();
                    Call<IFragmentPresenter>().StartEditing(theNewFragment, Member<ISystemUnderTest>());
                    Call<IApplicationController>().OpenScreen(Member<IFragmentPresenter>());
                };
    
                Then = delegate {
                    Assert.IsNotNull(Member<Suite>().FindFragment(theFragmentName));           
                };
            }
    
    

    The Old Code for the Same Test

            [SetUp]
            public void SetUp()
            {
                _mocks = new MockRepository();
                _node = _mocks.CreateMock<ILeafNode>();
                _suite = new Suite();
                _systemUnderTest = _mocks.CreateMock<ISystemUnderTest>();
                _inputDialog = _mocks.CreateMock<IInputCommand>();
    
                _applicationController = _mocks.CreateMock<IApplicationController>();
    
                _command =
                    new AddNamedFragmentCommand(_node, _suite, _systemUnderTest, _inputDialog, _applicationController);
            }
    
            #endregion
    
            private MockRepository _mocks;
            private ILeafNode _node;
            private Suite _suite;
            private ISystemUnderTest _systemUnderTest;
            private IInputCommand _inputDialog;
            private AddNamedFragmentCommand _command;
            private IApplicationController _applicationController;
    
            [Test]
            public void Execute()
            {
                string theFragmentName = "Fragment1";
                And fragmentConstraint = new And(
                    new TypeOf(typeof (Fragment)),
                    new PropertyIs("Name", theFragmentName)
                    );
    
                IFragmentPresenter fragmentPresenter = _mocks.CreateMock<IFragmentPresenter>();
                ObjectFactory.InjectStub(typeof (IFragmentPresenter), fragmentPresenter);
    
    
                Expect.Call(_inputDialog.PropertyValue).Return(theFragmentName);
    
    
                // Save the fragment
                _systemUnderTest.Save(null);
                LastCall.Constraints(fragmentConstraint);
    
                _node.RefreshNodes();
    
                // Open the screen
                fragmentPresenter.StartEditing(null, _systemUnderTest);
                LastCall.Constraints(fragmentConstraint, new Equal(_systemUnderTest));
                _applicationController.OpenScreen(fragmentPresenter);
    
                _mocks.ReplayAll();
                _command.Execute();
                _mocks.VerifyAll();
    
                Assert.IsNotNull(_suite.FindFragment(theFragmentName));
            }
    

     

  • Is it time to make IoC/DI tooling part of the BCL?

     I'm in Redmond this week helping out Patterns and Practices with a focus group on the WPF Composite guidance that is going to be the successor to the CAB.  Modular development is on everybody's mind here, and the de facto solution for stitching all of the components together is some sort of IoC/DI tooling.  Great, but one of the gripes about CAB is that it forces you to use the ObjectBuilder and many people want to use their own container.  P&P is on the ball, so they're planning to have some sort of way to swap out the IoC container.  Great, but... 

    • The MVC framework guys are making the container swappable (and one of the highlights of my career was hearing ScottGu say "you could use StructureMap" out loud in the MVC unveiling).
    • I saw a slide about Acropolis that had a block that said "Dependency Injection."
    • WCF arguably has a service locator built into itself.
    • The Provider Model is effectively an implementation of Service Locator
    It might be a good idea to finally put a very generic hook in the CLR Base Class Library to register an IoC container so that all these different pieces can start using a consistent IoC mechanism.  I'm pretty sure I've heard or read Microsofties say that they're considering it.  I think I'm ready to vote for it.  What do you think?
  • Using StructureMap to build a class that isn't registered with the container

    I had a query this morning about this.  Say you're working in the new MVC framework and you write your own routing engine that has a syntax like this:

      Route("some string pattern").IsHandledBy<MyController>();
    Route("some other string pattern").IsHandledBy<AnotherController>();

    Each Controller has its own set of dependencies that you'd prefer that StructureMap build out for you, but it might be inconvenient to have to register all these types with StructureMap.  That's okay.  As long as you know the concrete type you want, StructureMap can create the concrete class and "fill" it with all of the dependencies even if StructureMap isn't configured with that concrete type in advance.  The syntax is:

    MyController controller = ObjectFactory.FillDependencies<MyController>();

    or

    MyController controller = (MyController)ObjectFactory.FillDependencies(typeof(MyController));

    I don't use this feature much, but it's handy in some spots

  • Breaking News: Java trounces .Net in OSS activity

    Obviously, this isn't breaking news.  I saw this set of figures from Ohloh this morning.  If you're not familiar with it, Ohlog is a website that tracks information about Open Source development projects by scanning the major OSS sites like SourceForge.  According to them, in the last 5 years there were:

    146,996,128 lines of code committed by 10,604 people to Java OSS projects.

    22,800,806 lines of code committed by 1,817 people to C# OSS projects (The numbers for VB.Net trailed much rarer languages like Lua and Tcl)

    Maybe you can't take the numbers at face value because Java is so much older, but I still think the differences are striking.

    Make of it what you will, but I think we have to say that the OSS activity is simply much richer in Java than .Net land.  I suppose you can argue with me that Microsoft actually does a better job of building tools and frameworks than the Java vendors and OSS just isn't as important to us.  I think I'd still say that we don't have as rich an ecosystem of innovation and choice as Java.  When you consider that most of our major OSS projects are ports or copies of Java or Ruby tools, we come off even worse than the numbers imply.  I guess my real point is that I think we (.Net community) would be better off if we (the developers who do not work in Redmond) were much more actively involved in creating the tools, frameworks, and techniques that we use to do development.


More Posts Next page »

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP