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

March 2008 - Posts

  • In honor of Greg Young

     

  • We need ALT.NET to supplement the traditional .Net leadership

     

    One of the roles I’d like ALT.NET fulfill within the greater .Net community is to be a second pole of leadership and thought. I say a “second” pole, because the .Net community already has a long standing traditional leadership -- the book authors, the MVP’s*, the INETA speakers, and whatnot. They’ve done plenty of good in regards to explaining how to best use existing and forthcoming Microsoft tools, but I think there are a lot of valuable subjects and viewpoints that are largely missing from the mainstream .Net dialogue. Specifically, I’d like to see ALT.NET start to fill what I see as a void for information and leadership on:

    • OOP fundamentals. I think we as a community would achieve far more benefits on our projects from a stronger base of OOP design knowledge than we do for learning new API’s like WCF or LINQ. Learning the fundamentals will make us far better able to choose and use these new API’s.
    • Development processes and practices. Microsoft builds and sells tools, and they naturally see tools as the solution to most problems. We the community should be completely in charge of determining our best practices because we are the ones out there building software. Go to a .Net centric development conference. Outside of some token Agile track, you will not see very much about configuration management, project management, requirements, testing, or the all important people issues. A lot of Linq to XYZ talks, but not much about running successful software projects.
    • Alternative tools. Some of the tools Microsoft makes are great, but some are inferior to non-Microsoft options. Some of these alternative tools open up entirely new possibilities in how we can work.  I’d like to see the entire .Net community to simply broaden its horizons to be more accepting of tools originating from outside of Redmond.

     

    Two recent podcast's illustrate to me why I think something like ALT.NET has some value to offer the community by filling holes in the dialogue.  First up was Lerman on the Entity Framework on DotNetRocks. I promised Julie that I wouldn’t burn her in effigy here, so I’ll just say that I think that podcast covered the Entity Framework from a very data centric viewpoint that skated over some important concerns about using any persistence framework.  Namely, what does this tool do to my business layer and the application as a whole?  How much does the tool intrude on the rest of the application?  From my own, very different viewpoint, the Entity Framework is conceptually flawed in some significant ways and won't let me work in the way that *I* think makes me the most successful:

    • In my opinion the new “conceptual model” in the Entity Framework that allows you to treat the database more as a set of hierarchical entities is a poor substitute for fullblown OOP programming. I think the conceptual model is unnecessary complexity that detracts from the usability of the EF.
    • The lack of transparent “lazy loading” in the Entity Framework is a dealbreaker for me. The need to explicitly say “Order.LineItems.Load()” makes the EF a very poor fit for Test Driven Development by making the EF objects difficult or nearly impossible to use independently of the database. Lazy loading should be completely transparent to the business logic, and I should be able to completely express the business logic without letting infrastructure concerns leak in (that Separation of Concerns thing). The podcast completely whiffed on this topic in the discussion of “POCO” objects at the end of the episode.
    • At this point, EF couples you very tightly to the database. Support is very weak at this point for Domain Driven Design techniques. I really don’t think the EF is usable without using codegen to bake in the change tracking code that EF wants to be in the objects. Codegen-ing your business objects pretty well eliminates evolutionary design or keeping your domain logic in these classes. I know you can use partial classes for the business logic, but that's sooooo clumsy. Besides, the codegen is more or less optimized for scenarios where you merely replicate the structure of the database in the object model.

    Many people don’t feel that the EF picture is all that rosy, but those concerns simply aren’t getting much attention or understanding from our traditional community leadership. 

    The second podcast was .Net author Rocky Lhotka being interviewed on Hanselminutes about data access issues.  I mostly agree with Rocky on the general goals, but I think there's better mechanical ways to achieve an effective object model strategy than what Rocky was espousing on the show.  Rocky gets some serious points from me for talking about Responsibility Driven Design (my choice for the single most effective design technique) and the Single Responsibility Principle (SRP).  Ironically enough though, I advise people against using his CSLA.Net framework in no small measure because I think CSLA violates the Single Responsibility Principle.** It may be that Rocky and I have vastly different interpretations of the SRP, but that again points to the validity of a second pole of thought and discussion because I really don't think that Rocky (or any one else including me) gets to be the sole voice who gets to define design best practices.

    One of the other things Rocky said was that ORM tools tightly bind your object model to the database. His suggestion was to use an ORM as just a data access layer and manually write mapping code within your business objects to translate between the database model persisted by the ORM and your own domain model classes. I thought this was terrible advice in most situations because it's unnecessary, and putting that mapping code inside your business objects let’s infrastructure concerns bleed into my your domain logic code (a clear SRP violation).  When I use NHibernate, I can write my business objects in a structure that fits the behavior of the business logic the way Rocky and I both want to, but I can also persist these objects to a database structure that makes sense for the database with very little impact on the business objects.  I do not have any need to write all of that tedious mapping object-to-object code that Rocky was suggesting.  I don't know if Rocky was purposely overlooking the capabilities of NHibernate or the WilsonORMapper in favor of his traditional CSLA approach, doesn't believe in ORM, or if he just flat out doesn't know.  Either way, we need some alternative sources of information, and dare I say it, visible authority figures in the community.

     

    Sometimes the Microsoft solution isn’t the best

    Both podcast's were lacking in well informed opinions about alternatives to the Microsoft tooling on data access, and I think that's probably my biggest reason for writing this post.  If my choice was really a binary decision between Linq to SQL or Linq to Entities and rolling naked ADO.Net code, heck yes I'd jump for joy about the EF.  Fortunately for us, that's not the case.

    The biggest problem for me with the EF is that I think there are simply better existing tools for the vast majority of projects. For simpler CRUD or reporting applications, SubSonic is basically the exact same kind of “generate strongly typed object wrappers around the database tables” solution as the EF and Linq to SQL, but I bet SubSonic would be much easier to use. LLBLGen Pro is much more feature rich than the Entity Framework. NHibernate is vastly better if you want to use a rich Domain Model approach for your design and/or want to most effectively utilize TDD. iBatis.Net will probably be easier to use for nastier legacy database schemas and give you ultimate control over the SQL with lighter weight mapping than the EF. Heck, LLBLGen Pro and NHibernate are well on their way to having full LINQ support, and SubSonic has a strongly typed query language, so shoot down that advantage for EF.  My preference is NHibernate, but I was very happy with my usage of the Java version of iBatis.

    I honestly believe that if we don’t have any useful alternative to the traditional .Net leadership, all of these arguably superior tools will be shoved to the sideline in favor of the deeply flawed Entity Framework. Worse yet is that we might not get better tools because I don’t think our traditional leadership does a very good job of giving useful feedback to Microsoft to help make these tools better. I really do believe that our traditional leadership largely sees new tooling as simply opportunities to write articles, books, and be visible conference speakers rather than something that needs to be carefully evaluated and possibly rejected. I want leadership that can help us make good judgements about how and with what we should build software instead of just relaying the guidance from our toolmaker.

     

    Summing Up

    I didn't say here that I think we need to completely swap out our entire leadership clique.  All I want is an additional set of leadership types who are discussing other points of view to give us a more rounded conversation.  To some degree, I think we might just need a new generation of leadership that didn't come up through Windows DNA programming.  Lastly, I don’t really care if it’s the ALT.NET movement specifically that starts to fill this void as long as it’s filled by somebody in a useful way.

    When some .Net poobah says that every class should be accessed through WCF, someone else should speak up and say "that's insanely stupid," but in a reasoned, adult like manner.  And if any MVP speaker type says you should be using the Entity Framework/WF/putting all your business logic into XAML/whatever, I want to see some dissenting opinions too.

    Comments are open. Feel free to disagree with me.

     

     

     

     

    *To be fair, many of the most visible ALT.NET members, including myself and many other CodeBetter bloggers, are also MVP’s of one sort of another. I’d still say that we make up a very small minority of the total MVP lineup.

    ** To the CSLA proponents out there, I’m going to issue you a challenge. Run static code analysis numbers on your CSLA “business” objects. I’ll betcha that the Cyclomatic Complexity numbers are uncomfortably far into the dangerous zone – and yes, if this is so, this is something you should be concerned about.

  • If you need something in StructureMap, but you can't build it with new()...

    I've had 3 separate questions in the past week about this, so I figured it's blogworthy.  You'll have to download the latest bits from svn at http://sourceforge.net/projects/structuremap.  Anyway, let's say you want the HttpContext in StructureMap so that it can be injected into other classes.  The current HttpContext doesn't even exist at configuration time, and you certainly can't just say new HttpContext(), so we needed a way to tell StructureMap a way to fetch this object and bypass the traditional object building pipeline.  About 4 months ago I added this syntax to the trunk:

    StructureMapConfiguration.BuildInstancesOf<HttpContextBase>.TheDefaultIs(
    	ConstructedBy<HttpContextBase>(() => HttpContext.Current))
    );
    Doing this just enables StructureMap to poke the correct HttpContext into something like "public Controller(HttpContext context)." 
    This strategy should be useful for remoted objects, Provider classes, the HttpContext, and whatever else you can dream up. 
    Comments, and suggestions for improving the syntax (please), would be welcome. 
  • The big cutover

    Dear Diary,

    Last week I said that there's a "Great Refactoring" on every project -- and I just committed ours to SVN.  For what I thought were good reasons at the time, we started out with pure WinForms for our presentation layer.  Starting today, we're mixing in WPF for some of the little data entry screens.  I'm a complete newbie to WPF, so some of the learning curve hurt.  Anyway, here's my original reasons for using WinForms and other thoughts.

    • Risk.  I knew we could deliver in WinForms, and I didn't want to stop to ramp up with WPF.  I still think that was valid, but we're going to use WPF so simply that I don't think it would matter much.
    • I was initially hesitant to try WPF because the scuttlebutt was that WPF was hard or impossible to test.  So far I've been able to adapt my infrastructure and approach to testing WinForms and apply it almost unchanged to WPF.  All I really had to do was just put a little adapter code in my test automation for the different set of controls.  WPF doesn't really do anything to *help* you do automated testing, but it doesn't hamper testing (whatever that Automation API is supposed to be for, it isn't all that useful for testing).  Simulating events with the new RoutedEvent stuff was pure klooge, otherwise it's been fine.
    • The rendering performance is much, much better than the equivalent screens were in WinForms.  Even when we're just hosting WPF inside of a WinForms Panel the performance is still better.
    • We're doing some dynamic layout of screens with a little home cooked DSL.  The WPF layout controls are head and shoulders better than the WinForms analogues.  This was actually the main reason we switched, truth be told.
    • That whole "do Separated Presentation to protect yourself from changes in Presentation technology" bromide?  Yep.  The cutover really wasn't that bad because we had very little code that actually touched the WinForms classes.  The Fluent Interface stuff we use to drive the screens payed off in a big way here.
    • I thought we could reuse a lot of WinForms layout code from an earlier version of the system.  As usual, the old code is of dubious usefulness.  From this point on I'm only using the old code as reference.
    Anyway, I'm alive.  If that's the worst thing that happens in our code, I'm a happy camper.  Back to building real code now.
  • ALT.Net on MSDN Magazine

    There is a short article I wrote called What is ALT.NET on the back page of the March edition of MSDN Magazine.  Nothing you haven't seen before if you're a regular reader here, but it was nice to see something in the mainstream.  I'd say "my latest article" like James did for his piece of ALT.NET goodness, but this is the first official article I've published since 2002 (I've got at least 4 more coming this year).  Comments are open below for anything you do or don't like about the article. 

    And no, I don't think I was being unfair about the Entity Framework.  On the ASP.NET MVC framework, I'd say it's still cooking and the jury remains out.  Yeah, the unit testing looks really ugly so far to a casual observer like me, but they've got time to turn it around.

     

  • C# 3 is like a Moped

    When I was growing up I used to occasionally hear the saying "a Moped is just fast enough to get you into trouble, but not fast enough to get you out of trouble."  I have no idea where it came from, and never saw a single Moped until my twenties, but it's an ideal way to describe something I was feeling this week.  We're trying to do some language oriented programming in our new project with C# 3, and that generally means Fluent Interfaces.  We're getting some real benefits out of our approach, but the fluent interface code itself can become completely opaque when it devolves into "generics hell" like this:

     

    public abstract class LayoutExpression<THIS, MODEL, ELEM, EXPR> where ELEM : IScreenElement

    and

    public class TextboxLayoutExpression<MODEL> : LayoutExpression<TextboxLayoutExpression<MODEL>, MODEL, TextboxElement, TextEditingElementExpression>

    and

    public abstract class ControlDefinition<T, ELEM> : IElementSource<ELEM> where T : Control, new() where ELEM : IScreenElement 

    The API using this code is okay and generally pretty usable, but pain accrues when it's time to extend the Fluent Interface.

    C# 3 is great, and I'm glad to have it, but the new language features apparently have their limitations.  You can drive out more code reuse with generics and lambda expressions, but the readability eventually collapses when you push it too hard.  We're backing up and writing more lines of explicit code instead of trying so hard with generics.

    A couple years back there was a blog meme floating around called Is Ruby an Acceptable Lisp?  When C# 3 came out, there was some quiet discussion in ALT.NET circles that maybe the new language features (the "var" keyword, better type inference, lambdas) would be enough to satisfy us in regards to Language Oriented Programming and keep us from clamoring for Ruby.  The answer for me after three months of hands on C# 3 is that C# 3 is NOT an acceptable Ruby.  Simply having Duck Typing (or maybe the super type inference that OCaml and other exotic languages have) would have made what we were trying to do easier to code and easier to read.  Some of the Fluent Interface work helps to boil down code into a much smaller surface area, but there's still too many extraneous angle brackets, squiggley brackets, and semicolons floating around to make it really readable the same way that a Ruby or Python internal DSL can be.  Maybe my entire point here is that C# is simply not Ruby and we shouldn't try so hard to use C# like Ruby.

     

    So, anybody know any new news on IronRuby? 

  • Observations

    • Developers abhor a clean whiteboard
    • All code base's want to have an ICommand abstraction of some sort
    • Sooner or later, a project called TestHarness will appear in your source tree
    • There will be at least one "The Great Refactoring" episode on the project that you will hence use to date episodes from the project.  BDUF all you want, YAGNI all you want, it's still gonna happen.  If it doesn't, then your code probably sucks.
    • At least one grand sounding design idea will generate excitement only to lead to abject failure and disappointment
    • At some point you will look at a grand design and suddenly realize a much simpler way to achieve the same goal -- but it's too late
    • You'll do at least one refactoring that makes you walk away and say "I wish we'd done that sooner"
    • You'll do at least one refactoring that makes you walk away and say "Man, I'm glad we did that"
    • You will look back at 6 month old code and groan in utter frustration at your lack of ability
    • Design strategies that worked well on one project can easily flop on the next project
  • Test what you're testing

    I use the phrase in the title usually to refer to using mock objects in a useless way (mocking ADO.Net or Active Directory or calls to any API that you don't understand).  When you're choosing whether to write a small integration test or a mocked test, just think what would give you the actual value.  If the mocked test doesn't actually prove that whatever you're doing works, then it isn't useful. 

    Today we got a little reminder about this rule.  By accretion, we are building a little Fluent Interface that uses lambda tricks to configure NHibernate mappings without having to expose my tender eyes to angle bracket hell.  Behind the scenes, it still generates good old fashioned hbm Xml, but at least I don't have to see it.  Today we hit our first case of a somewhat common mapping scenario.  We had a unit test that specified that the Fluent Interface built the Xml exactly the way we intended it to for this scenario, but as soon as we tried to use it, NHibernate threw a 50 line stacktrace exception.  Lesson (re)learned here, we probably need to skip the intermediate unit test to worry about the intended effect of saving the object.  The Xml was only an intermediate deliverable, and not the real goal.

  • Build your own CAB: The Main Players in the Composite Application Neighborhood

    I spent a week in Redmond in January taking part in a focus group on the vision for the P&P's new Prism work on composite applications.  Part of the week long exercise was to identify the basic building blocks of building large composite clients. This is my list of the significant parts of an application that I see regularly reoccurring from app to app.  For CAB fans, you'll note that there is no "WorkItem" in my list, but the responsibilities that it fulfills in the CAB framework are all present in other (more logical) places.  if you're moving onto Composite Application Street, these are the classes and in your neighborhood (, in your neighborhood, in your neigh-bor-hood, oh here are... ):

     

    The IoC/DI tool of your choice

    These tools are good for more than just crowbarring mock objects into your code.  When you're talking about extensibility and modularity, an IoC tool is an easy way to wire up new Views, Presenters, and Services to your existing application.  If you take a long look at the CAB, you'll see that a major portion of it is related to Dependency Injection and (ObjectBuilder) and service location (the WorkItems).  One of the main reasons that I've always been dismissive of the CAB itself is how easy it is to roll your own framework wrapped around an existing IoC tool.   You could build a composite application without an IoC tool, but the responsibilities that were assumed by an IoC tool are just accomplished by something else (or hard coded which would pretty well shoot down the idea of a composite application).  Obviously I'm biased here, but I think that using an IoC tool is a huge shortcut in building any kind of extensible application.  Assuming that that level of extensibility is actually justified of course;-)

     

    Application Shell

    The main form that contains everything else.  The responsibility of the shell is to hold the main components of the user interface like menus, ribbon bars, and holders (panels, docking managers, etc.) for the screens that get activated later.  This should be fairly thin, and there's some very real danger in the ApplicationShell becoming a catch all that collects way too many unrelated responsibilities.   

     

    ApplicationController

    The Application Controller pattern identified by Martin Fowler is "A centralized point for handling screen navigation and the flow of an application."  The ApplicationController controls the screen activate lifecycle and the lifecycle of the main form.  In most of my systems other screens are activated by calling methods on the ApplicationController.  In smaller systems the ApplicationController would also control screen workflow.  In larger systems I would break some of that responsibility out into separate collaborating classes.

    I should point out that the ApplicationController is probably going to be a full blown subsystem in its own right.  The Single Responsibility Principle will often drive you to split the ApplicationController into some smaller parts:

    1. Screen Conductor -- Controls the activation and deactivation lifecycle of the screens within the application.  Depending on the application, the conductor may be synchronizing the menu state of the shell, attaching views in the main panel or otherwise, and calling hook methods on the Presenter's to bootstrap the screen.  It may also be just as important to deactivate a screen when it's made the inactive tab to stop timers.  My first exposure to a Screen Conductor was an insurance application that was built with web style navigation.  Anytime the user moved away from a screen we needed to check for "dirty" screens to give the user a chance to deal with unsaved work.  On the other hand, we also had to check the entry into a requested screen to see if we could really open the screen based on pessimistic locking or permission rules.  We pulled our a Layer SuperType for our Presenters for methods like CanLeave() and CanEnter().  The Screen Conductor would use these methods and others to manage screen navigation.
    2. Screen Collection -- In applications that have some sort of tabbed or MDI display of screens, you usually need to track what screens are active.  The easiest example I can think of is a TradeCapture application I built last year.  When a user opened a trade from either a search screen or by entering a trade id, the trade ticket window would popup in a separate window.  It was important that there only be one window for each trade up at one time, so if the user happened to request the same trade that was already opened, we would just show the existing screen instead of opening a brand new screen.  We used a Screen Collection class to track the open screens so that we could retrieve the active screen for an individual screen.  I've seen this pop up on at least 3 separate occasions now.
    3. Screen Subject -- I've only used this a couple times, but it's going into my regular rotation from now on.  I've built several applications along the tabbed display motif now.  In many of them there's a need to respond to a navigation request by first checking if the screen exists to either make the already open screen be the active tab or to create a brand new screen and make that the active tab.  I've gone to the idea of a ScreenSubject object that can determine if it matches an open Presenter and knows how to create the new screen if it isn't already open.  ScreenSubject works very closely with Screen Collection.

     

    Others

    • Bootstrapper and Registry - The IoC container and the ApplicationShell has to be constructed somewhere.  I like to put all of the "bootstrapping" into a class called, wait for it, Bootstrapper.  It's very useful to keep this separate from the ApplicationShell itself, both to keep the ApplicationShell cleaner and also to enabled integration testing scenarios that test partial application stacks.  Bootstrapper is also responsible for spinning up any services that need to run throughout the application lifecycle (like caching or the event aggregator).  The Registry is an optional piece that contains configuration for a specific module.  It might help configure the IoC container, add more menu items to the shell, or attach new services.
    • Model, View, and Presenter - I won't rehash these pieces here.  See the rest of Build your own CAB for more information.  There's about a hundred different ways to divide and organize these three things.
    • Service - The most overloaded term in all of software development.  Roughly put, it's the classes that you interact with that aren't one of the other things.  I would strongly recommend that
    • Command - Gang of Four Command objects.  "Jeremy's first law of enterprisey systems" -- Every system of sufficient complexity will have an ICommand interface.  This subject deserves its own chapter/post.
    • Event Aggregator / Event Broker - Here and here.  I'm going to include at least three different flavors of this in my book.
    • CommandExecutor - Also known as the Active Object.  I like to use Command Executor to standardize the way my applications use background threading.

     

     

    What did I miss?  Comments are open.

  • Quotes from the past couple days

    Things said to me in the last couple days:
    • "Jeremy, it sounds like you're building your own CSLA" -- you take that back Weston!
    • "You know, if you were using Unity it would have figured it out for you" -- said with major sarcasm
    • "It was like listening to 9 year olds describe how babies are made" -- in regards to a popular podcast several of us ALT.NET'ers were irritated with.  I'll make an attempt at a reasonable, adult type of blog post on the subject later.
  • Unit testing, playing tennis, and the lack of absolutes in TDD

    I'm not a particularly good tennis player.  Mostly from not having played in years, but even then, I suffered because I can't hit a decent backhand to save my life.  I have a big serve and a decent control with my forehand, but all you've got to do to beat me is put the ball where I have to attempt a backhand.  All of the best competitive tennis players can will choose either the backhand or forehand depending on where on the court they play the ball.

    Test Driven Developers need to be the same way in regards to choosing a state based style or interaction based style on every single unit test.  I've been disappointed with the recent conversations I've seen lately on the subject.  Many people are proudly describing themselves as Classicist or Mockist TDD'ers because they favor either state or interaction based unit tests and see the other style as something to avoid.  Specifically, I'm agitated at the people who are trumpeting themselves as "Classicists" because I feel like they're doing real harm to the state of TDD practice.  I've never met a self-described mockist and I'm tempted to say that the very term is a strawman.  On the other hand, self-described Classicists may be just like me on the tennis court -- they're taking bad shots and bad angles just so they can hit a forehand when a backhand is more appropriate.

     

    Over Specified Test

    Many people are concerned about the "over specified test" anti-pattern and rightly blame mocks as a primary source.  So mock objects are evil right?  Survey says:  bzzzt.  An over specified interaction test is generally caused by a fine-grained, chatty API or a lack of encapsulation between a class and it's dependencies.  In other words, you may be staring at a code smell.  I ran into this lately at work.  I had a Supervising Controller that was issuing a lot of fine-grained commands to its View.  Make the addresses editable, make the address read only, show Canadian address fields, make the stored address dropdown shown for certain customers, and hide the stored address dropdown at other times.  The code became nasty and the unit tests got ugly with runaway expectations.  I refactored the Supervising Controller to a bit of a state machine that could correctly create a "ScreenState" object at any point and rigorously tested that logic.  I then changed the interaction between View and Presenter to just ensuring that the Presenter was correctly passing a new ScreenState to the View upon certain View events.

    Some points about over specified interaction tests:

    • Do not try to mock chatty interfaces.  Favor coarse grained API's that hide more details of the internals of a class's dependencies.  I wrote a post a couple years back called Best and Worst Practices for Mock Objects.  I read over it this morning and I think it still holds up.
    • When you spot an over specified test brewing in your code, treat it as a code smell and reevaluate your class structure.  Remember that TDD is a DESIGN PROCESS.  If the unit test is going badly, your first assumption should be that the design needs refinement.  Listen to what the unit test is telling you about your code.
    • Be aggressive with dynamic and partial mocks to write smaller, more focused interaction based tests
    • You don't have to always use ReplayAll() and VerifyAll().  Sometimes you might want to call Verify on only one mock object to create a smaller, more focused unit test

     

    State Based Testing isn't all that and a bag of chips

    I generally tell people that State Based Testing is easier than Interaction Based Testing on the whole -- except when it's not.  Let's consider this state based test:

    [Test]
    public void The_presenter_saves_the_whatsit_if_the_whatsit_is_valid()
    {
    	Whatsit model = ObjectMother.ValidWhatsit();
    	WhatsitPresenter presenter = new WhatsitPresenter(new StubWhatsitView(), model, new StubWhatsitRepository());
    	bool returnValue = presenter.Save();
    
    	// Look ma!  I should have saved the Whatsit in this scenario
    	Assert.IsTrue(returnValue);
    }
    
    [Test]
    public void The_presenter_does_NOT_save_the_whatsit_if_the_whatsit_is_InValid()
    {
    	Whatsit model = ObjectMother.InvalidWhatsit();
    	WhatsitPresenter presenter = new WhatsitPresenter(new StubWhatsitView(), model, new StubWhatsitRepository());
    	bool returnValue = presenter.Save();
    
    	Assert.IsFalse(returnValue);
    }
    

    When the Save() method of my WhatsitPresenter is called the WhatsitPresenter should perform a validation of its Whatsit member and either use the WhatsitRepository to save the Whatsit, or have the WhatsitView display the validation errors.  That's the intent of the unit tests above, but how much of that intent is really coming through in these unit tests?  Very little right?  We're doing a nice simple state based test to check that the Save() method correctly returns a boolean value saying that it did or did not save the Whatsit.  That's nice, but the real intent behind the test is that the Whatsit was really saved.  This is an example of a bad unit test.  We're not even testing the real functionality, we're just testing a side effect of the code by checking the return value.  What we really need to do is to verify that our WhatsitPresenter did or did not send a Save() message to the WhatsitRepository, i.e. we should use some sort of mock object here. 

    I use a lot of contrived examples in my blog, but this example was adapted from another blogger.  Sometimes, favoring a state based testing philosophy leads you to useless tests that test through side effects.  Other times, a state based test will cause you to relax encapsulation in a harmful way to make the state based assertions where an interaction based test would maintain encapsulation.  When you play a ball on the backhand side of the court, you better use your backhand.

     

    Bottom Up versus Top Down

    Do you start from the "top" and code that against mock objects for the lower level concerns, or do you write the lower level pieces first, then assemble them together to create the aggregate structure?  Which is best?  Well, it depends.  Here's an easy rule of thumb.  Start with whatever you do know how to do. 

    If you know exactly how one or more steps of a complex algorithm should work, build those steps first in isolation.  Building out those steps will often suggest the structure of the coordinating code.  That's bottom up development. 

    At other times, you'll know the general workflow of the code, but not necessarily know how some of the lower level tasks will be performed.  In this scenario I write the controller type unit tests first and just drop off mock objects as a placeholder for concrete classes to be added later.  This is frequently a great way to work with any variant of the Model View Presenter pattern.  Building the overarching workflow will help define the API to the underlying steps in the algorithm and often give you some insight into how those tasks should be implemented.

    I don't see the usage of acceptance tests to have any impact whatsoever on my choice of bottom up or top down.  Either way, I'm going to break down the feature into a finite number of coding tasks and write fine grained unit tests for those tasks until I feel like it's appropriate to start running the coarse grained acceptance test.

    The beauty of TDD as a design process is the ability it grants you to work on one issue at a time without leaving yourself in the hole to create the other pieces.

     

    Summary

    You might have a mighty forehand with your state based tests, but there are going to be times when it's better to swing a backhand stroke and use an interaction based test with a mock object.  My advice is to focus on the goal of each unit test and make sure the unit test is mostly concerned with that goal.  If the goal of a unit test is to ensure that a change of state or a return value is correct, it's a state based test.  If the goal of a test is to ensure that a class is passing the correct messages to other classes during its internal functioning, you should be writing an interaction test.  Don't pick sides on the Classicist versus Mockist argument.  It's a false dichotomy and a harmful line of thought.  You aren't going into your toolbox at home and throwing out all the close-ended wrenches because you only want to use open-ended wrenches are you?  Same thing applies to mocks.

     

More Posts

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