220 likes | 485 Vues
John R Clawson CSCI 620: Software Architecture and Design C. Garrison November 14, 2006. Programming by Contract. Introduction.
E N D
John R Clawson CSCI 620: Software Architecture and Design C. Garrison November 14, 2006 Programming by Contract
Introduction • Programming by contract according to Eiffel.com is “a systematic approach to specifying and implementing object-oriented software elements and their relations in a software system.” • Interactive Software Engineering, Incorporated first developed the idea of programming by contract by developing an object-oriented language to facilitate the desired goals of programming by contract. • Design by ContractTM • Programming by contract is an approach that brings the project specifications down to the actual coding stage.
Introduction (Continued) • According to Wikipedia.org programming by contract asks and answers three basic questions: • What is expected? • What is guaranteed? • What is maintained?
Programming by Contract Terminology • Description – Describes what the module actually does. • Example: Divide two numbers and return the value. • Exception(s) – Indicates which, if any, exceptions are going to be thrown. • Examples: DivideByZero • Name – The name of the module. • Parameter(s) – Name and type of data that is being passed in, if any. • Example: newDivi, an Integer • Precondition – States assumptions of all data that is used in the module. • Example: newDivi > 0 • Postcondition – States assumptions of all data once the module has completed. • Return Type – Data type of the value being returned, if any.
/************************************************* *Name: divideTwo() * *Desc: Divides two integers and returns the result * *Parameters: numer, an Integer; divi, an Integer * *Precondition: numer and divi are both integers * and divi does not equal zero. * *Postcondition: The result of dividing numer by * divi is returned. * *Return Type: result, an Integer * *Exception: DivideByZero if divi is zero. *************************************************/ int divideTwo(int numer, int divi){ int result = 0; if(divi != 0){ result = numer / divi; }else{ result = -1; } return result; }//end of divideTwo()
/************************************************* *Name: divideTwo() * *Desc: Divides two integers and returns the result * *Parameters: numer, an Integer; divi, an Integer * *Precondition: numer and divi are both integers * and divi does not equal zero. * *Postcondition: The result of dividing numer by * divi is returned. * *Return Type: result, an Integer * *Exception: DivideByZero if divi is zero. *************************************************/ int divideTwo(int numer, int divi){ int result = 0; if(divi != 0){ result = numer / divi; }else{ result = -1; } return result; }//end of divideTwo()
/************************************************* *Name: divideTwo() * *Desc: Divides two integers and returns the result * *Parameters: numer, an Integer; divi, an Integer * *Precondition: numer and divi are both integers * and divi does not equal zero. * *Postcondition: The result of dividing numer by * divi is returned. * *Return Type: result, an Integer * *Exception: DivideByZero if divi is zero. *************************************************/ int divideTwo(int numer, int divi){ int result = 0; if(divi != 0){ result = numer / divi; }else{ result = -1; } return result; }//end of divideTwo()
/************************************************* *Name: divideTwo() * *Desc: Divides two integers and returns the result * *Parameters: numer, an Integer; divi, an Integer * *Precondition: numer and divi are both integers * and divi does not equal zero. * *Postcondition: The result of dividing numer by * divi is returned. * *Return Type: result, an Integer * *Exception: DivideByZero if divi is zero. *************************************************/ int divideTwo(int numer, int divi){ int result = 0; if(divi != 0){ result = numer / divi; }else{ result = -1; } return result; }//end of divideTwo()
What happens when...? • What happens when the precondition is false? • What happens if divi is zero? • The contract becomes void, and the postcondition may not be possible • What happens when the precondition is true, but the postcondition is false? • What happens if a String is returned instead of an Integer? • There must be a problem within the module
Benefits of programming by contract • Developers get better acquainted with object-oriented procedures and processes. • Inheritance - a way of creating is-a hierarchy between two or more classes. • Allows for a well defined approach to developing quality object-oriented software • The implementation of programming by contract allow for ease of debugging, quality assurance, and testing. • Another way of documenting software
Benefits Continued • According to Terence Parr of the University of San Fransisco programming by contract “is good because it forces you to think about the specification and thus the method will be more likely to actually do that.”
Programming by contract Versus Defensive programming • Defensive programming – write the code good enough the first time so that it is easy to maintain. • Defensive programming assumes nothing and tests for everything. • White values
Conclusion • Programming by contract is a great way of programmers to ensure software quality by bringing the specifications down to the code level. • Allows for quicker debugging of code since each module is documented. • The best approach to software development is a marriage between defensive programming and programming by contract. Bring the contract down to the code level, but continue to do error checking on data when applicable.
C++ Example //Name: generateNumber() //Parameters: a, an int, and b, an int //Precondition: a >= 1, b >= 1 //Postcondition: returns a random integer //Purpose: returns a random number between a and b int generateNumber(int a = 1, int b = 100){ //Handles potential erroneous values passed in if(a <= 0) a = 1; if(b >= 101) b = 100; //Handles possible division by zero if((b - a + 1) == 0){ ++b; } //Returns a randomly generated number within a and b return (a + 1 * rand() % (b - a + 1)); }//end of generateNumber()
Eiffel Example (code from Terence Parr) put (x: ELEMENT; key: STRING) is -- Insert x so that it will be retrievable through key. require count <= capacity not key.empty do ... Some insertion algorithm ... ensure has (x) item (key) = x count = old count + 1 end
Java Example //Name: enqueue() //Parameters: value, an Object //Desc: Inserts an Object into the rear of the queue. //Precondition: None. //Postcondition: None. //Exceptions: None. public void enqueue(NumberedObject value){ spot = ++counter; for(; (spot > 1) && (array[spot - 1].number() > value.number()); --spot){ array[spot] = array[spot - 1]; } array[spot] = value; }//end of enqueue() method
References • Bertrand Meyer. (October 1992).Applying Design by Contract. Retrieved October 8, 2006 from http://se.ethz.ch/~meyer/publications/computer/contract.pdf • Eiffel.com. (n.d.).Building bug-free O-O software: An introduction to Design by Contract(TM). Retrieved October 8, 2006 from http://archive.eiffel.com/doc/manuals/technology/contract/ • Parr, Terence. (n.d.)Programming “By Contract”. Retrieved November 4, 2006 fromhttp://www.cs.usfca.edu/~parrt/course/601/lectures/programming.by.contract.html • Wikipedia.org. (October 6, 2006).Design by contract. Retrieved October 8, 2006 fromhttp://en.wikipedia.org/wiki/Programming_by_contract