October 2007 Entries

TalesFromTheSmellySide<Code> - Episode #1

 

What is this?

Well, it was inevitable that my long stint of greenfield projects was going to come to end at some point, especially since I'm in the consulting world.  So now that I'm starting to find myself working in some pretty scary code bases again, my fellow LosTechies dude suggested I start blogging about my experiences. 

And since I've already seen many, many things that make me say "huh?" and, at times, brings tears to my eyes, I figured I'd give this first post a number (assuming there are many more coming).

Ok, so really this is just an opportunity for my fellow developers to perhaps not feel so bad about the code bases they are working in, because maybe, just maybe, someone else out there has it worse.  (As I'm sure there are folks who are forced to work in stinkier code than I...)

In order to make these somewhat useful, I'm making them all about the code.  Smells that I see, and hopefully some simple solutions for fixing them, leading to more maintainable and readable code.

Episode #1

catch (Exception ex)
{
    if (ex.GetBaseException().Message.Contains("You gotta know this just *feels* wrong!"))
    {
        // do something
    }
}

This one definitely had me scratching my head.  I can honestly say this is the first time I've ever seen a conditional expression based on the actual string message on an exception.   Scary, is it not?

Of course the first way to correct this smell that jumped out at me was just to simply create a custom exception and catch it in its own catch block.

catch (SomeCustomException ex)
{
    // do something
}

 

What kind of smelly exception-related code have you seen and corrected?

MonoRail Controller Test Analysis - Problem and Resolution

 

Last night, my fellow LosTechies geek Jason, wanted me to check out something he was trying to do in a MonoRail controller test. 

For some background and the original source code he was working with, see his Castle forum post.

So here was the partial test he was working with:

[Test]
public void Should_have_error_summary_message_when_required_name_is_not_filled()
{
    contact.Name = "";
    contactController.SendContactMessage(contact);
    Assert.AreEqual(@"Contact\contactform", contactController.SelectedViewName);
    ...
} 

 

And here is the target controller code being tested:

public void SendContactMessage([DataBind("contact", Validate = true)] Contact contact)
{
    if (HasValidationError(contact))
    {
        Flash["contact"] = contact;
        Flash["summary"] = GetErrorSummary(contact);
        RedirectToAction("contactform");
    }

    // send some email, etc...

    RenderView("confirmation");
}

So let's tackle 3 issues in this scenario, one by one.

Correcting the conditional logic

Since the error validation check is not returning out of the method, as it stands now, the email will always be sent and the "confirmation" view will always be rendered no matter what.  I made the exact same kinds of mistakes when I was first learning MonoRail; expecting that as soon as I call RedirectToAction, it would take care of performing the redirect right then.  But of course, essentially, that's just a method call to notify the framework of what should be done when the action execution is complete.

So this is an easy one to solve.  We can either throw in a return statement inside the conditional making it a guard clause, or just wrap the rest of the logic inside an "else" block.

public void SendContactMessage([DataBind("contact", Validate = true)] Contact contact)
{
    if (HasValidationError(contact))
    {
        Flash["contact"] = contact;
        Flash["summary"] = GetErrorSummary(contact);
        RedirectToAction("contactform");
        return;
    }

    // send some email, etc...
    
    RenderView("confirmation");
}

OR

public void SendContactMessage([DataBind("contact", Validate = true)] Contact contact)
{
    if (HasValidationError(contact))
    {
        Flash["contact"] = contact;
        Flash["summary"] = GetErrorSummary(contact);
        RedirectToAction("contactform");
    }
    else
    {
        // send some email, etc...

        RenderView("confirmation");
    }
}

I tend to like returning guard clauses shown in the first example better, but either way is of course acceptable.

Differences between testing Redirects and Renders

The test method is currently performing an assert on the SelectedViewName of the controller to make sure the "contactform" view is being displayed.  The problem here is that the controller is actually doing a Redirect, not a Render.  There is a difference in how those are tested. 

  • How to assert that the controller redirected to a particular view:
Assert.AreEqual("/Contact/contactform.rails", Response.RedirectedTo);
  • How to assert that a particular view was only rendered:
Assert.AreEqual(@"Contact\confirmation", contactController.SelectedViewName);

So this test method we're working with needs to be changed to use the first technique of asserting against a redirect, since that's what's happening in the controller.  Easy enough...

Simulating validation errors in the controller 

Ok, so now for the interesting one.  Right now, the call to HasValidationError inside the controller is always going to return false.  Because that property relies directly upon a dictionary of error summaries populated by the databinder.  The reason this an issue in our test method here, is that if you just call a controller's action method directly from a unit test, the databinder is not run, so the actual validation never takes place.  So even though the contact object that is being passed in really doesn't pass validation, the controller doesn't know that if you relying solely on the [DataBind] attribute to take care of the validation for you.  Of course you could run the validation yourself inside of the controller's action method as an alternative.  But there is an easier way.  Besides, you have to really ask yourself, "what should I really be testing here?". 

Jason already understood this, but for those who may not.  Do you really care about testing specific validation rules in your controller, like "is the contact name empty?"?  Well, you probably shouldn't.  Those should be saved for your actual domain object validation tests.  All we care about in this controller test is that if the validation fails for whatever reason (we don't care why), then show the error summary and redirect back to the contact form.

Here's one way that this can be simulated in the controller test:

[Test]
public void Should_load_error_summary_when_contact_is_not_valid()
{
    SimulateOneValidationErrorFor(contactController, contact);
    contactController.SendContactMessage(contact);

    Assert.AreEqual("/Contact/contactform.rails", Response.RedirectedTo);

    Assert.IsNotNull(contactController.Flash["contact"]);
    Assert.IsNotNull(contactController.Flash["summary"]);
    Assert.AreEqual(1, ((ErrorSummary) contactController.Flash["summary"]).ErrorsCount);
}

The important code is here in the helper methods:

private void SimulateOneValidationErrorFor(SmartDispatcherController controller, object instance)
{
    controller.ValidationSummaryPerInstance.Add(instance, CreateDummyErrorSummaryWithOneError());
}

private ErrorSummary CreateDummyErrorSummaryWithOneError()
{
    ErrorSummary errors = new ErrorSummary();
    errors.RegisterErrorMessage("blah", "blah");

    return errors;
}

The ValidationSummaryPerInstance dictionary is publicly exposed for us to manipulate (which is not my preferred way to expose/manipulate collections, since it breaks encapsulation).  But for now this will get us by.  We can just add our own dummied up error summary to the controller so that when the HasValidationError method is called, it will return true, since the result is based on an inspection of this dictionary of error summaries.

Getting something like this included in the BaseControllerTest would also be a nice thing to have.

There may be a better way to simulate this, but this is what I came up with.  Anyone else got any better ways of doing this?

From Windsor XML To Binsor In 4 Hours

 

I'm getting ready to take a break from my current project and switch gears for a little while, but there were a number of "clean up" type tasks I wanted to do before I wrapped things up. 

One of the main things I wanted to do was to get rid of the XML configuration files I had for Windsor and use Boo and Binsor instead.  Any chance I get to work with Boo is a joy.  Almost makes me wish Boo would've taken off instead of C# as the "default" .NET language (I can hear all the VB'ers screaming now...  :).

As of today, I've got 67 components configured for Windsor to manage for me spread across 13 different XML configuration files, just to keep it somewhat organized.  Needless to say, I was very much looking forward to nixing the angle brackets and verbosity of XML.  So I approached it the same way I do any other time I need to do some refactoring or configuration changes.  Make one little change, test, repeat.

About 4 hours later I had everything 100% switched over to Binsor, in a *single* file (I still may break it up into multiple files, but this works for now).  This was my very first time even trying out Binsor, so I'm sure next time I'll be able to do this kind of thing much faster.  Here are a couple cool things I learned...

  • When trying to configure the LoggingFacility using Binsor, I figured out that in order to set the loggingApi attribute correctly you need to use the brackets syntax like this:
