Skip to content

Kategória: Elvek

A terv (architecture) és az implementáció nem fedik egymást

Miért?
Azok a tervezési iratok, amelyek a megvalósítással nincsenek összhangban, többet ártanak, mint használnak. Ezért nem a tervezést kell feladni, hanem az inkozisztencia esélyét kell minimalizálni.

A szoftverfejlesztés egyik legalapvetőbb problémáját jelentik az olyan implementációk, melyeken nem lehet látni, hogy előre meg lettek tervezve. Ilyenkor tervezési diagrammok lógnak a falon, melyeknek már alig van köze a kód valóságához. Ennek az oka a legalapvetőbb DRY elv megsértése: A terv és az implementáció ismétlődései ugyanannak a dolognak, mégpedig a szoftver struktúrájának. Mivel az implementáció a tervezést követi, és a munka dandárját jelenti, ezért mindkettő gyorsan kilép az összhangból, amennyiben a struktúra implementáció alatti változásait nem vezetjük be újra és újra a tervbe. A tervezési diagramoknak az implementáció kezdete után nem sokkal már nincsen semmi értékük.

Hogyan lehet javítani a szituáción? Fel kellene hagyni a tervezéssel, ha végülis az implementációban él a „struktúra valósága”? Nem, biztosan nem. A tervezésre szükség van. Tervezés nélkül nincsen elképzelésünk a célról. De a tervnek és az implementációnak meg kell felelnie a DRY elvnek. Ezért a tervezésnek és az implementációnak, amennyire csak lehet, nem szabad egymást fednie. Az interfészüknek vékonynak kell lennie. Amikor ez igaz, akkor már nem egymás ismétlődései, hanem különböző dolgokat írnak le. Ez azt jelenti, hogy: A terv/architektúra nem törődik az implementációval és az implementáció nem törődik az architektúrával.

És hol van a választóvonal? Az úgynevezett komponenseknél (lásd lent praktikákat). Az architekt nem törődik a komponensek belső felépítésével. Az architekt számára ezek fekete dobozok, melyek osztálystruktúrája nem architektúra-releváns. Fordítva viszont a komponens implementálójának az architektúra irreleváns. Amit neki implementálnia kell, az a komponensének importált és exportált szerződéseiből derül ki számára. Nem kell ennél nagyobb összefüggéseket ismernie.

Az architektúra feladata ezáltal az is, hogy a szoftvert komponensekre bontsa, azok függőségeit meghatározza és a szerződések teljesítéseit leírja. Ezeket a struktúrákat aztán csakis az architektek fogják gondozni. És az implementáció feladata az architektúra által meghatározott komponensek megvalósítása. Hogy hogyan teszik ezt, az nem architektúra-releváns. A komponensek belső struktúrája az architektúra számára láthatatlan.

Az implementáció tükrözi a tervet

Miért?
Az olyan megvalósítás, amely tetszés szerint eltérhet a tervtől, egyenes úton vezet a karbantarthatatlanságba. A megvalósításnak szüksége van egy terv által meghatározott fizikai keretre.

Az architektúrának és az implementációnak nem kellene fednie egymást, hogy a DRY elvet betartsuk. Így lehet elkerülni az inkozisztenciát, ami az által léphetne fel, hogy az egyik oldalon megváltozik valami anélkül, hogy a másik oldalon ezeket a változásokat követnénk.Mindennek ellenére az architektúra tesz kijelentésket az implementációról. Nem a részleteiről, hanem az alapvető formájáról. Az architektúra határozza meg a struktúra elemeit és azok viszonyát egy kódrendszeren belül. Az implementáció tehát az átfedések hiányában sem létezhet függetlenül az architektúrától, hanem inkább csak benne.

