Dynamiczny serwer aplikacyjny w C++ platforma LEFTHAND
Projekt LeftHand- Historia Połowa 1998r. „system sieciowych notatek”- Corporate Office 0.1 Początek 2001 LeftHand 1.0 i aplikacja Firma LeftHand 2.0 ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Serwer aplikacyjny Serwer aplikacyjny to zestaw technologii (tzw framework) służących do tworzenia serwerów dla aplikacji biznesowych. Funkcjonalność: obsługa protokołów sieciowych praca wielowątkowa lub wieloprocesorowa współpraca z bazami danych, ze wsparciem dla transakcji modularyzacja kodu biznesowego Dynamiczne serwery aplikacyjne pozwalają na łatwe dodawanie funkcjonalności do istniejących aplikacji biznesowych. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Dynamiczne aplikacje Aplikacje biznesowe mają najczęściej dwie cechy: są złożone i muszą być rozwijane w sposób ciągły. Takie aplikacje muszą być podzielone na osobne moduły (które można rozwijać w sposób względnie niezależny) Jednym z podstawowych postulatów jest w tej sytuacji możliwość osobnej kompilacji modułów i ich późniejszej konsolidacji. (C) pliki zawierające kod źródłowy zostają skompilowane do postaci bibliotek, które są konsolidowane przez linker w gotowy program. Biblioteki mogą też być ładowane dynamicznie do kodu programu. Wykorzystując to, możemy podmienić biblioteki nawet w trakcie działania programu. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Dynamiczne aplikacje cd Jeśli znaliśmy sygnaturę funkcji z biblioteki w trakcie kompilacji naszego kodu, to kompilator i linker poradzą sobie z połączeniem naszego programu z biblioteką. Dopóki nie będziemy usuwać funkcji z biblioteki, a nowe parametry będziemy dodawać na końcu, to kolejne wersje biblioteki będą zgodne z poprzednimi i nasze programy będą działać bez rekompilacji. Natomiast w C++ wprowadzono pojęcie metody wirtualnej, które burzy ten prosty i skuteczny mechanizm. Metody wirtualne są realizowane jako struktury wskaźników do funkcji, zatem biblioteka będzie zgodna z poprzednią wersją, jeśli układ tej struktury będzie zgodny z poprzednią wersją. W praktyce tracimy tę kompatybilność przy zmianie sygnatury dowolnej metody i przy dodaniu metody. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Komponenty Opisane na poprzednim slajdzie problemy z tworzeniem efektywnych rozwiązań w C++ są głównym motorem napędowym powstania technologii komponentowych. Bardzo obrazowo jest to opisane w dokumencie z projektu OpenOffice. Autorzy podają, że projekt StarOffice rozrósł się do 5 min linii kodu i jego rekompilacja trwała 2 dni. W praktyce uniemożliwiło to dalszy rozwój projektu i zaczęto szukać innego rozwiązania ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Koncepcja działania komponentów W trakcie kompilacji naszego kodu nic nie wiemy o komponencie, którego będziemy używać (nie mamy plików nagłówkowych). Używając linkera, ładujemy w trakcie działania programu bibliotekę dynamiczną Rozwiązujemy kilka dobrze znanych symboli do funkcji (one dają nam pełny obraz co komponent zawiera) Wywołujemy dostarczone przez komponent metody Budujemy stos z parametrami wywołania (Foreign Function Call)- żeby wywołać funkcję o której nie wiedzieliśmy nic w trakcie kompilacji. Wymaga ona kodu pisanego w asemblerze, dostosowanego do konkretnej platformy ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Czy można to zrobić prościej ? W systemie Linux można zainstalować nowy, rozszerzający jądro systemu moduł, bez przerywania pracy systemu, czy rekompilacji samego jądra. Taki moduł składa się z zestawu funkcji i jednej funkcji inicjującej, która ustawia specjalną tablicę systemową zawierającą wskażniki do funkcji. Ilekroć system ma wykonać jakąś akcję, wywołuje funkcję wskazywaną przez daną pozycję w tej tablicy. W rezultacie mamy bardzo prosty, ale i bardzo skuteczny system, umożliwiający obiektowe projektowanie i budowę złożonych aplikacji. Takie podejście stało się głównym wzorcem dla rozwiązań przyjętych w LeftHand. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Dynamiczne klasy w LeftHand Przy projektowaniu systemu LeftHand autorzy przyjęli następujące cele: Zmiany takie jak: zmiana kodu metody, zmiana sygnatury metody, dodanie metody,dodanie klasy- można wykonywać bez zatrzymania procesu. Kompilowany będzie tylko ten kod, który rzeczywiście się zmienił- zmiana kodu metody będzie wymagała rekompilacji tylko kodu tej metody. Zastosowane technologie nie mogą w znaczący sposób spowolnić działania systemu. Z punktu widzenia programisty, wszystkie klasy mają być dostępne jako klasy C++ z możliwością dziedziczenia, tworzenia polimorficznych (wirtualnych) metod, używania operatorów .. itd ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Dynamiczne klasy w LeftHand Przyjęte rozwiązanie polega na zastosowaniu tablic wskaźników do funkcji, które służą jako tablice metod wirtualnych. Każda klasa posiada tablicę metod, wypełnioną wskaźnikami do konkretnych implementacji, które są pobierane z dynamicznie ładowanych modułów. Oznacza to, że w trakcie działania systemy możemy podmienić implementację konkretnej metody. Możemy zmienić treść metody, przekompilować jej bibliotekę DLL i załadować ją ponownie. Podobnie możemy dodawać nowe metody. Nowe metoty zawsze dodajemy na końcu tablicy, więc nie trzeba kompilować kodu, który nie korzysta z nowej metody. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Rozszerzenia Oprócz szybkiej tablicy metod wirtualnych jest też tworzona mapa, pozwalająca odnaleźć i wykonać metodę, jeśli znamy jej nazwę. Możemy również tworzyć egzemplarze klas, jeżeli mamy nazwę klasy. Pozwala to programować w sposób całkowicie dynamiczny, czyli odwoływać się do klas i metod, o których nic nie wiedzieliśmy w czasie kompilacji naszego programu. Możliwość podmienienia implementacji metody w trakcie działania programu otwiera bardzo szerokie możliwości dynamicznego programowania. Możemy podmienić implementację metod np.. W zależności od kontekstu albo tylko w wybranym fragmencie kodu, jeżeli jesteśmy w trakcie uruchamiania metody. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Języki skryptowe Języki skryptowe są, z natury swojego działania, bardzo dynamiczne. Dobrze, jeśli całe środowisko jest również dynamiczne (ułatwia to integrację z j. skryptowym). Integracja taka wymaga dwóch elementów: możliwości odwoływania się do motoru języka skryptowego i zanurzenia środowiska w środowisku skryptowym. Zanurzenie polega na udostępnieniu w środowisku skryptowym własnych metod, oraz możliwość przekazania parametrów. Trzeba też w jednolity sposób zarządzać pamięcią i obsługą błędów. LeftHand obsługuje obecnie integrację z JavaScript. Integracja z JavaScript polega na zdefiniowaniu klas, które będą dostępne w kodzie skryptów i będą obsługiwane przez biblioteki LH. Dla każdej klasy jest automatycznie tworzony kod pośredniczący pomiędzy C++ a JacaScript. Przy zmianach interfejsu kod ten jest ponownie generowany i kompilowany . ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Jak to jest możliwe? Jak widać, cały ten system jest dość skomplikowany. W ramach platformy LeftHand programiści nie zajmują się całą tą komplikacją, a po prostu tworzą nowe klasy i metody. Z wprowadzanej przez programistów treści są tworzone bardzo różne elementy systemu. Żeby to było możliwe, treść opisująca klasę i jej metody jest wprowadzana w postaci drzewa (drzewo jest podstawowa strukturą bazy danych w LeftHand). Można to robić przy pomocy plików szablonów (ang. template), które są następnie zapisywane do bazy danych .Dopiero z zapisów zawartych w bazie danych są generowane źródła C++, kod pośredniczący do JavaScript, dokumentacja itp. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019
Podsumowanie Korzystając z prostych i powszechnie używanych technik LH stworzyło ramy pracy nad aplikacjami biznesowymi, które dla programisty wyglądają jak zestaw klas C++, ale dają się dynamicznie zmieniać. Poprzez skrócenie czasu niezbędnego na wprowadzenie zmian w systemie, znacznie przyśpieszyli pracę programisty. Dodatkowo powstała możliwość dynamicznego zmieniania funkcjonalności aplikacji i łatwej integracji z językami skryptowymi. To wszystko bez utraty możliwości debugowania, szybkości działania i wstawek w asemblerze. ® EB czwartek, 17 stycznia 2019czwartek, 17 stycznia 2019