6 Apr 2012

Are You Limiting Your Abstractions, or Your Seams?

Here are some fun facts about me:

Photo

1.)  I drink liquids from cups, glasses, and cans.
2.)  I own tables.
3.)  My baby recently learned to stand and walk.

If you’re reading this, you probably share #1 with me.  There’s also a good chance that you share #2 with me.  If you don’t, I’d really recommend that you give tables a try, as they are great places to put your cups, glasses, and cans.

But #3 is different.  It’s what they call a “game-changer.”  If you are a parent, you know that once a baby gains mobility, the rules of the house change.  Such as:  Table edges are no longer such a great place to put cups, glasses, and cans.  If you put a drink down on a table within reach of the baby, within five minutes the baby is going to see it, walk up to it, and knock it over.  And he’ll be smiling while he does it.  

If I just turned you against having kids forever -- don’t be like that.  You can still use tables.  However, those few inches from the edge of the table to the middle become really important.  Put a drink on the table, but put it in the middle so the baby can’t reach.  See?  

It’s still hard.  My wife and I sometimes forget.  Then when the baby comes, we have to rush over and move the cup away.  Or we’ll see each other put a cup on the edge and we’ll say, “The baby’s going to knock that over”  Or on rare occasions, we put the cup on the edge and we get away with it.  Whew!

In my house, though, it’s really only a matter of time.  You put a cup on the edge of the table, and it’s going to be moved by someone.  Change is coming.

Limiting Your “Abstractions”

I’ve seen a general trend amongst many of the .Net programmers I follow on the internet:  “Limit your abstractions.”  It sounds like a great idea, as nobody wants too many abstractions in your system.  If you do not need an abstraction, you should not create it.  I’m on board!  

Oh, wait, what’s that word I saw again?  “Need.”  Hmm... now I’m afraid.  Saying you need something is very dependent on many facts that are specific to your situation. This is why when someone asks you if you should create an abstraction for [X], the “wise” answer is:  “It depends.”  

Personally, I hate “it depends” because it’s a phrase usually used to throw away principles.  Depends on what!?!?  Let’s whittle the idea down until we can find the principle!  Frankly, I think there are people who’d rather live in this ambiguous “it depends” because it’s a lot easier than finding the answer.

So let’s look at how this general “limit your abstractions” idea is getting applied.  Let me just thumb through my memory real fast to produce an example I’ve seen multiple times... ok, found it.  Oh, look, it’s a controller, and the issue in question is what we put in it.  

Here’s an example of a controller action for a page that shows all of the products of a website.  

   public ViewResult Index(){
       var products = productRetriever.GetAllProducts();
       return View(“Index”, products);
   }

It looks simple, but I see an abstraction:  IProductRetriever.  That’s brought in, I assume, through dependency injection, and then it’s used by the controller to get the products to show on the page.  

But we’re supposed to “limit our abstractions,” so let’s see how we get rid of that abstraction.

   public ViewResult Index(){
       var products = MyDatabaseSingleton.Products.Where(x => x.IsActive);
       return View(“Index”, products);
   }

No product retriever abstraction. Gosh, I bet you could instantiate this controller up without any constructor arguments or IoC container.  It just hooks to... a database context singleton...  then references a property to return an IQueryable of the Products, then …. sigh.... the controller filters out the inactive products.

This does things that anybody who has read Clean Code knows you’re not supposed to do.  But then the wise “it depends” crowd will reply “Why not?”  It works.  You can test it by hooking your tests to the database.  Slow tests?  Nope, we hook the tests to an in-memory database.  The controller taking responsibility for filtering active products?  Hey, it’s the only place we use products, why make an abstraction just to filter them out?  We can always “refactor” later!

Now, I’d argue that the controller should be responsible only for orchestrating the interaction between the website and the application.  It should only set what page to show and what content to show on it, and that’s it.  But in a simple case like this, my solution requires more code.  You’d have to make the interface, you’d have to make the implementation for that interface, and you’d have to wire it up in your IoC container.  The tightly-coupled takes less code, so why not do that and make them more complex later if necessary?

Change Is Coming

I can give you one big reason:  Change is coming.  If this application is actually being used, it’s going to be changed to better fit the needs of its owners and users.  And when the changes come, the “abstraction-limited” solution quickly falls apart.

But let’s try this out.  Let’s say that a new rule comes down, and that I shouldn’t show products that are expired.  Now my call has:

   var products = MyDatabaseSingleton
                             .Products
                             .Where(x => x.IsActive)
                             .Where(x => x.ExpirationDate > DateTime.Now);

Now let’s say that if the user is signed in as an admin, then they can see everything.  

Now let’s say that if a regular customer is signed in, he can see only products that are associated to his company’s account.

Now let’s say that if a regular customer is affiliated with a company from Iran, they see no products.

Now let’s say that if the price of a product is zero dollars or less, we don’t want the product shown because there’s obviously a problem.

Now let’s say that we also want a sitemap page that shows the same products as this page, but with different views.

Somewhere along this list, the wise “it depends” developer will say “Of course, now it’s more complex and we have multiple uses, so we should refactor.”  This is what I mean when I say it’s easy to be an “it depends” type of developer, because you always have an out.

