This blog has been moved to http://info.timkellogg.me/blog/

Wednesday, March 23, 2011

Object Incest

Note: I thought I had read this term from somewhere else, but after a quick internet search turned up only dirty videos, I think I may be the sole "coiner" of the term. 


Many inexperience developers (and experienced ones too) have been known to make several common mistakes in object oriented design. Hence, the coining of the terms anti-pattern and code smell to refer to patterns of development (like design patterns) that lead to convoluted, overly complex code that costs exponentially to maintain and exhibits little value.

Object incest is a pattern where two unrelated classes are intimately dependent on each other. Simply put, if object A directly relies on object B and B relies directly on A, you have two incestual objects. This usually happens to intermediate developers who realize that they need separation of concerns and break a class into two classes without actually breaking the dependencies. While it is understandable (and almost respectable) why a developer might commit object incest, it is no less dangerous and harmful to a code base full of child objects.

Here is an example of object incest:

class Brother {
 public Sister MySister { get; set; }

 private void GetMyHairBrushed() {
  MySister.BrushHair(this);
 }

 public void DefendFromBullies(Sister sis) {
  // ...
 }
}

class Sister {
 public Brother MyBrother { get; set; }

 public void BrushHair(Brother bro) {
  // ...
 }

 private void GetRidOfBullies() {
  MyBrother.DefendFromBullies(this);
 }
}

This is wrong because the two objects are so involved that it's hard to tell them apart, breaking the principal of separation of concerns. You can fix this by extracting roles from the objects as interfaces. Therefore, each object depends on some kind of object that can fulfill a role. A brother object needs someone to brush his hair, a sister needs someone to defend her from bullies.

class Brother : IDefenderOfTheWeak, IPersonWithHair {
 public IHairBrusher MyHairBrushPartner { get; set; }
 
 private void BrushMyHair() {
  MyHairBrushPartner.BrushHair(this);
 }
 
 public void DefendFromBullies(IWeakling weakling) {
  // ...
 }
}

class Sister : IWeakling, IHairBrusher {
 public IDefenderOfTheWeak Defender { get; set; }
 
 public void BrushHair(IPersonWithHair hairyPerson) {
  // ...
 }
 
 private void FightOffBullies() {
  Defender.DefendFromBullies(this);
 }
}

In the second example, the two objects are no longer reliant on each other. Now they only rely on the roles that each of them provide. Down the road it will be much easier to create other objects that implement those interfaces (roles) like Husband and Wife.

Thursday, March 17, 2011

Unit testing databases - with NHibernate!

One of the pesky problems with databases is unit testing the database portion of your application. For instance, it's enough of a pain to tear down and restore data to it's original state, but it's even harder if your application code requires you to commit changes. A while ago I saw this stack overflow question that said you could wrap all your code in a TransactionScope like:

using (new TransactionScope())
{
    // Database access code here
}

When .Dispose() is called at the end of the using block, the code is supposed to roll back all transactions, even if they were committed. After reading the documentation I realized that any new transactions will use this transaction scope, and hence be rolled back when the transaction scope rolls back at the end of the using block.

This all seems like a great idea for ADO.NET code, but I was skeptical of using this with NHibernate because I know NHibernate does funny things with the session and how it creates transactions. Even though I've known about this trick for some time, I never trusted it or even took the time to actually test it...until now.

I tested this idea out inside the scope of our application code which I'm basically just pasting here. So bear with some of the abstraction code we have built up in IGenericDAO and Container.

[Test]
public void CheckNHibernateMappings()
{
    using (new TransactionScope())
    {
        // IGenericDAO is our abstraction layer for accessing NHibernate
        var dao = Container.Resolve<IGenericDAO<WorkflowTransition>>();
        var obj = new WorkflowTransition() { FromFk = 1, ToFk = 2, IsAllowed = true, WorkflowFk = 1, RightFk = 1 };
        dao.Save(obj);
        dao.CommitChanges();

        var selected = dao.SelectById(obj.WorkflowTransitionId);
        Assert.That(selected.WorkflowTransitionId, Is.GreaterThan(0));
        Assert.That(selected.To, Is.EqualTo(2));
    }
}

