Download presentation
Presentation is loading. Please wait.
1
Design by Contract Jerry Fitzpatrick
Design by Contract is another best practice that many developers are not aware of.
2
Background Design by Contract (DbC) is a technique for building software DbC was developed by Dr. Bertrand Meyer First described in articles written in1986 Fully described in his book Object Oriented Software Construction, published in 1988 To a large degree, DbC is rooted in earlier work by the computer scientists – Edsgar Dijkstra C.A.R. “Tony” Hoare … and others Developers should refer to Bertrand Meyer’s landmark book “Object Oriented Software Construction”. Meyer carefully studied Hoare and Dijkstra’s work, particularly with regard to provably correct software. I was fortunate to be taught Design by Contract by Dr. Meyer personally. This short presentation cannot fully explain the benefits of Design by Contract, nor how to implement it correctly. Instead, Dr. Meyer is also the creator of the Eiffel programming language. Eiffel is perhaps the only language that has DbC constructs built into it. Copyright 2009 Software Renovation Corporation. All rights reserved.
3
Benefits Although the use of DbC is still not widespread, its benefits are hard to ignore It’s a very sensible and convincing approach to software development that leads to – Smaller code size Less complexity Increased reliability Simpler debugging Higher productivity Copyright 2009 Software Renovation Corporation. All rights reserved.
4
The Contract Metaphor DbC can be explained in terms of real-world contracts in which each party has obligations and benefits The various functional parts of a software system interact with one another From the perspective of a contract, we can say that – Each module provides one or more services (benefits) Other modules use services, but must use them properly (obligations) Often called a producer/consumer or client/server relationship Copyright 2009 Software Renovation Corporation. All rights reserved.
5
Benefits and Obligations
A provider offers specific benefits given stated conditions A consumer agrees to meet those conditions in order to use the provider’s services This formal agreement is important because it – Documents the responsibilities of providers and consumers Eliminates redundant error checking and error handling Makes code easier to understand and more reliable Bjarne Stroustrup mentioned the importance of an “articulated” error handling strategy with respect to Clean Code. Copyright 2009 Software Renovation Corporation. All rights reserved.
6
Contract Conditions DbC defines three basic contract conditions –
Preconditions Postconditions Class invariants These conditions are implemented as code inside of functions, methods or properties Generically called “routines” Copyright 2009 Software Renovation Corporation. All rights reserved.
7
Preconditions A precondition is a constraint that a routine requires in order to work correctly The constraint applies to any use of the routine Examples – Input value to a square root routine must not be negative A ‘Remove’ routine must not be called on an empty stack The consumer (client) – not the routine (provider) – is responsible for meeting all of the preconditions A routine has no obligations if any precondition is violated An important point which some developers have trouble accepting The importance of the fourth point (the routine’s obligations) cannot be over-emphasized. A developer who cannot accept this premise will usually make the code messy with redundant “error checking” and “error handling” code to make the routine “bullet-proof”. This is simply an attempt to overcome the fact that the consumer/client has not fulfilled their part of the contract. Instead of being helpful, this style of coding increases code size and complexity and muddies the responsibilities of the consumer and provider. Copyright 2009 Software Renovation Corporation. All rights reserved.
8
Postconditions A postcondition is a constraint on the results produced by a routine The routine itself must fulfill the obligations defined by its postconditions Examples – The value computed by a square root routine must be non-negative After executing a list ‘Add’ method, the list must not be empty Copyright 2009 Software Renovation Corporation. All rights reserved.
9
Class Invariants A class invariant is a constraint on object state that must be preserved by each of its methods Ensures the overall integrity or consistency of an object Example – In a list object, there is a connection between the Empty state and the list’s element count – Empty can only be true when the element count is zero Copyright 2009 Software Renovation Corporation. All rights reserved.
10
Rules for Inheritance Subclasses may weaken, but not strengthen preconditions Subclasses may strengthen, but not weaken postconditions or class invariants These rules complement the Liskov Substitution Principle Basically, they help ensure that substitution is possible Copyright 2009 Software Renovation Corporation. All rights reserved.
11
Implementing Contracts
DbC is built into the Eiffel programming language DbC concepts can be simulated in other languages to some extent Example: In C++, a ‘const’ method cannot modify the state of its object This is an implicit class invariant condition The simulation in other languages is generally less complete and less sophisticated than in Eiffel. Copyright 2009 Software Renovation Corporation. All rights reserved.
12
Assertions In many languages, “assertions” can be used to implement DbC constraints _ASSERT() macro in native C++ Debug.Assert() in C# Assertions do not implement all DbC features Copyright 2009 Software Renovation Corporation. All rights reserved.
13
Assertion Violations An assertion violation always means that there is a bug in the software Though the assertion may contain the bug if implemented incorrectly A precondition violation means that there is a bug in the consumer (client) A postcondition violation means that there is a bug in the producer (service) Copyright 2009 Software Renovation Corporation. All rights reserved.
14
Postcondition Example
Contract: The SquareRoot() method guarantees that the returned value is always non-negative double SquareRoot(double x) { double root = 0.0; … calculation … Debug.Assert(root >= 0.0) return root; } An explanation of what Debug.Assert() does might be helpful to people who aren’t familiar with it. Copyright 2009 Software Renovation Corporation. All rights reserved.
15
Precondition Example Contract: The SquareRoot method will return the square root of x only if x is non-negative. The SquareRoot method can do anything (or nothing) if parameter x is negative Remember, a routine has no obligations when any of its preconditions is violated double SquareRoot(double x) { Debug.Assert(x >= 0.0) … } Copyright 2009 Software Renovation Corporation. All rights reserved.
16
Precondition Notes Preconditions are especially valuable in –
Public constructors Public ‘setter’ methods or properties But also helpful in private methods and properties Assertions should be used thoughtfully Not just placed everywhere or randomly There is a tendency for DbC novices to litter the code with unnecessary assertions. This is “too much of a good thing”. Copyright 2009 Software Renovation Corporation. All rights reserved.
17
Important Point to Ponder
Contract constraints only apply to code within the boundaries of your program Interactions at the boundaries require other techniques (e.g. exceptions) This is not the same thing as boundaries between developers For example, DbC is not used to – Validate inputs from a user or external system Report run-time errors to a user or external system It’s very important that all developers on a project use the same error detection and handling strategy. Otherwise you end up with a confusing mix of strategies that don’t work well together. Copyright 2009 Software Renovation Corporation. All rights reserved.
18
Question The SquareRoot() method precondition states that its input must be non-negative It is the consumer’s obligation to ensure this How can they do that using the SquareRoot() routine? Copyright 2009 Software Renovation Corporation. All rights reserved.
19
Possible Answers The answer depends upon how the input value is obtained – If the value is input from a user, the consumer code should validate the input, report errors, and perhaps retry on error Better yet, consumer code can usually prevent users from entering a negative input In any case, the consumer should not call the SquareRoot() routine until this precondition is met How can negative input values be prevented in the UI? Use a different type of control (e.g. slider, numeric up-down, combo box). Use a text box that has pattern-matching capabilities. Handle the KeyUp or KeyPress event and ignore minus signs (and probably various other characters as well). Copyright 2009 Software Renovation Corporation. All rights reserved.
20
Assertions Versus Exceptions
Programming language exceptions were originally intended to report/handle “exceptional” errors Problems outside the control of an application such as memory exhaustion or I/O device errors Not bugs in the application itself For better or worse, some libraries and applications now use exceptions to report their own errors That is, bugs in the libraries or applications As a rule, DbC contracts should be independent of exception mechanism That is, contracts should not throw or catch exceptions Copyright 2009 Software Renovation Corporation. All rights reserved.
21
Bad Example #1 No! This is not a DbC precondition.
StatusCode GetSlime(Slime slime) { if (slime == null) return STATUS_NULL_POINTER; } … implementation … Why not? Copyright 2009 Software Renovation Corporation. All rights reserved.
22
Bad Example #2 No! This is not a DbC precondition either.
void GetSlime(Slime slime) { if (slime == null) throw new Exception(“invalid slime parameter”); } … implementation … Why not? Copyright 2009 Software Renovation Corporation. All rights reserved.
23
Good Example Yes! Here is a DbC precondition.
void GetSlime(Slime slime) { Debug.Assert(slime != null); … implementation … } Copyright 2009 Software Renovation Corporation. All rights reserved.
24
Design by Contract is NOT…
A development process or methodology Though it is a valuable technique Unit or regression testing Though automated testing is a useful DbC supplement Defensive programming Design by Contract is the opposite of defensive programming In his book, Dr. Meyer clearly explains the many disadvantages of defensive programming Copyright 2009 Software Renovation Corporation. All rights reserved.
25
References “Object Oriented Software Construction”, Bertrand Meyer, Prentice Hall “Design by contract”, Wikipedia, “A Conversation with Bertrand Meyer, Parts I, II, & III”, Copyright 2009 Software Renovation Corporation. All rights reserved.
26
Q&A Copyright 2009 Software Renovation Corporation. All rights reserved.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.