Wzorce projektowe Książki

Wzorce projektowe w analizie i projektowaniu modelu dziedziny systemu

Analiza biz­ne­so­wa i projektowanie

Wstęp

W arty­ku­le o apli­ka­cjach webo­wych, ponad rok temu, pisałem:

Generalnie klu­czo­wą cechą micro-ser­wi­­sów, czy­nią­cą z nich tak zwa­ną zwin­ną archi­tek­tu­rę, jest cał­ko­wi­ta wza­jem­na nie­za­leż­ność imple­men­ta­cji poszcze­gól­nych usług apli­ka­cyj­nych. (źr.: Aplikacje webo­we i mikro­ser­wi­sy czy­li archi­tek­tu­ra sys­te­mów webo­wych).

Przy innej oka­zji pisa­łem o wzorcach:

Wzorce pro­jek­to­we to bar­dzo waż­na część ??zawo­du? ana­li­ty­ka i archi­tek­ta opro­gra­mo­wa­nia. […] Generalnie wzor­ce są to ska­ta­lo­go­wa­ne stan­dar­dy i dobre prak­ty­ki . (Obiektowe wzor­ce projektowe ) 

Szkolenia dla ana­li­ty­ków poprze­dzam ankie­ta­mi przed szko­le­nio­wy­mi, jak do tej pory żad­na nie zawie­ra­ła pytań o wzor­ce pro­jek­to­we: ani tego że są uży­wa­ne ani tego, że są celem szko­le­nia, nie­mal­że każ­dy dekla­ru­je albo, że uży­wa UML lub, że chce zacząć uży­wać UML, nawet gdy są to pro­gra­mi­ści. Zauważyłem, że wzor­ce pro­jek­to­we w świa­do­mo­ści ana­li­zy biz­ne­so­wej i pro­jek­to­wa­nia (OOAD) nie ist­nie­ją”. Wśród pro­gra­mi­stów, jeże­li jest spo­ty­ka­na, to wie­dza o wzor­cach przy­dat­nych w two­rze­niu biblio­tek i narzę­dzi, czę­sto też powie­la­ne są wyuczo­ne sta­re i złe prak­ty­ki pro­gra­mi­stycz­ne rodem z lat 60-tych (np. prak­ty­ki SmallTalk, patrz dalej). 

Z dru­giej stro­ny od wie­lu lat zna­ne są tech­ni­ki MDA (Model Driven Architecture) czy MBSE (Model Based System Engineering), któ­re w róż­nych for­mach, ale jed­nak wska­zu­ją, że naj­sku­tecz­niej­sza for­ma wyra­ża­nia wyma­gań wobec roz­wią­za­nia to pro­jekt archi­tek­tu­ry i logi­ki dzie­dzi­no­wej (model) dzia­ła­nia apli­ka­cji . O pro­jek­to­wa­niu poprze­dza­ją­cym imple­men­ta­cję pisze sie od dość daw­na, meto­dy obiek­to­we i dobre prak­ty­ki zna­ne są od lat .

Autorzy BABoK prak­tycz­nie od począt­ku ist­nie­nia tego wydaw­nic­twa, zwra­ca­ją uwa­gę na tak zwa­ną bia­łą skrzyn­kę”, czy­li wyma­ga­nia wyra­żo­ne w posta­ci wewnętrz­nej struk­tu­ry pro­duk­tu, wska­zu­jąc, że to znacz­nie sku­tecz­niej­sza meto­da defi­nio­wa­nia wyma­gań wobec roz­wią­za­nia, niż tak zwa­na czar­na skrzyn­ka”, czy­li tra­dy­cyj­ne, i jed­nak mniej sku­tecz­ne, wyma­ga­nia wyra­żo­ne tyl­ko jako cechy funk­cjo­nal­ne i poza-funk­cjo­nal­ne. Pamiętajmy, że adre­sa­tem wyma­gań jest zawsze dostaw­ca produktu!

Kluczowe definicje

Generalnie wzo­rzec pro­jek­to­wy (ang. design pat­tern) w inży­nie­rii jest powszech­nie defi­nio­wa­ny jako: uni­wer­sal­ne, spraw­dzo­ne w prak­ty­ce roz­wią­za­nie. Kolejnym waż­nym poję­ciem jest poli­ty­ka. Z per­spek­ty­wy spo­so­bu postę­po­wa­nia, słow­nik języ­ka pol­skie­go defi­niu­je poli­ty­kę jako: zręcz­ne i układ­ne dzia­ła­nie w celu osią­gnię­cia okre­ślo­nych zamierzeń”. 

Polityka (poli­ty­ki) to poję­cie ogól­niej­sze niż wzo­rzec. Wyraża ona gene­ral­ne zasa­dy, te zaś dopie­ro impli­ku­ją sto­so­wa­nie okre­ślo­nych wzor­ców. Pozostaje ostat­nie już waż­ne poję­cie: para­dyg­mat: jest to przy­ję­ty spo­sób widze­nia rze­czy­wi­sto­ści w danej dzie­dzi­nie, dok­try­nie itp. Np. poli­ty­ką jest umo­wa (wyma­ga­nie), że sto­su­je­my wzorce. 

Paradygmat obiek­to­wy pro­jek­to­wa­nia opro­gra­mo­wa­nia to przy­ję­cie zało­że­nia, że opro­gra­mo­wa­nie to współ­pra­cu­ją­ce obiek­ty (kom­po­nen­ty). Kluczową cechą obiek­tu jest to, że nie ujaw­nia on swo­jej wewnętrz­nej budo­wy (her­me­ty­za­cja) a jedy­ną for­mą współ­pra­cy obiek­tów jest ich reago­wa­nie na wza­jem­nie prze­ka­zy­wa­ne bodź­ce (obiekt ma okre­ślo­ne zacho­wa­nia, wię­cej w arty­ku­le: para­dyg­mat obiek­to­wy). Reakcja na bodziec i wynik tej reak­cji zale­ży od obiek­tu a nie od bodź­ca (poli­mor­fizm). Definicja tego para­dyg­ma­tu jest prak­tycz­nie toż­sa­ma z ogól­niej­szą defi­ni­cją, jaką jest defi­ni­cja poję­cia «sys­tem»: zespół logicz­nie powią­za­nych, współ­pra­cu­ją­cych ele­men­tów . Wielu auto­rów doda­je do tej defi­ni­cji w okre­ślo­nym celu”, co uwa­żam za nad­uży­cie, gdyż poję­cie cel ozna­cza czy­jeś świa­do­me dzia­ła­nie, zaś to, że ota­cza­ją­cy nas świat moż­na opi­sać (model) jako sys­tem, nie wyni­ka z tego, że ktoś go celo­wo tak stworzył.

