Tuesday, September 23, 2008

Criticizing is easy, doing is hard

Sometimes I fall into the trap of overly criticizing and asking annoying questions to people who are presenting their work. It's very easy to spot that little grey dot on a white piece of paper. Harder it is to create something completely clean and spotless. And how annoying it is when you've put a lot of effort into something and people only whine about the few little things that are not 100% perfect.

The best solution to participate and do the work yourself. You're not going to heavily criticize yourself. And it shows the reasons why things are not perfect, because it's hard to achieve.

That's why I'm happy with the suggestion of my manager to participate in some of the handover meetings we've been having. I was asking a lot of critical questions, because I like doing that. It's to test my own knowledge and I also like to be right. But only being critical is not the way to go. I'll be more careful.

Thursday, September 11, 2008

Wordle cloud

This little toy Wordle is quite cool. Check my word cloud:

Procrastination

The last few days I've been working on a new website cms for Sanne. It's strange that I totally want to build this site for my girl. But something inside me is strongly resisting. Getting started is so hard. Once you start you get going. I still have to teach myself to break this feeling because this is painful.

This letter to a young procrastinator is very striking.

Monday, September 8, 2008

Inbox Zen

Something I've been following for a while: the inbox zero principle. It's quite simple: always have an empty inbox. When you check your mail categorize each item until the inbox is empty. You can either:
  • Delete
  • Delegate
  • Respond
  • Defer
  • Do
The great advantage of this is: less worrying, more doing. Every time you see the rising queue in your mailbox you get demotivated by the amount of work left. If you handle everything you can right away and schedule everything else you save time you can spend on other things!

One other thing I particulary like is having a 'waiting for' folder. Here I move all the mail I have send that I'm expecting a reply to. This way there's no more need to remember if I received a reply. Once a day or so I check my 'waiting for' and send a reminder to people if I think they're taking too long. It's amazing how many people (sorry to say, especially managers) fail to reply to an explicit question in a mail.

Check out this great talk about inbox zero by Merlin Mann. He writes 47 folders and also co-hosts the hilarious podcast You Look Nice Today.

Tuesday, September 2, 2008

Unit testing hooray!

Slowly I'm getting more into unit testing. It's hard to enforce the discipline to write the tests during development because writing tests takes more time and managers don't like things taking time. But they should be written during development because:
a) That's when you are most into the problem and thus best able to write the test
b) It makes you think about the code you are writing, perhaps discovering bugs as you create them
c) After the fact - there is never time to write tests anyway so it won't happen

When unit tests have been written the benefits are so marvelous. You can re-run them any time and be be sure all your app is still ok. It takes away the fear of changing things because they might break, just run the tests and you are sure you didn't break anything. Beats manually re-testing by a mile.

Finally, I've been getting into EasyMock to mock out the dependencies of my classes. Works great once you get used to it. Say you have a Controller class that needs a Service to search for something:

class Controller {
private final SearchService searcher;
public Controller(SearchService searcher) {
this.searcher = searcher;
}
}

interface SearchService {
List doSearch(String query);
}

class SearchServiceImpl implements SearchService {
List doSearch(String query) {
// Searching code here
}
}


Now to unit test the Controller just mock the SearchService:

@Test
public void testController() {
SearchService searchMock = EasyMock.createMock(SearchService.class);
EasyMock.expect(searchMock.doSearch("something")).andReturn(isA(List.class));
EasyMock.replay(searchMock);
EasyMock.verify(searchMock);
}


And the test can run without an implementation needed. And as a bonus you can check if the mock is called in the expected way.

Btw, I have to find some code syntax highlighting for Blogger.

Monday, September 1, 2008

Using HibernateInterceptor to make database schema name configurable

To fit in our DTAP (Development Test Acceptance Production) cycle I needed to make our application database schema name configurable. The idea is that multiple instances of the application and database can run side-by-side on the same server so each developer and tester can have their own environment if needed.

The problem I quickly realized is that our application uses two different schemas but only one Hibernate Session and the configuration is done using annotations where the schema name for each bean is hardcoded on the @Table annotation. No chance to replace that at runtime, except maybe messing with Reflection which I'm not going to get into now.

So the solution I went with was replacing the schema name on the query just before it is send to the DB using a HibernateInterceptor as described in this blog entry.

Here's how the solution looked in short:

public class ConfigurableSchemaNameHibernateInterceptor extends EmptyInterceptor {
public static final String DB_SCHEMA1_PATTERN = "schema1";
public static final String DB_SCHEMA2_PATTERN = "schema2";

@Override
public String onPrepareStatement(String sql) {
String prepedStatement = super.onPrepareStatement(sql);
prepedStatement = prepedStatement.replaceAll("(?i)" + DB_SCHEMA1_PATTERN, schema1ConfiguredName);
prepedStatement = prepedStatement.replaceAll("(?i)" + DB_SCHEMA2_PATTERN, schema1ConfiguredName);

logger.debug("Query replaced, old sql: " + sql);
logger.debug("Query replaced, new sql: " + prepedStatement);

return prepedStatement;
}
}


Maybe this is not too clean and a bit error prone (could accidently replace some genuine content..). But I learned some new things about Hibernate so I'm blogging this anyway. Next time I'll refactor it to use multiple Hibernate sessions and no harcoded schema name.