Obiektowy model systemu

Wprowadzenie

Na temat tak zwa­nych metod obiek­to­wych czę­sto moż­na spo­tkać tek­sty takie jak ten z wikipedii: 

Programowanie obiek­to­we (ang. object-orien­ted pro­gram­ming, OOP) ? 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. Programowanie obiek­to­we ma uła­twić pisa­nie, kon­ser­wa­cję i wie­lo­krot­ne uży­cie pro­gra­mów lub ich fragmentów

Portal mFiles podaje:

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.: Programowanie obiek­to­we ? Encyklopedia Zarządzania)

Albo takie jak ten ze stro­ny JavaStart:

Programowanie obiek­to­we jest para­dyg­ma­tem pro­gra­mo­wa­nia, któ­ry opie­ra się o two­rze­nie apli­ka­cji w taki spo­sób, aby jak naj­le­piej odzwier­cie­dlać ota­cza­ją­cą nas rze­czy­wi­stość i aby model danych odda­wał spo­sób postrze­ga­nia świa­ta przez czło­wie­ka (czy­li, że na przy­kład że jabł­ko jest owo­cem, a nie kolo­ro­wą kulą). […] Poznasz tu zagad­nie­nia mię­dzy inny­mi takie jak kla­sa, obiekt, inter­fejs, czy kla­sa abs­trak­cyj­na i dzie­dzi­cze­nie. (Java – Programowanie Obiektowe | JavaStart)

Bardzo wie­lu auto­rów powie­la schemat: 

Założenia pro­gra­mo­wa­nia obiek­to­we­go
?Abstrakcja
?Hermetyzacja danych (enkap­su­la­cja)
?Dziedziczenie
?Polimorfizm

Programowanie obiek­to­we zakła­da łącze­nie danych i funk­cji w jed­nym obiekcie.

(wie­le mate­ria­łów w sie­ci, na ten temat, podob­nie jak i ten, nie zawie­ra danych auto­rów ani daty publikacji)

Przykłady z dość powszech­nie wyko­rzy­sty­wa­nych mate­ria­łów dydaktycznych:

Abstrakcyjną ideą pro­gra­mo­wa­nia obiek­to­we­go jest powią­za­nie sta­nu (danych, któ­re okre­śla­ne są zwy­kle pola­mi) i zacho­wa­nia (algo­ryt­my zwią­za­ne ze sta­nem i całym obiek­tem, okre­śla­ne sło­wem meto­dy). Program korzy­sta­ją­cy z obiek­to­wo­ści 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ń. W pewien spo­sób jest to naj­bar­dziej intu­icyj­ne podej­ście do roz­wią­zy­wa­nia pro­ble­mów, bo w taki spo­sób ? trak­tu­jąc zagad­nie­nia jako obiek­ty wraz ze sta­nem i meto­da­mi; do roz­wią­zy­wa­nia pro­ble­mów pod­cho­dzi ludz­ki mózg. Typy obiek­tów nazy­wa­my kla­sa­mi. (źr. TI/Wstęp do pro­gra­mo­wa­nia obiek­to­we­go ? Brain-wiki)

(ten tekst tak­że nie zawie­ra danych auto­ra ani źródeł)

Programowanie zorien­to­wa­ne obiek­to­wo pole­ga na intu­icyj­nym, natu­ral­nym pisa­niu pro­gra­mów, poprzez mode­lo­wa­nie obiek­tów świa­ta rze­czy­wi­ste­go, ich atry­bu­tów i zacho­wań odpo­wied­ni­ka­mi opro­gra­mo­wa­nia. Programowanie zorien­to­wa­ne obiek­to­wo mode­lu­je tak­że komu­ni­ka­cję pomię­dzy obiek­ta­mi przez wia­do­mo­ści.
Obiekty mają atry­bu­ty (dane) i wyka­zu­ją zacho­wa­nie (funk­cje, meto­dy). Obiekty są ele­men­ta­mi opro­gra­mo­wa­nia do ponow­ne­go uży­cia, two­rzo­ne są z ?planów?zwanych kla­sa­mi. Różne obiek­ty mogą mieć wie­le takich samych atry­bu­tów i podob­ne zacho­wa­nia. (źr. dydak​ty​ka​.polsl​.pl ? kwmimkm )

W pro­gra­mo­wa­niu obiek­to­wym pro­gra­my defi­niu­je się za pomo­cą obiek­tów okre­śla­ją­cych dane rze­czy­wi­ste i funk­cji na nich ope­ru­ją­cych. 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ę mię­dzy sobą w celu wyko­ny­wa­nia okre­ślo­nych zadań. 

Dziedziczenie porząd­ku­je i wspo­ma­ga poli­mor­fizm i inkap­su­la­cję
dzię­ki umoż­li­wie­niu defi­nio­wa­nia i two­rze­nia spe­cja­li­zo­wa­nych obiek­tów na pod­sta­wie bar­dziej ogól­nych. Dla obiek­tów spe­cja­li­zo­wa­nych nie trze­ba rede­fi­nio­wać całej funk­cjo­nal­no­ści, lecz tyl­ko tę, któ­rej nie ma obiekt ogólniejszy.

W typo­wym przy­pad­ku powsta­ją gru­py obiek­tów zwa­ne kla­sa­mi
oraz gru­py klas zwa­ne drze­wa­mi. Odzwierciedlają one wspól­ne cechy
obiek­tów. Każdy obiekt może (choć nie musi) mieć przod­ka, od któ­re­go się wywo­dzi. Np. każ­dy czło­wiek ma swo­je­go przod­ka w posta­ci rodzi­ca.
W zależ­no­ści od przy­ję­tej meto­do­lo­gii obiekt może mieć jed­ne­go lub wie­lu przod­ków. O ile może ist­nieć ogra­ni­cze­nie w posta­ci jed­ne­go przod­ka, o tyle takie­go ogra­ni­cze­nia nie ma co do licz­by potom­ków, któ­rych dany obiekt jest przod­kiem. Fakt posia­da­nia przod­ka wią­że się ści­śle z dziedziczeniem.