Na koniec defi­ni­cja poję­cia pryn­cy­pium: naj­waż­niej­sza dla kogoś lub dla cze­goś zasa­da albo wartość. 

Wzorce projektowe czy polityki tworzenia architektury?

Podstawową, moim zda­niem, zasa­dą świa­do­me­go zacho­wa­nia jest jego celo­wość. Jeżeli więc sto­su­je­my (jakieś) wzor­ce pro­jek­to­we to nale­ży okre­ślić cel ich stosowania.

Nie ma sen­su sto­so­wa­nie jakich­kol­wiek wzor­ców dla same­go fak­tu ich sto­so­wa­nia, ale ich świa­do­me sto­so­wa­nie obni­ża ryzy­ko pro­jek­tu i popra­wia jego jakość.

Podstawowym celem inży­nie­rii jest pro­jek­to­wa­nie roz­wią­zań, a ich klu­czo­wą, poza-fun­cjo­nal­ną, cechą są kosz­ty utrzy­ma­nia i rozwoju. 

Wzorce pro­jek­to­we to przede wszyst­kim dobre prak­ty­ki obni­ża­ją­ce kosz­ty utrzy­ma­nia i rozwoju.

Postaram się poka­zać (posta­wić tezę), że gene­ral­nie cho­dzi o pew­ne okre­ślo­ne poli­ty­ki pro­jek­to­wa­nia archi­tek­tu­ry opro­gra­mo­wa­nia, a sku­pię się na spe­cy­fi­ce mode­li PIM .

Literatura na temat wzor­ców pro­jek­to­wych jest bar­dzo boga­ta, myślę że czy­tel­nik łatwo do niej dotrze (patrz mój arty­kuł cyto­wa­ny na począt­ku). W tym tek­ście sku­pię się na bar­dzo waż­nym aspek­cie tych wzor­ców, jakim jest model dzie­dzi­ny sys­te­mu jako obszar ich stosowania. 

Znakomita więk­szość wzor­ców pro­jek­to­wych opi­sy­wa­nych w lite­ra­tu­rze, doty­czy obsza­ru Control i View archi­tek­tu­ry MVC. Stosowanie ich w obsza­rze Model jest bar­dzo czę­stym zja­wi­skiem wśród pro­gra­mi­stów. Powielanie prak­tyk zna­nych z zale­ceń C++ czy SmallTalk jest wręcz złym pomy­słem (patrz pod­su­mo­wa­nie). Czego więc powin­ni nauczyć się ana­li­ty­cy-pro­jek­tan­ci? Tylko tego co wpły­wa na kosz­ty utrzy­ma­nia i roz­wo­ju funk­cjo­nal­no­ści systemu. 

Środowiska wyko­naw­cze (biblio­te­ki, fra­me­wor­ki) zmie­nia­ją się dość wol­no. Upgrade śro­do­wi­ska ma miej­sce co kil­ka lat. Zmiany w funk­cjo­nal­no­ści opro­gra­mo­wa­nia wspie­ra­ją­ce­go zarza­dza­nie zacho­dzą w takt zmian pra­wa i ryn­ku: nawet kil­ka razy w cią­gu roku. Dlatego wła­śnie decy­zje o zasto­so­wa­niu tech­nik i wzor­ców pro­jek­to­wych nale­ży podej­mo­wać w kon­tek­ście tego czy pro­jek­tu­je­my: imple­men­ta­cję logi­ki biz­ne­so­wej czy śro­do­wi­sko apli­ka­cji. To dru­gie sta­wia wyłącz­nie wyma­ga­nia takie jak wydaj­ność i nie­za­wod­ność oraz kompatybilność.

Oprogramowanie biz­ne­so­we (mecha­nizm reali­za­cji logi­ki biz­ne­so­wej) ma nie tyl­ko dłu­gi cykl życia ale i bar­dzo burzliwy.

Dlatego do reali­za­cji Modelu Dziedziny (kom­po­nent reali­zu­ją­cy logi­kę biz­ne­so­wą) wyma­ga­ne jest inne podej­ście niż do reali­za­cji wyma­gań poza-funkcjonalnych. 

Jedną z klu­czo­wych cech archi­tek­tu­ry speł­nia­ją­cej powyż­sze, eko­no­micz­ne, wyma­ga­nia jest zasa­da OCP (Open-Closed Principle): opro­gra­mo­wa­nie jest otwar­te na roz­sze­rze­nia, ale zamknię­te na zmia­ny. Oznacza to, że pro­jek­tant będzie mógł (powi­nien móc) doda­wać kolej­ne funk­cjo­nal­no­ści do kla­sy (kom­po­nen­tu, sys­te­mu), ale nie będzie edy­to­wał obec­nych już funk­cji w spo­sób, któ­ry wpły­wa na ist­nie­ją­cy pozo­sta­ły kod, któ­ry z nie­go korzy­sta. Zasada ta jest czę­ścią zesta­wu zasad zwa­nych SOLID, są wśród nich tak­że: zasa­da poje­dyn­czej odpo­wie­dzial­no­ści klas (ozna­cza jeden kon­tekst a nie jed­ną ope­ra­cję), zasa­da segre­ga­cji inter­fej­sów (to kon­se­kwen­cja poprzed­niej zasa­dy) . Autor tej publi­ka­cji, na pod­sta­wie swo­ich badań, pisze: 