Seams are Important

When you hardcode your database access in your controller, you’re not just limiting your abstraction -- you’re limiting your seams.  As defined in “Working Effectively With Legacy Code,” Michael Feathers defined a seam as “a place where you can alter behavior in your program without editing in that place.”

The “product retriever” interface is more than just an excuse to use your fancy IoC container -- it’s a seam that we can use to restrict the changes to our product catalog to one place, rather than having them bleed all over our application.  I could make every change that I mentioned above without touching the controller again.  In fact, the only reason I’d have to change that controller action is if that particular action changed.  Business logic is stowed away to the place it’s going to be anyway.

Without the abstraction, changes unrelated to the site itself will bleed into the controller as soon as the first change comes through.  The only question at that point is how much bleeding the developer will allow before he adds the abstraction that he should have had in the first place.

You’re Writing Legacy Code From the Start

Another important idea from Michael Feather’s book is the definition of legacy code as “code without tests.”  And I honestly believe that you are headed down that path when you start in a position where you have no alternative but to rewrite when change comes.

Think I’m crazy?  Well, lets say you take testing seriously and you write the integration tests to cover your database-touching controller.  From my original example, you’ll have at least the following three tests:

1.)  The action returns an index view.
2.)  The action returns active items.
3.)  The action returns inactive items.

If you’re following TDD, you’ll probably have more tests than this, but that’s not what I’m arguing here.

Now the changes come.  

4.)  When admin is signed in, return inactive items.
5.)  When non admin is signed in, do not return inactive items.

Then more changes.

6.)  When geolocation suggests Iran, return nothing.
7.)  When price is zero, return nothing.

(etc)

Notice how you have more tests for data retrieval behavior than for your controller behavior?  That’s because your controller is doing more than it should be responsible for.

By now, most people would have figured out that a separate class for retrieving products is necessary.  But if you’re testing, you can’t just move the code -- you have to make the tests work too.  But what tests?  All of your tests are tied to a controller.  Are you going to painfully rip the database-related tests out into a new test class, rename classes, set up new variables, etc.?  Or are you going to introduce the abstraction but keep the tests on the controller?  Or are you going to just start over?  Or are you just not going to test?

I never want to say that testing is bad, but when you don’t respond to the problems they show you and when you don’t respect SRP, the tests you write almost make it harder to refactor.  You’re not just wrong -- you’re cemented in with a bunch of test code that continually verifies that you’re wrong.  

That little bit of time and code you saved by gluing your controller and database together is not much different than putting a glass on the edge of a table in my house.  You may get away with it.  Maybe the baby will not try to grab it.  But you know the baby is around, you know the baby likes to grab, and you know that he’ll spill it if he gets to it.  So why not just put in that tiny bit of effort to put the glass out of his reach?

If you had the IProductRetriever (or whatever you want to call it) abstraction in the codebase from the beginning, changes would be a lot easier today.

If You Really Want to Limit Your Abstractions...

Switch to Ruby.  Or some other language or system that doesn't require them.  That’s what I did, I’ve gone almost six months without creating an interface or touching an IoC container.  Due to the flexible nature of Ruby, I don’t have to give up the seams.  I’m always capable of hopping into any object or class and modify behavior on the fly.  And it’s a lot of fun.

I think that’s the real solution to the abstraction problem.  Don’t fight the language and don’t give up the tests.  If you’re coding in C#, stick with the methods that make testing easy (or possible) and try to make those simpler.  Yeah, you’ll have a lot of interfaces.  But when change comes, you’ll be ready.  

9 Jan 2012

I Didn't Leave .Net, .Net Left Me

If this was the blog post you’d expect from a .Net-to-Ruby developer like me, this is where the anti-.Net rant would start.  I’d explain that I’ve been a .Net developer for years, that I’ve built dozens of sites using Classic ASP, WebForms, and ASP.Net MVC, and that I came to the conclusion that Ruby and Rails was the way to go.  Then I’d list all the reasons why I came to that conclusion, and I’d call you stupid if you didn’t agree with me.  Then we’d have a bunch of arguments in the comments.

But this isn’t that post.  The truth is, leaving .Net would be an incredibly dumb action for a developer who has invested as much time in it as I have.  It has been a huge part of my career, I have a lot of knowledge with it that can still be applied to projects today, and I’ve been an active contributor to .Net OSS projects (both others and my own).  My past does not change because I got a new Rails job.  I love programming, and I always planned to stay the .Net community through speaking and open-source.

But after trying to execute this plan for two short months, I don’t think it’s going to be successful.  I have the desire and ability to keep going, but it’s not going to be enough to get me over the roadblocks that have been put in front of me.  And it all comes down to one single word:

Express

Visual Studio C# 2010 Express.  Visual Studio Web Developer 2010 Express.  SQL Studio 2010 Express.  I never understood the differences between all of the skus on Microsoft developer products, but I always knew what “Express” meant:  The free version.  I never concerned myself with the Express versions when I was working at a Microsoft shop that provided me all of the full versions, but I knew free versions existed and that they were “good enough” for those who don’t want to pay the price for the full-blown versions.

