Dobre praktyki dla web developerów
Monday, October 22nd, 2007A taki szybki link – dość wstepna wersja, ale jest dużo ważnych “punktów”:
http://www.masukomi.org
A taki szybki link – dość wstepna wersja, ale jest dużo ważnych “punktów”:
http://www.masukomi.org
No dobrze, czyli obejrzałeś kilka screencastów, przerobiłeś parę tutoriali i postanowiłeś zrobić swoją własną aplikację Ruby on Rails?
Lokalnie wszystko działa, mongrel serwuje (wolno, bo wolno) strony, baza przetwarza rekordy, testy przechodzą w 100%.
Skończyłeś aplikację i pojawia się problem: Na jakim serwerze ją umieścić i jak go skonfigurować?
Zaczynasz od Dreamhosta… po tygodniu walki z killowanymi procesami odpuszczasz.
Wszyscy mówią: “serwer dedykowany”… i niestety mają rację. Jeśli Twoja aplikacja kierowana jest na rynek US – polecam SliceHost, a jeśli startujesz na Polskę/Europę – Hetzner.
OK, to teraz tylko jeden problem: Jak z czystej instalacji Ubuntu zrobić serwer Railsowy?
Z całej tej przygody jest to wbrew pozorom najłatwiejsze…
Deprec pozwala w 10 minut ustawić czyściutką instalację Ubuntu. Oto jak:
Jeden z ostatnich argumentów przeciwników RoR pada… instalacja i deployment serwisów w Ralisach przy użyciu deprec i capistrano to kaszka z mleczkiem ;-)
Męczysz się nad poprawieniem wydajności i wyglądu swojego kodu?
Wyślij go na http://refactormycode.com i pozwól sobie pomóc…
…czyli jak zadać dwa razy to samo pytanie i uzyskać inną odpowiedź.
akt 1. Cache’owanie zapytań
Cake zapamiętuje wynik każdego zapytania o czym nie można się dowiedzieć z manuala. Zapamiętuje jednak tylko w pamięci podręcznej, a więc jedyna korzyść z tego taka, że jak w tej samej metodzie (akcji) controllera wywołam np.
$user = $this->User->findAllByName('Alojzy');
...
$user = $this->User->findAllByName('Alojzy');
to zapytanie do bazy danych zostanie wykonane tylko raz. Dzieje się tak nawet, jeśli zamiast findAllByName skorzystamy z
$this->User->query(…)
Problem jednak pojawia się, gdy między tymi wywołaniami znajduje się coś jak:
$this->User->save($this->data);
wtedy drugie findAllByName zwróci nieaktualne dane (oczywiście o ile $this->data będzie zawierało informacje o jakimś Alojzym).
Sytuacji takiej oczywiście zwykle można uniknąć, bo jak odczytam dane z bazy, a potem je zmienię, to znaczy, że posiadam komplet wiedzy, żeby zbudować wynik kolejnego odczytu bez odwoływania się do bazy.
akt 2. Jak być powinno
Zgodnie z ideą CakePHP programista powinien dążyć, do traktowania modelu jako raczej reprezentanta konkretnego rekordu, a nie tabeli (oczywiście findAll i temu podobne to wyjątki). Dlatego przy zapisie danych ustalany jest klucz rekordu i wywołując ’saveField’, czy ’save’ bez klucza, odwołujemy się ciągle do tego samego rekordu. Ponieważ bywa to uciążliwe, gdy zapisuje się więcej niż jeden rekord (np. w pętli), Cake’owcy proponują w takim przypadku wywoływać:
$this->[nazwa_modelu]->create();
za każdym razem gdy skończymy odwoływać się do konkretnego rekordu (np. w tej pętli).
Wydaje sie naturalne, że wywołanie takiego resetu na modelu powinno wyczyścić jego cache (czy tylko mi się to wydaje naturalne?)
Niestety cache nie jest trzymany w klasie AppModel (model_php5.php), tylko w klasie DataSource (datasource.php i dbo_source.php). Dzięki temu zapytanie jest cache’owane jako jedno i to samo nawet gdy wywoływane jest poprzez różne modele (IMHO nieco wątpliwa korzyść). Utrudnia to jednak operowanie na cache’u.
akt 3. Rozwiązanie.
W przypadku, gdy chcę odczytać dane z bazy (select) przed i po modyfikacji danych (update), muszę po updacie wyczyścić cały cache zapytań. Na stronie: http://www.benjiegillam.com/serendipity/categories/11-CakePHP Benjie Gillam proponuje dodać do app/app_model.php następującą funkcję:
function clearAllDBCache() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db->_queryCache = array();
}
i wywoływać ją za każdym razem, gdy w środku controllera zapragniemy aktualnych danych.
Krzysiek Heród
Myślałem, że biblioteka wchodząca w skład Zend Framework zmieni trochę obecną sytuację – niestety wciąż generowanie pliku PDF ze znakami Unicode z poziomu PHP jest potężnym wyzwaniem.
Osobiście korzystam z biblioteki TCPDF. Nic innego nie udało mi się znaleźć.

Co jakiś czas będę pisał o dojrzałych php’owych bibliotekach, które warto wykorzystywać w swoich projektach…
W tym poście będzie trochę o SimplePie:
SimplePie to bardzo dobra biblioteka do parsowania źródeł XML (RSS, Atom), która nadrabia braki Magpie RSS.
Główne cechy Simplepie to:
Agregacji nigdy dość (szczególnie kiedy popularność i obecność RSSów jest bardziej niż oczywista).
Dlatego piszemy uniwersalny agregator z kilkoma ciekawymi funkcjonalnościami.
Agregator będzie oparty o zmodyfikowany przez nas framework CodeIgniter i wykorzystywał szereg sprawdzonych bibliotek, m.in.:
Główne cechy tego agreagatora to możliwość parsowania wielu źródeł RSS (z filtracją), możliwość dodania własnych postów, głosowania, tagowanie, kategoryzowanie (np. na podstawie zestawu tagów), bardzo rozbudowane preferencje wyświetlania… i przede wszystkim kojarzenie wpisów z miejscami, ludźmi, produktami… i jeszcze kilka funkcjonalności, o których z pewnością napiszemy kiedy będzie TEN moment.
Co najważniejsze… być może źródła będą udostępnione publicznie.