views:

908

answers:

6

You may think this question is like this question asked on StackOverflow earlier. But I am trying to look at things differently.

In TDD we write tests that include different conditions, criteria, verification code. If a class passes all these tests we are good to go. It is a way of making sure that the class actually does what its supposed to do and nothing else.

If you follow Bertrand Meyers' book Object Oriented Software Construction word by word, the class itself has internal and external contracts so that it only does what its supposed to do and nothing else, No external tests required because the to code to ensure contract is followed is the part of the class.

Quick example to make things clear-

TDD-

  1. Create test to ensure that in all cases a value ranges from (0-100)
  2. Create class containing method that passes the test.

DBC-

  1. Create a class, create a contract for that member var to range from (0-100), set contract for contract breach, define method.

I personally like DBC.


Is there a reason why pure DBC is not so popular?? Is it the languages or tools or being Agile or is it just me who likes to have code responsible for itself?

If you think I am not thinking right, I would be more than willing to learn.

A: 

I see no reason why both cannot co-exist. It is wonderful to look at a method and know at a glance exactly what the contract is. It is also wonderful to know that I can run my unit tests and know that nothing was broken with my last change. The two techniques are not mutually exclusive. Why design by contract is not more popular is a mystery.

Jim Petkus
+2  A: 

In my mind TDD is more "inductive". You start with examples (test cases) and your code embodies the general solution to those examples.

DBC seems more "deductive", after gathering requirements you determine object behavior and contracts. You then code the specific implementation of those contracts.

Writing contracts is somewhat difficult, more so than tests that are concrete examples of behavior, this may be part of the reason TDD is more popular than DBC.

Ryan
+11  A: 

The main problem with DBC is that in the vast majority of cases, either the contract cannot be formally specified (at least not conveniently), or it cannot be checked with current static analysis tool. Until we get past this point for mainstream languages (not Eiffel), DBC will not give the kind of assurance that people need.

In TDD, tests are written by a human being based on the current natural-text specifications of the method that are (hopefully) well-documented. Thus, a human interprets correctness by writing the test and gets some assurance based on that interpretation.

If you read Sun's guide for writing JavaDocs, it says that the documentation should essentially lay out a contract sufficient to write a test plan. Hence, design by contract is not necessarily mutually exclusive with TDD.

Uri
I never mentioned Eiffel in my question thinking, people might think of me as some guy who liked one weird language and is trying to prove a point. +1 to you
Perpetualcoder
Eiffel has a lot of interesting ideas, it's just not ready for mainstream use. A bunch of my friends are working on DBC formalisms for Java that are pretty cool. I've been working on improved documentation by formalizing "directives"
Uri
Sounds extremely interesting ! Eiffel people believe they do OO right and they are pretty stubborn about it :)
Perpetualcoder
True OO is Smalltalk ;)
Uri
@Uri, it's not that Eiffel is not ready for mainstream use, it's that the mainstream use is not ready for Eiffel :) But jokes aside, this language has a number (though, admittedly, one which I do not know :) of commercial applications.
Daniel Daranas
I have HEARD companies secretly using it...from Eiffel people :P
Perpetualcoder
It's been 8 years since I last coded in Eiffel... At the time, at least, the standard library failed to impress me, but that might be changed now. I'm sure it is used in some places.
Uri
Static analysis for contract specifics doesn't work for Eiffel either,it only has nominative typechecking, a really nice implementation, but not contract specific.
Ryan
+5  A: 

Meyer's book doesn't say that "you never make mistakes" :)

Actually if you look at the next chapter, When the contract is broken, it discusses what happens when a function fails to accomplish what its contract states.

So, the simple fact that you use the DbC technique doesn't make your code correct. It's helpful, but you can always mess things up.

TDD will check, from the outside world, black box style, that the public interface of your class behaves correctly.

So DbC and TDD are not mutually exclusive at all.

Daniel Daranas
+1 to you! I know I will make mistakes!
Perpetualcoder
+4  A: 

I think it is best to use both methods in conjunction rather than just one or the other.

It has always seemed to me that fully enforcing a contract within the class and its methods themselves can be impractical.

For example, if a function says it will hash a string by some method and return the hashed string as output, how does the function enforce that the string was hashed correctly? Hash it again and see if they match? Seems silly. Reverse the hash to see if you get the original? Not possible. Rather, you need a set of test cases to ensure that the function behaves correctly.

On the other hand, if your particular implementation requires that your input data be of a certain size, then establishing a contract and enforcing it in your code seems like the best approach.

zdan
+7  A: 

TDD and DbC are two different strategies. DbC permits fail-fast at runtime while TDD act "at compile time" (to be exact it add a new step right after the compilation to run the unit tests).

That's a big advantage of TDD over DbC : it allows to get earlier feedback. When you write code the TDD way, you get the code and its unit-tests at the same time, you can verify it "works" according to what you thought it should, which you encoded in the test. With DbC, you get code with embedded tests, but you still have to exercise it. IMO,this certainly is one reason that Dbc is not so popular.

Other advantages : TDD creates an automatic test suite that allow detecting (read preventing) regressions and make Refactoring safe, so that you can grow your design incrementally. DbC does not offer this possibility.

Now, using DbC to fail-fast can be very helpful, especially when your code interfaced other components or has to rely on external sources, in which case testing the contract can save you hours.

philippe