xime: Szablon dla modułów

tech • 397 słów • 2 minuty czytania

Ta notatka została oznaczona jako wymagająca dopracowania: code?.
Zawartość wpisu może ulec zmianie, zatem zapraszam do ponownych odwiedzin w niedalekiej przyszłości :)

Ta notatka jest częścią serii xime. Zapoznaj się z pozostałymi wpisami.

Dziś może bardziej techniczna notka związana z wewnętrznymi modułami aplikacji.

W xime przez pojęcie modułu rozumiemy jakiś komponent aplikacji, coś wykonujące określone funkcje, np. moduł konfiguracji, czy menadżera profili. Na początku były to typowe klasy do ściśle określonego zadania, ale problemem było tworzenie takich obiektów, trzymanie wskaźników do instancji i łatwy do nich dostęp z dowolnego kodu programu.

Rozwiązaniem tych problemów, mogłoby być zastosowanie wzorca projektowego singleton. Najprostsze, ale i mające kilka wad rozwiązanie - niepotrzebny narzut na sprawdzenie i w razie potrzeby utworzenie obiektu przy pobieraniu. Innym problemem byłoby tworzenie samych obiektów. Ponieważ na różnych etapach działania aplikacji, potrzebne są różne moduły, przy czym niektóre nie mogą istnieć na danym etapie, a inne powinny, więc kontrolowanie tego, lub implementacja jakiegoś mechanizmu do tego celu, byłaby trochę kłopotliwa.

Idealnym dla mnie rozwiązaniem jest napisanie prostego szablonu Module, który jest konkretyzowany klasą z jakiej ma zostać utworzony dany moduł oraz informacjami na jego temat. Idea podobna do singletonu, ale sam zarządzam życiem obiektu modułu poprzez statyczne metody Load i Unload, a wskaźnik/referencję do obiektu klasy modułu pobieram poprzez metodę Get, która rzuci ewentualnym assertem, gdy obiekt nie istnieje.

Przykład definiowania standardowego modułu menadżera profili:

struct ModuleProfilesInfo : public ModuleInfo {
	ModuleProfilesInfo() : ModuleInfo("Profiles", STANDARD) {}
};
typedef Module<impl::Profiles, ModuleProfilesInfo> Profiles;

Klasa Profiles z przestrzeni nazw impl zawiera implementacje funkcjonalności menadżera profili.

Niektórzy pewnie zalecaliby, by moduł Profiles był klasą impl::Profiles dziedziczącą po skonkretyzowanym wzorcu Module. Może byłoby to lepsze, ale wtedy by dostać się do zdefiniowanego jakiegoś typu w klasie modułu musiałbym używać czegoś na wzór:

Profles::module_class::typ_w_impl_profiles;

Wtedy statyczne metody Get/Load/Unload oraz inne ze wzorca Module mogłyby tworzyć konflikty z takimi samymi nazwami używanymi w klasie modułu, a nie wszystkie klasy używane do stworzenia modułu są lub będą mojego autorstwa. Niektóre i tak muszą posiadać podobne nazwy choćby Load, które coś tam ładuje. No i nie podobają mi się takie rozlegle nazwy jak GetModule, LoadModule, itd…

Można pokusić się o napisanie prostego generycznego loadera, który sam ładowałby moduły w zależności od typu. Mam tu na myśli kod pozwalający wygenerować w czasie kompilacji docelowy kod odpowiedzialny za wywołanie metod Load i Unload w danym miejscu ;)

W takim wypadku należałoby pomyśleć o jakiś priorytetach modułów, bo niektóre moduły zależą od innych. Dlatego ładowanie musi przebiegać w określonym porządku. Póki co nie ma ich za dużo, więc pozostaje ręczny kod. Nie zmienia to faktu, że zautomatyzowanie tego byłoby fajnym udogodnieniem.

Komentarze (0)

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/