locked
For CodeContracts, I think the syntax\API of CuttingEdge.Conditions is better. RRS feed

  • Question

  • Did you looked at the CuttingEdge.Conditions library? Code Contracts still gives me the work of creating the predicates, but CuttingEdge.Conditions has 95% of the predicates already build in. Also they syntax is better, because it instantly makes it clear what is checked. param != null is simple, but some predicates can become very difficult to understand and to read.

    The syntax of the library makes the following possible:
        id.Requires("id")  
            .IsNotNull()          /* throws ArgumentNullException on failure */ 
            .IsInRange(1, 999)    /* ArgumentOutOfRangeException on failure */ 
            .IsNotEqualTo(128);   /* throws ArgumentException on failure */ 
          
        xml.Requires("xml")  
            .StartsWith("<data>"/* throws ArgumentException on failure */ 
            .EndsWith("</data>"); /* throws ArgumentException on failure */ 
          
        col.Requires("col")  
            .IsNotNull()          /* throws ArgumentNullException on failure */ 
            .IsEmpty();           /* throws ArgumentException on failure */ 

    I changed one class of the library, to get the following syntax, which I like even more:
    Contract.Requires(id)                  
         .IsInRange(1, 999)  
         .IsNotEqualTo(128);  
     
    Contract.Requires(str)  
         .IsNotNullOrEmpty()  
         .HasLength(100)  
         .StartsWith("<data>")  
         .EndsWith("</data>"); 

    I hope that CodeContracts will have 95% of the predicates already done for me, because this saves me alot of work and the predicates are easy to understand\read by other programmers.

    What do you think about this?
    Thursday, January 15, 2009 10:01 PM

Answers

  • Thanks! We have looked at those kind of extension methods. While we are always looking for ways to improve the syntax (and are quite aware of how sub-optimal it is at present!), we're not sure that the CuttingEdge library is really better. For one thing, it seems limited to conditions on single parameters, where many contracts relate multiple parameters. Also, I'm not sure that x.IsNotEqualTo(y) is really shorter than writing "x != y". But we should continue this discussion and see if there are ways to get better syntax, short of language integration which we're still hopeful for.
    Wednesday, January 21, 2009 6:41 PM
    Moderator

All replies

  • The use of the extensions mechanism that CuttingEdge relies upon is an intriguing approach. Same with the provision of numerous predicates, which can be handy. Does CuttingEdge have any plans to support "OldValue" or "Result"?
    Sunday, January 18, 2009 4:05 PM
  • Thanks! We have looked at those kind of extension methods. While we are always looking for ways to improve the syntax (and are quite aware of how sub-optimal it is at present!), we're not sure that the CuttingEdge library is really better. For one thing, it seems limited to conditions on single parameters, where many contracts relate multiple parameters. Also, I'm not sure that x.IsNotEqualTo(y) is really shorter than writing "x != y". But we should continue this discussion and see if there are ways to get better syntax, short of language integration which we're still hopeful for.
    Wednesday, January 21, 2009 6:41 PM
    Moderator
  • The big advantage of something like Contract.Argument(x).IsNotNull() is that it can throw an appropriate exception type, i.e. ArgumentNullException.  What would really be nice, is to have some way, such as an attribute, to specify that some method or class is a contract specification, much as "if (cond) throw new ArgumentException()" is recognized as a contract specification.  This would allow libraries that simplify contract specifications, such as CuttingEdge.Conditions, to continue to be used.  The chained form used by CuttingEdge.Conditions may be difficult to deal with when doing static checking, but simply allowing a static method signature like the following would be a tremendous help:

    public static MyContracts
    {
       [RequiresAlwaysContract]
       void ShouldNotBeNull(object value, string argumentName)
       {
           if (value == null) throw new ArgumentNullException(argumentName);
       }
    }

    The requirement is that methods marked with RequiresAlwaysContractAttribute must have bodies that would be acceptable contracts, i.e. in the form "if (cond) throw".  Clever libraries could illiminate a lot of repetitive and tedious coding, given just this feature alone.  I suspect, given you already support "if (cond) throw", that a feature like this wouldn't be tough to implement, and I think a lot of devs would love to see this.  Heck, it might even be possible to do this without the attribute, though it could hurt performance at compile time.
    Wednesday, January 21, 2009 8:16 PM
  • Hi guys,

    I know I'm perhaps a bit late on entering the discussion, but I hope we can continue this discussion.

    I'm the developer behind CuttingEdge.Conditions and I'd like to give you my vision on this matter.

    While I feel flattered that Rémy notes CuttingEdge.Conditions as example of what Code Contracts should look like, I actually don't agree with him.

    Conditions has a set of extension methods that are defined with primarily argument validation in mind. From a API perspective it is very hard to define a set of extension methods that please everybody's needs. I believe it's quite dangerous for Code Contracts to go this way, because it's almost impossible to get it right and Microsoft will have to support such an API for many years to come.

    A far more appropriate solution is to get better language integration as Mike already notes. I hope C# 5.0 will use the syntax introduced in Spec#.

    Again, I believe the CuttingEdge.Conditions API is too specific for Code Contracts to use, but that doesn't mean users can only use one framework.

    The reason I created Conditions is because I wanted to lower the barrier for developers to write precondition checks, and with that higher the quality of code written by developers. Code Contracts on the other hand tries to higher that quality by enabling compile time checking. In the future I'd like to see CuttingEdge.Condition use Code Contracts in the background in a way that developers can still use my fluent API and also allow compile time checking (which is currently not possible with Conditions). Doing this without Code Contracts is almost impossible. Achieving this however, can be a tough job, so any help and advise is very welcome.

    Some other comments: BKStrelioff asked if Conditions has any plans to support "OldValue" or "Result". I've looked at this, but decided not to implement support for invariants. While the syntax is 'easy' for Code Contracts, because of it's compiler like behavior; Conditions contains solely library trickery and defining an easy API that is not overly verbose is quite hard. If you think otherwise, please send me an a mail or start a new discussion at the conditions.codeplex.com site. This thread here is of course about Code Contracts API, not about the Conditions API :-). Also checking result is hard without some sort of code weaving. Conditions currently supports result checking by using the “Ensures” extension methods. It works the same way as “Requires” but it throws an “PostconditionException” on failure.

    Also as Wekempf noted, Code Contracts doesn’t throw argument exceptions. In that way it breaks with the Framework Design Guidelines (FDG). CuttingEdge.Conditions tries it's best to obey the FDG. It makes much more sense to throw an ArgumentException when an argument is invalid and it helps while debugging. On the other hand the compile time checking of Code Contracts prevents the throwing of exceptions in the first place, so this might not be that big of a deal.

    I hope this helps keeping the discussion alive.
    Visit my blog: http://www.cuttingedge.it/blogs/steven/
    • Edited by NET Junkie Sunday, July 12, 2009 2:52 PM typo
    Sunday, June 7, 2009 7:39 PM
  • I'm not saying that CuttingEdge.Conditions is an example what Code Contracts should look like. I used it as an example library wich helps me in writing predicates fast and is readable for maintainers. CuttingEdge.Conditions helps me writing faster pre- and post-conditions: Code Contracts doesn't do this. This is one of the reasons I don’t like Code Contracts.

    There are more reasons I don’t like Code Contracts. The problem is that I see two categories of Design By Contract uses:

    1.    Defensive programming (Design By Contract light)
    By always validating input (and output) we can raise the quality of the software and reduce the number of bugs and problems. The software behaves in a predictable manner despite unexpected inputs or user actions. It also makes the code more comprehensible for code audits or maintenance, because the validations and expectations are readable and understandable.

    If input (or output) isn’t correct the software will throw an exception right away. These exceptions should be ArgumentExceptions in most cases, because developers expect. It also obeys the Framework Design Guidelines as noted by Steve. These exceptions also learns developers, how to use the code (we all know that developers don’t read manuals ;-)).

    The most important aspects of Defensive programming are validating arguments and expectations at runtime (soft contracts).

    2.    Design By Contract
    Design By Contract, brings Defensive programming to a new level. It’s a formal description, a hard contract, of how your software should work and this can be guaranteed by the compiler.

    If we take this to the extreme we even can guarantee bug-free software. Unittest should not be needed. Unittest are other way of writing contracts and validating these, because the compiler can’t do it for us. Design by Contracts brings the assertions in unittest into your code and let the compiler do the validation.

    An added benefit of this, is that we can see our contracts in intellisense, which helps developers understanding the API.


    A library as CuttingEdge.Conditions helps me with category 1 (Defensive programming). It helps me in writing pre- and post-conditions in several ways:

    -          Don’t have to write the Exception to be thrown. The library uses best practices and the Framework Design Guidelines for these.

    -          Helps in writing predicates fast, because the most used predicates for the specific type are show in intellisense.

    -          Documents the contract readable and understandable when a developer looks at the code (this can be a matter of taste of course)

    Code Contracts doesn’t help me a lot with 1 (Defensive programming). By default is uses Asserts instead of ArgumentExeptions. To follow the guidelines I have to write extra code to make this explicit. I still need to write the predications myself, so I don’t get a speed increase of using Code Contracts. It helps with the documentation of contracts, but are these the most readable contracts (a matter of taste of course)?

    Then we have the real Design by Contact implementation. Code Contracts aims for this, but I think that it isn’t usable for this. There are several problems that make this not happen:

    -          It isn’t embedded into the syntax of the language, but a library. A library is chosen, because Microsoft wanted this feature available for all languages that use the .NET Framework.  By doing this, it makes the feature less powerful. It is an additional step after compiling, because it needs the MSIL to act upon. It losses the language integration. Spec# was a good direction and I don’t understand why C# isn’t (or is going to be) enriched with this. Why does every language have to have the same features? Make C# a more stricted language and VB.NET a more loose typed language.

    -          It’s is only checked at runtime, which makes it fall into category 1 and it isn’t the best library for category 1 as already explained. Want compile time checking, use a team edition version to get this, which make it less useful (MS Test story happening again).

    -          It’s more a Visual Studio\MSBuild feature. It changes my IDE to enable this feature, which should have been a language feature in the first place.  What if I don’t use Visual Studio? What kind of loops do I need to go to make this working?

    -          I can disable contracts and use code that doesn’t enforce these contracts. It needs an additional file where the contracts are specified, to enforce them? Visual Studio can pick this file up and use it? I don’t looked much into this part, so I could be wrong about this, but why is it separated?

    For me Code Contract is a weak implementation of Design by Contract and I even think it shouldn’t be added to C# 4.

    • Edited by Rémy Friday, July 31, 2009 9:35 AM
    Friday, July 31, 2009 9:30 AM