Az informatikában a programtervezési mintának (angolulSoftware Design Patterns) nevezik a gyakran előforduló programozási feladatokra adható általános, újrafelhasználható megoldásokat. Egy programtervezési minta rendszerint egymással együttműködő objektumok és osztályok leírása.[1]
A tervminták nem nyújtanak kész tervet, amit közvetlenül le lehet kódolni, habár vannak hozzájuk példakódok, amiket azonban meg kell tölteni az adott helyzetre alkalmas kóddal. Céljuk az, hogy leírást vagy sablont nyújtsanak. Segítik formalizálni a megoldást.
A minták rendszerint osztályok és objektumok közötti kapcsolatokat mutatnak, de nem specifikálják konkrétan a végleges osztályokat vagy objektumokat. A modellek absztrakt osztályai helyett egyes esetekben interfészek is használhatók, habár azokat maga a tervminta nem mutatja. Egyes nyelvek beépítetten tartalmaznak tervmintákat. A tervminták tekinthetők a strukturált programozás egyik szintjének a paradigma és az algoritmus között.
A legtöbb tervminta objektumorientált környezetre van kidolgozva. Mivel a funkcionális programozás kevéssé ismert és használt, arra a környezetre még csak kevés tervminta ismert, például a monád. Az objektumorientált minták közül nem mindegyiket lehet, és nem mindegyiket érdemes itt használni. Van, amit módosítani kell.
A programtervezési minták fogalma
A programtervezési minták fogalma Christopher Alexander építész ötlete nyomán született meg. Ő volt az, aki olyan, az építészetben újra és újra felbukkanó mintákat keresett, amelyek a jól megépített házakat jellemzik. Könyvében, a „The Timeless Way of Buliding”-ben olyan mintákat próbált leírni, amelyek segítségével akár egy kezdő építész is gyorsan jó épületeket tervezhet. A minták a létrehozó építészek sok éves tapasztalata miatt szebb, jobb vagy használhatóbb házakat eredményeztek, mintha a tervezőnek csupán saját erejére támaszkodva kellett volna megterveznie azokat.
1987-ben Kent Beck és Ward Cunningham elkezdett kísérletezni hasonló minták alkalmazásával a programozásban, speciális mintanyelvek segítségével. Eredményeiket még abban az évben az OOPSLA konferencián mutatták be.[2] A következő években kutatásaikhoz mások is társultak.[3]
A programtervezési minták a 90-es évek elején (1994) tettek szert népszerűségre, amikor a négyek bandájaként vagy gammáékként (angolul "Gang of Four" vagy GoF)-ként emlegetett Erich Gamma, Richard Helm, Ralph Johnson és John Vlissides programozó négyes kiadta a Programtervezési minták[4] című könyvüket, amely ma is alapjául szolgál az objektumorientált programozási minták kutatásának. Magát a tervmintát nem definiálták. A fogalom maga évekig formalizálatlan maradt.[5]
Ez a könyv összesen 23 mintát mutat be, és a következő kategóriákba sorolja őket:
A szerzők kiemelik, hogy egyáltalán nem a valóságtól elrugaszkodott és elvont mintákat „találtak ki”, hanem csak összegyűjtötték a sokszor előforduló problémákat és a rájuk adott válaszokat, kielemezték őket, és a látottak alapján megpróbáltak általános megoldásokat nyújtani. A könyvben minden minta mellé leírták azt, hogy milyen felmerülő problémára adhat választ, alkalmazásának előnyeit és hátrányait, a megvalósítás lehetséges buktatóit, ismert felhasználásokat és példakódot, így teljes képet adva azok lehetséges használatának körülményeiről és eredményéről. Ez a könyv ma is referenciaként szolgál minden objektumorientált mintákkal kapcsolatos munkához.
Munkájuk alapján sok tervezési mintákkal foglalkozó közösség alakult, ezek közül talán a legismertebbek a Portland Patterns Repository[6] és a Hillside Group.[7] Mindkét oldal a tervezési minták népszerűsítését, a régi minták fejlesztését és új minták bemutatását tűzte ki céljául, a GoF könyvének szellemében. Az első kiadás óta eltelt több, mint tíz évben új könyvek sora is megjelent a témában, ezek közül a legismertebbek a Head First kiadó Design Patterns-e[8] és a Design Patterns Explained.[9]
A programtervezési minták definíciója, helye
A programtervezési minták a GoF definíciója szerint: „egymással együttműködő objektumok és osztályok leírásai, amelyek testre szabott formában valamilyen általános tervezési problémát oldanak meg egy bizonyos összefüggésben”.
A szoftvertervezésben egy-egy problémára végtelen sok különböző megoldás adható, azonban ezek között kevés optimális van. Tapasztalt szoftvertervezők, akik már sok hasonló problémával találkoztak, könnyen előhúzhatnak egy olyan megoldást, amely már kipróbált és bizonyított. Kezdő fejlesztőknek viszont jól jön, ha mindazt a tudást és tapasztalatot, amit csak évek munkájával érhetnek el, precízen dokumentálva kézbe vehetik, tanulhatnak belőle és az általa bevezetett kifejezésekkel könnyebben beszélhetik meg egymás között az ötleteiket. A programtervezési minták ilyen összegyűjtött tapasztalatok, amelyek mindegyike egy-egy gyakran előforduló problémára ad általánosított választ. Azonban mindezek mellett még számos előnyük van:
lerövidítik a tapasztalatszerzési időt. A programtervezési mintákat nem „feltalálták”, hanem a gyakran előforduló problémákra adott optimális válaszokat gyűjtötték össze, ezáltal olyan megoldásokat adtak, amelyekre előbb-utóbb a legtöbb fejlesztő magától is rájönne – csak esetleg jóval később. Természetesen nem kizárt, hogy léteznek jobb, hatékonyabb megoldások, és ritka amikor egy-egy mintát pontosan úgy lehet alkalmazni egy problémára, ahogy az a könyvekben le van írva, de mindenképpen érdemes megismerni őket, ha másért nem is, hogy elsajátíthassunk valamennyit a szerzők látásmódjából.
lerövidítik a tervezési időt. Az összes minta jól dokumentált, könnyen újrafelhasználható, így ha egyszer alkalmazzuk őket, jó eséllyel egy hasonló problémánál újra eszünkbe fognak jutni az összes előnyükkel és hátrányukkal együtt. Így azonnal hatékony, rugalmas megoldást adhatunk és megkímélhetjük magunkat sok tervezéstől és esetleges újratervezéstől. Ráadásul a minták után található „következmények” rész elősegíti, hogy teljesebb képet kapjunk az alkalmazás hatásairól is.
közös szótárat ad a fejlesztők kezébe. Ez megkönnyíti az egymás közti kommunikációt és a program dokumentálását is, hiszen könnyebb úgy beszélni egy probléma megoldásáról, ha van egy közös alap, ahonnan indulunk vagy amihez lehet hasonlítani az új terveket.
magasabb szintű programozást tesz lehetővé. Mivel ezek a minták elterjedtségük miatt már kiállták nagyon sok programozó próbáját, feltehetőleg az optimális megoldást tartalmazzák a problémára.
A tábla-adat kapu elkülöníti az adatok elhozását és felhasználását egy kapu objektum segítségével. A kapu felhasználói függetlenek az adatok tárolásának módjától.[10]
A hajlékonyság elérése érdekében a tervminták további szinteket vezetnek be, amelyekkel fellazítják a kapcsolatokat. Ezzel javítják a módosíthatóságot, de a nem funkcionális tulajdonságok romlanak. Alapvető szabály, hogy ne adjunk olyan flexibilitást, ami valószínűleg nem lesz kihasználva. Nem megfelelő használatuk csak bonyolultabbá teszi a programot.[11]
A back-off programtervezési minta éppen az erőforrások használatának csökkentésére való.[12] A minta külön szálat indít, ami elvégzi a várakozó feladatokat, és rendszeresen ellenőrzi a feladatsort. Ha nincs várakozó feladat, akkor alszik. Ez a minta szűkös, illetve fizetős erőforrások esetén hasznos.
A programtervezési minták nem az egyetlen, a programozáshoz kapcsolható minták. Általában háromféle csoportosítást szoktak alkalmazni:[13]
Menedzsmenti (Managerial) minták : folyamatok és emberek kezelésének szintje
Ezen kívül szokták használni a programozási minták (programming pattern) kifejezést azokra a programtervezési mintáknál kisebb mintákra, amelyek egy objektum belsejének részleteivel vagy egy nyelv elemeinek használatával foglalkoznak. A sor-adat kapu egy tervminta, amiben egy objektum egy adatbázis sor számára szolgál kapuként.[14]
Mivel a tervmintákat minden újabb programba be kell programozni, ez visszalépést jelent a kód újrafelhasználása terén. Kutatók (köztük Meyer és Arnout) foglalkoznak azzal, hogy a tervmintákból komponenseket készítsenek.[15]
Szerkezete
A tervezési minták leírása több szakaszból áll. Ezek közül a legfontosabbak a szerkezet, a résztvevők és az együttműködés. Ezek írják le magát a mikroszerkezetet, amit alkalmazni lehet bizonyos problémák megoldására. A mikroszerkezet a program egyes egységeiből, mint osztályok és metódusok, és kapcsolataiból áll.
Vannak törekvések arra, hogy konkrétabb, bizonyos célokra szolgáló mintákat találjanak. Ide tartoznak a felhasználói interfészek,[16] az információmegjelenítés,[17] a biztonságos tervezés,[18] a biztonságos használat,[19] Web design [20] a webdesign és az üzleti modell terv.[21]
Egyes mintákat a programozók átalakítanak, hogy jobban illeszkedjenek az éppen megoldani kívánt problémához. Ezek a minták angolul amelioration pattern néven ismertek, és akár antimintának is tekinthetők, mert a továbbfejlesztő azt hihetné, hogy itt az eredeti mintát használták, pedig mégsem.
A Pattern Languages of Programming Conference évenkénti gyűlései és kiadványai sok tartományspecifikus mintát mutatnak be.[22]
Tervezési minták osztályozása
A tervezési minták a modulokat és kapcsolataikat szervezik. Alacsonyabb szintűek, mint az architekturális minták, amelyek a teljes rendszer általános felépítését jellemzik.[23]
Több különböző tervminta létezik, például:[24][25]
Algoritmus stratégia minták
Magas szintű stratégiák, amelyek leírják, hogyan kell algoritmust szervezni egy adott architektúrára.
Számítástervezési minták
A kulcsfontosságú számítások megkeresését célozzák.[26][27]
Végrehajtási minták
A végrehajtás alacsonyabb szintjén címzésekkel, feladatok végrehajtásának szervezésével, optimalizálásával, szinkronizálásával foglalkozó minták.
Implementációs stratégia minták
A forráskód implementációjában támogatják a program szervezését, és a párhuzamos programozás számára fontos adatszerkezetek felépítését.
Szerkezeti tervezési minták
Az alkalmazás globális struktúrájával foglalkoznak.
A tervmintákat Gammáék eredetileg három kategóriába csoportosították: létrehozási minták, szerkezeti minták, és viselkedési minták, amihez használták a delegálás, az aggregálás, és a konzultáció fogalmát. Objektumorientált környezetben az öröklődés, polimorfizmus és az absztrakt ősosztály fogalmait is felhasználják, habár az absztrakt osztályok többnyire interfészek is lehetnek. Egyes szerzők elkülönítik az architekturális tervezési mintákat is, mint a modell-nézet-vezérlő.
Létrehoz egy interfészt egymástól függő vagy valamilyen módon összekapcsolódó objektumok családjainak anélkül, hogy megadnánk a konkrét osztály típusát.
Meghatároz egy interfészt egy objektum létrehozására, de a leszármazottakra van bízva az objektum típusának meghatározása. Segítségével elkerülhető, hogy alkalmazás specifikus osztályokat rakjunk a kódba. (Kapcsolódó: A kontroll megfordítása)[29]).
Hasonlóan az egyke tervezési mintához, egy példány készítését teszi lehetővé, viszont nem alkalmazásonként hanem kulcsonként. A multiton osztály tartalmaz egy mapot a példányokról (kulcs-érték párok).
Objektumok újrafelhasználása. Objektumok példányosítása és törlése költséges művelet lehet, ezért előre legyártott objektumokat használ az alkalmazás, és miután egy szükségtelenné vált, visszahelyezi azt az objektumkészletbe. Tipikus példája a szálkészlet, amely processzek által használatos szálakat tárol.
Meghatároz egy előzetes mintát az objektumok létrehozásához, és később ez kerül másolásra. Gyakran használjuk, ha az objektum pontos típusa csak futásidőben derül ki.
Egy egységes magasabb szintű interfészt hoz létre egy alrendszer számos interfészének. Leegyszerűsíti a bonyolult rendszert, általa könnyebben használhatók az alrendszer funkciói.
Sok egyforma objektum erőforrásaival hatékonyan gazdálkodik oly módon, hogy egy külön objektumban tárolja az újrahasznoítható (ismétlődő) funkciókat, tulajdonságokat.
Az üzenet vagy kérés küldőjének függetlenítése a fogadótól. Megvalósítása felelősségláncok kialakításával történik. Lényegében egy láncolt lista, amin a kérelem végig halad mindaddig, amíg egy objektum le nem tudja kezelni.
Kérelmek objektumba ágyazása. Ezáltal a klienseknek különböző parancsokat adhatunk át, amit naplózhatunk, sorba rendezhetünk és a visszavonást kezelhetjük le. Azaz az egyes kérelmek teljesen kivizsgálhatóak és hatálytalaníthatók lesznek.
Több egymással kapcsolatot tartó objektum kommunikációjának egységbe (objektumba) zárása. Definiál egy interfészt, amin keresztül objektumokkal kommunikálhat.
Meghatároz ez egy-a-többhöz függőséget objektumok között. Egy adott objektum módosulásáról automatikus értesítő információt küld a tőle függő objektumoknak, amik ezek alapján frissülnek.
Egységbe zárt, azonos interfésszel rendelkező algoritmusok dinamikus cserélgetése. Lehetővé teszi, hogy az algoritmus az őt használó kliensektől függetlenül változzon.
Egy olyan objektum, amely segítségével zárolni lehet objektumokat, amíg inkonzisztens állapotban vannak. Monitorokat használva fellép a holtpont (deadlock) lehetősége.
Egy adott mennyiségű, sorban (queue) elhelyezett, előre legyártott szál, amelyekkel elkerülhető a szálak költséges legyártása és eltakarítása. Az Objektumkészlet minta egy speciális változata.
A tervminta dokumentációja leírja, hogy milyen körülmények között használták a mintát, milyen kényszerek formálták a körülményeket, és hogyan sikerült megoldani a helyzetet. A tervminták dokumentálására nincs egy szabványos forma; a különböző szerzők különféleképpen írták le őket. Azonban Martin Fowler úgy találta, hogy egyes formák népszerűbbek, mint mások; az új leírásokhoz ezeket ajánlja. Gammáék leírása ezek között van:
Név, osztályozás: Azonosításra alkalmas, leíró név.
Cél: Miért használjuk a mintát, mi célt szolgál.
Más nevek: Alternatív elnevezések.
Motiváció: Egy kontextusba ágyazott probléma, amit a tervmintával lehet megoldani.
Alkalmazhatóság: Milyen körülmények között használható a minta.
Szerkezet: A minta szerkezetének grafikus megjelenítése osztály- és interakciós diagramokkal.
Résztvevők: A mintában szereplő osztályok és objektumok leírása, szerepük meghatározása.
Együttműködés: Az interakciók leírása.
Következmények: Az eredmények, mellékhatások, előnyök és hátrányok kifejtése.
Implementáció: Az implementáció bemutatása.
Példa kód: A tervminta megvalósításának példája egy programozási nyelven.
Ismert használatok: A tervminta használata valós környezetben.
Rokon minták: Más, hasonló, kapcsolódó minták, és a tárgyalt minta összehasonlítása velük.
Elemzés
A tervmintákat többen is elemezték és kritizálták.
A tervmintákra többnyire azért van szükség, mert az adott programozási nyelven nem célszerű az adott problémát másként megoldani, vagy mert nincs egyszerűbb, átláthatóbb megoldás rá. Ez tekinthető az adott programozási nyelv hibájának is. Peter Norvig megmutatta, hogy Gammáék Design Patterns könyvében leírt 23 minta közül 16 egyszerűsíthető Lisp és Dylan nyelveken.[34] Hasonló megfigyeléseket tett Hannemann és Kiczales, akik AspektJ-ben, egy aspektusorientált nyelvben valósítottak meg tervmintákat. A kódszintű függőségeket a 23 közül 17-ből ki tudták küszöbölni, és megmutatták, hogy aspektusorientált programozással a minták egyszerűsíthetők.[35] Paul Graham az eredményeket egy esszében (Revenge of the Nerds) foglalta össze.[36]
↑Baroni, Aline Lúcia (2003. június 1.). „Design Patterns Formalization”, Nantes, Kiadó: École Nationale Supérieure des Techniques Industrielles et des Mines de Nantes.
↑Christian Nagel, Bill Evjen, Jay Glynn, Karli Watson, and Morgan Skinner. Event-based Asynchronous Pattern, Professional C# 2008. Wiley, 570–571. o. (2008). ISBN 0-470-19137-6
Ez a szócikk részben vagy egészben a Software design pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.
Ez a szócikk részben vagy egészben az Amelioration pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.