Architektura… najpierw a nie na końcu

Szperałem w sie­ci szu­ka­jąc infor­ma­cji o archi­tek­tu­rze i micro­se­rvi­sach, a wpa­dłem na to:

… com­mu­ni­ca­tion betwe­en two dif­fe­rent softwa­re modu­les is pro­por­tio­nal to the com­mu­ni­ca­tion betwe­en the desi­gners and deve­lo­pers of the­se modu­les. Conway?s law expo­ses the vul­ne­ra­bi­li­ty in mono­li­ths as they grow in size. Micro-servi­ces may not be the best, but bet­ter than mono­li­ths for the con­tem­po­ra­ry web based appli­ca­tions. (Źródło: Micro-Services: A com­pa­ri­son with Monoliths | My Blog)

To pra­wo” wyja­śnia dla­cze­go powsta­ją złe inter­fej­sy a nawet zła archi­tek­tu­ra: z regu­ły dla­te­go, że to – archi­tek­tu­ra – jest lep­szym lub gor­szym kom­pro­mi­sem pomię­dzy zespo­ła­mi pro­gra­mi­stów, ich obcią­że­nia, krót­kich ter­mi­nów itp. Obserwuję to dość czę­sto w orga­ni­za­cji pra­cy developerów.

Jednak, żeby powsta­ła taka dobra archi­tek­tu­ra”, ktoś ponad zespo­łem deve­lo­pe­rów” powi­nien zapro­jek­to­wać archi­tek­tu­rę: kom­po­nen­ty z ich odpo­wie­dzial­no­ścia­mi i inter­fej­sy mię­dzy nimi.

Typowym pro­ble­mem jaki napo­ty­kam, nie tyl­ko w dużych pro­jek­tach dla budże­tów­ki”, jest archi­tek­tu­ra będą­ca efek­tem prze­py­cha­nek, poli­ty­ki, wal­ki o men­dej­sy”, czy­li o to któ­ry dostaw­ca (albo wewnętrz­ny zespół) dosta­nie więk­szy budżet. To naj­gor­sze i nie­ste­ty nie raz spo­ty­ka­ne meto­dy budo­wy architektury.

Jak to robić dobrze? Idąc za Fowlerem, pod­sta­wą budo­wy (usta­la­nia) gra­ni­cy odpo­wie­dzial­no­ści kom­po­nen­tu jest gra­ni­ca kon­tek­stu”. Można to przed­sta­wić tak:

Powyżej poka­za­no wynik ana­li­zy, mamy tu model poję­cio­wy. Widać, że pew­ne poję­cia (doce­lo­wo kla­sy, ich ope­ra­cje i atry­bu­ty) są dość gęsto powią­za­ne, inne luź­no. Granice pomię­dzy kom­po­nen­ta­mi powin­no budo­wać się tak, by sil­nie powią­za­ne ele­men­ty były w jed­nym kom­po­nen­cie (nigdy nie roz­dzie­laj rodzi­ny) a inter­fej­sy mię­dzy nimi były jak naj­prost­sze. Stosowanie DTO ozna­cza, że kom­po­nent powi­nien jed­no­ra­zo­wo zażą­dać całe­go agre­ga­tu danych (doku­men­tu) i same­mu sko­rzy­stać, nawet tyl­ko z czę­ści danych któ­re dostał, zamiast deta­licz­nie pro­sić o poszcze­gól­ne pola. Innymi sło­wy nie­za­leż­nie od tego czy w danym momen­cie potrze­bu­je­my tyl­ko war­to­ści kon­kret­nej fak­tu­ry, danych nabyw­cy czy fak­tycz­nie całej jej zawar­to­ści, zawsze żąda­my całej fak­tu­ry. Dzięki temu inter­fejs (API) jest prost­sze, licz­ba wywo­łań API jest zawsze mała. Powyższy przy­pa­dek zaowo­cu­je poniż­szym podzia­łem na komponenty:

ModelDziedzinyGraniceKontekstuKomponentu

Metoda ta i podej­ście (jako dobra prak­ty­ka), i u Fowlera (cyto­wa­ny DTO) i u Evansa (autor wzor­ca Domain Driven Design) nazy­wa­na jest boun­ded con­text” (gra­ni­ca kon­tek­stu, rodzi­na zawsze razem i tyl­ko jed­na rodzi­na w jed­nym miesz­ka­niu). Dzięki temu uzy­sku­je­my bar­dzo dobry, przy oka­zji zgod­ny z zasa­dą „[[Open Close Pryncypia]]”, model archi­tek­tu­ry, któ­ry pozwa­la zle­cić kom­po­nen­ty do wyko­na­nia, defi­niu­jąc wyłącz­nie opra­co­wa­ne już inter­fej­sy, kolej­ność ich (kom­po­nen­tów) wyko­na­nia nie ma zna­cze­nia dla całości.

Przy oka­zji ujaw­nia się zło” jakie wyrzą­dza budo­wa­nie zło­żo­ne­go opro­gra­mo­wa­nia na bazie inte­gra­cji poprzez współ­dzie­le­nie danych:

ModelDziedzinyIntegracjaPrzezWspoldzielnieDanych

Komponenty są sil­nie od sie­bie uza­leż­nio­ne (współ­dzie­lo­na baza danych w mode­lu rela­cyj­nym), nie da się two­rzyć (kodo­wać) tych kom­po­nen­tów nie­za­leż­nie od sie­bie, bo trze­ba uzgad­niać a potem uznać, wspól­ny model danych. Ingerencja w jaki­kol­wiek kom­po­nent z regu­ły ozna­cza inge­ren­cję w całą aplikację.

Dzieląc sys­tem na nie­za­leż­ne kom­po­nen­ty (każ­dy kom­po­nent sam zarzą­dza swo­imi dany­mi) , usta­la­my inte­gra­cję z uży­ciem inter­fej­sów a nie współ­dzie­ląc dane, z cze­go cał­ko­wi­cie rezygnujemy:

ModelDziedzinyWspolpracaKomponentowDziedzinowych


To jest powód dla któ­re­go, w dobrych fir­mach deve­lo­per­skich klu­czo­wą rolę peł­ni archi­tekt. Na pozio­mie logi­ki biz­ne­so­wej, w zasa­dzie jest nim – takim archi­tek­tem – ana­li­tyk biz­ne­so­wy-pro­jek­tant, któ­ry po zakoń­cze­niu eta­pu ana­li­zy i pro­jek­to­wa­nia, peł­ni rolę „[[pro­duct owne­ra]]”, pro­wa­dzą­ce­go nad­zór autor­ski i zarzą­dza­nie zmia­ną wymagań.

