Co je abstrakce
Bronislav Klučka, 24. 5. 2025 19:38
Vývojáři používají slovo "abstrakce" běžně, nicméně často s omezeným chápáním významu. Pro většinu byl koncept abstrakce zastíněn jejím použitím v některých jazycích pro označení metody nebo třídy, která musí být děděna a přetížena. Stejně tak "použij abstrakci" pro spoustu developerů znamená "napiš abstraktní třídu".
Abstrakce je jednou z nejdůležitějších technik pro docílení decouplingu a stabilizaci veřejného rozhraní na všech úrovních.
Abstrakce: Způsob prezentace entity, který zachovává důležité atributy a skrývá implementační detaily. Abstrakce umožňuje řízení komplexity.
Fajn, pěkné, ale co to znamená? Například slovo "auto" představuje velmi dobrou abstrakci. Víte, co si pod tím představit, víte, co má dělat. Na druhou stranu je za tím slovem skrytá velká variabilita implementace jednotlivých prvků.
A špatná abstrakce? "Plynový pedál", pravděpodobně převzato z anglického "gas pedal". Specificky zmiňuje plyn, kolik takových aut dnes jezdí? Většina je na benzín, některé na naftu, jiné na elektřinu, tak proč "plynový pedál"? Tato špatná abstrakce vznikla tím, že se do názvu dostal implementační detail. "Brzda" tím netrpí – technologie se mění, ale to, co brzda dělá, zůstává stejné.
Příklady
/**
* Jednoduchý příklad
* --------------
* data mohou být uložena do databáze, do souboru, poslána po síti...
*/
repository.saveToDatabase(item); // ❌ leaking
repository.save(item); // ✅ Nice
/**
* Auth příklad
* ------------
* user je autentikován pomocí tokenu
*/
authModule.tokenExists(token); // ❌ leaking
/*
* Samotný stav "přihlášen" může vyžadovat více, než jen existenci tokenu
* - Token může existovat během registrace
* - Token může existovat během 2FA/MFA.
* Nicméně v těchto případech uživatel stále není finálně přihlášen
*/
authModule.isLoggedIn(token); // ✅ Nice
/**
* UI příklad
* ------------
* zkontrolovat, jestli uživatel kliknul na tab
*/
// ❌ leaking
const activeTab = tabs.find(tab => {
return (tab.left < X) && (tab.right > X) &&
(tab.top < Y) && (tab.bottom > Y)
}) ?? null;
// Předpokládáte, že záložky jsou obdélníkové
// ✅ Nice
const activeTab = tabs.getTabFromPoint({x: X, y: Y});
Pár pravidel
Podle čeho se rozhodnout, zda je abstrakce správná?
Je v názvu "co to dělá" místo "jak to dělá"?
Můžete změnit implementaci, aniž byste museli měnit způsob použití?
Pokud používáte cizí objekt, voláte jeho metodu místo zpracovávání jeho dat?
Pokud jste odpověděli "ano", pravděpodobně jste na správné cestě.