Monday, October 17, 2005

More tests, less comments

I tried to practice Test Driven Development (TDD) where possible during the past couple of months. One interesting thing I noticed is that the more tests I write, the less comments I put into my code. I think it’s because TDD forces me to think about the functionality I’d like to have in my system before implementing it. Without TDD, when I for instance have to implement a new method, I usually write the method’s comment first. While writing I think about the task of the method, it’s outcome, constraints and all these things. I may decide to split the method into two or not to implement it at all because it’s nonsense. All this happens before I write a single line of code (I don’t really consider comments as code). Hence the main purpose of comments is forcing me to think about the behavior of a code fragment before implementing it. As a side effect, the comments may help others who have to use or to modify the code. TDD does exactly the same thing. Before I implement a new method I first write a test. While writing the test I think about the method’s behavior much in the same way I did when writing comments. The test also helps others to understand what’s going on. Even better, it provides a sort of “executable documentation”. If someone changes the code, she or he can run the test to ensure that everything still behaves as expected (documented). Now, adding a comment to the code is like restating the test in another language. Thus it would be a violation to the DRY principle so I usually don’t add comments for things I have a test for.

Beside this, it’s more difficult to keep comments and code synchronized than tests and code. A test fails if you change the behavior of the tested code fragment. This forces you to either adjust the code or the test. But for comments, you have to check them manually and it’s too easy to let them slip. At the end, we have code with wrong comments which is quite worse, even more worse than having code without comments.

Interestingly, the testing aspect is “just” a side effect of the TDD approach (much in the same way as “documentation” is a side effect of writing comments). The main reason for writing a test is, as stated before, to justify the expected behavior of the code to be written. The term Test Driven Development is therefore a bit misleading. It’s more about behavior than testing. Therefore, the term Behavior Driven Development/Design fits better. Have a look at this blog entry from Elizabeth Keogh for an idea of what “test” stands for in TDD. There are many other interesting reads in this blog about TDD/BDD.

Monday, September 12, 2005

Vindaloo Progress

Good news today. I finally got the search function working in the Vindaloo PDF reader. I'm quite excited that I managed to implement it like Firefox does. The user enters some text in the find textfield and after a short delay of 250 milliseconds the search starts. No need to press a find button. When the contents of the textfield change, the search is automatically restarted. The delay prevents the search to be restarted just after each letter of a word. 250 milliseconds is the upper bound for what a user usually experiences as "immediatly". The best is that all this works reasonably fast and the user interface keeps responsive (at least responsive enough). The whole thing still needs some work but I think I'm out of the woods today.

Sunday, September 04, 2005

MocKit

I recently started development of a small MockObjects
Cocoa/GNUstep framework called "MocKit". MockObjects is a technique to test for interactions of objects instead of state. MocKit is inspired by the jMock framework that is written in Java. The interesting thing about jMock is that it provides a small embedded domain specific language for defining expectations about object interactions. With expectations, you basically say what messages you expect to be send to an object during a test scenario. The document "Mock Roles, not Objects" describes this approach in more detail. MocKit follows the ideas of jMock although it's not an exact reimplementation.

Here is a little example.

id mock=[MockObject mockForClass: [MyClass class]];
[[[[mock expect: @selector(someMethodWithArg:)]
times: 2]
with: ArgEquals([NSNumber numberWithInt: 42])]
willAlwaysReturn: @"this is the answer"];
// run test scenario
[mock verify];

The approach of providing an embedded domain specific language for MockObjects is what makes MocKit different from OCUnit. OCUnit uses a recorder based approach. You first "record" the messages that are expected to be send to an object and run your test scenario. The messages send to the object during the test must match the previously recorded messages. The main advantage of MocKit is that it provides a more flexible approach. If focuses on expressing rules for object interactions. The resulting code (see example above) does not only test but also documents a system. By looking at the test code, one can easily see how objects in a system behave.

MocKit is currently in a usable state although it needs some polishing before I will release an official version. If you are interested, you can browse the darcs repository online. If you want to try MocKit, download the repository archive. It contains a makefile for the GNUstep environment as well as an XCode project (XCode 2 is required). For an introduction read MocKit/Documentation/MocKit.text. If you have questions or problems you can send me a mail (stefankst - at - gmail.com).

darcs

I switched to darcs for a few of my personal projects now. Darcs is a decentralized revision control system that does not require a central repository like Subversion and CVS do. Instead, you can have an arbitrary number of copies of a repository and darcs provides commands to keep these copies in synch.

With darcs, the number of developers who can work on a project is not limited. You can just put your repository on some http-server and everyone who wants can get a local copy of this repository by using darcs' get command. Changes made to the local copies are also recorded locally. Using darcs synchronization commands, changes can be populated from any repository to any other. A very useful feature is darcs' support for distributing changes via email. A developer can create a patch bundle for her local repository. This bundle is emailed to other developers who can then apply it to their repositories.

Darcs has no such things as branches. Just think of each copy of a repository as a branch. Changes can be moved back and forth between these copies. The drawback is that darcs doesn't support branch management as subversion or CVS do. But i'm not sure now if this could be a problem for me. The future will show.

