May 2007 Entries

Wii Got One...

 

Warning:  This is one of those personal, non-tech "this is what I ate for breakfast and this is what my cat did today" kind of posts.  Feel free to skip this one...  :)

 

The context of this is that my wife and I are coming up on our 5th anniversary...

5/28 @ 12:00pm (Conversation)

Stephanie (Wife):  So what are we going to do for anniversary gifts this year?

Me:  Tell ya what, if you can find a Wii, pick it up and that can be both of our anniversary gifts this year... (I'm thinking she''ll never find one, since I've been looking for the past couple months)

Stephanie (Wife):  Oh, that would be really cool!  (We've been wanting to get one for a while now...)

Stephanie (Wife):  Well, I'll see ya when you get back home from your round of golf.

5/28 @ 1:30pm - 5:30pm (Me out having one of the best rounds of golf I've had in a long time...)

5/28 @ 5:30pm (Call from Stephanie)

Stephanie (Wife):  Umm, I just bought us a Wii!

Me:  Yeah, right!  Whatever...

Stephanie (Wife):  Seriously, the box is on our living room table right now.

Me:  No way, are you serious?  (Typical guy, asking her if she's serious when she already told me she was...  :P  )

Stephanie (Wife):  Yeah, so come home and set it up so we can play it.  :)

5/28 @ 7:00pm - 10:00pm (Set up our Wii and had some good family fun, including our 3yr old, who actually picked it up pretty quickly)

 

Lessons Learned?

  • Challenging your wife to spend money turns out to not be much of a challenge at all...  :S
  • The Wii is definitely loads of fun, and it's very easy to get set up...
  • Now we can pretend like we're getting a workout in the geekiest way possible...  :P

 

Ok, enough of the non-tech mumbo jumbo.  Time to start another week...

NHibernate Mapping Validation Tool?

 

Writing my last post got me thinking...  Surely someone has written an automated script or tool that could examine NHibernate mapping files and verify all the items I pointed out in my previous post.  Or maybe even, another step further, also make sure the column names specified in the mapping files actually exist in the tables in a real database schema!

I'm very tempted to write a NAnt/MSBuild task to do this kind of thing so I can run it as part of my test suite.  I'm thinking something like this would be very useful as a kind of quick "smoke test" for NHibernate mappings.

But, before I do...

Does anyone know of an automated tool that does this kind of thing?

Thoughts On Validating NHibernate Mapping Files

 

Ben brought up a good (pain) point in his comment on my last post that can definitely occur when doing integration testing using NHibernate.  Invalid mapping files can cause the ISessionFactory to break upon creation, often leaving you to check the logs to see what's going on.  But there are a few things you can do to help prevent this, or at least, make it easier to figure out what's wrong.

XML Intellisense Is Your Friend

If you haven't already, you'll want to enable intellisense for your NHibernate xml mapping files.  This is a good first step to make sure you're xml mapping files are valid according to NHibernate's mapping file schema.  Any syntax errors that violate the schema will immediately be apparent.

nh_mapping_missingkey

Doh!  I forgot to add the <key /> element.  No worries...  :)

nh_mapping_intellisense

So xml schema validation and intellisense are kind of your first line of defense against making mistakes in your mapping files.

Don't Want To Hand Write XML Mapping Files?

For the most part, I still do hand-write my xml mapping files, mostly because they're pretty easy once you write a few, and with intellisense enabled, as shown in the previous section, it's even easier.  But, there is (at least) one alternative to this.  One of Ayende's great NHibernate utilities is his NHibernate Query Analyzer (NHQA).  This has a couple of uses (another of which I'll get into later), but included in it is a UI for maintaining NHibernate mapping files.

nhqa_mapping_ui

So this is one more way you can make sure you don't have errors in your mapping files because using the UI will make sure your mappings are in the correct format.

Are The Properties In My Mapping File Valid?

Schema validation and a configuration UI are great for making sure your mapping file is in the correct format.  But one thing it won't catch, for instance, is a <property /> mapping that points to a non-existing property on the specified class.  One quick and dirty way to catch these is to load up your mapping files into the NHQA and "build the project". 

nhqa_main_ui

When you click on Build Project, if any mapping errors are detected, it'll show an exception dialog with a pretty good error message telling what's wrong.

nhqa_mapping_exception

Of course this is still a manual process, which is not good, but it'll get you by for a quick sanity check.  It's also just a great tool in general for learning and building HQL queries against a real database.

