1.13k likes | 1.49k Views
Načrtovalski vzorci in načrtovanje sistema. Ozadje. Načrtovanje ponovno uporabljive program. opreme je težavno Iskanje dobrih objektov in abstrakcij fle ksibilnost, modularnost, eleganca ponovna uporaba Potrebujemo čas, izkušnje na napakah Imamo uspešne razvoje
E N D
Načrtovalski vzorci innačrtovanje sistema
Ozadje • Načrtovanje ponovno uporabljive program. opreme je težavno • Iskanje dobrih objektov in abstrakcij • fleksibilnost, modularnost, eleganca ponovna uporaba • Potrebujemo čas, izkušnje na napakah • Imamo uspešne razvoje • Kažejo ponavljajoče se razrede in strukturo objektov • Kako bi take ponavljajoče se strukture opisali?
Iskanje objektov • Najtežji del v razvoju sistema: • Identifikacija objektov • Dekompozicija sistema v objekte • Analiza zahtev je usmerjena v področje uporabe: • Identifikacija objektov • Razvoj sistema je naslavlja tako področje uporabe kot implementacije: • Identifikacija podsistemov • Objektno usmerjen razvoj je usmerjen v področje implementacije: • Še več identifikacije objektov
Tehnike iskanja objektov • Analiza zahtev • Začnemo s primeri uporabe: identifikacijo sodelujočih objektov • Tekstovna analiza poteka dogodkov (iščemo samostalnike, glagole, ...) • Izluščimo objekte področja uporabe z izpraševanjem stranke (znanje o področju uporabe) • Iskanje objektov s splošnim znanjem • Razvoj sistema • Dekompozicija podsistemov • Skušamo ugotoviti plasti in particije • Načrtovanje objektov • Dodatne objekte najdemo z uporabo znanja o implementaciji
Drug vir iskanja objektov : Načrtovanje vzorcev • Opazovanje: • Dosledno modeliranje realnega sveta vodi v sistem, ki odraža današnje razmere, ne pa nujno jutrišnje. • Potrebujemo ponovno uporabljive in fleksibilne načrte • Znanje o načrtovanju komplementira poznavanje področja in poznavanje implementacije. • Kaj so načrtovalski vzorci? • Načrtovalski vzorec opisuje problem, na katerega pogosto naletimo v našem okolju, opisuje bistvo rešitve problema, kar lahko nato ponovno uporabljamo
Načrtovalski vzorec (Design Pattern) • Opisuje ponavljajočo se strukturo načrtovanja • abstrakcija od konkretnih načrtov • identifikacija razredov, sodelovanj, odgovornosti • uporabljivost, kaj nas to stane, posledice • Primeri • Observer: MVC • Strategy: algoritmi kot objekti • Composite: rekurzivne strukture
Vzorci niso načrti • Napraviti moramo njihove instance • Oceniti kompromise (trade-offs) in posledice • Izvesti odločitve v načrtovanju in implementaciji • Implementirati, kombinirati z drugimi vzorci
Vzorci niso ogrodja (Frameworks) • Ogrodja kodirajo načrte reševanja družine problemov na danem področju • abstraktni, sodelujoči razredi • Prilagojena za • podrazrede, ki jih definira uporabnik • kompozicijo objektov • Vsebujejo instance več vzorcev
Seat Control Card Reader Onboard Computer Mirror Control Speech Recognition Speech Synthesis Primer resničnega projekta: Projekt JAMES • Nefunkcionalne zahteve • Primer uporabe vrste aplikacij s pametnimi karticami • Bonus sistem, personalizacija vozila, planiranje potovanja, • Fleksibilnost in razširljivost za bodoče aplikacije • Integracija različnih računalniških platform in naprav • Centralna podatkovna baza, osebni računalniki, vgrajeni računalnik, razpoznavanje govora, krmilniki naprav, pametne kartice • Skalabilnost • Podpora velikemu številu mobilnih odjemalcev in strežnikov • Odprtost • Uporaba odprtih standardov • in komercialnih komponent
JAMES Event Service Requirements • Peers can be created and deleted dynamically • Peers can subscribe dynamically as publishers or subscribers • A peer can subscribe to many event channels at the same time • A peer can be publisher and subscriber on a event channel at the same time • Publishers do not know their subscribers (only the event channel) • Event channels allow plug-and-play with cardlets Use of the Observer Pattern leads to scalable and extensible architecture
James Event Service as a set of objects • View (“Boundary objects”):Viewlets • Controller (“Control Object”):Event Channel • Model (“Entity Objects”): Cardlets and Vehicle Subsystem • Cardlets and Viewlets act as peers on the onboard software bus • cardlets are applications running on a Java smartcard • viewlets are the corresponding GUI frontends on the onboard computer
Card Reader Smartcard Onboard GUI (Touchscreen) VIPViewlet TravelViewlet VIPCardlet TravelCardlet On Board Bus Cardlets and Viewlets
VIP Viewlet VIPCardlet TravelCardlet Travel Viewlet Controller generic controller variable number of arbitrary viewlets variable number of arbitrary cardlets standard events download new viewlets in the field download new cardlets in the field Cardlet Communication in James Onboard GUI Smartcard Onboard Bus BonusCardlet Bonus Viewlet
Katalog 23 načrtovalskih vzorcev Structural Adapter Bridge Composite Decorator Façade Flyweight Proxy Behavioral Chain of Responsibility Command Interpreter Iterator Mediator Observer State Strategy Template Method Visitor Creational Abstract Factory Builder Factory Method Prototype Singleton
Robustnost na spremembe • Spreminjanje programov je nekaj normalnega • zaradi sprememb zahtev, tehnologije, platform • alternativne uporabe scenarijev • Robustnost na spremembe pomeni • lahkoto razvoja • posledične stroške vzdrževanja • dobro ponovno uporabljivost • Vsak vzorec naslavlja določeno spreminjanje • algoritmov, implementacij, instanc razredov • načrti, temelječi na teh vzorcih, so robustni na te spremembe
Zaupanje v načrtovanje • Pomanjkanje izkušenj z objekti • Je moj načrt v redu? • Vzorci vzbujajo zaupanje • pravilo uporabe nečesa že uporabljenega • še vedno je prostora za kreativnost
Pogosti problemi • Preveč navdušenja • “uspel bom” če uporabim čimveč vzorcev • reševanje napačnega problema • Vse bo rešeno z najnovejšim vzorcem, ki smo ga spoznali • Struktura namesto namena • Vse je“Strategy” • vzorci uporabljajo podobne konstrukte
Iskanje pravega vzorca • Ni povsem jasno, kdaj je nek vzorec uporabljiv • Težko je med razvojem postaviti prava vprašanja • Potrebne so izkušnje tako s področjem kot z vzorci • Ko najdemo vzorec, to vpliva na razvoj • ocenimo, kaj nas to stane (tradeoffs) in implementirajmo variacijo
Skupen slovar v razvoju • Jezik razvoja onstran tehnologije • abstrakcije problema, ne implementacije • Skupen slovar • med ekipami, med razvijalci in menažerji • lahko izključi tiste, ki niso vključeni
Vzorec Composite • Sestavlja objekte v drevesne strukture in tako predstavlja hierarhije del-celota s poljubno globino in širino. • Vzorec Composite omogoča odjemalcu enako obravnavo tako posameznih objektov kot kompozicij iz takih objektov komponenta odjemalec list Operation() Composite Operation() AddComponent RemoveComponent() GetChild() otroci
Motor Katedra Univerza Fakulteta Vzorec Composite Program Dynamic tree (recursive aggregate): Blok Enostavni Sestavljeni stavek stavek Ponovimo: modeliranje tipičnih agregacij fiksna struktura: Avto Akumulator Vrata Kolesa Organigram (variable aggregate):
Grafične aplikacije uporabljajo vzorec Composite • RazredGraphicpredstavlja tako primitive (Line, Circle) kot vsebovalnike (Picture) Graphic Odjemalec Circle Draw() Picture Draw() Add(Graphic g) RemoveGraphic) GetChild(int) Line Draw() Otroci
Modeliranje razvoja programov z vzorci Composite • Življenski cikel programske opreme: • Definicija: Življenski cikel programov je sestavljen iz množice razvojnih aktivnosti , ki so ali druge aktivnosti ali zbirke nalog • Composite: Aktivnost (Življenski cikel je sestavljen iz aktivnosti, ki so sestavljene iz aktivnosti, ki so sestavljene iz aktivnosti, ki ...) • Vozel (list): Naloga • Programski sistem: • Definicija: Programski sistem je sestavljen iz podsistemov, ki so ali drugi podsistemi ali zbirke razredov • Composite: Podsistem (Programski sistem je sestavljen iz podsistemov, ki so sestavljeni iz podsistemov, ki so sestavljeni iz podsistemov, ki so...) • Vozel (list): Razred
Modeliranje življenskega cikla programske opreme z vzorcem Composite Živl. cikel programov Nosilec projekta Naloga Aktivnost Otroci
Modeliranje programskega sistema z vzorcem Composite Programski sistem Razvijalec Razred Podsistem Otroci
Idealna struktura podsistema: Façade, Adapter, Bridge • Podsistem sestavljajo • Objekt – vmesnik (interface object) • množica objektov aplikacijskega področja (entitetni objekti) modelirajo realne entitete oziroma obstoječe sisteme • Nekateri objekti aplikacijskega področja so vmesniki do obstoječih sistemov • eden ali več kontrolnih objektov • Realizacija objekta - vmesnika: Facade • Nudi vmesnik do podsistema • Vmesnik do obstoječih podsistemov: AdapteraliBridge • Nudi vmesnik do obstoječega (dedovanega) sistema • Obstoječi sistem ni nujno objektno usmerjen!
Vzorec Facade • Nudi poenoten vmesnik do množice objektov v podsistemu. • Fasada definira visokonivojski vmesnik, ki olajša uporabo podsistema (abstrahira zoprne podrobnosti) • Fasade omogočajo uvedbo zaprte arhitekture
Odprta arhitektura: vsak odjemalec ima dostop do katerekoli komponente podsistema (in operacij v njih). Zakaj je to dobro? Učinkovitost Zakaj je to slabo? Odjemalec morda ne razume delovanja podsistema in kompleksnih relacij v njem Zagotovo pride do napačne uporabe podsistema, kar vodi v neprenosljivo kodo. Značilnosti odprte arhitekture VIP Subsystem Vehicle Subsystem Seat Card AIM SA/RT
Podsistem odloča, kakšen bo dostop do njega. Ni treba skrbeti za napačno uporabo s strani klicateljev Če uporabimo fasado, lahko podsistem uporabimo v zgodnjih testih integracije Zadošča, da napišemo le en gonilnik Realizacija zaprte arhitekture s fasado VIP Subsystem Vehicle Subsystem API Card Seat AIM SA/RT
Compiler compile(s) CodeGenerator create() Lexer getToken() Optimizer create() Parser generateParseTree() ParseNode create() Realizacija prevajalnika z vzorcem Facade Compiler
CodeGenerator create() Lexer getToken() UML notacija za podsisteme: Package • Paket = zbirka razredov, zloženih v skupino • S paketi pogosto modeliramo podsisteme • Notacija: • Pravokotnik z zavihkom. Zavihek vsebuje ime paketa Compiler Compiler Compiler compile(s) Optimizer create() Parser generateParseTree() ParseNode create()
Class Adapter Pattern (based on Multiple Inheritance) Target Request() Client Adaptee (Legacy Object) ExistingRequest() Adapter Request()
Pred nadaljevanjem ponovimo ... • Ponovna uporaba: • Ponovna uporaba znanja iz prejšnjih izkušenj na novem problemu • Ponovna uporaba funkcionalnosti, ki že obstaja • Kompozicija (imenjemo jo tudi ponovna uporaba črne škatle) • Nova funkcionalnost, ki jo dovimo z agregacijo • Nov objekt z več funkcionalnosti je agregacija obstoječih komponent • Dedovanje (imenujemo ga tudi ponovna uporaba bele škatle) • Novo funkcionalnost dobimo z dedovanjem. • Trije načini, da dobimo novo funkcionalnost: • dedovanje implementacije • Dedovanje vmesnika • Delegiranje
Dedovanje implementacije – dedovanje vmesnika • Dedovanje implementacije • Temu provimo tudi dedovanje razredov • Cilj: Razširiti funkcionalnost aplikacije s ponovno uporabo funkcionalnosti dedovanega razreda • Dedovanje iz obstoječega razreda, v katerem so vsaj nekatere ali vse operacije že implementirane • Dedovanje vmesnika • Temu pravimo tudi “subtyping” • Dedovanje iz abstraktnega razreda, v katerem so vse operacije specificirane, ne pa še implementirane
Dedovanje implementacije • Zelo podoben razred je že implementiran, dela pa skoraj vse, kar želimo. List • Primer: Imam razredList, potrebujem razred Stack. Kaj če podedujem razred LIST in dodam metodePush(),Pop()in Top()? Add () Remove() “Že implementirano” Stack Push () Pop() Top() • Problem z dedovanjem implementacije: • Nekatere od podedovanih operacij se lahko nezaželeno obnašajo. Kaj se zgodi, če uporabnik razreda Stack kliče Remove() namesto Pop()?
Delegiranje • Z delegiranjem tvorimo kompozicijo (na primer agregacijo), ki je za ponovno uporabo enako učinkovita kot dedovanje • Pri delegaciji sta v obravnavo nekega zahtevka vključena dva objekta • Objekt, ki sprejme zahtevek, prepusti izvedbo operacije svojemu delegatu. • Razvijalec lahko zagotovi, da bo sprejemajoči objekt odjemalcu preprečil napačno uporabo objekta - delegata Delegat Sprejemnik Odjemalec kliče posreduje
Delegiranje namesto dedovanja • Delegiranje: Ujamemo operacijo in jo posredujemo drugemu objektu. List Stack +Add() List +Remove() Remove() +Push() +Pop() +Top() Add() Stack +Push() +Pop() +Top()
Delegiranje ali dedovanje? • Delegiranje • Dobro: • Fleksibilnost: Katerikoli objekt lahko tudi v času izvajanja zamenjamo z drugim (če je le istega tipa) • Slabo: • Neučinkovitost: Objekti so enkapsulirani. • Dedovanje • Dobro: • Preprosta uporaba • Podpira ga vrsta programskih jezikov • Implementacija nove funkcionalnosti je lahka • Slabo: • Dedovanje razkriva podrazredu podrobnosti dedovanega razreda • Kakršnakoli sprememba dedovanega razreda vsiljuje spremembe podrazredu (potrebno je ponovno prevajanje obeh)
Vrnimo se k načrtovalskim vzorcem Veliko načrtovalskih vzorcev uporablja kombinacijo dedovanja in delegiranja
Vzorec Adapter • Pretvori vmesnik razreda v nek drug vmesnik, ki ga odjemalec pričakuje. Adapter omogoči sodelovanje razredov, ki bi zaradi nekompatibilnih vmesnikov sicer ne bilo možno • Tako zagotovimo nov vmesnik obstoječim komponentam (Interface engineering, reengineering). • Ta vzorec poznamo tudi kot “wrapper” (ovijalec) • Dva vzorca adapter: • Class adapter: • Uporablja večkratno dedovanje za prilagajanje enega vmesnika drugemu • Object adapter: • Uporablja eno dedovanje in delegiranje • Največkrat uporabljamo prilagojevalce objektov in jih preprosto imenujemo “adapters”
Adapter Request() Vzorec Adapter Ciljni objekt (target) Request() Odjemalec Prilagojenec (adaptee) ExistingRequest() • Za povezavo prilagalca (adapter) in prilagojenca (adaptee) uporabljamo delegiranje • Vmesnik razreda Adapter naredimo z dedovanjem vmesnika. • Ciljni objekt in prilagojenec sta običajno komponenti, ki obstajata pred uvedbo adapterja. • Ciljni objekt lahko v Javi realiziramo kot “interface”. adaptee
ServicesEnumeration hasMoreElements() nextElement() Primer vzorca Adapter Enumeration hasMoreElements() nextElement() Client RegisteredServices numServices(); getService(int num); public class ServicesEnumeration implements Enumeration { public boolean hasMoreElements() { return this.currentServiceIdx <= adaptee.numServices(); } public Object nextElement() { if (!this.hasMoreElements()) { throw new NoSuchElementException(); } return adaptee.getService(this.currentSerrviceIdx++); } adaptee
Vzorec Bridge (most) • Z mostom razvežemo abstrakcijo od njene implementacije, kar omogoča njuno neodvisno spreminjanje. • To poznamo tudi kot vzorec “ročica/telo” (Handle/Body). • Omogoča dinamično odločanje o različnih implementacijah nekega vmesnika.
C l i en t i mp I m pl eme ntor A bs tra c t i on O pe ra ti o n ( ) O p era t i o n I mp l ( ) I mp -> Op er a t i o n Im p( ) ; C on cr e t e I m p l e m en tor A C on cr e t e I m p l e m en tor B R e fi ned Ab s t ra c t i o n 1 R e fi ned Ab s t ra c t i o n 2 O pe ra ti o nI mp l() O pe ra ti o nI mp l() O pe ra ti o n ( ) O pe ra ti o n ( ) Vzorec Bridge
Uporaba vzorca Bridge • Vzorec “bridge” uporabljamo za nudenje več implementacij pod enim samim vmesnikom. • Primeri: Vmesnik na neko komponento ni popoln, je še neznan ali ga med preskušanjem še nimamo na voljo • Primer z avtom:Morali bi brati podatke o sedežu, vendar ta še ni implementiran ali je na voljo le simuliran. Uporabimo “bridge”: Seat (in Vehicle Subsystem) VIP imp SeatImplementation GetPosition() SetPosition() AIMSeat Stub Code SARTSeat
Bridge in primer z avtom public interface SeatImplementation { public int GetPosition(); public void SetPosition(int newPosition); } public class AimSeat implements SeatImplementation { public int GetPosition() { // actual call to the AIM simulation system } ... } public class SARTSeat implements SeatImplementation { public int GetPosition() { // actual call to the SART seat simulator } ... }
Primerjava Adapter in Bridge • Podobnosti: • Z obema skrivamo podrobnosti podložene implementacije. • Razlike: • Vzorec Adapter je usmerjen v sodelovanje nevezanih komponent • Uporabimo ga na že razvitih sistemih (reengineering, interface engineering). • Vzorec bridge,uporabimo pred načrtovanjem, da lahko abstrakcije in implementacije neodvisno spreminjamo. • V “zoološki vrt objektov” lahko dodajamo nove “živali”, čeprav jih še ne poznamo v času analize ali načrtovanja sistema.
Seat Seat Preferences AIMSeat SARTSeat ActualSeat PreferencesCardlet Example for Combination of Adapters and Bridges in JAMES SetSeatPos() GetSeatPos() Adapter Existing SmartCard Library from Schlumberger Seat Impl SLBRDR32 Bridge SLBAPISendIsoOutT0 Seats for the Car
Nekaj praktičnih navodil iz izkušenj • Never use implementation inheritance, always use interface inheritance • A subclass should never hide operations implemented in a superclass • If you are tempted to use implementation inheritance, use delegation instead