I placed a breakpoint at line 12, after CommitChanges(). I debugged the unit test and when it stopped at the breakpoint I ran this query in SSMS:

select * from WorkflowTransitions with (nolock)

The query returned the row I just inserted. The nolock table hint means to ignore any locks that might be on the table and read everything, even uncommitted data. This means we can see the results of NHibernate's  insert statement without having to mess with the SQL profiler. If you run the query without the nolock option it hangs until timeout. I then let the test finish and ran the query again. This time the row was gone!

Apparently, this TransactionScope is fully capable of rolling back all transactions, even if they were created automagically by NHibernate. I presume this means it will work with any ORM framework, not just NHibernate.

Monday, March 14, 2011

Introducing ObjectFlow

I've been assigned to create a light and flexible workflow for two separate projects. After doing some research, I found that there really aren't any light, easy to use and understand, workflows. I noticed that objectflow lets you define workflows in C# with an easy-to-read fluent interface, but after digging into it I realized it was missing some crucial features. For instance, there was no clear way that you could pause a workflow in the middle so that a real person can interact with it.

I contacted the maintainer of the project and have contributed a large portion of functionality that makes it easy to define workflows that include people. Here is a sample workflow:

var open = Declare.Step();
var wf = new StatefulWorkflow<SiteVisit>("Site Visit Workflow")
  .Do(x => x.GatherInformation())
  .Define(defineAs: open)
  .Yield(SiteVisit.States.Open)
  .Unless(x => x.Validate(), otherwise: open)
  .Do(x => x.PostVisit());

// And send an object through
var visit = new SiteVisit();
wf.Start(visit);

// It stops at the Yield, maybe persist it in a database and display a page to the user
wf.Start(visit);

// extension methods to check if it's still in the workflow
if (visit.IsAliveInWorkflow("Site Visit Workflow"))
    wf.Start(visit);

This workflow is fairly simple and demonstrates how you can create a module for defining workflow and isolate all business logic in data objects (models and view-models work great here). I was initially concerned with the idea of creating conditional goto constructs, but after more thought I decided that this shouldn't be a significant problem as long as workflows stay simple and there is a clear separation from business logic and workflow logic.

There is a lot more to this project - and to the features I contributed. However, I haven't even put forth a good effort in developing the official documentation, so perhaps I'll write about this more after developing the core documentation a little more. I think this is an excellent solution for companies who want to quickly through together workflows without a significant barrier to understanding. I think I will continue developing on ObjectFlow as long as I have something I feel I can add.

Friday, March 4, 2011

Crass grammar drives me crazy

I recently had a conversation with someone that went something like:

Me: Yeah, I went to the Sunflower market down on 287 & South Boulder Rd
PersonX: That's one long ass walk

How am I supposed to reply to that? I could say, "Not really, I wasn't ass walking the whole way" or "Yes, my ass is long, I should get in shape". No wonder people have such a hard time learning English...

Thursday, March 3, 2011

I'm becoming a DVCS snob

Today i was looking at open source workflow frameworks for work today and paused on objectflow. I almost decided not to use the library because they're still using SVN or TFS (I'm not real sure which) even though codeplex supports Mecurial.

I'm coming in with the idea that I may contribute to the project if I find, down the road, that I have something that could be added to the project. Submitting patches seems so painful compared to a simple pull request. The workflow of a distributed version control system (DVCS) makes sharing code so incredibly easy that it causes me psychological pain to think about going back to SVN.

On the other hand, one benefit of objectflow being available as SVN is that I can easily use git-svn to create a git clone that can be included as a submodule. It wouldn't be quite as straight-forward if it were a mecurial repository. Submodules are an excellent feature of Git!