I'm using darcs for a few weeks now and I'm quite satisfied. I have always found it annoying to setup a central repository for a one-man project. In addition, the absence of a central repository also eliminates the single-point of failure which is inherent to Subversion, CVS and friends. With darcs, the repository lives inside my working copy and no server failure can prevent me from using it. On the other hand, I can easily give other developers access to my project by providing a copy of my repository on some server. I neither have to setup nor to administrate a central repository.

Darcs is a fresh and lightweight system with a few straightforward concepts that are easy to understand. It runs on almost any platform so if you are not already using it, go and give it try.

Friday, August 19, 2005

Tiger

My PowerBook is running Mac OSX Tiger now for almost two weeks and I have to admit that I like it. I was a bit skeptical when has been announced because it seemed to me that they're moving in the wrong direction. Instead of making the user interface clean and more usable, Apple kept adding new features. I was especially concerned about Dashboard since it looked like a big blob of animated effects. More for marketing than for real users. However, I need Java 1.5 for University and so I finally ordered my copy after resisting for a few months.

To make it short, I was quite impressed. Installation went smooth as usual. The user interface elements are looking a bit cleaner now and Spotlight is unquestionable a big step forward. I still use my favorite tool LaunchBar to start applications, lookup addresses and sometimes navigate through my folders (go and get it, it's really great). But I can now drop all my PDF files and other documents into a single place and don't have to worry about placing them in more or less meaningful named folders (I almost never felt that I got my folder names right). One can assign metadata (called "Spotlight Comments") to documents but I'm not using it much. I feel there is enough data in most documents, so I don't think that adding more (meta)data provides much value.

I even find myself using Dashboard regularly. I'm ashamed but I like these neat little animation effects. I've setup my Dashboard with some quite useful widgets and it's nice to have them all at hand with a single key press. I find people (mostly Windows users) looking at it and saying how unprofessional and kittenish it looks. I think they are just envious because they don't have a nice looking notebook with a cool operating system. They are stuck with Windows OS and got so frustrated about it's mediocrity that they have to attack superior things. They would feel even more frustrated about their bad OS otherwise. Ups, I zoned out at bit.

Dashboard Screenshot

Speed has also improved by an order of magnitude. Well, if you have enough RAM. I've heard from a friend who owns a PowerBook stuffed with 256 megs that things slowed down compared to Panther. I've 768 megs of RAM and my PowerBook got speed bumped. Especially bootup is much faster now.

Of course there is room for improvement. Sometimes it's quite unhandy to have the Dashboard widgets only, well, on the Dashboard. If I try to sum up some numbers from an application using the Calculator widget, I'd like to copy the values from the application to the Calculator. It really drives me crazy to constantly toggle between Dashboard and application. I wish I could pick a widget from the Dashboard and take it into the foreground, putting it back when I'm done.

There are some rough edges in the system (eg my Terminal application sometimes fails to open a new window) but I expect them to disappear with future updates. There's nothing such serious that I'm really annoyed about it.

And I still would like to get the Shelf from the NeXTSTEP Workspace Manager back!!

Friday, August 05, 2005

Avoid Inheritance

I recently had to deal with a part of a system I'm working on that makes heavy use of implementation inheritance. The class hierarchy was quite complex and from the top it looked like a clumsy ball of classes. It took me quite a while to figure out what was going on. Information was spread over the classes in the inheritance tree and information has been duplicated in different classes. To make things even worse, the programmer was using anemic domain objects with almost no behavior. I figured out that the part of the system could be redesigned to be much cleaner and more extensible using almost no inheritance. I always wonder about this inheritance thing. I've talked to people who insist that inheritance, often proposed to be a key concept of today's OO languages, must be good to achieve reusability and maintainability.

But if you look around, it's hard to come up with a real-world example for inheritance. The world is composed, not inherited. Almost every object you see consists of several smaller "objects" working nicely together. Objects can be rearranged and combined in different manners to form new, bigger objects. You can use a stone to build a house or as a bookend. The stone doesn't care. It's perfectly decoupled from it's environment. You may say that you've inherited properties from your parents but in fact you don't "extend" your mother. You extend nothing. You're mother and father gave you a "construction plan" for your body, the DNA. And this construction plan is itself tells other objects how to build and arrange the cells your body consits of (can you feel the patterns emerging?). Still no inheritance in OO sense.

The concept of inheritance is rather abstract. In most OO languages, you define types (Classes) and objects are instances of these types. A type can extend another type. This is probably why one can't easily come up with a real-world example for the inheritance concept. The world is untyped. And even more, it doesn't need these types. Why do programmers? There are prototype-based languages, like Self, which don't have classes at all. They just have objects. New objects are created by copying and customization of existing objects. If you copy an object, it keeps a reference to it's source object and delegates messages it cannot handle itself to this object. This mechanism is called DelegationInhertiance and I like to put the emphasis on delegation. I feel this approach is more Object Oriented than our usual languages like Java etc. In fact, these languages should be called Class-Oriented, not Object-Oriented.

What does this mean for programmers? Well, I certainly don't want to tell you what this means for you. For me, this means that I strive to build systems that consist of small and shy objects working together. I aim to follow the "tell, don't ask" principle. I try to avoid inheritance where I can and favor delegation. Strategies and decorators are often a more flexible replacement for inheritance. I use interfaces to separate the different aspects and concerns of objects. I try to use dynamically-typed languages whenever I can since they make life so much easier.

Friday, July 29, 2005

Expressive Smalltalk

This is why I really like Smalltalk (and it's dynamically typed companions).

Determine the date at 12 days and 5 hours in the future!
Smalltalk:
future := DateAndTime now + 12 days + 5 hours.
Java:
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DAY_OF_MONTH, 12);
cal.add(Calendar.HOUR_OF_DAY, 5);
Date future = cal.getTime();
(Sun could at least make Calendar's add method return the Calendar itself so that we could daisy-chain the add calls like cal.add(...).add(...)).

Now tell me, which one is more expressive? This is exactly the advantage of the "everything is an object" principle. And maybe this expressiveness is the reason why in-language Domain Specific Languages (http://martinfowler.com/bliki/DomainSpecificLanguage.html) are so much easier to implement in languages like Smalltalk than in this Java crap.

Monday, July 25, 2005

Into Smalltalk

I think it is a good idea for a software developer to frequently learn a new programming language (http://www.pragmaticprogrammer.com/loty/). Even if you don't need the language at work, it'll change the way how you look at problems. So for this year, I decided to learn some Smalltalk. Well, I have to admit that it is not totally new to me. I've done a bit Smalltalk a few years ago but it was fairly basic. This time, I'll do a little application to cover different aspects and to really learn the language. The application is about recording working times for the projects I'm working with. Nothing spectacular but I think it has the right size for a "pet project". The application will get a small web interface which I plan to implement in Seaside.
After checking out Cincom Visual Works and Squeak, I opted for the latter since it runs at reasonable speed on nearly every platform. Visual Works is also pretty cross-platform but the user interface was so damn slow on my PowerBook that I wasn't able to really work with it. Squeaks user interface is, well, some sort of ugly but it's ok and very functional. And because my application will get a web interface, I don't really care about this.
Finally, I found a great book that's freely available online. It's called "Smalltalk by Example", you can get it from http://www.iam.unibe.ch/~ducasse/FreeBooks/ByExample. I immediately liked the style this book is written. If you are an experienced software developer, you can get the important things out of the book without having to read through much "noise". It's also a very good reference.
Oh, and one more thing at the end. There is a great intro into Squeak available at http://wilkesjoiner.com/UsingSqueak.html. It contains some nice videos.

Wednesday, July 20, 2005

Vindaloo 0.2

I completed the second increment of the Vinaloo PDF reader. Along with this comes an updated version of PopplerKit.
Download links:
The OSX version of Vindaloo comes bundled with PopplerKit, you don't need to install it seperatly. You only need PopplerKit for OSX if you want to do development with PopplerKit. The GNUstep archives contain the sourcecode which has to be compiled. This is done using the standard make and make install procedure. Vindaloo 0.2 won't work with older versions of PopplerKit. Installation instructions for PopplerKit can be found in the docs directory of the distribution. Please READ them!

What's new in Vindaloo & PopplerKit?
  • page caching for singlepage view
  • center page in scrollview
  • don't shove page into the edge when zooming in
  • adjust zoom factor when the window is resized such that the current page is either scaled to fit completly, by it's width or by it's height
  • better support for fontconfig in PopplerKit
  • minor UI tweaks and bug fixes
What comes next?
A search function is urgently required. At least I wish I had one in Vindaloo almost every day I'm using it. So the focus of the next increment will be to implement a simple search function.

Saturday, July 16, 2005

PopplerKit & Fontconfig

Upcoming changes in the poppler library forced me to spend some effort on integrating PopplerKit with fontconfig. Until now, PopplerKit comes with it's own fonts and bypasses fontconfig using the "old" font mechanism from xpdf. The poppler library is currently changed to use ONLY fontconfig. I now figured out how to integrate fontconfig. On OSX, PopplerKit will setup it's own fontconfig configuration with the default OSX font locations (/Library/Fonts,...). On GNUstep, PopplerKit will use the system wide fontconfig library and it's configuration. In both cases, some default PDF fonts that are bundled with PopplerKit will be added to fontconfig's configuration such that at least the minimum set of required fonts is available everywhere. GNUstep users will benefit most from proper fontconfig integration since PopplerKit (and thus the Vindaloo PDF reader) can make use of the system wide fonts. As a side effect, the way PopplerKit "handles" fonts is not much better. The changes are currently in an experimental branch. I need to do some more testing before I move them into the main trunk.

Sunday, July 03, 2005

Hello World!

Hmm, this is my very first blog post so: "Hello World!". My name is Stefan, I'm about 30 years old and a professional software developer with focus on object oriented technologies. Beside this, I'm currently attending to a Master course in software technology at the Unveristy of Lueneburg. This blog will be about thoughts on software development and my projects.