Ayende @ Rahien

Refunds available at head office

On API Design

Krzysztof points out that Rhino Mocks has 26(!) methods to create various mocks.

I was very surprised to hear that, so I took a look, and he is right. The problem is how you think about those. Those 26 methods are only applicable when you count each overload as a separate method. Without counting the overloads, we have 10 methods. Then we have to consider options. In Rhino Mocks, you tend to have the following options: Create mock, create mock with remoting, create mock from multiple types.

That works to reduce the amount of options that we have down to about 4 different types of mocks that Rhino Mocks can generate. And you know what. Almost all the time, you don't need to use them. You only have to use DynamicMock and that is it.

Krzysztof suggestion would consolidate all the options to a far smaller surface area, but it would have several major issues:

  • Break backward compatibility - I am wiling to do that, but not without due consideration.
  • Break the documentation - See previous point.
  • Force the user to deal with all the options explicitly - "In your face!" API design, from my perspective. That would lead people to create utility methods over it, which gets us right back to all the method options.

Comments

Krzysztof Koźmic
04/21/2008 08:03 PM by
Krzysztof Koźmic

Notice that I suggested not changing current MockRepository (at least for few releases), but creating a Facade for it. This way you don't break anything.

I'm not sure I understand what you mean by "In your face design".

Having methods that explicitly state kind of mock/stub you create is as explicit as using enum to denote it.

I agree, People will use DynamicMock 95% of the time (probably with no constructor parameters or multimocks).

With syntax I suggested its simply:

var foo = repo.Mock();

I don't see forcing anyone to deal with all options explicitly here. It's even less explicit than

var foo = repo.DynamicMock();

Also by using enum with FlagsAttribute you hide options like mocks with remoting that 99% users will never use.

And as with everything - each choice has pros and cons.

I'm not saying mine is the only one right, I'm far from that. I wanted to start a debate and I'm glad I succeeded with that.

PS. I also updated my example, to make it even a bit simpler.

Nikola Malovic
04/21/2008 08:36 PM by
Nikola Malovic

I like the facade idea. Sounds easier to explain to people rhino basics which is very scary for some people starting to use mocks.

Benny Thomas
04/21/2008 10:08 PM by
Benny Thomas

I dont see any problem in breaking the api. But I understand the documentationpart.

Who doent hate to write documentation.

Mike Minutillo
04/22/2008 03:39 AM by
Mike Minutillo

Out of interest I would look at the opportunity make the API more explicit (i.e. the "In your face" option specified) but add in a set of Compatability Extension Methods. These could be included (or not) at the users discretion to provide "simple" options via overloads. This makes the distinction clear between what is Core functionality and what is syntactic sugar. This way all that is required for backward compatability is to include a new namespace or two. Of course, this only really works for VS2008 customers.

Joseph Gutierrez
04/22/2008 02:33 PM by
Joseph Gutierrez

Facade would be nice.

With the 'in your face API'.

Gian Maria Ricci
04/26/2008 06:39 AM by
Gian Maria Ricci

I like the idea of the Facade, it is a good way not to break compatibility, but could give access only to the core functionality, to not "distract" new user with all the capability of the library.

alk.

Krzysztof Koźmic
04/28/2008 06:02 AM by
Krzysztof Koźmic

@Gian.

That was also my main goal. Not necessarily to expand it's capabilities, but what can be done to simplify access to those features that are already out there. How to make it easier for newcomers to start using it, and how to make it more likely for them to succeed.

Comments have been closed on this topic.