Monday, September 27, 2010

Nemo propheta in patria

I wonder why, when they have a subject matter expert close at hand at no cost, people almost always go looking for (very expensive) perfect strangers to (try and) solve their problems.

On repositories

I was writing code for a (actually not so) massive data export in a legacy application and I needed to retrieve all objects of a certain type modified after a given date, so I started writing a repository.

The simplest test that came into my mind was something like this:
@Test
public void queryingWithDateInTheFutureReturnsEmptyList(){
DateTime tomorrow = new DateTime().plusDays(1);
List<MyObject> result = instance.findModifiedAfter(tomorrow);
assertTrue(result.isEmpty());
}
Some clickety-clack (SHIFT+CTRL+I, ALT+SHIFT+F, CTRL+s, CTRL+F6 for the most curious) and NetBeans gives me a red bar. That's good as there's no code yet :-)

The first implementation was really too easy to write it, but as a very few people believe I work this way and all the rest think I'm wasting time I'll publish it anyway, saving my opinion for another occasion:

public List<MyObject> findModifiedAfter(DateTime startDate){
return Collections.emptyList();
}
So far, so good. Now, in the framework used in this project all persistent objects inherit from MyPersistenceObject (names have been changed to protect the innocents), which is a sort of Active Record with a hint of Row Data Gateway. Persistent object may also be managed by a MyPersistenceObjectController object, which is a sort of DAO that also manages transactions. Should you wonder, the class is not a controller at all, but the original developers thought that the name would fit. Before we go on, let me say that the framework works pretty well under many circumstances.

Not having a dedicated database that gets populated for each test end cleaned afterwards (did I mention the fact that this is a legacy application?) the next test tried to retrieve some data:

@Test
public void queryingSinceLastMonthReturnsAtLeast5kObjects(){
DateTime lastMonth= new DateTime().minusMonths(1);
List<MyObject> result = instance.findModifiedAfter(lastMonth);
assertTrue(result.size() > 5000);
}

I know it's not great, and that it breaks if someone truncates the corresponding table, but we must start from somewhere, right? Reading the tests also suggests that the method should probably be named findModifiedSince, but that is hardly the point now - even if it shows another useful feature of writing tests.

A little lookup on the existing code easily gave me a first implementation based on the "glorious" copy-paste-fix pattern:

public List<MyObject> findModifiedSince(final DateTime date) {
if (date == null || date.isAfterNow()) {
return Collections.emptyList();
}

try {
Object[] values = new Object[]{date.getMillis()};
String[] orderBy = null;
Criteria criteria = new Criteria("tms", "MyObjectImpl");
SimpleCondition simple = new SimpleCondition("tms", SimpleCondition.GE);
criteria.add(Criteria.NOP, simple);
Vector objects = new MyObjectImpl().retrieveByAlternateKey(
criteria,
values,
orderBy);
List<MyObject> result = new ArrayList<MyObject>();
result.addAll(objects);
return result;
} catch (Exception ex) {
return Collections.emptyList();
}
}
Clickety-clack, CTRL+F6...

...
...
(yawn)
...
...
(wtf?)
...
...

Green bar. After an insane amount of time. A little logging informed me that the test took 16 seconds to run, excluding the time needed to start and stop the persistence container.

A little profiling confirmed that also the memory usage grew abnormally. And all this for a little more than 6000 objects...

Now, to quote Eric Evans, a repository is

...an object that can provide the illusion of an in-memory collection of all objects of that type.

Well, this framework cannot provide that illusion, at least not whithout freezing everything else. I must admit that lately I was quite in clover, as using Hibernate I could simply write the very same method like this:


public List<MyObject> findModifiedSince(DateTime date) {
return HibernateUtil.getSession().
createCriteria(MyObject.class).
add(Restrictions.ge("tms", date)).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).
list();
}
and get my list, which is actually a list of proxies, in about no time. Now Evans says that repositories

...return fully instantiated objects or collections of objects whose attribute values meet the criteria, thereby encapsulating the actual storage and query technology.

Proxies are not exactly fully instantiated objects, but as they pretend to be I'm prepared to live with that :-)

At this point all I could do was to revert to the old give-me-the-ids-and-I'll-get-the-objects-myself :-(

Friday, September 24, 2010

More on classloaders

As an update for my post on classloaders, PMD informs me that in J2EE I should use
Thread.currentThread.getContextClassloader()
My bars are green, a manual end-to-end test makes my testers happy, so this will be our preferred syntax from now on.

Tuesday, September 21, 2010

NetBeans dependent project in Hudson

While configuring a Hudson job for the single project of ours which still hadn't one I had some problems, as it is a NetBeans project that depends on other NetBeans projects. That is not a problem per se, as everything has run as smooth as silk for years on each and every developer's machine.

When run on the CI server, the build reported this error:

