Development Blog

 Saturday, December 15, 2007

I just profiled one of our test assemblies (Unit tests only, nothing hitting the db). Mocking accounts for 196 seconds out of 357 seconds. The culprit is System.Reflection.Emit.TypeBuilder.CreateType(). This doesn't come as that much of a surprise to me, but still... is there a faster way to do this? Oh and yeah, the results of CreateType are cached so its only the first time you create a mock of a type that you take this hit, but still... that can really slow down TDD.

And no, I'm not saying we should stop mocking... just raising awareness.

by Aaron on Saturday, December 15, 2007 11:17:03 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Thursday, December 13, 2007

I'm going to be putting together a series of Vim Screencast Tutorials. My goal is to raise awareness in the world of just how powerful Vim is and then get everyone comfortable using it. Here's a short trailer that shows a few of the things that make me love Vim. This is my first Screencast of this kind and, yea, I know its cheesy.

You need to upgrade your Flash Player to at
least version 8 to view this video content.

Click here to download the latest version of Flash Player.

Click here to save

You can get Vim here, but I'd ultimately recommend ViEmu, a Vim emulator plugin for Visual Studio.

by Aaron on Thursday, December 13, 2007 2:23:32 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [14]  |  Trackback
 Wednesday, December 05, 2007

Well today was a big day at Eleutian. We've been running MonoRail and standard WebForms together in the same web application for more than a year now. As new features came up we would port things to MonoRail and so slowly things have been migrating over. Last week I noticed we had about four big pages left to convert and decided that my new mission was converting everything to MonoRail once and for all. I'm happy to say it's completely done!

aspx

What's nice is this has drastically cleaned up the Eleutian code base as we were able to get rid of:

  • Six projects in our solution, including one full of old server controls.
  • Duplicated template code in our brail layout and the master page.
  • Old ASP.NET provider's for authentication and permissions.
  • Some complex NHibernate session handling code (as well as other similar code for supporting both scenarios)
  • Several old presenters from when we did MVP with WebForms.

Not to mention many other things I deleted in my svn del frenzy today. Now we get to start the process of introducing a little more consistency into things. It'll be nice being able to finally refactor some things that were left alone because nobody wanted to go back and rewrite all of the WebForms code. I love deleting code almost as much as writing it.

by Jacob on Wednesday, December 05, 2007 8:34:04 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, November 29, 2007

So the other day, my computer started acting up, swapping like mad and that sort of thing. Turns out one of my drives had just up and disappeared. Luckily, I didn't lose anything important. My life pretty much revolves around subversion repositories at work and my university. But, it's still annoying to have to rebuild that local "cache" that my hard drive acts as. Especially since the failure was obvious and appeared to be fixable. The male SATA connector on the drive had broken. The small piece of plastic that the contacts rest on had snapped off inside of the cable. This left the gold pins floating helplessly in the air. I tried everything to get those seven posts on the drive to make contact with the cable. Lots of careful positioning and heavy application of electrical tape, etc... I went to the local Electronics Warehouse and they told me I was out of luck. I gave up.

A week or so later my dad hands me the same drive:

He had snipped off the end of a SATA cable and soldered the conductors directly onto the drive. He said it took him about an hour. Hah! My dad is a retired electrician who now works on industrial automation for rock and batch plants - PLC's and that sort of thing, a very different kind of programming. I plugged it in and it worked perfectly! I didn't think keeping the drive in service was a good idea so I just copied the data off. Thanks dad!

by Jacob on Thursday, November 29, 2007 11:18:26 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, November 18, 2007

I haven't posted in a while and decided to write a post about one of the little side projects I've worked on recently. I've been lurking around on the ALT.NET mailing list and one of the discussions I take time to keep up on is on Dependency Injection. Something I worked on a few weeks ago has some applications in that area and so I decided to see what others thought.

I was talking with Aaron several months ago about how many problems constructors in static languages cause. Ruby people are fortunate in that their constructors are much more flexible than their C# counterparts. Want something to be a singleton? Just return the same instance from the constructor! Lifecycle management and dependencies can be the responsibility of the constructor itself, rather than a function of a container.

Over the weekend a few weeks ago I wrote a library and MsBuild task that factors constructor calls out of code and into a pluggable factory system. You write code like this:

public class EmailSender
{
  public void TellEveryone(string message)
  {
    TemplateRenderer renderer = new TemplateRenderer();
    Console.WriteLine(renderer.Render(message));
  }
}
public class EmailSenderFactory : IObjectFactory<EmailSender>
{
  public EmailSender Create()
  {
    return new EmailSender();
  } 
}
EmailSender emailer = new EmailSender();
emailer.TellEveryone("Hello, World!");

What the MsBuild task will do is this:

  1. Load the target Assemblies using Mono.Cecil
  2. Find implementations of IObjectFactory<T> and add them to the FactoryMap.
  3. Find all instances of new T() for each of those factories and replace them with a call to the Factories.Create<T>(), ignoring calls inside of factories themselves.
  4. Weave the FactoryMap (just the Factory Type and its Object Type) into the Assembly.

So during runtime we can use the FactoryMap that was serialized in step #4 to create the factories and use them to create instances as they're demanded. It is important to note that your objects need default constructors, even though they may never be called after the code is weaved. One can also replace the factory implementations with IoC backed versions, etc...

Why don't you just create a New.Instance<T> method and use that instead of new T() and save yourself the pain of weaving and having a task and all that, moron?

Good question! I mostly did this as an exercise in code weaving using Cecil. It's a great library, although testing code using it can be a little tedious. I'm tossing around some other projects that I'd love to give a shot and this was a good introduction. You could achieve the same thing using reflection to build your factory map and remember to use New.Instance<T>() instead of the new operator in your code. Granted, the manual approach plasters the concern all over the place and weaving keeps the original code free from that. Which may be an OK trade-off for the simplified process.

Another thing to consider, is that perhaps the weaving approach has its applications elsewhere? Use it specifically for creating domain classes to transparently provide domain services? Another idea I've been tossing around is if you're writing code for platforms where garbage collection isn't as performant (xbox for example) you may be able to transparently add object pooling and other patterns after the fact and not clutter up the original code.

I want to release the code anyway, but I'm tired of uploading zip files. All my future source releases will probably be via Google Code or some public svn repository. Stay tuned.... In the meantime, feel free to opine.

by Jacob on Sunday, November 18, 2007 3:49:46 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, November 02, 2007
by Aaron on Friday, November 02, 2007 2:31:28 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, October 15, 2007

So everyone's been talking about the ALT.NET conference, Microsoft's take on MVC, and such, so I thought I'd briefly chime in with my thoughts. Photo 18 First of all, the ALT.NET conference rocked and I'm very much looking forward to the next one. Secondly, I must disclose that Scott Bellware paid me to say that ($1, signed) but I would have said it anyway.

OK, so then there's the whole MVC thing. This too was awesome and I should try and collect a signed dollar from Scott Guthrie. It's obvious he and the team working on MVC are doing their research. That said, as many of you know we're a MonoRail shop here. We've been using it heavily for about a year now and we've got a lot of code written on it. So what will the impending release of the MS MVC framework mean for us? What will it mean for MonoRail?

I can tell you that for us, it will very likely mean a week of exploration and quite possibly followed by a week or two of porting. That's right, it looked that good. Everything about it was done right or flexible enough to be made right so there really isn't any room to complain about it. MonoRail has more features at the moment, but the ones we use wouldn't be difficult to implement on top of MS MVC.

So what does this mean for MonoRail? I can't speak to that, but I will tell you what I would like for it to mean. What I'd like to see is MonoRail become more like Rails. I want to see something built on top of MS MVC that even more-so favors Convention over Configuration--including but not limited to generators and such. I want it to take it to the next level and be exactly what the community wants for a C# web platform. Dave Laribee says that "MonoRail will remain a viable option for smaller or more edgy shops." I think that's true, but I want to see it built on top of MS MVC.

Why throw away all of the framework code built into MonoRail? A few reasons:

  1. Castle has already been experimenting with throwing most of it away and starting over anyway.
  2. MS MVC will be built into the .NET Framework. This means  easier sells to big shops, and MonoRail would be just a free supplement rather than a replacement/paradigm shift, making it an easier sell.
  3. MS MVC appears to be more modular. There is no massive Controller or ginormous SmartDispatcherController. You can even start with a one method interface and implement your controller however you want.
  4. Routing.
  5. It was built with testability in mind. MonoRail is now mostly testable, but it is not nearly as clean as it could be... or as MS MVC's testability looks.
  6. We can probably all but throw away our codegenerator and use lambdas. We could reinvent this for MonoRail in .NET 3.5 but then we'd be... reinventing... it...

Whatever we decide to do when it comes out, we'll talk about our experiences so you can judge for yourself after we judge for ourselves how viable it will be to port from MonoRail to MS MVC.

by Aaron on Monday, October 15, 2007 10:59:24 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [10]  |  Trackback
 Saturday, September 29, 2007

First some code:

UserEntity user = New.User("bob").In(New.Company("ACME")).With(
  New.PurchaseOf("ProductA")
    .WithAcademicSlot(1).FilledBy(New.EnrollmentIn(101).ThatIsCanceled)
    .WithPlacementSlot(1).FilledBy(New.EnrollmentIn(1)));

