Archiwalia w kategorii 'software'

Chyrp!

Tak się złożyło, że od wczoraj jestem oficjalnym maintainerem Chyrpa. Jego implementacji w PHP dla ścisłości.

Chyrp to lekki silnik, który pozwala wygodnie prowadzić własnego (mikro-/foto-) bloga. Wszystko zaczęło się od tego, że pewien szesnastolatek (tak, szesnastolatek), Alex Suracil, postanowił zrobić WordPressowi konkurencję. Wokół projektu zrobił się mały szum i powstało community. Zaczęły pojawiać się piórka i moduły (odpowiedniki wtyczek), tłumaczenia, skórki, a z czasem pojawiło się pytanie o implementacje dla innych platform.

Ja przejąłem oryginalną implementację w PHP, Alex zaczął prace nad wersją w Rubym, a mitsuhiko pracuje nad projektem twig — implementacją silnika szablonów Jinja w PHP.

Jeśli szukacie czegoś wygodniejszego i lżejszego niż WordPress, to być może właśnie znaleźliście. Oczywiście projekt jest otwarty i z chęcią przyjmiemy kolejnych ochotników. Miłej zabawy!

Jak nie należy programować

Tydzień z grubsza zajęło mi doprowadzenie do używalności kodu, który otrzymałem w spadku po pewnym urlopowiczu. Dobrze, że nie mam włosów, bo z pewnością bym je dawno wyrwał, choć z — drugiej strony — na programowaniu cierpi moja broda. Kolega wypoczywa w Iranie, a my próbujemy dojść, co też podmiot liryczny miał na myśli. Kiedy czytanie źródeł dłuży się ponad lekturę Nad Niemnem, znak to, że czas na notkę.

Jak nie należy programować

Na wstępie już zaznaczę, że w ITS Ltd. zajmujemy się budowaniem aplikacji webowych w oparciu o Pythona i Django, więc niektórym poniższy tekst może wydać się płytki/nudny/pozbawiony sensu (niepotrzebne skreślić).

Poradnik niniejszy zalecany jest dla programistów, którzy w różny sposób związani są z serwisem The Daily WTF — czy to przez umiłowanie do czytania publikowanych tam historii, czy to przez bycie bohaterem tych ostatnich. Redakcja zastrzega sobie prawo do skrótów myślowych i przelotnego braku poczucia humoru.

Redundancja

Najważniejszą cechą systemów klasy Enterprise (jeden do teleportacji) jest ich wysoka dostępność (i cena). Jest to fakt tak niezaprzeczalny, jak niezaprzeczalna jest wysoka jakość produktów z rodziny Gadu-Gadu. Autorzy aplikacji klasy E (uniwersalny, automat i do tkanin czarnych) często uważają, że ich produkty z powodzeniem stawać mogą w konkury z aparaturą czasu rzeczywistego. Cóż, każdy może się mylić, ale jakież tajemne receptury zapewniają taką pewność siebie? Dziś Viagrę nabyć można na każdym bazarze, skupmy się więc na technikach programowania.

Autor aplikacji staje wielokrotnie przed trudnymi pytaniami egzystencjalnymi. Gdzie jest specyfikacja techniczna? Jak ja wczoraj wróciłem do domu? Skąd weźmiemy tyle galaretki, żeby napełnić basen? To tylko niektóre z nich. Najważniejsze pytanie, jakie zadają sobie autorzy aplikacji klasy E (E303, E301, może zawierać śladowe ilości orzechów), to jak uniknąć używania bibliotek, których sami nie napisaliśmy, wszak któregoś ranka gotowe przestać działać. Na szczęście tutaj z pomocą przychodzi dogmat Copiego-Paste’a. Wystarczy zatem skopiować kluczowe elementy frameworku do używającej go aplikacji i już możemy spać spokojnie — co dwie kopie to nie jedna, prawdopodobieństwo mówi, że obie nie popsują się jednocześnie.

Optymalizacja czasu pracy

Jeśli brać z kogoś przykłady (a klasa E czyni to niechętnie, sami wszakże stanowią elitę), to tylko z amerykańskiej marynarki. Tradycyjne pojęcia deadline’ów i zarządzania zasobami zastąpić można sprawdzonym na wielu wojnach ŻULU time. W firmie najważniejsi są ludzie, więc zawsze jest czas się napić! Pozwala to płynnie regulować stres powodowany przez pracę, a naukowcy dowodzą, że może w zupełności wyeliminować ryzyko wystąpienia nerwicy (stosujący tę metodykę rzadko dożywają czterdziestki).