(On a side note...  Is it just me, or does it seem that most open source tools have much better, detailed error/exception messages and logging than a lot of the commerical tools?  I've always been impressed with NHibernate and Castle in that regard...)

Anyways, hope you can find this useful.

Setting Default Focus Using MonoRail/Prototype Ajax Library

 

It's the little things that make web applications a bit more user friendly.  One of these very basic things is simply making sure that some element, ideally the most important one (i.e. search box, first data entry element, etc.), is set to have default focus when the page loads.  Think about those precious seconds that would be lost if, when you browsed to Google.com, you had to set focus to the search box yourself.  Ugh!  :)  (Some if this may be the keyboard-addict coming out in me...)

What makes this even worse, is that it's really not that hard to do this in your pages.  Here's just one example of how I'm doing it on my current MonoRail project using the fabulous Prototype javascript library.

I've built a simple reusable "sub view" named defaultFocus.brail which can be called from any of my pages, passing in the id of the html element I want to have default focus.

views/common/defaultFocus.brail

<script type="text/javascript">
   1:     Event.observe(window, 'load', function() { document.getElementById('<?brail output controlIdToFocus ?>').focus(); });
</script>

So then, an example of this can be used in one of your views...

views/home/index.brail

   1: <?brail OutputSubView('/common/defaultFocus', { 'controlIdToFocus':'searchCriteria' }) ?>
   2: <input type="text" name="searchCriteria" id="searchCriteria" />

Pretty simply stuff.  Yet you'd be surprised how many web applications and pages out there don't do this!  One example I just noticed today is in the Community Server blog dashboard in the "Tag Editor" dialog box. 

cs_tageditor

This niftly little web dialog window has a jazzy slide down effect when it opens, but lacks a very basic thing such as setting the default focus to the "Name" input box.  On a related note, if I'm adding a new tag, wouldn't I want it to be enabled by default most of the time?  Again, just a little thing...

I'm certainly guilty of these things myself sometimes, but I just wanted to encourage folks (including myself) to be good web usability citizens and look for opportunities to make little enhancements like this that can make web applications that much easier to use.

As usual, I've updated my ongoing sample code library to include these changes.

Unit Testing NHibernate DALs - What Are You *Really* Testing?

 

Someone new to NHibernate recently asked me how to unit test their data access layer which uses NHibernate.  I've already sent him my thoughts on it, but figured it may make for a good blog post to get some of the community's reaction. 

What Are You *Really* Testing?

From my perspective, there are (at least) a couple questions you should always be asking yourself when practicing TDD or just testing in general:

  1. What am I really testing here?  My code or 3rd party/framework code? 
    • At some point you need to trust the frameworks your using or else you’ll end up testing the whole .NET framework…   Not good!
  2. How much value is really being gained from this test that I am writing?  A quick quiz...
    • Which test do you think would bring the most value?
      • a) A unit test which uses a mocked ISession to verify that when Save(entity) is called that NHibernate does what it's supposed to do?
      • b) A unit test to make sure NHibernate is generating the correct sql for an HQL query or Criteria call which it's supposed to do?
      • c) An integration test which verifies that the mapping files you've written are configured correctly to map your domain objects to your database tables?
    • Answer?  More than likely, C is probably the best answer to this question.  If all you have are unit tests with no state-based integration tests, that's probably a bad sign.  At some point you've got to write integration tests to make sure all your components work together, especially in your data access/persistence layer.

Exceptions

Now, if for some reason you have another layer of abstraction in there like PersonRepository -> IPersistenceFacade -> NHibernate, then driving out the interaction between your PersonRepository and IPersistenceFacade is probably a good idea.  But that's probably as far down as I'd go for unit tests.

Also, if you're not using an ORM and have to use vanilla ADO.NET to hand roll your own data access/mapping layers, then I would most definitely recommend driving that out using TDD and unit tests.  But hopefully this is not something you're having to do for the most part.

Final Thoughts

So far in my current project, I'm only using integration tests for my persistence layer (aka DAL) to verify that my mapping files are correct.  The nice thing is that NH makes this really easy with its SchemaExport tool to very easily generate your database schema from your mapping files.  So I’m using that along with a couple hand-rolled utilities and factories for generating and inserting sample data to use for integration testing purposes.

Of course, having automated unit tests for as much of your application as possible is still a great goal, but sometimes it needs to be weighed against how much business value it’s going to help you deliver in terms of increasing the maintainability and testability of your code.  However, when in doubt, write a test!

Your Thoughts?

Creating Composite View Components In MonoRail / Refactoring Exercise

 

In a previous post, I showed some examples of how to create custom view components in MonoRail and touched on the ability to create composite view components.  Since then I've refactored towards the use of interfaces which I think is a cleaner approach, so I thought I'd share. 

