15 07 2010

Fundament, droga przez mękę

Każdy programista w PHP powinien stworzyć swoją własną bibliotekę (lub framework). W niniejszym artykule postaram się przedstawić dlaczego takie stwierdzenie pojawiło się na wstępie, by przejść do wstępnego szkicu biblioteki Underscore. Część stwierdzeń pochodzi z doświadczenia osobistego natomiast część z doświadczeń innych.

kategoria: Tworzymy bibliotekę autor: Michał Juszczak

Każdy z nas od czegoś zaczynał, jak przebiega standardowa ścieżka? W jaką stronę podążamy przy projektowaniu aplikacji. Cały zarys stał się podwaliną do budowy własnego frameworka własnej biblioteki.

Jak każdy zaczyna

Noworodek zaczyna od podstawowego: echo „Hello World”; By następnie uczyć się nowych rzeczy, początki są trudne. W okresie niemowlęcym, dla każdej akcji wszystko znajdowało się w pojedynczym pliku. Pliki typu index.php , about.php etc. zawierały w sobie kontrolę sesji, autoryzację użytkownika, kod HTML itp. większość kodu była powielona w każdym pliku. Cała logika, wygląd, kontrola powodowała nadmierny przerost. Nie wspominając o drobnych modyfikacjach, które wymagały stosunkowo dużych nakładów pracy. Następnie wiek dziecięcy. Programista zaczyna wydzielać podobne fragmenty, tworzy pliki typu session.php, db.php, auth.php i w razie potrzeby załącza je do danych akcji. Tutaj programiści dorastają, zaczynają podglądać rozwiązania innych, ciekawi świata budują swoje doświadczenie i stają się młodzieżą. Niestety, część pozostaje w tym „wieku”. Zamiast tworzenia oddzielnych plików na każdą akcję, powstają proste kontrolery typu instrukcja switch, parametr przekazany do pojedynczego pliku powoduje znowu pomniejszenie objętości kodu poprzez załączanie podstawowych modułów do wykonania akcji.

Dojrzewanie jest bolesne i wielu nie dotrze do tego etapu. Dojrzałość, tak możemy nazywać umiejętność tworzenia zaawansowanych kontrolerów, korzystania z plików konfiguracyjnych, obsługi błędów, a przede wszystkim wyraźnym podzieleniu logiki aplikacji. Tak powstają...

Frameworki, które

...są użyteczne, poznajemy ich funkcje i metody, by obsługiwać bazę danych, szablony, grafikę. Nie trzeba znać dokładnie języka PHP, między innymi: obsługi sesji, bezpieczeństwa. Wszystko to robi za nas framework, nie trzeba się głowić nad wieloma problemami które występowały w etapach dojrzewania. Teoretycznie pisanie stron za pomocą takich narzędzi jest szybsze i podobno przyjemniejsze. Dzięki nim można nauczyć się podstaw programowania obiektowego – większość z nich wymusza to na nas.

Jednakże często pojawiają się trudności taki jak brak jakiejś funkcjonalności. Wówczas szukamy pluginów, proponowanych rozwiązań, lub też sami próbujemy dodać nową klasę (tutaj można napotkać opór). Pojawiają się także inne problemy:

  • Może być bezpieczeństwo – szeroko rozprzestrzeniony wśród programistów framework przyczynia się do wyszukiwania dziur które umożliwiają włamanie.
  • Nadmierne rozbudowanie – pakiet plików zajmuje na serwerze ponad 1-2 MiB. Mimo, że tylko część jest załączana do podstawowego pliku powoduje to wzrost zajęcia pamięci RAM przez wykonywany skrypt.
  • Konfiguracja w różnych miejscach – każda klasa ma plik konfiguracyjny w innym miejscu, często dane konfiguracyjne pojawiają się w różnych plikach. Można przegapić jakąś istotną rzecz, lub co gorsza nie wiedzieć, że można ją zmodyfikować.
  • System szablonów – to mnie boli najbardziej, wręcz nienawidzę mieszania kodu PHP z HTML. Przekazując wygląd do modyfikacji przez grafika/webdesignera mogę się narazić się na usunięcie istotnych fragmentów kodu lub lekkie zmodyfikowanie kodu PHP (co jest gorszym przypadkiem do wykrycia). Nie popieram nawet instrukcji zapisanych w stylu XML wklejanych do kodu HTML, które następnie Framework przetworzy do kodu PHP.
  • Bałagan lub nadmierne rozbuchanie systemu plików – utrudniający życie nadmiar katalogów.