Ważne jest również, by programista miał podejście analitycznie i potrafił myśleć outside the box, co w języku polskim oznacza dosłownie myśl, jak ciągle być poza kubikiem. W praktyce sprawdza się najlepiej obranie niekonwencjonalnych godzin pracy (na przykład godzin nocnych) i planowanie przestrzenne (koduję od tego kieliszka do podłogi).

Generalizacja

Generalizacja to dar patrzenia na rzeczy z dystansu. Dla przykładu pies i samochód z dystansu wyglądają podobnie. Dlaczego więc nie umieścić ich w bazie danych we wspólnej tabeli rzecz, odpowiednio pomijając kolumnę rasa w przypadku samochodu i podając zero w kolumnie liczba_drzwi w przypadku psa? Tak zbudowana baza danych jest dużo prostsza do programowania, zwłaszcza jeśli w użyciu jest szkielet ORM.

Dodatkowe punkty komisja przyzna za uproszczenie tabeli do jednego pola, w którym umieścić można zserializowany obiekt dowolnego typu.

Obfuskacja

Duży projekt klasy E często jest oczkiem w głowie korporacji. Nie można zatem dopuścić, by sekrety jego działania poznał niepowołany śmiertelnik. Lata doświadczenia w dziedzinie refaktoryzacji uczą, że najpewniejszym środkiem zapobiegawczym jest obszerne stosowanie obfuskacji. Stosowanie jednoliterowych nazw zmiennych i funkcji nie tylko uniemożliwia zrozumienie geniuszu kryjącego się za kodem, ale także znacznie zmniejsza miejsce, jakie kod zajmuje na dysku. Jest to zaleta nie do pominięcia w przypadku projektów, które korzystają dodatkowo z technik programowania życzeniowego (ale o tym za chwilę).

Niezwykle ważne jest też konsekwentne nieumieszczanie komentarzy w kodzie. Łatwo policzyć, że przeciętna metoda o długości dziesięciu ekranów, stałaby się nieznośnie długa, gdyby co drugi wiersz wstawić komentarz i przeprosiny dla naszego zastępcy.

Zaawansowane techniki zabezpieczania kodu

Kolejną techniką obfuskacji jest, pochodzący z literatury, synkretyzm językowy. Dla zmylenia potencjalnego przeciwnika i lepszego utrwalenia w pamięci dawno nieużywanych technik, staramy się co jakiś czas wtrącić ekran kodu napisanego na przykład w PHP. W tym celu ograniczamy się do części wspólnej składni obu języków, dodatkowo emulując zachowanie zupełnie innego frameworku.

Mało znaną, ale opanowaną do perfekcji przez elitę, metodą wprowadzania zakłóceń w kodzie jest tak zwane prawo wolnego rynku (import bez ograniczeń). Główne zastosowanie tej metody to naprawianie wadliwych języków, których autorzy złośliwie wprowadzili przestrzenie nazw. Wystarczy jednak kilka instrukcji from foo import * starannie porozrzucanych po kodzie (nie zapomnijmy części z nich umieścić w instrukcjach warunkowych) i jesteśmy z powrotem w starym, dobrym bashu. Przyjemny skutek uboczny to fakt, że nikt nigdy nie będzie w stanie odtworzyć zależności aplikacji poza naszym środowiskiem rozwojowym.

Programowanie życzeniowe i stubenci

Jedną z podstawowych prawd na temat programowania jest taka, że każdą aplikację trzeba utrzymywać, a rzadko która nie ewoluuje wraz z upływającym czasem. Pragmatyczny programista dba o to już od pierwszej linii kodu. Zanim jeszcze zajmie się implementacją wymaganej funkcjonalności, stara się przewidzieć możliwe przyszłe drogi rozwoju. Jeśli programista zna się na fachu, owocuje to umieszczeniem w kodzie rozlicznych z pozoru niepotrzebnych metod. Są one z natury zepsute bądź puste i nazywamy je stubami, sam zaś autor nosi fachowe miano stubenta.

Stubenci zapewniają aplikacji bezpieczny margines nadmiarowości, podobnej w naturze do redundancji, co z kolei zmniejsza ryzyko, że przyszły opiekun projektu w wyniku zmieszania niechcący usunie coś niezbędnego. Jedną z rzadziej spotykanych metryk jakości kodu klasy E jest właśnie procentowy udział kodu, który można usunąć bez wpływu na działanie aplikacji. Najlepsi w branży utrzymują się w przedziale od czterdziestu do sześćdziesięciu procent.