First, let's review the code that I want to improve upon:

   1: private void ShowSearchButton()
   2: {
   3:     LinkSubmitButtonComponent linkButton = new LinkSubmitButtonComponent();
   4:     linkButton.Init(RailsContext, Context);
   5:     linkButton.Context.ComponentParameters.Add("linkText", "Search");
   6:     linkButton.Context.ComponentParameters.Add("formToSubmit", searchFormName);
   7:     linkButton.Initialize();
   8:     linkButton.Render();
   9:  
  10:     string html = string.Empty;
  11:     linkButton.Context.Writer.Write(html);
  12:     RenderText(html);
  13: }

Having this logic inside of the SearchForm component pretty clearly violates SRP and is just plain ugly.  So coming at this from a TDD-like approach, I write what I want to be able to do in this method.

   1: private void ShowSearchButton()
   2: {
   3:     RenderComponent(new LinkSubmitButtonComponent(), "linkText=Search",
   4:                     string.Format("formToSubmit={0}", searchFormName));
   5: }

Notice the design decisions I've made in this one statement.  I've said that I want to call a new method named RenderComponent which will take in an instance of a view component and a string array of key/value pairs as component parameters to use when rendering this view component to html.

(Side Note: The Castle MonoRail framework provides a great little utility class named DictHelper for converting an array of string key/value pairs ("key=value") to a an IDictionary.  Very handy for situations like this.  More on that in a sec.)

For now, I'll just add a new private method in this same class named RenderComponent and move the logic needed to render the LinkSubmitButton view component into this new private method.

   1: private void RenderComponent(ViewComponent viewComponent, params string[] componentParams)
   2: {
   3:     viewComponent.Init(RailsContext, Context);
   4:     foreach (DictionaryEntry dictionaryEntry in DictHelper.Create(componentParams))
   5:     {
   6:         viewComponent.Context.ComponentParameters.Add(dictionaryEntry.Key, dictionaryEntry.Value);
   7:     }
   8:  
   9:     viewComponent.Initialize();
  10:     viewComponent.Render();
  11:  
  12:     string html = string.Empty;
  13:     viewComponent.Context.Writer.Write(html);
  14:     RenderText(html);
  15: }

But this logic for rendering the LinkSubmitButton to html is still sitting in my SearchForm class.  Also notice how nothing in this method is directly using our LinkSubmitButton component, just any class that inherits from ViewComponent.  I smell some opportunities for reuse here; more on that in a sec.

This may be jumping a little ahead, but I want to go ahead and create a common interface for my view components.  Unfortunately, no common interface already exists in the MonoRail framework, but it's easy enough to create yourself.  Just extract an interface based on the ViewComponent class.

   1: public interface IViewComponent
   2: {
   3:     void Init(IRailsEngineContext railsContext, IViewComponentContext context);
   4:     void Initialize();
   5:     void Render();
   6:     bool SupportsSection(string name);
   7:     IViewComponentContext Context { get; }
   8: }

I then changed the two view components I'm working with to implement my new custom interface:

   1: public class SearchFormComponent : ViewComponent, IViewComponent
   2: ...
   3: public class LinkSubmitButtonComponent : ViewComponent, IViewComponent
   4: ...

Now I'll perform a "Pull Members Up" refactoring on the private method named RenderComponent in our SearchForm component to place that method on our newly created IViewComponent interface which will of course change the method to be public. 

   1: public interface IViewComponent
   2: {
   3:     void Init(IRailsEngineContext railsContext, IViewComponentContext context);
   4:     void Initialize();
   5:     void Render();
   6:     bool SupportsSection(string name);
   7:     IViewComponentContext Context { get; }
   8:     void RenderComponent(IViewComponent component, params string[] componentParams);
   9: }

(One minor change I've also made is the RenderComponent method now accepts the interface IViewComponent instead of MonoRail's ViewComponent class.  This is just because I always like to program to interfaces when at all possible.)

Ok, all seems good except the fact that our LinkSubmitButton component won't compile because it doesn't implement the RenderComponent method on the IViewComponent interface.  Remember when I mentioned that it appears that all of the logic in that method is completely generic and can probably easily be reused?  Well, instead of just duplicating this method in the LinkSubmitButton class, I'm going to perform an "Extract Superclass" refactoring to create a base class for my view components and then another "Pull Members Up" refactoring to move the RenderComponent method up to our new base class as shown below:

   1: public class BaseViewComponent : ViewComponent, IViewComponent
   2: {
   3:     public void RenderComponent(IViewComponent component, params string[] componentParams)
   4:     {
   5:         component.Init(RailsContext, Context);
   6:         foreach (DictionaryEntry dictionaryEntry in DictHelper.Create(componentParams))
   7:         {
   8:             component.Context.ComponentParameters.Add(dictionaryEntry.Key, dictionaryEntry.Value);
   9:         }
  10:  
  11:         component.Initialize();
  12:         component.Render();
  13:  
  14:         string html = string.Empty;
  15:         component.Context.Writer.Write(html);
  16:  
  17:         RenderText(html);
  18:     }
  19: }

