Saturday, 28 July 2007

Electric sheep and collective computer dreams

Just installed me a new screensaver -- the electric sheep. This is not just the most beautiful screensaver I've ever seen. It's a sort of genetic mutation engine. The screensaver is governed by a bunch of parameters ("genes"), which is a common thing. However, here these are not predefined. Numerous combinations are downloaded from the server (or maybe other clients), new combinations are generated by random mutations and uploaded again. You can vote for a combination and thus increase the chance that this specie survives. Thus, the Darwin law dictates that only the most beautiful sheep survive.

The sheep do resemble my computer's dreams indeed.

Thursday, 26 July 2007

Spaghetti on Rails

Yesterday I was totally enraged by the comments to this post. It was so bad I couldn't sleep until I got out of my bed and wrote a comment. Shame on me.

Anyway. People recently talk a lot about this Monorail thing, and how it encourages separation of concerns, testability, and maintainability of your code. I've been sort of curious, but not enough to dig into examples. So, judging from this post and the code example somebody provided, turns out all they can do is the PHP style spaghetti code.

But the most amazing thing is that how much effort these guys put into arguing that 1: This is the best method since it's putting presentation and presentation logic together; 2: Microsoft is bad (again) because they invented the DataGrid (and presumably forcing us to use it everywhere); and 3: "we can do it with less lines of code".
Chill, guys, peace and all that.

Sunday, 15 July 2007

My first attempts at "proper" TDD

Although I've used it several times in the past, my first serious attempt was with FreshReports. That is, I wasn't testing it manually at all.

FreshReports is a printing component (a framework wannabe). It uses xml files as the source for design and in-memory objects (in contrast to the majority of such components that use database rows) for the data.

Naturally, I quickly figured out some basic design, wrote a trivial xml file and started to write tests. In addition, I've been inheriting from System.Drawing.Printing.PrintDocument, and used the hardcoded System.Drawing.Graphics object. Just like all tutorials on printing suggested.

Like any amateur, I thought I was doing unit testing, but in fact I was doing integration tests. I thought I was doing test-first, but in fact I designed something first and tried to fix my bugs with testing. Well, I was doing just fine. I stumbled upon TypeMock, and this wonderful tool allowed me to do a lot of testing without all these IoCs and SoCs people talk about. I said I was doing just fine because, although I could spend an hour or two in the debugger trying to figure out what's going on (or lately, after I read in some blog post that I shouldn't be in the debugger, I started to log way too much to the console and also started writing tests for my private variables), I've been doing it all the time before. I just didn't know there could be a better way.

At least I learned what a mock is. Because before that I thought it was too complicated for me.

My second attempt was with Dormidontus. I've learned a lot since then, and I have heard that unit testing is about testing small isolated pieces. Armed with TypeMock, I could mock everything my methods call (even the class I've been testing). So I decided to move with small steps. I figured, for example, that my main workflow consists of three steps. So, I happily mocked three method calls (because I already figured the classes responsible for these steps), then wrote the main method and got a green. Now, each method call could be naturally broken into smaller steps, so I mocked these smaller steps, repeated the calls in the production code, got a green again.

In short, most of my tests (until I got to the lowest level) contained no asserts, but just mocked calls to other objects. I guess this is what you call interaction-based tests. All went rather smooth, however, I felt that something is wrong. First, my test code duplicated my production code. There was no way to write my production code other than it was dictated by my tests. So, in a way my design was driven by my tests, but at the same time I knew my design before I even started to write a test. Second (a direct consequence), it was impossible to refactor without breaking the tests. Given these two, I felt that my tests are pretty useless, except for the fact that I didn't have to debug my application.

I then posted a question to the testdriven yahoo group regarding testing my high level methods that don't do anything except for calling other lower-level methods. After I received a couple of very clarifying answers, I realized my mistake. Instead of trying to provide some business value as soon as possible, I was focused on my oh-so-elegant design.

I still believe that TypeMock is terrific. It is a pure magic. For example, back to FreshReports, no matter how you abstract and wrap the Graphics object, eventually you should test your wrapper, or adapter, or proxy. You just can't do it without TypeMock.

Some people dislike TypeMock for it does not force you to apply "good" practices. Not only I disagree, it drives me mad. I strongly believe that grown-ups should not be forced. But that's a good idea for another blog post. Now I admit that with regards to TDD I'm far from being a grown-up, so perhaps being forced (or I'd say, led) could be a good thing for me until I'm more confident with these things. However, I'm still thankful since TypeMock gave me a soft start with mocking, and also gave me these lessons.

With Dormidontus, I managed to switch to the right path right in the middle of the project (yes, I even managed to force myself to delete a good part of the existing code). As for FreshReports, with some hesitation I decided to build it again from scratch. I've got the second beta of Orcas Express (too lazy to download and too scared to install the full version). The first beta refused to work with TypeMock, so I decided that it's a sign and I should try RhinoMocks.

Now I'm fighting through my first test.

Wednesday, 11 July 2007

Custom exceptions in custom components

Just published my first article at CodeProject.

At the end they suggested I wrote some conclusion, so I got into a philosophical mood and wrote:

I strongly believe that for every programming pattern out there -- be it GoF, Microsoft, or your own, there should be a corresponding pattern of exception handling and/or raising, or at least the exceptions should be made an essential part of the pattern. After all, exceptions are classes, so many existing patterns could be applied to them. Perhaps some day we'll hear about Exception factories, Exception Strategies, and Exception Observers?

This is interesting, I do read a lot about design practices and patterns lately, and exceptions seem totally out of sight. Why? It's almost like not mentioning the devil..