Testy jednostkowe i UMŁ

Jak sama nazwa wskazuje, są to testy, które przeprowadza się tylko raz. Dla pewności, że zbędne dane nie wpłyną na wynik ani czas trwania testu, najlepiej przeprowadzić go w środowisku rozwojowym, przy pustej bazie danych. Już samo słowo wdrożenie sugeruje, że klient musi liczyć się z dodatkowymi kosztami w celu późniejszego doprowadzenia produktu do działania w środowisku produkcyjnym. Testy jednostkowe, z natury, mogą być ciężkie do powtórzenia nawet w warunkach laboratoryjnych, stąd nie należy mieć oporów przed skorzystaniem z wygodnego narzędzia, jakim jest UMŁ (u mnie łaziło).

Cóż, na dziś to wszystko, do zobaczenia w kolejnym odcinku poradnika Jak nie należy programować, gdzie wspólnie wzbogacimy wachlarz stosowanych praktyk. Czytał Lucjan Szołajski.

Rhythmbox i trzeszcząca muzyka

W PLD przez dłuższy czas ludzie skarżyli się na artefakty przy odtwarzaniu muzyki przez Rhythmboksa. Problem rozwiązany został dopiero wczoraj.

Zacznę może od rozwiązania, trzeba zaktualizować pakiet alsa-lib do wersji 1.0.16.

Jeśli kogoś ciekawi przyczyna problemu, to służę informacjami. Rhythmbox do odtwarzania dźwięku używa szkieletu GStreamer. GStreamer odpowiada za dekodowanie strumieni i nakładanie efektów, sam jednak do komunikacji z urządzeniem wyjściowym wykorzystuje jedną z bibliotek audio. Najczęściej używana jest w tym przypadku wspomniana ALSA.

Na każdym styku elementów następuje negocjacja obsługiwanych formatów danych. Rhythmbox przed otwarciem pliku sprawdza, czy GStreamer potrafi go obsłużyć. Następnie tworzony jest łańcuszek elementów GStreamera. Każde dwa elementy w kolejce ustalają między sobą preferowany format przekazywanych danych. Ostatnim elementem w łańcuchu odtwarzania jest odpływ (sink), przekazujący dane do biblioteki ALSA.

Również tutaj odbywa się negocjacja i tu pojawia się problem trzeszczenia. GStreamer od niedawna oferuje wsparcie dla 32-bitowych próbek dźwięku. Zapewnia to większą precyzję przy przetwarzaniu, a w przypadku droższego sprzętu także wyższą jakość dźwięku kierowanego na głośniki. Oczywiście, większość z nas słucha muzyki w formatach kompresowanych i nie usłyszymy raczej różnicy, ale GStreamer robi WłaściwąRzecz™.

Problemem jest jednak ALSA, która również od niedawna zmieniła sposób skalowania próbek w przypadku 16-bitowych kart muzycznych. Do niedawna operacja ta polegała na obcięciu 16 mniej znaczących bitów. Zastąpił go nieco bardziej skomplikowany wzór, który — w przypadku dużej siły sygnału — podatny był na przepełnienie arytmetyczne. Ten właśnie drobny szczegół poprawiono w wersji 1.0.16.

Miłego słuchania muzyki zatem, Rhythmbox jest niewinny ;)

Python: django-google

Jeśli ktoś z was czuje nieodpartą ochotę zbudowania aplikacji korzystającej z przypomnień lub kalendarza, to zapraszam do testowania django-google. Docelowo moduł powinien obsługiwać więcej API gdata Google, ale w tej chwili niewiele z nich ma sens w odniesieniu do Django (większość realizuje tylko dostęp do odczytu).

Drodzy deweloperzy dystrybucji…

Nie interesuje mnie, czy bazujecie na jądrze Solarisa, Linuksa, czy może BSD. Jeśli chcecie naprawić jakiś pakiet — bo się nie buduje — droga wolna — lokalne patche są często potrzebne.

Jeżeli zaś chcecie rozbudować program, czy ogólniej zmienić jego działanie, to róbcie to upstream. Gdyby każdy obywatel forknął każdy używany projekt i gdyby nawet wasze dzieci — i nie mówcie mi, że nie macie, bo zawsze możecie mieć (sprawdzić, czy nie ksiądz) — to byśmy żyli w takim burdelu, że wolałbym używać Windowsa.

