Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Wednesday, June 03, 2009

JUnit Assertion Adapter

I have been trying different assertion styles ever since I read this blog, like many others. If you google "assertThat" you can find many hits.

With the creation of Cotta project, I got a chance to really think hard on simple file operations and tests to see how I can make the API as polite as possible, and I think I have found a good answer.

With the default JUnit 4 assertion, you still don't get the benefit of a static typed language, in that you have to remember the class to use to create the matcher for a certain type.

So I created a JUnit assertion adapter that will allow you to type
ensure.that(yourValue)
and get the appropriate assertions object based on the type of the object being passed in. The type of the returned object will have just the assertion methods that are applicable to the value.

This also brings an additional benefit. For example, you can have a list instance and call
ensure.set(list)
and it will automatically convert the list to the set and return the set assertion object.

I have just made a release under the cotta project for general feedback

The simple document page is here: http://cotta.sourceforge.net/assertions.html
and the jar can be downloaded here:https://sourceforge.net/project/showfiles.php?group_id=171037

Sunday, April 22, 2007

GScript - You don't Have to Use Ruby to be Cool

So why do you think Ruby is cool?

If you are like me who work mainly on Java platform, then you probably like Ruby because how much less code you write in Ruby to achieve the same result. Now, if you think about it, not all of them are because of the type-free concept.

With the way that generics goes (what it was and what it is), we can see that the design of Java language comes with some tough trade-offs. After all, I don't suppose you want to piss off the big vendors who keep the money rolling.

Well, what if we can start fresh?

Check this one out...

var list = new ArrayList({one, two})
// this creats a map of beans with ID as key.
var idMap = list.partition(\bean -> bean.ID)
A few notes:
  • The last statement uses closure, in GScript syntax. For anyone familiar with Ruby, this call would be something like "list.partition {|bean| bean.id}"
  • The expression "bean.ID" is actually a "bean.getID()" method call, which is declared as property getter in GScript
  • Even though "list" is a type of List, you can add "Enhancement" to this interface so that you can have additional behavior built on top of existing public methods. This gives you some of the benefit of "mixing" without sacrificing the type safety. If you use apache commons library extensively, you probably have a list of enhancement that you can write already.
  • The type is inferred so you really need to type once. (Note that the type of variable idMap will be inferred as Map<Key, KeyableBean>, a generic map instead of just a Map)
  • Create the list like the way you mean it instead of the Arrays.asList syntax.
You have just caught a glimpse (and I do mean "glimpse") of GScript, the language that Guidewire developed on top of Java. You want a rule engine that can be configured? What about a rule engine that can be programed and deployed without bouncing the server?

There are talks about making this public, by which time you will be able to see the full power of it. Before that, you can consider coming in for an interview. :)

Monday, December 04, 2006

So Much for Java Generics

I always thought that Java generics is supported through compiler is a bit weird, and after 5 hours of email and spike, I finally know why.

Don't get me wrong, I love generics. Even though with TDD I can catch my mistakes most of the time, but with generics I can see my mistakes even before I run the tests. I won't say no to that.

Anyway, it all started with me starting a prove-of-concept project with another friend. So I am setting up libraries and figured I'll use jMock's constraint framework, after I convert it to support generics. Hence started my journey.

I checked out jmock code and was surprised to find out that there is a jmock2 directory. By the document that has been written, it is a way to stay with jMock style but don't lose the type safety. Cool! What is more, the constraint framework has been extracted into something called hamcrest.

Through email, Nat pointed me to the project in sourceforge (duh): http://sourceforge.net/projects/hamcrest. It looks very promising, even have the adapter for JUnit3, JUnit 4, and TestNG. It is apparent the intention of this project.

After I calmed down with all the excitement, I noticed one thing strange: The Matcher interface, the one interface that matching framework is evaluating matching logic, takes the "Object" type, rather than the generic type. What this means is that all the matching instance will have to do a type cast.

"That was silly", thought I, "Surely they know better than this". So I modified the interface in hamcrest, ran all the tests and proudly submitted my patch to Joe.

Turns out that the issue is not hamcrest itself, but jMock.

If you have two methods of the same name that you want to mock, say
public void test(int value);
public void test(String value);

And you provide the expectation
mock.expect("test").with(eq(1))

