Calling the library explicit?

Nov 22, 2008 at 8:22 PM
Edited Nov 23, 2008 at 10:12 AM
I like your Library very much. I even throw away my own code, that looked similar, but wasn't using extension methods, and I am now using yours!

The only thing I don't like, is that its methods, Requires and Ensures, are being forced on to 'almost' every object. I don't like that and I don't think it's needed or giving any additional benefit over calling it explicitly.

It's also not following the best practices from members of the VB Team, I agree with. 

Maby it's better, to create an explicit way, like so:
// Check all preconditions:
Require.That(id, "id")
.IsNotNull()  
.IsInRange(1, 999) 
.IsNotEqualTo(128);

/* Check all postconditions: */
Ensure.That(result, "result")
.IsNotNull()  
.IsOfType(typeof(ICollection));

I have added this classes to your library, removed the entry points, and using it like this.

Move the extension methods Requires and Ensures to a seperate namespace, so the user has an option to use them. What do you think about that?


Coordinator
Nov 24, 2008 at 9:50 PM
Hi Remy,

Thank you for using CuttingEdge.Conditions.

I understand your concern, and you are right about the VB best practices. As a matter of fact, CuttingEdge.Conditions breaks a Framework Design Guidelines rule. The FDG state that you shouldn't create extension methods on System.Object, but as you know this is exactly what CuttingEdge.Conditions does. I have considered this in the past, because I wasn't sure I wanted to break the FDG and the fact that extension methods don't work for System.Object in VB.NET, but I also wanted to keep the API fluent. While moving the entry point extension methods to another namespace fixes the problem you've encountered, it makes the library a little harder to use for those people who use the library the 'normal' way. They'll have to add a two namespaces instead of one. I designed CuttingEdge.Conditions to be as easy to use as possible. Therefore I'm afraid I'm not willing to change the library in the way you proposed.

Of course you're completely free to change CuttingEdge.Conditions the way you want and make a local build, as you've already done.

I hope you still keep using CuttingEdge.Conditions (or your local build) ;-).

Nov 27, 2008 at 10:46 PM
Edited Nov 27, 2008 at 10:49 PM

Is keeping the API fluent the only reason to break the FDG rule? If so, do you really think that’s enough reason to break the rule? I think not, but you already know that ;-).

Some other arguments for not doing it:
- The suggestion I gave is still a fluent API, different, but still fluent. I even like mine suggestion for a fluent API even better, but that’s a matter of taste and we can’t discuss that ;-).
- For developers new to .NET (and/or mine team), it can lead to confusion if Requires() and Ensures() methods are on every object and they don’t get it that these are extension methods from your library.
- You only use these extension methods when entering a method and/or leaving a method, but you force it on every object between it.
- If developers are practicing DbC only partially and only use the Requires() method, but they don’t use Ensures(), then they have an useless method on every object they use.

I still will be using your framework, but it gives me some friction to change and build it everytime you released a new build of it.



Coordinator
Dec 27, 2008 at 11:54 AM
I just checked in a code change (change set 23737) that might be useful to you. While I didn't move the entry point methods Requires and Ensures to another namespace, I moved them to another class, named 'Condition'.  This allows you to write validation like so:

' Check all preconditions:
Condition.Requires(id, "id").IsNotNull().IsInRange(1, 999).IsNotEqualTo(128)

' Check all postconditions:
Condition.Ensures(result, "result").IsOfType(GetType(ICollection))

The code snippets for VB changed to use this syntax. Requires and Ensures are still extension methods, but you can now simply remove the 'this' operator from the extension methods and recompile the project and you're good to go.

I hope this helps.