Inżynieria wewnętrzna struktury RAD... jako programista PHP z Nooku

Opublikowany: 2022-03-11

Każdy ma swój własny zestaw narzędzi. Jako programista PHP, jednym z moich ulubionych jest framework Rapid Application Development o nazwie „Nooku”. Według słów grupy programistów: „Nooku jest bardziej zestawem narzędzi do tworzenia stron internetowych niż frameworkiem”.

Jeśli go nie znasz, spójrz. Jest to projekt typu open source, który intensywnie wykorzystuje akceptowane w branży wzorce projektowe do tworzenia wysoce złożonych aplikacji, które można łatwo rozszerzać i ponownie wykorzystywać (początkowo stworzone przez jednego z wiodących programistów Joomla!). Po wyjęciu z pudełka Nooku oferuje wiele narzędzi do szybkiego tworzenia aplikacji, które pomogą szybciej rozpocząć projekty. Mała, ale mocna próbka:

  • Domyślna implementacja MVC, w której wszystko, co musisz zrobić, to napisać układ (to mnie zafascynowało)
  • Dostępność HMVC od zaraz
  • Obsługa różnych formatów wyjściowych, takich jak JSON i XML, dla wszystkich danych (tj. udostępnij swój interfejs API w ciągu kilku minut)
  • Domyślne wdrożenia administracyjne i front-endowe

