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?

category życie programisty Komentarze (13)

E-mail z Doliny Krzemowej

poniedziałek, 26 maja 2008

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.

Bezpośredni link do relacji.

category programowanie, życie programisty Komentarze (2)

Prawdziwy ajax upload

środa, 21 maja 2008

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).

swfupload logo

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

Plusy

  • Można zaznaczyć wiele plików naraz
  • Pasek postępu dla każdego pliku
  • Wstępna walidacja przed uplodem

Minusy

  • tworzy własną sesje
  • limit wielkości pliku do 100MB

swfupload

category javascript, jquery, programowanie Komentarze (3)

Zostać programistą to pikuś, wyzwaniem jest zostać dobrym programistą. 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.

czytaj dalej …

category życie programisty Komentarze (8)

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.

$('a[@href^=http]')
     .not('[@href*=www.dzbanyit.pl]')
     .addClass('linkexternal');

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.

dfc46656ab49a56e4ca8ff326a124c76

category javascript, jquery Komentarze (4)
  • W pracy nie wymagają ode mnie pisania testów
  • Nauka pisanie testów zajmuje zbyt dużo czasu
  • Pisanie testów zajmuje zbyt dużo czasu
  • Przeprowadzanie testów zabiera zbyt wiele czasu
  • Program został poprawnie skompilowany!
  • Płacą mi za pisanie kodu, a nie testowanie

A wy jakie macie wymówki ?

category życie programisty Komentarze (5)

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.

SimpeTest

czytaj dalej …

category programowanie, testy jednostkowe Komentarze (3)

echo ‘dupa’

czwartek, 27 marca 2008

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.

mini.jpg

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.

category programowanie Komentarze (9)

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.

Podstawy

  • używamy wyłącznie języka angielskiego
  • nazwy piszemy małymi literami
  • jako separator używamy podkreślenia
  • staramy się nie używać cyfr
  • używamy krótkich i samo komentujących się nazwy

czytaj dalej …

category programowanie Komentarze (7)

Singleton

sobota, 15 marca 2008

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.

czytaj dalej …

category wzorce projektowe Komentarze (5)