Then we'll change our two classes LinkSubmitButton and SearchForm to inherit from this new base class:

   1: public class LinkSubmitButtonComponent : BaseViewComponent, IViewComponent
   2: ..
   3: public class SearchFormComponent : BaseViewComponent, IViewComponent
   4: ..

Now our rendering logic for the LinkSubmitButton in our SearchForm composite view component is simplified to:

   1: private void ShowSearchButton()
   2: {
   3:     RenderComponent(new LinkSubmitButtonComponent(), "linkText=Search",
   4:                     string.Format("formToSubmit={0}", searchFormName));
   5: }

And we have the added benefit of reusability on our rendering logic making future composite view components easy to create.  Note: This steps shown in this post were actually performed in a matter of minutes, so it was a very quick refactoring.  Writing up this post took considerably longer than the work itself, as is usually the case.

As usual you can find the full source code here.

Anyways, hope this can be of some use to those utilizing this great MVC framework we call MonoRail.  :)

My Developer Bookshelf - Past, Present & Future

 

(Trying this post out using Google Docs...)

A co-worker asked me for a list of books that have shaped the way I think about software development as well as a list of books I'm currently reading and want to read. And instead of just sending it via email, I'm going to heed Jeff Atwood's advice and post it on my blog instead. I previously posted a couple lists of books that I haven't yet read, but want to. But I'll include them here as well so it can be all in a single list, if for nothing else, my own reference.

Have Read (and still re-read as necessary)


Am Reading


Need To Read (in no particular order)



Of course I'm sure I missed some and this is more a "living" document anyways... But it's a start... :)

Leveraging 3rd party/OSS tools in a VSTS/TFS environment

 

In light of the recent TFS vs. OSS debates, I wanted to share how we are using both TFS and OSS tools to work with each other.  Speaking as someone who has implemented (and extended!) TFS in a production environment since the early Beta 2 days and am currently using the VSTS/TFS stack, I can say that there is quite a bit of pain involved.  But some of that can be alleviated by utilizing both commercial and OSS tools *with* TFS.  Here are a few examples of how I (and some of our team) are "filling in the gaps" to make TFS and VSTS a little easier to work with.

 

Testing

I think it's pretty clear that the integrated testing that comes "out of the box" with VSTS is sub-optimal (I'm being nice... :) ), which I covered in a previous post.  I've seen first hand how much of a hindrance it can be due to its poor performance which negatively affects that all important rapid feedback cycle.  Not to mention it encourages developers to adopt bad habits and continue to tether themselves to the VS2005 IDE.  Using NUnit, or even better, MBUnit, can really speed up your tests.  But sometimes we find ourselves in an environment where we don't have a choice but to reference the *.UnitTestFramework.dll and use the MSTest attributes for the sake of those on the team that prefer using the integrated testing environment in VSTS.  Well, there is still hope as shown below...

Here are a few tools/tips you can use to get that rapid feedback without disrupting the rest of the team:

  • TestDriven.NET Plugin - In case you've been living in a hatch on an island with a guy named Desmond for the past couple years, this plugin is the fastest way to run your tests in the IDE, period!  Wire it up to Ctrl-T (tip from my friend, Paul), and you'll be on your way.
  • NUnit - Just the old skool NUnit will work as well since it "knows" how to interpret the MSTest attributes properly.  Either the console or GUI, pick your flavor; more on the console version next...
  • "Green Screen" - 'Cause it still feels good sometimes to be sitting a command prompt to get your work done (kermit green on black being my preferred color scheme).  On a related note, I think this (along with many other things) is why I'm referred to as a geek multiple times a day.  :P  Console2 is a great way to have multiple console windows open in tabs.  For the past few months I'm finding myself utilizing my automated build script for a majority of my testing needs.  The advantages of this are:
    • it's crazy fast 'cause you can have much more control over how you do compilation instead of relying upon VS for compilation which is about the slowest possible way
    • it'll force you to, at the very least, automate your compilation and testing which can then be re-used on a daily/CI build server and this has the added effect that when you do your "check in dance", you can run the exact same testing target that the CI build server uses 

 

Continuous Integration / Automated Builds