Facility(logging_facility, LoggingFacility, { @loggingApi:"log4net" })

I'm very familiar with this since I use Brail as my view engine of choice.  :)

  • One cool thing I learned was that you don't even need brackets when specifying parameter values and dependency overrides for your components.  I'm not sure if this is a Boo thing or something Ayende enabled, but you can use a hash without brackets as the last parameter, similar to how I can in Ruby.  An example might make this more clear...
Component(primary_catalog, ICatalog, Catalog, name:"Primary Catalog", otherParam1:"blah", otherParam2:"blah")
  • In a couple areas I have a set of mappers that just have default implementations right now and don't have any special configuration, so I used the power of Boo to dynamically configure them for me (a technique I first saw Ayende use)
for type in System.Reflection.Assembly.Load("Service.Implementations").GetTypes():
    continue unless type.Namespace == "Service.Implementations.Mappers"
    continue if type.IsInterface  or type.IsAbstract or type.GetInterfaces().Length == 0
    Component(type.FullName, type.GetInterfaces()[0], type)
  • One gotcha I had to easily work around was specifying decimal values for my components parameters.  I have a couple stubbed out calculation strategy components that take in a decimal rate during construction.  It may just be my lack of Boo knowledge, but every time I would try to use something like 0.06 or 0.06m I would get cast exceptions.  Eventually I remembered that I had the power of the Boo language so I just cast it myself and it seemed to work.
Component(tax_calculation, ITaxCalculationStrategy, TaxCalculationStrategy, taxRate:cast(decimal, 0.06))

(If anyone out there can correct me on this, that would be great!)  :D

So I'm pretty happy with how it turned out.  Much more concise than its XML counterpart.

Software is...

 

A friend and former colleague of mine has finally started blogging, after a year of me heckling him.  :P  Basically Daniel is the guy I go to for schooling me on some of those touchy areas of WinForms (ugh), threading and the occasional lesson in IL.  Umm, yeah.

Looking forward to some good content DPB.  :D

Effects Of Encapsulation On Unit Tests - EnumerableAssert

 

To keep your classes properly encapsulated, I've learned (from others and my own experience) that it's usually a good idea to expose collections only as IEnumerable<T>, until the need arises to elevate it to a higher type.  In keeping with this, it can sometimes make your unit tests less elegant.  Here are some examples and a quick little helper that can make things more readable...

So an extremely simple example would be something like this.

[Test]
public void Should_add_item_to_basket()
{
    IBasket basket = new Basket();
    IBasketItem basketItem = new BasketItem();
    
    basket.AddItemToBasket(basketItem);

    // TODO: Assert that the item was added to the basket
}

 

For reference, here is the IBasket interface:

public interface IBasket
{
    IEnumerable<IBasketItem> Items { get; }
    void AddItemToBasket(IBasketItem itemToAdd);
}

 

Ok, so of course there are a number of ways we could write this assertion.  Here are a couple examples using the out of the box MbUnit assertions.

Assert.IsTrue(new List<IBasketItem>(basket.Items).Contains(basketItem));

CollectionAssert.Contains(new List<IBasketItem>(basket.Items), basketItem);

foreach (IBasketItem currentItem in basket.Items) Assert.AreEqual(currentItem, basketItem);

 

Don't know about you, but those seem a little too verbose to me.  I tend to like something like this better.

EnumerableAssert.Contains(basket.Items, basketItem);

 

But you won't find that in the MbUnit framework.  Fortunately it's easy enough to write a little wrapper to "hide" the verbosity.

public class EnumerableAssert
{
    public static void Contains<T>(IEnumerable<T> enumerable, T actual)
    {
        CollectionAssert.Contains(new List<T>(enumerable), actual);
    }
}

 

