Down the RFP rabbit hole

April 10th, 2009 No comments

InterWorks recently invested a large amount of time into responding to the Oklahoma Department of Central Purchasing's (DCS) RFP for technology services. There were nine categories you could respond to and if you are one of the big winners (4 per category) you get to peddle your wares to state agencies without being required to go through the RFP process to do the work.

Going through the process re-kindled my dislike for the process. We've won very few private-sector RFP's historically. When we do win an RFP it's because of a pre-existing relationship and in many cases we helped write the RFP. If you have not had personal contact with the person putting out the RFP, I think your chances are significantly less.

Government RFP's are a bit different. Because it's the government (or is it duh-verment?) the scoring process is much more systemic and objective, although I'm not fooling myself because I'm sure that any scorers prejudices will come into play while reviewing the proposals. I understand the nature of the objective scoring system, but it tends turn the RFP process into a glorified term-paper writing contest. The merits of the company and their success are taken into account, but only after you carefully navigate all of the tiny little traps laced through the RFP and amendments (wrong font? oops -5, only 9 whizbangs listed instead of the requested 10? -10, and so on).

I also take issue with the minimum qualifications listed for team members included in the response. For example, programmers were expected to have 4+ years of experience if you were going to supply their resume as part of your team. Four years!? really? I know after 2-3 years of programming I thought I was hot sh-- and I met quite a few programmers with 10+ years under their belt who were plodding through their careers with no real passion for software development. Needless to say, someone who is passionate and loves what they do tends to learn faster and also produce higher quality work than the person who is just paying the bill with the good ol' J-O-B. I think 2+ years is more than adequate training for the programmers on the team, I can understand wanting more for an architect as learning how to be a systems analyst and architect take more time.

We put a ton of time into this, especially our COO, Dan Murray, and I really hope we win one of the categories (we bid on 4). Our proposal was not as AWESOME as it should have been, but it was respectable. Overall it was a positive experience and we definitely learned how the process of writing the response should be handled in the future, which could potentially be valuable if the right opportunity presents itself.

Categories: Sales Tags:

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 "" 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 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 was born. I would have preferred, 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. 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 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:

  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;
  14. Dictionary<string, ICriteria> subcriteriaMap = GetSubcriteria(criteria);
  15. List<string> aliases = new List<string>();
  17. string[] associationStrings = associationToLoad.Split(',');
  18. foreach (string associationString in associationStrings)
  19. {
  20. string[] associations = associationString.Trim().Split('.');
  22. ICriteria parentCriteria = null;
  23. ICriteria subcriteria = null;
  25. string association = "";
  26. string absolutePath = "";
  28. for (int i = 0; i < associations.Length; i++)
  29. {
  30. association = associations[i];
  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. }
  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. }
  51. parentCriteria.SetFetchMode(association, FetchMode.Eager);
  52. }
  53. }
  54. criteria.SetResultTransformer(CriteriaUtil.DistinctRootEntity);
  55. }

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: