Apr 18

Seriously, why? It uses XML. So instead of

copy(dir1, dir2)

You gotta write

<copy todir="dir2">
  <fileset dir="dir1" />
</copy>

It has a useless conditional logic. You cannot just say if-else. You have to define a conditional target based on whether a property is set or not. Did they go through all these trouble just so that some incompetent developer won’t screw up? The more I use Ant the more I feel it’s not the right tool. Don’t tell me Maven. It’s better. But not too much better. It still uses XML. Why are people so possessed about XML? What’s wrong with building with an easy to understand scripting language? That way you have the power of a real language rather than a bunch of verbose XML files and a limited set of library. In fact, that’s what I’m doing now. I’m writing a Ruby script to generate the deployment descriptors for Gigaspaces (hey, I’m becoming like Alan Covington!). It’s one step further even though the main build is still Ant. But who knows, I might change all our Ant build scripts to something like Raven.

Jan 14

Continue from the last post. Remember the JMock example I used? It’s a simple add() operation:

one (calculator).add(2, 2); will(returnValue(5));

Now, what if, just for fun, I used my own class called MyInteger instead of primitive int as the parameter for add() method? The expectation will be written like this:

one (calculator).add(new MyInteger(2), new MyInteger(2)); will(returnValue(5));

So I expect one single call to add() method with two parameters of type MyInteger. This simple expectation will fail miserably with JMock because it compare the expected parameters with the actual parameters using the equals() method. The persistence layer I’m using, like a lot of other similar products, prevents me from overriding the equals() method. So JMock is actually comparing the reference. I won’t be surprised if there is a workaround for it. But since I had SevenMock set up and running in ten minutes, I won’t spend my effort looking for those workarounds.

Tagged with:
Jan 13

I was trying out mock objects today at work. I didn’t really know which implementation to choose. Both JMock and EasyMock seemed pretty good. But I eliminated EasyMock first because I’m just not a big fan of the whole record-replay thing. Then I spent about an hour trying to make JMock work. It sort of did. But I didn’t really like its expectation mechanism. Take an example from their own tutorial. To expect one invocation of add() method on a calculator object, I need to write something like this:

one (calculator).add(2, 2); will(returnValue(5));

That is just too redundant to me. It’s also hard to return value from the method under test so that the workflow can continue. Overall, it just didn’t feel right.

Just when I was about to give up and go back to use my own stub class, I came across a link on JUnit’s site that points me to SevenMock. I spent five minutes setting it up and another five minutes to write the first test using it. And I really liked it. It doesn’t use any fancy expectation syntax and doesn’t have the record-replay feature. The expectation is defined in the form of anonymous inner class. You can put whatever you’d like to assert right in the inner class. So the above example will look like this:

mockControl.expect(new Calculator() {
  int add(int a, int b) {
    assertEquals(2, a);
    assertEquals(2, b);
    return a + b;
  }
});

Notice the return line. You can have the right logic there so that the workflow can continue. Or you can have something that doesn’t make sense at all to test the sad case.

One thing though. SevenMock can only directly mock classes. So you’ll have to create an adaptor for interface or abstract class. But I don’t think that’s a big deal. My next post will explain another reason that made me choose SevenMock: the assertion of the parameters.

Tagged with:
Jul 13

I always do a bad job explaining to people what REST is. Partly because I myself still doesn’t have a crystal idea either. But this explanation is so easy to understand that even your wife (or husband) can get it. It was written in 2004. I guess that shows how “new” REST is.

Jun 11

This was on digg today: Top Ten of Programming Advice NOT to follow. I’d like to share my take on them one by one.

10) “Use error codes instead of exceptions”

Agree. I don’t know why you want to use error codes unless you are dealing with legacy system.

9) “Use unsigned integers for values that can only be positive”

Well, I don’t really care.

8 ) “Design classes parallel to their physical counterparts”

Agree. It would be nice if you can do it. But you don’t have to. Especially if it’s gonna take a lot of effort.

7) “Make sure your team shares a common coding standard”

Disagree. I don’t care what coding style each team member uses. But with all the concurrent development, version control and merging going on, can we at lease use the same code format please?

6) “Write lots of comments”

Agree. Good programmers don’t need and don’t write comments.

5) “Use accessors or properties rather than public fields”

Disagree. I don’t see what’s the big deal with using accessors.

4) “Use the singleton pattern for variables that you KNOW you should have only one instance of”

Kind of agree. But I think singleton is appropriate for looking up stuff like factories or strategies.

3) “Be tolerant with input and strict with output”

