I’m still trying to wrap my head around OOP. All of the following examples work, of course, but is there one (or possibly another) that best exemplifies OOP concepts?
/**
* For the following examples the Image class queries an image
* and associated info from a database, which is passed on
* instantiation via dependency injection.
*/
$image = new Image(new Db());
Example 1:
if ($image->setImageId($id, $size)) {
header('content-type: ' . $image->content_type);
header('content-length: ' . $image->length);
echo $image->getBytes();
}
Example 2:
if ($image_info = $image->getImageInfoByIdAndSize($id, $size)) {
header('content-type: ' . $image_info->content_type);
header('content-length: ' . $image_info->length);
echo $image->getImageBytesByIdAndSize($id, $size);
}
Example 3:
$image->setImageIdAndSize($id, $size);
if ($image_info = $image->getImageInfo()) {
header('content-type: ' . $image_info->content_type);
header('content-length: ' . $image_info->length);
echo $image->getImageBytes();
}
4
I agree with delnan’s comment about “OOP”, and that there’s really no such thing as “proper OOP concepts”, but in terms of general coding principles, I think example 2 is a clear winner compared to the others.
Examples 1 & 3 are the same thing with different names. In this case it’s not obvious at all that setting the object’s ID and size would cause a database fetch and its other properties to be populated. I’ve debugged code like this and it’s hard to track down exactly what’s happening with these kinds of side effects hidden all over the place.
Example 2 is a sort of combination of a Data Access Object and a Factory, and these could potentially be separated out, but either way it’s more obvious to the reader what is happening.
Edit
Here’s an even clearer representation:
if ($image = $image_data_access->getImageById($id)) {
$image->scaleTo($size);
header('content-type: ' . $image->content_type);
header('content-length: ' . $image->length);
echo $image->getBytes();
}
7
(my opinion, please do not be offended if you disagree)
None is good.
Method name does not indicate at all that headers are being sent or something is being echoed.
I would prefer something like following.
class Image {
public function __construct($id) {
#load, if fail throw exception
}
private function getHeaders() {
return array(
'content-type' => $this->content_type,
'content-length' => $this->length
);
}
private function sendHeaders() {
#calls function sendHeaders defined somewhere far away (usually it is 'app' object which has method like this)
sendHeaders($this->getHeaders());
}
/** Sends image headers and content(bytes) */
public function sendImage() {
$this->sendHeaders();
echo $this->getBytes();
}
}
If I am missing ‘OOP way’ please write in comments as I am also learning, and I would be thankful for directing me in right way 🙂
1