Wielu współczesnych programistów wyraża przekonanie, że przy takiej mocy obliczeniowej optymalizacja aplikacji i w ogóle cały ten szum wokół wydajności jest zbędny. Co za problem dokupić dodatkowe podzespoły? Dla programisty żaden, gdyż już nie on za to płaci. Ale użytkownik nie bywa zachwycony zauważeniem, że jego nowiutki sprzęt nagle przymula, a już na pewno możemy spodziewać się ostrej reprymendy, gdyby dowiedział się on, że to wina "wygodnego" programisty. Wszystko ma swoje granice. Dopóki wzrost zasobożerności uzasadniony jest możliwościami i samymi założeniami projektu, których nie da się przeskoczyć, jest to w pełni zrozumiałe.
Przejdę teraz do sedna rzeczy. PHP, ASP, Java, Ruby, chcąc nie chcąc, są językami interpretowanymi z punktu widzenia maszyny. Choć występuje tam bytecode i inne tego typu pojęcia, nawet tenże bytecode nie może być przetwarzany bezpośrednio przez procesor, zatem jest to pewien wyższy poziom abstrakcji. Problem pojawia się, kiedy przenosimy różne nawyki programistyczne z języka kompilowanego do interpretowanego, nie patrząc na efekty uboczne. Przyjrzyjmy się takiej dobrze zhermetyzowanej klasie w C++:
class player { public: player(int x, int y); ~player(); void draw(); void move(); int getX(){ return x; } int getY(){ return y; } private: int x; int y; };
Widzimy tutaj dwie metody: getX() oraz getY(), których jedynym zadaniem jest udostępnianie pewnych informacji obiektu bez możliwości ich zmiany. W tym języku jest to całkiem wygodne - poprzez zapisanie ich (krótkiej) akcji bezpośrednio przy prototypie, ich kod zostanie przez kompilator wstawiony we wszystkich miejscach, gdzie są one wywołane, co da efekt, jakbyśmy zwyczajnie odwoływali się do pól obiektu (poza tym, że kompilator zablokuje wszystkie próby odczytu). Przenieśmy to teraz w realia PHP:
<?php class player { private $x; private $y; public function __construct($x, $y) { // tu rob cos } // end __construct(); public function __destruct() { // tu rob cos } // end __destruct(); public function draw() { // tu rob cos } // end draw(); public function move() { // tu rob cos } // end move(); public function getX() { return $this -> x; } // end getX(); public function getY() { return $this -> y; } // end getY(); }
Co się dzieje, kiedy wywołujemy $obiekt -> getX()? Jest to proste - PHP to język interpretowany i w pospiesznie tworzonym na własne potrzeby bytecodzie (tak, PHP od wersji 4 wzwyż też takie coś robi, tylko nie zapisuje tego na dysku) po prostu nakazuje w tym miejscu wywołanie takiej, a takiej funkcji. Samo miejsce z treścią funkcji jest odnajdywane, gdy interpreter bytecode'u dotrze do tego miejsca, później należy wykonać tam przeskok, odnaleźć w obiekcie zmienną "x", odczytać wartość, zwrócić ją, wykonać skok do poprzedniego miejsca i zapisać wartość tam, gdzie jest potrzebna. W porównaniu z C++ jest to całe mnóstwo roboty związanej z jednym tylko wywołaniem funkcji! Przy małych skryptach różnica wydajności jest niezauważalna, ale duże projekty z dziesiątkami klas, mogą (a nawet muszą) już boleśnie odczuć kurczowe trzymanie się takiej hermetyzacji.
Gwoli ścisłości podam, że tam, gdzie bytecode zostaje zapisany na HDD, także możliwe jest wyjście stosowane w C++, chociaż akurat ekspertem w budowie takich języków nie jestem, więc zostawię to komuś bardziej kompetentnemu.
Wynika z tego dosyć oczywisty wniosek, że programowanie to sztuka kompromisów. Fanatycy wzorców projektowych, poziomów abstrakcji operujących na kosmicznym poziomie, byleby zaoszczędzić te 30 minut na pisaniu kodu, są dobrzy i jakichś braków w ich wiedzy bynajmniej tu nikomu nie zarzucam. Ich kod jest także dobry, ale niestety tylko od strony teoretycznej. Programowanie, jak życie, to sztuka kompromisów (lub kompromitacji, zależnie od wykonania :)), a do przygotowania teoretycznego wypada też dołożyć świetne orientowanie się właśnie w takich duperszmitach i nielekceważenie ich. Dlatego dwa razy zastanówcie się, czy naprawdę potrzebny jest Wam ten właśnie wzorzec projektowy w tym miejscu, w takim kształcie, czy też wystarczy jakiś prostszy wariant lub nawet jakieś kosmocudo.














