Slashdot Mirror


Why Is "Design by Contract" Not More Popular?

Coryoth writes "Design by Contract, writing pre- and post-conditions on functions, seemed like straightforward common sense to me. Such conditions, in the form of executable code, not only provide more exacting API documentation, but also provide a test harness. Having easy to write unit tests, that are automatically integrated into the inheritance hierarchy in OO languages, 'just made sense'. However, despite being available (to varying degrees of completeness) for many languages other than Eiffel, including Java, C++, Perl, Python, Ruby, Ada, and even Haskell and Ocaml, the concept has never gained significant traction, particularly in comparison to unit testing frameworks (which DbC complements nicely), and hype like 'Extreme Programming'. So why did Design by Contract fail to take off?"

8 of 178 comments (clear)

  1. Comment removed by account_deleted · · Score: 4, Insightful

    Comment removed based on user account deletion

  2. no bang for your buck by majiCk · · Score: 3, Insightful

    Design by contract seems like a lot of extra work and runtime cost for something that might once in a while catch a bug in already-deployed code. Lighter weight methods like static typing catch (certain kinds of) errors before the code is even compiled; unit testing is usually done before code is deployed, and with the express aim of exposing incorrect behavior in corner cases.

    Just what niche is design-by-contract supposed to fill? It's heavyweight, costly at runtime, undirected, and likely to catch bugs only after deployment -- too-little-too-late. Maybe it's unpopular because it's a poor tradeoff.

    1. Re:no bang for your buck by barrkel · · Score: 4, Insightful

      In a phrase, the niche is professional coders, rather than hack-a-day cowboys.

      Assertions, whether invariants, preconditions or postconditions, can be viewed as extensions to the type system [1]. Since they are expressions of a boolean type and don't modify state (at least, no sane ones would mutate state), they're very easily analysed.

      Combine that with a runtime like .NET or the JVM. Compilers and analysers can use such contracts to perform extra typechecking of e.g. arguments to methods, where the methods have preconditions. "Runtime cost" doesn't exist if the runtime has support, especially where verification also exists. Consider the old conundrum: do you check your parameters, or do you expect your caller to check the arguments before they're passed? What if the parameters being wrong leads to a subtle error that manifests later rather than a dramatic failure? With properly stated contracts, these checks can be inserted at the lowest level and automatically propagated higher statically by the compiler or dynamically by the runtime as necessary.

      The niche that DbC is supposed to fill is formalising what is already recognised good practice - stating your assumptions while writing your code. If you have much experience as a programmer, you'll know that it's useful to use assert, ASSERT, or some other feature of your environment at choice places where you make certain assumptions that you think can't be broken. And if you've read The Pragmatic Programmer, you'll know why you'll want to leave those assertions in the final release.

      Most popular languages, such as C#, Java, C++ etc., capture very little programmer intent in their type systems. There's a lot more potential there - preconditions and postconditions can e.g. state that a variable will be in a certain range dependent on the values of other variables, and then automatically detect range mismatches with e.g. loop invariants. Basically, assertions are really useful extensions to the type system.

      [1] For example, consider that a 'requires x != null' constraint and a notional non-nullable reference type from C# or Java, analogous to 'MyType!' in C-w (C Omega):
      http://blogs.msdn.com/cyrusn/archive/2004/06/03/14 7778.aspx

    2. Re:no bang for your buck by Coryoth · · Score: 3, Insightful

      Design by contract seems like a lot of extra work and runtime cost for something that might once in a while catch a bug in already-deployed code. Lighter weight methods like static typing catch (certain kinds of) errors before the code is even compiled; unit testing is usually done before code is deployed, and with the express aim of exposing incorrect behavior in corner cases. DbC doesn't incur any runtime cost if you choose not to bother - any good contract system allows you to turn off contract checking for production code. That is, DbC provides a test harness during testing but needn't do any checking of finished code after testing is complete. Moreover good contract systems like JML and Spec# are smart enough to allow static checking which allow you to catch a whole host of errors before compilation that static types just aren't going to be able to catch. And I have to admit that I am unsure how DbC is "a lot of work" given that you should be writing unit tests anyway, and if you have constraints or invariants then you ought to be checking those with unit tests - writing the constraint as a contract is less work than writing the equivalent unit test. Finally DbC enables testing that for which unit tests of corner cases simply can't compare - by using the contracts as a test oracle you can do automated randomised testing of several integrated units. That is to say, you can automatically generate data to search the input space delimited by preconditions, and use postconditions, invariants, and preconditions of any called code, to test that several units all work together correctly and potentially catch weird interelated corner cases that you hadn't anticipated. Honestly, check out AutoTest or Quickcheck sometime, they are suprisingly powerful and have found bugs in established production code that had already undergone extensive standard testing.
  3. Re:Management by ShieldW0lf · · Score: 3, Insightful

    A good business analyst will answer the question "What is it that we (the client) need." They help make sure that the excellent code you write, when it's doing as you were hired to write it to do, solves problems instead of making them.

    A good architect will help establish clear separation of authority, giving team members more autonomy to go do what they're good at without having other peoples fingers in their pies or needing to leave their area of scope.

    There are a lot of people with pieces of paper from a school that are terrible at these things, and they muddle along leaving wreckage behind them. But that doesn't dismiss the value of having someone competent in those roles when you can find them.

    --
    -1 Uncomfortable Truth
  4. Re:Who cares? by Just+Some+Guy · · Score: 4, Insightful

    Who cares if it's popular? If it solves your problem, use it.

    Two reasons: first, the more people use it, the wider it will be supported. It's nice to be involved with something on the upswing that more people are interested in than bored with. Second, it's nice to know why something's unpopular. Maybe it's hard to use, but you're a genius and will be able to put it to work. Or, maybe, everyone else realized that it's awful and moved on to something less heinous.

    --
    Dewey, what part of this looks like authorities should be involved?
  5. Too many layers by Geoffreyerffoeg · · Score: 3, Insightful

    You know the aphorism about how any CS problem can be solved by another layer of indirection -- except the problem of too many layers of indirection. That's what design-by-contract is. Instead of having the intrinsic type-safety checks and the social trust that the code author has run unit tests if necessary and makes the code do something reasonable, design-by-contract formalizes all this and makes you specify conditions on the code manually. That's quite a bit of effort for relatively little advantage. The popular design-by-informal-agreement works almost as well and doesn't have the extra, unneeded layer of indirection.

  6. been doing that for years already by imbaczek · · Score: 5, Insightful

    assert(condition) is your friend. It's not called a contract, it's not design (but a very good practice!) and it does the job well.