Sednem Nooku jest zasada projektowania „Kompozycja ponad dziedziczeniem” (w rzeczywistości jest to pierwsza koncepcja na stronie wprowadzającej Nooku. W jednym wierszu: powinieneś skomponować (lub zsumować) funkcjonalność wielu obiektów, aby stworzyć pewne rodzaj obiektu złożonego, zamiast polegać na podklasach.

Wizualizacja składu nad zasadą dziedziczenia w szybkim tworzeniu aplikacji PHP (RAD).

Ta zasada pozwala pisać mniej kodu i często prowadzi do całkiem eleganckich rozwiązań. Jak dokładnie jest promowany? Cóż, na poziomie kodu najlepsze przykłady pochodzą z użycia domieszek i identyfikatorów zasobów/usług. Spójrzmy.

Mixin

Przed PHP 5.4 język nie miał pojęcia o cechach . Są to struktury podobne do klas, które „używane” przez obiekt zapewniają pewien rodzaj funkcjonalności (podobnie jak w przypadku dziedziczenia wielokrotnego). Nooku rozwiązuje ten problem od lat (od PHP 5.2) za pomocą Mixina .

Mixin nie tylko umożliwia komponowanie obiektów razem, ale także dodaje metody każdego mieszanego obiektu do interfejsu obiektu złożonego. Obiekt używający domieszki wydaje się „dziedziczyć” metody domieszki obiektu.

 /** * Mixin an object * * When using mixin(), the calling object inherits the methods of the mixed * in objects, in a LIFO order. * * @param KMixinInterface $object An object that implements KMinxInterface * @return KObject */ public function mixin(KMixinInterface $object) { $methods = $object->getMixableMethods($this); foreach($methods as $method) { $this->_mixed_methods[$method] = $object; } // Set the mixer $object->setMixer($this); return $this; }

Prawie wszystkie obiekty w Nooku mają tę możliwość, ponieważ rozszerzają klasę bazową KObject, która zdefiniowała metodę mixin .

Główne klasy w architekturze kontrolera Nooku również wywodzą się od KObject. Abstrakcyjnym kontrolerem jest klasa KControllerAbstract i po przyjrzeniu się widać, że od razu korzysta z możliwości mieszania. Za każdym razem, gdy tworzona jest instancja tej klasy, funkcje KMixinCommand i KMixinBehavior są natychmiast dodawane do jej interfejsu. W związku z tym każdy kontroler w Nooku składa się z funkcji zarządzania łańcuchem poleceń i zachowaniem poprzez odpowiednie obiekty.

Dlaczego K przed wszystkimi nazwami klas? Główna biblioteka Nooku nosi nazwę kodową „Koowa”.

Wracając do kontrolera Nooku: klasa KMixinBehavior przechowuje wszystkie elementy, aby umożliwić KControllerAbstract ładowanie określonych zachowań w czasie wykonywania. Strategie behawioralne to klasy opisujące proces lub logikę, które mogą być oddzielone i używane przez inne klasy (np. edytowalne, porządkowalne). KMixinBehavior jest dość prosty i ma tylko cztery metody: getBehavior, hasBehavior, addBehavior i getBehaviors. I to wszystko, czego potrzebujemy, aby dać obiektowi zdolność radzenia sobie i zawierania różnych strategii behawioralnych.

Podobnie KMixinCommand ma tylko trzy metody: getCommandContext, getCommandChain, setCommandChain. Jeśli nie zgadłeś, te trzy metody zapewniają KControllerAbstract możliwość zaimplementowania łańcucha poleceń, ale pozwalają to zrobić w czasie wykonywania.

Możesz myśleć o tym mieszaniu jako o prostym dodawaniu arytmetycznym:

Przedstawienie mieszania Nooku jako dodawania arytmetycznego w tym szybkim frameworku do tworzenia aplikacji.

Daje nam interfejs, który wygląda tak:

Tak wygląda wynikowy interfejs w tym konkretnym frameworku RAD.

Z definicji Klasy abstrakcyjne mają być rozszerzane, a więc dzięki magii dziedziczenia wszystkie obiekty będące dziećmi lub instancjami KControllerAbstract zyskują również możliwość dodawania zachowań i łańcucha poleceń w czasie wykonywania.

Brzmi nieźle. Ale co to właściwie oznacza? Krótko mówiąc, Nooku zapewnia złożoną funkcjonalność; oznacza to, że Nooku umożliwia modularyzację funkcjonalności i komponowanie funkcjonalności między modułami w czasie wykonywania.

Te dwa przykłady służą do zademonstrowania składu. Służą również do zademonstrowania wsparcia struktury Nooku RAD dla dalszego składu w jego rdzeniu. To ważna zaleta. Metody dodane do KControllerAbstract powyżej obsługują „Wzorzec projektowania strategii”, dając programistom narzędzia do enkapsulacji tego, co się zmienia, zanim zostanie napisany jeden wiersz kodu. Fakt, że metoda mixin() jest częścią każdego rozszerzenia KObject oznacza, że ​​można łatwo zdefiniować i dodać inne interfejsy zarządzania behawioralnego do większości obiektów w czasie wykonywania.

Identyfikatory i lokalizatory usług i zasobów: Oddziel nazwę mojej klasy od mojego obiektu

Identyfikatory i lokalizatory usług i zasobów w Nooku zapewniają również potężne wsparcie w separacji obaw.

Przyjrzyjmy się ponownie KObject, ale także KService. Większość rzeczy w Nooku możemy traktować jako usługę lub zasób i jako takie tworzyć i przesłuchiwać je w dokładnie ten sam sposób.

Pomyśl o usłudze jako o czymś, z czego otrzymujesz zasób. Wszystkie usługi są zasobami, ale nie wszystkie zasoby są usługami

Kiedy idziesz do sklepu spożywczego i kupujesz produkt, myśl o sklepie jako o Usłudze, tj. zbiorze przedmiotów, które możesz B wierszować; a produkt jako Zasób, tj. pojedyncza logika przedmiotu/rozwiązania, która może być:


  • przyjrzał się konkretnie ( odczytaj ) (np. patrząc na puszkę zupy pomidorowej)
  • poruszał się po sklepie ( E red.) (np. przenieś zupę do alejki z produktami)
  • dodane lub usunięte z inwentarza sklepu (Dodaj i Usuń) (np. dodaj nowy rodzaj zupy i pozbądź się pomidora)

Idąc dalej tym przykładem, wyobraź sobie, że sklep spożywczy ma dział franczyzy i chcesz prowadzić biznes. W takiej sytuacji Serwis jest działem franczyzy, a zasobem jest sklep spożywczy, który kupujesz. Jest to w dużej mierze klasyfikacja kontekstowa. Jako całość jest to znane jako wzorzec akcji BREAD (zobaczysz każdy z nich reprezentowany między KControllerService i KControllerResource z przedrostkiem '_action', tj. _actionRead()).

Model może być usługą, obiekt tabeli może być traktowany jako usługa, konkretna triada MVC jest instancją jako zasób lub usługa, podczas gdy konkretny rekord wynikający z przesłuchania usługi może być traktowany jako zasób.

Każdy obiekt w Nooku jest kompozycją obiektów, w której każdy z nich zawiera odniesienie do usług, które powstały w całej aplikacji w „kontenerach usług” oraz metodę dostępu do usług o nazwie getService(). Wszystko, czego wymaga metoda KObject::getService(), to przekazanie prawidłowego identyfikatora zasobu, który zwróci usługę gotową do użycia.

W szybkim rozwoju aplikacji PHP, identyfikatory zasobów dają nam potężny sposób na oddzielenie tworzenia instancji obiektu od nazwy jego klasy, a tym samym zapewniają aliasy dla tej identyfikacji. Ma to istotny wpływ na łatwość utrzymania aplikacji. Poprzez aliasowanie programista może zmienić klasę używaną przez każdy obiekt, który ma instancję o podanym identyfikatorze, dodając jedną linię kodu za pomocą KService::addAlias().

Przykładem znanego nam identyfikatora zasobu jest URI lub Uniform Resource Identifier:

Przykładowy identyfikator zasobu w tym samouczku dotyczącym struktury Nooku RAD.

To są wszystkie informacje potrzebne KService do zlokalizowania i załadowania odpowiedniej klasy. Te elementy są zgodne z konwencjami nazewnictwa i rozmieszczania klas Nooku, które zapewniają przewidywalność rozmieszczania i tworzenia instancji. Powyższy przykład identyfikatora (com://site/user.database.table.user) próbuje załadować plik /components/com_user/databases/tables/user.php, który ma nazwę klasy ComUserDatabaseTableUser. Nawiasem mówiąc, jeśli plik nie istnieje, framework da ci domyślny obiekt tabeli i zbuduje go w oparciu o nazewnictwo baz danych i konwencje schematu identyfikatorów (to mnie jeszcze bardziej zainteresowało). Jak wspomniano wcześniej, KService pozwala również na ustawianie aliasów dla twoich identyfikatorów. Korzystanie KService::setAlias('maindbaseadapter','com://admin/default.database.adapter.mysqli') ; pozwala nam załadować obiekt db za pomocą KService::getService('maindbaseadapter') .

Daje nam to rozdzielenie, o którym mówiliśmy, i zapewnia wyraźną przewagę w utrzymaniu i rozbudowie naszych aplikacji. W razie potrzeby możemy tworzyć aplikacje inne niż „witryna” i „administrator”, a dzięki opisanym tutaj identyfikatorom możemy z łatwością korzystać z usług znajdujących się w innych aplikacjach, aby pomóc naszym rozwiązaniom w spełnieniu ich wymagań. Ponownie, jest to kolejny przykład tego, jak Nooku zapewnia programistom PHP i RAD oraz zespołom obsługę kompozycji nie tylko pojedynczych obiektów klasy, ale całych usług i aplikacji… za darmo.

Podsumowując

Z kompozycją nad dziedziczeniem w jego sercu; inteligentne, istniejące wcześniej kompozycje i struktury, które istnieją, aby wspierać kolejne amalgamaty; i bezpłatna architektura zorientowana na usługi z opisanymi tutaj identyfikatorami, Nooku zapewnia potężny framework RAD ze znaczącym przewagą nad dowolnymi narzędziami programistycznymi PHP.