OOP-DBC
Coming out of high school, it was stressed that good practice makes good composition. One of these pillars of thought was code purity. Purity in the sense that each method should do as it’s advertised without causing side effects.
It’s not much different than Design By Contract, (DBC) – a coding technique promoted in The Pragmatic Programmer, another book I’m reading for work. The thought is that every method has a contract to which it and other methods – and in OOP, objects/classes – abide by. Everyone fulfills their contract, everyone benefits, and the programmer can go home early that night.
The downside, as T.P.P. describes, is that OOP does not lend itself nicely to automatic DBC programming: namely that method inheritance doesn’t imply contract inheritance. This seems like a relatively small gripe to be made about OOP, in my opinion, especially when a simple coding standard can surmount this problem.
In what I’ve learned from OOP, good style is to use both public and private methods, and methodologies, to their advantage. This, thankfully, lends itself well to implementing DBC.
As with most of my posts, this one includes an example!
/**
* Basic object class, all other classes should extend this
*/
class BaseObject {
/**
* Public accessor to the toString() concept
*/
public function toString() {
// contract invariants
$invariants = Array('this'=>$this);
// contract presumptions
assert(is_object($this), get_type($this)." is not an Object");
// inherited method
$r_val = $this->_toString();
// contract post assertions
assert(equals($invariants['this'], $this), get_class($this)."::toString() modified the Object in a read-only context");
assert(is_string($r_val), get_class($this)."::toString() did not return a String.");
return $r_val;
}
/**
* Private implementation of the toString() concept
*/
private function _toSring() {
$r_val = Array();
$r_val[] = $this->some_val;
return implode("\n", $r_val);
}
}
/**
* A class which does what it's supposed to do
*/
class GoodObject extends BaseObject {
/**
* This function abides by the BaseObject::toString() contract
*/
public function _toString() {
$r_val = Array();
$r_val[] = $this->some_val;
$r_val[] = $this->other_val;
return implode("\n", $r_val);
}
}
/**
* A mischevious class
*/
class BadObject extends BaseObject {
/**
* This function does not abide by the BaseObject::toString() contract
*/
public function _toString() {
$r_val = Array();
$r_val[] = $this->yet_another_val;
$r_val[] = $this->some_val;
return $r_val;
}
}
So we can see that it’s not too hard to notice that the assertions set in place in the BaseObject class will catch whatever the contract for toString() has been set up. Better even than that, the contract can be amended in one place and it will filter down throughout all subclasses. It’s OOP-DBC; and it could save your life – or at least your program.
About this entry
You’re currently reading “OOP-DBC,” an entry on Advent Digerati
- Published:
- Friday, February 6th, 2009 at 12:03 AM
- Author:
- Zack
- Category:
- PHP
- Tags:
- Code Snippet
No comments
Jump to comment form | comments rss | trackback uri