Agree. Actually I don’t recall hearing this advice from anybody.

2) “Code all the corner cases immediately, cause otherwise you’ll never go back and fix things”

Agree. If you follow this advice, it means you are not doing Test Driven Development.

1) “Design first, then code”

Agree. That’s sooooo waterfall.

Apr 22

When I first heard of WATIR, it was an eye opener for me. It kicked HttpUnit/JWebUnit’s ass. Why use something that pretends to be a browser while you can simply interact with a real browser, right? After I introduced Ted to Paul Rogers, we started using WATIR extensively in our project. We created hundreds or maybe even thousands of WATIR tests in just a few months. Everything seems to be going well.

But when we object-oriented developers meet a good OO language, we tend to create a thing called object hierarchy. The more object-oriented we are, the deeper the hierarchy we create. This is not a good thing when you are working with a language with close to zero IDE support. Ruby is one of those languages. It’s a nightmare to figure out whether a constant or method has been defined and where it is if it has. There is also a lot of duplications and therefore chances for error because we cannot reuse the Java code in Ruby. Not too many developers are willing to write and maintain them except those who have to.

Here is where Ruby’s impact on Java comes into play. We’ve already seen it in stuff like GWT, Groovy and Grails. Now there is Watij. My coworker Chris found out about it when he’s working on a side project. It’s pretty much a WATIR clone in Java. But it’s easier to use than WATIR because you can reference your Java code, write your tests as JUnit tests and run them in your favourite IDE. It’s also very easy to set up. I can’t post any screen shots here because Watij currently only support IE and I’m a Mac guy. So you have to give it a try yourself. I’m sure you won’t be disappointed.

Mar 16

Have you ever used TreeSet in Java? Let’s say we have a class called AClass. It only inherits from Object and doesn’t implement any interface. Now I want to use the following code snippet to add a collection of AClass to a TreeSet:

TreeSet treeSet = new TreeSet();
treeSet.addAll(listOfAClass)

What happens when you run this piece of code? You get a ClassCastException! Why? Because if you don’t supply a Comparator to the TreeSet, it by default thinks that the element you are adding implements Comparable. It just blindly tries to cast whatever you put in it to Comparable. This is not very nice, is it? Shouldn’t it prevent me from adding element that’s not Comparable in the first place? Exception should be part of the interface. Yes, there is the API and source code I can look at. But in the world of code completion, people rarely do that. An appropriate exception would have been a lot better.

Feb 20

I came across this blog post when I googled rails data type. Below is part of the post:

And what’s the difference between datetime and timestamp? Or binary and boolean? Any database gurus read this?

And one of the comments from the original author:

Ooooh yeah. Duh. Of course binary == storing files in the DB. I guess I was just stuck on “binary” being 0s and 1s and boolean being either a 0 or a 1.

I think we all know it doesn’t take a database guru to answer the question. It’s scary how little computer science knowledge you need to do some “programming”.

Jan 01

I didn’t expect it to be a difficult task. Well, it wasn’t very difficult to do in Ruby. But it was annoying. Not because of Typo or Ruby, but because of Blogger’s crappy API and limited functionality. The following is the steps that I had to go through to make it work:

  • Migrate my old Blogger account to the new one because the old one uses Blogger’s Atom 0.3 API, which is a piece of junk. It doesn’t have the creation date of the post. Therefore it’s impossible to preserve the time when the posts are created. The new Google Data API, on the other hand, has a lot more meta information in it.
  • Change the Allow Blog Feed option in Blogger settings to Full. You can only specify Short or Full but not both for this setting. If you select Short, you can only get the summary in the feed.
  • Now comes the most annoying part. Blogger doesn’t support Markdown so it outputs straight HTML in its feed! Some of the HTML tags caused casting of method parameters to fail when I posted to Typo using metaWeblog API. It took quite a few gsub() to replace those tags with Markdown.

In the end, I was able to migrate all the posts successfully. So Vlad, are you ready to move to Typo now?

Dec 31

We had a test that failed randomly with different actual results today. After spending half an hour on it, I finally figured out what was going on. My coworkers had sorted a list of products first and then used them as keys to create a HashMap. Later on they got the key set out of the HashMap and hope to process the products in order. What they forgot is that Set is not sorted therefore won’t return stuff in the same order they are put in. Our progressive rounding calculator happens to be very order dependent.

You should only sort a collection right before you need it to be sorted. This way you won’t miss a sort. It also makes the interface clearer because sorting a collection should be part of your implementation and other people who are using your API shouldn’t have to do the sort for you.

preload preload preload