2008/08/19

Contract Verifiers - Part I. - Introduction

Writing unit tests is costly. Surely less costly than not writing them, but costly too. A commonly accepted trade-off consists in not testing trivial features, or worst, repeating features. You know, all those dozens of little classes that implement repeatedly a roughly similar stuff: custom exceptions, event arguments, equatable, comparable, or disposable interfaces, etc. If you write unit tests, you know how painful and uninteresting it is to test those objects.

Honestly, look at the last project you have worked on. Do you see all those custom exceptions you have written? Have you really tested their serialization and unserialization support? Look at these classes implementing the generic IEquatable interface. Have you verified that the equality behaves correctly in all the possible ways (to a null reference, to itself, commutability of the operation, etc?) If the answer is no, then I sympathize. If yes, well, it was a so boring job, wasn't it?



The next release of Gallio (alpha 4) will come with a cool feature called Contract Verifiers. Actually, it is already available in the alpha 3, but under a preliminary form which will be probably marked as obsolete in the future (or perhaps simply removed).
[Update; Actually, Jeff has just removed it from the repository.]

The principle of the contract verifiers is simple. Basically, a contract verifier is a set of predetermined test methods that you can attach to a given test fixture without actually writing them (we could describe it as a kind of Mixin). The test methods will verify for you that the object fulfills the given implementation contract. It is an all-in-one functionality because the test methods have already been written for you. They also support some configuration; so they can be used in different scenarios.

