Does Design By Contract Work For You? [closed]
Asked Answered
S

10

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.

Shanell answered 25/8, 2008 at 17:26 Comment(1)
This question is perfectly suited for programmers.stackexchange.com. See programmers.stackexchange.com/q/128717/1282Prostatectomy
B
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.

Burtis answered 25/8, 2008 at 17:41 Comment(3)
Any recommendations of open-source software that does this for C#/.NET?Ehrlich
I fail to see how this example test case is supposed to test the "and only if" part of the "iif".Mudguard
@NiklasB: since no other tests are performed, 0 is the only possible input ;) ;)Cogon
C
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.

Coralloid answered 23/9, 2008 at 20:32 Comment(0)
A
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.

Afrit answered 25/8, 2008 at 21:36 Comment(4)
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.Jardiniere
+1 I don't think debug assertions are contracts.Cerulean
"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.Rift
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#][research.microsoft.com/en-us/projects/specsharp/] and [cofjoa][code.google.com/p/cofoja/]Cockcroft
B
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.

Burtis answered 29/8, 2008 at 17:30 Comment(1)
" 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.Terce
B
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.

Bollix answered 25/8, 2008 at 17:42 Comment(3)
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.Contingency
"when doing anything in an SOA realm" != "always", but loosely coupled > tightly coupled. Always.Bollix
@GregHurlman I hate it when people talk like thatHeretical
K
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.

Kit answered 25/8, 2008 at 18:10 Comment(1)
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.Jardiniere
B
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.

Bespectacled answered 6/10, 2009 at 16:29 Comment(0)
N
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.

Nudity answered 16/11, 2010 at 4:30 Comment(1)
Hi @necode, we wrote github.com/Parquery/gocontracts to introduce design-by-contract to Go. It worked well so far on a largish code base.Hhd
L
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.

Lorna answered 25/8, 2008 at 21:4 Comment(1)
Unfortunately it has not been incorporated into the D standard libraries which makes the whole DbC almost useless in practice.Worl
N
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.

Neocene answered 28/1, 2010 at 22:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.