Éppen ennek kell megjelennie az implementációban. Így könnyebben érthető lesz, így könnyebben lehet biztosítani, hogy az implementáció tényleg kövesse az architektúrát. Az architektúra által különböző absztrakciós szinten meghatározott struktúra elemeknek ezért nem kellene egy nagy „kódvödörbe” (pl. egy nagy Visual Studio solution) „összevonásra kerülniük”. Sokkal jobb, már csak a magas produktivitás és a tesztelhetősg érdekében is, az architektúra logikai struktúráit a lehető legfizikaibb módon megjeleníteni.

  1. Az architektúra által különböző absztrakciós szintre tervezett struktúráknak amennyire csak lehet tükröződniük kell a kód elrendezésben. Ez egyik oldalon azt jelenti, hogy az architektúra mint struktúra elemeket elsősorban fizikai kódegységeket használ. És a másik oldalon ezeknek a struktúraelemeknek a forráskódban ill. a repository kód elrendezésében tisztán kivehetőnek kell lenniük.
  2. A struktúraelemek implementációja közben és különösen a komponensek belsejében lehetetlennek kell lenniük az „mellékes” architektúraváltoztatásoknak. Aki egy struktúraelemben vagy elemen dolgozik, tehát egy részen, annak nem szabad ad hoc megváltoztatnia a környező struktúrát, tehát az egészet. Csak amikor ez biztosítva van, akkor nem fog kontrollálatlanul nőni a szoftver entrópiája. Ez fontos, mert az architektúra fő célja, a szoftver entrópiájának és ezzel a komplexitásának minimalizálása.

A tervezésre szükség van. Az implementációnak nem szabad megtorpedóznia a tervezést. (Természetes, ha az implementáció felismerései visszahathatnak a tervezésre.) Ezért kell a tervezést és az implementációt szétválasztani. És ahol ez nem lehetséges, ott a tervezésnek az implementáció eszközeivel kellene dolgoznia és az implementációnak a tervezést fizikailag tükröznie kell.

You Ain´t Gonna Need It (YAGNI)

Miért?
Az olyan dolgok, amikre senkinek nincsen szüksége, azok értéktelenek. Ne pazaroljunk rá tehát időt.

A YAGNI elv (You Ain´t Gonna Need It) a szoftverfejlesztés egyik legegyszerűbb – és a DRY elv után leggyakrabban megsértett elve. Ezért a YAGNI nem csak a piros fokozat elején áll, hanem itt, az értékrendszeren keresztül vezető útnak majdnem a végén is.A YAGNI szabály a követelménypontosságból és a termék materialitásának a szoftverfejlesztésben különleges viszonyából alakult ki. A követelmények notorikusan pontatlanok vagy váltakozók, a termék pedig, amiben meg kellene valósulniuk, immateriális. Összehasonlítva a gépészettel vagy az építészettel az anyag végtelenszer rugalmasabb és elvileg viszonylag kevés ráfordítással szinte minden követelményhez hozzá lehet igazítani. Magas illékonyság ill. pontatlanság tehát nagy rugalmasságra talál. Ez elsőre ideálisnak tűnhet.

A gyakorlat azonban azt mutatja, hogy pontosan ebben az arányban rejlik sok projekt sikertelenségének magja. Rövidtávon a figyelve a projektek megpróbálják a legkézenfekvőbbel a helyes dolgot tenni:

  • A pontatlan követelményeket gyakran olyan termékek kompenzálják, melyek megkísérlik a pontatlanságot kompenzálni. A szoftver immaterialitását arra használják, hogy olyan szélesen és rugalmasan implementáljanak, hogy a még ismeretlen vagy elmosódó követelményeket már quasi előresiető engedelmességel kielégítsék.
  • A folyamatosan változó követelmények a termékben a lehető leggyorsabban bevezetésre kerülnek, mert ez az immaterialitásának köszönhetően lehetséges.

Hosszútávon azonban az ilyen viselkedés kontraproduktív:

  • Az előresiető engedelmesség szélességhez és rugalmassághoz vezet, amelyekre nincsen valóban szükség. Olyan feature-öket valósít meg, amelyeket később nem használnak.
  • A szoftver gyors átépítése a változós követelményeknek megfelelően a kód minőségének eróziójához vezet. A szoftver ugyan immateriális és rugalmas – de nem minden szoftverstruktúra továbbfejleszthető vagy csak érthető.

Zavaros és változó követelményszituációk az szoftver alapvető rugalmasságának háttere előtt gyorsan vezetnek felesleges többletköltségekhez és merev kódhoz. Sok olyan projekt, amelyik messze túllépte a költségeit, és még több olyan projekt, amely pár év elteltével karbantarthatatlanná vált, bizonyítja ezt.

