Framework idealny? Wstęp

Chciałbym poruszyć dosyć głęboki a być może i kontrowersyjny temat dotyczący wizji frameworka, który byłby jak najbardziej idealny. Oczywiście moje przemyślenia są mocno subiektywne jednakże są one podparte doświadczeniem nad pracą z różnymi rozwiązaniami. Ten post to jedynie ogólny wstęp do cyklu artykułów w których pojedynczo będę traktował o różnych aspektach budowy frameworka – wybierając zawsze (moim zdaniem) najlepsze rozwiązanie.

Moja idea/wzór będzie dotyczyła frameworka w języku PHP, gdyż uważam, że obecnie nie ma dobrego rozwiązania. Z czego to wynika? Moim zdaniem jest kilka powodów:

  1. PHP sam w sobie.  W porównaniu z innymi językami takimi jak Ruby czy Python można śmiało powiedzieć, że składniowo PHP nie jest zbyt elegancki. Ponadto jego bardzo duże możliwości nie są zbyt powszechnie wykorzystywane a z innych, istotnych dziedzinach niestety nie daje rady. Bardzo często trzeba się ratować rozwiązaniami zastępczymi, które niepotrzebnie wprowadzają dodatkowy nakład pracy, zabierają moc obliczeniową i zmuszają do nauki nowych, niekoniecznie potrzebnych rzeczy.
  2. Mnogość frameworków do PHP. To wynika właściwie z tego, że istniejące rozwiązania nie są idealne i rożne osoby/grupy starają się zrobić coś swojego. Zend framework miał być odpowiedzią na ten problem, ale moim zdaniem jest on bardzo daleki od ideału. O tym za chwilę.
  3. Przejrzałe rozwiązania. Im większe community danego frameworka tym trudniej wprowadzić w nim rewolucyjne zmiany, gdyż napotykają one na opór ze strony osób dla których refactoring ich systemu nie jest opłacalny podczas gdy chcieliby mieć poprawione błędy. W związku z tym powstają niekiety nowe „major” version danego frameworka na przykładzie których widać jak bardzo twórcy zmienili tok myślenia podczas pracy nad poprzednią wersją – niestety muszą oni także brać pod uwagę istniejące community aby wszyscy byli „zadowoleni” i niestety bardzo szybko taki framework znów zmienia się w „potworka”. Przykładem takiego postępowania jest Symfony Framework a i zaryzykuję stwierdzenie, że także nowy Zend Framework. Zupełne inne podejście reprezentuje grupa, która jest odpowiedzialna za Prado Framework. Zauważyli oni konieczność zrobienia czegoś zupełnie nowego – Yii Framework i jest to rzeczywiście zupełnie inne podejście – bardzie współczesne i odpowiadające obecnym czasom.

PHP zyskał ostatnimi czasy kilka naprawdę bardzo fajnych możliwości

  1. Przestrzenie nazw (namespace)
  2. Traits
  3. Mikroserwer
  4. Funkcje anonimowe
  5. Ładniejszy zapis tablic
  6. i parę innych ciekawych rzeczy.

Biorąc pod uwagę powyższe fakty oraz mniej lub bardziej głębokie przemyślenia odnośnie idealnego frameworka doszedłem do tego co faktycznie musiałoby się w nim znaleźć aby uznać go za idealnym. Oczywiście idealnym z mojego punktu widzenia i przypominam, że dotyczy to PHP.

Cechy idealnego frameworka wg mnie:

Przyjemność programowania. 

Myślę, że programowanie jest wtedy przyjemne gdy nasza praca przekłada się bezpośrednio na to co chcemy zrobić a nie na godziny konfiguracji i rozwiązywania problemów próbując wykonać podstawowe zadania. Oczywiście z czasem można dojść do wprawy działając na zasadzie „kopiuj – wklej” ale po co w ogóle to robić? Framework powinien sobie siedzieć „w tle”, odzywać się wtedy kiedy powinien i nie kazać mi nauczyć się najpierw mówić w jego języku. Framework ma służyć mi a nie odwrotnie. Jak najbardziej pewne reguły powinny obowiązywać, które wynikają z oczywistej logiki i powinny być zautomatyzowane (w końcu to framework) ale nie wolno popadać w skrajności dotyczące całkowitej automatyzacji albo całkowitej elastyczności. Przykładem skrajności w całkowitej elastyczności jest Zend Framework. Zastosowałbym pewną analogię do złożenia samochodu:

Jeśli zastanawiałbym się nad skonstruowaniem nowego modelu samochodu a nie miałbym zaplecza inżynierów, chciałbym mieć podstawowe komponenty takie jak np rama czy silnik, to w normalnej sytuacji dostałbym kompletny silnik o konkretnych parametrach, do którego muszę powpinać kabelki i wmontowany jest on w prostą ramę. Mogę od tego zacząć i pozmieniać jeśli miałbym taką potrzebę. Natomiast programiści Zend Framework przysłaliby mi zestaw różnych kartonów z których musiałbym sobie wszystko złożyć. Rama nie byłaby skręcona odpowiednimi wkrętami bo może chciałbym ja zbić gwoździami, albo skleić kropelką. Silnik również byłby w częściach bo może życzyłbym sobie aby tłoki zamontować na dachu. Fajnie? Może i tak, ale wtedy to nie jest framework tylko zestaw różnych części z których sam sobie składam to co chcę. Na dodatek części te znajdują się na wytopionych matrycach, z ktorych interesuje mnie tylko po jednej części ale te części zależą od innych zestawów części. Problem tylko polega na tym, że ja tak ładnie nie złożę tej ramy ani nie spasuję dobrze elementów silnika – albo się jeszcze pomylę. Na dodatek zostanie mi mnóstwo dodatkowych części o które wcale nie prosiłem ale muszę je teraz odłożyć gdzieś w garażu bo nie wiem czy tak naprawdę są one mi potrzebne czy nie.