Jeżeli ktoś zaczął przygodę z PHP od etapu noworodka i dotarł do przełomu młodzież/dorosły zna ten język na poziomie dobrym i na pewno ma przygotowanych kilka lub nawet kilkanaście plików typu biblioteka najpotrzebniejszych klas/funkcji.

Przeglądając dokumentacje gotowych rozwiązań, można stwierdzić, że czegoś im brakuje, lub też nie podoba się sposób ich obsługi. To prowadzi do prób stworzenia swojego frameworka.

Poznanie wzorców i dobrych praktyk

Mamy stworzoną swoją pierwszą wersję frameworka, często jest to zlepek wcześniej przygotowanych i wykorzystywanych przez nas bibliotek funkcji. Przygotowany jest zarys struktury katalogów, klas i działania. Zastanawiamy się czy można coś dodać.

Przeglądamy inne frameworki od strony kodu, sprawdzamy ich możliwości, kopiujemy i modyfikujemy kod. W wielu miejscach zastanawiamy się „Dlaczego?” oraz „O co w tym fragmencie chodzi?”. Szukamy porad na forach, czytamy fachową literaturę. Chcemy stworzyć frameworka o którym usłyszy Świat.

To jest duży plus. Ulepszamy swój warsztat, uczymy się, uczymy i jeszcze raz uczymy. Dowiadujemy się co to są wzorce, tworzymy dokumentację kodu (w końcu robimy framework dla wszystkich), upiększamy kod. Nie chcemy wydać produktu, który przyniesie tylko wstyd.

Testowanie i narzędzia

Mamy swoją bibliotekę. Zabieramy się za tworzenie strony z jej wykorzystaniem. Szablon przygotowany, struktura katalogu również, zapisujemy index.php z wprowadzonym podstawowym kontrolerem, uruchamiamy i...

(do) Mamy błąd w linijce xx w pliku yy. Zaglądamy do źródła, szukamy błędu, wykorzystujemy funkcje print_f, var_dump, echo itp poprawiamy uruchamiamy i... (while error===true)

Nie mamy błędów, straciliśmy bardzo dużo czasu, jesteśmy zadowoleni z poprawy błędów, uruchamiamy, ale aplikacja nie działa tak jak chcemy. Inne wartości, podejrzane działanie, nie wykonywanie kodu w niektórych miejscach. Na myśl o echo i print_r zaczyna się burzyć krew. Trzeba znaleźć jakiegoś odpluskwiacza, znowu czas stracony na wyszukanie odpowiedniego i na końcu testowanie, ale udało się. Szukamy...

Jeżeli ktoś zagłębił się w literaturę fachową lub porady może ten fragment opuścić.

Operacja się udała, pacjent nie przeżył, czyli praktycznie wszystko ok, ale nie przewidzieliśmy czegoś tam, i tego że można zamiast daty urodzin wpisać imię ulubionego chomika. Aplikacja się wysypała. Pamiętacie sławny wzór na deltę? Nauczyciel informatyki wbijał do głowy informację, o tym, że mimo iż wy tego nie wpiszecie, użytkownik może wpisać. Trzeba przewidzieć wszystkie możliwości. Zagłębiamy się w testy jednostkowe.

Mamy rozbudowany warsztat, wiedzę wszystko powinno być ok. Stronę wrzucamy na serwer. Wchodzimy, działa. Sprawa praktycznie zamknięta, do czasu. Zaczynają się pojawiać problemy z obciążeniem serwera, odczytem plików, zapisem, czasem wykonania strony. Po prostu strona dobrze działała jak testowaliśmy ją jako pojedynczy użytkownik, jednakże przy większej ilości żądań zaczyna coś nie grać.

Serwisowanie

Mamy pierwszą stronę za sobą. Działa bo działa. Jak to w życiu bywa zapał maleje wraz z upływającym czasem i rosnącym doświadczeniem. Mamy masę błędów, poprawek, myślimy, że coś tam można jeszcze poprawić. Kod który napisany był rok temu wygląda aktualnie tragicznie, zadajemy sobie pytanie „Czy ja to napisałem?” lub „Co autor miał na myśli”.

Nasz framework nie jest doskonały.

Modyfikujemy go, poprawiamy błędy, dodajemy nowe pomysły, dodajemy nowe funkcjonalności by po chwili je usunąć. Powstaje wiele wersji Frameworka. Zdarza się że w pewnym momencie zmieniamy nawet jego nazwę. Nasza biblioteka ewoluuje.