I was wrong, at least with Visual Studio.  Visual Studio C# 2010 Express’ features are so crippled, I barely recognize it from the Pro version I’ve used since launch.  VS Express doesn’t just block Resharper, it blocks all extensions.  No ViEmu.  No test runners.  No SpecFlow.  Not even Nuget is allowed!  

But it gets even worse:  Many common Visual Studio practices have been randomly removed.  No solution folders.  No cleaning solutions or projects!  I checked that I can, indeed, still change fonts and colors, but the long lists of options under “Tools,” “Options,” and the other menus are gone.  I can build projects and solutions, open files, and save edits, but that’s about it.

Bare-Bones Isn’t Enough

I can understand why Microsoft has to put some limits on the free versions.  It wouldn’t make much sense to offer a free IDE and then let a company like Jet Brains or Dev Express undercut the Pro version with cheap plugins.  

But what about SpecFlow?  SpecFlow is a free, open-source plugin that turns Gherkin into tests.  It’s one of my favorite .Net OSS projects, and it’s one I’ve made considerable contributions to.  Yet I, today, cannot use SpecFlow in Visual Studio.  Does that seem ridiculous to you as much as it seems to me?  SpecFlow is one of the best .Net-enhancing tools, a product that keeps .Net relevant in today’s programming world of things like test-driven- and behavior driven development, but its apparently better that programmers who don’t work for companies with MSDN subscriptions can’t be allowed to use it or make it better.

To be fair, I have to say that I can still contribute to SpecFlow.  And I recently did with this minor fix for a handful of date tests that were failing ouside of the US.

https://github.com/techtalk/SpecFlow/pull/155

This tiny commit used to take me a few minutes when I had Visual Studio Pro and Resharper.  I’m embarrassed to tell you how long this takes me today.  But working on anything with the Visual Studio integration is out, and the final check-it-on-a-set-of-real-projects testing phase that I used to put all of my SpecFlow contributions through is out.  

In other words, I can look at the project's code, but I can't touch the product.

Given what I’ve seen of Visual Studio Express and my experience with Visual Studio Pro, I’m surprised Microsoft wants developers to think that Express represents what Visual Studio offers in any way.

I Thought I Was One of the Good Guys

I’m not as big-time as some other .Net open-source developers, but I’m no slouch.  If you look at my Github page or my NuGet profile, you’ll see an active .Net developer.  I’ve made many contributions to popular projects like SpecFlow and MVC Turbine.  I’ve made small contributions to projects that I use regularly when I see opportunities for improvement, like to Simple.Data and PagedList.  And I have many small (but very useful, I think) projects of my own like AutoMoq, AutoMapperAssist, and plugins for MVC Turbine.  I think I can safely say that my code has helped hundreds, if not thousands, of .Net developers.

It doesn’t stop there.  I’ve been an active speaker in my region the past couple years, giving talks including BDD, SpecFlow, CQRS/ES, composite MVC, and MVC Turbine to Dot Net User Groups in Kansas City, Topeka, and (in two weeks) St. Louis.  I’ve given talks at the last two Kansas City Developer Conferences and the last St. Louis Day of Dot Net, and I’ve presented at the last two fall Iowa Code Camps and the first Nebraska Code camp.  I’m scheduled to give my “How Ruby Has Made Me a Better C# Developer, and a Better Man” talk to two Dot Net User Groups in the coming three months, and I’m working on more presentations for the year.

If you add in my big mouth on Twitter, Google Groups, Youtube, Vimeo, comments on blog posts, my study groups on books like Clean Code, The Clean Coder, and The Art of Unit Testing, my regular lunch & learns with coworkers, and my general help and advice to anybody that asks, I think most would agree -- I’ve made my section of the .Net world a little brighter.  I’m one of the good guys.

But if I want to continue I must pay Microsoft $800 now, and probably $500+ when Visual Studio 2012 comes out.  Or, I can shell out hundreds or thousands for my own MSDN subscription.

Obviously, hundreds of dollars is too much to pay to use the *real* Visual Studio just for open-source development.  The money aside, do you know how much marital good will I’d have to spend to get my wife’s approval on that type of financial commitment?  I’d never hear the end of it...

I can’t believe I used to give the iPhone guys grief for paying Apple’s $100-a-year developer fee.  I’d gladly pay that amount today.

The Alternative to Rage-Quitting

Wouldn’t this be easier if I were to rage-quit .Net for Ruby, instead of staying involved?  Then the lack of tooling and support would not matter, I’d go in one direction, .Net would go in another direction, and the bridge between us would burn down.

But I’m not going to rage-quit.  I’m not going to steal Microsoft’s property by using an unlicensed version, either.  I accept Microsoft’s position.  This is where they want to put developers like me, and this is where I’ll stay.  I’ll limp along with Express when I feel like working in a .Net project, I’ll do what I can, and I won’t do what Microsoft says I can’t.  

