Nieco zaawansowane techniki analizy i modelowania

W dwóch ubie­gło­rocz­nych arty­ku­łach pisa­łem o mode­lach poję­cio­wych oraz o związ­kach w UML. Opisałem je od stro­ny nota­cyj­nej. Dzisiaj o ich zastosowaniu. 

Generalnie zagad­nie­nia mode­li poję­cio­wych, abs­trak­cji i meta­mo­de­li oraz związ­ków mię­dzy nimi są dość trud­ne (wbrew pozo­rom, więk­szość ludzi ma pro­blem z abs­trak­cyj­nym myśle­niem), jako narzę­dzia są bar­dzo przy­dat­ne w ana­li­zie i projektowaniu.

Rzecz w tym, że sys­te­my ana­li­zo­wa­ne ist­nie­ją, co zna­czy ni mniej ni wię­cej tyl­ko to, że są dobre bo są i dzia­ła­ją”. Gorzej jest gdy sys­tem, nie raz nie­try­wial­ny, jest na eta­pie pro­jek­to­wa­nia. Wtedy o tym jest dobry” prze­ko­na­my się dopie­ro gdy go stwo­rzy­my (lub podej­mie­my taką pró­bę). Odkrycie, że jed­nak nie jest dobry bywa kosztowne.

Najczęstszymi wada­mi pro­jek­tów sys­te­mów są wewnętrz­na nie­spój­ność, nie­kom­plet­ność i wewnętrz­ne sprzecz­no­ści. Jak ich unik­nąć na eta­pie pro­jek­to­wa­nia? Jest rada: pro­jek­to­wać od ogó­łu do szcze­gó­łu, sta­le prze­strze­gać śla­do­wa­nia, pra­co­wać na abs­trak­cjach i meta­mo­de­lach. To pozwo­li zapa­no­wać nad zło­żo­no­ścią pro­jek­tu (sys­te­mu). Nie da się tego robić ręcz­nie” dla­te­go bez dobre­go opro­gra­mo­wa­nia CASE takie pro­jek­ty są raczej ska­za­ne na nie­po­wo­dze­nie lub znacz­ne dodat­ko­we koszty. 

Przykład

Na pro­stym przy­kła­dzie poka­żę jak i kie­dy uży­wać róż­nych, bar­dzo waż­nych związ­ków i pozio­mów abs­trak­cji. Przykładem będzie pies i kojec. Najpierw model poję­cio­wy, któ­ry zagwa­ran­tu­je jed­no­znacz­ność cało­ści oraz zro­zu­mie­nie problemu. 

Bardzo czę­sto popeł­nia­nym błę­dem jest prze­cią­ża­nie” dia­gra­mów i (lub) mie­sza­nie kon­tek­stów. Polega to na mie­sza­niu na jed­nym dia­gra­mie mode­li poję­cio­wych i struk­tu­ral­nych (pisa­łem też o tym w arty­ku­le o dia­gra­mach klas). Model poję­cio­wy to słow­nik pojęć i zależ­no­ści pomię­dzy poję­cia­mi (w nota­cji SBVR są to wyłącz­nie fak­ty łączą­ce te poję­cia w jeden kon­tekst). W tym przy­kła­dzie mamy taki oto model:

Tworzenie mode­lu poję­cio­we­go ma jed­no klu­czo­we zada­nie: zagwa­ran­to­wać spój­ność i jed­no­znacz­ność nazew­nic­twa w resz­cie pro­jek­tu. A nazwy dosta­ją: kla­sy, atry­bu­ty, ope­ra­cje, akto­rzy, war­to­ści atry­bu­tów klas, obiek­ty, itp.. Utrzymanie tu porząd­ku, wbrew pozo­rom, nie jest łatwe. Na mode­lach poję­cio­wych sto­su­je­my wyłącz­nie dwa związ­ki: dzie­dzi­cze­nie czy­li zwią­zek uogólnienia/specjalizacji (wska­zu­je typy) oraz aso­cja­cje czy­li nazwa­ne związ­ki mię­dzy poję­cia­mi. Tak więc typy ras to owcza­rek, pudel, ratler zaś pomię­dzy psem a rasą jest taki zwią­zek, że nazwa rasy opi­su­je pew­ne cechy psa. Mamy tak­że typy lego­wisk (buda, kojec) i zwią­zek psa z lego­wi­skiem. Każda z tych nazw (pojęć) powin­na mieć ści­słą defi­ni­cję (w doku­men­ta­cji osob­na tabe­la, zestawienie).

Teraz pora na projekt.

Projekt jest pro­sty wiec jego ele­men­ty zmie­ści­ły się na jed­nym dia­gra­mie. Tu mamy dia­gram obiek­tów (moż­na na nim umiesz­czać tak­że kla­sy). Większe pro­jek­ty to więk­sza licz­ba dia­gra­mów bar­dziej specjalizowanych. 

Tak więc meta­mo­del to kla­sy­fi­ka­to­ry i związ­ki mię­dzy nimi. Klasyfkator (kla­sa) zastę­pu­je np. set­ki psów i ich koj­ców. Metamodel poka­zu­je w posta­ci uogól­nio­nej związ­ki mię­dzy obiek­ta­mi nasze­go świa­ta, tu poka­za­no, że zwie­rze korzy­sta z koj­ca. Jak widać, uży­to nazwy kojec a nie lego­wi­sko, dla­cze­go? Bo z jakie­goś powo­du wie­my, że to jed­nak kojec i uży­to tej nazwy do nazwa­nia kla­sy. Konkretna sytu­acja to pies rasy ratler korzy­sta­ją­cy z koj­ca w posta­ci podusz­ki (u kon­kret­nych Kowalskich). Burek (tak sie wabi pies) to ratler, jest instan­cją kla­sy zwie­rzę. Poduszka u Kowalskich to instan­cja koj­ca. Rynkowy pro­dukt Kojec ALFADOG to reali­za­cja Kojca, któ­re­go kon­kret­nym przy­pad­kiem wyko­na­nia jest ów kojec u Kowalskich. Klasa Kojec ALFADOG repre­zen­tu­je kon­kret­ny typ koj­ca (pro­dukt ryn­ko­we) na bazie spe­cy­fi­ka­cji wyma­gań jaką jest tu kla­sa Kojec na metamodelu. 

Już taki pro­sty model to nie mało zależności:

Diagram obra­zu­je związ­ki pomię­dzy dia­gra­ma­mi i obiek­ta­mi na nich, moż­na poprze­stać na związ­kach pomię­dzy kla­sa­mi, obiek­ta­mi itp. Jednak peł­ny obraz śla­do­wa­nia i kon­tro­la tego śla­do­wa­nia pozwa­la zapew­nić spój­ność, kom­plet­ność i nie­sprzecz­ność dowol­nie duże­go pro­jek­tu. Czy war­to to robić? Ręcznie nie ma sen­su z powo­du pra­co­chłon­no­ści, mając dobre narzę­dzie CASE nasza godzi­na pra­cy nad korek­tą mode­li to ekwi­wa­lent nie raz dzie­sią­tek godzin deve­lo­pe­ra po wykry­ciu nie­spój­no­ści w two­rzo­nym opro­gra­mo­wa­niu lub wdra­ża­nej zmia­nie orga­ni­za­cyj­nej w fir­mie. Powyższy dia­gram to ana­li­za wpły­wu obiek­tu Burek na pozo­sta­łe ele­men­ty pro­jek­tu. Narzędzie CASE robi to auto­ma­tycz­nie w kil­ka sekund… Aktualizacja całe­go pro­jek­tu po zmia­nie jed­ne­go z nich tak­że wyko­ny­wa­na jest automatycznie. 

Na zakończenie 

Takie ana­li­zy i pro­jek­ty to (u mnie) ok. 70% to pro­jek­tu pro­gra­mi­stycz­ne, pozo­sta­łe to ana­li­zy doty­czą­ce pro­jek­to­wa­nia reor­ga­ni­za­cji, two­rze­nia wdra­ża­nia nowych reguł biz­ne­so­wych (zarzą­dza­nia zarzą­du, two­rze­nie pra­wa a kra­ju). To co tu opi­sa­łem, to tak na praw­dę sze­ro­ko poję­ta ana­li­za sys­te­mo­wa. Modelowanie to jedy­na moż­li­wość ode­rwa­nia się od tysię­cy deta­li świa­ta real­ne­go. Bez tego czło­wiek nie jest w sta­nie nicze­go sku­tecz­nie ana­li­zo­wać czy pro­jek­to­wać z uwa­gi na zbyt duży poziom zło­żo­no­ści. UML (i nie tyl­ko) to narzę­dzie do two­rze­nia abs­trak­cji i meta­mo­de­li, bez cze­go żad­na dobra ana­li­za sie obejść nie może. 

Związki w UML czyli abstrakcja vs rzeczywistość

Wstęp

Tym razem o kil­ku powszech­nie popeł­nia­nych błę­dach w korzy­sta­niu z UML. Chodzi o poję­cia abs­trak­cji, meta­mo­de­li i zależ­no­ści oraz o związ­ki mię­dzy ele­men­ta­mi na dia­gra­mach. Kluczową, moim zda­niem, przy­czy­ną two­rze­nia złych” mode­li obiek­to­wych jest uży­wa­nie nota­cji UML do two­rze­nia mode­li struk­tu­ral­nych, nie mają­cych z obiek­to­wym para­dyg­ma­tem nic wspól­ne­go. Druga to nie­zro­zu­mie­nie poję­cia para­dyg­ma­tu obiek­to­we­go. Ogromna ilość dia­gra­mów wyko­na­nych z uży­ciem sym­bo­li nota­cji UML, z UML i para­dyg­ma­tem obiek­to­wym ma nie­wie­le wspólnego.

Najpierw kil­ka defi­ni­cji i pojęć.

Paradygmat pro­gra­mo­wa­nia (ang. pro­gram­ming para­digm) ? wzo­rzec pro­gra­mo­wa­nia kom­pu­te­rów przed­kła­da­ny w danym okre­sie roz­wo­ju infor­ma­ty­ki ponad inne lub cenio­ny w pew­nych oko­licz­no­ściach lub zasto­so­wa­niach. (Źródło: Paradygmat pro­gra­mo­wa­nia ? Wikipedia, wol­na ency­klo­pe­dia)

No to teraz obiek­to­wy paradygmat:

Programowanie obiek­to­we (ang. object-orien­ted pro­gram­ming) ? para­dyg­mat pro­gra­mo­wa­nia, w któ­rym pro­gra­my defi­niu­je się za pomo­cą obiek­tów ? ele­men­tów łączą­cych stan (czy­li dane, nazy­wa­ne naj­czę­ściej pola­mi) i zacho­wa­nie (czy­li pro­ce­du­ry, tu: meto­dy). Obiektowy pro­gram kom­pu­te­ro­wy wyra­żo­ny jest jako zbiór takich obiek­tów, komu­ni­ku­ją­cych się pomię­dzy sobą w celu wyko­ny­wa­nia zadań. Podejście to róż­ni się od tra­dy­cyj­ne­go pro­gra­mo­wa­nia pro­ce­du­ral­ne­go, gdzie dane i pro­ce­du­ry nie są ze sobą bez­po­śred­nio zwią­za­ne. (Źródło: Programowanie obiek­to­we ? Wikipedia, wol­na ency­klo­pe­dia)

albo:

Programowanie obiek­to­we lub ina­czej pro­gra­mo­wa­nie zorien­to­wa­ne obiek­to­wo (ang. object-orien­ted pro­gra­ming, OOP) to para­dyg­mat pro­gra­mo­wa­nia przy pomo­cy obiek­tów posia­da­ją­cych swo­je wła­ści­wo­ści jak pola (dane, infor­ma­cje o obiek­cie) oraz meto­dy (zacho­wa­nie, dzia­ła­nia jakie wyko­nu­je obiekt). Programowanie obiek­to­we pole­ga na defi­nio­wa­niu obiek­tów oraz wywo­ły­wa­niu ich metod, tak aby współ­dzia­ła­ły wza­jem­nie ze sobą. (Źródło: Programowanie obiek­to­we ? Encyklopedia Zarządzania

Słownik języ­ka pol­skie­go mówi:

współ­dzia­łać
1. ?dzia­łać wspól­nie z kimś?
2. ?przy­czy­niać się do cze­goś razem z inny­mi czyn­ni­ka­mi?
3. ?o mecha­ni­zmach, narzą­dach itp.: funk­cjo­no­wać w powią­za­niu z innymi?

wywo­łać ? wywo­ły­wać
1. ?woła­niem skło­nić kogoś do wyj­ścia skądś?
2. ?przy­po­mnieć sobie lub innym coś?
3. ?spo­wo­do­wać coś lub stać się przy­czy­ną cze­goś?
4. ?oznaj­mić coś publicz­nie?
5. ?oddzia­łać na kli­szę, bło­nę lub papier foto­gra­ficz­ny środ­ka­mi che­micz­ny­mi w celu uwi­docz­nie­nia obra­zu uta­jo­ne­go na mate­ria­le światłoczułym?

Tak więc stwier­dze­nie, że obiek­ty z sobą współ­dzia­ła­ją” ozna­cza, że wywo­łu­ją się” wza­jem­nie w celu spo­wo­do­wa­nia cze­goś kon­kret­ne­go. Innymi sło­wy obiek­ty two­rzą­ce pro­gram (sys­tem) są od sie­bie wza­jem­nie uza­leż­nio­ne. Dlatego pod­sta­wo­wym związ­kiem w pro­ce­sie ana­li­zy i pro­jek­to­wa­nia zorien­to­wa­ne­go obiek­to­wo jest wza­jem­na zależ­ność”, nazy­wa­na w ory­gi­nal­nej spe­cy­fi­ka­cji UML związ­kiem usłu­go­daw­ca-usłu­go­bior­ca”.

Zależności

Związek ten nale­ży utoż­sa­miać z każ­dą wza­jem­ną zależ­no­ścią. Z uwa­gi na to, że mamy wie­le typów zależ­no­ści, wska­zu­je­my kon­kret­ny typ z pomo­cą ste­reo­ty­pu («[nazwa_typu]»).

Najczęściej wystę­pu­ją­cy typ zależ­no­ści to zwią­zek uży­cia. Oznacza on, że jeden obiekt wywo­łu­je umie­jęt­no­ści (ope­ra­cje) inne­go czy­li uży­wa go” do reali­za­cja swo­je­go zada­nia. Związek taki ozna­cza­ny ste­reo­ty­pem «use»:

uml-diagram-klas-zwiazek-uzycia

F uży­wa (jest zależ­ny od) E (co do zasa­dy tu F nie jest samo­dziel­ny w tym co robi”).

Formą zależ­no­ści jest tak­że dość rzad­ko wyko­rzy­sty­wa­na abs­trak­cja («Abstraction»). Związek ten jest wyko­rzy­sty­wa­ny do łącze­nia dwóch pojęć, z któ­rych jed­no jest abs­trak­cją dru­gie­go. Inna czę­sto wyko­rzy­sty­wa­na zależ­ność to «instanceOf» ozna­cza zależ­ność mode­lu (obiek­tu) od jego meta­mo­de­lu (kla­sy­fi­ka­to­ra) a tak­że od meta­me­ta­mo­de­lu.

Tak więc model opro­gra­mo­wa­nia w nota­cji UML z uży­ciem obiek­to­we­go para­dyg­ma­tu powi­nien wyglą­dać mniej wię­cej tak:

Wzorzec BCE

Na dia­gra­mie uży­to sym­bo­li klas (gra­ficz­na repre­zen­ta­cja ste­reo­ty­pów) zaczerp­nię­tych wzor­ca archi­tek­to­nicz­ne­go BCE.

Realizacja i kompozycja

Dokumentowanie deta­li struk­tu­ry ele­men­tów np. repo­zy­to­rium, wyma­ga stwo­rze­nia kolej­ne­go dia­gra­mu: mode­lu struk­tu­ry obiek­tów repre­zen­tu­ją­cych np. zło­żo­ną struk­tu­rę obiek­tu nio­są­ce­go infor­ma­cje (np. z formularza).

uml-diagram-klas-zwiazki-realizacja

Korzystamy tu ze związ­ku reali­za­cja i związ­ku kom­po­zy­cja. Realizacja to zwią­zek pomię­dzy spe­cy­fi­ka­cją a jej reali­za­cją (pro­jek­tem, imple­men­ta­cją, itp.), wska­zu­je zależ­ność imple­men­ta­cji od jej mode­lu. C2 jest spe­cy­fi­ka­cją (opi­sem, doku­men­ta­cją) reali­za­cji D2. Najczęściej zwią­zek ten jest sto­so­wa­ny pomię­dzy spe­cy­fi­ka­cją inter­fej­su a jego imple­men­ta­cją a tak­że gene­ral­nie pomię­dzy abs­trak­cją a jej reali­za­cją. Typowym przy­kła­dem uży­cia tego związ­ku jest np. poka­za­nie na jed­nym dia­gra­mie abs­trak­cji bytu w repo­zy­to­rium i reali­za­cji jej struktury:

model-dziedziny-realizacja-repozytorium

Na dia­gra­mie uży­to tak­że związ­ku całość-część”: linia zakoń­czo­na wypeł­nio­nym rom­bem na jed­nym koń­cu. Romb wska­zu­je na całość”: ele­ment nad­rzęd­ny drze­wia­stej struk­tu­ry kon­struk­cji. Jest to spe­cjal­ny zwią­zek ozna­cza­ją­cy trwa­łe (kon­struk­cyj­ne) powią­za­nie pomię­dzy deta­la­mi skła­da­ją­cy­mi się na okre­ślo­ną całość. UWAGA! Nie ma on nic wspól­ne­go z poję­ciem rela­cji” zna­nym z teo­rii rela­cyj­nych baz danych!

Biorąc pod uwa­gę fakt, jakim jest her­me­ty­za­cja jako cecha obiek­to­wych kon­struk­cji, takie enti­ties” nie współ­dzie­lą mie­dzy sobą ŻADNYCH ele­men­tów (danych). Użycie na dnie” bazy danych, wspól­nej dla całej apli­ka­cji, bazy dopro­wa­dzo­nej do tak zwa­nej znor­ma­li­zo­wa­nej posta­ci, łamie wszel­kie zasa­dy obiek­to­wych kon­struk­cji: łamie pod­sta­wo­wą zasa­dę jaką jest her­me­ty­za­cja imple­men­ta­cji obiek­tów (zakaz jakie­go­kol­wiek współ­dzie­le­nia cze­go­kol­wiek, nie nale­ży mylić współ­dzie­le­nia z re-użyciem).

Generalizacja i asocjacja

Oprócz mode­li struk­tur, powsta­ją czę­sto mode­le poję­cio­we. Są to odręb­ne dia­gra­my. Ich celem jest doku­men­to­wa­nie związ­ków seman­tycz­nych i syn­tak­tycz­nych pomię­dzy klu­czo­wy­mi poję­cia­mi wyko­rzy­sty­wa­ny­mi w pro­jek­cie. Stanowią one nazwy obiek­tów i ich typy (atry­bu­ty klas to tak­że obiek­ty). Wykorzystywane są tu dwa rodza­je związ­ków: gene­ra­li­za­cja i aso­cja­cja. Są to związ­ki repre­zen­tu­ją­ce WYŁĄCZNIE logicz­ne powią­za­nia pomię­dzy poję­cia­mi, nie mode­lu­ją one struk­tur a ni implementacji!

Jeżeli jakieś poję­cie ma swo­je spe­cja­li­zo­wa­ne typy, lub z dru­giej stro­ny, gru­pa pojęć daje się uogól­nić innym nad­rzęd­nym poję­ciem (gene­ra­li­zo­wa­nie), sto­su­je­my zwią­zek gene­ra­li­za­cji. Związek ten (korzy­sta­nie z nie­go) ma sens tyl­ko gdy licz­ba typów to co naj­mniej dwa, co do zasa­dy zwią­zek gene­ra­li­za­cji słu­ży do gru­po­wa­nia. Jeżeli pomię­dzy poję­cia­mi ist­nie­je zwią­zek wyni­ka­ją­cy z dzie­dzi­ny pro­ble­mu (np. zwią­zek pomię­dzy zwie­rzę­ciem a kar­mą dla nie­go) mode­lu­je­my go linią cią­głą łączą­cą powią­za­ne tak poję­cia. Poniżej gra­ficz­ny przy­kład uży­cia tych związków:

zwiazki-generalizacji-i-asocjacje-w-modelu-pojeciowym

B1 i B2 to kon­kret­ne typy poję­cia A (typem jest tak­że poję­cie). Analogicznie B12 i B22 to typy poję­cia A3. Pomiędzy poję­cia­mi A i A3 ist­nie­je zwią­zek logicz­ny (moż­na go nazwać, wpi­su­jąc te nazwę na linii). Typy mogą mieć wię­cej niż jeden kon­tekst dla­te­go mogą zostać pogru­po­wa­ne a każ­da gru­pa otrzy­mu­je nazwę nazwa gru­py” (oryg. Generalization Sets). Nie ma sen­su zwią­zek gene­ra­li­za­cji pomię­dzy tyl­ko jed­ną parą pojęć, bo ozna­cza wte­dy po pro­stu toż­sa­mość. Np. poję­cie woje­wódz­two” w Polsce ma obec­nie szes­na­ście spe­cja­li­za­cji, mają one swo­je nazwy, i to jest jed­na gru­pa typów. Jednak woje­wódz­twa moż­na podzie­lić tak­że np. ze wzglę­du na wiel­kość na np. trzy gru­py: małe woje­wódz­two, śred­nie woje­wódz­two i duże woje­wódz­two, i to będzie dru­ga i nie­za­leż­na gru­pa typów.

Modele…

Wszystkie powyż­sze przy­kła­dy to dia­gra­my klas nota­cji UML, jed­nak jak widać każ­dy ma zupeł­nie inne prze­zna­cze­nie (jest mode­lem cze­go inne­go). Nie oma­wia­łem tu zupeł­nie dia­gra­mów klas mode­lu­ją­cych kod pro­gra­mów. Zaznaczę jedy­nie, że są to kolej­ne mode­le doku­men­to­wa­ne z uży­ciem dia­gra­mów klas nota­cji UML, i omó­wio­ne powy­żej związ­ki dzie­dzi­cze­nia i aso­cja­cje na mode­lach poję­cio­wych mają tam zupeł­nie inne znaczenie.

Modele mogą być róż­ne i doty­czyć róż­nych rze­czy (patrz Modele.…). Tu chcę zwró­cić uwa­gę na bar­dzo waż­ny aspekt: abs­trak­cyj­ne i rze­czy­wi­ste poję­cia w mode­lach (na dia­gra­mach). Dostrzegam ogrom­ny bała­gan nie tyl­ko w doku­men­tach pro­jek­to­wych ale tak­że i w lite­ra­tu­rze, gdzie auto­rzy poka­zu­ją wie­le róż­nych przy­kła­dów, któ­re nie­ste­ty są złe i pozba­wio­ne uzasadnienia.

Przede wszyst­kim mode­le dzie­li­my, jak już wspo­mnia­łem, na poję­cio­we i te mode­lu­ją­ce jakąś okre­ślo­ną rze­czy­wi­stość. Modele poję­cio­we to mode­le poka­zu­ją­ce poję­cia oraz seman­tycz­ne i syn­tak­tycz­ne związ­ki mie­dzy nimi. Modele poję­cio­we słu­żą do udo­ku­men­to­wa­nia dzie­dzi­no­wej tak­so­no­mii co z jed­nej stro­ny pozwa­la utrzy­mać peł­ną jed­no­znacz­ność doku­men­ta­cji a z dru­giej, na eta­pie imple­men­ta­cji, pozwa­la podej­mo­wać decy­zje o typach danych. Służą one np. do budo­wa­nia słow­ni­ków i ety­kie­to­wa­nia np. pól for­mu­la­rzy (pole Nazwa woje­wódz­twa, któ­re­go zawar­tość będzie wybie­ra­na ze słow­ni­ka zawie­ra­ją­ce­go szes­na­ście nazw). Na tych mode­lach poja­wia­ją się w zasa­dzie wyłącz­nie poję­cia sta­no­wią­ce abs­trak­cje i typy, nie są to mode­le żad­ne­go kodu, dzie­dzi­ny itp. Tu przy­po­mnę, że model dzie­dzi­ny sys­te­mu to model opi­su­ją­cy mecha­nizm jego (sys­te­mu, apli­ka­cji) dzia­ła­nia, repre­zen­to­wa­ny jest przez liter­kę M we wzor­cu MVC, poważ­nym błę­dem jest uzna­wa­nie tych mode­li za mode­le danych.

Modele struk­tu­ry to mode­le opi­su­ją­ce okre­ślo­ne kon­struk­cje”, głów­nie na dwóch pozio­mach abs­trak­cji: jako model i jako meta­mo­del. Z regu­ły, w pro­jek­tach zwią­za­nych z opro­gra­mo­wa­niem, ta kon­struk­cja to wła­śnie Model Dziedziny czy­li mecha­nizm dzia­ła­nia, tak zwa­na logi­ka biznesowa/dziedzinowa aplikacji.

Podsumowanie

Tak więc nie ma cze­goś takie­go jak dia­gram klas dla pro­jek­tu”. Mamy dla dane­go pro­jek­tu: model poję­cio­wy, mode­le logi­ki sys­te­mu, mode­le struk­tu­ry obiek­tów, mode­le imple­men­ta­cji. To wszyst­ko są dia­gra­my klas ale każ­dy z nich do model cze­goś inne­go”. Paradygmat obiek­to­wy jasno mówi: obiek­ty współ­pra­cu­ją, więc stan­dar­do­wym związ­kiem w mode­lach logi­ki dzia­ła­nia są związ­ki uży­cia a nie aso­cja­cje ani związ­ki dzie­dzi­cze­nia czy kom­po­zy­cji. Diagramy te nie są żad­ny­mi mode­la­mi danych mię­dzy inny­mi dla­te­go, że z zasa­dy para­dyg­mat obiek­to­wy ukry­wa je (her­me­ty­za­cja), na zewnątrz” dostęp­ne są wyłącz­nie publicz­ne ope­ra­cje obiek­tów. Utrwalanie obiek­tów (zapis war­to­ści atry­bu­tów np. w bazie danych) to zada­nie do roz­wią­za­nia dopie­ro na eta­pie imple­men­ta­cji, pole­ga­ją­ce na zagwa­ran­to­wa­niu zacho­wa­nia” sta­nów obiek­tów na czas wyłą­cze­nia zasi­la­nia, by nie ule­cia­ły” z pamię­ci kom­pu­te­ra, któ­ry jest śro­do­wi­skiem wyko­na­nia pro­gra­mu. Na eta­pie ana­li­zy obiek­to­wej i mode­lo­wa­nia logi­ki sys­te­mu nie mode­lu­je­my żad­nych danych.

Poniższy przy­kład, jakich wie­le w sie­ci, jest wzor­co­wym antyprzykładem.

(https://​www​.wie​dza​na​plus​.pl/​p​r​o​g​r​a​m​o​w​a​n​i​e​/​3​3​-​u​m​l​/​6​8​-​j​e​z​y​k​-​u​m​l​-​p​r​o​j​e​k​t​-​s​k​l​e​p​u​-​k​o​m​p​u​t​e​r​o​w​e​g​o​.​h​tml)

Pierwsza zła cecha tego dia­gra­mu to czę­sty błąd nazy­wa­ny popu­lar­nie prze­cią­ża­niem obiek­tów”: tu obiekt Faktura ma ope­ra­cje spo­rządź”. Klasyczny błąd archi­tek­to­nicz­ny pole­ga­ją­cy na obcią­ża­niu obiek­tu cudzą odpo­wie­dzial­no­ścią. Jeżeli kla­sa Faktura repre­zen­tu­je np. fak­tu­ry sprze­da­ży, to sys­tem mają­cy w pamię­ci kolek­cję setek fak­tur i każ­da z kodem (ma te ope­ra­cję) słu­żą­cym do jej spo­rzą­dze­nia był­by masa­krą zaję­to­ści pamię­ci. Dodam, że model taki nie ma nic wspól­ne­go z rze­czy­wi­sto­ścią, bo fak­tu­ry wysta­wia ktoś” a nie fak­tu­ra”. Trzecia rzecz: fak­tu­ra zaku­pu i fak­tu­ra sprze­da­ży to niczym nie róż­nią­ce się struk­tu­ry, więc two­rze­nie takie­go roz­róż­nie­nia jest pozba­wio­ne sen­su. To błę­dy poję­cio­we i ten dia­gram ma masę takich błę­dów. Druga wada: błęd­ne uży­cie związ­ku kom­po­zy­cji: powyż­szy dia­gram nale­ża­ło­by inter­pre­to­wać jako struk­tu­rę o jed­nej zwar­tej kon­struk­cji, np. takiej jak samo­chód skła­da­ją­cy się z setek pod­ze­spo­łów ale sta­no­wią­cy jed­nak jed­ną całość. Brak mode­lu poję­cio­we­go i słow­ni­ka powo­du­je wie­le nie­jed­no­znacz­no­ści. Np. zwią­zek pomię­dzy Klientem a rekla­ma­cją wska­zu­je, że Reklamacje są inte­gral­ną czę­ścią Klienta (tak jak koła i sil­nik są inte­gral­ną czę­ścią samo­cho­du) co nawet w świe­tle potocz­ne­go rozu­mie­nia tych słów kłó­ci się ze zdro­wym rozsądkiem.

Użycie związ­ków poję­cio­wych (aso­cja­cja) jest zupeł­nie nie­zro­zu­mia­łe w tym przy­pad­ku. Nazwa aso­cja­cji zawie­ra” nie ma kie­run­ku a więc nie wia­do­mo co jest zawar­te w czym. Związki zależ­no­ści tak­że są nie­ja­sne: jak inter­pre­to­wać np. zapis mówią­cy, ze obiek­ty kla­sy użyt­kow­ni­cy zale­żą od obiek­tów kla­sy Raporty? Jeżeli autor miał na myśli użyt­kow­nik uży­wa rapor­tów” to popły­nął w sfe­rę mowy potocz­nej”, to chy­ba naj­czę­ściej spo­ty­ka­ny błąd pole­ga­ją­cy na tym, że autor dia­gra­mu nadal pisze spe­cy­fi­ka­cję pro­zą, ale z uży­ciem sym­bo­li (tu UML) zamiast słów.

Mogę się jedy­nie domy­ślać, że autor dia­gra­mu miał w gło­wie” model rela­cyj­ny związ­ków encji i użył ikon z nota­cji UML w cał­ko­wi­cie innych zna­cze­niach niż ta nota­cja defi­niu­je. Takie dia­gra­my nie powin­ny powsta­wać, są one nie­ste­ty dowo­dem na to, że pro­gra­mi­ści mówią­cy te doku­men­ty z UML nic nie wyja­śnia­ją i są nie­pre­cy­zyj­ne, i tak musi­my sami powtó­rzyć te ana­li­zę” mają rację. Są tak­że dowo­dem, że są to jed­nak pro­jek­ty struk­tu­ral­ne a nie obiek­to­we, a uży­cie nota­cji UML pole­ga­ło na sko­rzy­sta­niu z zesta­wu ikon tak się to robi two­rząc nie­sfor­ma­li­zo­wa­ne sche­ma­ty blo­ko­we z uży­ciem np. pro­gra­mów do two­rze­nia pre­zen­ta­cji takich jak PowerPoint. Zapewne poza auto­rem tego dia­gram, nikt nie ma poję­cia o co w nim cho­dzi.… Jeżeli autor miał na celu udo­ku­men­to­wa­nie mode­lu danych” to powi­nien użyć nota­cji ERD. A tak to mamy sche­mat blo­ko­wy, w któ­rym ktoś użył UML jako biblio­te­ki sym­bo­li wpro­wa­dza­jąc czy­tel­ni­ka w błąd.

Z przy­kro­ścią muszę przy­znać, że od takich błę­dów nie są wol­ne tak­że nie­któ­re pod­ręcz­ni­ki i mate­ria­ły szko­le­nio­we… a tak­że doku­men­ty two­rzo­ne przez pra­cow­ni­ków wie­lu firm na ryn­ku IT.

P.S.

Na przy­kła­dy popraw­nych dia­gra­mów z uza­sad­nie­niem zapra­szam do mojej książ­ki i na moje szko­le­nia i warsz­ta­ty.

Specyfikacja UML v.2.5

Niestety spraw­ne” korzy­sta­nie z takich spe­cy­fi­ka­cji wyma­ga umie­jęt­no­ści czy­ta­nia mode­li poję­cio­wych (dia­gra­mów klas UML) opi­su­ja­cych syn­tak­ty­kę (syn­tax) jak wyżej (ich two­rze­nie też do łatwych nie nale­ży…). Przytaczam to jako źró­dło tego o czym tu pisałem.

W UML wszyst­ko jest kla­są”, związ­ki mię­dzy ele­men­ta­mi dia­gra­mów tak­że. Zostało to poka­za­ne w spe­cy­fi­ka­cji UML v.2.5.:

uml-zaleznosci
uml-klacyfikator
uml-zwiazki

W UML 2.5 prak­tycz­nie zni­ka w koń­cu dzie­dzi­cze­nie i agre­ga­cja. Uff… poni­żej pod­su­mo­wa­nie na jed­nym diagramie.

Dodatek [2022 – 07-22]

…chciał­bym zapy­tać o dzie­dzi­cze­nie w UML. Brałem ostat­nio udział w kil­ku roz­mo­wach o pra­cę. Moi roz­mów­cy czę­sto utrzy­mu­ją, że w UML jest to dzie­dzi­cze­nie. Mało tego, wyko­rzy­stu­ją to dzie­dzi­cze­nie na dia­gra­mach klas, w czymś co nazy­wa­ją mode­lem dzie­dzi­ny (oczy­wi­ście bez ope­ra­cji klas). Zajrzałem do spe­cy­fi­ka­cji UML i jestem tro­chę zdez­o­rien­to­wa­ny, ponie­waż poję­cie dzie­dzi­cze­nie dość czę­sto wystę­pu­je w tej doku­men­ta­cji, choć­by w tym fragmencie. 

W jakim zna­cze­niu jest tu uży­te poję­cie dzie­dzi­cze­nia? Czy jest gdzieś w spe­cy­fi­ka­cji wprost infor­ma­cja o usu­nię­ciu dzie­dzi­cze­nia z UMLa?

Porównując ze spe­cy­fi­ka­cją 2.4. nie ma, poję­cie dzie­dzi­cze­nia nadal jest obec­ne w języ­kach pro­gra­mo­wa­nia, a w spe­cy­fi­ka­cji 2.5.xx sło­wo inhe­ri­tan­ce” poja­wia sie tyl­ko 4 razy, i doty­czy wyłącz­nie komen­ta­rzy zwią­za­nych z uogólnieniami. 

Cytowany zwią­zek Generalizacji jest związ­kiem poję­cio­wym a nie struk­tu­ral­nym cze­goś ist­nie­ją­ce­go (struk­tu­ra mode­lo­wa­ne­go sys­te­mu). Formalnie w UML mamy zwią­zek Generalizacji, i jest to zwią­zek poję­cio­wy, ale nie ma w UML roz­dzia­łu Dziedziczenie”. Inherit w j. angiel­skim to tak­że prze­ję­cie cech po czymś” czy­li zwią­zek gene­ra­li­zo­wa­nia i spe­cja­li­zo­wa­nia. Generalziacja, jako zwią­zek ogól­ny-szcze­gól­ny, poka­zu­je że szcze­gól­ny przy­pa­dek, poję­cie i jego defi­ni­cja, ma wszyst­kie cechy przy­pad­ku ogól­niej­sze­go, więc pies jako szcze­gól­ny typ ssa­ka ma wszyst­kie cechy ssa­ka (cho­dzi o defi­ni­cje tego czym jest ssak). Czyli:
1. ssak: krę­go­wiec, któ­re­go mło­de kar­mią się mle­kiem mat­ki,
2. pies: <ssak> któ­ry szcze­ka,
więc:

pies: <krę­go­wiec, któ­re­go mło­de kar­mią się mle­kiem mat­ki>, któ­ry szczeka, 

czy­li pies (a kon­kret­nie defi­ni­cja psa) dzie­dzi­czy” po ssa­ku (defi­ni­cji ssa­ka) jego okre­ślo­ne cechy, czy­li ozna­cza to, że są one (cechy ssa­ka) np. dla psa i kota wspól­ne, a nie że, kot czy pies coś dzie­dzi­czy” po ssaku :). 

Dlatego w UML teraz jest napi­sa­ne, że mamy gene­ra­li­za­cję jako zwią­zek mię­dzy kla­sa­mi, ale nigdzie nie ma związ­ku dzie­dzi­cze­nia” mię­dzy klasami.

Tekst rozdz. 9.2.3.2. tłu­ma­czy­my tak, ze gene­ra­li­za­cja ozna­cza, że gene­ra­li­zo­wa­na defi­ni­cja (cechy czy­li atry­bu­ty i zacho­wa­nia) są wspól­ne (dzie­dzi­czą) dla spe­cja­li­zo­wa­nych ele­men­tów. W mode­lu poję­cio­wym (name­spa­ce) tak to dzia­ła. I teraz: model struk­tu­ry cze­go­kol­wiek ist­nie­ją­ce­go nie ma abs­trak­cji (a gene­ra­li­zo­wa­ne poję­cia to abs­trak­cje, poję­cie ssak to poję­cie abs­trak­cyj­ne). Opisując więc trak­tor jako pojazd czy doku­men­ty w księ­go­wo­ści jako doku­en­ty, nie ma nad nimi uogól­nień”, po któ­rych dzie­dzi­czą (sa to jed­nak poję­cia słow­ni­ko­we). Po tra­wie nie bie­ga­ją ssa­ki” tyl­ko psy, koty, lwy… 

Znakomita więk­szość zna­nych mi ludzi w IT nie odróż­nia mode­lu poję­cio­we­go od mode­lu struk­tu­ry sys­te­mu, któ­ry zbu­do­wa­ny jest (każ­dy) z real­nych ele­men­tów. W miej­sce sta­re­go” dzie­dzi­cze­nia w UML wpro­wa­dzo­no poję­cia: sza­blon (tem­pla­te) oraz rola (real­nym czymś w samo­cho­dzie jest sil­nik”, poję­cie napęd” to nazwa funkcji/roli okre­ślo­ne­go kom­po­nen­tu, ale nie pisze­my: „<sil­nik> dzie­dzi­czy po <napę­dzie>” tyl­ko „<sil­nik> peł­ni rolę <napę­du>” tak samo jak nie powie­my „<pies> dzie­dzi­czy po <zwie­rzę domo­we>” tyl­ko „<pies> peł­ni rolę <zwie­rzę­cia domowego>”. 

Języki pro­gra­mo­wa­nia pozwa­la­ją na tak zwa­ne re-uży­cie kodu, czy­li wycią­ga­nie pew­nych wspól­nych cech ponad kon­kret­ne komponenty/klasy (abs­trak­cja) po to by tyl­ko raz pisać kod kom­po­nen­tów mają­cych wspól­ne cechy. Jednak pro­jek­tu­jąc model dzie­dzi­ny” nie ma w niej abs­trak­cji, mając model dzie­dzi­ny (mecha­nizm dzia­ła­nia apli­ka­cji) zamie­nia­my gene­ra­li­za­cje i dzie­dzi­cze­nia” poję­cio­we na atry­bu­ty i typy real­nych rze­czy, tak to opi­sa­no książ­ce o mode­lo­wa­niu sys­te­mów już w 2007 roku: 

Oczywiście pro­gra­mi­sta może uży­wać gdzie chce dzie­dzi­cze­nia (ma taką moż­li­wość w każ­dym obiek­to­wym języ­ku pro­gra­mo­wa­nia) ale to jed­na z naj­gor­szych prak­tyk, bo łamią­cych klu­czo­wą zasa­dę jaką jest her­me­ty­za­cja kom­po­nen­tów („zakaz” współ­dzie­le­nia cze­go­kol­wiek). To dla­te­go od wie­lu lat OOP (Object-orien­ted Programming, języ­ki i pro­gra­mo­wa­nie obiek­to­we) i OOAD (Object-orien­ted Analysis and Design) to odręb­ne dzie­dzi­ny”.

Diagram prawdę Ci powie

Dzisiaj będzie bar­dzo krót­ki wpis, któ­rym nie­mal­że w cało­ści będzie cytat z arty­ku­łu pew­ne­go pro­gra­mi­sty. Każdy ana­li­tyk i pro­jek­tant powi­nien prze­czy­tać cały arty­kuł (nie jest dłu­gi) i koniecz­nie komen­ta­rze pod nim. Jeden komen­tarz zacy­tu­je bo jest zna­mien­ny, choć­by dla­te­go, że moje doświad­cze­nia są dokład­nie takie same:

Co Ty czło­wie­ku, życia nie znasz? Przecież w realu jak­byś poszedł do takie­go i podzie­lił się taki­mi uwa­ga­mi to foch na pare tygo­dni co naj­mniej gwa­ran­to­wa­ny. Kiedyś mia­łem podob­ną sytu­ację (a raczej serię sytu­acji, ale doty­czą­cych rze­czy o mniej­szej ska­li) to efekt był taki, że wola­łem zmie­nić robotę 😉

A teraz zapra­szam do lek­tu­ry tek­stu, któ­ry napi­sał nie ana­li­tyk a pro­gra­mi­sta (a kim jest to pole­cam jego CV na stronie):

Jak to z każ­dym języ­kiem bywa, nie­kie­dy jeste­śmy w sta­nie wydo­być bar­dzo wie­le nawet bez zbyt­nie­go wgłę­bia­nia się w szcze­gó­ły, po pro­stu wie­my, że nie­któ­re rze­czy są waż­niej­sze niż inne. Tak jak w zda­niach, któ­rych spój­ni­kiem jest ?ale?. Każdy wie, że wszyst­ko to, co przed owym ?ale? się znaj­du­je jest nie­war­te słu­cha­nia 😛 I wła­śnie kil­ka takich przy­pad­ków chciał­bym dzi­siaj opi­sać. Sytuacji, w któ­rych rozu­mie­nie całe­go kon­tek­stu jest zbęd­ne, wystar­czy szyb­ki rzut okiem na dia­gram, aby wie­dzieć co jest najważniejsze.

W oma­wia­nych prze­ze mnie przy­pad­kach cho­dzi o szyb­kie wyła­pa­nie błę­dów pro­jek­to­wych, bez koniecz­no­ści zagłę­bia­nia się w logi­kę, któ­ra kry­je się za dia­gra­ma­mi. (Programistyka: Diagram praw­dę Ci powie)