Tworzymy moduł: struktura

powershell-module-structureWakacje dobiegły końca i pora wrócić do cyklu dotyczącego tworzenia modułu. W poprzedniej części skupiliśmy się na tym, jak korzystając z gita zarządzać kodem wewnątrz naszego modułu. Dziś przyjrzymy się temu, jak dostosować strukturę modułu do pracy z gitem, pomagając nam uniknąć problemów związanych z konfliktami w gicie i jednocześnie jak później zadbać o to, by publikowany moduł był możliwie najprostszy. Zanim jednak przejdziemy do struktury, którą staram się wykorzystywać obecnie, postaram się opisać proces, który nas do niej doprowadził.

Jeden plik

Tworzenie modułów zaczęliśmy od tradycyjnej struktury z dwoma jedynie plikami. Plikiem manifestu (niezbędnym by nasz moduł posiadał takie informacje jak wersja, autor, listę eksportowanych poleceń) i plikiem głównym modułu (zawierającym implementację wszystkich poleceń). Szybko jednak okazało się, że tego rodzaju struktura sprawdza się dobrze w przypadku, gdy kod zmieniany jest w sposób liniowy, bez rozgałęzień i kilku użytkowników dokonujących jednocześnie zmian. Dlaczego? Odpowiedź jest prosta: konflikty w kodzie.

git-conflict

Konflikty wynikać będą zarówno ze zmian w tej samej funkcji, jak i w różnych funkcjach, które „zachodzą” na siebie. Git nie jest zdolny rozróżnić elementów składni i ogranicza się do śledzenia zmian w poszczególnych liniach kodu. Jeśli więc kolega doda funkcję do modułu a my rozbudujemy inną funkcję, to zmiany kompletnie ze sobą nie związane mogą doprowadzić do konfliktu.

Wiele plików – dotsourcing (i pokrewne)

Pierwsze rozwiązanie, jakie się nam nasunęło, to rozbicie pliku modułu na pliki zawierające poszczególne funkcje i wykorzystanie dot-sourcingu, by w pliku modułu połączyć wszystko w całość. W ten sposób bardzo szybko ograniczyliśmy konflikty do jednego pliku, które rozbić nie byliśmy w stanie: manifestu. A i tam na ogół konflikt ograniczał się do dwóch elementów: wersji i listy eksportowanych poleceń. Co ważne: rozwiązywanie takich konfliktów nie stanowiło większego problemu.

Szybko okazało się jednak, że takie podejście powoduje spore problemy w czasie koniecznym do załadowania modułu. Mimo iż nasze pliki nie miały podpisu cyfrowego, to PowerShell za każdym razem (dla każdego z osobnych skryptów) próbował pobierać listę CRL-ów (certificate revocation list). Nie ma z tym problemu, jeśli możemy korzystać z internetu. Jest wolniej, ale tylko troszkę. Gorzej, jeśli nasza stacja robocza dostępu do internetu nie ma – każda próba pobrania CRL skutkuje czekaniem na to, aż system uzna, że ich pobranie nie jest możliwe. Im więcej plików – tym dłużej ładował się moduł. W przypadku jednego z naszych modułów, który traktowaliśmy jako swoisty „utility belt” ładowanie modułu zaczęło zajmować przeszło minutę.

Ostatecznie problem udało się rozwiązać wykorzystując dość pokręcony kod i wszystko było dobrze do momentu, w którym konieczne było skorzystanie z debuggera. Okazało się bowiem, że nie da się ustawić break-pointów w sytuacji, gdy moduł ładowany jest przy pomocy naszego „triku”. Dodaliśmy więc opcje ładowania modułu w trybie „debug”, które zajmowało masę czasu, ale w zamian za to oferowało możliwość debuggowania. Wreszcie ostatnio uznaliśmy, że pora przestać kombinować i zacząć „budować” nasz moduł.

Wiele plików – łączone

Na czym to polega? Otóż kod w repozytorium przechowujemy w osobnych plikach. Oprócz plików dla funkcji, mamy też pliki zawierające np. klasy w modułach korzystających z możliwości PowerShella 5.1. Manifest generujemy w oparciu o pliki umieszczone w odpowiednich podfolderach, z oryginalnego manifestu pozostawiając takie elementy jak opis, wersja, aliasy czy dane niezbędne do publikowania w galerii modułów. W ten sposób nasze moduły zyskały pewną strukturę, dzięki której łatwo zadbać o funkcje publiczne, prywatne, klasy czy inne elementy naszego modułu.

Oprócz kodu przeznaczonego do publikacji mamy też oczywiście kod związany z testami jednostkowymi oraz kod przeznaczony do budowania i publikowania naszego modułu. W dużym przybliżeniu taka struktura może wyglądać następująco:

PowerShellPL-Struktura

Oczywiście, łączenie można wykonywać na różne sposoby. Istotne jest jedynie to, by na końcu uzyskać jedynie pliki, które muszą być osobno (pliki formatów, pliki DLL zawierające zewnętrzne biblioteki, inne pliki pomocnicze) oraz dwa pliki modułu. Moduł ładuje się szybko i umożliwia analizę błędów z wykorzystanie debuggera a w trakcie pracy w ramach repozytorium konflikty zdarzają się niezmiernie rzadko: zjedliśmy ciastko, i mamy ciastko. Winking smile

~ - autor: Bartek Bielawski w dniu 22 września, 2020.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s

 
%d blogerów lubi to: