Připadá mi to jako divočina, hlavně mi vadí pleonasmy. Proč má v tom svém "správném přístupu" 2× slovo "hnuj", když stačí jedno?
Vidle.naber(hnuj)
Vidle.naber(seno)
Souhlas. Pokud jazyk umožňuje přetěžování metod/funkcí (např. Java ano, Céčko ne) tak tam nadbytečná slova taky nedávám. Líp se to čte a kód je kratší.
Nicméně v tom příkladu šlo o tu logiku, který objekt je aktivní a který pasivní a kde se nachází implementace. Jde třeba o různé ukládání nebo načítání – ať už do různých souborových formátů nebo třeba do databáze nebo odeslání na po síti. Ve většině případů považuji za špatný návrh to, aby ten datový objekt měl takovou metodu. Většinou patří spíš do jiného objektu, který se o de/serializaci příslušného formátu (PNG, XML atd.) nebo obsluhu příslušného úložiště a správu spojení stará. Je to pružnější návrh, který umožňuje přidávat další formáty a úložiště (i jiným autorům) a nezanáší to rozhraní toho objektu a nezvyšuje to komplexitu jeho implementace (v něm je jen metoda a kód pro vrácení nebo načtení nějaké kanonické implementace třeba RGB bitmapy, zatímco implementace jednotlivých kodeků je jinde).
Těch rozhraní bude víc - je to popsáno v SOLID. V každém z nich bude tolik metod, kolik bude třeba - klidně i jen jedna. Dělám to tak a nejsou s tím problémy. Dokonce se ta rozhraní pojmenovávají mnohem snáze, než kdyby tam těch metod bylo víc.
Ta doporučení a principy je dobré znát, ale aplikovat je až příliš „nábožensky“ je někdy na škodu. Podobné je to s novějšími konstrukty jazyka (třeba lambdy od Javy 8 ). Kolikrát si napíšu více variant kódu a porovnávám je, přemýšlím nad tím z hlediska čitelnosti, budoucího rozvoje, výkonu… někdy z toho vyjde, že to „modernější“ nebo „správnější“ řešení slouží hůře, je méně užitečné, méně praktické. Podobně člověk někdy poruší normální formy při návrhu databáze.
Připadá mi logické, když MouseAdapter extends Adapter. Otázkou samozřejmě je, zda takového předka potřebuji.
Ten Adapter v Javě je návrhový vzor nebo spíš jen konvence. Pokud má rozhraní více metod, tak se k němu dodá i pomocná abstraktní třída Adapter, která ty metody implementuje prázdné. Pokud programátor nechce implementovat všechny metody, ale třeba jen jednu, tak podědí tuhle třídu.
To rozhraní by samozřejmě šlo rozsekat na více menších, kde v každém bude jedna metoda. Ale přínos takto vysoké granularity je sporný až záporný. Taky už jsem párkrát návrh přehnal tímhle způsobem… nebo jsem používal cizí kód napsaný tímto způsobem – a byť je to teoreticky „správnější“ není to moc užitečné.
Je dobré nad tím přemýšlet i z hlediska strukturování… v tom odkazovaném článku o komplexitě taky píšu:
Je možné, že už jsme blízko hranice dané inherentní složitostí a další zjednodušení už není bez změny zadání možné. V tomto případě si můžeme ještě trochu pomoci přeskupením prvků. Člověk není stroj a jeho kognitivní schopnosti mají svoje limity. Millerovo magické číslo nám říká, že člověk dokáže udržet v krátkodobé paměti maximálně 7±2 prvků. Počítači je celkem jedno, kolik má program tříd, kolik má třída metod, výčtový typ členů nebo komponenta parametrů. Počítač zvládne hravě vykreslit na obrazovku desítky ikon nebo vyhodnotit desítky CLI parametrů u jednoho příkazu. Počítač často škáluje lineárně a vypořádá se i s velmi vysokým počtem prvků. U člověka se to ale na určité hranici láme a schopnost porozumět systému a pracovat s ním prudce klesá. Platí to pro programátory upravující software i pro uživatele, kteří ho mají používat. Samotnou změnou struktury tedy můžeme lidem trochu pomoci vypořádat se s komplexitou.
Jinak řečeno: příliš mnoho rozhraní, tříd, metod, souborů atd. může lidem zhoršovat schopnost orientace a pomůže strukturovat program jinak. Příčí se mi sice napsat „když máte ve třídě příliš mnoho metod, tak to rozdělte do víc tříd“ nebo „když máte v adresáři příliš mnoho rozhraní tak je rozdělte do víc adresářů nebo spojte více rozhraní do jednoho“ ale ve výsledku to tak trochu je.
Pak jsou i jiné možnosti jak to navrhnout. Třeba to rozhraní posluchače událostí může mít jednu metodu
přijmout(událost), do které budou chodit instance různých tříd nebo rozhraní a uvnitř té metody si pak vybereš, na co budeš reagovat. Ale to má zase jiná úskalí – kód bude méně přehledný (než u rozhraní s více metodami a Adapteru) a s dědičností/hierarchií/granularitou se sice nepotýkáme u rozhraní, ale u těch objektů reprezentujících události, takže jsme problém jen přesunuli jinam. Pro programátora-uživatele taky může být těžší dohledat, jaké všechny události mu tam můžou chodit (zatímco v jednom rozhraní vidí ty související metody vedle sebe – a až při případném rozšiřování rozhraní se udělá další, aby se nenarušila zpětná kompatibilita).