Zgodnie z moimi bada­nia­mi i punk­ta­mi, któ­re omó­wi­li­śmy powy­żej, wnio­sek jest taki, że nie ma [nie są sto­so­wa­ne] żad­ne kon­kret­ne zasa­dy i regu­la­cje w pro­jek­to­wa­niu opro­gra­mo­wa­nia. Warto zauwa­żyć, że pro­jek­to­wa­nie jest sty­lem, jed­nak nie wszyst­kie sty­le prze­ba­da­łem. Zaobserwowałem, że pro­jek­tan­ci sto­su­ją róż­ne podej­ścia, np. ta sama agen­cja Narodów Zjednoczonych raz sto­su­je opi­sa­ne zasa­dy a raz nie. Nadal nie ma żad­nych zasad ani wska­zó­wek, któ­re sto­so­wa­ne były by we wszyst­kich przy­pad­kach, cho­ciaż, są pró­by sfor­ma­li­zo­wa­nia dąże­nia doskonałości”.

Moje wie­lo­let­nie obser­wa­cje potwier­dza­ją powyż­sze spo­strze­że­nia: wzor­ce i meto­dy są od lat zna­ne, jed­nak rzad­ko są sto­so­wa­ne. Warto tu zwró­cić uwa­gę na fakt, że mamy rok 2021 a o wzor­cach mówi­my od począt­ków metod obiek­to­wych. Pozostaje pyta­nie: nie są powszech­nie sto­so­wa­ne bo nie są dobre, czy nie są sto­so­wa­ne bo wie­dza o nich jest nadal mało roz­po­wszech­nio­na. A może są inne powo­dy? Moim zda­niem wie­dza ta jest powszech­nie dostęp­na, ale nie jest popu­lar­na. Po dru­gie pro­mo­wa­nie zwin­no­ści (czy­li dro­ga na skró­ty) skut­ku­je tak­że ogra­ni­cza­niem prac ana­li­tycz­nych i pro­jek­to­wych w począt­ko­wym eta­pie pro­ce­su two­rze­nia opro­gra­mo­wa­nia, i tu upa­tru­ję głów­ne­go powo­du małej popu­lar­no­ści wzor­ców: wyma­ga­ją eta­pu ana­li­zy i pro­jek­to­wa­nia. Analiza i pro­jek­to­wa­nie pod­no­si pla­no­wa­ne kosz­ty wytwo­rze­nia, ale prak­ty­ka oka­zu­je nie jest praw­dą, że wydłu­ża czas do pierw­sze­go uru­cho­mie­nia. Nie jest tajem­ni­cą, że pierw­szy etap (jego koszt) czę­sto decy­du­je o wybo­rze dostaw­cy, jed­nak mści się to wie­lo­krot­nie na eta­pie utrzy­ma­nia i rozwoju.

Jaką war­tość wno­si sto­so­wa­nie wzor­ców? Pojawia się nastę­pu­ją­cy tok uza­sad­nie­nia ich użycia:

  1. wyznacz­ni­kiem jako­ści opro­gra­mo­wa­nia są kosz­ty w całym jego cyklu życia, a nie tyl­ko na eta­pie wytwa­rza­nia i wdrażania,
  2. klu­czem sta­je więc zasa­da OCP: opro­gra­mo­wa­nie jest otwar­te dla roz­sze­rze­nia, ale zamknię­te na zmia­ny, co w kon­se­kwen­cji pozwa­la na uzy­ska­nie linio­we­go (zamiast wykład­ni­cze­go) wzro­stu łącz­ne­go kosz­tu roz­wo­ju apli­ka­cji: pono­si­my koszt reali­za­cji nowej potrze­by, bez dodat­ko­we­go kosz­tu aktu­ali­za­cji (refak­to­ry­za­cja) już używanego,
  3. w kon­se­kwen­cji zamiast mono­li­tu, sto­su­je­my archi­tek­tu­rę kom­po­nen­to­wą (np. mikro ser­wi­sy, micro aplikacje),
  4. pod­sta­wo­wą jed­nost­ką pro­jek­to­wa­nia i roz­wo­ju sta­je się Usługa Aplikacji mode­lo­wa­na w UML jako Przypadek Użycia (np. patrz Use Case 2.0),
  5. z uwa­gi więc na to, że każ­dy przy­pa­dek uży­cia to odręb­ny, sepa­ro­wa­ny kom­po­nent, mają­cy swój wła­sny cykl życia, wyma­ga­ją­cy tak­że utrzy­ma­nia i roz­wo­ju, wymie­nio­ne zasa­dy (wzor­ce pro­jek­to­we) sto­su­je­my tak­że do pro­jek­to­wa­nia jego wewnętrz­nej architektury.

System to jego archi­tek­tu­ra oraz zacho­wa­nie (struk­tu­ra i reak­cja cało­ści na bodź­ce). Dlatego mówiąc o wzor­cach pro­jek­to­wych, mówi­my o wzor­cach archi­tek­to­nicz­nych i o wzor­cach zacho­wa­nia. W tym opra­co­wa­niu sku­pię się głów­nie na wzor­cach archi­tek­to­nicz­nych, o wzor­cach (zasa­dach) zacho­wa­nia wspomnę. 

Architektura oparta na wzorcach – po kolei

Umowa na zakres czyli jakie usługi

Na tym eta­pie podej­mu­je­my decy­zję «Co i dla kogo apli­ka­cja ma robić» (a nie JAK). 

Zakres pro­jek­tu pro­jek­to­wa­nia opro­gra­mo­wa­nia wyra­żo­ny w posta­ci usług apli­ka­cji (przy­pad­ki uży­cia sys­te­mu w nota­cji UML)

