Monday, February 1, 2010

Fluent Creator for Advanced GivWenZen Features

I was starting to create a screencast covering some advanced features in GivWenZen and I realized it was more difficult to use these features than it should be. I had just seen Szczepan Faber, the mockito guy, give a tutorial on using fluent creators (read aobut fluent interface here) for testing and I thought this type of creator would also fit my current need. I was very pleased with how this turned out. Not only did it make using the advanced features easier, by hiding details that I did not need, it also reduced the need for a client to depend on other parts of GivWenZen when changing the defaults.

When I started I had one main class to startup the system. Normally, that is when you do not want to change the defaults, you simply call the no parameter constructor.

new GivWenZenExecutor();

Simple enough but as soon as you want to change one parameter it gets more difficult. Now you need a set of constructors that take specific objects and things get to be a pain real fast. Getting parameter order such that it makes since is difficult and many times impossible. In my case I got tired of that and created one additional constructor that tool all the parts that could be changed. The problem with this is you need to know about all the parts that could change even if you want change only one of the defaults.

Original way to override only the base package where step classes are located:

new GivWenZenExecutor(new DomainStepFinder("my.step.package."),
new DomainStepFactory(),
null);

Now the client has dependencies on DomainStepFinder and DomainStepFactory. What does that null parameter mean???

In reality the only thing the client wanted to do was configure the executor to look for steps in a different package.

Here is how it turned out with the fluent creator:

GivWenZenExecutor executor = GivWenZenExecutorCreator.instance()
.stepClassBasePackage("my.step.package.")
.create();
Wow, I no longer know about any of the dependencies the executor has. I was able to simply tell the creator what my package was and ask it to create the executor. I could even remove the dependency on the GivWenZenExecutor by assigning the created object to the GivWenZen interface.

If I neeed to change the object that finds classes I am less likely to have to change the client now. I simply make the change in the creator. I can rename and repackage and change to my hearts desire as long as I do not change the creators contract.

It is funny, and sad, that I have used this type of interface in a few cases such as several mocking frameworks and quite a bit in different Ruby frameworks but I always forget about it when writing Java code for a project. Actually, I am not sure I could have come up with this interface before using the features a few time and understanding where things were difficult. By the time I wrote the creator I knew exactly what I wanted it to do and it only took a few minutes to write.

Now I can do the screencast on using GivWenZen advanced features.

3 comments:

  1. Nice way to clean up an area of code I always hated.

    ReplyDelete
  2. thanks, I am not sure I understand all the context in which this type of contract/interface is appropriate but I do like how this worked out. I can see how this would work good in combination with an object mother for creating testing objects, especially for functional and acceptance testing.

    ReplyDelete
  3. found this article which describes issues to avoid with fluent interfaces http://weblogs.java.net/blog/carcassi/archive/2010/02/04/building-fluent-api-internal-dsl-java

    ReplyDelete