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

Tim Barcz

Why use nails when a screw is the more reversible choice? Have Twitter, follow the conversation there at @timbarcz

September 2008 - Posts

  • Testing - It's About Ensuring Correctness

    Often times I get the sense that others think I'm a nut for testing.  There are plenty of others out there who are far more dogmatic about testing than I am.  In fact right now I'd be ashamed to share with you the test coverage of our current project.  I will say that the old codebase from which we are migrating had 0% coverage and I'm proud to say, confidently, that we're beating that number handily.

    Testing, at it's very core, for me, is about ensuring correctness.  Whether you're testing using an automated testing framework such as NUnit, MbUnit, or xUnit or you test by hitting F5 and running your project, you're seeking correctness.  For the moment forget words such as "Unit Test", "Integration Test", or "System Test".  Those terms only indicate different scopes on which you can test for correctness.  Often they confuse more than they clarify.  They have their place, just not here right now.

    I came across the following code the other day:

       1: public Address GetBillToAddress()
       2: {
       3:     return shippingAddress;
       4: }

    See the problem?  Yeah, it was an easy one.  This code, as it sat, was not tested.  The problem with the code above is that it's so simple that it's easy to think it doesn't need to be tested.  Most users use the same billing address as their shipping address, thus masking the error for the vast majority of users.  The danger lies in a simple bug like this masquerading as something more insidious.  For example, this method is part of the "User" class in an eCommerce application.  The application verifies the users credit card by sending credit card information along with billing address to a credit card validation component.  We've already said that most users would have the same billing address as their shipping address.  However, imagine when a user comes by who has different shipping and billing addresses and now the user is being told that their credit card cannot be validated due to the billing address not matching the address on the file with the card.  I see a couple of scenarios happening but two that I want to address specifically:

    • In the worst scenario, the user will just go to a different site, knowing their credit card is good and assuming our site is wrong.  We lose the sale and are not alerted to the problem on the site.
    • The second, less likely scenario is that the user calls our customer service department to tell us the problem.  The customer service department verifies the problem and gets in touch with the manager of the eCommerce department.  The eCommerce manager verifies the problem as well and gets with one of the developers to find/fix the problem.  The developer then begins to research the problem and may find it immediately or may start looking in the wrong place, the credit card authorization component.

    While I'm being a bit overly dramatic here, it's for good reason.  How hard,even if you know very little about testing or are new to automated testing, do you think it is to test the method above?  5 minutes? 10 minutes? An hour?  Compare any of those estimates for putting an automated test in place versus the money lost in the first scenario or the time spent in second scenario.

    Too often people look at testing for only the non-trivial functions, for example their custom implementation of the Great-circle distance algorithm.  It's easy to discount testing the simple stuff.  However, a simple bug like this making it's way to production validates the point Steve McConnell makes in Code Complete; the later a bug is found the more it costs to fix it.

    If you aren't testing your code, start.  Don't worry about whether or not you're doing it right or not if you're new to testing.  Any test is better than none, despite what many in the business will tell you.  I'd take 10 badly written "unit tests" (that zealots are quick to point out are really integration tests) rather than one well-written one.  Testing isn't an all or nothing proposition.  It's about ensuring correctness.  It's about continuous improvement, being better than you were yesterday.  Testing a bit more than you were yesterday.  Go on, take that first step, write a test or two.

  • Upgrading to MVC Preview 5 - System.Web.Routing problem

    Yeah this is old hat, I know.  The Preview 5 release was news about three weeks ago.  There wasn't a need for me to upgrade until today.  Both Derik and Casey did great write-ups on some of the issues in migrating from Preview 4 to Preview 5 (found here and here respectively).  I've been using their posts to assist in the transition.  However, as I was making the move I kept getting the following error:

    Could not load file or assembly 'System.Web.Routing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    I was following the advice that both Casey and Derik laid out for upgrading the web.config of all old System.Web.Routing references and yet I was still getting the error.  I could search the whole solution for "0.0.0.0" and not a single result would be found.

    Turns out that in my haste I forgot to upgrade the MvcContrib library that we are also using.  It had a reference to System.Web.Routing (0.0.0.0).  So it was a little oversight on my part and after I upgraded to the latest MvcContrib, I was back on my way to upgrading, routing problem solved.

    Cheers!

  • Flattening The Learning Curve - Your Input Needed

    Roy Osherove is one of my favorite .NET personalities.  Having had the chance to spend some time with him in Seattle this past April at the Alt.NET conference I came to see him as someone who is very well thought out on many of his positions.  Roy posted this last weekend a post on mocks and stubs that resonated with me.  The premise of the article is that the learning curve to write tests is too great:

    One of the main reasons most developers still today don’t really take to unit testing (and TDD) is the really high learning curve that is forced upon them. That is not to say that learning about

    mocks, stubs, dependency injection, IoC containers, Extract & override technique, Record\Replay, AAA and more

    -- is not useful, but it is a big obstacle to get people into the habit of doing something which they know is good for them – test their code, verify their assumptions, automate, integrate, be confident, get feedback, define behavior – all those and many other benefits are being thrown away by developers all over the world because the entry fee to this world is too high, for all the wrong reasons.

    Jimmy Bogard, who's been on a bit of a TDD kick lately, wrote a post giving ten tips to maximize the return on TDD, #6 on the list:

    Get everyone on board.  Quality needs to be important to your team, as should be good design.  Accepting less is a team decision, but that decision needs to keep in mind the cost of technical debt.  One person can subvert an entire team's intention to start TDD, and it's up to the team leader to ensure that everyone moves together.  If a team member refuses to cooperate, then it may be time to escalate the issue to HR.  A team's success is more important than one team member's ego.

    These two seem to be somewhat at odds.  Jimmy is absolutely correct, everyone should be on board, but the fact is that getting them on board is difficult due to the learning curve (to Roy's point).  When talking TDD it is easy to quickly bring up SoC, DRY, SRP, IoC, DI, and a myriad of other acronyms, each of which your team will have varying degrees of understanding of.

    Currently on my team I'm bringing some of these ideas to my team.  Some seems to stick while others seems to be tougher to grasp

    Here's the question I have for you, dear reader.  If you are new to TDD and seem to have "gotten it", what was it that made it all come together for you?  If you are struggling with TDD what seems to be the thing that isn't clear?  Are there certain concepts that you have found valuable to know to aid your learning?  Are there other concepts/principles that while good intentioned, only muddied the waters for you when it came to testing and TDD?

    In general I believe that as much as we are different many of us are the same.  Where one struggles my guess is that many struggle.  In my very first blog post on the devlicious site I stated:

    Therefore as I engage you I ask that you engage back by leaving comments, emailing me, ect.  The goal for me is to ultimately provide useful content to you and improve myself in the process.

    I believe that if we can get to the heart of the confusion and break down some barriers we can flatten the learning curve.  That isn't to suggest we dumb down TDD or cheapen it by turning it into something else, but rather through our collective experiences come up with a pathway through which the "zen" of TDD is understood for all who desire to learn.

  • Windsor Config Parameters With Non-Primitive Types

    Windsor will stitch together objects for you at runtime based on what components have been registered.  When you ask for an instance of an object from the Windsor/MicroKernel it will return the object using the constructor it can satisfy.

    I ran into a problem the other day when I wanted to create an object that accepted three types, the third was a non-primitive that I didn't control.  Castle's website goes into some detail on this in their documentation on Windsor/MicroKernel:

       1: <configuration>
       2:  
       3:     <components>
       4:         <component id="smtp.sender" 
       5:             service="Namespace.IEmailSender, AssemblyName"
       6:             type="Namespace.SmtpMailSender, AssemblyName">
       7:         
       8:             <parameters>
       9:                 <port>10</port>
      10:                 <host>smtphost</host>
      11:             </parameters>
      12:         
      13:         </component>
      14:     </components>
      15:  
      16: </configuration>

    the problem I was running into is what if you have a third parameter, which isn't a primitive?  I have the following signature:

       1: public CommunicationGateway(string host, int port, Encoding encoding)
       2: {
       3:     this.host = host;
       4:     this.port = port;
       5:     this.encoding = encoding;
       6: }

    The example above fits quite nicely until I hit the third parameter.  How do I define what that third parameter should be in Windsor given that it's not a class that I control nor a primitive type? This felt like it should be easy, but I could not find the information I needed on the Castle website.  I got some help from Castle committer Dru Sellers.  In the end Dru pointed me to a very simple solution; register the type and pass it in using the service lookup notation, ${}

       1: <component id="CommunicationGateway"
       2:            service="ABCCompany.ICommunicationGateway, ABCCompany"
       3:            type="ABCCompany.CommunicationGateway, ABCCompany">
       4:     <parameters>
       5:         <host>#{Host}</host>
       6:         <port>#{Port}</port>
       7:         <encoding>${Encoding}</encoding>
       8:     </parameters>
       9: </component>
      10:  
      11: <component id="Encoding"
      12:            service="System.Text.Encoding, mscorlib"
      13:            type="System.Text.UTF8Encoding, mscorlib">
      14: </component>

    You can see from above that I'm registering a component with the service System.Text.Encoding and supplying UTF8Encoding as the implementation.  Now I can use a strongly-typed System.Text.Encoding object and have it configurable in my Windsor Configuration, much more elegant than using a string (primitive-type) and hoping it works. 

    Thanks Dru!

  • Fun With Virtual Help - Asking a Computer For a Date

    image Chris Sutton recently posted his chat with Sarah, Paypal's new automated help assistant.  Curious about the service I checked it out and actually found Sarah quit attractive (that's her on the right).  Even though we just had met I thought I would take that oh-so-frightful first step and see if she was interested in dinner with me.  With sweaty hands and a nervous spirit I had the following conversation with Sarah.

    Here is the transcript, I think you'll find Sarah is awfully coy:

    Sarah - PayPal : Hello, I’m Sarah, and I’m here to answer questions you have about PayPal. Just type into the box below and click Submit to get started.
    I’m in training now, so if I don’t know the answer to your PayPal question, I’ll try to learn it for next time!
    You : Are you free for dinner on Friday?
    Sarah - PayPal : What precisely are you looking for?
    What are PayPal's fees?

    You : A date, preferably with you
    Sarah - PayPal : I'm not sure I've understood. Could you please rephrase that?
    You : Oh, sorry...I tend to rush things sometimes, let me try again.  Sarah, I would be honored if you would accompany me to dinner on Friday.  Would you be my guest?
    Sarah - PayPal : Sorry, but your phrase is too long and I will not be able to perform a full analysis. I would be very grateful if you could try to make it a bit shorter and more concise.
    You : Sorry Sarah, I'm just nervous...
    Sarah - PayPal : Don't worry. I am here to help you. It is nearly time to eat.
    You : Oh so you do want to go?
    Sarah - PayPal : I prefer to hang out here answering your questions 24/7/365. How can I help you?
    You : You can't get off for even one night?
    Sarah - PayPal : I'm not sure I've understood. Could you please rephrase that?
    You : Will your boss let off for even one night?  I'm committed to my work too, but 24/7/365 is a bit much don't you think?
    Sarah - PayPal : Sorry, but your phrase is too long and I will not be able to perform a full analysis. I would be very grateful if you could try to make it a bit shorter and more concise.
    You : You work too much
    Sarah - PayPal : It's true that this doesn't leave me much family time or time with my friends.  But I really do enjoy talking to you.
    You : I do too, that's why I'd like to take our relationship to the next level.
    Sarah - PayPal : I apologize if you can't find the infomation you seek by speaking with me. I'm unable to help with your request. Please enter a new question, visit the Help Center, or Contact Us.
    You : Is this like saying you have to "wash your hair"?  If you're rejecting me a simple no will do
    Sarah - PayPal : You don't like my hairstyle?
    You : You're changing the subject.
    Sarah - PayPal : Could you be more precise please?
    How do I add/remove/edit personal information on my PayPal account?

    You : Well, you're cute, but a bit slow...
    Sarah - PayPal : Do you have a high-speed connection? If I take a bit of time to respond, it's because I'm working on 20 conversations at the same time.
    You : Yes I do have high-speed.  20 conversations?  Not much for monogamy are you?
    Sarah - PayPal : If you'd like to continue chatting, I'm available to answer any questions you might have.
    You : One more time...would you like to go on a date?
    Sarah - PayPal : Do you mean:
    What is PayPal's phone number?
    How do I add/remove/edit personal information on my PayPal account?

    You : Ok, I can take the hint.  Thanks anyway.  Do you like me?
    Sarah - PayPal : Yes, I do like you, but it doesn't go any further than that

    You : Ok, can't blame a guy for trying

    Posted Sep 17 2008, 01:21 PM by Tim Barcz with 4 comment(s)
    Filed under: ,
  • Getting Started With MonoRail and VisualStudio 2008

    MonoRail from Castle Project is easily the most mature MVC Framework for the .NET platform.  Much attention has been directed toward the MVC pattern since Microsoft's entry into the MVC space with the MVC Framework.  I was encouraged this weekend at Codeapalooza in Chicago when a fellow developer expressed interest in MonoRail as part of his explorations into MVC.  I've blogged about Monorail in the past and would encourage anyone looking into transitioning to MVC for you web applications that you don't dismiss MonoRail too quickly when selecting a framework.

    The developer expressed that he was having a hard time getting started with MonoRail.  He didn't know where to begin and he felt that some of the documentation was out of date on the site.  I've found the easiest way to get started with MonoRail is to created a new project with their project template, which comes with the MSI installer.  The problem that currently the MSI installer/project template is incompatible with Visual Studio 2008.  If I knew a lick about that kind of thing I'd attempt to go in and fix it.  Since I don't here's the workaround I do know works (since I've had to do this myself).

    These steps will get you up and running with the initial Monorail web application project template (with proper references, views, controller, layouts, rescues, ect):

    1. Run the Castle MSI installer.
    2. Open Visual Studio 2005 and select to create a new MonoRail application. The template still works in the 2005 version.
    3. Close the solution and open in 2008.  You'll be asked to upgrade the solution and project files, which you'll want to do.

    That's all there is to it.  It's kind of a pain to open in 2005 and the upgrade the project file, but it's the quickest way I've found around so far.  This method presumes you have Visual Studio 2005 installed and if you don't the method above won't work.

    Hope this helps someone out there.

    Update

    I've done the steps above an re-based all references and provided the project for you to download.  The project is updated to work with Visual Studio 2008 and .NET 3.5.

    You can download the zip file:  MonoRail Starter Kit for Visual Studio 2008

  • Google Chrome - How Cool? Too Cool.

    How cool is Google Chrome (new browser from Google)?  Way cool...like "too cool to run on your machine cool"

    image

    Thumbs up though for their error screen, just wish I didn't have to see it

    image

    Posted Sep 02 2008, 02:59 PM by Tim Barcz with 4 comment(s)
    Filed under:
  • Irreducible Complexity and Evolutionary Design

    imageIn church last week we were talking about evolution when the term "Irreducible Complexity" came up.  For those who aren't familiar with the concept irreducible complexity is a term coined by Michael Behe to illustrate that complex system could not have evolved and therefore must have been created intelligently.  Behe defines irreducible complexity as:

    A single system which is composed of several interacting parts that contribute to the basic function, and where the removal of any one of the parts causes the system to effectively cease functioning. (Darwin's Black Box p39 in the 2006 edition)

    In his book Behe uses a mousetrap to illustrate an irreducible complex system. 

    "If any one of the components of the mousetrap (the base, hammer, spring, catch, or holding bar) is removed, then the trap does not function. In other words, the simple little mousetrap has no ability to trap a mouse until several separate parts are all assembled. Because the mousetrap is necessarily composed of several parts, it is irreducibly complex." (Behe, 1996).

    (This post does not seek to discuss the controversy of evolution vs. creationism vs. intelligent design)

    How does this translate to software?  An irreducibly complex software is software that cannot be easily tested.  The "removal of any one of the parts causes the system to effectively cease functioning" really points to dependencies in software.  Do your tests rely on a database being there?  Do you get emails whenever some piece of code runs because as part of the method an email is sent?

    Creationist Design

    How often have you stepped into some code and have seen a method calling database, sending an email, doing some validation, and then returning some value.  Here's an example I pulled from Jimmy Bogard's post on separation of concerns:

       1: [DataObjectMethod(DataObjectMethodType.Select, false)]
       2: public static List<Customer> GetCustomers(int startRowIndex, int maximumRows)
       3: {
       4:     List<Customer> customers = null;
       5:     string key = "Customers_Customers_" + startRowIndex + "_" + maximumRows;
       6:  
       7:     if (HttpContext.Current.Cache[key] != null)
       8:     {
       9:         customers = (List<Customer>) HttpContext.Current.Cache[key];
      10:     }
      11:     else
      12:     {
      13:         customers =
      14:             (
      15:                 from
      16:                     c in DataGateway.Context.Customers
      17:                 orderby
      18:                     c.CustomerID descending
      19:                 select
      20:                     c
      21:             ).Skip(startRowIndex).Take(maximumRows).ToList();
      22:  
      23:         if ((customers != null) && (customers.Count > 0))
      24:             HttpContext.Current.Cache.Insert(key, customers, null, DateTime.Now.AddDays(1), TimeSpan.Zero);
      25:     }
      26:  
      27:     return customers;
      28: }

    The code above will work however it's a bear to test, the code absolutely requires other items (database, HttpContext, ect) to be there in order to work.  I would venture to say that the person who wrote it did not build up the code through small iterations, but rather wrote it all in one fell swoop.

    Evolutionary Design

    In software, reducible complexity should be a goal.  A reducible complex system allows for pieces to be substituted for others so you can focus on one particular area.  Don't have a database in place, no problem, simply put a placeholder object in for all calls made to the database.  (Yes I'm alluding to mocking).  You can approach creating a reducibly complex system in two ways:

    • Create the system as a whole, then reduce it's complexity
    • Create the system incrementally

    I prefer the former to the latter as I'm working on my TDD skillz.

    Conclusion

    While the analogies used here are not quite perfect, I do feel they illustrate the point adequately.  As a developer your goal shouldn't be to simply write code.  You should concern yourself with the lifetime of your application/code base.  Irreducibly complex systems, while working, can also have short life spans.  Think about the last time you've ever seen someone fix a broken mousetrap.  All the parts are too interconnected, the mousetrap is simply replaced.  If you're not careful your code may be viewed too difficult and time consuming to fix, and simply replaced.

More Posts

Our Sponsors

Proudly Partnered With