Vývoj komplexného softvéru

Zdeno Jašek

15.02.2019

 Vlkolak je bežný človek, ktorý sa v noci náhle a nečakane premení na monštrum. Presne to sa deje aj pri vývoji softvéru: jedného dňa sa samotný proces vývoja softvéru zmení na monštrum. Každý zásah do softvéru je utrpením, oprava chyby spôsobí chyby ďalšie, termíny sa nedodržiavajú, rozpočty sa prekračujú, programátor si nemôže byť istý, kedy mu tá beštia zhltne víkend. A tak ako pri vlkolakovi pomáha strieborná guľka do srdca šelmy, kladú si programátori otázku, či podobnú striebornú guľku nemajú po ruke tiež.

Autorom prirovnania vývoja softvéru k vlkolakovi je Fred Brooks, šéf vývoja operačného systému pre mainframe IBM System/360. Vo svojej eseji „No Silver Bullet“ z roku 1975 tvrdí, že za problémy môžu štyri základné vlastnosti samotného softvéru: komplexita, adaptabilita, otvorenosť voči zmenám a nemožnosť softvér vizualizovať.

Tento článok je o prvej z vymenovaných vlastností: o komplexite softvéru.

Čo je to komplexita?

Systémy sa dajú z pohľadu náročnosti rozdeliť na tieto kategórie:

  1. jednoduchý – ľahko spoznateľný
  2. komplikovaný – ťažko spoznateľný
  3. komplexný – nedá sa celý spoznať, ale dá sa odhadnúť jeho správanie
  4. chaotický – nedá sa ani spoznať, ani odhadnúť jeho správanie
Zdroj: http://noop.nl/2008/08/simple-vs-complicated-vs-complex-vs-chaotic.html

Analógia s výstavbou domu

Dom je komplikovaný systém. Elektrina, voda a plyn musia byť precízne naplánované a zohľadnené v stavbe. Stavba podlieha fyzikálnym aj právnym zákonom, čo prináša ďalšie komplikácie.

Softvér je nielen komplikovaný, ale aj komplexný systém. Funkčnosť jednotlivých častí softvéru sa môže navzájom ovplyvňovať a vytvárať nové správanie, ktoré sa nedá spoznať len zo znalostí izolovaných častí. To je dôvod, prečo softvér vyžaduje testovanie celej funkčnosti. Ak by softvér nebol komplexný systém, stačilo by tvoriť unit testy. Otestovanie jednotlivých častí systému by garantovalo spoľahlivé fungovanie celého systému.

Na analógii s domom je práve vidieť, prečo dom nie je komplexný systém: po ukončení výstavby nie je nutné testovať kompletné scenáre použitia, čiže klásť si otázky ako:

  1. Funguje voda v kúpeľni po tom, čo bola použitá spálňa?
  2. Funguje elektrina v kúpeľni, keď tečie voda?
  3. Funguje kúrenie v kúpeľni, keď sa používa elektrina a voda?
  4. Funguje chladnička, keď sa predtým použila kúpeľňa a spálňa?

Takéto testy sa po dostavaní domu nerobia. Stačí, keď sa inžinieri ubezpečia, že funguje elektrina, voda, plyn atď., čiže otestujú jednotlivé časti domu. Nie je nutné testovať, či pustenie vody nespôsobí zablokovanie dverí.

Testy, ktoré v súvislosti s domom pôsobia smiešne, sa však pri vývoji softvéru robia. Dôvodom je práve fakt, že softvér je komplexný systém. Programátori nevedia, ako sa budú jednotlivé časti softvéru navzájom ovplyvňovať. Preto nestačí, keď si každý programátor otestuje svoj kus kódu. V sumáre môže komplexný systém vykazovať odlišné správanie.

Boj proti komplexite

Komplexita je nepríjemná vlastnosť softvéru, dá sa však previesť na komplikovanosť. Existuje na to niekoľko pomenovaných taktík na úrovni architektúry alebo vývoja softvéru:

  1. Application layering – rozbíjanie softvéru na vrstvu biznis logiky a prezentačnej logiky
  2. Microservices – rozbíjanie biznis logiky podľa doménového kontextu
  3. Clean architecture – rozbíjanie jedného modulu na technologickú a doménovú časť
  4. Domain module (z Domain-Driven Design) – rozbíjanie doménovej funkčnosti na skupiny súvisiacich entít
  5. Design Patterns – sada šikovných návodov na zvládnutie opakujúcich sa dizajnérskych problémov so zreteľom na redukciu komplexity
  6. Open/Close Principle – vytváranie otvorených mechanizmov na zmeny funkčnosti formou pridávania tried
  7. Single Responsibility Principle – rozbíjanie jednej triedy na viacero tried na základe zodpovednosti
  8. Side-effect free function – rozbíjanie jednej metódy na viacero metód na základe exaktne definovanej funkčnosti

