Ostatnio natrafiłem na pewien problem podczas prac nad nowym projektem (opartym o Zend Framework). Rozwiązanie problemu sprowadza się do odpowiedzi na pytanie: Co jest ważniejsze: optymalizacja czy zasady programowania obiektowego?
Mamy model Photos oraz klasę PhotosRow reprezentujący pojedynczy rekord. W aplikacji istnieją różne rodzaje zdjęć (profile, albumy, wydarzenia). Każde zdjęcia, w zależności od typu posiada kilka różnych rozmiarów.
class Photos extends Advaf_Db_Table {
public function deleteAlbumPhoto($photosId, $usersId) {
if ($this->_hasAccessToPhoto(..., 'albums')) {
$row = $this->findOne($photosId);
return $row->delete();
}
return null;
}
public function deleteEventPhoto($photosId, $usersId) {
if ($this->_hasAccessToPhoto(..., 'events')) {
$row = $this->findOne($photosId);
return $row->delete();
}
return null;
}
}
class PhotosRow extends Advaf_Db_Table_Row {
public function _postDelete() {
$mgr = new PhotoMgr();
foreach ($mgr->getSizes(this->type) as $size) {
$path = $mgr->getPhotoFullPath(...);
if(file_exists($path)) {
unlink($path);
}
}
}
}
Chciałem umieścić w metodzie _postDelete() klasy PhotosRow cały kod odpowiedzialny za usuwanie z przestrzeni dyskowej odpowiednich zdjęć. Mój kolega, Szymon od razu zwrócił uwagę, że to nie jest optymalne. Aby usunąć rekord, najpierw go pobieramy, potem usuwany (SELECT + DELETE, zamiast tylko DELETE). Wykonujemy jedno zapytanie dodatkowo, dla każdego zdjęcia. Dla 20 zdjęć do 20 extra zapytań! Szymon zaproponował aby przenieść cały kod odpowiedzialny za usuwanie zdjęć do Photos, a zdjęcia usuwać bezpośrednio $this->delete($where).
class Photos extends Advaf_Db_Table {
public function deleteAlbumPhoto($photosId, $usersId) {
if ($this->_hasAccessToPhoto(..., 'albums')) {
$where = $this->quoteInto('id = ?', $photosId);
$this->_unlink(...);
return $this->delete(where);
}
return null;
}
private function _unlink(...) {
}
}
Mimo wszystko obstaje przy swoim. Zgodnie z zasadą odpowiedzialności to klasa PhotosRow powinna po sobie posprzątać. Wydaje mi się, że właśnie w tym celu developerzy Zenda stworzyli takie metody jak _postDelete czy _postInsert w klasie Zend_Db_Table_Row.
Nie oznacza to oczywiście, że twórcy ZF nie moją głupich pomysłów… moim zdaniem do nich m.in należy obsługa formularzy i osobiście preferuje rozwiązanie Szymona: Fasic_Form.
Jestem bardzo Ciekawy twojej opinii, bo sprawa nadal nie jest rozstrzygnięta. Być może znasz lepsze rozwiązanie?
Dodaj mój rss to swojego czytnika.