It’s kinda sad.  That’s all I can say.  It’s silly for me to tell Microsoft how to run its business, but it seems that creating a working alternative for the non-enterprise, open-source developers would benefit them.  It seems that I, and other developers like me, should be a prized asset for the .Net community and Microsoft -- even if .Net is not our day job.  But perhaps not?

So the next time you get mad at an ex-.Net developer's "Adios .Net Suckers" blog post, remember that this is our alternative.

The big lesson I’ve learned from this is that I should never let my career and day-to-day work become so dependent on one organization.  I thought I knew this, but I don’t think you *really* understand it until you reach the end of your leash.  
10 Aug 2011

Unity, and Lying about Performance

Before I write one word about Philip Mateescu’s post about Unity and IoC containers, I should state clearly:  

My IoC container of choice is Unity.

Why?  Well, it was the first IoC container I used on a real project.  And it worked out, so I used it on the next, and then the next, and then the next.  I knew how it worked, I trusted it, and I haven’t switched because I have no reason to take on another risk.

However, I am familiar with all of the popular IoC containers, except for Spring.Net.  I am a contributor to MVC Turbine, which contains a service locator abstraction for every popular IoC container (except Spring.Net).  I have worked on the service locator for every supported container.  I’ve even gone as far as spending hours on an AutoFac and Hiro implementation.

So while I’m a Unity fan, I’m no slouch when it comes to the rest.  In fact, I don’t care what IoC container people use, so long as they use it the right way.

The Accusation

A coworker of mine is a Castle Windsor fan.  So a couple days ago when he came across a post by Philip Mateescu that showed that Unity was orders of magnitude slower than *EVERY* IoC container, he made sure to show me.  But I still took a look, and found these types of numbers:

              10k - 1st  10k - 3rd  100k - 1st  100k - 3rd
------------------------------------------------------------
Autofac                25         23         166         163
Castle.Windsor         35         39         342         328
Ninject               128        133       1,053       1,040
Spring.Net             59         36         223         229
StructureMap          114        118         289         348
Unity               6,012      5,945      62,278      59,292

Yikes, right?  Unity is getting killed.  I’ve said before that the differences in the speed of the IoC containers isn’t enough of a factor to choose one over the other, but these types of numbers suggest that Unity is doing something incredibly wrong.  If these numbers were true, I’d stop using Unity today.

The Error

Philip posted his code on Github, so I took a look.  And sure enough, it didn’t take long to find the problem:



What’s that IsRegistered<T> call?  I’ve been using Unity for years, and I didn’t even know it had that method.  I never thought to even see if it did, as I’ve never had a need to check if a something was registered in my container.  

But more importantly, why is that IsRegistered call in his tests?  Philip certainly knows it’s being registered, as that’s exactly what he’s testing.  Plus, in multiple places in his blog post, he states that he’s testing the Resolve()-ing of each container... but he’s not.  He’s actually testing the combination of the IsRegistered method (which he does for every container) in addition to the Resolve().

So, I took out all of the type checks so each test just ran the resolve call.  And not surprisingly, the numbers were drastically different:
 

Chart_1
 These numbers show the four situations in which he was running the tests, and for 10K resolve calls. I don’t think it’s necessary to go over every iteration that Philip went through for the problem to be obvious: Unity’s numbers are very comparable to the rest. So far as these tests measure performance (which I think is still questionable), Unity is in middle of the pack.

The Lie

Normally, I’d consider this just a simple error and leave it at that.  However, the problem is -- Philip knows of this issue.  I checked him on Twitter, and there were three people who showed him this problem and told him how to correct it.  His responses?

@philipmatix: @roryprimrose in absence of IsRegistered you're left with handling ResolutionFailedException. pluggable apps need that check.

and

@philipmatix: @slaneyrw that's most likely true, but in a pluggable app you either check IsRegistered or handle ResolutionFailedExceptions.

Basically, because *Philip* believes that we should be calling this IsRegistered method before we resolve out of the container, then it’s perfectly acceptable to consider that part of the cost of resolving.

That is an opinion.  Not one that I agree with, but let’s say that I do.  And let’s say that everybody does.  Still, you have to make it clear how you are measuring something when you present numbers about those measurements.  He doesn’t.  Without someone actually spending the time to analyze his code and his measurements (which the majority of his readers aren’t going to do), they’re going to leave his post with the impress that Unity really is as slow as he states.  Which is not true, and he knows it’s not true.

Think about it this way.  Let’s say I wrote a blog post about how many calories are in the most popular hamburger buns.  Using Philip’s logic, I can say that a hamburger bun below is over 800 calories...

… because I have a personal belief that nobody should ever eat that hamburger bun without a big, delicious hamburger patty and fixings like this:


This is obviously a very bad way to measure things.  I believe Philip should either change his test methodology and make the proper changes to the results, or he needs to make it SO CLEAR to anybody who reads that post that he’s not testing just the Resolve method.

Throwing Stones

It’s bad enough that Philip has to report these bad numbers, but he also has to take a few swipes at the Unity team as he’s doing it.  In his post he questions their sanity, says Unity is weird, and a makes few other jabs.  And unlike most blog posts, he does not accept comments (which would be enough to help to fix the errors in his post).