This code actually creates and saves (with NHibernate) about 12 or so entities. We can use code like this to set up one off sample data for tests in a way that's easy to read, understand and change. There is a decent amount of magic that goes into making this work and I wanted to talk about how I did it.

First we have a FixtureContext, which is just a hub for the DaoFactory, the current Session, and three helper classes, New, Current and Existing. New is the class responsible for the beginning of the syntax you see above. Each method on New returns a Creator. There's some magic in Creator, so here's the code:

public class Creator<T> : FixtureContextAware where T: class, new()
{
  private T _creation;
  
  protected T Creation
  {
    get { return _creation; }
    private set 
    {
      if (Current.Get<T>() != value)
      {
        Current.Push(value);
      }
      _creation = value; 
    }
  }

  public Creator(IFixtureContext context) : base(context)
  {
    Creation = new T();
  }

  public Creator(IFixtureContext context, T creation) : base(context)
  {
    Creation = creation;
  }

  public static implicit operator T(Creator<T> creator)
  {
    if (creator._creation == null) throw new Exception(
      String.Format("Creation of {0} is null, it probably shouldn't be.", typeof(T)));
    creator.Current.Pop<T>();
    return creator._creation;
  }
}

The first thing is that Creator is a subclass of FixtureContextAware, which is just a helper base class that provides access to FixtureContext's children. Next there are a few references to Current which is simply a collection of stacks of entities so that Creators can refer to other entities that are being created so they don't have to be passed around. This is better explained with an example. In the beginning example you see New.EnrollmentIn(101). An enrollment requires a User to be created, so because there is a User in this creation context, we can do this:

public CourseEnrollmentCreator(IFixtureContext context, short number) : base(context)
{
  Creation.User = Current.User;
  Creation.Course = Existing.Course(number);
  Creation.StartDate = DateTime.Now;
  Creation.EndDate = DateTime.Now.AddMonths(1);

  Session.Save(Creation);
}

The next thing is that the creation itself is stored as Creation in the Creator. This can either be new'd up or can be passed in to the constructor.

The coolest part (at least in my opinion) is the implicit operator. This allows you do to do things like: UserEntity user = New.User().Foo(), where each of those methods returns a UserCreator, but at the end of all of it the Creator is implicitly cast to a UserEntity, the thing actually being created. This also serves as an excellent time to pop the entity from the Current stack.

Next we have the Existing class. This is essentially just a wrapper for your Daos/Repositories so you can fetch things that are already in your database (like Existing.Course(number) or Existing.User("bob")).

With this simple framework in place, the next step is to start writing your domain specific Creators. Here's an example:

public class PurchaseCreator : Creator<PurchasedProductEntity>
{
  protected PurchaseCreator(IFixtureContext context, PurchasedProductEntity creation) : base(context, creation)
  {
  }

  public PurchaseCreator(IFixtureContext context, string productName) : base(context)
  {
    Creation.Product = New.Product(productName);
    // Initialize Purchase...
  }

  public PurchaseCreatorWithSlot WithAcademicSlot(int credits)
  {
    // Create and add slot...
   
    return new PurchaseCreatorWithSlot(Context, this, slot);
  }

  public PurchaseCreatorWithSlot WithPlacementSlot(int credits)
  {
    // Create and add slot...

    return new PurchaseCreatorWithSlot(Context, this, slot);
  }

  public PurchaseCreator WithSessions(int credits)
  {
    // Create and add sessions...

    return this;
  }
}

public class PurchaseCreatorWithSlot : PurchaseCreator
{
  private readonly PurchasedCourseEnrollmentSlotEntity _slot;

  public PurchaseCreatorWithSlot(IFixtureContext context, PurchasedProductEntity creation, PurchasedCourseEnrollmentSlotEntity slot) : base(context, creation)
  {
    _slot = slot;
  }

  public PurchaseCreatorWithSlot FilledBy(CourseEnrollmentEntity enrollment)
  {
    // Fill slot...
  }
}

Then we add a PurchaseOf(string productName) method to New that will create and return a new PurchaseCreator. We can also add a PurchaseOf(ProductEntity product) and pass a New.Product("Product") in instead. You can make it as granular or magic as you want. Also, Notice that WithAcademicSlot and WithPlacementSlot return a subclass of PurchaseCreator that adds another method. Using techniques like this you can make some very verbose and context sensitive fixtures.

We also make our HibernateTests base class FixtureContextAware so that we can use nice syntax in our tests.

Here is the source for the basic framework. Let me know what you think. 

by Aaron on Saturday, September 29, 2007 3:48:54 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [1]  |  Trackback