Skip to content

Kategória: Elvek

Interface Segregation Principle (ISP)

Miért?
Az olyan teljesítmény-leírások, melyek a konkrét megvalósítástól függetlenek, függetlenné tesznek.

Az Interface Segregation Principle (ISP) egy további SOLID elv. A Segregation azt jelenti, hogy leválasztás. Ez az elv azt mondja, hogy egy kliens ne függjön egy szerviz részleteitől, amelyekre neki nincs is szüksége. Minél kevesebb dolog található az interfészben, annál lazább a csatolás (coupling) a két komponens között.Gondoljunk csak bele, ha egy olyan dugaszt kellene terveznünk, amelyikkel egy monitort egy számítógépre lehet csatlakoztatni. Úgy döntünk, hogy minden jelet, amely egy számítógépben felléphet, egy dugaszon keresztül rendelkezésre bocsájtunk. Ennek ugyan lesz pár száz lába, de maximálisan rugalmas lesz. Sajnálatos módon ezzel a csatolás (coupling) is maximálissá válik.

A dugasz példáján nyilvánvaló, hogy egy monitor-összeköttetésnek csak azokat a jeleket kell tartalmaznia, amelyek egy kép ábrázolásához szükségesek. Ugyanez van a szoftver interfészeknél is. Ezeknek is a lehető legkisebbnek kellene lenniük, hogy elkerüljük a felesleges csatolást (coupling). És pont mint a monitordugasznál az interfésznek erős összetartásúnak (cohesion) kell lennie. Csak olyan dolgokat kellene tartalmaznia, amelyek szorosan összefüggnek.

Az Interface Segregation Principle alkalmazásához a két refaktorálás Extract interface és az Extract superclass áll rendelkezésre.

Dependency Inversion Principle

Miért?
A pontszerű tesztelésnek az osztályok elszigeteltsége a feltétele. Az elszigeteltség akkor lép fel, amikor az osztályoknak már nincsenek függőségeik implementációktól – sem futásidőben, sem fordításidőben. A konkrét függőségeket tehát a lehető legkésőbb kellene eldönteni. Lehetőleg futásidőben.

A Dependency Inversion Principle (DIP) is egy SOLID elv. A következőket mondja:
  • A high level osztályoknak nem szabad függniük a low level osztályoktól, hanem mindkettő interfészektől függjön.
  • Az interfészeknek nem szabad részletektől függniük, hanem a részleteknek kell az interfészektől.

Amennyiben egy high level osztály közvetlenül használ fel egy low level osztályt, akkor kettejük közt egy erős csatolás (coupling) keletkezik. Legkésőbb akkor ütközünk nehézségekbe, amikor megpróbáljuk tesztelni a high level osztályt. Ebből az okból a high level osztálynak egy interfésztől kell függnie, amit aztán a low level osztály implementál. Így a unit tesztnél a low level osztályt egy mockup helyetesítheti.

Három lehetőség mutatkozik arra, hogy az invertált absztrakt függőséget egy konkért objektummal a futásidőben feloldjuk:

  • konstruktor paraméter segítségével „kézzel”
  • Egy Inversion of Control Container (IoC Container) használatával, mint amilyen a Castle Windsor
  • Dependency Lookup

A sárga fokozaton egyelőre a függőséget a konstruktor paraméterében „fecskendezzük be”. Az elején ez a legegyszerűbb megoldás és egy csomó osztálynál egészen jól működik. Később a zöld fokozaton egy IoC konténert és dependency lookup-ot használunk majd.

Liskov Substitution Principle

Miért?
Akinek örökösökkel van dolga, nem akar meglepetéseket, ha ismeri az öröklőt.

