Temat integracji przewija się niemalże w każdym wdrożeniu. W wymaganiach najczęściej widuję opis tego, jakie dane są wymieniane, bardzo rzadko widuję dodatkowe ograniczenia, w szczególności chroniące kupującego przez dużymi kosztami utrzymania. Kupujący jako “laik”, szczególnie sam piszący wymagania, praktycznie nie jest w stanie się obronić przed takimi kosztami, a kryterium niskiej ceny przy wyborze, praktycznie zawsze doprowadzi do przyszłych kłopotów. Dlatego po raz kolejny piszę: specyfikacja wymagań powinna zawierać projekt rozwiązania, wtedy niejako “zabronimy” stosowania “szkodliwych” rozwiązań przez dostawcę oprogramowania. Większość dostawców oprogramowania zawsze będzie szła na skróty.
W poprzednim artykule pisałem o wymaganiach pozafunkcjonalnych, dotyczących kupowanego oprogramowania (Wymagania pozafunckjonalne czyli jaka architektura), dzisiaj o integracji z innymi.
Niestety stale obserwuję podejście dostawców oprogramowania (także wewnętrzne działy IT!), bazujące na możliwie niskim koszcie i czasie wykonania integracji (budowanie marży, oszczędności czasu, nie raz niewiedza) przy kompletnym ignorowaniu tego, że przyszłe koszty utrzymania są wielokrotnie większe niż te oszczędności, a nie raz traci się nawet panowanie nad złożonością posiadanego systemu (z perspektywy dostawcy jest to zwykłe uzależnianie klienta i generowaniu mu kosztów). Znam przypadki, w których źle (czytaj złą metodą, bo transfer danych działał) wykonane kolejne integracje nowych aplikacji, doprowadziły do sytuacji, w której praktycznie nie był możliwy, bez bardzo dużego ryzyka krachu całości, upgrade żadnego z podsystemów! (w jednym z przypadków to nie była mała firma, to był jeden z większych operatorów sieci CATV).
Ale po kolei…
Wzorzec architektoniczny integracji – fasada/adapter
Architektura oprogramowania stosującego wzorzec fasady (tu API) do integracji wygląda tak:
Mamy tu dwie aplikacje: Aplikacja 1 i Aplikacja 2. Każda ma jakąś logikę i jakiś skład danych (system utrwalania, celowo nie piszę baza danych, bo może to być także system plików). Tak zwane [[API]] to komponent zapewniający separację wnętrza aplikacji od jej otoczenia i bezpieczne udostępnienie określonych operacji (z reguły parametryzowalnych), które można z zewnątrz wywoływać, żądając pobrania lub zachowania jakichś informacji. Na zewnątrz API udostępnia Interfejs Oferowany (lizak w notacji UML powyżej). Interfejs Wymagany (kieliszek w notacji UML powyżej) to specyfikacja tego, czego potrzebuje aplikacja. Innymi słowy Interfejs oferowany to funkcjonalności (usługi) jakie oferuje aplikacja, interfejs wymagany to nasze wymagania wobec aplikacji (należy je zdefiniować w toku analizy wymagań).
Na diagramie przypadków użycia interfejs oferowany to przypadki użycia a interfejs wymagany to aktor i jego oczekiwania (diagram komponentów i odpowiadający mu diagram przypadków użycia):
(więcej na temat stosowania diagramów przypadków użycia w kontekście integracji w artykule o przypadkach użycia i granicy systemu)
Jak doprowadzić do przyszłego krachu systemu
Otóż, jak wspomniałem, częstą praktyka jest “droga na skróty”, przez niektórych nazywana “spawaniem aplikacji”. Wygląda to tak:
W Aplikacji 1 dodaje się kilka bezpośrednich odwołań do bazy danych Aplikacji 2, by pobrać dane, które są potrzebne. Efekt tego podejścia to całkowite uzależnienie działania Aplikacji 1 od jakichkolwiek zmian w strukturze danych Aplikacji 2. Każda taka zmiana w Aplikacji 2 (np. jej update czy upgrade) rodzi ryzyko błędów w tej wymianie danych (integracja przestanie działać). Stosowanie tablic pośrednich chroni wyłącznie przed nieumyślnym naruszeniem integralności danych. Kolejna poważna wada tej metody to wymóg, by obie aplikacje pracowały na jednym serwerze lub w jednej sieci lokalnej. Tak więc każda przyszła inicjatywa związana np. z pracą w sieci rozległej (przeniesienie z jednego do innego oddziału, przejście do chmury itp.) nie ma tu racji bytu (stosowanie sieci VPN w sieciach rozległych to bardzo zawodny pomysł, wymagający bardzo kosztownych łączy).
Ta metoda ma jeszcze inną poważną i bardziej “ukrytą” wadę. Logika biznesowa (reguły biznesowe) raczej “tkwi” poza bazą danych (tu Logika aplikacji 2), w efekcie pobieranie informacji bezpośrednio z bazy danych (System utrwalania 2) rodzi poważane ryzyko, że pobrane dane będą “szkodliwe”, gdyż pobieranie ich z pominięciem reguł biznesowych, powoduje, że sens i cel implementacji tych reguł zostaje zaprzepaszczony.
Jeżeli nasza aplikacja nie ma API
Nie raz mamy do czynienia ze “starymi” aplikacjami ([[legacy system]]). Wtedy trzeba API po prostu zaprojektować i napisać. Powinien to zrobić dostawca aplikacji, z którą się integrujemy: jemu przedstawiamy specyfikację Interfejsu Wymaganego (I_Żądany1):
Gdyby wymiana danych odbywała się w obu kierunkach, tworzony adapter dodatkowo pośredniczy w pobieraniu danych z Aplikacji 1.
Na zakończenie
Integracja to jeden z trudniejszych problemów. Wymaga bowiem nie tylko specyfikowania (i potem ich implementowania) interfejsów, ale także analizy i opracowania bezpiecznej architektury całego systemu (tu znowu architektura korporacyjna). Wiele firm ma, nie dwie ale kilka, kilkanaście a niektóre nawet setki aplikacji. Jeżeli będę ze sobą “pospawane” wywołaniami SQL/ODBC, to ruszenie “tego” praktycznie zawsze kończy się krachem (czytaj ogromne koszty przywrócenia funkcjonowania całości). Brak przemyślanej architektury, integracja ad-hoc “każdy z każdym”, to prosta droga do kłopotów i ogromnych kosztów utrzymania całości. Stosowanie API (ich tworzenie) nieco tylko podnosi koszty wdrożenia, za to chroni przed bardzo dużymi, nieplanowanymi, wydatkami w przyszłości. Wielu dostawców oprogramowania oferuje w swoich produktach API, wystarczy z nich korzystać.
Dedykowane dziedzinowe aplikacje coraz częściej są wdrażane etapami zamiast jednego dużego ERP, taka integracja nie jest wbrew pozorom kosztowna, kosztowny jest brak stosowania dobrych praktyk i wzorców, które warto poznać. Zwinność działania dzisiejszych firm na rynku to wymóg a nie opcja. Zwinność taka to nie jeden duży ERP (monopol jednego usługodawcy), to kilka zintegrowanych, dedykowanych niezależnych aplikacji , wdrażanych bez kastomizacji (wybieramy najlepszy produkt w danym momencie). Ich (aplikacje dziedzinowe) wymiana na inne, przy dobrze wykonanej integracji, to jest proces, który nie generuje monstrualnych kosztów każdorazowej analizy i przeróbki całości IT (kolejnej kastomizacji jednego ERP) w firmie.
P.S.
2014-10-14 Ukazał się ciekawy post na ten temat na blogu Trzecia Kawa:
Warto stosować kontrakt dla usługi, gdy integrujemy systemy z mało modyfikowalnym i słabo zdokumentowanym API; gdy nie mamy możliwości sprawdzenia integracji usług w trakcie implementacji oraz gdy działamy w środowisku o rozproszonej odpowiedzialności za integrację systemów.Stosowanie kontraktu dla usługi pozwala uniknąć dużych problemów w trakcie testów integracyjnych; stanowi fragment specyfikacji systemowej, a w przypadku zastosowania middleware pozwala na dokumentowanie specyfikacji usługi względem określonego klienta. (Kontrakt świadczenia usługi ? Trzecia kawa).
Nie napisał Pan jawnie (celowo?) o tym, że do realizacji zadania wymiany informacji między różnymi komponentami potrzeba pośrednika zupełnie spoza tych komponentów, czyli czegoś co przyjęło nazwę ESB (Enterprise Service Bus). Samo API nie wystarczy żeby uniknąć gąszczu zależności jednego komponentu od drugiego.
Nie pisałem celowo, ale nie po to by coś ukryć :), a by nie sugerować, że ESB jest konieczne, bo nie jest. Wspomniałem o “dobrze opracowanej” architekturze, co miałem na myśli? Warto zwrócić uwagę, że analizując systemy dziedzinowe w jednej organizacji można zawsze wskazać te, które są źródłem referencyjnym określonych danych i te, które z nich korzystają.
Przemyślana architektura to odpowiedni podział odpowiedzialności pomiędzy aplikacje, który minimalizuje liczbę interfejsów i czyni jest prostymi. Często struktura taka przyjmuje postać gwiazdy lub czegoś zbliżonego. Jeżeli jest jakaś logika manipulowania tą wymianą danych, warunkowego rozdzielania itp. to bardzo opłacalne jest napisanie, wdrożenie, nieskomplikowanego brokera komunikatów (mediator) z motorem reguł, niż zakup kosztownych systemów typu SOA/ESB.
Bardzo często role takiej szyny integracyjnej pełni też (jako rodzaj brokera) system BPM. Problem pojawia się dopiero gdy tych aplikacji jest nie kilka a kilkanaście i więcej ale też bał bym się mówić o regule. Patrząc na dobrze zaprojektowane oprogramowanie obiektowe, mamy tam dziesiątki klas z ich interfejsami i nie mamy żadnej szyny, raczej wzorce projektowe w rodzaju obserwator czy [[publish/subscribe]] (rodzaj bardzo prostej szyny komunikacyjnej albo po protu czasem jedna centralna aplikacja), które także można zastosować na poziomie komponentów jakimi są aplikacje.
Moim zdaniem problemem są raczej chaotyczne, oderwane od siebie zakupy aplikacji w wielu dużych firmach, gdzie problemem jest “zastany/uzyskany” stan “inwentarza”. W wielu przypadkach przemyślana architektura całości (znowu ta architektura korporacyjna :)) zupełnie wystarczy by model integracji nie był węzłem gordyjskim. Niestety kilka wdrożeń ESB, które widywałem (jedno nawet w pewnym banku) upadły nie dlatego, że rozwiązanie było złe, tylko dlatego, że zastane aplikacje było dziełem przypadku i nie było żadnej logiki w ich komunikacji, tego żadne ESB nie wyleczy.
Użycie kosztownych rozwiązań ESB powinno mieć raczej sens ekonomiczny.
Czyli jest sposób taki, który nie potrzebuje ESB a daje ten sam efekt (czyli między innymi luźne powiązania między komponentami)? Mimo wszystko teraz nie potrafię go sobie wyobrazić, ale to raczej wina mojej niewiedzy. Czytałem kiedyś artykuł na stronach IBMa o tym, że po ESB trzeba sięgać ostrożnie, bo jego wymagania (nad zarządzaniem) mogą przerosnąć jego zalety. Sądzę jednak, że IBM miał na myśli te duże ESB.
A samo ESB nie musi być ani drogie, ani skomplikowane. Wystarczy sięgnąć po rozwiązania spoza mainstreamu, np: https://zato.io/
P.
Przede wszystkim nie łączmy pojęć “produkt cośESB firmy XXX” i “komponent realizujący logikę wymiany danych”. To także powód, dla którego nigdy w projektach integracyjnych nie operuję pojęciem ESB. To dopiero z wymagań i projektu architektury może wynikać, że taki komponent jest potrzebny. W przeciwnym wypadku można doprowadzić do sytuacji, w której najpierw ktoś kupuje “cośESB” a potem na siłę szuka mu zastosowania (w kontekście uwagi na stronach IBM i kilku wielkich porażek w tym kraju). Wybór “implementacji ESB” powinien być konsekwencją wymagań i rentowności a nie mody ;), wiem, ze są i drogie i niedrogie i open source i nie… Nie raz okazuje się, że taki komponent po prostu nie jest wymagany.
Ciekawe informacje o integracji i wzorcach architektonicznych można znaleźć tu: EIP
Ciekawy artykuł o integracji z użyciem ESB