Špagetový kód

Špagetový kód je označení pro nevhodnou strukturu zdrojového kódu, která způsobuje jeho nesrozumitelnost a obtížnou udržovatelnost. Hlavní příčinou je nedisciplinované používání nestrukturovaných konstrukcí, jako jsou skoky, výjimky nebo vlákna, které vedou ke vzniku komplikovaných struktur. Podle úrovně programátora může být tentýž kód pro jednoho špagetový a pro druhého nikoli. Pojem špagetový kód tedy není vázaný na konkrétní návrhový vzor, např. spaghetti pattern.

Obecné ukazatele pro špagetový kód (může platit jedno i více ukazatelů): - je zcela nepochopitelný - je potřeba pochopit celý kód, abychom pochopili malou část programu

Špagetový kód a objektově orientované programování

Od objektově orientovaného programování se očekávalo že se problémy se špagetovým kódem vyřeší tím, že se programový kód rozdělí do menších objektů a tím pádem bude možné sledovat každou část programu odděleně a OOP nástroje pro využití tohoto principu poskytuje. Programování pomocí tříd však nemusí být nutně zárukou udržovatelného a přehledného kódu.

K častým ukazatelům špagetového kódu s použitím OOP jsou následující:

  • nekontrolovatelně mnoho stavových proměnných
  • stavové proměnné jsou zneužity jako mezipaměť
  • míchání různých zodpovědností v jedné a té samé třídě

Příklad

Jako příklad si můžeme uvést jednu a tu samou programátorskou úlohu, kterou se pokusíme vyřešit dvěma způsoby. Jelikož je úloha dostatnečně jednoduchá, jsou oba postupy docela pochopitelné, ale v případě že by se jednalo o složitější případ, je jasné, že jedno řešení je vhodnější než druhé. Nesprávný způsob se jmenuje SpaghettiCalculator a ten správný OOPCalculator. Kód je napsán v jazyce PHP.

SpaghettiCalculator

Třída SpaghettiCalculator se vyznačuje tím, že míchá data a business logic dohromady v jedné a té samé třídě. Metody nemají žádné vstupní ani výstupní parametry. Pokud chceme pomocí této třídy spustit výpočet metodou SpaghettiCalculator::complicatedCalculation je potřeba znát celou implementaci třídy.

<?php
class SpaghettiCalculator
{
 
    /**
     * @var int
     */
    protected $value1;
 
    /**
     * @var int
     */
    protected $value2;
 
    /**
     * @var int
     */
    public $plus;
 
    /**
     * @var int
     */
    public $minus;
 
    public function complicatedCalculation()
    {
        $this->prepareVariables();
        $this->plus  = $this->value1 + $this->value2;
        $this->minus = $this->value1 - $this->value2;
    }
 
    public function prepareVariables()
    {
        $this->value1 = 6;
        $this->value2 = 7;
    }
}

$spaghettiCalculator = new SpaghettiCalculator();
 
$spaghettiCalculator->complicatedCalculation();
 
echo $spaghettiCalculator->plus . PHP_EOL;
echo $spaghettiCalculator->minus;

OOP Calculator

Řešením je rozdělení třídy do více tříd s jasnou zodpovědností. Z hlediska OOP je vhodné rozdělit kód tak, abychom nemíchali data a business logic v jedné a té samé třídě. Metody by měly mít definované vstupní parametry a návratové hodnoty. Využívání stavových proměnných jako mezipaměť se doporučuje pouze při implementaci konkrétního návrhového vzoru. Pokud chceme spustit kalkulaci pomocí metody OOPCalculator::complicatedCalcualtion, je potřeba znát pouze implementaci datové struktury reprezentované třídou OutputData, jejíž instanci metoda vrací.

<?php
class InputData
{
 
    /**
     * @var int
     */
    public $value1;
 
    /**
     * @var int
     */
    public $value2;
}
 
class OutputData
{
 
    /**
     * @var int
     */
    public $plus;
 
    /**
     * @var int
     */
    public $minus;
}
 
class OOPCalculator
{
 
    /**
     * @return OutputData
     */
    public function complicatedCalculation()
    {
        $inputData         = $this->prepareInputData();
        $outputData        = new OutputData();
        $outputData->plus  = $inputData->value1 + $inputData->value2;
        $outputData->minus = $inputData->value1 - $inputData->value2;
        return $outputData;
    }
 
    /**
     * @return InputData
     */
    protected function prepareInputData()
    {
        $inputData         = new InputData();
        $inputData->value1 = 6;
        $inputData->value2 = 7;
        return $inputData;
    }
}
 
$oopCalculator = new OOPCalculator();
 
$result = $oopCalculator->complicatedCalculation();
 
echo $result->plus . PHP_EOL;
echo $result->minus;

Externí odkazy