Winni nie muszą się zgłaszać, bo pewnie nie czytają tego bloga. Podejrzewam też, że nie znają polskiego — tak, jak ja pospołu z autorami nie znam łatek nakładanych lokalnie. Przodują w tym panowie z Ubuntu, trzon peletonu stanowią zaś Novell, Sun i RedHat. Każdy z dużych ma generalnie w dupie, że autor pakietu nigdy nie dowie się ani o błędach, które załatali zainteresowani, ani o oczekiwaniach użytkowników.

Długofalowy efekt jest taki, że w Ubuntu wszystko działa inaczej, niektóre aplikacje mają problemy, które Novell u siebie poprawił trzy lata temu, a użytkownik nie ma się komu poskarżyć, bo przecież autor programu za cudze łaty spowiadał się nie będzie, autor zaś łatek od dwóch lat pracuje pewnie dla innej korporacji. Nie uwierzycie pewnie, ile radości sprawia szukanie łat w repozytoriach innych dystrybucji, kiedy bugzilla danego projektu świeci pustkami.

Postscript: Byliśmy dzisiaj w kinie na trzeciej części Resident Evil. Streszczenie filmu:

  1. Cela
  2. Cube 2
  3. Mad Max
  4. Szklana Pułapka
  5. www.Strach
  6. Mad Max
  7. Ptaki
  8. X-Men
  9. Mission: Impossible
  10. Gwiezdne Wojny
  11. Mad Max
  12. Pitch Black
  13. Liga Niezwykłych Dżentelmenów
  14. Star Trek
  15. X-Men
  16. Cube 2
  17. Matrix

Warto obejrzeć, poważnie. Brakowało mi tylko Generała Daimosa.

Dear lazyweb…

Jestem szczęśliwym posiadaczem dwóch konsol — PlayStation 2 i PlayStation 3. Byłbym jeszcze szczęśliwszy, gdybym posiadał jeszcze więcej gier. Oczywiście, wychowałem się z joystickiem w ręce i pewnie mógłbym z radością przebrnąć przez wszystkie wydane tytuły, ale jest jeden problem.

O ile mordowanie tłumów za pomocą katany Onimushy i kopanie raperskich tyłków w DefJam Icon sprawia mi wiele radości, często zdarza się sytuacja, w której w pokoju znajduje się mnoga liczba potencjalnych partycypantów zabawy, toteż dobrze byłoby uruchomić coś mniej zobowiązującego niż Dragon Quest 8 i mniej angażującego intelektualnie od Okami. Nie każdy też chce przed zabawą nauczyć się wszystkich 100+ ciosów wybranej postaci w Tekkenie.

Jak zapewne domyślacie się, w potrzeby idealnie wpasowuje się Katamari, mam też oczywiście Super Rub ‘a’ Dub, ale gdzie dalej? Kiedy przeglądam ofertę, to wydaje mi się, że wydawcy gier na Xboksa i PS3 uznali, że skoro konsole mają świetną grafikę i dostęp do internetu, to ludzie przestali się spotykać przy piwie.

Drogi lazywebie, szukam gier, w które można pograć na jednej konsoli i przy jednym telewizorze. Tak, wiem, że Warhawk ma tryb dzielonego ekranu nawet dla czterech graczy, jednak nie spełnia powyższych wymagań. Tak, też czekam na LittleBigPlanet i Beautiful Katamari. Pomóżcie ;)

Strip #NaN: Lord of the Patents

Lord of the Patents

PLD Th: fixing a vserver

Niniejszy post jest oparty o historię z pola bitwy. Bardzo techniczny i nieszczególnie ciekawy, jeśli ktoś nie używa wymienionych technologii. Być może komuś się przyda.

Awaria

Poszukiwanie przyczyn pozwoliło nam ustalić następujące fakty:

  • W jednej z maszyn wirtualnych ktoś zainstalował pakiety rpm i poldek, a następnie użył ich do instalacji oprogramowania;
  • Maszyna miała cały czas zamontowaną zewnętrzną bazę rpm (prawdopodobnie utils-vserver zdechło i pozostawiło po sobie bałagan, ale o tym później);
  • Wewnętrzny rpm miał inną wersję i w jakiś sposób uszkodził bazę zainstalowanych pakietów;
  • Następujący po nim rpm --rebuilddb bezpowrotnie wyczyścił bazę pakietów maszyny;
  • W międzyczasie miał miejsce upgrade pakietów rpm i poldek w zewnętrznym systemie;

Postanowiliśmy zatem przeinstalować maszynę od nowa, rekonstruując na podstawie działających usług listę niezbędnych pakietów.

Nosem w dół

Dość szybko okazało się, że nie będzie tak łatwo:

ncontext: vc_net_create(): Invalid argument

Tak właśnie kończyło się każde wywołanie narzędzi vrpm i vpoldek. Winnym okazało się wywołanie chbind, a poprawka wygląda tak:

--- /usr/lib/util-vserver/functions~    2007-09-05 16:09:16.967334575 +0200
+++ /usr/lib/util-vserver/functions     2007-09-05 16:10:29.456275993 +0200
@@ -1171,5 +1171,5 @@
     export RPM_FAKE_CHROOT RPM_FAKE_CTX RPM_FAKE_CAP RPM_FAKE_FLAGS

     LD_PRELOAD=$_RPM_FAKE_SO${LD_PRELOAD:+:$LD_PRELOAD} \
-       exec $_CHBIND "${CHBIND_OPTS[@]}" "$@"
+       exec $_CHBIND --nid $RPM_FAKE_CTX "${CHBIND_OPTS[@]}" "$@"
 }

Dość szybko okazało się, że radość jest przedwczesna. O ile vrpm i vpoldek zaczęły działać, to żadne z nich nie potrafiło nic zmienić. Odpytywanie bazy nie przysparzało żadnych trudności, próba instalacji lub usunięcia pakietu kończyły się kolejnym radosnym komunikatem:

error: cannot open Basenames index using db3 - No such file or directory (2)

Winny

Okazało się, że winny jest rpm-4.4.9 w połączeniu z db4.6. Nie miałem okazji sprawdzić, co dokładnie powoduje nieprawidłowe działanie, dość było upewnić się, że działa wersja rpm-4.4.9-1, zbudowana z pakietem db4.5-devel.

Problemem jest fakt, że db4.6 automatycznie konwertuje każdą otwartą bazę do swojego formatu, co oznacza, że po wykonaniu downgrade pakietu rpm zostaniemy z bezużytecznym narzędziem.

Rozwiązanie

Jeff, autor rpm pomógł mi cofnąć upgrade:

  1. Instalujemy pakiet db4.6-utils, kopiujemy z niego program db_dump;
  2. Odinstalowujemy db4.6-utils, zachowując sam db4.6;
  3. Instalujemy pakiet db4.5-utils;
  4. Cofamy wersję rpm i instalujemy pakiet poldek zbudowany dla tej wersji rpm;
  5. Wykonujemy:
    cd /var/lib/rpm
    rm __db*
    mv Packages{,.old}
    db_dump_4.6 Packages.old > Packages.dump
    db_load Packages < Packages.dump
    rpm --rebuilddb
  6. Powyższą czynność powtarzamy dla wszystkich katalogów /vservers/.pkg/*/rpm/state, które zdążyły się zaktualizować do nowej wersji, odpowiednio modyfikując pierwszą linię i do ostatniej dopisując --dbpath <sciezka_do_katalogu_state>

Kolejny problem

Ostatnim krokiem było przekonanie narzędzia vpoldek, że instalowane pakiety są dla właściwej architektury. Tutaj rozwiązaniem było dopisanie do każdego pliku /vservers/.pkg/*/rpm/etc/macros linijki:

%_host_os %_os

Voila, wszystko działa, maszyna została przebudowana. Następnym razem postaram się pozbyć irytujących komunikatów LD_PRELOAD.

Licencja, panie

Strasznie mi przykro, że niektórzy to jednak czytać nie potrafią. Zrozumiem, że jedna z drugą doda mają problem z przeliterowaniem wyrazu dłuższego niż kark czy dres, ale żeby programiści nie potrafili czytać własnych licencji?

Trafiłem wczoraj na Undeadly na wątek dotyczący złamania licencji przez deweloperów Linuksa. Podniósł się wielki rumor, kamienie leciały gęsto, do flejma włączyli się przedstawiciele obu obozów, *BSD i Linuksa. Jedni jeździli po nie do końca wolnej licencji GNU, drudzy przypominali sytuację odwrotną, która nie miała miejsca tak znowu dawno temu.