A Liskov Substitution Principle (LSP) is egy SOLID elv. Azt írja elő, hogy az altípusoknak úgy kell viselkedniük, mint a alaptípusnak. Ez először banálisan hangzik. A kivételek (exception) példáján érthetővé válik, milyen problémák lépnek fel, ha ezt az elvet megsértik. Amennyiben az alaptípus egy eljárásának végrehajtásakor nem vált ki kivételt (exception), akkor az összes altípusnak is tartania kell magát ehhez a szabályhoz. Amennyiben az egyik altípus eljárása mégis kivételt (exception) vált ki, akkor ez gondot okoz olyan helyeken ahol egy alaptípusú objektumot használunk, mert ott nem vagyunk felkészülve erre. Ha az alaptípus ezen a helyen nem vált ki kivételt, akkor a használó nincsen felkészülve arra, hogy kivételt kell kezelnie.Általánosabban úgy is ki lehetne fejezni ezt az elvet, hogy az altípusnak csak kibővítenie szabad az alaptípus funkcionalitását, de korlátoznia nem. Amennyiben egy eljárás az alaposztályban egy értéktartományban van meghatározva, akkor az altípusnak ezt az értéktartományt szabad átvennie vagy bővítenie, de semmiképpen sem szabad korlátoznia.

A Liskov Substitution Principle-ből továbbá az az ajánlás következik, hogy alaposan gondoljuk át az öröklődést. A lehető legtöbb esetben a kompozíciót a öröklődéssel szemben előnyben kell részesíteni (Favor Composition over Inheritance). A öröklődésnél mindenképpen el kell gondolkodni a viselkedésről is, nem csak a struktúráról. Ahelyett, hogy a öröklődést mint egy is-a relációt tekintjük, és eközben csak az adatstruktúrára gondolunk, inkább egy behaves-as relációból kellene kiindulni és az osztály viselkedését figyelembe venni.

 

Principle of Least Astonishment

Miért?
Amikor egy komponens meglepő módon másképpen viselkedik, mint ahogyan várnánk, akkor a felhasználása feleslegesen komplikált és nagy a valószínűsége a hibának.

A szoftverfejlesztés nagy mértékben kreatív folyamat. Ebben a folyamatban fontos az, hogy a belemerüljünk az áramlatba (flow). Amikor elértük ezt az állapotot, akkor a kód már csak úgy dőlni fog. Az áramlat (flow) minden nemű zavara csak megszakításokhoz és végeredményben ahhoz vezet, hogy a rendelkezésre álló időben csak kevés kód jön létre, illetve a kód minősége nem lesz optimális. Mert a fejlesztőnek minden megszakítás után fel kell vennie a fonalat, és újra bekerülnie az áramlatba (flow). A meglepetések zavarok. Megszakításokhoz és hibákhoz vezetnek. Erre egy példa: Amennyiben a fejlesztői környezet úgy van beállítva, hogy a szokásos Ctrl-C billentyűkombináció teljesen más jelentéssel bír, akkor ez akadályozza a fejlesztőt. A fejlesztő minden esetre bosszankodni fog, hogy a „rossz” billentyűkombinációt nyomta meg. Ez akadályozza a kreatív munkát.A szoftvereket a lehető legkevesebb meglepetéssel kellene implementálni. Amikor egy GetValue() nevű lekérdező eljárás nem csak egy értéket ad vissza, hanem egyben a rendszer állapotát is megváltoztatja, akkor a fejlesztő ezt az eljárást a legjobb esetben is elkerüli, mivel furcsa meglepetésekkel számol. Rossz esetben viszont nem tűnik fel neki a furcsa viselkedés időben. (Az olyan lekérdező eljárások, melyek megváltoztatják az állapotot megszegik a Command Query Separation elvet). A tesztvezérelt fejlesztés elősegíti a meglepetésekben szegény interfészek készítését, mivel az interfészt a felhasználásának szemszögéből tervezik és implementálják.

Information Hiding Principle

Miért?
Azáltal, hogy egy interfész elrejti a részleteket, csökkennek a függőségek.

Egy interfész tervezésénél azt a kérdést kell feltegyük, hogy mely részleteknek kell látszódniuk kívül. És itt ne csak a programozástehnikai interfészekre gondoljunk, hanem minden egyéb olyan implicit felületre is, amit valamilyen komponens kifelé mutat. Minden osztály szükségszerűen mutat egy implicit felületet magáról – ez tartalmazza az összes kifelé látható részletet. Minél több részlet látszik kívülről, annál magasabb a csatolás (coupling) az osztály és a használói között. Amennyiben egy osztály használói egyszer már használnak egy részletet, akkor azt a részletet onnantól fogva már nehéz lesz megváltoztatni. Ez ellent mond a szoftver továbbfejleszthetőségének.