Tak więc archi­tek­tu­ra powin­na być efek­tem głę­bo­kiej ana­li­zy i pro­jek­to­wa­nia z testa­mi, dopie­ro potem powin­na się stać – być może każ­dy kom­po­nent osob­no – mate­ria­łem do zle­ce­nia dla deve­lo­pe­rów. Najgorszy wariant to podział na kom­po­nen­ty z pomo­cą nego­cja­cji, poli­ty­ki i wal­ki o budżet. 

Analysis Patterns: Reusable Object Models

Jedna z cie­kaw­szych i popu­lar­niej­szych ksią­żek (ja mam dodruk z 2010 roku). Bardzo czę­sto spo­ty­kam się w sie­ci z powo­ły­wa­niem się na tę książ­kę w kwe­stii wzor­ców ana­li­tycz­nych”. Jednak po pierw­sze nie nale­ży zapo­mi­nać, że napi­sa­na zosta­ła w 1996 roku (od tam­tej pory mamy jed­nak pewien postęp, do tego książ­ka jest ilu­stro­wa­na sym­bo­la­mi opar­ty­mi na nota­cji ERD a nie UML), a po dru­gie, o czym wie­lu zapo­mi­na, Fowler pre­zen­tu­je w niej mode­le kon­cep­cyj­ne a nie struk­tu­ral­ne (wytłusz­cze­nie moje):

Analysis Patterns pro­vi­des a cata­lo­gue of pat­terns that have emer­ged in a wide ran­ge of doma­ins inc­lu­ding tra­ding, measu­re­ment, acco­un­ting and orga­ni­za­tio­nal rela­tion­ships. Recognizing that con­cep­tu­al pat­terns can­not exist in iso­la­tion, the author also pre­sents a series of sup­port pat­terns” that discuss how to turn con­cep­tu­al models into softwa­re that in turn fits into an archi­tec­tu­re for a lar­ge infor­ma­tion sys­tem. Included in each pat­tern is the reaso­ning behind the­ir design, rules for when they sho­uld and sho­uld not be used, and tips for imple­men­ta­tion. (Źródło: Analysis Patterns: Reusable Object Models: Martin Fowler: 9780201895421: Amazon.[1]com: Books)

Generalnie książ­kę pole­cam oso­bom doświad­czo­nym, czy­ta­jąc ją, nie wol­no zapo­mi­nać o tym, że Fowler bazu­je w nich na mode­lach poję­cio­wych. Książka nie zawie­ra mode­li dzie­dzi­ny (struk­tu­ra, mecha­nizm dzia­ła­nia apli­ka­cji). Modele poję­cio­we (słow­nik pojęć i związ­ków pomię­dzy nimi) słu­żą do zro­zu­mie­nia ana­li­zo­wa­ne­go obsza­ru wie­dzy, nie są (jak to ma miej­sce w dia­gra­mach ERD) ani mode­lem dzie­dzi­ny a nie struk­tu­rą kodu. Nie będę w tej recen­zji tego opi­sy­wał, opi­sa­łem to tu (cytat to pyta­nie pew­ne­go forumowicza):

Czy może­cie mi wytłu­ma­czyć co ozna­cza­ją poję­cia ?model dzie­dzi­ny? oraz ?model kon­cep­tu­al­ny?? Czy model dzie­dzi­ny zawie­ra tak­że dia­gram kon­cep­tu­al­ny klas? (Źródło: Czym jest a czym nie jest tak zwa­ny model dzie­dzi­ny sys­te­mu | Jarosław Żeliński IT-Consulting)

Książkę pole­cam, duża daw­ka obiek­to­wej wie­dzy i przy­kła­dów, ale bierz­cie popraw­kę na powyż­sze. Fragmenty na Google books: czy­taj.[2]

Analysis Patterns: Reusable Object Models Hardcover
October 19, 1996, Martin Fowler

Footnotes
[1]M. Fowler, Analysis Patterns. Reusable Object Models, Addisson_Wesley 2010.
[2]J. Zelinski, Czym jest a czym nie jest tak zwa­ny model dzie­dzi­ny sys­te­mu [na:] ?Jarosław Żeliński IT-Consulting?, https://it-consulting.pl//2013/02/17/czym-jest-a-czym-nie-jest-tak-zwany-model-dziedziny-systemu/, udo­stęp­nio­no 16 lipiec 2017.

Bibliografia

Fowler, M., Analysis Patterns. Reusable Object Models, Addisson_Wesley 2010.
Zelinski, J., Czym jest a czym nie jest tak zwa­ny model dzie­dzi­ny sys­te­mu [na:] ?Jarosław Żeliński IT-Consulting?, https://it-consulting.pl//2013/02/17/czym-jest-a-czym-nie-jest-tak-zwany-model-dziedziny-systemu/, udo­stęp­nio­no 16 lipiec 2017.

CQRS czyli jak osiągnąć wydajność c.d.

Rok temu pisa­łem o wzor­cu CQRS, tam­ten wpis bazo­wał głów­nie na arty­ku­le M.Fowlera i sta­no­wił raczej zajaw­kę tema­tu. Teraz mam trosz­kę wła­snych doświad­czeń, tak­że w dys­ku­sjach z pro­gra­mi­sta­mi, i przy­to­czę tu moja kon­klu­zję, nie­co chy­ba odbie­ga­ją­cą od opi­su M.Fowlera, któ­re­go albo nie zro­zu­mia­łem ale on upro­ścił swój wpis (dzię­ki cze­mu ja wte­dy nie zrozumiałem).

Mamy pro­blem pole­ga­ją­cy na tym, że fir­ma ma ogrom­ną ofer­tę pew­nych bar­dzo zło­żo­nych pod­ze­spo­łów, żeby nie psuć ich opi­su i moż­li­wo­ści roz­bu­do­wy, model dzie­dzi­ny odwzo­ro­wu­je struk­tu­rę tych czę­ści. Jednak bar­dzo duża licz­ba użyt­kow­ni­ków skle­pu inter­ne­to­we­go regu­lar­nie przy­wo­łu­je na ekran listę pod­ze­spo­łów w posta­ci cen­ni­ka, peł­ne­go, stro­ni­co­wa­ne­go, sor­to­wa­ne­go alfa­be­tycz­nie lub ceną.

Rozwiązanie: repo­zy­to­rium prze­trzy­mu­je dwa kom­ple­ty tych danych: jeden jako peł­ny kata­log danych o pro­duk­tach dru­gi jako pła­ski cen­nik. bar­dzo czę­sto spo­ty­kam się z opi­nia (imple­men­ta­cją), w któ­rej (np. za pomo­cą ORM) mapu­je się model (pro­jekt) logicz­ny na bazę danych w spo­sób jak poniżej:

CQRS 1

Prawdopodobnie dla­te­go, że na stro­nie http://​mar​tin​fow​ler​.com/​b​l​i​k​i​/​C​Q​R​S​.​h​tml mamy taki oto dia­gram opi­su­ją­cy wzo­rzec CQRS:

cqrs

i to jest ten moment, w któ­rym ja chy­ba cze­goś nie zro­zu­mia­łem u Fowlera (i nie tyl­ko u nie­go). W moim mnie­ma­niu (i w mojej wer­sji w pro­jek­tach) wyglą­da to jed­nak tak:

CQRS 2

Czyli z zewnątrz” mamy RepozytoriumPodzespołów (jeden inter­fejs) a logi­ka jest taka: na bazie kolek­cji agre­ga­tów powsta­je rów­no­le­gle (jest aktu­ali­zo­wa­na okre­so­wo) nie­za­leż­na pła­ska lista. Korzystający z tego kom­po­nen­tu – wyko­nu­jąc ope­ra­cje podajCennik() – nie wie, czy cen­nik jest gene­ro­wa­ny wprost z agre­ga­tów czy z pła­skiej tabli­cy, bo to jest ukry­te za inter­fej­sem. Jednak, jak nie trud­no się domy­śleć, odpo­wiedź z kolek­cji ProstyopisPodzespołów będzie o nie­bo” szyb­sza niż ad-hoc zapy­ta­nie do kolek­cji bar­dzo zło­żo­nych agre­ga­tów. Agregaty prak­tycz­nie wyłącz­nie obsłu­gu­ją ope­ra­cje CRUD. Warunkiem uzy­ska­nia dużej wydaj­no­sci ope­ra­cji podajCennik() jest, pro­jek­tu­jąc utrwa­la­nie, zbu­do­wa­nie dwóch odręb­nych zesta­wów tablic dla agre­ga­tów i dla pła­skiej kolekcji.

Dane są nieważne bo liczy się przede wszystkim mechanizm działania

Tym prze­wrot­nym tytu­łem chcę dziś zwró­cić uwa­gę na dwa waż­ne i bar­dzo pomoc­ne wzor­ce ana­li­tycz­ne (sło­wo ana­li­tycz­ne ode mnie, w książ­kach na temat wzor­ców bar­dzo rzad­ko uży­wa­na jest nazwa wzor­ce ana­li­tycz­ne”) opi­sa­ne w książ­ce M.Fowlera. Wzorcami ana­li­tycz­ny­mi nazy­wam te wzor­ce pro­jek­to­we, któ­re poma­ga­ją w ana­li­zie i pro­jek­to­wa­niu mode­lu dzie­dzi­ny sys­te­mu (biz­ne­so­wy model obiektowy).

MFowlerWzorceProjektowePolecam oczy­wi­ście lek­tu­rę całej książ­ki Martina Fowlera Architektura Systemów Zarządzania Przedsiębiorstwem Wzorce Projektowe.[1] Opisuje on w niej wła­snie wzor­ce pro­jek­to­we bar­dzo przy­dat­ne już na eta­pie pro­jek­to­wa­nia. Fowler nie uży­wa poję­cia wzor­ca ana­li­tycz­ne­go” ale książ­ka jest podzie­lo­na na obsza­ry zasto­so­wa­nia wzor­ców, wśród nich znaj­dzie­cie więc wzor­ce logi­ki dzie­dzi­ny, wzor­ce pre­zen­ta­cji inter­ne­to­wych czy omó­wio­ne tu wzor­ce dys­try­bu­cji a tak­że bar­dzo przy­dat­ne wzor­ce okre­ślo­ne jako pod­sta­wo­we”.

Poza wzor­ca­mi typo­wy­mi dla sys­te­mów obiek­to­wych w ogó­le, war­to zwró­cić uwa­gę na dwa. Opiszę krót­ko dwa bar­dzo przy­dat­ne na eta­pie ana­li­zy wzor­ce pro­jek­to­we (odno­śni­ki do stro­ny M.Fowlera): Transfer Object oraz Value Object.

Przykład użycia Value Object i Transfer Object

Na eta­pie ana­li­zy pro­ble­mu (ana­li­zy i mode­lo­wa­niu dzie­dzi­ny sys­te­mu) powin­no nas inte­re­so­wać przede wszyst­kim co i po co się dzie­je. Wielu ana­li­ty­ków o rodo­wo­dzie pro­gra­mi­stycz­nym zaczy­na pra­cę od pytań w rodza­ju ile nazwi­sko ma zna­ków, czy mogą to być tyl­ko lite­ry czy coś jesz­cze”, itd. Jest to moim zda­niem kom­plet­ne nie­po­ro­zu­mie­nie. Zabieranie się za opra­co­wa­nie mode­lu od tej stro­ny (mode­lo­wa­nie danych) cał­ko­wi­cie przy­ćmi roz­wią­zy­wa­ny pro­blem. Np. sta­ra­jąc się zro­zu­mieć sys­tem sprze­da­ży bile­tów na samo­lot istot­ne jest na począt­ku nie to, ile zna­ków może mieć nazwi­sko a to, że bar­dzo istot­na jest iden­ty­fi­ka­cja pasa­że­rów i miejsc jakie mają zająć w samo­lo­cie. To nie jest to samo, bo iden­ty­fi­ka­cja pasa­że­rów ma za cel kon­tro­lę, kogo wpusz­cza­my na pokład samo­lo­tu, a nazwi­sko to jed­na z cech pasa­że­ra i na eta­pie ana­li­zy nie nale­ży zakła­dać, że to jedy­ny i naj­lep­szy spo­sób na to roz­róż­nie­nie. Brzmi jak here­zja? Zapewne, bo więk­szość” ana­li­ty­ków zaczy­na wła­śnie od bada­nia np. nazwiska.

A kie­dy zając się nazwi­skiem? Dopiero wte­dy gdy zro­zu­mie­my pro­blem i opra­cu­je­my sys­te­mo­we jego roz­wią­za­nie. Po pierw­sze dla­te­go, że na począt­ku nie mamy wie­dzy (za wcze­śnie na taką decy­zję) by usta­lić na jakich kon­kret­nie danych będzie opie­ra­ła się iden­ty­fi­ka­cja pasa­że­rów (a nuż poja­wi się [[bio­me­tria]]), po dru­gie nie­po­trzeb­nie skom­pli­ku­je­my doku­men­ta­cję zamu­la­jąc ją od same­go począt­ku dużą ilo­ścią zbęd­nych atry­bu­tów”.

Druga istot­na rzecz, to komu­ni­ka­cja. Wiemy, że fir­ma sprze­da­ją­ca bile­ty lot­ni­cze ope­ru­je róż­ny­mi dany­mi (lokal­ny model biz­ne­so­wy tej fir­my) na temat rezer­wo­wa­nych bile­tów. Wiemy, że te dane – o sprze­da­nych bile­tach – muszą być prze­ka­za­ne linii lot­ni­czej, ta zaś wcze­śniej musi jakoś prze­ka­zać infor­ma­cje o tym, na jakie loty i jakie bile­ty oferuje.

Co cie­ka­we, dosko­na­le to pasu­je to opi­sów wyko­ny­wa­nych przez zama­wia­ją­ce­go (albo jak kto woli user sto­ry). Normalny czło­wiek raczej powie nam, że zapi­su­je dane pasa­że­ra”, ale raczej nie powie nam, że reje­stru­je 25 zna­ków nazwi­ska, 20 zna­ków imie­nia i cza­sem 20 zna­ków dru­gie­go imie­nia.….”. Ten sam czło­wiek powie następ­nie, że prze­ka­zu­je dane o sprze­da­nych bile­tach do odpo­wied­nich linii lot­ni­czych a nie, że doko­nu­je trans­fe­ru kolek­cji danych zawierających.….”.

Analiza i projektowanie

Na bazie wywia­dów, doku­men­tów itp. sta­ra­my się zro­zu­mieć co jest gra­ne”, jak ten sys­tem funk­cjo­nu­je. Powstaje np. taki dia­gram. Tu zakła­dam już, że mode­lu­je­my sys­tem sprze­da­ży bile­tów, ale sys­tem ozna­cza wszyst­ko to, co bie­rze w tym udział” a nie kon­kret­ne oprogramowanie”:

Transfer biletów do linii lotniczej

Mamy model cze­goś co ma się wyda­rzyć. Na tym eta­pie kom­plet­nie nie ma sen­su zaj­mo­wa­nie się tym ile zna­ków ma nazwi­sko. To może się zmie­nić w toku ana­li­zy a nawet imple­men­ta­cji, ale nie powin­na ulec zmia­nie logi­ka tej operacji.

Jak już opa­nu­je­my logi­kę (zro­zu­mie­my co i jak ma dzia­łać i zapro­jek­tu­je­my jak to zre­ali­zo­wać) zabie­ra­my się za szcze­gó­ły. Model dzie­dzi­ny (frag­ment):

Model dziedziny

Jak widać, np. danePasażera jako zawar­tość to daneOsoby a nie pola i typy danych”. Czym są DaneOsoby znaj­dzie­my tu:

ValueObject

Zamiast pro­stych typów danych (np. zna­ko­we) sto­su­je­my obiekt jako typ danych. To zna­ko­mi­cie uła­twia póź­niej­sze roz­sze­rze­nia i zmia­ny (nie musi­my nic zmie­niać w mode­lu dzie­dzi­ny by np. dodać dru­gie imię do danych oso­by, mody­fi­ku­je­my w jed­nym miej­scu jedy­nie dekla­ra­cję kla­sy DaneOsoby).

Wywołanie ope­ra­cji podajDaneBiletu zwra­ca obiekt DaneBiletuLitniczego (lub agre­gat zawie­ra­ją­cy wszyst­kie bilety):

Transfer ObjectNie jest to ten sam obiekt co wcze­śniej, ValueObject to typ danych, Transfer Object to seria­li­za­cja, któ­rej celem jest jedy­nie prze­nie­sie­nie w moż­li­wie naj­prost­szy do odczy­ta­nia spo­sób okre­ślo­nych infor­ma­cji (oba te obiek­ty nie mają jed­nak toż­sa­mo­ści). Nie nale­ży tych wzor­ców mylić ani utoż­sa­miać, gdyż Value Object to typ danych” zaś Transfer Object to jedy­nie para­metr wywo­łań, Value Object powi­nien mieć ope­ra­cje sparw­dza­ja­ce jego popraw­ność (wali­da­cja), Transfer Object słu­ży wyłącz­nie do prze­ka­zy­wa­nia infor­ma­cji jako para­metr wywo­łań i odpo­wie­dzi (w pew­nym sen­sie defi­niu­je pro­to­kół wymia­ny danych).

Korzyści ze sto­so­wa­nia tych wzor­ców to mię­dzy innymi:

  1. szcze­gó­ły danych odkła­da­my na koniec pro­jek­tu co jest bez­piecz­ne (nie musi­my mody­fi­ko­wać pro­jek­tu w mia­rę postę­pu pozy­ski­wa­nia wie­dzy o szczegółach),
  2. zmia­na tych szcze­gó­łów nie spo­wo­du­je potrze­by zmia­ny szkie­le­tu mode­lu dziedziny,
  3. może­my pro­wa­dzić spo­koj­ną upo­rząd­ko­wa­ną ana­li­zę top-down” (od ogó­łu do szczegółu),
  4. może­my się umó­wić z deve­lo­pe­rem, że jako ana­li­ty­cy nie będzie­my wni­ka­li w szcze­gó­ły danych, nadal może­my ope­ro­wać kla­sa­mi ValueObject i TransferObject (kla­sy te będą w począt­ko­wej fazie pro­jek­tu bez atrybutów),
  5. mimo to może­my umie­ścić w kla­sach ValueObject warun­ki wali­da­cji (ope­ra­cje klas, któ­rych tu nie poka­zy­wa­łem) i do tego one mię­dzy inny­mi słu­żą (to się nazy­wa okre­śla­nie wyma­gań poprzez testy czy­li TDD),
  6. już na samym począt­ku może­my uzgod­nić postać danych wymie­nia­nych na inter­fej­sach (np. zdal­na komu­ni­ka­cja) i korzy­stać z tej umowy.

Tak zapro­jek­to­wa­ny sys­tem speł­nia tak­że jed­ną z klu­czo­wych zasad pro­jek­to­wa­nia obiek­to­we­go: sys­tem jest zamknię­ty na zmia­ny i otwar­ty na rozszerzenia”.

Na zakończenie

Często sły­szę, że to trud­ne i pra­co­chłon­ne (dodat­ko­we kla­sy w mode­lu), nie­ste­ty zbyt pro­sty pro­jekt potra­fi być kosz­tow­niej­szy w roz­bu­do­wie w porów­na­niu z pier­wot­nym wytwo­rze­niem, dla­te­go jak klient w ramach wyma­gań wpi­su­je (a wpi­su­je coraz czę­ściej): sys­tem ma umoż­li­wiać łatwe roz­sze­rze­nia funk­cjo­nal­no­ści, to nale­ży go tak pro­jek­to­wać, w prze­ciw­nym wypad­ku wyma­ga­nie to nie jest spełnione…

Druga uwa­ga: czę­sto sami klien­ci zabi­ja­ją swo­je pro­jek­ty żąda­jąc na samym począt­ku udo­ku­men­to­wa­nia wszyst­kich szcze­gó­łów jakie im do gło­wy przyj­dą nie potra­fiąc jed­no­cze­śnie opi­sać mecha­ni­zmu dzia­ła­nia ich orga­ni­za­cji (lub nowe­go pomy­słu). To nie­ste­ty czę­sto spo­ty­ka­ne zja­wi­sko, z któ­rym moim zda­niem nale­ży wal­czyć. Paradoksalnie zło­żo­ność sys­te­mów biz­ne­so­wych tkwi w mecha­ni­zmie ich funk­cjo­no­wa­nia a nie w danych, któ­re zbie­ra­ją (któ­rych nie raz jest po pro­stu za dużo…).

Dane to fak­ty jakie chce­my znać, te fak­ty są kon­se­kwen­cją dzia­ła­nia a nie odwrotnie. 

Na ryn­ku w Polsce są jesz­cze mię­dzy inny­mi książ­ki o wzorcach:

Moim zda­niem jed­nak nie przy­dat­ne ana­li­ty­kom. Pierwsza to wzor­ce tech­nicz­ne”, sto­so­wa­ne głów­nie z kom­po­nen­tach Controller i View (archi­tek­tu­ra MVC). Druga to w zasa­dzie doku­men­ta­cja [[J2EE]]. Tak więc obie raczej dla pro­gra­mi­stów i archi­tek­tów. Książkę Fowlera pole­cam ana­li­ty­kom i archi­tek­tom tak­że. Wszystkim pole­cam tak­że UML i Wzorce pro­jek­to­we Larmana.

(UWAGA! Pokazano pro­jekt poglą­do­wy, wyssa­ny z pal­ca, nie ujaw­ni­łem tre­ści żad­ne­go z moich real­nych projektów).

Footnotes
[1]M. Fowler, Architektura sys­te­mów zarzą­dza­nia przed­się­bior­stwem. Wzorce pro­jek­to­we [na:] ?helion​.pl?, http://​helion​.pl/​k​s​i​a​z​k​i​/​a​r​c​h​i​t​e​k​t​u​r​a​-​s​y​s​t​e​m​o​w​-​z​a​r​z​a​d​z​a​n​i​a​-​p​r​z​e​d​s​i​e​b​i​o​r​s​t​w​e​m​-​w​z​o​r​c​e​-​p​r​o​j​e​k​t​o​w​e​-​m​a​r​t​i​n​-​f​o​w​l​e​r​,​s​z​a​b​k​o​.​htm, udo­stęp­nio­no 16 lipiec 2017.
[2]H. SA, J2EE. Wzorce pro­jek­to­we. Wydanie 2 [na:] ?helion​.pl?, http://​helion​.pl/​k​s​i​a​z​k​i​/​j​2​e​e​-​w​z​o​r​c​e​-​p​r​o​j​e​k​t​o​w​e​-​w​y​d​a​n​i​e​-​2​-​d​e​e​p​a​k​-​a​l​u​r​-​j​o​h​n​-​c​r​u​p​i​-​d​a​n​-​m​a​l​k​s​,​j​2​e​e​w​2​.​htm, udo­stęp­nio­no 16 lipiec 2017.

Bo banki od wszystkiego są do niczego czyli złe modele dziedziny

Ten arty­kuł to odpo­wiedź na pew­ną dys­ku­sję roz­po­czę­tą od tezy, że na wie­lu stro­nach WWW (w nie­któ­rych książ­kach tak­że) mamy nie­ste­ty do czy­nie­nia z pseudowiedzą…

W arty­ku­le Cholerny dia­gram klas pisa­łem o mode­lu dzie­dzi­ny. Modelowana jest dia­gra­mem klas (nota­cja to narzę­dzie), zawie­ra logi­kę biz­ne­so­wą. W kon­wen­cji DDD ([[Domain Driven Design]]), model ten jest szkie­le­tem kom­po­nen­tu Model we wzor­cu MVC.

Tym razem napi­sze kil­ka słów o poje­dyn­czych kla­sach w mode­lu dzie­dzi­ny. Błąd numer jeden: kla­sy w mode­lu dzie­dzi­ny odwzo­ro­wu­ją poję­cia mode­lu poję­cio­we­go! Nie, model poję­cio­wy (słow­nik pojęć ich wza­jem­nych związ­ków) to nie model dzie­dzi­ny sys­te­mu. Tak się pro­jek­to­wa­ło encje w mode­lach rela­cyj­nych baz danych, prze­no­sze­nie tych doświad­czeń na grunt obiek­to­wy to powszech­na, cięż­ka cho­ro­ba, to rak toczą­cy te pro­jek­ty. Owszem, jeże­li ktoś zade­kla­ru­je, że two­rzy sys­tem meto­da­mi struk­tu­ral­ny­mi już może prze­stać czy­tać, ale niech uży­wa nota­cji i dia­gra­my ERD a nie UML i nie nazy­wa tego meto­da­mi obiek­to­wy­mi ana­li­zy i projektowania.

Niestety przy­kła­dy dia­gra­mów klas” na stro­nach wie­lu firm dorad­czych, szko­le­nio­wych i stro­nach wie­lu kon­sul­tan­tów”, «tre­ne­rów” itp. poka­zu­ją, że duch ana­li­zy struk­tu­ral­nej nadal żyje oraz, że myle­nie nota­cji UML z meto­da­mi obiek­to­wy­mi ana­li­zy i pro­jek­to­wa­nia jest powszech­ne. Przypomnę tu tyl­ko, że dia­gram klas to nota­cja, któ­rej moż­na użyć do wie­lu rze­czy, w tym do mode­lo­wa­nia pojęć, struk­tu­ry kodu opro­gra­mo­wa­nia obiek­to­we­go (zgod­ne­go z obiek­to­wym para­dyg­ma­tem, a nie tyl­ko korzy­sta­ją­ce­go z pole­ce­nia class w uży­tym języ­ku pro­gra­mo­wa­nia), sta­tycz­nych mode­li orga­ni­za­cji i wie­lu innych. Tak więc zda­nie pro­szę zro­bić dia­gram klas” nie zna­czy nic, to coś jak weź samo­chód o pojeź­dzij trosz­kę”, z trans­por­tem nie ma to nic wspólnego.

Jeżeli jed­nak uzna­my, że pro­wa­dzi­my ana­li­zę obiek­to­wą to zna­czy, że model rze­czy­wi­sto­ści (mode­lo­wa­nej) budu­je­my jako zespół współ­pra­cu­ją­cych obiek­tów reali­zu­ją­cych okre­ślo­ny cel”. Wtedy dia­gram klas to nie żad­ne dane, encje i inne nie­obiek­to­we pomy­sły (znam takich co mode­lu­ją klu­cze rela­cyj­ne w dia­gra­mach klas a to już jest tra­ge­dia nie­ste­ty, jest nawet wyda­na w Polsce książ­ka z taki­mi przy­kła­da­mi!). Projekt zaczy­na­my od klas i ich ope­ra­cji a nie od atrybutów!

Uwaga dodat­ko­wa. Sprawdzoną meto­dą ana­liz (w ogó­le) jest ana­li­za sys­te­mo­wa, jest to:

meto­da roz­wią­zy­wa­nia zło­żo­nych pro­ble­mów wyko­rzy­stu­ją­ca podej­ście sys­te­mo­we (holi­stycz­ne). Polega na trak­to­wa­niu ana­li­zo­wa­nej orga­ni­za­cji (zja­wi­ska) jako zło­żo­ne­go sys­te­mu, któ­re­go poszcze­gól­ne czę­ści pra­cu­ją” na powo­dze­nie cało­ści”. Obejmuje ona czte­ry zasad­ni­cze eta­py roz­wią­zy­wa­nia pro­ble­mu: (1) iden­ty­fi­ka­cja i sfor­mu­ło­wa­nie pro­ble­mu, (2) bada­nie (ana­li­zo­wa­nie) sytu­acji pro­ble­mo­wej (gro­ma­dze­nie infor­ma­cji, wyja­śnia­nie kwe­stii, ana­li­zo­wa­nie fak­tów itp., (3) ana­li­za pro­ble­mu (dekom­po­zy­cja zło­żo­ne­go pro­ble­mu na mniej­sze), (4) pro­jek­to­wa­nie roz­wią­za­nia (budo­wa mode­li, spe­cy­fi­ka­cje, symu­la­cja, warian­ty itp.).

Jak widać podo­bień­stwo para­dyg­ma­tu obiek­to­we­go i ana­li­zy sys­te­mo­wej jest bar­dzo duże, żeby nie powie­dzieć uderzające.

Tak więc ana­li­za i mode­lo­wa­nie (na eta­pie ana­li­zy) to roz­ło­że­nie ana­li­zo­wa­nej orga­ni­za­cji (ana­li­zo­wa­ne­go śro­do­wi­ska) na pro­ste obiek­ty, każ­dy o pro­stej odpo­wie­dzial­no­ści”. Wyłania się obraz mode­li skła­da­ją­cych się z tych czę­ści, któ­re pra­cu­ją na powo­dze­nie cało­ści”. Jakie powin­ny być owe czę­ści? Teraz pora na dwa cyta­ty z blo­gów pew­nych pro­gra­mi­stów (lubię dobrych pro­gra­mi­stów, bo przy­ta­ku­ją mi lub negu­ją a nie raz moc­no uczą poko­ry to co myślę czy­li nie błą­dzę w chmurach):

Single Responsibility Principle mówi, że kla­sa powin­na robić jed­ną rzecz, mieć jed­ną odpo­wie­dzial­ność. Jeśli ma jed­ną odpo­wie­dzial­ność to nie powin­na raczej grze­bać we wszyst­kich war­stwach. Wątpliwe jest aby kla­sa, któ­ra ma jed­ną odpo­wie­dzial­ność musia­ła się­gać do bazy danych i inter­fej­su użyt­kow­ni­ka i pli­ków i logi­ki biz­ne­so­wej i Bóg raczy wie­dzieć gdzie jesz­cze. (za using – papie­rek lak­mu­so­wy Twojej archi­tek­tu­ry | arek onli­ne | Arkadiusz Benedykt).

…naj­bar­dziej traf­ną meta­fo­rą obiek­tów pro­gra­mi­stycz­nych jest orga­nizm bio­lo­gicz­ny. Podobnie jak komór­ki, obiek­ty nie wie­dzą”, co dzie­je się wewnątrz innych obiek­tów, ale komu­ni­ku­ją się z nimi reali­zu­jąc bar­dziej zło­żo­ne cele. W prze­ci­wień­stwie do takie­go orga­ni­zmu pro­gram mono­li­tycz­ny przy­po­mi­na mecha­nizm zegar­ka, zawie­ra­ją­cy nie­prze­li­czal­ną (sic!) licz­bę try­bi­ków. Trybiki nie mają żad­nej inte­li­gen­cji i są bez­u­ży­tecz­ne poza mecha­ni­zmem, w któ­rym pra­cu­ją. Taki pro­jekt nie ma szans powo­dze­nia. Budując mecha­ni­zmy zega­ro­we, docho­dzisz w koń­cu do takiej zło­żo­no­ści, że całość prze­sta­je funk­cjo­no­wać. (Holistycznie o inży­nie­rii opro­gra­mo­wa­nia: Bo naj­waż­niej­sza jest odpo­wie­dzial­ność Synu…).

i nie­ste­ty to co widu­ję na wie­lu stro­nach WWW, w pro­jek­tach itp. (dru­ga wada czę­sto spo­ty­ka­nych mode­li dziedzinowych):

Dopisujemy kolej­ne meto­dy a tym­cza­sem kla­sa puch­nie. Przy osią­gnię­ciu masy kry­tycz­nej, wpro­wa­dze­nie jakiej­kol­wiek zmia­ny, nawet tej naj­mniej­szej powo­du­je, że spę­dza­my godzi­ny na debu­go­wa­niu kodu i spraw­dza­niu dla­cze­go nie zawsze dzia­ła tak jak byśmy tego chcie­li. (Single Responsibility Principle | arek onli­ne).

Swego cza­su na jed­nej z kon­fe­ren­cji o ana­li­zie wyma­gań, mówi­łem o potrze­bie zro­zu­mie­nia funk­cjo­no­wa­nia ana­li­zo­wa­nej orga­ni­za­cji (fir­my) o i tym jak to udokumentować:

…wszyst­ko to co nas ota­cza, samo w sobie jest natu­ral­nie pro­ste. Złożone są, nie poszcze­gól­ne rze­czy, a to, że jest ich wie­le i mają na sie­bie wza­jem­ny wpływ. Pamiętajmy, że jed­na z naj­trud­niej­szych gier na świe­cie ? sza­chy ? to tyl­ko kil­ka­na­ście figur i pro­ste regu­ły ich prze­miesz­cza­nia, sno­oker – naj­trud­niej­sza gra w bilar­da – to to tyl­ko pro­ste kule i kij. Nawet naj­więk­szą orga­ni­za­cję moż­na, w toku ana­li­zy, roz­ło­żyć na skoń­czo­ną licz­bę ról i reguł ich postę­po­wa­nia by zro­zu­mieć jej funk­cjo­no­wa­nie. (żr. Jarosław Żeliński, refe­rat na kon­fe­ren­cji o sys­te­mach ERP).

Analiza biz­ne­so­wa to etap opi­su (zro­zu­mie­nia) mode­lo­wa­nej orga­ni­za­cji (mode­le pro­ce­sów itp.). Potem, powsta­je model roz­wią­za­nia, któ­rym jest nie raz wła­śnie opro­gra­mo­wa­nie, jego logi­ka (patrz powyż­szy cytat) to obiek­to­wy model dzie­dzi­ny sys­te­mu”, a nie jakiś dia­gram klas nafa­sze­ro­wa­ny atry­bu­ta­mi i pozba­wio­ny ope­ra­cji bo jest dokład­nie odwrotnie:

zly modelAnemic Domain Model: This is one of tho­se anti-pat­terns tha­t’s been aro­und for quite a long time, yet seems to be having a par­ti­cu­lar spurt at the moment. I was chat­ting with Eric Evans on this, and we’ve both noti­ced they seem to be get­ting more popu­lar. As gre­at boosters of a pro­per Domain Model, this is not a good thing. (AnemicDomainModel).

Dla kon­tra­stu cytat z jed­nej ze stron WWW pew­nej fir­my szkoleniowej:

Zwróćmy uwa­gę, że na mode­lu dzie­dzi­ny nie umiesz­cza­my klas imple­men­tu­ją­cych logi­kę apli­ka­cji, jej inter­fejs użyt­kow­ni­ka czy war­stwę dostę­pu do danych. Nie war­to też na mode­lu dzie­dzi­ny umiesz­czać metod. (Diagramy klas – model dzie­dzi­ny i pro­jekt apli­ka­cji).

I tyle mam dzi­siaj do powie­dze­nia o nie­któ­rych kon­sul­tan­tach i wykła­dow­cach … (a tu trosz­kę praw­dy)

P.S.

Bardzo czę­sto spo­ty­kam się z tezą, że model dzie­dzi­ny powi­nien opra­co­wy­wać archi­tekt by doko­nać ewen­tu­al­nych opty­ma­li­za­cji jesz­cze przed imple­men­ta­cją. Stawianie takich tez ma w moich oczach dwa głów­ne źró­dła: dostaw­ca usłu­gi (deve­lopr) szu­ka oka­zji by pro­jekt nagiąć do swo­ich potrzeb, do posia­da­nych goto­wych kom­po­nen­tów nie speł­nia­ją­cych jed­nak wyma­gań. Innym powo­dem jest zwy­kła nie­wie­dza. O opty­ma­li­za­cji kil­ka pro­stych tez usta­mi pro­gra­mi­sty: 3 zasa­dy opty­ma­li­za­cji. Więc powtó­rzę: na eta­pie ana­li­zy i pro­jek­to­wa­nia nicze­go nie uprasz­cza­my ani nie opty­ma­li­zu­je­my bo nie wie­my czy w ogó­le zaist­nie­je taka potrze­ba, a opty­ma­li­za­cja ZAWSZE psu­je model.

Dom bez planów

CQRS czyli kto, co i jak zamawia i dostarcza

Poprzedni arty­kuł koń­czy­ły słowa:

Tak więc jest to moim zda­niem dro­ga do mode­lo­wa­nia wyma­gań meto­dą ?tak to ma dzia­łać? a nie tyl­ko ?tak to ma wyglą­dać?, bo to dru­gie jest przy­czy­ną wie­lu problemów?

Wielu deve­lo­pe­rów zacie­kle bro­ni się przed tezą, że wyma­ga­nia to tak­że ?żąda­na reali­za­cja logi­ki biz­ne­so­wej?, ocze­ku­ją wyłącz­nie zesta­wu wyma­gań funk­cjo­nal­nych i poza-funk­cjo­nal­nych. Jest to moim zda­niem źró­dło dwóch ryzyk:

  • jeże­li zamó­wie­nie jest opi­sem czar­nej skrzyn­ki tak na praw­dę nie wie­my do dosta­nie­my jako jej realizację,
  • jeże­li auto­rem reali­za­cji jest dostaw­ca, pozo­sta­je mu nie­zby­wal­ne pra­wo do pro­jek­tu tej realizacji.

Dlatego war­to, jako wyma­ga­nie prze­ka­zać pro­jekt tak zwa­nej ?bia­łej skrzyn­ki?, bo zabez­pie­cza to nas przed powyż­szy­mi ryzy­ka­mi. (Wzorzec ana­li­tycz­ny Boundary Control Entity).

Czemu tak bro­nię tej tezy? Zarzuty deve­lo­pe­rów wobec mnie to: wymu­szasz imple­men­ta­cję a to rola pro­jek­tan­ta”. Jest to nie praw­da, bo pro­jek­ty wyma­gań zawie­ra­ją­ce wewnętrz­ną logi­kę to jesz­cze nie imple­men­ta­cja, ale na pew­no jest to ocze­ki­wa­nie kupu­ją­ce­go opro­gra­mo­wa­nie. Gdybym kupo­wał samo­chód nie chciał bym, by mi ktoś powie­dział, że wol­no mi powie­dzieć tyl­ko jak będę do nie­go wsia­dał, wysia­dał i po co, że będę zgod­nie z ogól­ny­mi zasa­da­mi naci­skał peda­ły i mani­pu­lo­wał drąż­kiem zmia­ny bie­gów. Nie! Mam pra­wo i ocho­tą okre­ślić typ sil­ni­ka, żądać ABS i wie­le innych rze­czy. Jeżeli ja nie znam się aż tak na samo­cho­dach popro­szę o pomoc kogoś kto się zna. Jest ryzy­ko? Jest, ale to ja o nim decy­du­ję a nie sprze­daw­ca samochodów!

Jeden z wielu powodów takiego podejścia

Przytłaczająca więk­szość deve­lo­pe­rów, z któ­ry­mi się spo­tka­łem, roz­wią­zu­je pro­blem wydaj­no­ści np. pra­cy z listą pro­duk­tów, podej­mu­jąc kom­pro­mis pomię­dzy szcze­gó­ło­wo­ścią i wier­no­ścią opi­su pro­duk­tu” a wydaj­no­ścią (czas odpo­wie­dzi sys­te­mu) np. pod­czas pre­zen­ta­cji (gene­ro­wa­nia) uprosz­czo­ne­go cen­ni­ka. Większość zna­nych mi deve­lo­pe­rów nie­ste­ty pre­zen­tu­je coś co nazy­wam struk­tu­ral­ny model pro­jek­to­wa­nia opro­gra­mo­wa­nia opar­ty na ane­micz­nym mode­lu dzie­dzi­ny”. Z regu­ły roz­wią­zu­ją oni opi­sa­ny wyżej pro­blem cen­ni­ka, uprasz­cza­jąc opis pro­duk­tu (psu­ją model!), umiesz­cza­ją uprosz­czo­ne dane o pro­duk­cie w mode­lu rela­cyj­nym wraz z resz­tą danych i wal­czą z opty­ma­li­za­cją zapy­tań do tej rela­cyj­nej bazy (uprasz­cza­nie i denormalizacja).

Nie raz pro­wa­dzi to do sytu­acji, w któ­rej opro­gra­mo­wa­nie jest szyb­kie i nieprzydatne”. 

< – jeże­li nie jesteś ana­li­ty­kiem przejdź na koniec artykułu – >

Wygląda to wte­dy np. tak (źr. Fowler CQRS):

Od pra­wej: inter­fejs użyt­kow­ni­ka, model dzie­dzi­ny, baza danych (pod­sys­tem utrwalania).

CQRS

Nie od dzi­siaj zna­ny jest wzo­rzec pro­jek­to­wy, któ­ry radzi sobie z tym pro­ble­mem. Nazywa się CQRS, i tak jest opi­sy­wa­ny przez guru” ana­li­zy i pro­jek­to­wa­nia :), Martina Fowlera:

CQRS stands for Command Query Responsibility Segregation. It’s a pat­tern that I first heard descri­bed by Greg Young. At its heart is a sim­ple notion that you can use a dif­fe­rent model to upda­te infor­ma­tion than the model you use to read infor­ma­tion. This sim­ple notion leads to some pro­fo­und con­se­qu­en­ces for the design of infor­ma­tion sys­tems. (źr. CQRS).

Idea tego pomy­słu na tym, by nie opty­ma­li­zo­wać wydaj­no­ści sys­te­mu meto­dą, nie raz zgni­łe­go, kom­pro­mi­su, a podejść do pro­ble­mu dzie­ląc go na dwa pro­ble­my: zgod­ność mode­lu z rze­czy­wi­sto­ścią i wydaj­ność całe­go sys­te­mu. Pierwszy pro­blem roz­wią­zu­je­my two­rząc wier­ny model struk­tu­ry opi­su­ją­cej pro­duk­ty, dru­gi pro­blem – wydaj­no­ści – roz­wią­zu­je­my two­rząc dru­gi uprosz­czo­ny model pro­duk­tów, do celów szyb­kiej reali­za­cji kil­ku waż­nych zapy­tań” (np. publi­ka­cja on line uprosz­czo­nej posta­ci cennika).

Powyższy dia­gram poka­zu­je: UI (inter­fejs użyt­kow­ni­ka), poka­zu­je menu zgod­ne z opi­sem z przy­pad­ków uży­cia (wyma­ga­nia funk­cjo­nal­ne). Model dzie­dzi­ny (część środ­ko­wa) poka­zu­je ocze­ki­wa­ne roz­wią­za­nie (takie­go żądam w wyma­ga­niach). Polega ono wła­śnie na zapro­jek­to­wa­niu w czę­ści dzie­dzi­no­wej odręb­ne­go mode­lu do zarzą­dza­nia poje­dyn­czy­mi pro­duk­ta­mi i odręb­ne­go do wydaj­ne­go zarzą­dza­nia ich kolek­cją. Owszem, model się nie­co skom­pli­ko­wał (jest nie­co kosz­tow­niej­szy w imple­men­ta­cji), ale jako zama­wia­ją­cy mam to cze­go potrze­bu­ję: wydaj­ny i uży­tecz­ny system.

< – jeże­li nie jesteś ana­li­ty­kiem tu zacznij czy­tać dalej – >

Opisując wyma­ga­nia wyłącz­nie jako czar­ną skrzyn­kę” nie wiem co dosta­nę. Większość deve­lo­pe­rów będzie dąży­ło do uprosz­cze­nia imple­men­ta­cji (ich koszt, nie raz brak wie­dzy) by zaspo­ko­ić na mini­mal­nym pozio­mie wyma­ga­nia opi­sa­ne przy­pad­ka­mi uży­cia. Nie raz klient sły­szy tu musi­my to upro­ścić bo tak się nie da”, a zama­wia­ją­cy, nie mając kom­pe­ten­cji by pole­mi­zo­wać z taką opi­nią, zga­dza się i dostar­czo­ny w efek­cie sys­tem sta­je się zgni­łym kom­pro­mi­sem opar­tym wła­śnie na czar­nej skrzyn­ce” jako spe­cy­fi­ka­cji zamó­wień: dosta­li­śmy dokład­nie to co zamó­wi­li­śmy ale zupeł­nie nie to cze­go napraw­dę potrzebujemy”. 

Tak więc,

nie ma zna­cze­nia fakt, że na pew­no są na ryn­ku deve­lo­pe­rzy zna­ją­cy pro­blem, któ­ry opi­sa­łem i sto­su­ją­cy opi­sa­ne tu roz­wią­za­nie takich pro­ble­mów. Jednak nawet cień ryzy­ka (a jest ono na praw­dę duże), że dosta­nie­my bubla, daje zama­wia­ją­ce­mu pra­wo do szcze­gó­ło­we­go defi­nio­wa­nia wyma­gań jako bia­łej skrzyn­ki”, bo dzię­ki temu zama­wia­ją­cy dosta­nie to cze­go potrze­bu­je a nie tyl­ko to co zamó­wił”.

Dla zain­te­re­so­wa­nych tak­że do pobra­nia książ­ka z MSDN:

The CQRS pat­tern and event sour­cing are not mere sim­pli­stic solu­tions to the pro­blems asso­cia­ted with lar­ge-sca­le, distri­bu­ted sys­tems. By pro­vi­ding you with both a wor­king appli­ca­tion and writ­ten guidan­ce, we expect you’ll be well pre­pa­red to embark on your own CQRS jour­ney. (za CQRS Journey).