26

Do you use Design by Contract professionally? Is it something you have to do from the beginning of a project, or can you change gears and start to incorporate it into your software development lifecycle? What have you found to be the pros/cons of the design approach?

I came across the Design by Contract approach in a grad school course. In the academic setting, it seemed to be a pretty useful technique. But I don't currently use Design by Contract professionally, and I don't know any other developers that are using it. It would be good to hear about its actual usage from the SO crowd.

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116

10 Answers10

16

I can't recommend it highly enough. It's particularly nice if you have a suite that takes inline documentation contract specifications, like so:

// @returns null iff x = 0
public foo(int x) {
  ...
}

and turns them into generated unit tests, like so:

public test_foo_returns_null_iff_x_equals_0() {
  assertNull foo(0);
}

That way, you can actually see the tests you're running, but they're auto-generated. Generated tests shouldn't be checked into source control, by the way.

James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
15

You really get to appreciate design by contract when you have an interface between to applications that have to talk to each other.

Without contracts this situation quickly becomes a game of blame tennis. The teams keep knocking accusations back and forth and huge amounts of time get wasted.

With a contract, the blame is clear.

Did the caller satisfy the preconditions? If not the client team need to fix it.

Given a valid request, did the receiver satisfy the post conditions? If not the server team need to fix that.

Did both parties adhere to the contract, but the result is unsatisfactory? The contract is insufficient and the issue needs to be escalated.

For this you don't need to have the contracts implemented in the form of assertions, you just need to make sure they are documented and agreed on by all parties.

Ged Byrne
  • 801
  • 6
  • 10
3

If you look into STL, boost, MFC, ATL and many open source projects, you can see there are so many ASSERTION statements and that makes project going further more safely.

Design-By-Contract! It really works in real product.

popopome
  • 12,250
  • 15
  • 44
  • 36
  • 3
    The STL probably isn’t the best example of design by contract. Basically, the STL policy is that “if the user did something wrong, all guarantees are voided, feel free to wreck the system.” The assertions you mentioned are only triggered in debug mode. Error handling in optimized C++ code is notoriously fickle. – Konrad Rudolph Oct 06 '09 at 16:45
  • 1
    +1 I don't think debug assertions are contracts. – rpattabi Aug 10 '10 at 07:34
  • 2
    "the user did something wrong, all guarantees are voided, feel free to wreck the system" that *is* the DbC approach: failure to meet a precondition results in undefined behaviour. – Raedwald Sep 14 '11 at 12:13
  • Assertions are not contracts. The fact that assertions can be turned off when released for production means that a lot of subtle errors that programmers for some reason believe they can use assert to manage often become security holes. Far better examples of contracts are [Spec#][http://research.microsoft.com/en-us/projects/specsharp/] and [cofjoa][http://code.google.com/p/cofoja/] – Visionary Software Solutions Apr 11 '12 at 06:15
3

Frank Krueger writes:

Gaius: A Null Pointer exception gets thrown for you automatically by the runtime, there is no benefit to testing that stuff in the function prologue.

I have two responses to this:

  1. Null was just an example. For square(x), I'd want to test that the square root of the result is (approximately) the value of the parameter. For setters, I'd want to test that the value actually changed. For atomic operations, I'd want to check that all component operations succeeded or all failed (really one test for success and n tests for failure). For factory methods in weakly-typed languages, I want to check that the right kind of object is returned. The list goes on and on. Basically, anything that can be tested in one line of code is a very good candidate for a code contract in a prologue comment.

  2. I disagree that you shouldn't test things because they generate runtime exceptions. If anything, you should test things that might generate runtime exceptions. I like runtime exceptions because they make the system fail fast, which helps debugging. But the null in the example was a result value for some possible input. There's an argument to be made for never returning null, but if you're going to, you should test it.

Community
  • 1
  • 1
James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
  • " If anything, you should test things that might generate runtime exceptions." - In particular, at the exact point where a runtime exception becomes inevitable, a violation of the assertion should at least be logged. The problem with Gaius is that the runtime failure happens at some random instance of the assumption violation, rather than at the exact point where the assumption was first violated. If calling f(x) results in a crash when x==NULL, then log/fail on this issue must happen at the call to f(x) - rather than deep inside at some random location. – Rob Jan 07 '15 at 21:29
2

It's absolutely foolish to not design by contract when doing anything in an SOA realm, and it's always helpful if you're working on any sort of modular work, where bits & pieces might be swapped out later on, especially if any black boxen are involved.

Greg Hurlman
  • 17,666
  • 6
  • 54
  • 86
  • This answer isn't very good. SOA, modularwork, etc. are basic programming skills so what you're saying is that Design By Contract is applicable and useful in *all programming situations. –  Dec 18 '10 at 21:21
  • "when doing anything in an SOA realm" != "always", but loosely coupled > tightly coupled. Always. – Greg Hurlman Dec 23 '10 at 17:47
  • 1
    @GregHurlman I hate it when people talk like that – Pacerier Nov 05 '11 at 14:56
1

Both Unit testing and Design by Contract are valuable test approaches in my experince.

I have tried using Design by Contract in a System Automatic Testing framework and my experience is that is gives a flexibility and possibilities not easily obtained by unit testing. For example its possible to run longer sequence and verify that the respons times are within limits every time an action is executed.

Looking at the presentations at InfoQ it appears that Design by contract is a valuable addition to the conventional Unit tests in the integration phase of components. For example it possible to create a mock interface first and then use the component after- or when a new version of a component is released.

I have not found a toolkit covering all my design requirement to design by contract testing in the .Net/Microsoft platform.

1

In lieu of more expressive type systems, I would absolutely use design by contract on military grade projects.

For weakly typed languages or languages with dynamic scope (PHP, JavaScript), functional contracts are also very handy.

For everything else, I would toss it aside an rely upon beta testers and unit tests.

Gaius: A Null Pointer exception gets thrown for you automatically by the runtime, there is no benefit to testing that stuff in the function prologue. If you are more interested in documentation, then I would use annotations that can be used with static analyzers and the like (to make sure the code isn't breaking your annotations for example).

A stronger type system coupled with Design by Contract seems to be the way to go. Take a look at Spec# for an example:

The Spec# programming language. Spec# is an extension of the object-oriented language C#. It extends the type system to include non-null types and checked exceptions. It provides method contracts in the form of pre- and postconditions as well as object invariants.

Community
  • 1
  • 1
Frank Krueger
  • 69,552
  • 46
  • 163
  • 208
  • 2
    Can you justify your first sentence (particularly “in lieu of”)? It certainly seems controversial enough, what with the US military taking the exact opposite route (which brought us Ada …). Your last sentence also seems to contradict it. I also want to point out that expressive type systems can be harnessed perfectly to *provide* contracts, through static type checking. – Konrad Rudolph Oct 06 '09 at 16:43
1

I find it telling that Go programming language has no constructs that make design by contract possible. panic/defer/recover aren't exactly that as defer and recover logic make it possible to ignore panic, IOW to ignore broken contract. What's needed at very least is some form of unrecoverable panic, which is assert really. Or, at best, direct language support of design by contract constructs (pre and post-conditions, implementation and class invariants). But given strong-headedness of language purists at the helm of Go ship, I give little change of any of this done.

One can implement assert-like behaviour by checking for special assert error in last defer function in panicking function and calling runtime.Breakpoint() to dump stack during recovery. To be assert-like that behaviour needs to be conditional. Of course this approach fells apart when new defer function is added after the one doing assert. Which will happen in large project exactly at the wrong time, resulting in missed bugs.

My point is that is that assert is useful in so many ways that having to dance around it may be a headache.

necode
  • 41
  • 4
  • Hi @necode, we wrote https://github.com/Parquery/gocontracts to introduce design-by-contract to Go. It worked well so far on a largish code base. – marko.ristin Jun 11 '19 at 20:33
0

Yes, it does! Actually a few years ago, I designed a little framework for Argument Validation. I was doing a SOA project, in which the different back-end system, did all kind of validation and checking. But to increase response times (in cases where the input was invalid, and to reduce to load those back-end systems), we started to validate the input parameters of the provided services. Not only for Not Null, but also for String patterns. Or values from within sets. And also the cases where parameters had dependencies between them.

Now I realize we implemented at that time a small design by contract framework :)

Here is the link for those who are interested in the small Java Argument Validation framework. Which is implemented as plain Java solution.

Verhagen
  • 3,885
  • 26
  • 36
0

I don't actually use Design by Contract, on a daily basis. I do, however know that it has been incorporated into the D language, as part of the language.

Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
  • 1
    Unfortunately it has not been incorporated into the D standard libraries which makes the whole DbC almost useless in practice. – Lothar Sep 23 '10 at 21:55