Let's take an example. Imagine you need to write a class A implementing a well-known interface, or deriving from a well-known base class. Let's call it X. You will have to override the necessary members of X, so that A works correctly; and to write a bunch of unit tests that will verify that the functionalities of X (let's call them x1, x2 and x3) work as expected in your implementation of A. Fortunately, Gallio comes with a contract verifier for X. We will name it XContractVerifier. Unit testing A comes suddenly easy:

[TestFixture]
[TestsOn(typeof(A)]
[XContractVerifier(option1=blabla, option2=blabla)]
public class ATest
{
// My other own tests here...
}

Thanks to the XContractVerifier attribute, and during the execution of the test fixture, the test runner of Gallio will add behind the scene, the necessary test methods that will verify that A implements correctly x1, x2, and x3.

Gallio Alpha 4 includes three built-in contract verifiers (it is a beginning):
It is interesting to notice that the internal working of the contract verifiers is based on the remarkable capability of the Gallio exploration engine to dynamically attach child test methods to a given fixture; although those test methods do not physically exist.

2008/07/25

Contributing to Gallio

It is not the first time I have a close look at the source code of an open source project. My hard drive has a dedicated folder where I can find the internals of NHibernate, Paint.NET, Rhino, or Castle. Studying and analyzing good code, and understanding the whys and hows of its internal design, is worth the time you will invest. There is so much to learn from the guru coders who lead those projects.

However, it is the first time I have the desire to contribute significantly to such a project (Other than submitting small patches which fix minor issues). I discovered the Gallio Automation Platform early in its alpha 1 stage. It was an exciting project with tons of innovative concepts; and I have eagerly followed the development phases since that very moment.

When Jeff Brown, the lead developer of Gallio, mentioned in his blog the existence of the contract verifiers, I immediately thought that it was a cool feature that I would like to work on. Two months later and with Jeff's invaluable help, I am in the process of refactoring completely the implementation of the contract verifiers for MbUnit v3, based on Jeff's own road map and ideas. I am more than happy to work on such a great project during my free time.

Expect to learn about contract verifiers later on this blog.

2008/07/05

Every interface is public

A few days ago, I posted a comment on timm's blog. I made a remark about the difficulties that most .NET developers had and still have when they have to handle with Stream objects to read and write text files; especially in the early days of the .NET framework, when methods such as File.ReadAllText and File.ReadAllLines did not exist yet.

Then, I remembered reading that on the book written by Brad Adams and Krzysztof Cwalina: "Framework Design Guidelines".



Although published already two years ago, this is still an excellent reference about naming conventions, sane type design and class library extensibility. Perhaps it would deserve a second edition with additional stuff about C#3, Linq, WPF, WCF, etc. This book is also a source of valuable comments and amusing little stories from various actors in the .NET framework world, explaining why some classes were designed the way they are, or which were the difficulties they met while designing the class library. Delightful…

However, there is a little point in that book which I tend to disagree with. It is apparently only a detail, but which hides perhaps an entirely different philosophical point of view about code design. The authors say about naming guidelines:
Although adopting these naming conventions as general code development guidelines would result in more consistent naming throughout your code, you are required only to apply them to APIs that are publicly exposed.

As a corporate developer, I write code that has little chance to be read or to be reused by other developers outside my work place. The question I ask myself, is what exactly "publicly exposed APIs" mean? Technically speaking, it should be any type or member with a public scope. But actually, when my colleague reads my code, he has also access to objects with private or internal scope. When I download the code of an open-source project such as Rhino or the promising Gallio, I also have access to internal types. In VS2008, we have also the possibility to see the source code of the class library, which has not a public scope. And finally, when I stop working for a while on a project of mine, the person I am when I resume the job is not exactly the same. I have perhaps forgotten how the system was designed; so I come with a new fresh eye and new recently acquired experience.

I believe that "publicly exposed APIs" is not synonym of "types and members with a public scope". In fact, I tend to consider every single line of code as public at a certain level: public to other anonymous developers, public to your colleagues, or only public to you. As soon as a line of code is written, it can obviously be read as well. Maybe not by everyone, but at least by you and the other developers who work with you.

That's why I think it does not make sense to apply partially such a guideline. It's like pushing dust under the carpet. For sure, people passing next to the house will never know you do that. They will only see the "public interface", that is the front of your home. But your family might discover it, or your neighbor, who will visit you one day or another. But more important, YOU will know it. If you can live with that mess in your code, I have the bad feeling that you are not rigorous enough to become a good developer.

2008/06/24

Better be deaf

As promised, today, I am going to share with you an amusing anecdote which demonstrates how a poorly designed user interface can ruin a good and simple system into something which is hardly usable.

I already talked you about my elevator front panel. I know another device in my apartment building which deserves, I believe, some words: my entry phone!



In fact, my entry phone has nothing special compared to the other entry phones in the building. They are all the same. Its usage is also very usual. Each phone is connected to a microphone located at the entrance of the building. When a visitor wants to enter the building, she presses a button close to the door. The host hears a short tone melody which warns about the presence of a visitor. The host comes to the entry phone, and speaks into the microphone to the visitor. Eventually, the host lets the visitor enter the building by pressing another button. As I said, nothing unusual.

But the entry phone has a second functionality. There is also a ring at the door of the apartment. That ring is connected to entry phone as well. When a visitor rings, the host hears a melody which warns about the presence of the visitor (deja vu?). The host comes at the door, looks into the peephole, and eventually opens the door and welcomes the visitor.

Perhaps you already figured out what is the problem: the tone melodies. In both the scenarios, the entry phone plays a tone melody and there is no easy way to know where the visitor is: at the entrance of the building, or at the entrance of the apartment. One could argue that any visitor will first come at the entrance of the building, but it is no help for several reasons: the entrance of the building was sometimes left unclosed by a previous visitor; or you are sometimes visited by your own neighbor; or some people are actually visiting all the inhabitants so they need obviously to enter the building only once.

At the beginning, I did believe it was only me. Perhaps I have a bad sound memory, or perhaps I would finally learn for what event is each melody. But surprisingly, ten years after, the problem remains the same. Each time the phone entry plays the little music, I don't know where to go: at the entry phone or at the door. My wife does experience the exact same problem. But it seems my neighbors too! A few weeks ago, I needed to talk to one of them. So I rang at his door. After some seconds, I clearly hear my neighbor not too far behind the door trying to vainly speak in the entry phone: "Hello? Hello? Who is it?" So I just knock at the door to tell him he should stop speaking alone in the microphone and come at the door instead.

The fact is that the system exposes two different features through a problematic user interface:
  • It uses a single communication channel: sound. No light, no display, nothing else. But it's not the worst issue, as most of the existing user interfaces do the same without any major problem (phones, traffic signs, and even software applications which most of the time, focus on visual user experience only.)
  • Both the features are exposed through symbols (the melodies) which are totally disconnected from their meaning. They do not evoke anything. They are just a short abstract series of unrelated tones without any semantic. You have to be very imaginative to be able to associate them with one feature or another.
I am unsure what solution could have been chosen to design an effective interface for that system: visual support, multiple sound source (at the door and at the entry phone), better distinct melodies, artificial voice? (I'm a bit reluctant about using artificial human voice when not absolutely necessary. It tends to be quickly irritating. This is something I will probably come back later in a future post.)

What I know for sure is that the designer should have issued a meeting notice for some brainstorm with his colleagues.

2008/06/16

Oversimplification

The lead developer of NDepend, Patrick Smacchia, explains what he considers a key to a successful interface design:

Make the simple things simple and hard things possible. IMHO, this tenet applies perfectly in how UI should be designed. Typically, the most direct way to use a UI control should result in the most awaited feature from a user perspective (make the simple things simple). Then, some extra/hidden UI control facilities can be added to the control to support more in-depth scenario (make hard things possible).

But achieving simplicity in interface design is everything but an easy task. A common mistake (but apparently not so commonly known) is the oversimplification. It consists in an unfortunate too low threshold in what the designer considers simple things and hard things. It's an error because it may lead the average user to frustration. Every time she needs to activate such a designated "hard" feature, although she would consider it as a basic feature, she has to manipulate a more complex interface to access to the hidden functionality.

A good example is the automatic collapsed/expanded menu of Microsoft Office 2003. Why features like text replace or page setup were put by default in the "hard things" list? The authors have apparently decided that those functionnalities are less commonly used. Perhaps it is true actually, for most users. But what about people who, for a reason or another, needs to use them twenty or fourty times a day?
But generally speaking, determining what is simple and what is hard is a difficult task; especially if you target a wide audience from the modest grandma to the tech geek. Mitigation is always possible by providing some options for personal customization, or automatic adaptation based on the most frequently used commands (like the menus described aboved, in fact). But in the real world (I mean the non-IT world), this is sometimes just impossible. Look at this remote control device I saw recently in a paper advertisment.



Although very simple, the idea is great and not so common for that kind of device. When folded, it presents just a few buttons for the very basic features: turn the TV on and off, change the channels, etc. Only when unfolding it, you can access to the advanced functionalities. One can suppose that a feature like video recording or TV internet access is probably only accessible from inside the remote control. This is surely not an issue for grandma. But for the tech geek, after all, it’s perhaps not a so well designed device.

Think twice about your audience and its level of expertise before implementing such a solution, whatever your system is software- or hardware-based.

2008/06/09

Turn right... but not so much!

In his excellent blog, Jeff Atwood already talked several times about road signs in the perspective of user interface design. Indeed, as a professional software developer, I have occasionally to design interfaces (end-user panels, API, or frameworks); and I share the fascination of Jeff for road signs and for symbols usage in general.

In a previous article, I already made an analogy between road signs and software interfaces, about the necessity to design consistent models.

But even though you follow your own design rules and make a consistent interface, you still have make a proper usage of it. Let's continue our analogy with traffic signs and look at the following picture I took recently there.


So what? Obviously, you must turn right soon. But why installing two nearly identical traffic signs located at 10 meters from each other. The first sign indicates that the road turns 90° right; but a few meters later, it's only 45°.

According to the local driving rules (Page 121), the two signs have actually the same meaning: they indicate to the drivers the obligatory way(s) to follow according to the direction indicated by the arrow. So in fact, I cannot see any logical nor legal reason for the presence of those signs with a different arrow.

This example is a perfect illustration of an interface with a good design (simple sign intuitively understandable) but used improperly or inconsistently. Or did I miss something ?

2008/06/01

Written interfaces and localization

I live in a non-English speaking country. Although a significant part of the population can speak English a little, the vast majority of it does not know a single word. This is the case for my wife. She perfectly speaks Portuguese and French, and she has some solid notions of Italian and Spanish, but no English at all.

Of course, there is nothing wrong. The most annoying for her is the plethora of little devices we daily uses (computers, recorders, music players, etc.) and which have been designed for international marketing but without any consideration for localization of the user interface. Look at that radio alarm for instance:


Each time my wife wants to change the settings, she has to ask me whether she must switch it on or off. That is because she has no idea what "on" or "off" means. For her, it could be so well written "sglurmf" and "zxqwaghs"! Without any reference, it is very difficult to remember a foreign word and its meaning.

In the IT world and especially on the Internet, the possibility to switch between languages is so common that we do not notice it any more. But unfortunately, it is not so easy for non-software user interfaces.