Uvod u uzorke dizajna, 1. dio: Povijest i klasifikacija uzoraka dizajna

Osmišljene su brojne strategije za pojednostavljivanje i smanjenje troškova dizajniranja softvera, posebno u području održavanja. Učenje prepoznavanja i rada sa softverskim komponentama za višekratnu upotrebu (koje se povremeno nazivaju softverskim integriranim krugovima ) jedna je od strategija. Korištenje uzoraka dizajna je drugo.

Ovaj članak pokreće trodijelnu seriju o uzorcima dizajna. U ovom dijelu predstavit ću konceptualni okvir dizajnerskih uzoraka i proći kroz demonstraciju procjene dizajnerskog uzorka za određeni slučaj upotrebe. Također ću razgovarati o povijesti dizajnerskih uzoraka i anti-uzoraka. Na kraju ću klasificirati i sažeti najčešće korištene obrasce dizajna softvera koji su otkriveni i dokumentirani u posljednjih nekoliko desetljeća.

Što je obrazac dizajna?

Stvaranje višestruko objektno orijentiranog softvera koji modelira postojeći sustav istinski je izazov. Programer softvera mora entitete sustava podijeliti na klase čija javna sučelja nisu pretjerano složena, uspostaviti odnose među klasama, izložiti hijerarhije nasljeđivanja i još mnogo toga. Budući da većina softvera ostaje u upotrebi dugo nakon što je napisana, programeri softvera također se moraju pozabaviti trenutnim zahtjevima aplikacije, a svoj kôd i infrastrukturu održavaju dovoljno fleksibilnima da zadovolje buduće potrebe.

Iskusni objektno orijentirani programeri otkrili su da obrasci dizajna softvera olakšavaju kodiranje stabilnih i robusnih softverskih sustava. Ponovna upotreba ovih obrazaca dizajna, umjesto neprestanog razvijanja novih rješenja od nule, učinkovita je i smanjuje dio rizika od pogreške. Svaki obrazac dizajna identificira ponavljajući problem dizajna u određenom kontekstu aplikacije, a zatim nudi generalizirano rješenje za višekratnu upotrebu koje je primjenjivo na različite scenarije aplikacije.

"Uzorak dizajna opisuje klase i interakcijske objekte koji se koriste za rješavanje općeg problema dizajna u određenom kontekstu."

Neki programeri definiraju obrazac dizajna kao entitet kodiran klasom (poput povezanog popisa ili vektora bitova), dok drugi kažu da se obrazac dizajna nalazi u cijeloj aplikaciji ili podsustavu. Moje je stajalište da obrazac dizajna opisuje klase i interaktivne objekte koji se koriste za rješavanje općeg problema dizajna u određenom kontekstu. Formalnije, obrazac dizajna naveden je kao opis koji se sastoji od četiri osnovna elementa:

  1. Naziv koji opisuje uzorak dizajna i daje nam rječnika za to opisala
  2. Problem koji identificira problem dizajna koji trebaju biti riješeni uz kontekst u kojem se pojavljuje problem
  3. Rješenje za problem koji (u softverskom dizajnu uzorak kontekstu) treba identificirati klase i objekte koji pridonose dizajnu zajedno sa svojim vezama i drugim čimbenicima
  4. Objašnjenje posljedica upotrebe uzorka dizajna

Da biste identificirali odgovarajući obrazac dizajna za upotrebu, prvo morate jasno prepoznati problem koji pokušavate riješiti; tu je koristan problemski element opisa dizajnerskog uzorka. Odabir jednog uzorka dizajna u odnosu na drugi također obično uključuje kompromise koji mogu utjecati na fleksibilnost aplikacije ili sustava i buduće održavanje. Zbog toga je važno razumjeti posljedice korištenja određenog uzorka dizajna prije nego što ga počnete provoditi.

Procjena uzorka dizajna