Použitie každého z uvedených princípov znižuje komplexitu softvéru a súčasne zvyšuje jeho komplikovanosť. Čím je softvér komplexnejší, tým viac sa oplatí takáto investícia. Komplikovaný softvér je možné mať viac pod kontrolou ako komplexný softvér. Komplikované koncepty sa dajú kresliť a dokumentovať, komplexné nie – tie totiž nepoznáme.

Vymenované taktiky nie sú kompletné. Napríklad na prezentačnej vrstve sa veľmi úspešne využíva rozdelenie na model-view-controller s rôznymi obmenami apod.

Boj proti komplexite teda vedú vývojári na všetkých úrovniach softvéru: od veľmi hrubého konceptu architektúry (application layering, microservices), až po úrovne samotných tried či dokonca metód (single responsibility principle, side-effect free function). Každé zníženie komplexity má však svoju cenu – zvyšuje komplikovanosť softvéru. Preto treba vždy dôkladne zvážiť, ktoré taktiky je vhodné využiť pre vybrané zadanie a ktoré naopak vedú iba ku zbytočným komplikáciám.

Dôsledky komplexity na odhad softvéru

Komplexita spôsobuje problémy aj v odhadovaní nákladov na vývoj softvéru. Pri komplikovanom systéme je možné zostaviť podrobnú dekompozíciu celého systému na základe úplného poznania a následne odhadnúť každú jednu atomickú časť. Odhad na vybudovanie takéhoto systému je len prostý súčet odhadov jednotlivých častí systému. Pri komplexnom systéme je takýto postup nemožný, lebo systém nie je možné spoznať celý. Jednotlivé časti sa navzájom ovplyvňujú, čiže celkový systém je viac ako prostý súčet jeho častí. 

Rozšírené metodiky odhadovania vývoja softvéru (functional point analysis, use-case points) stavajú na získaných štatistických dátach z realizovaných projektov. Naproti tomu expertné odhady, ktoré sa snažia odhadnúť softvér na základe znalostí jednotlivých častí, sú obvykle optimistické, lebo ignorujú komplexitu systému. Expertné odhady fungujú iba pri odhadovaní komplikovaných častí softvéru, čiže typicky pri požiadavkách na zmenu do existujúceho systému. Samozrejme, s podmienkou, že komplexita existujúceho systému je na zvládnuteľnej úrovni. Občas sa totiž stáva, že softvér je už natoľko komplexný, že akákoľvek zmena vedie k nečakaným dôsledkom. V takých prípadoch vzniká potreba prepísať celý softvér nanovo.

Na klietku pre vlkolaka treba myslieť od začiatku

Komplexita sa na začiatku vývoja veľmi neprejavuje, preto vývojársky tím nepociťuje potrebu riešiť ju. Naopak: riešenie komplexity častokrát odmieta, pretože zvyšuje komplikovanosť vývoja a viditeľne navyšuje náklady na vývoj softvéru. A tak v jednu mesačnú noc sa vývoj softvéru zmení na hrôzostrašné monštrum. Každá zmena je zrazu trápenie, oprava chyby spôsobí chybu novú.

Komplexitu nie je možné zo softvéru odstrániť úplne, takže pomenované príznaky bude mať nutne každý softvér. Avšak uvedenými taktikami je možné komplexitu radikálne znížiť.

Fred Brooks napísal svoju esej pred štyridsiatimi rokmi. Vtedy vyslovil proroctvo známe ako „no silver bullet“: „But, as we look to the horizon of a decade hence, we see no silver bullet.“. Predpokladal, že v najbližších desiatich rokoch nenájde softvérový priemysel striebornú guľku, ktorou by porazil vlkolaka. Sotfvérový priemysel takúto zázračnú guľku dosiaľ nemá a zrejme ani mať nebude.

Vie však zavrieť vlkolaka do klietky.

Čítanie pre záujemcov:

http://noop.nl/2008/08/simple-vs-complicated-vs-complex-vs-chaotic.html
http://worrydream.com/refs/Brooks-NoSilverBullet.pdf
Zdroj: https://www.spe.org/en/twa/twa-article-detail/?art=2475

Ďalšie blog posty, čo by ťa mohli zaujímať