Notice all I'm doing is leveraging one of MbUnit's existing assertions (CollectionAssert) to wrap an IEnumerable<T> and perform a contains assertion.  Pretty simple stuff, but it can help keep your tests more readable.

RE: Technology Brainstorm

 

(Because I often get tired of writing my verbose comments in a 300x300 text box...)

Colin seems to find himself in a pretty good spot.  The wonderful world of Greenfield development.  But of course with this comes...decisions.  MVC or Web Forms?  ActiveRecord or PI (persistent ignorant)?  .NET or Ruby?  (the latter being the question I'm starting to ask on new projects)

Colin seems to be pretty set on Castle Windsor+MonoRail+ActiveRecord which is a wonderful combination.  The simplicity of AR is just dang nice.  And with things like the ActiveRecordMediator in Castle and the Repository<T> techniques made popular by Ayende, it seems like you can remove some of the "persistence tax" from your entities while still remaining pretty simple.  I say "it seems like" because unfortunately I haven't had a chance to try out ActiveRecordMediator+Repository<T> on my own yet.  But it looks very attractive.

I still struggle with the decision between MR+AR vs. MR+PI (persistent ignorant) myself, in the .NET world at least.  (I'm finding this decision in a dynamic language like Ruby to be a whole different kind of conversation though.)  The purist in me wants to have a 100% "pure" domain model and not let any of that pesky "infrastructure" stuff pollute my precious domain model.  And then the simplicityness (yes, I made that up) in me says "is that really necessary?".  Eric Evans himself recently said he noticed a lot of overuse of DDD, which I admit to being guilty of.  But, I'm still learning (something I hope I'm always doing...)

So since Colin asked for suggestions, here are a couple things I'd look into for use on a brand new MR project (most of which I haven't used yet...):

Oh, and I absolutely agree on using Windsor from the start.  That's what I've done on my current project and you start getting giggly once you realize how easy it is to shift responsibilities among classes.  Not to mention the nice decorator chains that can be created to help you adhere closer to OCP.

That's it for now.  After all, this was just supposed to be a comment.  :)

Funny question and response of the day

 

A co-worker of mine sent an email with this question to the whole "dev" group:

"Does anyone have a random password generator that I can quickly plug into my application?"

My response:

"Guid.NewGuid().ToString()"  :P

What's even funnier is that my team lead sent the exact same response (Guid).  Others replied with "google '.net random password generator'".  LOL.

The correct answer turned out to be:

System.Web.Security.Membership.GeneratePassword

But of course that's not nearly as funny, now is it...

  • tags: c#

Presentation Model: "Screen" Store Example

 

"It is better to trust in the LORD Than to put confidence in man." -- Psalm 118:8

Ok folks.  First, a couple disclaimers:

  • I first heard of this kind of approach from JP back during his Richmond boot-camp tour.  :)  Having said that, I'm fully expecting folks (including JP) to shoot holes in the implementation of this example.  I'm merely providing it to better explain the pieces involved.
  • A lot of the patterns and layering you will see in the example are intentionally overdone for the purposes of showing the mechanics.

Now that we have that little tidbit out of the way.  This post is intended to be read in 2 parts. 

First, get the code man...

You can grab the entire source code (either from my google code repository or in this convenient little zip file).  Feel free to browse the code for a bit, but come back to this post so I can show an example of adding a new, simple feature using this code base.

Some quick notes regarding the solution:

  • If you open a console to the root directory of the solution you can run "build test" to run all the unit tests and see them succeed (hopefully, :P)
  • I was lazy in this example and didn't include my usual "build run" target which will automatically compile, test and fire open a browser to run the application without opening VS.  So you'll have to open up VS and do the old skool Ctrl+F5 (sorry).

Second, let's add a quick little feature

Right now the monitor search results show brand, size and model.  Let's say the customer would like to also see whether or not the monitor is in stock from the search results.  Let's see what that would take.

First off, you may have noticed that I'm using the very handy SmartGridComponent from Ayende (now included in the Castle Contrib project).  Here's how it's used in this example: 

<% 
    component smartGrid, { @source:searchResults, @displayId:false } : 
    
        section more:
        %>
            <td>${Html.LinkTo("Details", "monitor", "view", item.Id)}</td>
        <%
        end
    end   
%> 

As you can see, I don't actually have to specify which columns should be shown in the grid, since it's "smart" enough to figure it out from the object it is bound with.  This means we don't even have to modify our view to add this feature!

(To learn more about using this component, check out the new Castle project wiki page on it).

So we know that the object that is used to display our search results is MonitorSearchResultDTO.  Instead of just adding an IsInStock property to it now, let's drive it out via TDD like good little boys and girls.  :D

If we glance at our Monitor domain object, we see that a Monitor already has the ability to check if its in stock or not (whether it should or not is a whole 'nother discussion which is not the point of this post).  Well, sounds like all we have to change is our mapper implementation.  Let's open up our MonitorToMonitorSearchResultDTOMapperTest fixture.

Mapper tests are, for the most part, not all that exciting.  A lot of value matching and that's about it.  So let's set up our 2 stubbed monitors to return values for their IsInStock() methods.

// ...
SetupResult.For(mockDell24InchUltraSharp.IsInStock()).Return(true);

// ...
SetupResult.For(mockApple30InchCinemaDisplay.IsInStock()).Return(false);

 

Now let's add our asserts to make sure the mapper is doing its job of setting the appropriate values on the DTO.  (Yes, I realize relying upon indexers in this case is just plain ugly, but you'll forgive me this time, won't ya?  :)

// ...
Assert.IsTrue(listOfSearchResults[0].IsInStock);

// ...
Assert.IsFalse(listOfSearchResults[1].IsInStock);

 

You'll probably notice we don't have an IsInStock property on our MonitorSearchResultDTO yet.  Simply use ReSharper to add it now. 

(You'll probably want to update the constructor for this DTO in order to keep it immutable, since there really isn't a reason it should ever need to change once created.)

Now if your run our test suite using "build test" from the console, you'll probably get a compilation error.  That's because we need to actually make the necessary changes to get our test to pass.  So we just need to update our mapper to use the modified constructor on our DTO.

return new MonitorSearchResultDTO(monitor.Id, monitor.Brand, monitor.Model, monitor.Size, monitor.IsInStock());

 

So, re-run the tests using "build test" and we should be green.  Now just build the app and refresh the browser.  You should see that a new column appears in the search results named "Is In Stock". 

(Note: This feature actually only takes about 30 seconds to add.  Needless to say it took much longer to actually write about it and explain it here.)

One last problem though.  It's using "true/false" as the values which makes for a pretty terrible user experience. 

Need Something To Do?

So, dear reader.  Here's a petty little task for you if you're interested.  How would you change the search results "Is In Stock" column to show "Y/N" instead of "true/false"?  (Bonus points for leveraging built-in MonoRail features in the solution)

In Conclusion

Let the flaming begin.  :)  Seriously though, I hope this example at least has some value and maybe gives a small glimpse into one way to use a presentation model to maintain a nice separation between your presentation and domain.  I'd really like to see other folks post some examples as well.

Anyone played with Enso?

 

I ran across this pretty nifty looking launcher/productivity tool called Enso.  I've downloaded the launcher and have been playing with it.  Unlike most everybody else, I haven't switched to Launchy yet from Slickrun.  (I *heart* Slickrun!).  Launchy just seemed a little to "pretty" for me I guess.  Slickrun is fast and its "magic words" have integrated themselves deeply into my work habits.

At first glance, Enso looks similar to Launchy, but from watching the demo, it seems to have some distinct advantages over your typical "launcher".  Although it will probably take me a little while to get used to holding down the Caps key while doing everything.

Anyone else played with Enso?  Do you like it better than Launchy and/or Slickrun?