A Clean Code fejlesztőknek, mint professzionális szoftverfejlesztőknek nap mint nap ellen kell állniuk az ilyen fejleményeknek. A szoftver tagadhatatlan természete miatt – immateriális és az is marad – ezt a követelményekkel való bánásmódnál lehet megfogni. Ez a YAGNI szabály forrása.

A YAGNI szabály olyan, mint egy éles kés: Aki használja, az egy problémát a közvetlenül szükséges elemek kicsi kockáira vág. A YAGNI szabály szerint csak a kétségtelenül és közvetlenül hasznot hozó dolgok kerülnek implementálásra. Minden egyéb… azt majd később. Ilyen tekintetben a YAGNI kéz a kézben jár a Lean Software Development„dönts a lehető legkésőbb” szabályával.

A YAGNI szabály a szoftverfejlesztés minden síkján és minden fázisában releváns. Bármikor, amikor azt kérdezzük magunktól, hogy „Szükség van-e erre a ráfordításra?” vagy „Szükségünk van erre valóban?” – és jöjjön ez akár egészen elnyomva agyunk leghátsó zugaiból – akkor ez a YAGNI szabály egy használati esete. A következőket mondja: Ha kétségeid vannak, akkor dönts a ráfordítás ellen.

Könnyűnek tűnhet, de nehéz. Innen adódnak a gyakori megszegései. Sok erő létezik, mely a ráfordítás elleni döntésnek ellentmond. „Nem is olyan nagy ráfordítás” vagy „Ha most nem gondolkodunk előre, akkor a jövőben nem fogunk tudni változtatni” ez csak két kézenfenkő magyarázat a ráfordítás megindoklására, akkor is, ha kétségek merülnek fel a hasznosságát illetően. Ez a architektúradöntéseket is érinti (pl. El kellene-e már most kezdeni a megosztott architektúrát, akkor is, ha a mai terhelésnél ez még nem szükséges?) és a lokális döntéseket is (pl. Kell-e már most optimalizálni az algoritmust, akkor is, ha pillanatnyilag nem okoz architektúraproblémákat?).

A megrendelő csak a közvetlen haszonért fizet. Az amit ma nem tud világosan specifikálni, az nem használ neki. Ezt az implementálásnál előre látni akarni, ráfordítást fektet be, haszon generálása nélkül. Amikor a megrendelő később pontosabban tudja, hogy mit is akar, akkor – és nem korábban! – eljött az ideje annak, hogy kielégítsük az akaratát. Amikor azonban egy projekt soron kívűl próbálja ezt az akaratot kielégíteni, akkor azt kockáztatja, hogy a megrendelő holnapi akaratával ennek ellent fog mondani. Egy olyan feature – funkcionális vagy nem funkcionális – amit ma világos követelmény nélkül implementálnak, az a megrendelőt holnap talán már nem is érdekli. Vagy talán már nem lesz neki annyira fontos, mint egy másik feature.

Ez a szoftverfejlesztés számára a következőket jelenti:

  • Kizárólag a világos követelményeket szabad implementálni.
  • A megrendelő priorizálja a világos követelményeit.
  • A világos követelményeket kell a prioritásuk sorrendjében megvalósítani.
  • A fejlesztési folyamatot és a kód struktúráját nagyban és kicsiben úgy kell kialakítani, hogy ne ébredjen félelem a változó és új követelmények megvalósítása iránt.

A Clean Code fejlesztők, mint professzionális fejlesztők a megrendelő felé ezt az eljárást félreérthetetlenül kommunikálják. Ezáltal:

  • szolgáltatásszelleművé válunk, hiszen nem kell elutasítanunk a megrendelő egyetlen világos követelményét sem
  • felelősségteljessé válunk, mert a büdzsét csak a világosan megfogalmazott haszon érdekében használjuk
  • védelmezővé válunk a kóddal szemben, mert megóvjuk a végeredményben szükségtelen dolgokkal történő túlpakolástól.

A YAGNI ezért nem csak egy olyan szabály, amit minden fejlesztőnek be kellene tartania, hanem projekteknek és teameknek a szabálya, tehát szervezeti szinteken. A YAGNI ugyanúgy mindig használandó, mint a DRY. Kétség esetén, ha lehetséges halaszd el a döntést. Különben dönts a ráfordítás ellen. Ez feszültségtől mentesít, salaktalanít és gyors sikerhez vezet.