Upon the invocation of a.test("arg"), it will try to find the match by checking the matcher returned by eq(1) as well as that returned by eq("arg"). When comparing to eq(1) it will fail because from the instance there is no way you can figure out what the generic type is, and invoking by force will cause a class cast exception because there is a class cast injected by the compiler.

So in the above invocation, instead of having something like "unexpected invocation error", you end up with a weird ClassCastException error.

Bloody hell.

Saturday, August 26, 2006

Tying Up Loose End - Cotta

So I have rolled off another project and I am going on the next project right away next week.

Typing up a few the loose end at the moment, since I won't be able to have a couple of weeks beach time like I did last time.

I have started with Cotta because this is most close to being ready. Based on the feedback and my experience with Ruby file handling, I have finalized the core API. Release candidate is now available. Even though I still prefer setting all the API right on the first release, my busy schedule just won't allow it. I think I'll release 1.0 and leave it like that, until I get a chance using it or get some feedback from the field.

Of course, SourceForge is done, so in the meanwhile, only the website is available.

More blog coming up with last project, and other loose ends.

Sunday, July 02, 2006

Cotta Power

So I got one feedback already for Cotta project, neat!

So the million-dollar question is: "How is Cotta different from other files system project like Apache commos VFS, other than support a lot less file system types?"

My first response is, "Ouch, that hurt!"

Second response would be, "Hmm... I think we should think through how we structure our website so that people would not try to compare it with the wrong kind of library"

From the beginning, the main reason behind Cotta project is to make file operations easy to write and test (or verify the behaviours, in jBehave term). So the main focus, which is also the power, of Cotta, is as below in two parts. We are still bouncing our thoughts around it, and the final documentation should be published on cotta project website.

Domain Driven

In my humble opinion, the current File class in Java, or the FileObject in Apache common VFS, or the Url in the VFS system of Borland JBuilder OpenAPI (BTW, it is nicely designed as well), all has one fundamental problem. For this or that reason, they still don't match fully to the domain, which is, in this case, NORMAL file system operation.

The number one problem I have is: "A file is NOT a directory". Namely, you want to list the children of a DIRECTORY, and the parent of a FILE should be a DIRECTORY. You should be able read/write only the content of a FILE, not a DIRECTORY. When your code has a path string, it should already know that it is a DIRECTORY or a FILE.

Also, when I delete a DIRECTORY, it should be GONE, instead of telling me that it is not empty. If I want a safety measure, my filesystem implementation should do that for me. My list can go on for a while if you let me...

Cotta was implemented in that way. As it was written, we have already got a project that does file operations, so we laid out the expected behaviours of the classes one by one, and implemented the code one by one. When it comes down to physical file system operations, there has been no guesses. The resulting API is compact, which is exactly what we intended.

Test Driven

Or Behaviour-Driven to be exact. When I write a class that operates on filesystem, I'd like to be able to verify the behaviour of that class. Even being a seasoned BDD developer, I still like to spend less time writing more functionality. And cutting the time spend on setting up and tearing down environment is always a good choice, hence the birth of XmlFixture (part of XPE, but you'll have to download the package to see the document), DbFixture, and now Cotta.

When it comes to behaviour verification, a common pattern is to go through "Dependency Injection". With Cotta, the domain class just need to work on a "FileSystem" instance being passed in, or one of the Cotta objects (TFileFactory, TFile, TDirectory) that can be created from the FileSystem. During the verification phase, the filesystem is replaced with a "InMemoryFileSystem".

Cotta also has FileSystem decorators that can be used to verify the behaviour on file system like read only (ControlledFileSystem), or file system with disk problems (CatastrophicFileSystem).

What Next?

The idea of making file system implementation for JAR file, FTP etc., was an after thought. I forgot to check with Apache common VFS again to see if I am re-inventing the wheels (as it turns out, I am, more or less). I think the next thing for us to do is to focus more on the two aspects that I have laid out above, and make it clear on the website about the real market value of this project.

Why dive into the Red Ocean when you have already discovered a Blue one, right?

Saturday, July 01, 2006

Cotta Project in Business

Finally we are in bunnies, well, sort of.

A project to ease the pain of using file/directory related operations. See detail at the front page that is still under construction: http://cotta.sourceforge.net