Programista z doświadczeniem zarówno w projektach biznesowych (CRM, B2B) jak i web 2.0.
Zwolennik zwinnego podejścia do wytwarzania oprogramowania hubert@dzbanyit.pl
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?
Bardzo polecam obejrzeć prezentacje Marka Hołyńskiego jaką przeprowadził na Bootstrapie 8.5. Dowiecie się z niej między innymi o historii startup’ów, o różnicy w rozwiązywaniu problemów w akademicki i biznesowy sposób. Poznacie również co się stało z pewnym geniuszem z Grecji.
Tytuł może być trochę mylący. Bo nie jest możliwe przesyłanie plików poprzez XMLHTTPRequest! Wszystkie znane Wam z sieci ajaxowe uploady bazują na pewnych trickach, o których zamierzam opowiedzieć.
IFrame
Tak to ten sam stary dobry IFRAME, kiedy web nie miał jeszcze numerka, a na stronach www rządził kolor szary i niebieskie linki. Minęło trochę czasu i ten znacznik został zapomniany, a nawet wyklęty. Jednak bez ten trick nie będzie mógł działać.
Przepis jest prosty. Formularz z polem input type="file" umieszczamy w pływającej ramce. Kiedy naciśniemy przycisk wyślij - zacznie się uplodowanie pliku, ale wszystkie pięknie w ‘tle’. Można dodać indykator tak, aby użytkownik myślał, że to ajax.
Plusy
Bardzo proste rozwiązania
Minusy
Brak paska postępu
Można uploadować tylko jeden plik naraz
Flash upload
Kolejne rozwiązanie bazuje na flashu i javascript. Cały proces uploadu przechodzi przez ‘niewidzialny’ obiekt flasha. Sposób jest prawie idealny… problem tkwi w tym, że flash uruchamia własną sesje. A to jest dużym problemem (np. autoryzacja). Rozwiązanie tego problemu to przejęcie sesji, w php można to uzyskać poprzez session_id($passedId).
Moim zdaniem najlepsza implementacją uploadu z wykorzystanie flashu jest biblioteka swfupload. Jest napisane w czystym javascripcie, dlatego można ją integrować z dowolnym innych kodem js. Ma sporą społeczność i jest ciągle rozwijana
Zostać programistą to pikuś, wyzwaniem jest zostać dobrymprogramistą. Niniejszym otwieram serię wpisów z kategorii rozwój osobisty, w której będę na podstawie własnego doświadczenia pokazywał drogę do sukcesu.
W jQuery zakochałem się od pierwszego wejrzenia. I była to miłość odwzajemniona. Dzięki tej bibliotece javascript byłem w stanie tworzyć ciekawe efekty oraz dodawać funkcjonalności do stron przy pomocy kilku linijek kodu i małej ilości pracy. Analizując kod pluginów, jak i samej biblioteki doskonaliłem swoje umiejętności programowania w javascripcie, co pozwoliło mi na budowanie bardzo zaawansowanych stron i całych ‘ajaxowych’ portali.
JQuery ma tę samą wspaniała cechę co Zend Framework. Jest tak pięknie zaprojektowana, że można dowolnie modyfikować i rozszerzać. Kolejnym super rozwiązaniem jest zastosowanie fluent interface co bardzo skraca zapis i ułatwia programowanie.
Filozofie pisania pod jquerowemu, trzeba po prostu poznać i polubić. Dla osób korzystających wcześniej z innych bibliotek, w szczególności Prototype, może to zabrać więcej czasu, ale naprawdę warto.
Główne cechy jQuery:
Skompresowane jQuery waży tylko 19kb
Wspiera selektory: CSS 1-3 i XPath
Działa pod: IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+
Ponieważ nie lubię wynajdywać koła na nowa i tworzył kolejnego kursy ‘podstawy jQuery’, poniżej prezentują wam garść przydatnych linków, a w następnych postach z cyklu jQuery & javascript będę poruszał konkretne tematy i pokazywał rozwiązania realnych problemów.
Test jednostkowy (unit test) to fragment kodu, który sprawdza inny fragment kodu - to najprostsza definicja jaką udało mi się znaleźć. Poza podstawowym celem jakim jest eliminacja błędów, dzięki używaniu testów jednostkowych zyskamy m.in
redukcje kosztów
bezproblemowy refactoring
wyższą jakość kodu
Eliminacja błędu jest tym bardziej kosztowna im projekt jest dalej posunięty w czasie. Szczególnie eliminacja błędów na etapie wdrożenia zabiera dużo czasu i zasobów. Co gorsze wpływa negatywnie na nasz profesjonalizm w oczach klienta, a może nawet mieć swoje skutki w postaci kar umownych, czy nawet zerwania umowy.
PHP nie jest idealne i od czasu do czasu pojawia się biały ekran śmierci. I nic nie pomoże error_reporting(E_ALL), dalej widzimy pusty ekran. Jedyne co pozostaje to stare dobre echo 'dupa', które trzeba umieszczać w kolejnych sekcjach kodu, szukając miejsca wystąpienia błędu.
Sam udoskonaliłem tę metodę do postaci echo 'd'. Czasami jednak potrzebowałem więcej informacji o zmiennych. Z pomocą przyszedł print_r umieszczony między znacznikami pre, co pozwalało na wyświetlanie zagnieżdżonych tablic. Jednak to nie było to, czego szukałem.
W końcu znalazłem dBug autorstwa Kwaku Otchere. W zagnieżdżonych tabelkach dBug wyświetla tablice, obiekty, xml’a. Wszystko pokolorowane zgodnie z typami danych.
Wystarczy krótki kod new dBug($yourVariable) i wszystko ładnie się wyświetla. Ponieważ mimo wszystko ten zapis był dla mnie za długi i pozostał sentyment do echo ‘dupa’. Stworzyłem pomocniczą funkcję d():
/**
* Debug
* @see echo 'dupa';
* @param mixed $var
*/
function d($var) {
new dBug($var);
}
Użycie pojedynczej litery dla nazwy funkcji kłóci się z ogólnie przyjętymi zasadami nazewnictwa, jednak w przypadku funkcji pomocniczej można zrobić wyjątek. W javascripcie również używam takiego samego strutu d(), co jest bardzo wygodne i przyspiesza pisanie kodu.
Ludzie tworzą pewne standardy, aby ułatwiać życie sobie i innym. W przypadku języków programowanie java czy php, standardy nazewnictwa i kodowania są jasno zdefiniowane (PEAR2 Standards, Zend Framework Coding standard) i wystarczy ich jedynie przestrzegać. W przypadku baz danych jest już gorzej…
Dlatego też postanowiłem wypracować standard, który będę używał w swoich projektach. Cześć rzeczy może budzić kontrowersje, dlatego bardzo liczę na waszą reakcje. Wpis ma status ‘open’ i na pewno będę wprowadzał do niego zmiany.
Wzorzec singleton pozwala na ograniczenie liczby egzemplarzy danej klasy do jednego. Klasa albo nie ma żadnych egzemplarzy, albo ma tylko jeden, nie więcej.
Typowym zastosowaniem tego wzorca jest sytuacja, gdy tworzenie egzemplarza klasy wiąże się z dużym kosztem. Najlepszym przykładem jest klasa komunikacji z bazą danych. Zakładająć, że będziemy się komunikować z jedną bazą danych, wykorzystanie wzorca singletona będzie najlepszym rozwiązaniem.