Diagram Przypadków Użycia to dia­gram pomoc­ni­czy w UML . Jego celem jest zawar­cie umo­wy na to co ma powstać i dla kogo, czy­li spre­cy­zo­wa­nie wyma­gań wobec sys­te­mu. Bardzo waż­ne: tu wyma­ga­niem biz­ne­so­wym (usłu­ga apli­ka­cyj­na) jest to CO chce uzy­skać Aktor Systemu a nie to JAK to będzie reali­zo­wa­ne. Decyzja JAK jest decy­zją pro­jek­tan­ta roz­wią­za­nia, decy­zja CO jest usta­le­niem celu two­rze­nia opro­gra­mo­wa­nia. Usługa z per­spek­ty­wy Aktora, to opis reak­cji Systemu. Zachowanie bar­dzo czę­sto doku­men­tu­je­my, począt­ko­wo nie­for­mal­nie, w posta­ci pro­ce­du­ry tek­sto­wej (np. wypunk­to­wa­na lista kolej­nych kro­ków). Kolejny etap to ite­ra­cyj­no-przy­ro­sto­wa for­ma­li­za­cja opi­su zacho­wa­nia z pomo­cą dia­gra­mu aktyw­no­ści lub sekwen­cji . Diagram aktyw­no­ści to naj­czę­ściej idea wza­jem­nej komu­ni­ka­cji kom­po­nen­tów, dia­gram sekwen­cji wska­zu­je już na ope­ra­cje kom­po­nen­tów (ale na dia­gra­mach aktyw­no­ści tak­że moż­na to pokazać).

Architektura aplikacji

Tak zwa­ną archi­tek­tu­rę wyso­kie­go pozio­mu (ang. HLD, High Level Design) budu­je­my już na bazie wzor­ca mówią­ce­go, że usłu­gi apli­ka­cji imple­men­tu­je­my jako odręb­ne kom­po­nen­ty, sepa­ru­je­my je tak­że od resz­ty oto­cze­nia. Idea takich mikro­ser­wi­sów jest zna­na od daw­na, jeden z naj­po­pu­lar­niej­szych chy­ba, zna­nych mi, sche­ma­tów blo­ko­wych poka­zu­je to tak:

About Microservices | Bee Travels
Monolit vs. mikroserwisy

Więc nasza Aplikacja powin­na mieć np. taką wewnętrz­ną architekturę:

Architektura wyso­kie­go pozio­mu” sys­te­mu, wyra­żo­na jako dia­gram kom­po­nen­tów UML.

Komponenty reali­zu­ją­ce Usługi Aplikacji są inte­gro­wa­ne w Portalu, zewnętrz­ne usłu­gi są izo­lo­wa­ne Adapterem. Zaleca to wie­lu pro­du­cen­tów fra­me­wor­ków, np.:

