Modularyzacja i testy architektury

Obrazek techniczny ilustrujący kilka prostopadłościanów z zaznaczeniem miar

The art of programming is the art of organizing complexity;
mastering multitude & avoiding its chaos as effectively as possible.

Edsger W. Dijkstra

Modularyzacja w projektach stanowi jedną z kluczowych technik, które pozwalają na zachowanie czytelności, skalowalności oraz łatwości w utrzymaniu kodu. Wraz z rozwojem projektów, zwłaszcza tych o większym zakresie, staje się ona ważnym elementem zapewniającym porządek i przejrzystość w strukturze kodu. Jednakże, wraz z rozwojem projektu, gdy wprowadzane są kolejne zmiany, a programiści przychodzą i odchodzą, łatwo zapomnieć o początkowych założeniach architektury. Z pomocą przychodzą testy automatyczne. Tylko co testować i jak je zrobić? Bez solidnych testów nie jesteśmy w stanie upewnić się, że nasza struktura modułowa spełnia założenia, które sobie postawiliśmy.

Co testować

Pewne aspekty modułów, takie jak zależności międzymodułowe oraz cykle w języku java możemy testować za pomoc archunit. Biblioteka ta nie rozwiązuje jednak wszystkich problemów. Przyjrzyjmy się dwóm innym szczególnie istotnym przypadkom:

1. Równomierna dystrybucja kodu

Gdy mamy wiele modułów, ale jeden z nich zawiera znaczną większość kodu, modularyzacja traci swoje znaczenie. Przykładowo, jeśli mamy 15 modułów, a jeden z nich zawiera aż 80% kodu, to nie możemy mówić o rzeczywistej modularyzacji, ponieważ niemal całość kodu jest zawarta w jednym module. Jest to sytuacja, którą należy wyeliminować poprzez automatyczne testowanie rozmiaru modułów.

2. Niektóre moduły powinny być szczególne małe

Ważne jest również zapewnienie, że poszczególne moduły są niewielkie i stabilne pod kątem wprowadzanych zmian (jak często wprowadzamy zmiany). Na przykład, moduł typu „commons” powinien być niewielki i zawierać ogólną funkcjonalność, która jest często używana w różnych częściach projektu. Jeśli ten moduł staje się zbyt duży, może to prowadzić do problemów z zarządzaniem kodem i jego modyfikacjami. Oczywiście jest to przybliżenie, ponieważ ważniejsze jest minimalizowanie interfejsu modułu i zachowanie jego stabilności pod kątem zmian, co nie musi wiązać się z minimalizacją rozmiaru modułu.

Jak testować

Ponieważ opisane powyżej zagadnienia są dla mnie bardzo istotne postanowiłem je weryfikować w testach. Implementacja może być bardzo prosta i polegać na zliczaniu linii kodu w pakietach. Ku mojemu zaskoczeniu nie znalazłem gotowego narzędzia, które w szybki sposób pozwoliłoby sprawdzać rozmiar modułów.

Przygotowałem więc bibliotekę java, która pozwala na testowanie rozmiaru modułów – module-size-calculator. Biblioteka ta umożliwia analizę rozmiaru modułów w projekcie na podstawie liczby linii kodu (LOC). 

Wystarczy zdefiniować zależność

<dependency>
    <groupId>pl.tfij</groupId>
    <artifactId>module-size-calculator</artifactId>
    <version>1.0.0</version>
</dependency>

Od teraz możemy pisać testy w stylu

ProjectSummary projectSummary = ModuleSizeCalculator.project("src/main/java")
	.withModule("com.example.module1")
	.withModule("com.example.module2")
	.analyze()
	.verifyEachModuleRelativeSizeIsSmallerThan(0.3)
	.verifyModuleRelativeSizeIsSmallerThan("com.example.commons", 0.1);

Biblioteka pozwala na różnego rodzaju asercje rozmiaru modułów, a jeśli coś nie zostało przewidziane można, na podstawie wygenerowanego raportu napisać klasyczną asercję w JUnit. Biblioteka pozwala także wygenerować raport w postacie wykresu Mermaid, który może następnie być dołączony np. do dokumentacji.

Po więcej szczegółów i przykładów zapraszam na github.

Przekaz na dziś

Modularyzacja jest kluczowym aspektem projektu. Testuj ją aby mieć pewność, że nie zanika z czasem.


Autor Tomek Fijałkowski

Tomek jest pasjonatem zwinnych metodyk, TDD i DDD. W swojej karierze pełnił przeróżne role. Był programistą, scrum masterem, liderem, architektem, managerem. Aktualnie wrócił do tego co lubi najbardziej i jest programistą w point72.

2 thoughts on “Modularyzacja i testy architektury

  1. Bardzo ciekawe to co piszesz. Często można trafić na dyskusje o tym jaki rozmiar modułu jest optymalny, ale zazwyczaj są to opinie mocno subiektywne. Ja trafiłem tylko na jedne wyniki badań w tym temacie, które opisał Eric Raymond w swojej książce „The Art of Unix Programming” (wersję online rozdziału „Modularity: Encapsulation and Optimal Module Size” można znaleźć pod adresem http://www.catb.org/esr/writings/taoup/html/ch04s01.html). Niestety są to dość stare badania, z końca poprzedniego wieku. Trafiłeś może na coś nowszego?

  2. Dziękuję za Twój komentarz! Jestem wdzięczny, że dzielisz się swoimi spostrzeżeniami.
    Zgadzam się z Tobą, że dyskusje na temat optymalnego rozmiaru modułu często opierają się na subiektywnych opiniach. Aby prowadzić tę dyskusję, istotne jest ustalenie spójnej definicji modułu, co nie jest łatwe.
    W moim poście używam bardzo ogólnej definicji, gdzie moduł to po prostu katalog zawierający pliki. Ta elastyczność sprawia, że biblioteka do testowania może być bardziej wszechstronna i użyteczna w różnych kontekstach. Propozycja testów opartych na względnym rozmiarze wydaje mi się sensownym podejściem, które może być stosowane zarówno w małych, jak i dużych projektach. Uniknąłem też problemu definiowania jaki rozmiar jest właściwy.
    W ogólności uważam, że modularyzacja powinna być wielopoziomowa, co jeszcze bardziej utrudnia definicję modułu. Myślę, że to świetny materiał na kolejny post, który chętnie napiszę, gdy znajdę tylko chwilę.

Leave a Reply