Szkoda, że nikt nie skontaktował się z autorami albo chociaż nie przeczytał diffa. Widać wszyscy zapomnieli, że specjalnie na potrzeby włączenia sterownika — pierwotnie napisanego na potrzeby *BSD — do Linuksa, cały kod został udostępniony na podwójnej licencji BSD/GPLv2. A co oznacza podwójna licencja kodu? Ano to, że można sobie dowolnie wybrać jedną z licencji, która będzie nas obowiązywać. Tak, to znaczy, że w ramach licencji GPL można sobie dowolnie usuwać treść licencji BSD z nagłówków kodu. Tak, nawet jeśli licencja BSD mówi, że nie można jej usuwać, bo rzeczona licencja nie obowiązuje.

Żeby było jeszcze śmieszniej, niemal ukamienowany i żywcem spalony na stosie bezbożnik jest jednym ze współautorów kodu. Jeszcze zabawniejszy jest fakt, że nawet gdyby kod był dostępny tylko na jednej licencji, to w ramach amerykańskiego prawa każdy ze współautorów dzieła ma prawo udostępnić je na dowolnej licencji bez konsultacji z pozostałymi (jedyne ograniczenie dotyczy tego, że nie może zmienić reguł podziału zysków z tego tytułu).

Tak, czytanie to nie jest mocna strona ludzi. Nasz Trybunał Konstytucyjny kolejny raz udowodnił, że wyobraźnia również.

Wyjątkowość PHP

Podobno PHP5 jest językiem obiektowym, niektórzy twierdzą nawet, że językiem czwartej generacji. Ja bym go nazwał językiem obiektowalnym, bo zaiste, można w nim programować obiektowo, jednak sam język ani do tego nie zachęca, ani procesu nie ułatwia. Znakomita większość funkcji bibliotecznych obiektowości zwyczajnie nie obsługuje. Ciekawsze jednak są wyjątki, które w PHP są… niemal bezużyteczne.

Autorzy języka uznali, że najważniejsza jest zgodność wstecz za wszelką cenę. Zamiast jednak przygotować moduł, który dostarczałby API zgodnego ze starszymi wydaniami i zmodernizować rdzeń funkcjonalności bibliotecznej, postanowili ciągnąć za sobą brzemię średniowiecznych początków języka. Złośliwi mówią, że wystarczy zamienić część znaków dolara na małpki i otrzymamy poprawny kod Perla, a usuwając dolary w liniach deklaracji otrzymamy zgodność ze skryptami powłoki. Trudno się dziwić, bo szerokie możliwości języka to głównie posklejane kawałki bibliotek standardowych Perla i C, pomieszane z możliwościami powłoki. Faktycznie, jeśliby dodać do siebie procentowy udział języków pomnożony przez ich generację, to PHP okazuje się stać na czele i już tylko krok dzieli go od interpretacji języka naturalnego.

Nie o tym jednak chciałem pisać. Jedną z konsekwencji zachowania zgodności jest wyjątkowość języka, przejawiające się w braku wbudowanych wyjątków. Nie mam tu na myśli klasy Exception, mówię o tym, że żadna z funkcji bibliotecznych wyjątkami nie rzuca. Zwracają magiczne wartości, ustawiają liczniki błędów, ale wyjątków unikają jak ognia. Dlaczego? Może dlatego, że przeciętny konsument API o obiektowości, wyjątkach i wzorcach projektowych ma takie samo pojęcia, jak ja o ornitologii. Dlatego właśnie uważam, że wyjątki w PHP są niemal bezużyteczne.

$f = foo();
if (foo_error())
	return false;
if (!foo_write($f, 'bar'))
	return false;
if (!foo_write($f, 'baz'))
	return false;
foo_flush($f);
if (foo_error())
	return false;
foo_close($f);
if (foo_error())
	return false;

Czy tak powinien wyglądać kod? A może tak:

$result = true;
try
{
	$f = foo();
	$f->write('bar');
	$f->write('baz');
	$f->flush();
}
catch (FooException $e)
{
	$result = false;
}
finally
{
	if ($f)
		$f->close();
}
return $result;

Żeby móc osiągnąć czytelność drugiej wersji kodu, programista musi poświęcić kilka godzin na napisanie wrapperów dla większości bibliotecznych wywołań. W przeciwnym wypadku używanie wyjątków jest bezcelowe, bo i tak na każdym kroku trzeba kontrolować zwracane wartości. Czy jest tu zaszyta jakaś głębsza logika, czy słusznie wydaje mi się, że PHP5 wygląda na zaprojektowany na kolanie?