Dziecko jako obiekt może dzie­dzi­czyć po swo­ich przod­kach
takie atry­bu­ty, jak kolor oczu, wzrost itp. Obiekt może oprócz dzie­dzi­cze­nia atry­bu­tów odzie­dzi­czyć meto­dy, czy­li ? ana­lo­gicz­nie ? w naszym przy­kła­dzie dziec­ko może po swo­ich przod­kach odzie­dzi­czyć takie ?meto­dy? (zacho­wa­nia), jak skłon­ność do pale­nia papie­ro­sów, talent w wybra­nych dzie­dzi­nach życia, wcze­sne wsta­wa­nie itp. ?(Gryglewicz-Kacerka & Duraj, 2013)?

Ta prób­ka jest moim zda­niem repre­zen­ta­tyw­na, jeśli cho­dzi o treść publi­ka­cji na ten temat. Autorzy tych tre­ści, naj­czę­ściej pro­gra­mi­ści, sku­pia­ją się na funk­cjach, danych, i tak na praw­dę trak­tu­ją poję­cie obiek­to­we­go para­dyg­ma­tu” jak kolej­ne wcie­le­nie struk­tu­ral­ne­go kodu, tyle, że wg, innych zasad (obiekt łączą­cy dane i funk­cje, dzie­dzi­cze­nie itp.), co jest ogrom­nym uprosz­cze­niem. Sam fakt zasto­so­wa­nia wymie­nia­nych wyżej kon­struk­cji języ­ków zorien­to­wa­nych obiek­to­wo nie czy­ni pro­gra­mu obiek­to­wym, to kolej­ne wcie­le­nie pro­gra­mo­wa­nia struk­tu­ral­ne­go, gdzie blo­ki i pod­pro­gra­my zyska­ły nazwę obiek­tów a re-uży­cie kodu nazwę dzie­dzi­cze­nia. Paradygmat obiek­to­wy to przede wszyst­kim architektura

Jednak para­dyg­mat to tyl­ko umo­wa, pozo­sta­je sto­so­wa­nie wzor­ców i dobrych prak­tyk w toku projektowania. 

Prawie nikt nie pisze o ana­li­zie i pro­jek­to­wa­niu zorien­to­wa­nym obiek­to­wo, a cała idea pole­ga tu na zaczy­na­niu od ana­li­zy i pro­jek­to­wa­nia, potem dopie­ro się pro­gra­mu­je. Nie przy­pad­kiem naj­po­pu­lar­niej­szym skró­tem w lite­ra­tu­rze przed­mio­tu jest OOAD (ang. Object-Oriented Analysis and Design, Obiektowo Zorientowane Analiza i Projektowanie). 

Istotą obiek­to­we­go para­dyg­ma­tu w inży­nie­rii opro­gra­mo­wa­nia jest to, że wynik ana­li­zy jest zara­zem projektem!

Paradygmat obiektowy

Pół roku temu w arty­ku­le Paradygmat obiek­to­wy i Przypadki Użycia pisa­łem o para­dyg­ma­cie obiektowym:

Paradygmat obiek­to­wy, w swej isto­cie, nawią­zu­je do teo­rii sys­te­mów: sys­tem (ana­li­zo­wa­ny lub pro­jek­to­wa­ny) skła­da się z współ­pra­cu­ją­cych obiek­tów. Cechą obiek­tów jest ich her­me­ty­za­cja, któ­ra ozna­cza, że obiekt nie udo­stęp­nia (i nie współ­dzie­li) swo­jej wewnętrz­nej struk­tu­ry (imple­ment­cji), ma z oto­cze­niem wyłącz­nie okre­ślo­ne inte­rak­cje: wyko­ny­wa­ne ope­ra­cje. Inny­mi sło­wy obiekt reagu­je w okre­ślo­ny spo­sób na okre­ślo­ne bodź­ce, igno­ru­jąc wszel­kie pozo­sta­łe, a zbiór tych bodź­ców (ope­ra­cji) nazy­wa­my inter­fej­sem obiek­tu. Jedy­nym spo­so­bem pozy­ska­nie infor­ma­cji o obiek­cie jest ?zapy­ta­nie go o to?. 

Generalnie więc:

Paradygmat obiek­to­wy to przy­ję­cie zasa­dy: sys­tem skła­da się ze współ­pra­cu­ją­cych i nie­za­leż­nych obiek­tów, obiek­ty cechu­je okre­ślo­na odpo­wie­dzial­ność, współ­pra­ca obiek­tów pole­ga na wza­jem­nym wywo­ły­wa­niu (call) ope­ra­cji w celu uzy­ska­nia okre­ślo­ne­go efek­tu. Obiekty udo­stęp­nia­ją ope­ra­cje, jest to inter­fejs publicz­ny obiek­tu nazy­wa­ny tak­że jego kon­trak­tem (odpo­wie­dzial­ność). Obiekty ukry­wa­ją przed oto­cze­niem swo­ją wewnętrz­ną budo­wę (her­me­ty­za­cja) a kon­trakt gwa­ran­tu­je, że ta sama ope­ra­cja zawsze da ten sam efekt, nie­za­leż­nie od uży­te­go w danej chwi­li do jej reali­za­cji algo­ryt­mu (meto­dy), co nazy­wa­my poli­mor­fi­zmem. (patrz tak­że ).

Związek dzie­dzi­cze­nia jest sto­so­wa­ny w obiek­to­wych języ­kach pro­gra­mo­wa­nia ale nie jest on ele­men­tem (cechą) para­dyg­ma­tu obiek­to­we­go jako takie­go (został nawet usu­nię­ty z nota­cji UML w 2015 roku patrz UML 2.5). Związek dzie­dzi­cze­nia to spo­sób re-uży­cia kodu w języ­kach zorien­to­wa­nych obiek­to­wo i sta­no­wi sobą łama­nie pod­sta­wo­wej cechy obiek­tów jaką jest nie­za­leż­ność i her­me­ty­za­cja (nie­współ­dzie­le­nie i nie ujaw­nia­nie niczego).

Jeden z naj­czę­ściej publi­ko­wa­nych przy­kła­dów dia­gra­mu klas UML (źr. mate­ria­ły dydaktyczne)

Powyższa kon­struk­cja jest bar­dzo łatwa do imple­men­ta­cji w języ­kach zorien­to­wa­nych obiek­to­wo, jest bar­dzo czę­sto poda­wa­na jako przy­kład, jed­nak łamie pod­sta­wo­we cechy para­dyg­ma­tu obiek­to­we­go: nie­za­leż­ność obiek­tów i her­me­ty­za­cję. Kod repre­zen­to­wa­ny kla­są Figura_Geometryczna jest wspól­ną czę­ścią kon­struk­cji Okrąg i Kwadrat, w efek­cie wszyst­kie trzy kla­sy są z sobą ści­śle powią­za­ne (zależ­ne od sie­bie) co prze­czy zasa­dzie pro­jek­to­wa­nia obiek­to­we­go zwa­nej loose coupling (luź­ne powiązanie).

Kluczową cechą obiek­to­wej archi­tek­tu­ry sys­te­mu jest współ­pra­ca her­me­tycz­nych i luź­no powią­za­nych obiek­tów, więc pod­sta­wo­wym związ­kiem pomię­dzy obiek­ta­mi jest zależ­ność (zwią­zek uży­cia) a nie aso­cja­cja czy kom­po­zy­cja, bo te to związ­ki struk­tu­ral­ne. Wszystkie obiek­ty MUSZĄ mieć ope­ra­cje, bez któ­rych nie ma mowy o jakiej­kol­wiek komu­ni­ka­cji czy­li tak­że współ­pra­cy. Od lat zna­ny jest antyw­zo­rzec obiek­to­wy o nazwie ane­micz­ny model dzie­dzi­ny”. Jest to struk­tu­ra trwa­le (aso­cja­cje) powią­za­nych klas (obiek­tów) pozba­wio­nych ope­ra­cji ?(Fowler, 2003)?. Taki model, jak ten poni­żej, nie jest mode­lem obiektowym: 

(źr.https://en.wikipedia.org/wiki/Domain_model)

Kluczowe wady powyż­sze­go dia­gra­mu to: brak ope­ra­cji i w kon­se­kwen­cji brak związ­ków uży­cia, trwa­łe powią­za­nia oraz dzie­dzi­cze­nie (jego wady opi­sa­no wcze­śniej): te obiek­ty nie komu­ni­ku­ją się w żaden spo­sób. Diagram zorien­to­wa­ny jest na dane. 

Mitem wyrzą­dza­ją­cym chy­ba naj­wię­cej szkód jest teza o mode­lo­wa­niu danych z uży­ciem UML („UML łączy naj­lep­sze cechy: mode­lo­wa­nia danych ERD, mode­lo­wa­nia czyn­no­ści DFD., […]”, mate­ria­ły dydak­tycz­ne: Modelowanie z wyko­rzy­sta­niem UML, Politechnika Poznańska) oraz teza, że pod­sta­wo­wa idea obiek­tu to łącze­nie danych i funk­cji je prze­twa­rza­ją­cych”. Tu war­to wie­dzieć, że jed­nym z pod­sta­wo­wych wzor­ców pro­jek­to­wych i dobrych prak­tyk archi­tek­tu­ry jest sepa­ro­wa­nie two­rze­nia ele­men­tów infor­ma­cji, skła­do­wa­nia infor­ma­cji, i prze­twa­rza­nia infor­ma­cji (odręb­ne kom­po­nen­ty: fabry­ka, repo­zy­to­rium, usłu­ga) ?(Evans, 2015)?. Atrybuty obiek­tu to nie są pola bazy danych a stan obiek­tu to nie aktu­al­na war­tość jego wszyst­kich atrybutów. 

Nie mniej wadli­we są czę­sto publi­ko­wa­ne dia­gra­my przy­pad­ków uży­cia skła­da­ją­ce się z dużej ich licz­by, wie­lu związ­ków inc­lu­de i extend a nie raz i owe­go dzie­dzi­cze­nia, ale ten temat już opi­sa­łem w arty­ku­le Paradygmat obiek­to­wy i Przypadki Użycia .

UML: klasa, klasyfikator, obiekt

Modele obiek­to­we doku­men­tu­je się z uży­ciem nota­cji UML (Unified Modeling Notation?*?). Notacja ta nie powsta­ła do doku­men­to­wa­nia kodu (jak piszą nie­któ­rzy auto­rzy) a do doku­men­to­wa­nia wyni­ków ana­li­zy i pro­jek­to­wa­nia (OOAD, Object Oriented Analysis and Design, Analiza i Projektowanie Zorientowane Obiektowo). Zostało to opi­sa­ne w OMG (Object Management Group???) jako pro­ces MDA (Model Driven Architecture???). Kolejność powsta­wa­nia opro­gra­mo­wa­nia to: ana­li­za i model biz­ne­so­wy, decy­zja o zakre­sie pro­jek­tu czy­li wyma­ga­nia, model logi­ki sys­te­mu (Platform Independent Model) czy­li opis roz­wią­za­nia i dopie­ro pro­jekt imple­men­ta­cji (Platform Specific Model). Wszystkie te mode­le (jeże­li doty­czą tego same­go sys­te­mu) muszą korzy­stać z tej samej prze­strze­ni poję­cio­wej (jed­no­li­ty słow­nik pojęć). Pokazano to poniżej:

Model pro­jek­tu obiek­to­we­go, strzał­ki do związ­ki zależ­no­ści i wska­zu­ją na źró­dło­we informacje. 

Niektórzy auto­rzy jed­nak piszą:

Proces pro­jek­to­wa­nia sys­te­mu infor­ma­tycz­ne­go obej­mu­je nastę­pu­ją­ce głów­ne eta­py:
? pro­gra­mo­wa­nie (two­rze­nie kodu pro­gra­mu w wybra­nym języ­ku pro­gra­mo­wa­nia),
? opra­co­wy­wa­nie doku­men­ta­cji (opi­sy­wa­nie wszyst­kich ele­men­tów skła­do­wych sys­te­mu, zależ­no­ści zacho­dzą­cych mię­dzy nimi, a tak­że opra­co­wy­wa­nie szcze­gó­ło­wej instruk­cji użyt­kow­ni­ka),
? wdra­ża­nie sys­te­mu do pra­cy (jest to pro­ces odpo­wie­dzial­ny, zło­żo­ny i dłu­go­trwa­ły obej­mu­ją­cy: insta­la­cję sys­te­mu w miej­scu prze­zna­cze­nia, uru­cha­mia­nie, testo­wa­nie oraz szko­le­nie per­so­ne­lu obsłu­gu­ją­ce­go system).

Projektowanie sys­te­mu infor­ma­tycz­ne­go wyma­ga okre­śle­nia:
? mode­lu danych (Data Model),
? inter­fej­su użyt­kow­ni­ka (User Interface, Front-End).
Model danych okre­śla zbiór ogól­nych zasad posłu­gi­wa­nia się danymi.

?(Gryglewicz-Kacerka & Duraj, 2013)?

Autorzy tu cał­ko­wi­cie pomi­nę­li etap ana­li­zy i pro­jek­to­wa­nia co prze­czy tytu­ło­wi tej publi­ka­cji: Projektowanie obiek­to­we sys­te­mów infor­ma­tycz­nych. Padają tu tak­że sło­wa o mode­lu danych, od któ­rych para­dyg­mat obiek­to­wy cał­ko­wi­cie abstrahuje. 

Notacja UML ope­ru­je trze­ma klu­czo­wy­mi poję­cia­mi: kla­sa (nazwa), kla­sy­fi­ka­tor (zna­cze­nie, defi­ni­cja obiek­tów), obiek­ty (desy­gna­ty, mają­ce toż­sa­mość egzem­pla­rze). Pojęcia te są opar­te na tak zwa­nym trój­ką­cie semiotycznym:

trój­kąt semio­tycz­ny (źr. Logika ogól­na, Grzegorz Malinowski, PWN 2010).

Trójkąt semio­tycz­ny to kon­tek­sto­we powią­za­nie pojęć: znak (sło­wo), defi­ni­cja, przed­miot. Określony znak (nazwa) wska­zu­je (deno­tu­je) przed­miot (uży­wa­my nazwy/znaku do wskazania/nazwania przed­mio­tu). Wszystkie przed­mio­ty zgod­ne z okre­ślo­nym opi­sem (desy­gna­ty danej nazwy) moż­na nazwać (ozna­czyć) tym sło­wem (nazwa). Np. każ­de stwo­rze­nie, któ­re szcze­ka” (znaczenie/opis) moż­na nazwać sło­wem pies” i są to te wszyst­kie psy” (kon­kret­ne zna­ne nam psy czy­li desy­gna­ty sło­wa pies). W nota­cji UML kla­sa” to poję­cie: nazwa”, kla­sy­fi­ka­tor do defi­ni­cja, a obiek­ty to desy­gna­ty (instan­cje kla­sy­fi­ka­to­ra, tu UWAGA: z uwa­gi na nie­jed­no­znacz­ność pew­nych zapi­sów w UML, instan­cje – obiek­ty – ma kla­sy­fi­ka­tor a nie kla­sa, kla­sa to tyl­ko nazwa zbioru).

W mode­lach poję­cio­wych uży­wa­ne są związ­ki seman­tycz­ne (aso­cja­cja) i defi­ni­cyj­ne (gene­ra­li­za­cja). Związek gene­ra­li­za­cji jest klu­czo­wym narzę­dziem two­rze­nia defi­ni­cji spra­woz­daw­czych (patrz przy­pis na stro­nie Słownik pojęć). W nota­cji UML sto­so­wa­ny jest tak­że zwią­zek kom­po­zy­cji (zwią­zek struk­tu­ral­ny całość – część), słu­ży do doku­men­to­wa­nia tak zwa­nych kla­sy­fi­ka­to­rów zło­żo­nych zwa­nych tak­że agregatami.

Tak więc pro­jekt obiek­to­wy to udo­ku­men­to­wa­ny zestaw współ­pra­cu­ją­cych w okre­ślo­nym celu obiek­tów (kom­po­nen­tów). Wymaganym i klu­czo­wym ele­men­tem pro­jek­tu jest słow­nik pojęć, czy­li zna­cze­nia i struk­tu­ra nazw uży­tych w tym pro­jek­cie (nazwy klas, atry­bu­tów i ich war­to­ści, ope­ra­cji, para­me­trów itp.). Jest to tak zwa­na prze­strzeń poję­cio­wa sys­te­mu (słow­nik, name­spa­ce) przed­sta­wia­na jako model poję­cio­wy (tak­so­no­mie). Jeżeli dany atry­but przyj­mu­je skoń­czo­ną licz­bę war­to­ści jako skut­ków okre­ślo­nych fak­tów, doku­men­tu­je­my to dia­gra­mem maszy­ny sta­no­wej. Kolejnym ele­men­tem pro­jek­tu obiek­to­we­go są sce­na­riu­sze (mode­le) opi­su­ją­ce współ­pra­cę (dyna­mi­kę) ele­men­tów sys­te­mu (obiek­tów), któ­rej efek­tem są ocze­ki­wa­ne rezul­ta­ty (przy­pad­ki uży­cia oraz ich sce­na­riu­sze, jako dia­gra­my sekwen­cji UML). 

Model obiektowy systemu

Należało by raczej powie­dzieć, zorien­to­wa­ny obiek­to­wo lub zgod­ny z obiek­to­wym para­dyg­ma­tem. Oznacza to, że struk­tu­ra sys­te­mu (jego model) skła­da się z samo­dziel­nych obiek­tów, któ­re razem jako sys­tem, reali­zu­ją okre­ślo­ne zada­nia. System jako taki może być tak­że obiek­tem, mogą­cym współ­pra­co­wać z innym sys­te­mem. Innymi sło­wy każ­dy obiekt sam z sie­bie jest pro­stym (ato­mo­wym, ele­men­tar­nym) systemem. 

Omówię tu przy­kład pro­jek­tu pro­stej apli­ka­cji. Projekt zosta­nie udo­ku­men­to­wa­ny z uży­ciem nota­cji UML. Pominę etap two­rze­nia mode­li CIM (pro­ce­sy biznesowe). 

Zakres pro­jek­tu to usłu­ga reje­stra­cji wizyt u wete­ry­na­rza oraz usłu­ga pre­zen­to­wa­nia wete­ry­na­rzom ich pod­sta­wo­wych danych a tak­że ter­mi­nów wizyt im przy­po­rząd­ko­wa­nych. Zakres udo­ku­men­to­wa­no z uży­ciem dia­gra­mu przy­pad­ków uży­cia nota­cji UML.

Z apli­ka­cji będą korzy­sta­li wete­ry­na­rze. Aplikacja świad­czy dwie usłu­gi: zarzą­dza­nie wizy­ta­mi oraz pro­fi­le wete­ry­na­rzy. Można zapi­sać infor­ma­cje o pla­no­wa­nych wizy­tach, kar­ta wizy­ty będzie zawie­ra­ła tak­że pod­sta­wo­we dane przy­po­rząd­ko­wa­ne­go wete­ry­na­rza, pobra­ne z pro­fi­lu tego wete­ry­na­rza. Każdy wete­ry­narz będzie pro­wa­dził swój pro­fil: poda­jąc klu­czo­we infor­ma­cje o sobie np. imię, nazwi­sko, spe­cja­li­za­cja, kon­takt do sie­bie. Będzie tak­że widział swój kalen­darz wizyt. Pełny pro­jekt zawie­rał­by deta­licz­ne sza­blo­ny tych for­mu­la­rzy. W ramach wyma­gań spi­sa­no regu­ły biz­ne­so­we czy­li logi­kę biz­ne­so­wą systemu:

  • Wizyty nie mogą być uma­wia­ne w dni wol­ne od pracy
  • Weterynarz może mieć tyl­ko jed­ną zapla­no­wa­na wizy­tę w danym terminie
  • Profil okre­ślo­ne­go wete­ry­na­rza może edy­to­wać wyłącz­nie on sam

(regu­ły biz­ne­so­we i słow­nik pojęć, patrz spe­cy­fi­ka­cja SBVR: Semantics Of Business Vocabulary and Rules?§?). Reguł biz­ne­so­wych nie doku­men­tu­je­my w UML bo nie do tego służy.

Do kon­tro­li pola Data wizy­ty, zapla­no­wa­no spraw­dza­nie danych o dniach wol­nych od pra­cy w zewnętrz­nym sys­te­mie, udo­stęp­nia­ją­cym dane o dniach wol­nych od pra­cy (na dia­gra­mie aktor po pra­wej stro­nie, taka sytu­acja to nie przy­pa­dek uży­cia! a zwią­zek zależ­no­ści od aktora).

Kluczowa część pro­jek­tu to ana­li­za poję­cio­wa i opra­co­wa­nie mode­lu poję­cio­we­go czy­li słow­ni­ka pojęć, ich tak­so­no­mii i definicji.

Model poję­cio­wy (dia­gram klas UML lub dia­gram fak­tów SBVR)

Słownik pojęć sta­no­wi pod­sta­wo­we źró­dło nazw wszyst­kich ele­men­tów mode­lu dzie­dzi­ny sys­te­mu. Jak widać słow­nik to tyl­ko kla­sy (same nazwy) połą­czo­ne aso­cja­cja­mi (związ­ki seman­tycz­ne) i związ­ka­mi gene­ra­li­za­cji (łączą poję­cia ogól­niej­sze i ich typy). Pojęcia ogól­ne są czę­sto kan­dy­da­ta­mi na nazwy kla­sy­fi­ka­to­rów (kom­po­nen­tów sys­te­mu) i ich atry­bu­tów, typy pojęć (liście tak­so­no­mii) są kan­dy­da­ta­mi na nazwy war­to­ści atry­bu­tów (ich słow­ni­ki). To nie jest ani model danych ani model archi­tek­tu­ry tego systemu!

Zaprojektowano kom­po­nent Model (model dzie­dzi­no­wy) sys­te­mu (patrz opis wzor­ca MVC: Model, View, Controller), jego archi­tek­tu­ra jest zgod­na z opi­sa­nym obiek­to­wym para­dyg­ma­tem i ma cechy dobrej archi­tek­tu­ry (zasa­dy SOLID). Dla uprosz­cze­nia pomi­ną­łem na dia­gra­mie imple­men­ta­cję reje­stru weterynarzy). 

Architektura kom­po­nen­tu Model Dziedziny sys­te­mu (dia­gram klas UML). 

Przedstawiony przy­kład nie ma poważ­nej wady archi­tek­to­nicz­nej (wręcz pla­gi), pole­ga­ją­cej na wycią­ga­niu” zawar­to­ści atry­bu­tów obiek­tu serią pole­ceń Get/Set dla każ­de­go atry­bu­tu. Powoduje to bar­dzo sil­nie uza­leż­nie­nie obiek­tu pobie­ra­ją­ce­go dane od obiek­tu będą­ce­go ich źró­dłem (wadę tę opi­sał dokład­nie Foler: ?(Fowler, 2013)?). Operacje zapisz i przy­wo­łaj powo­du­ją zapi­sa­nie i przy­wo­ła­nie całej kar­ty wizy­ty (wszyst­kich jej danych).

Jak widać mamy peł­ną her­me­ty­za­cję kom­po­nen­tów i luź­ne powią­za­nia mię­dzy nimi (tyl­ko związ­ki uży­cia). Oddzielono logi­kę biz­ne­so­wą od repo­zy­to­rium. Nie ma tu żad­ne­go dzie­dzi­cze­nia (nie ma go w UML od 2015 roku). Każdy kom­po­nent (kla­sy­fi­ka­tor) ma ope­ra­cje. Pola gatu­nek i wiel­kość mają zde­fi­nio­wa­ne słow­ni­ki (enu­me­ra­tor). Nazwy te są zde­fi­nio­wa­ne w odręb­nym mode­lu poję­cio­wym (bo do tego on mię­dzy inny­mi słu­ży). Model powyż­szy jest jed­nak nadal dość tra­dy­cyj­ny” (prze­sta­rza­ły) bo atry­bu­ty repre­zen­tu­ją poszcze­gól­ne pola for­mu­la­rzy (od cze­go się odchodzi!). 

Wadą tego prze­sta­rza­łe­go” pomy­słu jest to, że każ­da mody­fi­ka­cja for­mu­la­rzy będzie wyma­ga­ła refak­to­rin­gu tego sys­te­mu (atry­bu­ty kla­sy­fi­ka­to­rów i meto­dy). Dlatego poka­za­łem alter­na­tyw­ne nowo­cze­śniej­sze podej­ście (różo­we tło), w któ­rym kla­sy­fi­ka­tor Wizyty2 ma iden­tycz­ny inter­fejs, nadal odpo­wia­da za prze­cho­wy­wa­nie infor­ma­cji o wizy­tach, ale tu są one – cała kar­ta wizy­ty – prze­cho­wy­wa­ne jako treść jed­ne­go atry­bu­tu: tu w posta­ci tek­stu XML. Dzięki temu zmia­na struk­tu­ry for­mu­la­rza nie będzie wyma­ga­ła refak­to­ry­za­cji, a jedy­nie wymia­ny sza­blo­nów XML i XSD. Polimorfizm i her­me­ty­za­cja pozwo­li na wymia­nę imple­men­ta­cji z Wizyty na Wizyty2 bez kon­se­kwen­cji dla resz­ty sys­te­mu (kla­sa Wizyty2 ma iden­tycz­ny interfejs). 

Aktualne war­to­ści atry­bu­tów nie są sta­nem obiek­tu” (kolej­ny mit). Obiekt Wizyty to repo­zy­to­rium kart wizyt, sta­nem (sta­tu­sem) danej wizy­ty jest jed­na infor­ma­cja (war­tość jed­ne­go atry­bu­tu). Wizyta jako taka ma sta­tu­sy, zmie­nia­ją się one automatycznie.

Zmiany war­to­ści atry­bu­tu status_wizyty (maszy­na sta­nów UML)

Aby udo­ku­men­to­wać przy­pa­dek uży­cia (jego sce­na­riusz) oraz jed­no­cze­śnie prze­te­sto­wać tę archi­tek­tu­rę (udo­ku­men­to­wać dyna­mi­kę sys­te­mu) two­rzy­my dia­gram sekwencji.

Scenariusz reali­za­cji usłu­gi Wizyta (dia­gram sekwen­cji UML). 

Myślę, że nie wyma­ga on komen­ta­rza. Warto wie­dzieć, że uży­wa­nie do tego celu dia­gra­mów aktyw­no­ści jest mało efek­tyw­ne, a w UML 2.5 dia­gra­my aktyw­no­ści są zare­zer­wo­wa­ne już wyłącz­nie do mode­lo­wa­nia kodu programu. 

Cały pro­jekt ma nastę­pu­ją­cą strukturę:

Pełna doku­men­ta­cja zawierałaby: 

  • model poję­cio­wy (jeden lub kil­ka dia­gra­mów klas),
  • jeden dia­gram przy­pad­ków użycia,
  • jeden lub wię­cej (alter­na­tyw­ne) sce­na­riu­szy dla każ­de­go przy­pad­ku uży­cia (dia­gra­my sekwencji),
  • jeden model dzie­dzi­ny sys­te­mu czy­li model archi­tek­tu­ry kom­po­nen­tu Model dla wzor­ca MVC (dia­gram klas, duży sys­tem to dia­gram kom­po­nen­tów, każ­dy z osob­nym mode­lem swo­jej wewnętrz­nej architektury),
    • dla każ­de­go obiek­tu w mode­lu dzie­dzi­ny, mają­ce­go sta­tu­sy, model maszy­ny sta­no­wej opi­su­ją­cy war­to­ści atry­bu­tu repre­zen­tu­ją­ce­go stan obiek­tu (może ich być wię­cej niż jeden).
    • struk­tu­ry tak zwa­nych obiek­tów trans­fe­ro­wych czy­li struk­tu­ry danych wymie­nia­ne pomię­dzy obiek­ta­mi (agre­ga­ty, naj­czę­ściej XML).

Do tego bogat­szy opis kon­tek­stu, makie­ty for­mu­la­rzy, peł­ną spe­cy­fi­ka­cję reguł biznesowych

Model taki nada­je się (pomi­ja­jąc potrze­bę zapro­jek­to­wa­nia gra­fi­ki i śro­do­wi­ska wyko­naw­cze­go) do imple­men­ta­cji wprost, sta­no­wi więc bar­dzo pre­cy­zyj­ne wymaganie

Korzyści

Najczęściej jako korzy­ści ze sto­so­wa­nia metod obiek­to­wych wska­zy­wa­ne jest re-uży­cie kodu, łatwe korzy­sta­nie z biblio­tek, podział pra­cy na zespo­ły. A tak na praw­dę klu­czo­wą korzy­ścią są skut­ki her­me­ty­za­cji i poli­mor­fi­zmu: sys­tem podzie­lo­ny na cał­ko­wi­cie nie­za­leż­ne (her­me­ty­za­cja) kom­po­nen­ty i cał­ko­wi­ta nie­za­leż­ność od ich wewnętrz­nej budo­wy (poli­mor­fizm) powo­du­je, że roz­wój i wpro­wa­dza­nie zmian dla sys­te­mu jest szyb­kie, łatwe i nie­mal­że pozba­wio­ne ryzy­ka. To jak rower, jeże­li nie jest spa­wa­ny a zło­żo­ny ze stan­dar­do­wych ele­men­tów łączo­nych na unor­mo­wa­ne zaci­ski i śrub­ki (stan­da­ry­za­cja inter­fej­sów), mody­fi­ku­je­my go w dowol­nym momen­cie, małym nakła­dem pra­cy, w mia­rę zmian naszych potrzeb i nawy­ków. W 2013 pisałem:

Zasa­da ?nigdy nie mów nigdy? ozna­cza, że żaden pro­gram nie jest skoń­czo­ny. Inny­mi sło­wy powin­no być moż­li­we roz­sze­rza­nie jego funk­cjo­nal­no­ści bez prze­bu­do­wy. (czy­taj wię­cej: Plansza do gry w sza­chy czy­li ana­li­za i pro­jek­to­wa­nie | | Jarosław Żeliński IT-Consulting )

Opisałem tam obiek­to­wy model gry w sza­chy speł­nia­ją­cy powyż­szą zasadę. 

Na zakończenie

Mam nadzie­ję, że ten arty­kuł wyja­śni wie­le wąt­pli­wo­ści. Wiele róż­nych przy­kła­do­wych dia­gra­mów moż­na zna­leźć w lite­ra­tu­rze i w sie­ci inter­net. Wiele z nich, mimo że są zgod­ne z nota­cją UML, to nie mode­le obiek­to­we a struk­tu­ral­ne. Niestety wie­le zawie­ra tak­że błę­dy nota­cyj­ne. Dodam tak­że, co bar­dzo waż­ne: spe­cy­fi­ka­cja UML to nie jest pod­ręcz­nik ana­li­zy i mode­lo­wa­nia a tyl­ko spe­cy­fi­ka­cja nota­cji. Zawiera popraw­ne kon­struk­cje UML ale nie koniecz­nie są to zawsze dobre wzor­ce architektury. 

Warto wie­dzieć, że to co nazy­wa­my para­dyg­ma­tem obiek­to­wym to aksjo­mat a nie dogmat. Dlatego nota­cja UML nie narzu­ca nicze­go poza zasa­da­mi jej sto­so­wa­nia, jed­nak jeże­li już pisze­my, że nasz pro­jekt jest obiek­to­wy, to musi­my (wypa­da­ło by) uznać aksjo­mat: sys­tem to współ­pra­cu­ją­ce samo­dziel­ne obiek­ty (a więc uznać kon­se­kwent­nie her­me­ty­za­cję i poli­mor­fizm). Dobre prak­ty­ki archi­tek­tu­ry to już kon­se­kwen­cje doty­czą­ce cyklu życia sys­te­mu, w szcze­gól­no­ści kosz­tu jego utrzy­ma­nia i rozwoju. 

Ciekawostką jest tak­że to, że o opi­sa­nych tu zale­tach archi­tek­tu­ry obiek­to­wej pisa­no już w 1994 roku (i póź­niej też nie raz). Wiedza, któ­rą tu pre­zen­tu­ję ma 25 lat:

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

Na zakoń­cze­nie powiedz­my sobie wprost: nie ma cze­goś takie­go jak obiek­to­wy model danych”!. 

Dane to infor­ma­cje (zna­ki), któ­re mogą zostać zor­ga­ni­zo­wa­ne w okre­ślo­ne nazwa­ne struk­tu­ry, one same z sie­bie nic nie robią. Obiekt to coś co ma okre­ślo­ne zacho­wa­nie”, więc okre­śle­nie obiek­to­wy model danych” jest pozba­wio­ne sen­su… Jednym z naj­bar­dziej zna­nych antyw­zor­ców obiek­to­wych jest tak zwa­ny «ane­micz­nym model dzie­dzi­ny». Jest to model któ­ry skła­da się z klas mają­cych atry­bu­ty, ale nie­za­wie­ra­ją­cych żad­nych metod, co powo­du­je, że nie jest obiektowy.

Jak zawsze zachę­cam do zada­wa­nia pytań…


  1. ?*?
    https://​www​.uml​.org
  2. ???
    https://​www​.omg​.org
  3. ???
    https://​www​.omg​.org/​m​da/
  4. ?§?
    https://​www​.omg​.org/​s​p​e​c​/​S​B​V​R​/​A​b​o​u​t​-​S​B​VR/

Źródła

  1. Evans, E. (2015). Domain-Driven Design. Zapanuj nad zło­żo­nym sys­te­mem infor­ma­tycz­nym. Gliwice: HELION.
  2. Fowler, M. (2003). AnemicDomainModel. Retrieved 2019, from martinFowler​.com websi­te: https://​mar​tin​fow​ler​.com/​b​l​i​k​i​/​A​n​e​m​i​c​D​o​m​a​i​n​M​o​d​e​l​.​h​tml
  3. Fowler, M. (2013). TellDontAsk. Retrieved 2019, from martinFowler​.com websi­te: https://​mar​tin​fow​ler​.com/​b​l​i​k​i​/​T​e​l​l​D​o​n​t​A​s​k​.​h​tml
  4. Gryglewicz-Kacerka, W., & Duraj, A. (2013). Projektowanie obiek­to­we sys­te­mów infor­ma­tycz­nych. Włocławek: Państwowa Wyższa Szkoła Zawodowa we Włocławku.
Shishkov, B. (2020) Designing enter­pri­se infor­ma­tion sys­tems mer­ging enter­pri­se mode­ling and softwa­re spe­ci­fi­ca­tion.

Inne artykuły na podobny temat

image_print(wydruk PL)

Komentarze

  1. Jarek Żeliński 12 października 2019 at 10:26

    Na pew­nym forum poja­wi­ły sie pyta­nia do tego tek­stu, jed­nak forum jest zamknię­te więc moje komen­ta­rze publi­ku­je tu:

    Kluczowa zasa­da: model dzie­dzi­ny to nic inne­go jak kom­po­nen­ty sys­te­mu, sko­ro her­me­ty­zo­wa­ne to zna­czy, że jako kom­po­nent mogą zostać w dowol­nym momen­cie usu­nię­te lub zastą­pio­ne czymś innym (poli­mor­fizm) a tak­że zmie­nio­ne (her­me­ty­za­cja). W konsekwencji:
    – w mode­lu archi­tek­tu­ry logi­ki sys­te­mu z zasa­dy nie ma klas abs­trak­cyj­nych (cze­goś nad nimi”) bo uza­leż­nia­ją od sie­bie potom­ne komponenty
    – zaspo­ka­ja­nie potrzeb biz­ne­so­wych użyt­kow­ni­ków to cecha her­me­tycz­ne­go kom­po­nen­tu (patrz wyżej) więc imple­men­ta­cja nowej cechy powin­na się zamknąć w jed­nym wybra­nym komponencie,
    – jak słusz­nie zauwa­żo­no: nad­rzęd­ne kla­sy abs­trak­cyj­ne nisz­czą her­me­ty­za­cję (nie­za­leż­ność kom­po­nen­tów) więc w Modelu nie nale­ży ich używać,
    – doda­nie kolej­ne­go typu (np. zwie­rzę Tygrys) to nic inne­go jak roz­bu­do­wa słow­ni­ka, jeże­li to może być czę­ste to nie będzie to (słow­nik) enu­me­ra­tor o kolek­cja (czy­li coś co użyt­kow­nik może rozbudowywać),
    – bio­rą­cą pod uwa­gę fakt, że dzie­dzi­no­wy słow­nik jest jeden i dzie­dzi­na też (boun­ded con­text) mamy tak­że jeden współ­dzie­lo­ny wali­da­tor, więc doda­nie poję­cia słow­ni­ko­we­go odby­wa sie poza struk­tu­rą doku­men­tów XML (w XSD), w jed­nym miej­scu i nie ma pra­wa wpły­wać na histo­rycz­ne dokumenty,
    – kla­sa pojazd (przy­kład poda­ny przez foru­mo­wi­cza) jest zawsze nie­lo­gicz­na, logicz­na jest kla­sa dane pojaz­du”, gdzie typy to nie dzie­dzi­cze­nie a słow­nik war­to­ści atry­bu­tu Typ pojaz­du”, cechy mecha­nicz­ne kon­struk­cyj­ne to jeden agre­gat (kolor, waga sil­nik itp.) numer reje­stra­cyj­ny nie jest cechą kon­struk­cyj­na pojaz­dy a cechą dowo­du reje­stra­cyj­ne­go (i umiesz­czo­ną w posta­ci wymie­nia­nej tabli­cy na pojeździe),
    – daty reje­stra­cji itp. to nie cechy pojaz­dy a treść dowo­du reje­stra­cyj­ne­go, jeże­li dla użyt­kow­ni­ka istot­ne są inne eks­tra cechy np. Forda Mustanga, ale cechy te nie są prze­twa­rza­ne auto­ma­tycz­nie, to sta­no­wią one treść opi­su pro­zą” np. jako ostat­nie pole XML inne notatki „..
    – poziom modu­lar­no­ści zale­ży wyłącz­nie od wiel­ko­ści apli­ka­cji, nie zmie­nia to fak­tu że nie powin­ny one nicze­go współ­dzie­lić (czy­li dzie­dzi­cze­nie odpa­da, zwra­cam uwa­gę że znik­nę­ło z UML i nie jest to przypadek)

  2. Harnaś 16 października 2019 at 13:49

    ? doda­nie kolej­ne­go typu (np. zwie­rzę Tygrys) to nic inne­go jak roz­bu­do­wa słow­ni­ka, jeże­li to może być czę­ste to nie będzie to (słow­nik) enu­me­ra­tor o kolek­cja (czy­li coś co użyt­kow­nik może rozbudowywać)”

    Nie enu­me­ra­tor, czy­li zwy­kła klasa?

    • Jarosław Żeliński 16 października 2019 at 18:35

      Nie tyle zwy­kła” kla­sa, co zarzą­dza­na kolek­cja. Enumerator to zamknię­ty typ, a nie nale­ży ich zmie­niać po imple­men­ta­cji. Dlatego dni tygo­dnia to będzie raczej enu­me­ra­tor, ale już nazwy woje­wództw powin­ny być mody­fi­ko­wal­ne. Tu słow­nik zwie­rząt, na któ­rych zna się wete­ry­narz, powi­nien być mody­fi­ko­wal­ny przez użytkownika.

    • Harnaś 17 października 2019 at 10:25

      Jak zarzą­dza­ną kolek­cję” poka­zać na dia­gra­mie klas?

    • Jarosław Żeliński 17 października 2019 at 15:00

      Jako pro­stą kom­po­zy­cję: korzeń to kla­sa sta­no­wią­ca narzę­dzie jej udo­stęp­nia­nia i zarzą­dza­nia nią, ma ope­ra­cje: dodaj ele­ment, usuń ele­ment, lista elementów.

    • Harnaś 18 października 2019 at 12:38

      Dziękuję za wyczer­pu­ją­cą odpowiedź.
      Ja myśla­łem o tym, żeby w mode­lu poję­cio­wym poka­zać kla­sę Województwa o ste­reo­ty­pie <>, ale patrząc na ten przy­kład: widzę, że wcho­dził­bym już w architekturę.

    • Jarosław Żeliński 18 października 2019 at 12:59

      Dlatego nale­ży bar­dzo się pil­no­wać i nie mylić mode­li poję­cio­wych dzie­dzi­ny sys­te­mu z mode­la­mi archi­tek­tu­ry sys­te­mu. Są to odręb­ne mode­le w UML (model poję­cio­wy zamy­ka­my jako Namespace).

  3. Pytacz 28 października 2021 at 23:09

    Witam. Jaka rolę peł­ni kom­po­nent Zarządzanie wizy­ta­mi” na dia­gra­mie dziedziny?

    • Jarosław Żeliński 29 października 2021 at 01:11

      (to jest Model Dziedziny 🙂 ) Obsługuje dia­log aktor-sys­tem (kla­sa typu boun­da­ry wzor­ca BCE), reali­zu­je sce­na­riu­sze tego przy­pad­ku uży­cia (pierw­szy ele­ment kaska­dy ele­men­tów wzor­ca Łańcuch odpo­wie­dzial­no­ści, opi­su­ją­ce­go mię­dzy inny­mi pro­jek­to­wa­nie reali­za­cji mikro­usług jako imple­men­ta­cji usług aplikacji).

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.