180 likes | 205 Views
Extreme Design by Contract. Yishai A. Feldman Efi Arazi School of Computer Science The Interdisciplinary Center Herzliya, Israel http://www.idc.ac.il/yishai. Is Software Development a Pain??. Of course not! It's fun! But when requirements change in the middle …
E N D
Extreme Design by Contract Yishai A. Feldman Efi Arazi School of Computer Science The Interdisciplinary Center Herzliya, Israel http://www.idc.ac.il/yishai
Is Software Development a Pain?? • Of course not! It's fun! • But when requirements change in the middle… • Dan Berry (2002): Every development method has a fatal flaw, a pain that developers postpone and avoid. • In XP, this is refactoring. • For me, it is unit testing!
Why are Unit Tests Painful? • Unit tests need to change with almost any change in the code. • Need a program to generate test data? • The solution: tests should be responsible for exercising the code, not for checking correctness. • How is correctness to be checked? • By the contract!
Design by Contract • A practical methodology for evolving code together with its specification. • Class invariants, method preconditions and postconditions. • Has important methodological implications on inheritance: • Invariants and postconditions may only be strengthened; • Preconditions may only be weakened.
Tool Support forDesign by Contract • Selectively instrument program with assertion checks. • Built-in support in Eiffel. • External DbC tools for Java: iContract, Jcontract, JMSAssert, …
Extreme Design by Contract • Correctness checked by contract. • Of course, contract may need to change when code changes… • But contract expresses intent of code! • Contracts can be refactored systematically. • Contract refactoring can be partially automated.
Example: RPN Calculator Class /** @inv size() >= 0 * @inv elements != null */ public class RPNCalc { final protected Vector elements = new Vector(); /** @post size() == 0 */ public RPNCalc() {} /** @pre size() >= 1 */ public int display() { return ((Integer)elements.lastElement()).intValue(); }
Example: RPN Calculator Class /** @pre size() >= 2 */ public int second() { return ((Integer)elements.elementAt (elements.size() - 2)).intValue(); } /** @post size() == $prev(size()) + 1 * @post display() == n * @post size() <= 1 || second() == $prev(display()) */ public void enter(int n) { elements.addElement(new Integer(n)); }
Example: RPN Calculator Class /** @pre size() >= 2 * @post size() == $prev(size()) - 1 * @post display() == $prev(second()) + $prev(display()) */ public void add() { int size = elements.size(); elements.setElementAt (new Integer(second() + display()), size-2); elements.setSize(size-1); }
Example: TestRPNCalc Class public void test1() { RPNCalc c = new RPNCalc(); for (int i = 1; i <= n; i++) c.enter(i); while (c.size() > 1) c.add(); assertEquals(n*(n+1)/2, c.display()); for (int i = 1; i < n; i++) { c.enter(i); c.sub(); } assertEquals(n, c.display()); assertEquals(1, c.size()); }
Refactoring (and Development) with Contracts • First, change the contract to reflect new design • In most cases, no need to change the tests! • Then refactor the code according to the new contract • Test
New Contract-Related Refactorings • Pull Up Contract • Push Down Contract • Create Abstract Precondition • Simplify Assertion
Refactoring with Contracts: Automation • Contracts may affect the applicability and mechanics of refactorings • Contracts are composed of boolean expressions; some refactorings treat contracts as code: • Rename Method; Inline Method; … • Some refactorings introduce obvious assertions: • Introduce Null Object; Self Encapsulate Field; …
Refactoring with Contracts: Automation • Some refactorings move or transform contracts in simple ways: • Push Down Method; Replace Constructor with Factory Method; … • The applicability of some refactorings may depend on the contract: • Move Method; Extract Superclass; …
Refactoring with Contracts: Automation • Some refactorings may require completely new contracts: • Extract Method; Pull Up Constructor Body; …
Conclusions • Design by Contract is an essential technique for producing high-quality code. • Is synergistic with XP practices. • Expresses intent of classes and methods. • Helps develop and refactor with confidence. • Simplifies maintenance of tests. • Can be automated to some extent.