Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Refactoring with Contracts Shmuel Tyszberowicz School of Computer Science The Academic College of Tel Aviv Yaffo Maayan Goldstein School of Computer.

Similar presentations


Presentation on theme: "1 Refactoring with Contracts Shmuel Tyszberowicz School of Computer Science The Academic College of Tel Aviv Yaffo Maayan Goldstein School of Computer."— Presentation transcript:

1 1 Refactoring with Contracts Shmuel Tyszberowicz School of Computer Science The Academic College of Tel Aviv Yaffo Maayan Goldstein School of Computer Science Tel Aviv University Yishai A. Feldman Efi Arazi School of Computer Science The Interdisciplinary Center Herzliya

2 2 Is Software Development a Pain?? Of course not! It's fun! But the requirements are always changing… Dan Berry (2002): Every development method has a fatal flaw, a pain that developers postpone and avoid In XP, this is refactoring For us, it is unit testing!

3 3 What Seems to be the Problem? Writing all the necessary tests is hard work Unit tests need to change with almost any change in the code: Functionality Refactoring Test data generation needed

4 4 Solution Tests should be responsible for exercising the code The correctness is to be checked by the contract!

5 5 Agenda Introduction Refactoring Examples Crepe Recipe Summary

6 6 Agenda Introduction Refactoring Examples Crepe Recipe Summary

7 7 Design by Contract A practical methodology for evolving code together with its specification Class invariants, method preconditions and postconditions: Precondition binds clients Postcondition obliges suppliers Invariant is a consistency constraint

8 8 Behavioral Subtyping (Liskov) Invariants and postconditions in subclasses May only be strengthened Computed as conjunctions (ANDed) Preconditions in subclasses May only be weakened Computed as disjunctions (ORed)

9 9 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 Crepe == Contract Refactoring Plugin for Eclipse

10 10 Agenda Introduction Refactoring Examples Crepe Recipe Summary

11 11 ReadyQueue (1) size() >= 0 */ public class ReadyQueue { final private List elements = new LinkedList(); public int size() { /*... */ } job != null job.status() == Job.READY elements.get(0) == job size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ }

12 12 ReadyQueue (2) size() > 0 size() == $prev(size()) - 1 */ public void remove() { /*... */ } (size() == 0) == ($ret == null) */ public Job top() { /*... */ } }

13 13 FreeJobs (1) size() >= 0 */ public class FreeJobs { final private List elements = new LinkedList(); public int size() { /*... */ } job != null job.status() == Job.INACTIVE top() == job size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ } READY elements.get(0)= = job

14 14 FreeJobs (2) size() > 0 size() == $prev(size()) - 1 */ public void remove() { /*... */ } size() > 0 $ret != null $ret.status() == Job.INACTIVE */ public Job top() { /*... */ } (size() == 0) == ($ret == null)

15 15 Example: Extract Superclass JobDispenser ReadyQueueFreeJobs ReadyQueue FreeJobs

16 16 Extract Superclass Refactoring (1) size() >= 0 */ public abstract class JobDispenser { protected List elements = new LinkedList(); false size() == 1 + $prev(size()) */ public abstract void insert(Job job); Contradictory preconditions in job.status() == job.status() == Job.INACTIVE

17 17 Extract Superclass Refactoring (2) size() > size() == $prev(size()) */ public abstract void remove(); size() > 0 */ public abstract Job top(); public abstract int size(); } Precondition from FreeJobs, but not from ReadyQueue Common postconditions (Form slightly changed by theorem-prover)

18 18 Changes: ReadyQueue (1) size() >= 0 */ public class ReadyQueue { job != null job.status() == Job.READY elements.get(0) == job size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ }

19 19 Changes: ReadyQueue (2) size() > 0 size() == $prev(size()) - 1 */ public void remove() { /*... */ } public int size() { /*... */ } size() == 0 (size() == 0) == ($ret == null) */ public Job top() { /*... */ } } Crepe reasoning: true size() <= 0 size() == 0 Complement size() > 0 from superclass Simplify with invariant size() >= 0

20 20 Changes: FreeJobs (1) size() >= 0 */ public class FreeJobs { job != null job.status() == Job.INACTIVE top() == job size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ }

21 21 Changes: FreeJobs (2) size() > 0 size() == $prev(size()) - 1 */ public void remove() { /*... */ } size() > 0 $ret != null $ret.status() == Job.INACTIVE */ public Job top() { /*... */ } public int size() { /*... */ } }

22 22 PriorityQueue size() >= 0 */ public class PriorityQueue { job != null job.status() == Job.READY job.priority()< Scheduler.current_priority() size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ } //... }

23 23 Example: Add Inheritance ReadyQueue PriorityQueue ReadyQueue PriorityQueue

24 24 PriorityQueue vs. ReadyQueue size() >= 0 */ public class ReadyQueue { job != null job.status() == Job.READY elements.get(0).equals(job) size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ } } size() >= 0 */ public class PriorityQueue { job != null job.status() == Job.READY job.priority()< Scheduler.current_priority() size() == $prev(size()) + 1 */ public void insert(Job job) { /*... */ } } Extra precondition Extra postcondition

25 25 Add Inheritance Cannot add inheritance relationship between two classes if, in the subclass, it causes Preconditions to be strengthened Invariants or postconditions to be weakened

26 26 Add Inheritance (Crepe)

27 27 Agenda Introduction Refactoring Examples Crepe Recipe Summary

28 28 The Crepe Recipe Use Eclipse ASTParser on assertions Parse the assertions in the Javadoc Convert to predicate form Use theorem prover (Mathematica) to verify relationships between assertions Find contract contradictions Compute the new contract Combine existing assertions to create new ones Compute contracts for arbitrary code (in preparation)

29 29 Combining Assertions Preconditions are conjoined and simplified Postconditions can be disjoined But, sometimes the most precise assertions are not best!

30 30 Extract Superclass - Postconditions class A { x >= 0 x < 10 y >= 0 y < 10 */ void foo(); } class B { x >= 10 x < 20 y >= 10 y < 20 */ void foo(); } A B

31 31 Postconditions Computation A B A B class AB_strongest { * (x >= 0 && x < 10 && * y >= 0 && y < 10) || * (x >= 10 && x < 20 && * y >= 10 && y < 20) */ void foo(); } class AB_alternative { /** x >= 0 x < 20 y >= 0 y < 20 */ void foo(); }

32 32 Postconditions Computation class A extends AB_alternative { x < 10 y < 10 */ void foo(); } class B extends AB_alternative { x >= 10 y >= 10 */ void foo(); } A B

33 33 Agenda Introduction Refactoring Examples Crepe Recipe Summary

34 34 Contracts Refactoring Statistics

35 35 Crepe Limitations Contract computation from arbitrary code Theorem prover (Mathematica): Supports only Booleans, Integers, Doubles, and Reals Fails to simplify some expressions using assumptions Not open source Assertions parsing Return type computations

36 36 Summary Design by Contract is an essential technique for producing high-quality code It is synergistic with Agile practices It helps develop with confidence Automation needed for the process of refactoring with contracts Crepe demonstrates such automating techniques

37 37 Questions?

38 38 Thank you!


Download ppt "1 Refactoring with Contracts Shmuel Tyszberowicz School of Computer Science The Academic College of Tel Aviv Yaffo Maayan Goldstein School of Computer."

Similar presentations


Ads by Google