In summary, he makes up these ridiculous tests, doesn’t explain what they actually are and takes unfair shots at devs who produced something of real value to a lot of people.  But worst of all:  He leaves the post out there despite knowing the issues, which will only lead to confuse more and more people that hit his blog post over the months and years.  

 
I believe he needs to take it down, just to prevent any further damage.  If he wants to compare IoC containers, great.  Just be accurate and fair about it.


 

19 Jul 2011

Testing with Simple.Data and SpecFlow

One of the most important lessons you can learn about tools like Cucumber and SpecFlow is the need to get your entire application into the specs.  When you execute your specs, you’re supposed to be running your application, not a bunch of stubs and mocks that won’t be in your live application.  That’s what integration testing is about -- testing the integration of all of the pieces that you (should) be unit-testing.

From my personal experience, one of the biggest hurdles to proper integration testing with SpecFlow is handling the database.  Let’s be honest, getting data in-and-out of a database can be a huge pain, even with today’s most popular tools.  In fact, data access can be so difficult, I and many others have actually left that part out of our specs.  We swap out in-memory databases, our specs run, we go green... and then we run our application and get a big database error.  Tests that go green when the app is broken aren’t that helpful, right?

Well, earlier this year I listened to a Herding Code podcast about a tool called Simple.Data, and it’s changed everything for me.  Over the course of a few months, Simple.Data has turned the most painful part of building an application into the most fun.  Simple.Data has removed the barrier between my specs and the database.  

Here’s a basic scenario.  I want to test that when someone submits a form to create an account, the account record is created in the database.  



Let’s start with the two steps here that relate to the database, “Given the following accounts exist” and “Then the following accounts should exist.”  The first is responsible for loading the accounts into the database, and the latter is responsible for asserting that records in the database match what is in the table.

The standard methods for doing data access can be pretty expensive, at least in terms of code and abstractions.  Heavy tools (like Entity Framework and NHibernate) require a certain amount of setup and wiring-up to specific objects and assemblies, and lighter tools (like direct SQL calls) sometimes require extra work or the loss of helpful libraries.

Enter Simple.Data.  Simple.Data is a library that makes data access incredibly simple, but without giving up the core features we want out of an ORM.  I’ll just show you the step definitions below and let the code speak for itself.



This code is pretty simple.  Before each scenario, the account table is cleared so each test will have a clean database.  In the “Given the following accouns exist,” SpecFlow’s CreateSet<Account>() method is used to quickly create a set of accounts from the table.  And in the “Then the following accounts should exist,” we pull out all of the accounts from the database and use SpecFlow’s CompareToSet to make sure that the records match what is in the table.

And Database.Open()?  That’s a Simple.Data method that finds a default connection string in my test config, connects to the SQL database, and returns a dynamic object which can be used to access the database.  

Pretty simple, right?  You can check out the full solution on Github at http://bit.ly/nlg177.  You can also read the Simple.Data wiki at http://bit.ly/nV8dYl, or listen a recent Herding Code podcast on Simple.Data at http://herdingcode.com/?p=305.


 

28 Mar 2011

Hiro is Fast (IoC container comparison in MVC Turbine)

Philip Laureano is one of the guys that I've been following on Twitter for a while.  He wrote LinFu and is one of those guys who can make sense of IL writing and other deep details of .Net.  So when he posted the following tweet a week or two ago that "Hiro" was released, I made a note to check it out.  

And check it out I did.  What I found was a simple and blazing fast IoC container.  In fact, I don't think calling Hiro "fast" is fair to Hiro.  You can read about Hiro on Philip's posts on CodeProject (Part I, Part II, Part III, and Part IV).  Basically, what Philip claims Hiro provides is inversion-of-control that runs just as fast as if you were using no IoC.

What's that, you say?  IoC containers slow your app down?  Yes, they do.  Using an IoC container can be considerably slower than using the "new" operator to instantiate your objects.  It's not a difference most people ever notice because we're dealing with milliseconds, but it is there.  Hiro claims to practically eliminate that loss in speed while still allowing you to use an IoC container.

What's the catch?  Well, Hiro doesn't do much other than basic IoC.  You can register mappings between interfaces and concrete types.  You can register singletons, single instances, and functions.  You can register multiple mappings with a simple string key.  And once you are done setting up, Hiro will create a single, immutable container that you can use to get things back out.  No out-of-the-box lifetime management, XML configuration, child containers, or m of the other bells and whistles that come with the more mature IoC containers.

Now, before you dismiss it becuase you think all of those extra features from StructureMap, Ninject, and the like are necessary, I'd like to throw out a fact:

A lot of good software is written without an IoC container.

I know, I know.  As a .Net developer, I was pretty shocked when I learned this.  Once I started to open my eyes to how others build software, I realized that many of the things I took for granted in the .Net world were not even a thought in other communities.  Yet, people were still building good, SOLID-principle-following, TDD'd software development without first setting up their IoC container.  

That doesn't mean IoC containers are bad or we shouldn't use them.  Quite the contrary -- I think there are certain aspects of .Net and C# (most notably, static typing) that can make life pretty difficult for those who who want to go it alone.  In fact, I'm of the opinion that it's almost ridiculous to build a .Net application without some sort of IoC tool..  However, there are many varying opinions about for what and how we use them.