TFS comes with a product called Team Build, which is their "out of the box" automated build server.  I think it has a lot of potential in future versions, but this first version I've found to be lacking some key features and in general is just a pain to get up and running.  Some of the things I hope are addressed in future versions are:

  • Boy, is it slow.  Of course slow can be a relative term, but in comparison to something like CruiseControl.NET, it's painfully slow.  I've seen it consistently take as long as 20-30 minutes just to get the latest source, compile and drop the binaries.  Now, this was a fairly large project consisting of multiple solutions, maybe 30-40 projects in all.  And it was using the default compilation options in MSBuild against the solutions, which as noted above, is probably the slowest way to compile code.  So a lot of the slowness may have been caused directly by MSBuild.
  • Unless they've changed or issued a patch for this, I had problems trying to run more than one Team Build "build type" at a time on the same server.  This seemed very odd to me and would definitely rule it out as a continuous integration server, if you want host multiple projects on the same CI server, which is often needed.
  • No scheduling!  Another likely showstopper.  Almost enough to not be able to call it an "automated" build server.  Of course you can use the OS's built-in scheduled tasks to shell out to a batch file and run it on a scheduled basis, which works.  But the lack of sophisticated triggers and scheduling system needs to be addressed.

Fortunately, it looks like a lot of these issues can be addressed now using various tools like Automaton and CI Factory, which I've heard great things about, but have never personally used either of them.

Another option is to just use CruiseControl.NET as your automated build server.  This is an established product and isn't plagued by any of the problems listed above.  It's fast, can run concurrent builds on the same server and comes with some very flexible scheduling options.  It has support for most testing and code metric tools out there, including MSTest, if you must use it.  And in combination with the dashboard and CCTray application, it makes for a great continuous integration environment.  I've set up some pretty complex build environments using CCNet with TFS, so this is another example of how OSS tools can be used alongside TFS.  Just grab the TFS source control plug-in for CCNet, and you'll be on your way.

Even though Team Build has it's limits, I'm looking forward to see what Microsoft is planning for future versions.  It has the potential to be a very powerful automated build / continuous integration server.

 

TFS Work Item Management

For the most part, using TFS to manage requirements and tasks as work items works pretty well.  The ability to link work items to check-ins probably being the most interesting and useful feature.  You can also link work items to other work items, which make it a decent candidate practices like Scrum where you have a product backlog of high level features and more granular sprint backlog items that link back up to the high level product backlog item. 

One problem with this though is that you can't easily see a hierarchical representation of this data.  This can make it difficult to quickly identify the relationships between work items.

Well, a co-worker of mine has started an OSS project on CodePlex called TFS Work Item Explorer.  This has some interesting potential to give an alternate view of your work items in TFS.  I believe his latest release even has the ability to update work item data.  Definitely worth a look if you feel limited in the data grid style view of work items in TFS.

 

Well, I guess that's it for now.  Hopefully this will help some of you folks who are struggling with TFS to look at possible alternatives to complement your use of TFS as a way of managing projects.  The good thing is that most of these can be used without interfering with those who want to just use the "out of the box" components.

Unused Code, Stinks

 

Speaking of things that make us developers feel good, one of my favorite things is looking for and deleting unused code.  My definition of unused code (thanks to ReSharper):

  • "Gray code".  This is code that is absolutely not used anywhere.  Delete it!
  • "Lingering code".  This is that code that starts off serving a purpose, but due to refactoring and other code changes the only thing that ends up referencing it is your unit tests.  Yes, this includes those overloaded constructors that you may have initially needed, but serve no real purpose now.  Alt-F7 your way to making the necessary test code changes to remove the dependency on the "lingering code" and then delete it!

Oh, and get used to using the Alt-Del shortcut for ReSharper for all of your code deletion needs.  This makes sure no dependencies exist on what you're deleting and will give you list of them if any are found.  It's also handy that you can Alt-Del a class name in the "public class SomeClass" declaration and it will automatically delete the .cs file associated with it as well.  Great for keyboard junkies who don't want to Ctrl-Alt-L to show the solution explorer, highlight the file and hit Delete.  Remember, less code == less bugs.  :)

"Oh yes, it's a most satisfying feeling deleting swaths of code that have been made redundant by your cunning refactoring."  -- ??

ReSharper 3.0 EAP And My New Favorite VS2005 IDE Indicator

 

ReSharper_GlobalErrorAnalysis

That would mean I have no ReSharper errors in my entire solution thanks to my favorite new feature so far of ReSharper 3.0, Global Error Analysis!  Now you can Alt-F12 your way to peace of mind and free yourself even more from relying on the IDE for compilation, as JP points out.

So this is the point where I reiterate what I've said in the past along with a lot of other folks...  Please JetBrains, build us a .NET IDE!  :)