Wypracowanie własnego stylu

Po przekroczeniu tej ścieżki, napisaniu kilku bibliotek, sprawdzeniu innych dochodzimy do tego ze poprawiamy funkcje pochodzące od zewnętrznych autorów, sami wiemy co nam się przyda, co będzie lepiej działać, co jest niepotrzebne. Modyfikujemy klasy, przenosimy metody do innych.

Dochodzimy do wniosku, że tworzymy framework dla siebie a nie dla Świata. Ustalamy własny wygląd kodu, odpowiednie wcięcia, docblocki, testy, zmniejszamy/zwiększamy objętość plików. I zastanawiamy się czy to wszystko.

Tutaj dochodzimy do rozstajów:

  • minimalizacja biblioteki – jak najmniej funkcji w podstawowych klasach,
  • rezygnacja z wielu wzorców: np. powrót do pisania proceduralnego, rezygnacja z wzorców projektowych, zmiana podejścia do programowania obiektowego,
  • napisanie nowego frameworka,
  • zmiana języka programowania i tworzenie w nim nowego frameworka.

To jaką ścieżkę wybierzemy zależy wyłącznie od nas. Jedno jest pewne zyskaliśmy doświadczenie, które nie będzie tylko nauką PHP, ale wiedzą z programowania.

Dodaj komentarz:

Komentarze podlegają moderacji, nie dopuszczam komentarzy spamujących, z wyzwiskami, wulgaryzmami, oszczerstwami. Rozumiem przez to również nie akceptowanie komentarzy, których treść jest prawnie zabroniona. Pozostałe komentarze, nawet takie które będą sprzeczne z moimi poglądami są akceptowane. Należy czekać na akceptację, każdy komentarz zostanie sprawdzony przeze mnie a następnie ukaże się na stronie.

Komentarze:

Ostatnie wiadomości:

Ostatnie komentarze:

  • (2010-10-26) Nie wiem, że metody statyczne są szybsze i nie wiem, skąd bierzesz tak...
    NEWS Tworzenie biblioteki Underscore: Nie wiem, że metody statyczne są szybsze i nie wiem, skąd bierzesz takie rewelacje, bo odkąd pamiętam, zawsze było na odwrót. Nawet przed chwilą zrobiłem szybki benchmark i nic się nie zmieniło w tym względzie. Ponadto z tego, co piszesz (zwłaszcza o krótkości kodu), wydaje mi się, że nie rozumiesz sensu programowania obiektowego. Robienie metod typu wordCount() to głupota do kwadratu - przecież po to się robi obiekty, by te metody pracowały w ich kontekście i wykonywały coś na nich, a nie działały tak sobie w próżni. O wiele lepsze wyniki wydajnościowe osiągniesz dobrymi algorytmami i odpowiednią architekturą, a nie robieniem sobie pseudoobiektowego śmietnika. Ponadto co z takimi kwestiami, jak niezawodność i elastyczność? Zyx (grrrr, mój nick jest trzyliterowy!)
  • (2010-10-26) Niestety, takie rozwiązanie jest wybitnie niepraktyczne. Już to przera...
    NEWS Konfiguracja klas i obiektów - metoda settings: Niestety, takie rozwiązanie jest wybitnie niepraktyczne. Już to przerabiałem spory kawałek czasu temu przy okazji tworzenia Open Power Libs 2.0 i do dziś odbija mi się to czkawką. Po pierwsze, używasz do tego elementów statycznych, czyli już na wejściu utrudniasz sobie testowanie i wprowadzasz elementy niedeterminizmu, które mogą być źródłem podobnych problemów, jakie powoduje "global". Po drugie, Twoja funkcja do ładowania konfiguracji też jest niepraktyczna, bowiem wymaga uprzedniego załadowania wszystkich możliwych klas nawet, jeśli ich nie używamy, gdyż inaczej oberwiemy wyjątkiem. Dobrym, sprawdzonym rozwiązaniem jest idea wstrzykiwania zależności. PS. Masz u mnie minusa za nałożenie limitu min. 5 znaków na długość nicka, który jest idiotyczny, jako że jest całkiem sporo osób, które mają czteroliterowe nicki, a trzyliterowe takie, jak mój, też się trafiają. Zyx (grrrr, mój nick jest trzyliterowa!!!)

Kategorie:

Tworzenie stron internetowych Tworzymy bibliotekę Zarządzenie przedsiębiorstwem Blog Zarządzanie jakością