Razmotrite zadatak dizajniranja složenog korisničkog sučelja pomoću gumba, tekstualnih polja i ostalih komponenata koje nisu spremničke. Uzorak kompozitnog dizajna promatra spremnike kao dijelove, što nam omogućuje da spremnike i njihove sastavne dijelove (spremnike i nekontejnere) ugnijezdimo u druge spremnike, i to rekurzivno. Ako odlučimo ne koristiti kompozitni uzorak, morali bismo stvoriti mnogo specijaliziranih komponenata koje nisu spremnici (na primjer jedna komponenta koja kombinira tekstualno polje lozinke i gumb za prijavu), što je teže postići.

Nakon što smo dobro razmislili, razumijemo problem koji pokušavamo riješiti i rješenje koje nudi kompozitni uzorak. Ali koje su posljedice korištenja ovog uzorka?

Korištenje Composite znači da će vaše hijerarhije klasa miješati komponente spremnika i komponente koje nisu spremnici. Jednostavniji klijenti ravnomjerno će se odnositi prema komponentama spremnika i nekontejnera. I bit će lakše uvesti nove vrste komponenata u korisničko sučelje. Sastav također može dovesti do previše generaliziranih dizajna, što otežava ograničavanje vrsta komponenata koje se mogu dodati u spremnik. Budući da se nećete moći osloniti na kompajler da bi nametnuo ograničenja tipa, morat ćete koristiti provjere vremena izvođenja.

Što nije u redu s provjerama vremena izvođenja?

Provjere tipa izvođenja uključuju izraze if i instanceofoperator, što dovodi do krhkog koda. Ako zaboravite ažurirati provjeru vremena izvođenja kako se zahtjevi vaše aplikacije razvijaju, mogli biste naknadno uvesti bugove.

Također je moguće odabrati odgovarajući obrazac dizajna i koristiti ga pogrešno. Uzorak zaključavanja Double-Checked klasičan je primjer. Dvostruko provjereno zaključavanje smanjuje troškove preuzimanja brave tako što se prvo testira kriterij zaključavanja bez stvarnog stjecanja brave, a zatim zaključavanje dobiva samo ako provjera ukazuje da je zaključavanje potrebno. Iako je na papiru izgledalo dobro, dvostruko provjereno zaključavanje u JDK 1.4 imalo je nekih skrivenih složenosti. Kada je JDK 5 proširio semantiku volatileključne riječi, programeri su napokon uspjeli iskoristiti blagodati dvostruko provjerenog uzorka zaključavanja.

Više o dvostruko provjerenom zaključavanju

Pogledajte "Dvostruko provjereno zaključavanje: pametno, ali slomljeno" i "Može li se dvostruko provjereno zaključavanje popraviti?" (Brian Goetz, JavaWorld) da biste saznali više o tome zašto ovaj obrazac nije radio u JDK 1.4 i starijim verzijama. Za više informacija o specificiranju DCL-a u JDK 5 i novijim, pogledajte "Izjavu" Dvostruko provjereno zaključavanje je slomljeno "(Sveučilište u Marylandu, Odjel za računalne znanosti, David Bacon i dr.).

Anti-uzorci

Kada se uzorak dizajna obično koristi, ali je neučinkovit i / ili kontraproduktivan, uzorak dizajna poznat je kao anti-uzorak . Netko bi mogao tvrditi da je dvostruko provjereno zaključavanje kao što se koristi u JDK 1.4 i starijim verzijama bilo anti-obrazac. Rekao bih da je to bila samo loša ideja u tom kontekstu. Da bi se loša ideja razvila u anti-obrazac, moraju biti ispunjeni sljedeći uvjeti (vidi Resursi).

  • Ponovljeni obrazac djelovanja, procesa ili strukture koji se u početku čini korisnim, ali u konačnici proizvodi više loših posljedica nego korisnih rezultata.
  • Postoji alternativno rješenje koje je jasno dokumentirano, dokazano u praksi i ponovljivo.