Zamiast skupić się na moim wyposażeniu wnętrza, elektronice, karoserii… siedzę nad problemami ze złożeniem podstawowych elementów. A to mi się coś zacina, a tu okazało się, że trzeba nasmarować, a to tak a to siak. Czy to powinno definiować framework? Moim zdaniem nie.

Szybkość działania

Nikt mi nie powie, że Zend Framework czy Symfony Framework jest szybki. Są dużymi, bardzo złożonymi frameworkami i funkcjonuje to bardzo prosta zasada… im więcej kodu tym więcej czasu potrzeba na jego wykonanie. Poza tym zbyt duża elastyczność, luźno powiązane komponenty sprawiają, że łączenie ze sobą rzeczy, których nie powinno się łączyć jest dosyć proste to zrobienia. Efekt jest taki, że „działa” ale „jak działa” to jest już inna historia.

Tak sobie wyobrażam stronę zbudowaną np na Zend Framework. Można? Można. Czy o to chodzi? Moim zdaniem niekoniecznie. Nie chodzi wcale o to, że Zend Framework czy Symfony Framework ma bardzo dużo różnych fajnych gotowych komponentów. To świetnie, że tak jest, ale problem polega na tym, że sam framework od wielu z nich jest bardzo uzależniony i przy każdym rozruchu musi do nich zaglądać, podnosić i przetwarzać. Dobre rozwiązanie polegałoby na tym aby sam framework składał się z porządnego, ściśle i stabilnie działającego silnika i miał w pakiecie dodatkowe komponenty które są od niego niezależne. Czy framework powinien standardowo pozwalać na to aby przewrócić swój sposób działania do góry nogami? Czy nie prościej wtedy zrobić coś od nowa? Czy nie jest to wtedy dowód na to, że to co mamy nie spełnia naszych oczekiwań? Więc może warto wybrać jakieś alternatywne rozwiązanie, które okaże się prostsze, tańsze i lepiej dostosowane do konkretnych potrzeb.

Każde z tych zadań może być zupełnie inne byleby było zgodne ze sposobem w jaki framework mógłby sobie z nim poradzić.

Gdy istnieje konkretna potrzeba framework może wziąć na „swoje barki” to zadanie jakie ma wykonać. Robi to po prostu, tak jak został stworzony. Wyobrażam sobie, że framework jest jak ciągnik ciężarówki. Wielka, potężna maszyna, w której wszystkie trybiki, idealnie spasowane i naoliwione pracują perfekcyjnie. Ktoś wcześniej tak złożony ciągnik przetestował i dopracował w najmniejszych szczegółach. Jedyne zadanie tego ciągnika to zabrać na „swój pokład” naczepę. Ta naczepa to może być dowolna rzecz, dowolny towar byleby jego łącze było zgodne z łączem ciągnika. Ten sam ciągnik może ciągnąć różne naczepy. Każda naczepa może być zrobiona przez inną firmę, która nie ma w ogóle pojęcia jaki ciągnik będzie używany do jej ciągnięcia. Dla mnie takie rozwiązanie jest idealne.

Bezpieczeństwo

Istotne jest bezpieczeństwo takiego rozwiązania. Ale jak wiadomo każdy z aspektów związanych z programowaniem stron ma inne niebezpieczne miejsca na które należy zwrócić uwagę.

  • HTML. Trzeba zwrócić uwagę na escapowanie danych. Na zamykanie danych ze zmiennych attrybutów w cudzysłowiach. Na zamienianie encji
  • Javascript – Trzeba escapować dane w inny sposób
  • SQL – Trzeba zwrócić uwagę na zabezpieczenie przed SQL injcection oraz przed podaniem nieprawidłowego typu (np string w miejsce inta)
  • PHP – Trzeba zwrócić uwagę na typowanie zmiennych, przepełnienia bufora, zużycie pamięci i inne możliwe sposoby włamania się na serwer
Pomijając fakt, że sam framework powinien być odporny na powyższe problemy to także powinien pomóc programiście w wyeliminowaniu takich problemów albo swoją specyfiką na całkowitym ich wykluczeniu. Nie chodzi o to, że programista ma być totalnie nieświadomy zagrożeń, ale nie powinien poświęcać zbyt dużo czasu na to aby to wszystko zabezpieczać. Znów analogia do ciągnika: To maszyna ma przecież odpowiedni punkt mocowania naczepy i nie pozwoli zamocować innego. Maszyna powinna mieć zabezpieczenie przed próbą ciągnięcia źle zamocowanej naczepy albo takiej która przekracza dopuszczalną masę. Kierowca nie powinien zastanawiać się czy przy próbie ruszenia przypadkiem nie urwie sobie całego tyłu. Kierowca skupia się na zadaniu jakie ma wykonać. Jakie wybrać drogi żeby było najszybciej i najtaniej. Gdzie w ogóle jechać czy brać nowe zlecenie i będzie miał czas itd. Nie ma obowiązku siedzieć i zastanawiać się czy z jego maszyną jest wszystko w porządku, czy przypadkiem zaraz nie odlecą koła w jakimś tam szczególnym przypadku. Idealny framework powinien zabezpieczać się i nakierowywać programistą na właściwy sposób tworzenia kodu (inaczej nie pozwolić działać).