September 2008 Entries

I realize I have been a bit quiet the past few weeks, but we just kicked off the first iteration of a new project at work, so still settling into the project groove. Luckily, the team I am on is outstanding, so there has been good progress made for the first iteration.

Now, for the real purpose of this post. I've been a TDD enthusiast for about a year now and have been reading and watching videos about BDD the past few months and I am really intrigued. I have been trying it over the past week (using Scott Bellware's SpecUnit.NET) and I have to say it feels very powerful, but there are still some disconnects for me.

frustrated

First, I understand that BDD is not a new technology meant to replace TDD. It is a way of doing TDD the way TDD was meant to be done. It can help developers avoid the pitfalls of the language of TDD. When doing TDD, developers can get sucked into the mental trap of "Unit Testing". TDD is supposed to be all about setting up expectations of things the system is should do. It's not about testing to make sure that your class works as expected, or you emailing service works, etc. It's about behavior the system should have. My disconnect here is: how does that drive your design? One of the great things about TDD is that it helps you to design loosely-coupled, highly cohesive systems, because you test everything in a fine-grained way. I write a test method that tests that validates when the IsValid method is called on my domain object that it verifies valid classes and throws exceptions when the domain object does not pass validation. But it is not necessarily behavior of the system. I guess the question is, do I consider internal, technology processes behaviors as well? Even though my customer may not care that the validation method works, they only care that valid objects are saved to the persistence medium. It's a subtle difference, but when developing a large enterprise system, there are tons of internal things that may not be represented on a User Story or Scenario, but are by-products of those user stories. Maybe my observations should be more fine-grained, or maybe I just don't care about the fine-grained?

Also, how does Integration Testing fit into the BDD development cycle? Do I still do my regular NUnit integration tests? or do I assume that if my observation works as expected that my integration works? My initial thought is that my integration tests remain the same and the BDD contexts, concerns, and observations are used to verify my behaviors from an end-to-end perspective.

I would be interested in seeing how people are doing BDD. Are you doing BDD, TDD AND integration tests on your system? Do you write a failing BDD observation, then red-green-refactor TDD and Integration Tests on the component pieces till each component piece passes and then, by most accounts, your observation should pass?

Again, I have just dived into this in the last couple of weeks, and suggestions and comments are welcomed.

Thanks in advance,

Lee

I finally got a chance to run NDepend against a code base I'd written and I gotta tell you, it was an eye opening experience.

First of all, I'd recommend spending some time reading about static code metrics first. Patrick Cauldwell's book is a good resource to start with. He has a chapter about static code analysis and he explains it at a high level in a very simple way. The NDepend website also has some excellent resources on understanding your NDepend analysis output. they have screen casts, which make it easier to get up to speed faster if you're like me and don't read very fast. :) Wikipedia has this page that defines some of the metrics you might encounter when doing static code analysis.

Next just pick a chunk of code you've written and run it. If you find your code in the "Zone of Uselessness", don't be discouraged. Running static code analysis can be painful, but it will only serve to help you write better code later. when you see your coupling getting looser, but your cohesion is dropping, you'll start to get a better feel for what kinds of designs offer the best balance.

Overall NDepend is easy to use, but might be painful to see, when you get your results. Just remember: in software development,  ignorance is not bliss; it's deadly. The more you know about the problems in your code, the better your code will be. Also remember that software development is about choices. You may sometimes choose to leave some things more tightly coupled in order to make the software easier to extend & maintain. NDepend is a tool that can help you INTELLIGENTLY make those choices.

~Lee

Today I needed to override the default convention settings in Fluent NHibernate. By default, fNH sets up the default key columns that it looks for as “[TableName]_id”. The convention that we decided on at my work is ID for the surrogate key column of the table and “[TableName]ID” for every place it is used as a foreign key.

 

In our RepositoryBase class is where we setup the session factory for NHibernate. This is also the place where you set up the PersistenceModel for fNH. Normally, what you might have is:

   1: var cfg = new Configuration().Configure();
   2: var persistenceModel = new PersistenceModel();
   3: persistenceModel.addMappingsFromAssembly(Assembly.Load("Examinetics.NHibernate.Data"));
   4: persistenceModel.Configure(cfg);
   5: factory = cfg.BuildSessionFactory();

But if you need to change some of the default conventions, try:

   1: var cfg = new Configuration().Configure();
   2: var persistenceModel = new PersistenceModel();
   3: persistenceModel.addMappingsFromAssembly(Assembly.Load("Examinetics.NHibernate.Data"));
   4: persistenceModel.Conventions.GetForeignKeyNameOfParent = type => type.Name + "ID";
   5: persistenceModel.Configure(cfg);
   6: factory = cfg.BuildSessionFactory();

The extra line sets the key column name when it is used as a foreign key.

There may be better ways to do this. This is pretty simple, but It was a tough find.

 

Hope this helps someone.

~Lee