sobota, 27 kwietnia 2013

Złożoność EA (2) - miary złożoności IT

Zgodnie z definicją CUEC (Consortium for Untangling Enterprise Complexity): złożoność, to cecha systemu, która powoduje, że jest on trudny w użyciu, w zrozumieniu, w zarządzaniu i/lub trudny do implementacji. Złożoność może więc dotyczyć różnych aspektów IT, np. złożoności implementacji systemu, złożoności komunikacji między ludzi w projekcie czy złożoności procesów biznesowych wspieranych przez system.

Jeśli budujemy prostą, jednostanowiskową aplikację do używania przez jednego użytkownika, wtedy prawdopodobnie nie będziemy potrzebować żadnego architekta. Jeśli jednak zamierzamy zbudować rozwiązanie o architekturze rozproszonej, używane w całej organizacji i wspierające krytyczne procesy firmy, wtedy najprawdopodobniej będziemy potrzebować architekta baz danych, architekta rozwiązań architekta infrastruktury, architekta biznesowego oraz architekta korporacyjnego.

W celu skutecznego zarządzania złożonością w IT niezbędny jest jakiś sposób jej zmierzenia. Istnieje wiele miar złożoności oprogramowania. Opierają się one głównie na badaniu struktury kodu źródłowego. W tym artykule przedstawiam dwie najbardziej znane miary złożoności oprogramowania: miarę złożoności cyklomatycznej oraz miarę złożoności Halstead'a. Jednak miary złożoności oprogramowania niestety nie nadają się do mierzenia złożoności architektury. Najczęściej cytowane w tym obszarze są wyniki prac Rogera Sessions, który zdefiniował miarę złożoności architektury IT, przedstawioną na końcu tego artykułu.

Miara złożoności cyklomatycznej

Miara złożoności cyklomatycznej oprogramowania została opracowana przez Thomasa J. McCabe’a w 1976 roku. Mierzy liczbę pełnych, niezależnych ścieżek, przez które można przejść w programie. Oryginalnie oblicza się ją przy użyciu grafu skierowanego reprezentującego przepływ sterowania w danym programie. Węzły tym grafie odpowiadają podstawowym blokom programu (niepodzielny ciąg instrukcji, jedno wejście, jedno wyjście, instrukcje wykonywane po kolei, bez skoków z i do wnętrza bloku) a skierowane krawędzie oznaczają skoki w przepływie sterowania. Dla danego grafu przepływu sterowania G, złożoność cyklomatyczna M jest zdefiniowana jako :
v(G) = E - N + 2P
gdzie:
E = liczba krawędzi w grafie
N = liczba węzłów w grafie
P = liczba oddzielnych podgrafów (połączonych komponentów mierzonego grafu)

Po uproszczeniach, złożoność cyklomatyczną CC dla danej funkcji lub metody lub całej klasy lub całego systemu złożonego z wielu takich elementów, można wyrazić następująco:
CC = d - e + 2
gdzie:
d = liczba węzłów decyzyjnych o charakterze binarnym
e = liczba wyjść z programu

Dla przykładu: jeśli program ma jedno wyjście, nie zawiera żadnej instrukcji if/else (lub innej sprawdzającej warunek) ani żadnej pętli, wtedy złożoność cyklomatyczna takiego programu będzie wynosiła 1, gdyż zawiera on tylko jedną ścieżkę przejścia. Jedna instrukcja if/else zwykle wprowadza dwie możliwe ścieżki - jedną, gdy badany warunek jest spełniony i drugą, gdy badany warunek nie jest spełniony. Złożoność cyklomatyczna programu z jednym wyjściem i jedną instrukcją if/else, nawet zawierającego wiele funkcji, będzie wynosiła 2.

Złożoność cyklomatyczna programu przekłada się na trudność jego zrozumienia, pracochłonność testowania, niezawodność, trudność utrzymania, itd . Jedną z metod zmniejszania zmniejszania złożoności cyklomatycznej jest partycjonowanie oprogramowania, czyli podział na moduły o wysokiej kohezji i słabych związkach z innymi modułami.

Miary złożoności Halstead'a

W 1977 roku Maurice Howard Halstead opracował kilka metryk oprogramowania na podstawie empirycznych doświadczeń. Jedną z nich jest miara złożoności, która określa trudność zrozumienia lub skłonność do występowania błędów. Wg Halstead'a, trudność (D) programu jest proporcjonalna do liczby unikalnych operatorów w programie. D jest również proporcjonalna do stosunku pomiędzy całkowitą liczbą wystąpień operandów, a liczbą operandów unikalnych. Zapis matematyczny :
D = (n1 / 2) * (N2 / n2)
gdzie:
n1 – liczba unikalnych (różnych) operatorów w programie
n2 – liczba unikalnych (różnych) operandów w programie
N1 – całkowita liczba wystąpień operatorów
N2 – całkowita liczba wystąpień operandów

Miara złożoności Halstead'a mówi, że jeśli te same operandy są używane w programie wielokrotnie, to błędy występują w nim częściej.

Złożoność architektury IT Sessions'a

Obie ww. miary zostały przewidziane jedynie do mierzenia złożoności oprogramowania, nie nadają się więc bezpośrednio do mierzenia złożoności architektury IT.
Na poziomie architektury IT można wyróżnić dwa aspekty złożoności: złożoność funkcjonalna i złożoność koordynacji .

Złożoność funkcjonalna
Weźmy system, które ma zaimplementowaną jedną funkcjonalność. Taki system będzie mniej złożony od systemu, który ma trzy funkcjonalności. A z kolei system z trzema funkcjonalnościami będzie mniej złożony od systemu, który ma ich dziewięć - patrz poniższy rysunek:


Błędne działanie systemu z jedną funkcją a będzie spowodowane błędem tylko w tej jednej funkcji a. Błędne działanie systemu z dwoma funkcjami a i b może być spowodowane błędem w funkcji a lub błędem w funkcji b lub błędem w obu funkcjach a i b. Błędne działanie systemu z trzema funkcjami a, b i c może być spowodowane błędem w: a, b, c, a+b, a+c, b+c, a+b+c.

Widać, że złożoność systemu C rośnie szybciej, niż ilość funkcjonalności F w tym systemie. W 1979 roku S. N. Woodfield przeprowadził eksperyment wykazujący empirycznie, że wzrost ilości funkcjonalności o 25% powoduje wzrost złożoności o 100%. Czyli dla funkcjonalności F=1 złożoność C wynosi 1 a dla funkcjonalności F=1.25 złożoność C wynosi 2. Ta obserwacja prowadzi do wzoru na złożoność będącą funkcją liczby N funkcjonalności systemu:
FC(N) = 10^(3.11 * log(N))

Po uproszczeniu:
FC(N) = N^3.11

Złożoność współdziałania
Złożoność danego systemu może rosnąć nie tylko z powodu wzrostu liczby funkcjonalności, ale również wraz ze wzrostu zależności tego systemu od innych systemów - patrz poniższy rysunek:



Te zależności, które składają się na złożoność danego systemu, to mogą być zarówno usługi innych systemów w sensie SOA jak i współdzielone dane, wywołania funkcji innych systemów, czy współdzielone transakcje. Każda taka zależność, to po pierwsze dodatkowa funkcjonalność w danym systemie a po drugie potencjalne źródło błędu, więc dodatkowy element do sprawdzenia podczas szukania przyczyny nie działania systemu czyli dodatkowe punkty złożoności danego systemu. Możemy więc przyjąć, że wzór na złożoność współdziałania CC wynikającą z M zależności danego systemu od innych będzie analogiczny do wzoru na złożoność wynikającą z liczby funkcjonalności :
CC(M) = M^3.11

Złożoność całkowita architektury IT
Złożoność danego systemu składa się ze złożoności wynikającej liczby funkcjonalności oraz ze złożoności wynikającej z liczby zależności danego systemu od innych. Przy założeniu, że te dwie złożoności są od siebie niezależne, wzór na całkowitą złożoność C systemu zawierającego N funkcjonalności oraz M zależności można wyrazić wzorem:
C(N, M) = N^3.11 + M^3.11

Systemy w złożonych architekturach przeważnie nie funkcjonują samodzielnie. Złożoność architektury A złożonej z X systemów będzie więc sumą złożoności poszczególnych systemów:
C(A) = SUMA( C(X) )

Zakończenie

Problem złożoności, wstępnie zidentyfikowany 25 lat temu, gdy architektura korporacyjna powstawała, dzisiaj dochodzi do punktu krytycznego. Złożoność i koszt systemów IT wzrosły wykładniczo a łatwość uzyskiwania realnej wartości z użycia tych systemów dramatycznie zmalała . Tymczasem architektura korporacyjna miała m.in. właśnie zaadresować problem rosnącej złożoności organizacji, łącznie z jej komponentami technologicznymi. Po to właśnie powstały metodologie zarządzania architekturą korporacyjną - aby zmniejszyć ryzyka i poprawić jakość efektów planowania i realizacji zmian w architekturze przedsiębiorstwa. Pomimo to żadna z dzisiejszych metodyk zarządzania architekturą korporacyjną nie definiuje, czym ta złożoność jest, jak ją można kontrolować ani jak sprawdzać, czy udało się ją zmniejszyć lub wyeliminować.

Zgodnie z zasadą, że nie da się zarządzać czymś, czego nie da się zmierzyć więc w celu poradzenia sobie ze złożonością w IT konieczny jest jakiś jej pomiar. W mniejszym artykule przedstawiłem dwie miary złożoności oprogramowania oraz jedną miarę złożoności architektury, ale jest zaledwie drobny wyimek z dostępnych metod, których istnieje około 100.

Złożoność kosztuje. Samo zmierzenie złożoności nie powoduje, że staje się ona mniejsza, ale pomaga w skupieniu się na tych działaniach, które ją zmniejszają. Metody radzenia sobie ze złożonością zastaną przedstawię w następnym artykule.

Źródła

  • Standard Definitions of Common Terms, CUEC (Consortium for Untangling Enterprise Complexity), http://www.cuec.info/index.php/download_file/view/166/205/, [2013-04-27].
  • McCabe T. J., A Complexity Measure, [w:] IEEE Transactions on Software Engineering, 1976, vol. 2, nr 4, s. 308-320, http://www.literateprogramming.com/mccabe.pdf, [2012-06-09].
  • Halstead M. H., Elements of Software Science, Amsterdam 1977, Elsevier North-Holland, Inc.
  • Sessions R., The Mathematics of IT Simplification, ObjectWatch, Inc., 2011-04-01, http://www.objectwatch.com/whitepapers/MathOfITSimplification-103.pdf, [2012-06-09].
  • Sessions R., Simple Architectures for Complex Enterprises, 1 edycja kindle 2010, Microsoft Press.
  • Watson A. H., McCabe T. J., Structured Testing: A Testing Methodology Using the Cyclomatic Complexity Metric, Wrzesień 1996, NIST Special Publication 500-235, s. 16, http://www.mccabe.com/pdf/mccabe-nist235r.pdf, [2012-06-09].
  • Woodfield S.N., An Experiment on Unit Increase in Problem Complexity, 1979, IEEE.