BUILD FAILED
C:\HudsonWorkspace\.hudson\jobs\myProject\workspace\myProjectFolder\NBProject\nbproject\build-impl.xml:558: Warning: Could not find file C:\HudsonWorkspace\.hudson\jobs\myProject\workspace\myOtherProject\dist\myOtherProject.jar to copy.

Unwilling to give up the "depend on project" feature on NetBeans (my colleagues would skin me alive), I investigated a little. Once you know where to look, everything seems quite easy, and as a matter of fact it is.

The dependency is defined, as you would expect, in the project.properties file, where you can find something like this:

project.myOtherProject=../../myOtherProject
reference.myOtherProject.jar=${project.myOtherProject}/dist/myOtherProject.jar

In practice, the first line defines where the other project is while the second defines where to find the relative jar file.

All you have to do is then override these properties in the job configuration in Hudson, either using the path relative to the build.xml file or using the absolute path of the referenced project on the Hudson server.

Now you have no more excuses... :-)

Setting Ant properties in Hudson

As an update to an old post of mine, now I use a different approach for setting properties for the jobs defined on our Hudson instance. Instead of relying on the private.properties file defined for our NetBeans projects (which means all our projects) I simply copy those properties into the relative section in the job configuration page:


This also makes easier copying these properties between projects, besides the fact that it clearly points out which "hidden" variables we're relying upon.

Thursday, September 16, 2010

The FizzBuzz kata

The first time I came over this kata was thanks to a post in which Matteo was looking for design problems. I reckon everyone has played FizzBuzz at school, so I already knew what it was about; I had in mind to try it sooner or later, and it looks like somehow I finally did.

Once I wrote my own solution, I was a little curious to compare it with others, so while googling around I landed on this page which states that

Michael Feathers and Emily Bache performed it at agile2008 when competing in "Programming with the stars" in python, in 4 minutes.

That made me feel a little inadequate, since my solution took a little more to emerge, and I guess it's not because I used Java. But, after all, I'm not Michael Feathers nor Emily Bache, so I guess it's all right.

The solution proposed follows the classic filter paradigm: you register some filters in a list (after all you want the program to say "FizzBuzz" and not "BuzzFizz") each of which processes the output of the previous one. The nice thing is that you can inject filters as you like, which is good: the main class itself has the only responsibility to iterate through the filters, whatever they might do.

My solution is somewhat different, as it is based on the decorator pattern, yet it is similar because you can still inject the decorator, which is built wrapping each rule in the outer one, and the main class has the only responsibility to ask its decorator to decorate the input. If no decorators are provided, a no-op default one is used: this is a small complication compared to the previous solution. Another complication is that the decorator actually knows it's wrapping another decorator, no-op decorator excluded, while a filter has no knowledge of whatsoever other object might operate on the input.

Anyway, the most important thing is that my design satisfies Matteo's (evolving) requirements and supports the Anti-If Campaign :-)

Of course, TDD was used :-)

Don't touch my code

There is not such thing as "my code". If there is, there should not be. This is the basis of collective code ownership: everybody can touch anything. Of course, we MUST make sure that our changes do not alter the existing behaviour (unless we're fixing bugs, or altering behaviour is exactly what we're after, of course).

Sentences like "if you touch my code I'll have to spend a lot of my time to correct your errors" are based on the (hopefully wrong) assumption that your fellow developers commit carelessly modified software. Collective code ownership also means collective responsibility, that should go hand in hand with the "leave your campfire better than you found it" habit.

If I touch "your" code (with which I actually mean "the code of which you were the first author") I magically become responsible for it. But be warned: this is a responsability I share with everybody else in the team. Actually I don't even have to touch "your" code to be responsible for it, as I already am. That's it. Do I see something unclear? I'll try to clarify it. Do I see obsolete comments? I delete them. Do I see comments? I'll probably delete them too, provided that the code speaks enough. If it doesn't, I'll try to make it speak. And delete the comments :-)

Thursday, September 9, 2010

You'll never excel if you stick with Excell

Please, pay attention when you write something. I am sincerely tired of seeing the use of the word "Excell" (note the double "l") instead of Excel. I can accept it perfectly when a customer uses it, as most customers are not (why should they be, after all?) IT experts; on the other hand, I really can't stand it when a (should-be) IT expert falls in the same trap.
  • It is Excel, not Excell.
  • It is Outlook, not Outlock, Outloock, Out Look or other combinations.
  • Ajax is not a programming language.
  • Tomcat is not an application server. And, by the way, Apache sounds like "a-patchy"
I could go on forever, but I'm sure you get the point. At best you're considered sloppy because you didn't review what you wrote (which is already bad enough), but maybe you don't know what you're talking about at all. So why should I trust you? How can I think that you can possibly be able to solve my problems? Are you just a waffler? Please get your homework done.