Archive

Archive for January, 2009

Career Fair Success? Be Funny and Unique

January 30th, 2009 No comments

This was my seventh trip to the Oklahoma State Career Fair for InterWorks (I did one stint for Acxiom back in 2000). As the de facto recruiter I was very please to see the success of our new "WeHireNerds.com" campaign. The idea for the website came to me in a moment of frustration when a couple of excellent .NET developers turned our offers down. The frustration arose because I had done a good job in the recruiting of both these fine gentleman, but factors outside my control swayed their decisions. I realized that if I wanted to hire great developers, I needed to have more highly qualified candidates to interview.

We had been running Dice.com ads for about a year at this point, and while they had born fruit, the fruit was sparse and required poring through hundreds of resumes. At that moment I realized we needed to drive great developers to us instead of relying on boring job postings and crossing our fingers.

Thus WeHireNerds.com was born. I would have preferred WeHireGeeks.com, but the domain was taken and I needed a cheap domain so I would have an easy sell to the rest of the management team. We ran a non-scientific poll at the office (i.e., we sent out a 1 sentence email) and while some employees were taken aback by the name, most of the team was behind the idea.

The true test was today at the Oklahoma State Career Fair. This is our home court (literally, it's held in the Gallagher-Iba basketball arena) so we were comfortable flying our nerd colors with pride. We pulled out our trusty (or is it massive?) 10 ft. WeHireNerds.com display and I waited with a father's pride for everyone to descend and fawn upon us... Unfortunately the fawning dind't come, but the response was overwhelmingly positive and inquisitive. Both students and career fair staff were intrigued by our name and wanted to know more about us. The most common feedback was "That's AWESOME! I'm definitely a nerd!". Now this was not only from tech nerds, but from nerds in all walks of academia who toil in obscurity: PoliSci nerds, soil science nerds, aerospace nerds, and yes, even marketing nerds.

My hopes for WeHireNerds.com were definitely met today. Our success reaffirms that the best people are looking for something different in the companies they go to work for.

Categories: Team Management Tags:

Castle ActiveRecord and Eager Fetching

January 10th, 2009 5 comments

In the beginning of 2006 we began using NHibernate at InterWorks. The learning curve to NHibernate is steep and I quickly searched for any tools or frameworks that could mitigate the learning curve by simplifying the mapping and querying process. I found ActiveRecord at that time, but it was still a work in progress and I didn’t feel it was safe to use in production projects.

Thus began our journey to create our own framework around NHibernate. We created something very similar to ActiveRecord, but we did not hide the entire NHibernate implementation as ActiveRecord does. Instead we created a base object class (creatively named DataObjectBase) and wrote a MyGeneration template to generate our mapped objects from a database. We have this refined to the point where we can design our database and easily generate dataobjects. That template generates several convenience static methods on the dataobjects: GetById, GetByProperty, GetByCriteria, and others.

Being the kind of person that hates to do something manually twice, I’m constantly looking to automate processes. Lately the issue I’ve been thinking about is how we can more easily track and maintain database changes across version of projects. One of our guys is a former RoR evangelist (he still likes Ruby, but realizes that Rails is not a silver bullet ?) and brought up the Rails migration feature. We began to search for a migration framework to use with our NHibernate framework. During the course of that search, I found ActiveWriter for Castle ActiveRecord. A nice tool to do exactly what we need… if only we used ActiveRecord!

This prompted me to take another look at ActiveRecord. We won’t be able to move to it during this coming year, but in 2010 I’d like to move us back to a framework that has community support, be that ActiveRecord or ADO.NET Entity Framework (would have to be next release of VS.NET, current version is too limited). This prompted me to take a second look at ActiveRecord and examine if there were features missing that would keep us from using it and if so were they surmountable issues that we could implement ourselves?

One of the common arguments I have heard against ActiveRecord is that it oversimplified the mapping of objects to tables and did not allow enough flexibility to do complex mapping. That issue doesn’t bother me because we only use our NHibernate framework on new databases and have a standard database design approach that should easily work with ActiveRecord. As long as it can support joined subclasses (which it does), we are good on that front.

One issue that was tricky for us to get right with our framework was lazy loading. We tried setting lazy loading in the mapping, but quickly realized this was problematic. The data you want to lazy load is usually dependent on the context of where you are using the object and since you have no context at the point of the mapping, you simply have to make a decision based on the most likely case. Luckily, NHibernate allows you set a relationship to eager load either through HQL or the Criteria queries. You can do this by calling ICriteria.SetFetchMode(association,FetchMode.Eager) on the SubCriteria object that represents the join you want to eager load.

This would be problematic with our framework because we were trying to minimize how often the application developer had to use the Criteria object, preferring them to use our convenience methods. To resolve this we added another parameter to our convenience methods called associationsToLoad. This string would be parsed by our framework and traverse the Criteria object tree and set the specificed associations to be eagerly loaded. Here’s the code for the method that does the heavy lifting:

  1.  
  2. /// Adds all the specified associations to the ICriteria. This will cause these associations
  3. /// to be loaded in one database query with the top level object.
  4. ///
  5. /// The associationsToLoad string should be in the format "association1,association2".
  6. /// The associations themselves can have multiple depth, e.g. "Company.Clients.State".
  7. /// Associations can duplicate safely, e.g. "Company.State,Company.Orders".
  8. /// All associations are set to load using a left outer join.
  9. public static void AddAssociations(ICriteria criteria, string associationToLoad)
  10. {
  11. if (String.IsNullOrEmpty(associationToLoad))
  12. return;
  13.  
  14. Dictionary<string, ICriteria> subcriteriaMap = GetSubcriteria(criteria);
  15. List<string> aliases = new List<string>();
  16.  
  17. string[] associationStrings = associationToLoad.Split(',');
  18. foreach (string associationString in associationStrings)
  19. {
  20. string[] associations = associationString.Trim().Split('.');
  21.  
  22. ICriteria parentCriteria = null;
  23. ICriteria subcriteria = null;
  24.  
  25. string association = "";
  26. string absolutePath = "";
  27.  
  28. for (int i = 0; i < associations.Length; i++)
  29. {
  30. association = associations[i];
  31.  
  32. if (i == 0)
  33. {
  34. parentCriteria = criteria;
  35. absolutePath = association;
  36. }
  37. else
  38. {
  39. parentCriteria = subcriteria;
  40. absolutePath = String.Format("{0}.{1}", absolutePath, association);
  41. }
  42.  
  43. if (subcriteriaMap.ContainsKey(absolutePath))
  44. subcriteria = subcriteriaMap[absolutePath];
  45. else
  46. {
  47. subcriteria = parentCriteria.CreateCriteria(association, GetAlias(association, aliases), JoinType.LeftOuterJoin);
  48. subcriteriaMap.Add(absolutePath, subcriteria);
  49. }
  50.  
  51. parentCriteria.SetFetchMode(association, FetchMode.Eager);
  52. }
  53. }
  54. criteria.SetResultTransformer(CriteriaUtil.DistinctRootEntity);
  55. }
  56.  
  57.  

This works great. It allows you to quickly optimize your page by passing in the string without having to create a Criteria query and manually set FetchMode.Eager on each association.

Unfortunately, ActiveRecord does not currently support anything like this. You have to jump down to HQL to preload associations outside of the mapping. This is just way to onerous for me. Call me lazy, but one of the major reasons to use an ORM was so you don’t have to write SQL, and to me writing HQL isn’t much better. However, I think that this would be relatively easy for us to implement on top of the ActiveRecord framework. If not, we can write it into the framework itself and submit to the community for approval.

After further review, I didn’t see any other issues that would keep me from using ActiveRecord at this time. It has an active community and appears to be a very healthy project. However, this move will be a large move for us and I will abstain my decision until I see the new version of the ADO.NET Entity Framework in VS.NET 2010.

Categories: Software Development Tags: