-
nowość
Modelowanie i implementacja systemów informatycznych 2.0 - ebook
Modelowanie i implementacja systemów informatycznych 2.0 - ebook
Książka poświęcona jest problematyce wytwarzania oprogramowania z wykorzystaniem podejścia obiektowego i notacji UML. Szczególny nacisk położono na przełożenie teoretycznych pojęć obiektowości na praktyczne odpowiedniki implementacyjne. Na konkretnym, biznesowym przykładzie (biblioteka) opisano poszczególne fazy wytwarzania oprogramowania. Wyjaśnienia zilustrowano wieloma diagramami UML, m. in. klas, przypadków użycia, aktywności oraz stanów. Opisy poparto praktyczną implementacją wielu omawianych konstrukcji (ekstensja, asocjacje, ograniczenia, dziedziczenia), często w kilku wariantach. Jako ilustrację możliwości frameworku Spring dla język Java (Data REST, kontrolery Spring, MVC z Thymeleaf), stworzono fragmenty systemu nawiązującego do ww. wymagań użytkownika. Pokazano również jak w praktyce można zrealizować testy integracyjne oraz E2E. Niniejsza publikacja to nowa wersja książki z roku 2008. Została gruntowanie przebudowana i uzupełniona o całkiem nowe elementy.
Ta publikacja spełnia wymagania dostępności zgodnie z dyrektywą EAA.
| Kategoria: | Programowanie |
| Zabezpieczenie: |
Watermark
|
| ISBN: | 9788397644205 |
| Rozmiar pliku: | 12 MB |
FRAGMENT KSIĄŻKI
Długo się zastanawiałem, czy i w jakiej formie tworzyć nową wersję oryginalnego wydania tej książki z roku 2008. Od tego czasu minęło sporo lat, wiele rzeczy się zmieniło, włączając w to rynek książek i skłonność do ich czytania. Zachęcające były pytania potencjalnych czytelników o nową wersję i zgłaszane problemy z dostępnością tej oryginalnej. Rozważałem różne scenariusze, począwszy od napisania wszystkiego od nowa, poprzez modyfikacje istniejącej wersji, a kończąc na wariancie w którym w ogóle nic nie piszę.
Ostatecznie założyłem optymistycznie, że znajdą się jacyś zainteresowani i zaczynam prace. Uznałem, że większość zasadniczych pomysłów z oryginalnej książki wytrzymała próbę czasu i nie ma potrzeby ich wymyślać całkiem od nowa. Oczywiście trzeba było je zaktualizować - choćby o nowsze rozwiązanie programistyczne. W efekcie wyszło całkiem sporo zmian, które sprawiają, że rezultat moich prac jest bardziej zbliżony do nowej publikacji niż tylko kolejnego wydania.
Zmieniłem też tematykę wymagań użytkownika, wokół których jest budowana duża część niniejszej książki (analiza, projektowanie, implementacja). Oryginalnie była to wypożyczalnia wideo, o której niektórzy z potencjalnych czytelników może nigdy nie słyszeli. Zamiast tego mamy również wypożyczalnię, ale książek, czyli bibliotekę. Nie była to tylko prosta zamiana nazw, ponieważ w trakcie prac okazało się, że pewne koncepcje nie mają bezpośrednich odpowiedników.
Oprócz aktualizacji wszystkich diagramów, kodów programów, dodałem również całkiem nowe rozdziały/sekcje, których w ogóle nie było pierwotnie, m.in.:
- implementacja różnych rodzajów aplikacji we frameworku Spring (Data REST, kontrolery Spring, MVC z Thymeleaf),
- testy integracyjne we frameworku Spring,
- testy E2E we frameworku Spring,
- konserwacja oprogramowania.
Sporych aktualizacji doczekał się też rozdział o maperze obiektowo-relacyjnym Hibernate.
O skali zmian może też świadczyć fakt, iż niniejsza edycja książki ma ponad 200 stron więcej niż ta z roku 2008.
Znacząco zaktualizowana i rozbudowana została też bibliografia - teraz ma ponad 100 pozycji. Starałem się znaleźć nowe, interesujące publikacje dotyczące omawianych zagadnień. W niektórych przypadkach (szczególnie tych bardziej teoretycznych jak, np. modelowanie UML, czy dobre praktyki programistyczne) okazało się, że nadal popularne są wydania książek sprzed wielu lat. Z tego powodu niektóre z nich pozostawiłem. Być może są aż tak dobre i/lub w teorii zmiany następują zdecydowanie wolniej, a szybsze są w konkretnych technologiach.
Zastanawiałem się również jak rozwiązać kwestię zwracania się do czytelników oraz feminatywów, np. w nazwach zawodów. Ostatecznie uznałem, że pisanie za każdym razem "programista/programistka", "analityk/analityczka" będzie utrudniało czytanie i z tego zrezygnowałem. Mam nadzieję, że nikt nie poczuje się urażony.
Zmienił się również podział na rozdziały, sekcje itp. Nie zawsze jest idealnym odzwierciedleniem znaczenia poszczególnych koncepcji, ale zbyt dokładne trzymanie się takich reguł prowadziło do zbyt wielu poziomów zagnieżdżeń. Czasami granice są też dość płynne. W efekcie, np. model relacyjny jest poza projektowaniem.
Zastosowałem też pewnie zmiany natury edytorskiej w postaci tzw. uwag. Opisują one różne zagadnienia, które mogą być istotne dla wszystkich zainteresowanych wytwarzaniem systemów informatycznych.
Na koniec tego wprowadzenia, chciałbym prosić o przysyłanie znalezionych błędów (w tym literówek), uwag, komentarzy, pomysłów, sugestii na adres: [email protected]_. Postaram się odpowiedzieć na każdego maila i odnieść się do każdej z uwag, a pomysły w miarę możliwości zrealizować w aktualizacjach do niniejszego wydania.WPROWADZENIE (Z PIERWSZEGO WYDANIA)
_Poniżej znajduje się wprowadzenie z pierwotnej wersji książki z roku 2008. Jako, że w dużej części jest aktualne, to zdecydowałem się je zostawić._
Ponad dziesięć lat temu przeczytałem książkę o programowaniu, która mnie urzekła: „Symfonia C++” napisana przez Jerzego Grębosza . Do dzisiaj nie spotkałem lepiej napisanej książki dotyczącej języków programowania. Niektórzy mogą uważać, że pisanie o takich poważnych i skomplikowanych sprawach jak języki programowania wymaga bardzo naukowego stylu. Pan Grębosz zastosował styl „przyjacielski” - jak sam to określił: „bezpośredni, wręcz kolokwialny”. Moim celem jest stworzenie książki podobnej w stylu, ale traktującej o całym procesie wytwarzania oprogramowania, ze szczególnym uwzględnieniem pojęć występujących w obiektowości i ich przełożenia na praktyczną implementację. Czy i w jakim stopniu mi się to udało oceną Czytelnicy.
Książka ta powstała na podstawie mojego doświadczenia nabytego w czasie prowadzenia wykładów, ćwiczeń oraz przy okazji prac w różnego rodzaju projektach, począwszy od badawczych, aż do typowo komercyjnych. Na co dzień pracuję w Polsko-Japońskiej Wyższej Szkole Technik Komputerowych jako adiunkt, więc mam też spore doświadczenie wynikające z prowadzenia zajęć ze studentami. Dzięki temu będę w stanie omówić też typowe błędy popełniane przy tworzeniu oprogramowania.
Odbiorcami tej publikacji mogą być wszyscy zainteresowani wytwarzaniem oprogramowania, obiektowością, programowaniem czy modelowaniem pojęciowym, np. programiści, analitycy czy studenci przedmiotów związanych z programowaniem, inżynierią oprogramowania, bazami danych itp. Zakładam, że Czytelnik ma już jakąś wiedzę na temat programowania oraz modelowania, ale wszędzie, gdzie to tylko możliwe, staram się przedstawiać obszerne wyjaśnienia. Aby oszczędzić Czytelnikowi przewracania kartek oraz ułatwić zrozumienie omawianych zagadnień, w niektórych miejscach powielam wyjaśnienia, ale z uwzględnieniem trochę innego punktu widzenia (lub argumentacji).
Pomysł na książkę był prosty: pokazać cały proces wytwarzania oprogramowania, począwszy od analizy potrzeb klienta, poprzez projektowanie, implementację (programowanie), a kończąc na testowaniu. Szczególnie chciałem się zająć przełożeniem efektów analizy na projektowanie oraz programowanie. W związku z tym, czynności z tej pierwszej fazy są potraktowane nieco skrótowo (nie dotyczy to diagramu klas, który jest omówiony bardzo szczegółowo). Czytelnik, który potrzebuje poszerzyć swoją wiedzę na temat tych zagadnień, powinien sięgnąć po którąś z książek traktujących o modelowaniu, UML itp. (lista proponowanych tytułów znajduje się w ostatnim rozdziale: Bibliografia). Większość przykładów w książce oparta jest na konkretnych wymaganiach biznesowych (wypożyczalnia wideo). Implementacja została wykonana dla języka programowania Java SE 6. Czasami też zamieszczam odnośniki do Microsoft C# czy C++. Na początku książki mamy jakiś biznes do skomputeryzowania (wypożyczalnia wideo), przeprowadzamy jego analizę, robimy projekt, a na koniec częściową implementację w postaci prototypu systemu komputerowego.
Proces analizy potrzeb użytkownika i projektowania oprogramowania oraz zagadnienia z tym związane (szeroko pojmowana obiektowość) są czasami postrzegane (szczególnie przez niektórych studentów) jako zbędny balast teoretyczny. Można spotkać się z opinią, że należy usiąść i zacząć pisać program (programować), a reszta jakoś się ułoży. Nieznajomość tych podstaw, nazwijmy to teoretycznych, lub ich niezrozumienie prowadzi do tego, że programy pisane w obiektowych językach programowania nie są wcale zbyt obiektowe. I tak naprawdę, przez to, że nie korzystają z tych udogodnień, wymagają więcej pracy oraz zawierają więcej błędów. Mam nadzieję, że po przeczytaniu tej książki uwierzysz, drogi Czytelniku, że jak powiedział Kurt Lewin, twórca podstaw współczesnej psychologii społecznej: „nie ma nic praktyczniejszego niż dobra teoria”.
To tyle słowem wstępu — dalej już będzie bardziej konkretnie. I jeszcze jedna rzecz: bardzo proszę o przysyłanie uwag, komentarzy, pomysłów, sugestii na adres: [email protected]_.2 ANALIZA
Wytwarzanie współczesnego oprogramowania to proces bardzo skomplikowany. Bierze w nim udział cały sztab ludzi, z których każdy ma konkretne zadanie do wykonania. Aby te osoby mogły się wzajemnie porozumieć, muszą mówić wspólnym językiem. W przypadku projektowania systemu informatycznego do tego celu najczęściej używa się notacji UML (_Unified Modeling Language_) , , . Umożliwia ona w miarę precyzyjne opisanie wszystkich elementów składających się na projekt nowoczesnego oprogramowania. Więcej informacji na temat samego procesu pozyskiwania wymagań można znaleźć np. w książkach , , .
Istnieje wiele różnych metodyk definiujących proces wytwarzania oprogramowania, zaczynając od klasycznych (zwanych często wodospadowymi (_waterfall_)), a kończąc na lekkich (_Agile_). W większości z nich mamy do czynienia z jakąś wersją faz pokazanych na rysunku 2.1. Nawet jeżeli metodyka jest przyrostowa (iteracyjna), to i tak ma ich jakieś odpowiedniki. Główna różnica polega na tym, że w podejściu przyrostowym fazy te są powtarzane wielokrotnie (w każdej iteracji), a w klasycznym realizujemy je jednorazowo.
Rysunek 2.1: Typowe fazy wytwarzania oprogramowania.
Krótko rzecz biorąc, zadaniem poszczególnych faz jest:
Z punktu widzenia tej książki najmniej interesujące są dla nas fazy pierwsza (strategiczna) oraz ostatnia (wdrożenie i pielęgnacja). Z tego powodu raczej nie będziemy się nimi zajmować.
2.1 Wymagania klienta
Jak już wspomnieliśmy, książka ta będzie bazowała na wymyślonym przypadku biznesowym. Dzięki temu będziemy w stanie opisać na praktycznych przykładach sytuacje maksymalnie zbliżone do rzeczywistości.
Wśród analityków panuje przekonanie, że klient nie wie, czego chce. Zwykle chce wszystko, najlepiej za darmo i do tego na wczoraj. Po przeprowadzeniu fazy analizy, gdy już ustaliliśmy, czego tak naprawdę mu potrzeba, okazuje się, że to twierdzenie bardzo często jest prawdą. W związku z tym warto stosować się do kilku rad:
Jak łatwo można sobie wyobrazić, proces ustalania wymagań na system nie jest zbyt prosty. Dla potrzeb tej książki załóżmy jednak, że udało nam się go przeprowadzić łatwo i bezboleśnie, a w efekcie otrzymaliśmy „historyjkę” (zamieszczoną w rozdziale 2.2) opisującą biznes naszego klienta. Celowo wybraliśmy bibliotekę 1, ponieważ w zaproponowanym kształcie posiada większość elementów występujących podczas modelowania systemów komputerowych.
2.2 Wymagania dla biblioteki
Jak można się zorientować, powyższe wymagania odpowiadają mniej więcej typowej bibliotece (może oprócz postaci występujących w publikacji). I jak również łatwo się zorientować, nie są całkowicie precyzyjne. Na pewno brakuje tam pewnych informacji, o czym będziesz mógł się przekonać, drogi Czytelniku, w trakcie lektury pozostałych rozdziałów tej książki. Jest to zabieg celowy: po prostu nie chciałem tworzyć osobnej książeczki poświęconej tylko opisowi wymagań na system. W rzeczywistości należy zebrać jak najwięcej informacji. A co gdy jednak o coś zapomnieliśmy zapytać? Czy robimy tak jak uważamy, że będzie dobrze? Oczywiście, w żadnym wypadku nie! Kontaktujemy się z naszym zleceniodawcą i ustalamy szczegóły (np. uwzględniając porady z rozdziału 2.1).
Warto również zwrócić uwagę na to, że wymagania mogą się zmieniać w trakcie realizacji projektu. W takim przypadku należy zastosować odpowiednie procedury zmiany wymagań, które zazwyczaj są opisane w umowie zawartej z klientem.
2.3 Przypadki użycia
Diagramy przypadków użycia są bardzo ważnym elementem analizy. Ich głównym zadaniem jest zdefiniowanie funkcjonalności tworzonego systemu. Pojęcie funkcjonalności określa, co system ma robić (jakie funkcje może realizować). Ich odzwierciedleniem będą odpowiednie komendy w menu, wyświetlające dedykowane elementy GUI (_Graphical User Interface_ – graficznego interfejsu użytkownika). Ewentualnie, w przypadku tzw. Aplikacji konsolowych (pozbawionych graficznego interfejsu użytkownika) będą miały przełożenie na odpowiednie parametry tekstowe, np. „/remove” lub „-add”. Jednakże na tym etapie tworzenia oprogramowania nie interesuje nas dokładne mapowanie przypadków użycia (funkcji) na konkretne pozycje menu czy przyciski. Nie zajmujemy się też określaniem, jak te funkcje mają być dokładnie wykonywane – to jest przedmiotem fazy projektowania.
Przeprowadzenie dokładnej analizy jest o tyle istotne, że rzutuje na dalsze prace projektowe. Wyobraźmy sobie sytuację, że na tym etapie zapomniano o uwzględnieniu jakiejś funkcji. Oznacza to, że nie zostanie ona uwzględniona przy projektowaniu, implementacji oraz testowaniu. Po prostu jej nie będzie w tworzonej aplikacji! Naturalnie, zawsze można ją dodać na późniejszym etapie (bo nie będziemy mieli innego wyjścia – klient nie zechce systemu, który nie ma wymaganych funkcji). Należy jednak pamiętać, że tworzony system komputerowy jest trochę jak naczynia połączone. Zmiana elementu w jednym miejscu skutkuje zmianami w innym. W efekcie coś, co dobrze działało, może przestać działać lub, co gorsza, zacząć działać źle (złe działanie jest gorsze od braku działania, ponieważ trudniej jest to zaobserwować; gdy coś nie działa, to widzimy to od razu). Generalnie, w inżynierii oprogramowania uważa się, że im błąd wcześniej popełniony, tym ma gorsze skutki dla całego projektu. Jest to też zgodne ze zdrowym rozsądkiem: niezauważenie konieczności dodania funkcji na etapie analizy jest dużo poważniejsze niż jakiś błąd typowo programistyczny, który, gdy występuje w sposób deterministyczny (wiemy, co trzeba zrobić, aby wystąpił), możemy stosunkowo łatwo naprawić.
W większości przypadków, zamiast rysować diagram przypadków użycia (_use case diagram_) możemy wypisać poszczególne funkcje w punktach. Pod względem zawartości te dwa podejścia są prawie równoważne. Wydaje się, że główne zalety diagramu to:
Diagramy przypadków użycia są stosunkowo proste. Ich najważniejsze elementy to (zobacz rysunek 2.2):
Rysunek 2.2: Przykładowy diagram przypadków użycia służący jako ilustracja notacji.
Przypadki użycia mogą być powiązane ze sobą na dwa sposoby:
2.3.1 Ogólny diagram przypadków użycia dla Biblioteki
Diagramy przypadków użycia można rysować na różnym poziomie szczegółowości. Zwykle robi się jeden (lub więcej dla bardzo rozbudowanych systemów) ogólny diagram i uszczegóławia się go na oddzielnych diagramach. Nasuwa się pytanie: jak bardzo należy wchodzić w szczegóły? Nie ma jednej precyzyjnej odpowiedzi. Przeważnie robimy to tak, aby dało się z niego odczytać dość ogólne informacje. Do przedstawiania bardziej szczegółowych i precyzyjnych danych służą inne diagramy (np. aktywności – podrozdział 2.5, stanów – podrozdział 2.6; warto także zajrzeć do książki ).
Rysunek 2.3: Diagram przypadków użycia dla biblioteki.
Rysunek 2.3 zawiera przykładowy, ogólny (zawierający wszystkie funkcje) diagram dla naszej biblioteki. Słowo przykładowy nie jest przypadkowe. Inny analityk (np. ty, Czytelniku) mógłby narysować (trochę) inny diagram. Jego kształt oraz zakres pokazanych funkcji zależy od dwóch głównych czynników:
Poniżej w punktach omówimy niektóre decyzje projektowe podjęte przy okazji tworzenia tego diagramu:
Rysunek 2.4: Diagram dziedziczenia dla aktorów.
2.3.2 Szczegółowy diagram przypadków użycia
Jak już wcześniej ustaliliśmy, nie ma jednoznacznych reguł, czy i jak organizować różne stopnie szczegółowości dla diagramów przypadków użycia. Każdy z analityków może mieć własny pogląd na tę sprawę. Generalnie zakłada się, że umieszczanie zbyt wielu szczegółów zmniejsza czytelność tych diagramów i dlatego należy tego unikać.
Rysunek 2.5: Przykładowy, uszczegółowiony diagram przypadków użycia.
Rysunek 2.5 zawiera uszczegółowioną wersję jednego z przypadków użycia („Wypożyczenie egzemplarza”) przedstawionych ogólnie na rysunku 2.3. Poniżej zamieszczono jego skrótową analizę:
Rysunek 2.6: Notacja dla klas.
Rysunek 2.7: Notacja do oznaczania atrybutów.
Rysunek 2.8: Notacja do oznaczania metod.
Rysunek 2.9: Przykład ilustrujący wykorzystanie asocjacji.
Rysunek 2.10: Przykład ilustrujący wykorzystanie asocjacji. W stosunku do rysunku 2.9 zmieniono nazwę oraz jej kierunek czytania
Rysunek 2.11: Ilustracja wykorzystania ról asocjacji
Rysunek 2.12: Liczności asocjacji
Rysunek 2.13: Redukcja liczności dla asocjacji
Rysunek 2.14: Przykład asocjacji skierowanej
Rysunek 2.15: Przykładowa asocjacja n-arna
Rysunek 2.16: Ilustracja problemu z asocjacją n-arną
Rysunek 2.17: Asocjacja binarna (a) oraz kwalifikowana (b)
Rysunek 2.18: Przykładowa asocjacja rekurencyjna (zwrotna)
Rysunek 2.19: Przykładowy diagram obiektów dla asocjacji rekurencyjnej z rysunku 2.18
Rysunek 2.20: Zastosowanie klasy asocjacji
Rysunek 2.21: Diagram obiektów ilustrujący wykorzystanie klasy asocjacji
Rysunek 2.22: Przykładowa agregacja
Rysunek 2.23: Przykładowa kompozycja
Rysunek 2.24: Przykładowa hierarchia dziedziczenia
Rysunek 2.25: Ilustracja wykorzystania klasy abstrakcyjnej
Rysunek 2.26: Hierarchia dziedziczenia z dodanymi metodami
Rysunek 2.27: Hierarchia dziedziczenia z dodanymi metodami zwracającymi dochody
Rysunek 2.28: Przykładowa hierarchia wielodziedziczenia
Rysunek 2.29: Dziedziczenie typu overlapping
Rysunek 2.30: Przykładowe dziedziczenie wieloaspektowe
Rysunek 2.31: Przykład dziedziczenia dynamicznego
Rysunek 2.32: Ilustracja ograniczenia subset
Rysunek 2.33: Ilustracja ograniczenia {ordered}
Rysunek 2.34: Ilustracja ograniczenia {bag}
Rysunek 2.35: Ilustracja ograniczenia {xor}
Rysunek 2.36: Tworzenie diagramu klas dla biblioteki – krok 1
Rysunek 2.37: Tworzenie diagramu klas dla biblioteki – krok 2
Rysunek 2.38: Tworzenie diagramu klas dla biblioteki – krok 3
Rysunek 2.39: Tworzenie diagramu klas dla biblioteki – krok 4
Rysunek 2.40: Tworzenie diagramu klas dla biblioteki – krok 5
Rysunek 2.41: Tworzenie diagramu klas dla biblioteki – krok 6
Rysunek 2.42: Tworzenie diagramu klas dla biblioteki – krok 7
Rysunek 2.43: Tworzenie diagramu klas dla biblioteki – krok 8
Rysunek 2.44: Tworzenie diagramu klas dla biblioteki – krok 9
Rysunek 2.45: Tworzenie diagramu klas dla biblioteki – krok 10
Rysunek 2.46: Tworzenie diagramu klas dla biblioteki – krok 11
Rysunek 2.47: Tworzenie diagramu klas dla biblioteki – krok 12
Rysunek 2.48: Tworzenie diagramu klas dla biblioteki – krok 13
Rysunek 2.49: Tworzenie diagramu klas dla biblioteki – krok 14
Rysunek 2.50: Tworzenie diagramu klas dla biblioteki – krok 15
Rysunek 2.51: Tworzenie diagramu klas dla biblioteki – krok 16
Rysunek 2.53: Tworzenie diagramu klas dla biblioteki – krok 17
Rysunek 2.54: Tworzenie diagramu klas dla biblioteki – krok 18
Rysunek 2.55: Tworzenie diagramu klas dla biblioteki – krok 19
Rysunek 2.56: Tworzenie diagramu klas dla biblioteki – krok 20
Rysunek 2.57: Tworzenie diagramu klas dla biblioteki – krok 21
Rysunek 2.58: Tworzenie diagramu klas dla biblioteki – krok 22
Rysunek 2.59: Tworzenie diagramu klas dla biblioteki – krok 23
Rysunek 2.60: Tworzenie diagramu klas dla biblioteki – krok 24
Rysunek 2.61: Tworzenie diagramu klas dla biblioteki – krok 25
Rysunek 2.62: Tworzenie diagramu klas dla biblioteki – krok 26
Rysunek 2.63: Tworzenie diagramu klas dla biblioteki – krok 27
Rysunek 2.66: Tworzenie diagramu klas dla biblioteki – krok 30
Rysunek 2.67: Tworzenie diagramu klas dla biblioteki – krok 31
Rysunek 2.68: Tworzenie diagramu klas dla biblioteki – krok 32
Rysunek 2.69: Tworzenie diagramu klas dla biblioteki – krok 33
Rysunek 2.70: Diagram klas dla biblioteki – wersja finalna
Rysunek 2.71: Diagram aktywności przedstawiający dodawanie nowego klienta
Rysunek 2.72: Diagram aktywności przedstawiający wypożyczenie publikacji (egzemplarza)
Rysunek 2.73: Przykładowy diagram stanów dla obiektów klasy _Egzemplarz_
------------------------------------------------------------------------