SOLID principy: Princip odděleného rozhraní
Michal KatuščákPrincip odděleného rozhraní je definované Robertem C. Martinem původně pro Xerox a říká:
Více specifických rozhraní je lepší než jedno obecné rozhraní.
Při jeho dodržování se kód stává více znovupoužitelný a užitečný. Pokud je více tříd nuceno implementovat rozhraní s metodami, které nepotřebují, je vhodné najít logický průnik (v čem se shodují) a rozhraní oddělit.
Video (1:29)
Na ukázku zde mám rozhraní IBag, třídu Bag, která jej implementuje a třídu Renderer:
<?php
interface IBag {
    public function setContent(string $content);
    public function appendContent(string $content);
    public function prependContent(string $content);
    public function getContent(string $content);
    public function loadFromFile(string $file);
    public function saveToFile(string $file);
    public function render(): string;
}
class Bag implements IBag
{
    private $content;
    public function setContent(string $content)
    {
        $this->content = $content;
    }
    public function appendContent(string $content)
    {
        $this->content = $this->content . $content;
    }
    public function prependContent(string $content)
    {
        $this->content = $content . $this->content;
    }
    public function getContent(string $content)
    {
        return $content;
    }
    public function loadFromFile(string $file)
    {
        if (!file_exists($file)) {
            throw new InvalidArgumentException("File from argument not exists.");
        }
        $this->content = file_get_contents($file);
    }
    public function saveToFile(string $file)
    {
        if (!file_exists($file)) {
            throw new InvalidArgumentException("File from argument not exists.");
        }
        return file_put_contents($file, $this->content);
    }
    public function render(): string
    {
        return "Content: " . $this->content;
    }
}
class Renderer
{
    public function render(IBag $bag)
    {
        echo $bag->render();
    }
}Větší interface IBag mohu rozdělit na tři logické rozhraní: Contentable, Fileable, Renderable.
Třída Renderer tak už není nucena záviset na IBag, ale postačí Renderable. Třída Bag implementuje všechny tři rozhraní, ale další třídě může stačit už jenom třeba jedno.
<?php
interface Renderable {
    public function render(): string;
}
interface Contentable
{
    public function setContent(string $content);
    public function appendContent(string $content);
    public function prependContent(string $content);
    public function getContent(string $content);
}
interface Fileable
{
    public function loadFromFile(string $file);
    public function saveToFile(string $file);
}
class Bag implements Renderable, Contentable, Fileable
{
    private $content;
    public function setContent(string $content)
    {
        $this->content = $content;
    }
    public function appendContent(string $content)
    {
        $this->content = $this->content . $content;
    }
    public function prependContent(string $content)
    {
        $this->content = $content . $this->content;
    }
    public function getContent(string $content)
    {
        return $content;
    }
    public function loadFromFile(string $file)
    {
        if (!file_exists($file)) {
            throw new InvalidArgumentException("File from argument not exists.");
        }
        $this->content = file_get_contents($file);
    }
    public function saveToFile(string $file)
    {
        if (!file_exists($file)) {
            throw new InvalidArgumentException("File from argument not exists.");
        }
        return file_put_contents($file, $this->content);
    }
    public function render(): string
    {
        return "Content: " . $this->content;
    }
}
class Renderer
{
    public function render(Renderable $bag)
    {
        echo $bag->render();
    }
}Jako u všech zásad je potřeba dbát na to, aby to nebylo přehnané. Aby nás pak nestrašily třídy se stovkou rozhraní. :)