MVC Turbine

If you haven't heard of it, MVC Turbine (written by Javier Lozano) is a project that has been making dependency injection available to Asp.Net MVC developers since version 1.  It makes a few slight modifications to the MVC framework that opens the framework for extension by applying a few simple conventions and leaning on the IoC container.  

Not only does MVC Turbine make Asp.Net MVC application development easier, it's also a shining example of how .Net developers should approach dependency injection.  With Turbine, you define how you want to use your IoC container, and that definition can be applied to any IoC container.  It cuts to the essense of what IoC should be in .Net:  When someone needs an IFoo, you tell Turbine you want them to have Foo, or these IFoos, or this Func<Foo>.  Everything else an IoC container provides is probably an extension on these basic ideas.

The Speed Test

Currently MVC Turbine has adapters for StructureMap, Unity, Castle Windsor, and Ninject.  Since Hiro looks so promising, I decided to write an adapter for it.  I think that adapter is just about done, so now I'd like to demonstrate the numbers I'm seeing.

This demo project is a MVC Turbine V3 (not officially released yet) application.  I have five IoC containers ready for testing in it (StructureMap, Unity, Castle Windsor, Ninject, and Hiro).  I created a relatively complex set of related interfaces and implementations, and separated my tests into three groups:  

  1. No Dependencies:  I instantiate 100,000 instances of a controller that has no dependencies.
  2. A Few, Simple Dependencies:  I instantiate 10,000 instances of a controller with a few, simple dependencies.
  3. Many, Deep Dependencies:  I instantiate 1,000 instances of a controller with many dependencies, with some of them that go many layers deep.

And here are my results (all in milliseconds):

No Dependencies (run 100,000 times)
Hiro: 60-75
StructureMap: 150-190
Unity: 230-250
Windsor: 3200-3400
Ninject: 1900-2200

Few Dependencies (run 10,000 times)
Hiro: 5-10
StructureMap: 90-105
Unity: 150-175
Windsor: 750-850
Ninject: 800-1000

Many Dependencies (run 1,000 times)
Hiro: 7-15
StructureMap: 125-155
Unity: 1800-2000
Windsor: 6400-6800
Ninject: 8000-9000

Where's Autofac?  I'd gladly include Autofac if I could get a clear, unchanging version that follows the same basic approach and philosophy as the rest.  And yes, I'm bitter about it.

If you want to run these numbers yourself, just clone the project on Github and run them for yourself.  Just open up global.asax, uncomment the service locator you want to use, and hit F5.  At the very least, you can see how much faster your computer is than mine.

So What?

As you can see with these numbers, Hiro is very fast.  Incredibly fast.  It's already heads-and-shoulders above the other IoC containers for basic stuff, but it leaps into an entirely different league when dependencies start to come into play.  While the other IoC containers work harder and harder to figure out what they're supposed to do, Hiro continues to follow a consistent, pre-compiled path.  It's an IoC container that scales very well to the work it is given.

That said, who needs this type of speed and scale when it comes to dependency injection?  If you're instantiating thousands of objects at a time like my demo, you have bigger problems than your choice in IoC container.  For practically all of the situations you're probably going to encounter, any of these IoC containers are fast enough.  And if they have tools that make your development life better, you'll be getting something in exchange for the milliseconds that you're never going to notice anyway.

So don't use these numbers alone to judge which IoC container you should use.  I wouldn't even hestiate to use Windor or Ninject in a real application, so long as I had legitimate, objective reasons for doing so.

However, these numbers should still count as facts when making that objective decision on which IoC container to choose.  Given what I've learned about Hiro while writing the MVC Turbine adapter and running these tests, I think Hiro deserves to be included in the group of commonly-considered .Net IoC containers.  I know we have a lot of good, mature ones, but Hiro is very special -- both in its approach and the results it gives you.  

One More Hand for MVC Turbine

In case you hadn't noticed, my demo project offers a way to swap out IoC containers by editing one line.  Repeat:  My demo project offers a way to swap out IoC container by editing one line.  Wow, right!  

This isn't important because developers will want to swap out IoC containers often.  Hardly.  The real value is that MVC Turbine allows me to write code that leverages an IoC container without defining what IoC container I'm using.  This means that I can write modules that use IoC that can be used by StructureMap users, Unity users, Windsor users, etc.  MVC Turbine lets me define how I want to use my classes, and it handles the details.

If MVC Turbine was more widely adopted, MVC developers would be able to share common dlls that include packaged functionality (including controllers, routing, views, IoC setup, etc.) that could be sucked into any application, no matter what IoC container it runs under. It could essentially make every developer's IoC choice into just that -- a personal choice -- instead of a decision that further segregates him from the rest of the .Net pack. If you haven't tried MVC Turbine, you ought to give it a try.

So yea for MVC Turbine, and yea for Hiro!

23 Mar 2011

Stop Using Mocks - A Rebuttal

This morning, I opened my Twitter client to find a cheerful tweet posted by Karl Seguin (@karlseguin), who stated:

"I'm pretty close to the opinion that if you are testing with Moq, you simply aren't testing properly."

Yeah, I know it's bait, but I still responded.  After some talk with me and others, Karl graciously wrote a blog post explaining what he meant.  In his post titled "Stop Using Mocks," he wrote about the "plague" of which the .Net community suffers -- a lack of understanding of what stubs and mocks are.  And since he thinks that...

"The fact though is that if you aren't testing properly, you might as well not test at all."

... he took the time provided a clear example of what he meant, with a code sample, a test that the average .Net developer might write (incorrectly), and a set of tests that he thought were properly written.

Before I get into this, I want to say that I think this is an important discussion to have because it gets down to some fundamental approaches to testing and design.  This is even a discussion I've had recently with peers over a set of tests that look eerily-similar to the ones Karl provided.  And since I had already had that debate, I knew how to break Karl's tests as soon as I read them.  

Test Driven Design

Karl provided the simple example

Here's my first disagreement with him. If you're practicing TDD, what you'll want is to produce tests that mold the production code to that which will produce the expected results.  If you're not practicing TDD, you'll look at production code and make assumptions about how best to write tests for it.  

Yes, I know that TDD isn't the subject of his post, but I think it's what shapes the entire discussion.  He took a piece of pre-written code and stated that there were FIVE things that he wanted to test about that code.  If we were going test-first, we'd have to take our requirements and then figure out what tests to write to satisfy them.

For example, given what I know about his sample, it seems that what we need is a class that will return a user if a user/pass match.  If they don't, we get no user.  So based on that, here's how I'd start my tests:

  1. Test that if the username and password match a user in the system, return that user.
  2. Test that if the username matches but the password does not, we return no user.
  3. Test that if the username does not match, we return no user.

That's about as simple as it can be.  I see three tests, and they are all tied to actual business requirements -- not preexisting code, and not even dependencies or any existing code.  I state what I need, I write the failing tests, and now the question is:  How do I make them pass?

Testing Internals

The danger in writing tests after-the-fact is that it's sometimes easy to see the need for tests for code-based things that have no tie to business requirements.  Take his "LoadsTheUserFromTheDataStore" test: 

[Test]
public void LoadsTheUserFromTheDataStore()
{
  var store = A.Fake<IDataStore>();
  new UserRepository(store, A.Fake<IEncryption>()).FindByCredentials("Leto", null);

  A.CallTo(() => store.FindOneByNamedQuery("FindUserByUserName", "Leto")).MustHaveHappened(); 
}

This test asserts that the username was passed to this particular data store method.  What happened to the results?  Don't know.  

It could be said that making sure that result is returned is the responsibility of another test, which Karl also provides:

[Test]
public void ReturnTheValidUser()
{
  var store = A.Fake<IDataStore>();
  var encryption = A.Fake<IEncryption>();
  var expected = new User();

  Any.CallTo(store).WithReturnType<User>().Returns(expected);
  Any.CallTo(encryption).WithReturnType<bool>().Returns(true);
  var user = new UserRepository(store, encryption).FindByCredentials(null, null);

  Assert.AreSame(expected, user);
}

So here's the test that shows that the user is returned when... any username and password is used?  

You could say the two, combined, will work.  You'd be wrong, but let's say you're right.  What will these tests mean to another programmer who is approaching the problem from the point-of-view of a contract the code is supposed to satisfy?  This programmer needs to be able to see the username and password go in, and the user returned.  That simple fact is nowhere to be seen in the code, and instead has to be derived by looking at multiple tests and the production code itself.

Complex Tests Don't Work

Karl explains why he doesn't like how the average .Net developer would test this, but I think that .Net developer has one thing going for him -- his tests throws exceptions for obvious errors.  I said earlier that I knew how to break his code, so here it is:

This code still passes Karl's tests, despite the obvious problems.  

The tests still fail because what they're testing for is still happening.  Does the class check for a matching password?  Yes.  Does the class pull an user out of the data store?  Yes.  Does it call the data store with the username passed in?  Yes.  

Does it ever check that all of these micro-unit tests are ever run together, as a single unit, to test the business requirement?  No.  And since it doesn't test for that, it's not hard to modify the production code in such a way that violates the requirement but still passes the other tests.

I don't mean to poke at Karl's examples, especially since they were written in a blog post instead of Visual Studio (yet I could still copy-paste them into VS and run them, kudos Karl).  However, he's is stating that much of the .Net community is doing it wrong, that we don't understand testing, and that this is how we should do it.  If we're the ones that are wrong, why is it that the "wrong" example test he provides will fail when the production code breaks yet his won't?

Hit Me Back

If I'm going to tear down something, it's only fair that I offer an alternative.  Now, normally I'd use some combo of SpecFlow with MSpec, but since Karl's examples were NUnit tests I'll show you my TDD'd result.  I'm using AutoMoq, a small auto-mocking container I wrote that hides away some of the ugliness of passing around stubs/mocks/fakes/whatever.  I also love to refactor my unit tests into something that reads more like English and less like lambda-e.  But all of my personal preferences aside, I think these tests are aligned more with the intent and would be easier to maintain and understand in the long-term.

