set_error_handler jako elegancki sposób na bolączki z PHP

Gdy PHP powstawało nikt nawet nie śnił, że to narzędzie znajdzie zastosowanie w dużych projektach informatycznych aniżeli tylko w prostych skryptach. Pewnym tego pokłosiem jest wprowadzenie mechanizmu wyjątków (https://www.php.net/manual/en/language.exceptions.php) dopiero w wersji 5. Niestety ze względu na kompatybilność sporo wbudowanych funkcji, struktur języka takich jak np. fopen(), mail(), dzielenie przez zero etc. nie zgłasza wyjątków a E_ERROR, E_WARNING.. (https://php.net/manual/en/errorfunc.constants.php).

Jeśli zamiast tego chcielibyśmy otrzymać wyjątek lub inaczej obsłużyć taką sytuacje to trzeba customizować obsługę błędów w PHP właśnie przez set_error_handler(). Poniżej przykład zaczerpnięty z Zend Mail (zendframework/zend-mail/src/Transport/Sendmail.php)

/**
 * Send mail using PHP native mail()
 *
 * @param  string $to
 * @param  string $subject
 * @param  string $message
 * @param  string $headers
 * @param  $parameters
 * @throws \Zend\Mail\Transport\Exception\RuntimeException
 */
public function mailHandler($to, $subject, $message, $headers, $parameters)
{
    set_error_handler([$this, 'handleMailErrors']);
    if ($parameters === null) {
        $result = mail($to, $subject, $message, $headers);
    } else {
        $result = mail($to, $subject, $message, $headers, $parameters);
    }
    restore_error_handler();

    if ($this->errstr !== null || ! $result) {
        $errstr = $this->errstr;
        if (empty($errstr)) {
            $errstr = 'Unknown error';
        }
        throw new Exception\RuntimeException('Unable to send mail: ' . $errstr);
    }
}

Z tego miejsca warto przypomnieć, że gdy już się customizuje error handler to należy zadbać o zapisanie kompletnej informacji o pochodzeniu błędu (komunikat, miejsce wywołania i inne dodatkowe informacje ułatwiające debugowanie).

Więcej w https://www.php.net/manual/en/function.set-error-handler.php

Skąd biorą się wielcy programiści

Dzisiejszy wpis chciałem by był o wzorcu Remote Facade jako uzupełnienie poprzedniego wątku. Jednak nie będzie o tym bo za sprawą Pawła (tego od alpak) wpadł mi artykuł autorstwa Eduards Sizovs, link na końcu. Wyczytałem tam kilka ciekawych sugestii jak powinien wyglądać proces rekrutacji dewelopera, ale też o przeszkodach jakie mogą czyhać w rozwoju samej kariery. Skupmy się na tej drugiej kwestii oraz porozmawiajmy o tym skąd właściwie biorą się ci wielcy programiści.

Każdemu z nas zależy by być w czymś dobrym, by stać się mistrzem w swojej profesji, by okiełznać te wszystkie przeszkody rzucone po drodze i odnieść sukces. Problem w tym jak tego dokonać, kiedy bardziej jesteśmy skupieni na dostarczaniu oprogramowania a w mniejszym stopniu na własnym rozwoju. Wydaje mi się, że najbardziej istotne jest uświadomienie sobie w tym wszystkim, że

“Wielcy programiści są wychowywani a nie zatrudniani”

Wynika z tego, że każdy ma szanse. Trzeba zdekomponować problem na mniejsze składowe. Znaleźdź mentora. Zaplanować swoją karierę…hmm wydaje się to nazbyt proste… Bo co z emocjami? Co z zwątpieniem w swoje możliwości lub wypaleniem? Jak poradzić sobie gdy czujesz, że projekt Cię przerasta? Cóż…dobrze wtedy być w takim zespole, w którym tworzy się miejsca pracy do rozwoju zamiast szukać tego wielkiego programiste…

Link do oryginalnego wpisu https://sizovs.net/2019/04/10/the-best-developers-are-raised-not-hired/

Data Transfer Object – Obiekt Transferu Danych

Co raz cześciej przychodzi mi pisać aplikacje w środowisku rozproszonym to też dzisiejszy, inauguracyjny wpis będzie o Data Transfer Object – Obiekt Transferu Danych, zwany także przez niektórych jako Value Object. W skrócie

Obiekt przenoszący dane pomiędzy procesami, umożliwiający zmniejszenie ilości wywoływanych metod M. Fowler

Tylko co się za tym kryje? Jednym z wielu problemów używania obiektów rozproszonych jest ich koszt wywołania. To czas, który trzeba ponieść, by wywołać zdalną metodę. W przypadku wywołań we wspólnej przestrzeni adresowej danego procesu, nie musimy przejmować się tym czasem. Natomiast sytuacja radykalnie się zmienia, kiedy potrzebujemy wywołać metodę na innym procesorze, w szczególności gdy ów procesor znajduje się na drugim krańcu kuli ziemskiej.

Jednym ze sposóbów radzenia sobię z tym problem jest zmniejszenie ilości wywołań takich metod. Można do tego podejść po przez przesłanie większej ilości danych niż jest to konieczne za jednym razem. Nie jest to jednak takie proste w implementacji. Niektóre języki programowania jak np. Java wymuszają zwrócenie tylko jednej wartości. Dlatego tutaj z pomocą przychodzi nam wzorzec Data Transfer Object, który z pozoru wygląda jak klasa mająca jedynie swoje pola, akcesory i mutatory. Jednakże dodatkowo owa klasa wzbogacana jest o serializacje

Serializacja

To właśnie dzięki niej, DTO jest w stanie przesłać całą swoją zawartość przez sieć w jednym wywołaniu. Natomiast konkretny używany format zapisu zależy już od programów. Wiele języków programowania jak np. PHP czy Java posiadają gotowe do tego mechanizmy. Trzeba jednak pamiętać, aby zarówno klient jak i serwer używały tego samego mechanizmu. Pewnym dylematem jest czy wybrać serializacje do postaci binarnej czy tekstowej np. XML, JSON. Kuszące jest to drugie rozwiązanie ze względu na łatwość odczytu, ale wymaga to większej przepustowości. Innym problemem jest synchronizacja obiektów transferu danych pomiędzy komunikującymi się stronami. Gdy serwer zmienia dane, taka aktualizacja powinna zajść także po stronie klienta…w teorii. W praktyce po prostu dostaniemy błąd.

Jak utworzyć taki obiekt DTO ?

Zdaniem Fowlera takie obiekty nie powinny być częścią dziedziny, ale też obiekty dziedziny nie powinny być zależne od obiektów transferu danych (bo struktura tych drugich może się zmieniać wraz ze zmianami formatów przesyłanych danych). Tutaj Fowler sugeruje użycie “obiektów grupujących” / “asemblerów“, czyli obiektów tworzących DTO używajac interfejsów modelu dziedziny. Takie obiekty grupujące przypominają wzorzec Mapper, mapują obiekt dziedziny na obiekt transferu danych.

Na zakończenie, warto nadmienić, że DTO całkiem fajnie współpracuje z innym wzorcem – Remote Facade, ale o tym kiedy indziej…

Więcej informacji na ten temat w ksiażce “Architektura Systemów Zarządzania Przedsiębiorstwem. Wzorce projektowe“. M. Fowler.