W niniejszym artykule opiszę co będzie składać się na bibliotekę (bibliotekę a nie frameworka!). Przedstawię założenia, projekt budowy, oraz poszczególne rozwiązania. Dokładne opisy klas składających się na bibliotekę znajdą się w późniejszych artykułach.
Artykuł podzielony na kilka części tematycznych. Zachęcam do dopisywania komentarzy, może część będzie na tyle konstruktywna, że uwzględnię je w projekcie. Aktualnie biblioteka jest w fazie ukończenia wersji 0.6. Biblioteka jest tworzona, poprawiana i wykorzystywana w innych projektach od kilku lat. Aktualnie postanowiłem przebudować i zmniejszyć objętościowo cały rdzeń biblioteki.
Część osób wie, że: funkcje są szybsze od klas oraz metody statyczne są szybsze od metod wywołanych z obiektów. Różnice te są praktycznie niezauważalne przy pojedynczym wywołaniu. Jednakże przy dużym natężeniu ruchu na stronie możemy stracić/zyskać wiele zasobów sprzętowych w zależności od budowy aplikacji. Najlepszym rozwiązaniem pod względem szybkości jest stworzenie biblioteki funkcji, jednakże wówczas nie jesteśmy w stanie ukryć części rozwiązań. Metody klas posiadają parametr private lub protected, dzięki temu ukrywamy to, czego nie chcemy by programista używał. Tak więc obieramy kierunek na funkcje w klasach.
Wybór pada na klasy które posiadają metody statyczne. Dlaczego? Moja odpowiedź brzmi: Po co tworzyć obiekt by przetworzyć string i skrócić go do x wyrazów. Nie tylko uzyskamy na szybkości wywołania, co również na objętości kodu. Użycie w kilku/kilkunastu miejscach:
$string = transform::wordCount($string, 10);
Jest krótsze o 31 znaków niż poniższe:
$transform = new transform();
$string = $transform->wordCount($string, 10);
I wydaje mi się że kod jest czytelniejszy.
Decyzja podjęta – wszystko klasy będą miały metody statyczne (w końcu będą tylko zbiorem funkcji), poza klasą bazy danych, ale wyjaśnienie opiszę później.
Funkcje o podobnym działaniu będą pogrupowane w odpowiednie klasy –
tak więc, zmiany ciągu znaków będą się znajdować w klasie np. Format;
sprawdzanie poprawności danych w klasie Validation;
działania na szablonach w Template; itp. itd.
Klasy jak w najmniejszym stopniu zależne od siebie –
i nie chodzi wyłącznie o możliwość ustalania w parametrach powiązań dopisywania
klas pomocniczych, ale o całkowitą enkapsulację. Klasa ma być niezależna,
ma nie odwoływać się do innych klas, wszystko zawarte w jednym.
Niestety, nie da się tego rozwiązać w 100%. Powstaną min.2 klasy, które
będą wymagane przez inne. Będą to klasy Exception, czyli przechwytywanie wyjątków
wraz z logowaniem błędów oraz Core(Base) zawierającą metody wspólne dla wszystkich klas,
np. sprawdzanie istnienia pliku.
Każda klasa powinna mieć możliwość zmiany ustawień – najlepiej żeby można
było je przekazać jako metodę zmiany ustawień, oraz możliwość przechowywania
ustawień w pliku.
Jak najmniejsze pliki – tego nie muszę tłumaczyć.
Wszystko ładnie upakowane w paczki – możliwość tworzenia i obsługi archiwów PHP - PHAR.
Ułatwi to tworzenie aktualizacji, uporządkuje miejsce na dysku. Łatwiej wgrać pojedynczy pliki
klient.phar zawierający pliki php, html, xml; niż kilka plików do odpowiednich katalogów.
Przejrzysta struktura katalogów – Trzy podstawowe katalogi: biblioteka, dane publiczne
(pobierane bezpośrednio przez przeglądarkę pliki css, js, grafika), oraz dane strony.
Ostatni katalog dzielący się na kilka: konfiguracja, baza danych, pliki html/php, cache, logi.
Struktura wyglądająca następująco:
├─── _ (biblioteka)
├─── public (dane js, css itp)
└─── private (dane strony)
├─── cache (cache)
├─── conf (konfiguracja)
├─── db (baza danych – sqLite)
├─── data (pliki php/html – przetwarzane)
└─── logs (logi)
Poniżej, bez zbędnego opisywania przedstawiam proponowany (i wstępny podział na klasy),
a także strukturę katalogów. Jedyną nie statyczną klasą jest klasa bazy danych, natomiast
częściowo statyczną (logi i błędy) klasa przechwytywania wyjątków.
Docelowo każdy katalog będzie paczką PHAR, którą będzie łatwiej aktualizować.
├─── _ (core)
│ ├─── _.php (podstawowe funkcje)
│ ├─── _C.php (kontroler)
│ ├─── _D.php (obsługa bazy danych)
│ ├─── _E.php (wyjątki i błędy)
│ ├─── _F.php (formatowanie tekstu)
│ ├─── _Q.php (generowanie zapytań SQL)
│ ├─── _R.php (generowanie RSS)
│ ├─── _S.php (sesje)
│ ├─── _T.php (szablony)
│ ├─── _U.php (utf8)
│ └─── _V.php (walidacja)
│
└─── _H (helpery)
├─── _H_C (captcha)
├─── _H_H (helpery ogólne)
├─── _H_L (generator Lorem)
├─── _H_I (instalacja i konfiguracja)
├─── _H_P (zarządzanie użytkownikami)
├─── _H_R (wyrażenia regularne)
└─── _H_T (testowanie klas - unit test)
To jest wstępna budowa. Główny katalog (core) prawdopodobnie się nie zmieni. Jedynie nad czym się zastanawiam to wycięcie _Q.php i _R.php i przeniesienie do Helperów jako klas nie będących tak często w używaniu. Brakuje mi również jakiegoś pliku bootstrap.php konfigurującego wstępnie bibliotekę. No i helpery, nie wiem czy nie rozbić ich na mniejsze.
Aktualnie biblioteka (w fazie produkcji) zajmuje około 400kiB, po usunięciu komentarzy, wcięć itp pozostaje około 120kiB kodu. Plik PHAR zajmuje ok 60kiB. Tak więc pracuję i skracam dalej.
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.
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ść?