And if you don't like them, please write a long blog post bashing them -- I can take it.  Hey, this is how we all get better, right?

 

14 Feb 2011

My Response to "Whose Domain Is It Anyway?"

On the SpecFlow Google Group, someone brought up Dan North's recent post, "Whose Domain Is It Anyway?" and asked the following question:

Which approach do you prefer? 

1) One single step for each human action, thus providing more reusability? 

2) Dan North's suggestion, to have a "generic" step "When the user submits valid credentials"? 

I'm making my response to him my first post on this blog:

 

I prefer neither.  I think this is actually a situation where writing something *more specific* will make the spec more understandable and reusable.  This is how I might do it: 

Scenario: User with valid credentials 
   Given the following login credentials exist 
   | AccountId | Username | Password | 
   | 1         | john       | galt        | 
   | 2         | howard   | roark    | 
   | 3         | hank      | rearden  | 
   When the user submits the following login form 
   | Field         | Value   | 
   | Username | howard | 
   | Password | roark     | 
   Then the user should be logged in as account 2 

There are a few reasons I do it this way: 

1.) Understandable:  If at all possible, I want someone to be able to see what makes up a scenario by reading the steps.  If your scenario title is "User with valid credentials" and all your steps say is "When the user enters a valid name in the Name field" or "the user enters a corresponding password" or "When the user submits valid credentials," nobody except the programmer knows what "valid" means. 

Does it mean the username and password match?  Case-sensitive match? Or not?  Let's ask the programmer to look in the step definition code to get the real meaning! 

2.) Reusability:  When my steps are this detailed, they become ultra-reusable because they describe a single "thing" or concept in the system.  If I added one more step, "Then the user should not be logged in", I've pretty much covered every possibility with that login system.  That means I'll spend most of my time switching between my text feature file and my production code, *NOT* my step definitions. 

Look at it this way:  If you say "the user enters a valid name in the Name field," what are you going to do when you need to handle an invalid name?  Write another step.  If you say "When the user submits valid credentials," what are you going to do when you want to handle an invalid credential?  Write another step. 

If we're writing lots of steps, our steps are obviously not reusable. 

3.) Maintainability:  When you say things "the user enters the corresponding password in the Password field," what do you mean?  The password that corresponds to "the user enters a valid name in the Name field?"  Doing it this way, you are gluing your steps together. 
What's worse is, it might be very hard for another developer to be able to see this invisible tie, and might use the step in another feature or scenario without knowing. 

I don't think Dan North's example is any better.  If you say "When the user submits valid credentials," you are not just talking about submitting particular form values -- you're talking about data in the database.  What data?  What form?  What does it mean to be valid? This step has now just glued completely different things together. 

Add in the fact that you have to create lots of these glued steps because of the reusability issues in (2), you are in some maintainability trouble. 

4.)  Extension:  Dan North brought up the case of OpenID, and how raising the abstraction in the way he words his steps ("the user submits valid credentials") lets him reuse it when writing a scenario surrounding protecting access in another feature.  I have a couple things to say about that: 

   a.)  When we're talking about the login screen itself, adding extensions like OpenID/Facebook Connect is very easy when you are detailed in your steps.  Since clicking an OpenID/Facebook/Twitter link is very different than submitting a login form, you just have to create another step.  Like this: 

   Scenario:  A user logs in with Facebook Connect 
      Given a Facebook authentication token 'TOKEN' will return the following Facebook user 
      | Field           | Value    | 
      | FacebookID | 1234     | 
      | FirstName    | Ellis    | 
      | LastName   | Wyatt    | 
      When a user clicks the Facebook Connection button and returns this authentication token 'TOKEN' 
      Then the user should be logged in as Facebook user 1234 

   b.)  Dan North's example is a scenario that crosses two features, a Login page and a page that offers restricted content.  He's chaining a series of behaviors together.  It all works great when you're just getting started, but what happens when the change tide comes in and the login scenario changes?  The restricted content page breaks.  And it breaks for the *wrong* reason, which is that the part of the login feature "When the user submits valid credentials" is being repeated across any other feature that wants this redirection behavior. 

   Here is how I might change things: 

   # Restricted content feature 
   Given an unauthenticated user 
   When the user tries to access restricted asset 5 
   Then they should be directed to the login page with a request to redirect back to '/Asset/5' 

   # Login page 
   Given the following login credentials exist 
   | AccountId | Username | Password | 
   | 2             | howard   | roark    | 
   And the user came in with a redirect request for '/SendMeHere' 
   When the user submits the following login form 
   | Field         | Value   | 
   | Username | howard | 
   | Password  | roark   | 
   Then the user should be logged in as account 2 
   And the user should be redirected to '/SendMeHere' 

5.)  I know the way I'm suggesting you write these specs makes them almost seem like unit tests, and project managers/owners won't be able to follow them.  This might be because of the people I work with, but I've found that project managers appreciate detail when it's detail they can *understand*. 

 

 

 

Darren Cauthon's Space

Husband, father, programmer, Objectivist, tuba player. I write software with TDD.