Soudržnost (informatika)
Soudržnost je v informatice způsob pro měření, jak vysoce je daný kus kódu zaměřený na specifickou funkcionalitu. Jedním ze základních pravidel moderního programování je tuto soudržnost maximalizovat. Cílem tohoto pravidla tedy je, aby každá vytvořená metoda dělala pouze takové operace, které směřují k předem danému výsledku metody, nikoliv však operace, které by měly být v jiné metodě či třídě. Čím více je vytvořený kód soudržný, tím lépe se nám s ním pracuje, výsledná aplikace je více flexibilní a kdokoliv po nás bude mít za úkol aplikaci rozšířit, bude pro něj snazší pochopit jednotlivé metody aplikace.
Druhy soudržnosti
Soudržnost v programování je rozdělena na několik typů. Jsou to:
- Náhodná soudržnost
Jednotlivé části komponenty jsou sdruženy do jedné, aniž by spolu měli cokoliv společného (běžné jsou třídy jako Utility, které obsahují pomocné metody)
- Logická soudržnost
Komponenty, které vykonávají podobné funkce jsou sdruženy v samostatné komponentě (StringUtils).
- Dočasná soudržnost
Sdruženy jsou komponenty, které jsou v určitý čas za běhu programu spouštěny pospolu.
- Procedurální soudržnost
Procedurální soudržnost je taková soudržnost, kde jsou seskupeny části, které jsou za běhu systému volány v předem dané posloupnosti.
- Komunikační soudržnost
Součásti modulu jsou seskupeny podle dat, se kterými pracují, tj. pracují nad stejnou bází dat.
- Sekvenční soudržnost
Sekvenční soudržnost je seskupení částí tak, jak na sebe navazují při předávání dat mezi sebou. Příkladem můžou být metody, které jsou jakýmsi řetězem a výstup jedné metody je vstupem druhé metody.
- Funkční soudržnost
Při funkční soudržnosti jsou seskupeny části, které společně přispívají k jednomu předem specifikovanému cíli.
Příklad nízké soudržnosti
Jednoduchou ukázkou málo soudržného kódu může být metoda report(), která zpracovává data a dále je exportuje do výsledného formátu, který je uložen na disk počítače. Už z tohoto popisu je možné vidět, že metoda má na starosti více rozličných úkolů, než jen jeden specifický. Taková metoda by mohla vypadat následovně:
public void report(ReportData data, boolean save, String path) {
String nameLine = data.getTitleBefore() + " " + data.getFirstName()
+ " " + data.getLastName() + ", " + data.getTitleAfter();
Integer score = data.getScore();
// dalsi zpracovani dat
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("candidates");
doc.appendChild(rootElement);
// ... tvorba struktury dokumentu
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result;
if(save) {
result = new StreamResult(new File("C:\\file.xml"));
} else {
result = new StreamResult(System.out);
}
transformer.transform(source, result);
} catch (Exception e) {
// osetreni vyjimky
}
}
Jak již bylo řečeno, tato metoda není soudržná. Na jednom místě se řeší vytvoření výsledné podoby dat pro report, tvorba struktury souboru a následně jeho vytvoření a uložení. Někomu se takováto metoda může zdát užitečná, přece jen umí hodně věcí, ale už podle názvu metody by obsah měl vypadat jinak. Názvy metod jsou velmi důležitým faktorem v soudržnosti. Předchozí metoda se jmenuje „report“, takže by kdokoliv mohl předpokládat, že metoda bude pouze zobrazovat výsledky. Místo toho ale metoda dělá spoustu jiných věcí. Další chybou v příkladě je delegování kontroly směrem dolů. Až uvnitř metody se řeší, zda bude výsledek uložen nebo jen zobrazen uživateli. Takováto rozhodnutí by měla být prováděna o stupeň výš, ne být součástí jedné obecné metody. Jak tedy z takovéto nesoudržné metody udělat soudržnou? Řešení je jednoduché – rozdělit metodu na nezávislé metody, které budou odpovědné pouze za jednu specifickou funkci. V našem případě bychom mohli vytvořit metody processData(), createXMLStructure(), saveFile() a printFile(). Každá z těchto metod dělá přesně to, co se od ní očekává a co koresponduje s jejím názvem.
Vysoká soudržnost a počet metod
V předchozím příkladě je ukázáno, jak by to při tvorbě metod vypadat nemělo a je nastíněno správné řešení. Může ale dojít také k situaci, kdy třída obsahuje sice samé vysoce soudržné metody, ale je jich příliš mnoho a tím se stává nepoužitelnou. Při navrhování metod by se měly dodržovat dvě základní pravidla – maximalizovat soudržnost a nepředávat kontrolu metodám na nižším stupni. Někdy to však není možné a v těchto případech je občas nutné jedno z pravidel porušit, běžné je však i porušení obou pravidel. Dobrým příkladem pro tento případ může být metoda pro zpracování stisku tlačítka. Metoda jako parametr dostane tlačítko, které bylo stisknuto a to poté zpracuje. Pokud takovouto metodu implementujeme přes switch(key) a dále pro každé tlačítko máme case příkaz, takováto metoda je jednoduše čitelná, stejně jako v případě, kde bychom měli pro všechna tlačítka vlastní metody handleAButton() atd.
public void keyPressed(KeyEvent ke){
switch (ke.getKeyCode()) {
case KeyEvent.VK_A:
// zpracuj tlačítko A
break;
case KeyEvent.VK_B:
// zpracuj tlačítko B
break;
// další tlačítka
default:
break;
}
}
Na tomto příkladu je vidět, že dodržovat pravidla soudržnosti je dobré, ale programátor by se především měl řídit zdravým rozumem, jinak se může jednoduše stát, že kvůli soudržnosti nám vzniknou třídy s desítkami metod, což ne vždy vede k nejlepším výsledkům.
Shrnutí
Soudržnost má své právoplatné místo v programování a snažit se maximalizovat soudržnost je výhodné z více hledisek. Díky soudržnosti a správnému pojmenovávání metod je kód srozumitelný i pro lidi, kteří ho po vás převezmou. Zároveň je takovýto kód snadno udržovatelný a flexibilní. Přesto je tato metoda měření subjektivní a nemá představovat univerzální návod, jak správně psát metody.