Iako je dvostruko provjereno zaključavanje u JDK 1.4 udovoljilo prvom zahtjevu anti-uzorka, nije udovoljilo drugom: iako biste mogli koristiti synchronizedza rješavanje problema lijene inicijalizacije u višenitnom okruženju, to bi pobijedilo razlog za koristeći dvostruko provjereno zaključavanje.

Mrtvi uzorci

Prepoznavanje anti-obrazaca preduvjet je da ih se izbjegne. Pročitajte trodijelnu seriju Obija Ezechukwua za uvod u tri anti-uzorka poznata po izazivanju s mrtve točke:

  • Nema arbitraže
  • Zbrajanje radnika
  • Inkrementalno zaključavanje

Povijest dizajnerskog uzorka

Obrasci dizajna sežu u kasne 1970-te objavljivanjem časopisa A Pattern Language: Towns, Buildings, Construction arhitekta Christophera Alexandera i nekoliko drugih. Ova je knjiga predstavila dizajnerske uzorke u arhitektonskom kontekstu, predstavljajući 253 uzorka koji su zajedno tvorili ono što su autori nazivali jezikom uzoraka .

Ironija dizajnerskih uzoraka

Iako obrasci dizajna koji se koriste za dizajn softvera vode svoj početak do jezika uzoraka , na ovo arhitektonsko djelo utjecao je tada nastajući jezik za opisivanje računalnog programiranja i dizajna.

Koncept jezika uzoraka pojavio se naknadno u dizajnu sustava usmjerenom prema korisnicima Donalda Normana i Stephena Drapera , koji je objavljen 1986. Ova knjiga sugerira primjenu jezika uzoraka na dizajn interakcije , što je praksa dizajniranja interaktivnih digitalnih proizvoda, okruženja, sustava i usluge za ljudsku upotrebu.

U međuvremenu su Kent Beck i Ward Cunningham počeli proučavati obrasce i njihovu primjenjivost na dizajn softvera. 1987. koristili su niz dizajnerskih obrazaca kako bi pomogli Tektronixovoj grupi za poluvodičke ispitne sustave koja je imala problema s dovršenjem projekta. Beck i Cunningham slijedili su Aleksandrove savjete za dizajn usmjeren na korisnika (dopuštajući predstavnicima korisnika projekta da odrede ishod dizajna), a istovremeno su im pružali neke uzorke dizajna kako bi posao olakšali.

Erich Gamma također je uvidio važnost ponavljajućih dizajnerskih obrazaca radeći na svojoj doktorskoj tezi. Vjerovao je da dizajnerski obrasci mogu olakšati zadatak pisanja višekratno korištenog objektno orijentiranog softvera i razmišljao je kako ih učinkovito dokumentirati i komunicirati. Prije Europske konferencije o objektno orijentiranom programiranju 1991., Gamma i Richard Helm počeli su katalogizirati uzorke.

Na OOPSLA radionici održanoj 1991. godine Gammi i Helmu pridružili su se Ralph Johnson i John Vlissides. Ova Gang of Four (GoF), kako su kasnije poznati, nastavila je s popularnim dizajnerskim uzorcima: elementi višekratno korištenog objektno orijentiranog softvera , koji dokumentira 23 dizajnerska uzorka u tri kategorije.

Suvremena evolucija dizajnerskih obrazaca

Uzorci dizajna nastavili su se razvijati od izvorne knjige o GoF-u, pogotovo jer su se programeri suočili s novim izazovima vezanim uz promjenu hardverskih i aplikacijskih zahtjeva.

1994. godine neprofitna organizacija sa sjedištem u SAD-u poznata kao Hillside Group otvorila je Pattern Languages ​​of Programs , skup godišnjih konferencija čiji je cilj razviti i usavršiti umjetnost uzoraka softverskog dizajna. Te su konferencije u tijeku dale brojne primjere dizajna specifičnih za područje. Na primjer, dizajnirajte uzorke u istodobnom kontekstu.

Christopher Alexander na OOPSLA

Glavnu adresu OOPSLA 96 održao je arhitekt Christopher Alexander.Alexander se osvrnuo na svoj rad i na to kako je objektno orijentirana programska zajednica pogodila i promašila cilj prilikom usvajanja i prilagođavanja svojih ideja o jezicima uzoraka softveru. Aleksandrovo obraćanje možete pročitati u cijelosti: "Podrijetlo teorije uzoraka: budućnost teorije i generacija živog svijeta."

Mark Grand je 1998. godine objavio obrasce na Javi . Ova je knjiga sadržavala uzorke dizajna koji se ne nalaze u knjizi GoF, uključujući uzorke paralelnosti. Grand je također koristio Unified Modeling Language (UML) za opisivanje dizajnerskih obrazaca i njihovih rješenja. Primjeri knjige izraženi su i opisani na jeziku Java.

Uzorci dizajna softvera prema klasifikaciji

Suvremeni obrasci dizajna softvera široko su klasificirani u četiri kategorije na temelju njihove upotrebe: kreativni, strukturni, bihevioralni i paralelni. Razgovarat ću o svakoj kategoriji, a zatim ću navesti i opisati neke od istaknutih obrazaca za svaku od njih.

Ostale vrste dizajnerskih uzoraka

Ako mislite da postoji više vrsta uzoraka, u pravu ste. Kasniji članak u ovoj seriji raspravljat će o dodatnim vrstama dizajnerskih uzoraka: interakcija, arhitektonski, organizacijski i komunikacijski / prezentacijski obrasci.

Kreativni obrasci

Stvaralačka uzorak oduzme proces instanca, odvajajući kako su objekti stvoreni, u sastavu, a zastupljena s kodom koji se oslanja na njih. Kreacijski obrasci klasa koriste nasljeđivanje za variranje klasa koje su instancirane, a obrasci kreacijskih uzoraka delegiraju instanciranje drugim objektima.

  • Tvornica sažetaka : Ovaj obrazac pruža sučelje za inkapsuliranje skupine pojedinačnih tvornica koje imaju zajedničku temu bez navođenja njihovih konkretnih klasa.
  • Graditelj : Odvaja izgradnju složenog objekta od njegovog predstavljanja, omogućujući istom procesu gradnje stvaranje različitih prikaza. Apstrahiranje koraka konstrukcije objekata omogućuje različite izvedbe koraka za konstrukciju različitih prikaza objekata.
  • Tvornička metoda : Definira sučelje za stvaranje objekta, ali dopušta potklase da odluče koju će klasu instancirati. Ovaj obrazac omogućuje klasi odgađanje instanciranja za potklase. Ubrizgavanje ovisnosti povezan je obrazac. (Pogledajte Resurse.)
  • Lijena inicijalizacija : Ovaj obrazac daje nam način da odgodimo stvaranje objekta, traženje baze podataka ili neki drugi skup postupak dok prvi put nije potreban rezultat.
  • Multiton : proširuje se na singleton koncept kako bi upravljao mapom imenovanih instanci klase kao parovi ključ / vrijednost i pruža im globalnu točku pristupa.
  • Objekt bazen : Držite niz inicijaliziran objekata spreman za korištenje, a ne biti dodijeljena i uništeno na zahtjev. Namjera je izbjeći skupo prikupljanje i obnavljanje resursa recikliranjem predmeta koji se više ne koriste.
  • Prototip : Određuje vrste objekata koje treba stvoriti pomoću prototipske instance, a zatim stvoriti nove objekte kopiranjem ovog prototipa. Prototipska instanca klonirana je za generiranje novih objekata.
  • Prikupljanje resursa je inicijalizacija : Ovaj obrazac osigurava da se resursi automatski i pravilno inicijaliziraju i povrate vezivanjem za životni vijek prikladnih objekata. Resursi se nabavljaju tijekom inicijalizacije objekata, kada nema šanse da se koriste prije nego što postanu dostupni, a puštaju se s uništavanjem istih objekata, što će se zajamčiti čak i u slučaju pogrešaka.
  • Singleton : osigurava da klasa ima samo jednu instancu i pruža globalnu točku pristupa toj instanci.