Microservice Using ASP.NET Core
(https://www.c‑sharpcorner.com/article/microservice-using-asp-net-core/)

W kolej­nych kro­kach zaj­mie­my się logi­ką reali­zo­wa­ną przez kom­po­nen­ty odpo­wie­dzial­ne za dostar­cza­nie usług. Z uwa­gi na to, że zawsze nale­ży się spo­dzie­wać wewnętrz­nej inte­gra­cji (np. jeden kom­po­nent udo­stęp­nia Słownik dla dru­gie­go) uzu­peł­nia­my nasz model o interfejsy:

Architektura wyso­kie­go pozio­mu”, uzu­peł­nio­na o wewnętrz­ne inter­fej­sy (archi­tek­tu­ra integracji).

Powyższy model to sta­tycz­ny opis archi­tek­tu­ry. Opis zacho­wa­nia, bazu­ją­cy na wzor­cu Łańcuch odpo­wie­dzial­no­ści” może wyglą­dać jak poniżej:

Scenariusz reali­za­cji Usługi Aplikacji 1 na pozio­mie HLD, dia­gram sekwen­cji UML (sce­na­riusz integracji).

Architektura usługi aplikacji

W latach 90-tych powstał wzo­rzec BCE (ang. Boundary, Control, Entity) w ramach dość cięż­kiej meto­dy­ki RUP (Rational Unified Process) i ICONIX . To były począt­ki orien­ta­cji na kom­po­nen­ty i przy­pad­ki uży­cia. Inżynieria opro­gra­mo­wa­nia i wzor­ce ewo­lu­ują, postrze­ga­nie tego wzor­ca tak­że. Poniżej pro­sta archi­tek­tu­ra na bazie tego wzorca:

Architektura reali­za­cji poje­dyn­czej usłu­gi apli­ka­cyj­nej (przy­pad­ku użycia)

Wzorzec bazu­je na zasa­dzie poje­dyn­czej odpo­wie­dzial­no­ści oraz na wzor­cu zacho­wa­nia: Kaskada (łań­cuch) odpo­wie­dzial­no­ści. Komponent Boundary odpo­wia­da wyłącz­nie za dia­log z Aktorem. Komponent Control odpo­wia­da wyłącz­nie za reali­za­cję logi­ki biz­ne­so­wej, kom­po­nent Entity odpo­wia­da wyłącz­nie za utrwa­la­nie danych (pier­wot­nie były to obiek­ty DAO: ang. Data Access Object, sta­no­wią­ce sobą zapy­ta­nia SQL do rela­cyj­nych baz danych).

Z per­spek­ty­wy cza­su zmie­ni­ło sie wie­le ale nie para­dyg­ma­ty. Obiektów Entity są set­ki, tysią­ce, a obec­nie milio­ny (BigData) co może powo­do­wać pro­blem z per­spek­ty­wy logi­ki (Control), któ­ra z tej kolek­cji danych korzy­sta. Do tego pro­ste­go wzor­ca doda­je­my więc inter­fejs sepa­ru­ją­cy logi­kę (Control) od ogrom­nej nie raz kolek­cji obiek­tów, któ­rych jedy­ną rolą jest prze­cho­wy­wa­nie danych. Z uwa­gi na to, że kon­tro­lo­wa­ny dostęp do kolek­cji obiek­tów to tak­że logi­ka, iko­na kla­sy (gra­ficz­ne ozna­cze­nie ste­reo­ty­pu) jest taka jak iko­na kom­po­nen­tu Control:

Architektura reali­za­cji poje­dyn­czej usłu­gi apli­ka­cyj­nej z uży­ciem wzor­ca Repository (Repozytorium)

Modyfikacja pole­ga tu na tym, że kolek­cję obiek­tów repre­zen­tu­ją­cych dane (obiek­ty kla­sy Entity) oddzie­la­my od resz­ty apli­ka­cji (her­me­ty­zu­je­my) za pomo­cę logi­ki reali­zu­ją­cej inter­fejs do tej kolek­cji. Ten kom­po­nent reali­zu­je dostęp do danych i ewen­tu­al­ne zasa­dy dostę­pu. Obiekty Entity z zasa­dy nie reali­zu­ją żad­nej logi­ki biz­ne­so­wej, zacho­wu­ją jedy­nie dane, mają wyłącz­nie ope­ra­cje zapisz/przywołaj, two­rzo­ne i usu­wa­ne są przez logi­kę usłu­gi lub przez dodat­ko­wą usłu­gę, gdy zaj­dzie taka potrze­ba. Wzorzec ten (kolek­cja obiek­tów i inter­fejs do niej) nazy­wa się Repozytorium (Repository).

Jak wyglą­da tu roz­wój i roz­bu­do­wa? Jeżeli mody­fi­ka­cja nie wpro­wa­dza nowych wewnętrz­nych usług, a jedy­nie ulep­sza (np. nowy lep­szy algo­rytm) już ist­nie­ją­ce, wystar­czy zmia­na, któ­ra nie wyj­dzie” poza mody­fi­ko­wa­ny kom­po­nent (her­me­ty­za­cja). Jeżeli doj­dzie do roz­bu­do­wy funk­cjo­nal­no­ści, nale­ży zapro­jek­to­wać nowy kom­po­nent i włą­czyć go do architektury:

Architektura reali­za­cji poje­dyn­czej usłu­gi apli­ka­cyj­nej z uży­ciem wzor­ca Repository po doda­niu ele­men­tu nowej logi­ki: Control3.

Nowy kom­po­nent Control3 został doda­ny w spo­sób mini­ma­li­zu­ją­cy zmia­ny. Komponent Control2 prak­tycz­nie peł­ni role inter­fej­su do nie­go. Jest to bar­dzo wygod­ne, bo mógł to być np. kom­po­nent kupio­ny na ryn­ku, z inter­fej­sem (ope­ra­cje) wyma­ga­ją­cym dopa­so­wa­nia, wte­dy Control2 peł­ni rolę inter­fej­su i adap­te­ra (nie ma inne­go doj­ścia do Control3, jest on her­me­ty­zo­wa­ny w tej archi­tek­tu­rze za kom­po­nen­tem Control2). Tak wła­śnie wyglą­da reali­za­cja zasa­dy OCP w toku roz­wo­ju aplikacji.

Dane

Naturalną for­mą zarzą­dza­nia infor­ma­cją są doku­men­ty a nie rela­cyj­ne bazy danych”. 

Relacyjny model danych opra­co­wał Edgar Codd w 1970 roku, jego celem i klu­czo­wą zale­tą jest mecha­nizm spój­no­ści i trans­ak­cyj­no­ści zbio­ru danych (ACID). Model ten nie­ste­ty jest bar­dzo nie­na­tu­ral­ny z per­spek­ty­wy doku­men­tów: w mode­lu rela­cyj­nym ich po pro­stu nie ma. Warto pamię­tać, że:

Information Science inc­lu­des two fun­da­men­tal­ly dif­fe­rent tra­di­tions: a docu­ment” tra­di­tion con­cer­ned with signi­fy­ing objects and the­ir use; and a com­pu­ta­tio­nal” tra­di­tion of apply­ing algo­ri­th­mic, logi­cal, mathe­ma­ti­cal, and mecha­ni­cal tech­ni­qu­es to infor­ma­tion mana­ge­ment. Both tra­di­tions have been deeply influ­en­ced by tech­no­lo­gi­cal moder­nism: Technology, stan­dards, sys­tems and effi­cien­cy ena­ble pro­gress. Both tra­di­tions are needed. Information Science is rooted in part in huma­ni­ties and quali­ta­ti­ve social scien­ces. The land­sca­pe of Information scien­ce is com­plex. An ecu­me­ni­cal view is needed.” [Nauka o infor­ma­cji obej­mu­je dwie zasad­ni­czo róż­ne tra­dy­cje: tra­dy­cję doku­men­to­wą”, zaj­mu­ją­cą się opi­sy­wa­niem obiek­tów i ich wyko­rzy­sta­niem, oraz tra­dy­cję obli­cze­nio­wą”, pole­ga­ją­cą na zasto­so­wa­niu tech­nik algo­ryt­micz­nych, logicz­nych, mate­ma­tycz­nych i mecha­nicz­nych do zarzą­dza­nia infor­ma­cją. Obie tra­dy­cje zna­la­zły się pod głę­bo­kim wpły­wem moder­ni­zmu tech­no­lo­gicz­ne­go: Technologia, stan­dar­dy, sys­te­my i wydaj­ność umoż­li­wia­ją postęp. Obie tra­dy­cje są potrzeb­ne. Nauka o infor­ma­cji jest czę­ścio­wo zako­rze­nio­na w naukach huma­ni­stycz­nych i jako­ścio­wych naukach spo­łecz­nych. Krajobraz nauki o infor­ma­cji jest zło­żo­ny. Potrzebne jest spoj­rze­nie ekumeniczne.]

Dlatego są obsza­ry, w któ­rych model rela­cyj­ny spraw­dza sie dosko­na­le (obli­cze­nia) i obsza­ry, w któ­rych nie spraw­dza się wca­le (doku­men­ty).

Pojawiły się (pra­wie 20 lat temu) bazy NoSQL (Not only SQL). Porównania poka­zu­ją też, że bazy NoSQL (np. doku­men­to­we) ofe­ru­ją znacz­nie szyb­szy dostęp do danych . Porównania poka­zu­ją, że czas zapi­su i dostę­pu do zło­żo­nych doku­men­tów w bazach NoSQL jest nawet o trzy rzę­dy (tysiąc­krot­nie!) krót­szy niż w bazach SQL . Model rela­cyj­ny to sztyw­na struk­tu­ra i po utwo­rze­niu jest prak­tycz­nie nie­zmien­ny. Niestety w obec­nych cza­sach sta­bil­na na wie­le lat struk­tu­ra danych to prak­tycz­nie fik­cja. Po dru­gie udział danych struk­tu­ral­nych w ogól­nej ilo­ści zbie­ra­nych danych sta­le spa­da, oce­nia się, że obec­nie dane struk­tu­ral­ne to <10% ogó­łu zebra­nych danych (wie­dzy). Dokumenty biz­ne­so­we, ich struk­tu­ra, zmie­nia­ją sie wraz ze zmia­na­mi pra­wa i mode­li biz­ne­so­wych, czy­li nie raz nawet czę­ściej niż raz w roku. Dlatego opar­cie się na doku­men­to­wych wzor­cach jest obec­nie znacz­nie sku­tecz­niej­sze, mikro­ser­wi­sy zresz­tą z zasa­dy wyklu­cza­ją mono­li­tycz­ne rela­cyj­ne bazy danych.

Rezygnacja z mode­li rela­cyj­nych zna­ko­mi­cie uprasz­cza etap ana­li­zy i pro­jek­to­wa­nia, nota­cja UML od lat dosko­na­le wspie­ra nie­esqe­lo­we” meto­dy pro­jek­to­wa­nia opro­gra­mo­wa­nia, w tym doku­men­to­we (w szcze­gól­no­ści XML) struk­tu­ry danych . Warto zazna­czyć, że UML nie słu­ży do mode­lo­wa­nia danych w mode­lu relacyjnym!

Dane, biz­ne­so­we w szcze­gól­no­ści, są orga­ni­zo­wa­ne w struk­tu­ry doku­men­to­we, jest to ich natu­ral­na postać (wię­cej na ten temat w arty­ku­le Struktury for­mu­la­rzy jako for­ma wyra­ża­nia wyma­gań).

Dokumentowa struk­tu­ra danych wyra­żo­na w posta­ci Diagramu Struktur Złożonych UML (źr. I jak to wszyst­kim poka­zać żeby było czy­tel­ne?)

W efek­cie osta­tecz­na postać mode­lu reali­za­cji usłu­gi ma postać:

Architektura reali­za­cji poje­dyn­czej usłu­gi apli­ka­cyj­nej z uży­ciem wzor­ca Repository po doda­niu ele­men­tu nowej logi­ki i nośni­ka danych jakim jest Formularz

Jak widać dane i ich struk­tu­ry (doku­men­ty) są cał­ko­wi­cie oddzie­lo­ne od metod ich two­rze­nia, korzy­ści z takie­go podej­ścia opi­su­je Evans w DDD, reko­men­da­cje takie moż­na zna­leźć u wie­lu innych auto­rów . Ten pro­jekt nie wyma­ga żad­ne­go SQL i rela­cyj­ne­go mode­lu. Na eta­pie pro­jek­to­wa­nia na pew­no, a na eta­pie imple­men­ta­cji obec­nie raczej też nie. 

Architektura usłu­gi to dość pro­sta struk­tu­ra. Każdy kon­kret­ny przy­pa­dek uży­cia (usłu­ga apli­ka­cji) może być nie­co inny, ale ogól­na idea zasto­so­wa­nia zasad: łań­cuch odpo­wie­dzial­no­ści (nie pomi­ja­my żad­ne­go kom­po­nen­tu w dro­dze od akto­ra do doku­men­tu), repo­zy­to­rium (inter­fejs do kolek­cji obiek­tów biz­ne­so­wych), i nowe zacho­wa­nia, to nowe a nie zmie­nio­ne, kom­po­nen­ty zorien­to­wa­ne na role. Całość daje bar­dzo przy­dat­ny zestaw tyl­ko kil­ku wzor­ców na eta­pie ana­li­zy i pro­jek­to­wa­nia mode­lu dzie­dzi­ny sys­te­mu (kom­po­nent reali­zu­ją­cy logi­kę biz­ne­so­wą, czy­li wyma­ga­nia funk­cjo­nal­ne, to Model Dziedziny Systemu) . Model opi­su­ją­cy inte­rak­cje tych kom­po­nen­tów był­by zbu­do­wa­ny ana­lo­gicz­nie jak wcze­śniej poka­za­ny dla archi­tek­tu­ry HLD. 

W real­nym pro­jek­cie każ­da kla­sa mia­ła­by oczy­wi­ście ope­ra­cje. Tu tego nie poka­zy­wa­łem by nie kom­pli­ko­wać dia­gra­mów. Przykład real­ne­go pro­jek­tu wyko­na­ne­go wg. powyż­szych reguł opi­sa­łem w arty­ku­le Inżynieria opro­gra­mo­wa­nia z uży­ciem narzę­dzia CASE ? przy­kła­do­wy pro­jekt. Szczegóły oma­wiam na szko­le­niach: Analiza obiek­to­wa i pro­jek­to­wa­nie logi­ki opro­gra­mo­wa­nia z uży­ciem nota­cji UML.

Podsumowanie

To co opi­sa­no to archi­tek­tu­ra kom­po­nen­to­wa zna­na od ponad 20 lat . Orientacja na odpo­wie­dzial­ność klas zna­na od 2003 roku, książ­ka Rebeki Wirfs-Brock jest cyklicz­nie wzna­wia­na . Także w 2003 roku, w duchu powyż­szych zasad, Eric Evans opi­sał wzo­rzec Domain Driven Design . Jest on nadal pod­sta­wą wie­lu frameworków.

Problemem jaki dostrze­gam, jest uprosz­czo­na edu­ka­cja na stu­diach, zrów­nu­ją­ca pro­jek­to­wa­nie obiek­to­we z pro­gra­mo­wa­niem obiek­to­wym. To co nazy­wa­my pro­gra­mo­wa­niem obiek­to­wym jest czę­sto defi­nio­wa­ne na bazie cech języ­ka Smalltalk (Smalltalk ? naj­czyst­szy z obiek­to­wych języ­ków pro­gra­mo­wa­nia) lub C++: 

  1. Wszystko jest obiektem
  2. Każdy obiekt jest instan­cją klasy
  3. Każda kla­sa ma kla­sę nadrzędną
  4. Wszystko dzie­je się przez wysy­ła­nie wiadomości
  5. Wyszukiwanie metod uży­wa łań­cu­cha dziedziczenia

I to nie­ste­ty jest klu­czo­we źró­dło wie­lu pro­ble­mów. Punkt 3. jest jed­ną z naj­gor­szych i naj­kosz­tow­niej­szych prak­tyk w obsza­rze mode­lu dzie­dzi­ny, uza­leż­nia­ją­cych defi­ni­cje klas od sie­bie (łama­nie klu­czo­wej zasa­dy jaką jest her­me­ty­za­cja). Punkt 5 jest w zasa­dzie mar­twy, bo meto­dy albo są zna­ne bo wyma­ga­ne inter­fej­sem, albo nie wie­my, że są (kosz­tow­ne, osie­ro­co­ne ele­men­ty kodu w wie­lu sys­te­mach). Dziedziczenie z zasa­dy łamie her­me­ty­za­cję (współ­dzie­le­nie ele­men­tów kodu, przy­po­mi­nam, że dzie­dzi­cze­nie usu­nię­to z UML w 2015 roku). Tak więc para­dyg­mat obiek­to­wy to po pro­stu komu­ni­ku­ją­ce się obiek­ty i tak pro­jek­tu­je­my. Klasy to wyłącz­nie defi­ni­cje obiek­tów w kodzie źró­dło­wym, i tak kodu­je­my (UWAGA! Kod pro­gra­mu wyra­żo­ny w języ­ku obiek­to­wym to meta­mo­del dzia­ła­ją­ce­go pro­gra­mu!). Typowymi popu­lar­ny­mi i zły­mi prak­ty­ka­mi są umiesz­cza­nie metod kre­acyj­nych w ich kla­sach bazo­wych czy pobie­ra­nie i zapi­sy­wa­nie war­to­ści atry­bu­tów pole­ce­nia­mi get/set-atry­but. Szkodliwość tej dru­giej prak­ty­ki opi­sał Fowler w Tell don’t ask . Fowler jest auto­rem jed­nej z naj­po­pu­lar­niej­szych na świe­cie pozy­cji o wzor­cach pro­jek­to­wych, mają­cej już kil­ka wzno­wień i aktu­ali­za­cji .

Jak poka­za­no, ana­li­za i pro­jek­to­wa­nie DOSKONALE oby­wa się bez SQL i rela­cyj­nych mode­li danych (nie uży­wam ich na eta­pie ana­li­zy i pro­jek­to­wa­nia od ponad 15 lat i nie jestem w tym osa­mot­nio­ny na świe­cie). Problem jaki stwa­rza­ją usil­nie pro­jek­to­wa­ne i reali­zo­wa­ne sys­te­mo­we rela­cyj­ne mode­le danych” jest zna­ny od dekad:

(Designing Object Systems: Object-Oriented Modelling with Syntropy Textbook Binding ? November 18, 1994 by Steve Cook (Author), John Daniels (Author))

Odejście od tej prak­ty­ki (mode­le danych i SQL od same­go począt­ku ana­li­zy i pro­jek­to­wa­nia) pozwa­la pro­jek­to­wać apli­ka­cje nie­za­leż­nie od metod imple­men­ta­cji, zro­zu­mia­łe dla inte­re­sa­riu­szy. Projekt roz­wią­za­nia na tym eta­pie (przed wybo­rem dostaw­cy) z zasa­dy powi­nien abs­tra­ho­wać od imple­men­ta­cji (jest to model PIM, nie­za­leż­ny od plat­for­my imple­men­ta­cji). Dzięki cze­mu cała doku­men­ta­cja, jeże­li zosta­nie napi­sa­na języ­kiem i słow­nic­twem inte­re­sa­riu­sza (patrz DDD), może być zro­zu­mia­ła dla niego. 

No i na koniec: chmu­ro­we sys­te­my utrwa­la­nia danych nie ope­ru­ją języ­kiem SQL i rela­cyj­nym mode­lem danych, więc pora w koń­cu zapo­mnieć o SQL i rela­cyj­nie zor­ga­ni­zo­wa­nych danych na eta­pie ana­li­zy i pro­jek­to­wa­nia. Zresztą dużych trans­ak­cyj­nych sys­te­mów, nie­ko­rzy­sta­ją­cych z SQL i rela­cyj­ne­go sys­te­mu orga­ni­za­cji danych, jest bar­dzo dużo, nie tyl­ko sklep Amazon. 

Lista wzorców wykorzystana w artykule

  • BCE (Boundary, Control, Entity) – dekla­ro­wa­nie odpo­wie­dzial­no­ści obiek­tów klas: B – pośred­ni­cze­nie pomię­dzy apli­ka­cją a jej oto­cze­niem, C – reali­za­cja logi­ki dzie­dzi­no­wej, E – reali­za­cja utrwalania,
  • agre­gat – prze­cho­wy­wa­nie danych w zwar­tej, hie­rar­chicz­nej struk­tu­rze (jako doku­ment, np. XML),
  • saga – zarzą­dza­nie trans­ak­cja­mi (sekwen­cje pro­ce­du­ry) z jed­ne­go miej­sca (rola obiek­tu Control),
  • łań­cuch odpo­wie­dzial­no­ści – kaska­do­we prze­ka­zy­wa­nie wywo­łań od kra­wę­dzi apli­ka­cji do danych i spowrotem,
  • repo­zy­to­rium – sepa­ro­wa­nie kolek­cji obiek­tów Entity od resz­ty apli­ka­cji za pomo­cą obiek­tu reali­zu­ją­ce­go kon­tro­lę dostę­pu do tej kolek­cji (inter­fejs do danych),
  • micro ser­wis (lub mikro-apli­ka­cja) – imple­men­ta­cja każ­dej usłu­gi sys­te­mu jako odręb­ne­go kom­po­nen­tu, poprze­dza­nie cało­ści kom­po­nen­tem, reali­zu­ją­cym por­tal dostępowy.

Dostępny jest warsz­tat, na któ­rym może w prak­ty­ce poznać te wzor­ce i prze­ćwi­czyć ich sto­so­wa­nie w prak­ty­ce: ZAPRASZAM.

Źródła

Jaiswal, M. (2019). Software Architecture and Software Design. International Research Journal of Engineering and Technology (IRJET) e‑ISSN, 2395 – 0056.
IIBA. (n.d.). A Guide to the Business Analysis Body of Knowledge®. Retrieved October 30, 2021, from https://www.iiba.org/career-resources/a‑business-analysis-professionals-foundation-for-success/babok/
OMG​.org. (2017, December). Unified Modeling Language (UML) [OMG​.org]. UML. https://​www​.omg​.org/​s​p​e​c​/​U​ML/
Zelinski, J. (2020). Synthesis of MOF, MDA, PIM, MVC, and BCE Notations and Patterns. In Applications and Approaches to Object-Oriented Software Design: Emerging Research and Opportunities (pp. 78 – 89). IGI Global. https://​www​.igi​-glo​bal​.com/​b​o​o​k​/​a​p​p​l​i​c​a​t​i​o​n​s​-​a​p​p​r​o​a​c​h​e​s​-​o​b​j​e​c​t​-​o​r​i​e​n​t​e​d​-​s​o​f​t​w​a​r​e​/​2​3​5​699
Ozkaya, M., & Fidandan, I. (2020). MVCLang: A Software Modeling Language for the Model-View-Controller Design Pattern: Proceedings of the 15th International Conference on Software Technologies, 75 – 83. https://​doi​.org/​1​0​.​5​2​2​0​/​0​0​0​9​5​7​1​4​0​0​7​5​0​083
Michael Buckland. (1998). Landscape of Information Science: ASIS at 62. Berkeley Univerity of California. https://people.ischool.berkeley.edu/~buckland/asis62.html
Šilingas, D., & Butleris, R. (2009). Towards imple­men­ting a fra­me­work for mode­ling softwa­re requ­ire­ments in MagicDraw UML. Information Technology and Control, 38(2).
Rosenberg, D., & Stephens, M. (2007). Introduction to ICONIX Process. Use Case Driven Object Modeling with UML: Theory and Practice, 1 – 20.
Rosenberg, D., & Scott, K. (1999). Use case dri­ven object mode­ling with UML. Springer.
Rosenberger, P., Gerhard, D., & Dumss, S. (2019). Modelling the Behaviour of Context-awa­re Systems: State-of-the-Art Analysis and Introduction of a Customized UML Profile. MODELSWARD, 519 – 526.
Martin Fowler, & Martin Fowler. (2013). bli­ki: TellDontAsk [Martinfowler​.com]. Martinfowler​.Com. https://​mar​tin​fow​ler​.com/​b​l​i​k​i​/​T​e​l​l​D​o​n​t​A​s​k​.​h​tml
Garba, M. (2020). A Comparison of NoSQL and Relational Database Management Systems (RDBMS). 1(2), 9.
D’Souza, D. (1998). Objects, Components, and Frameworks with UML The CatalysisTM Approach. 116.
Győrödi, C., Győrödi, R., Pecherle, G., & Olah, A. (2015). A com­pa­ra­ti­ve stu­dy: MongoDB vs. MySQL. 2015 13th International Conference on Engineering of Modern Electric Systems (EMES), 1 – 6. https://​doi​.org/​1​0​.​1​1​0​9​/​E​M​E​S​.​2​0​1​5​.​7​1​5​8​433
Lippert, M., Roock, S., & Züllighoven, H. (n.d.). From Documents to Applications via Frameworks: the Tools and Materials appro­ach. 2.
Jenney, J., Gangl, M., Kwolek, R., Melton, D., Ridenour, N., & Coe, M. (2010). Modern methods of sys­tems engi­ne­ering: with an intro­duc­tion to pat­tern and model based methods. Joe Jenney.
Wirfs-Brock, R., & McKean, A. (2009). Object design: roles, respon­si­bi­li­ties, and col­la­bo­ra­tions. Addison-Wesley.
Bertalanffy, L. van. (2003). General sys­tem the­ory: foun­da­tions, deve­lop­ment, appli­ca­tions (Rev. ed., 14. paper­back print). Braziller.
Cook, S., & Daniels, J. (1994). Designing object sys­tems: object-orien­ted model­ling with Syntropy. Prentice Hall.
Akehurst, D. H. (2004). Computer Science at Kent. Citeseer.
Fowler, M. (1997). Analysis pat­terns: reu­sa­ble object models. Addison Wesley.
Rosenberg, D., Stephens, M., & Collins-Cope, M. (2005). Agile deve­lop­ment with ICONIX pro­cess: people, pro­cess, and prag­ma­tism. Apress.
Züllighoven, H., & Beeger, R. F. (2005). Object-orien­ted con­struc­tion hand­bo­ok: deve­lo­ping appli­ca­tion-orien­ted softwa­re with the tools & mate­rials appro­ach. Morgan Kaufmann ; dpunkt.verlag.
Evans, E. (2003). Domain-Driven Design. Pearson Education (US).

Inne artykuły na podobny temat

image_print(wydruk PL)

Dodaj komentarz

Twój adres email nie zostanie opublikowany

Komentuj i zadawaj pytania autorowi.

Identyfikator *
E-mail *
Witryna internetowa

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.