Development Blog

 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
 Friday, September 14, 2007

I just had to try the typing speed test that Mitch and Darren tried. Here are my results:

typingspeed

Wanting to try and be a bit more accurate since Darren said it's important, I tried it again (and yes, it was different text, so I didn't have any additional advantage other than the burning in my forearms... which isn't quite an advantage):

typingspeed2

I just can't seem to break 100 WPM and I don't see myself ever getting over 98% accuracy, ah well.

by Aaron on Friday, September 14, 2007 7:33:58 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, September 10, 2007
mount19

OK, so it's not 100% free as you'll need a few drywall anchors (if you're not on a stud) and screws, but you probably have those laying around, and other than that it's free. When you're done, you'll be able to move the monitor up and down, tilt it up and down, and rotate it, just like you can on its stand.

I started taking it apart to see what I could do with it and I didn't start taking pictures until I was almost done, so you're going to have to use your imagination a bit on some of the pics and some of the steps may be off a bit. It looks like a lot of steps, but they're tiny and somewhat detailed... all in all it's pretty easy. Any ways, here you go:

  1. Pull off the monitor from the stand by pushing the black button and rotating it off.
    mount1
  2. Unscrew the four screws that mount the connecting plate to the stand and pull the connecting plate off.
    mount2
  3. This may be optional, but it's easy: unscrew the two little screws on the gray plastic circle and pull it off.
    mount3
  4. This is also probably optional: unscrew the two screws holding the plastic hinge cover on and pull off the cover.
  5. Pull off the bottom black plastic piece from the track on the stand.
    mount5
  6. Use all of your might to push the mount down to the bottom of the track until it locks.
  7. Pull off the rest of the black track cover (this is a little tricky, and I broke some of the tabs doing it, but who cares, right?) Basically you have to pull the sides out from each other and go all the way up to the top, then slide the middle part out.
  8. Push the button so that the mount slides (very quickly, watch your hands) to the top.
  9. Unscrew the three screws holding the long metal piece down to the track assembly and pull it out. Things will fall out, don't worry that's fine.
    mount9
  10. Unscrew the four tiny screws holding the track assembly to the stand. These screws were a pain because they're in there pretty tight and they're so small. I stripped one of them and had to drill it out.
  11. Unscrew the four screws holding the rear bracket to the two track rails.
    mount11
  12. Rotate the rails up and pop the metal coil out of the plastic thing.
    mount12
  13. Mount the rear bracket using the incredibly convenient four screw holes to the wall. I used some 2"x1/4" plastic drywall anchors and 1.5" screws. If you have a stud there, all the better, but it may be tricky getting all 4 screws into the stud.
    mount13
  14. Pop the metal coil into the plastic thing at the top of the bracket. Check to make sure it got in there straight or you may have some annoying problems.
    mount14
  15. Replace the four screws to secure the tracks to the bracket. In order to do this I needed to hold the mount a few inches down from the top and have my girlfriend screw the screws into the rails. That last sentence may get me some unexpected traffic from google.
    mount11
  16. Purely optional: Replace the two plastic covers and the four screws.
  17. Replace the mounting plate and secure it with all four screws.
  18. Play with the plate/mounting a bit to make sure its secure before putting the monitor on it.
  19. Put the monitor onto the mounting plate.
    mount19 mount20
  20. Hook up your cables and enjoy--if you're feeling adventurous, feel free to drill some holes and fish those cables through the wall :)
diy | hardware | tips
by Aaron on Monday, September 10, 2007 6:38:28 AM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback