< Day Day Up > |
A system is made up of interfaces that interact with each other. The interfaces can be implemented by object-oriented code or by procedural code. Yukihiro Matsumoto, the inventor of Ruby, suggests that the interface is everything to the user . I would add that the interface is everything to the developer.
Bertrand Meyer introduced the concept of Design by Contract in Object-Oriented Software Construction (Prentice Hall PTR, 2000). An interface has a contract with the user of that interface. The contract consists of preconditions and postconditions for every method in the interface. Preconditions are assertions that must be true when the method is called so that the method can perform its operations. Postconditions are assertions that should be true when the method finishes. [*]
For example, when you're writing to a file, a precondition is that the file must be opened, and a postcondition is that the file length has changed (if you're appending to the end of the file). A precondition can also apply to the value of an argument in a call; for instance, it must be between a given set of values. The called method should assure that the postconditions are met. Otherwise , it has not performed its job properly. The questions are who checks the preconditions and what should result if a precondition is not met. Some designers feel that it is the calling routine's responsibility to make sure the preconditions are satisfied. For example, the calling routine should ensure that parameters are within the ranges the preconditions specify. If they are not, the called method has no responsibility to perform its contractual obligation. I prefer that the called method specifically check for its preconditions in its code. The code is the record of the contract. Putting checking responsibility on the called method parallels the concept that a whole program is responsible for checking the input from the user. The called method contains the most knowledge of the preconditions. Unless performance requirements dictate otherwise, the called method can check for all preconditions and report via an error notification mechanism if the conditions are not satisfied. Is a failure to satisfy a precondition a programming error or an inherent error in the domain? That depends on context. The called method likely has the most information as to "what" caused the precondition violation, but the caller has the most information as to the meaning of the precondition violation. Make the contract explicit. It should be visible in the code for the class and any derived documentation. To check the contract, you can use regular code style (e.g., if (parameter_value < 3) , assertions ( assert(parameter_value < 3) ), aspects (see http://aosd.net/ for details on aspects), or language-specific features.
|
< Day Day Up > |