JE_25 - Pečlivě navrhujte podpisy metod

Tato rada je seskupením takových doporučení k vytváření API, které si nezasluhují své vlastní rady. Společně vám však pomohou vytvářet rozhraní API, která je snazší pochopit a používat a která jsou méně náchylná k chybám.

Názvy metod vybírejte s rozvahou. Názvy by vždy měly vyhovovat standardním konvencím vytváření názvů (rada 38). Vaším hlavním cílem by měla být volba takových názvů, které jsou pochopitelné a konzistentní s dalšími názvy v témže balíčku. Vaším druhotným cílem by měla být volba názvů podle širšího konsenzu, pokud nějaký existuje. Máte-li pochybnosti, podívejte se do API knihovny Javy. Třebaže je tu mnoho nesouladů - což je nevyhnutelné kvůli velikosti a rozsahu těchto knihoven - je tu také určitý soulad. Velmi hodnotným zdrojem je kniha Patrick Chan, The java Developers Almanac [Chan00], která obsahuje deklarace každé jednotlivé metody v knihovnách platformy Javy seřazené podle abecedy. Pokud například přemýšlíte, zda máte nějakou metodu nazvat remove nebo delete, pak vám zběžný pohled do rejstříku této knihy potvrdí, že správnou volbou je remove. Existují stovky metod, jejichž názvy začínají na remove, a jen několik málo těch, jejichž názvy začínají na delete.

Nepřehánějte to s poskytováním usnad�ujících metod. Každá metoda by měla "utáhnout sama sebe". Příliš mnoho metod činí třídu obtížně pochopitelnou, použitelnou, dokumentovatelnou, testovatelnou a spravovatelnou. Dvojnásobně to platí pro rozhraní, kde příliš mnoho metod komplikuje život implementátorům i uživatelům. Každé akci podporované vaším typem poskytněte nějakou plně funkční metodu. Zvažte poskytování "zkratky" nějaké operce jen v případě, bude-li se používat příliš často. Máte-li o tom pochybnosti, vynechte ji.

Vyhýbejte se dlouhým seznamům parametrů. Obvykle se za praktické maximum považují tři parametry a čím méně, tím lépe. Většina programátorů si nedokáže zapamatovat delší seznamy parametrů. Pokud tento limit překročí mnoho vašich metod, pak nebude vaše API použitelné bez neustálého listování jeho dokumentací. Zejména škodlivé jsou dlouhé seznamy typově stejných parametrů. Nejenže si uživatelé vašeho API nezapamatují pořadí paramterů, ale když chybně nějaké parametry zamění, jejich programy se přesto zkompilují a spustí. Jenom nebudou fungovat podle přání autorů.

Existují dvě techniky zkrácení příliš dlouhých seznamů parametrů. Jednou je rozdělit metodu na více metod, z nichž každá vyžaduje jen podmnožinu daných parametrů. Nebudete-li však opatrní, může to vést ke vzniku příliš mnoha ,etod, zárove� však může dojít k omezení pčtu metod zvýšením ortogonality. Zvažme například rozhraní java.util.List. Neposyktujte metody vyhledání prvního nebo posledního indexu nějakého prvku v podseznamu, protože obě by vyžadovaly tři parametry. Namísto toho poskytuje metodu subList, která přebírá dva parametry a vrací pohled na podseznam. Tuto metodu lze zkombinovat s metodami indexOf nebo lastIndexOf, z nichž každá má jen jeden parametr, a získat tak požadovanou funkčnost. Navíc lze metodu subList zkombinovat s libovolnou jinou metodou, která pracuje s instancí List, a vykonávat tak jakékoli výpočty s podseznamy. Výsledné API má velmi vysoký poměr síly k hmotnosti.

Druhá technika zkrácení příliš dlouhých seznamů parametrů spočívá ve vytvoření pomocných tříd obsahujících seskupení parametrů. Takové pomocné třídy jsou obvykle statickými členskými třídami (rada 18). Tato technika se doporučuje, pokud lze nějakou často se vyskytující sekvencí parametrů považovat za reprezentaci určité samostatné entity. Předpokládejme například, že píšeme třídu představující nějakou karetní hru, a že náhle zjistíme, že se neustále předává sekvence dvou parametrů představujících hodnotu a barvu karty. Naše API (i vnitřek naší třídy) by se pravděpodobně vylepšilo, pokud bychom přidali pomocnou třídu představující určitou kartu a nahradili každý výskyt dané sekvence parametrů jediným parametrem této pomocné třídy.

U typů parametrů dávejte přednost rozhraním před třídami. Kdykoli existuje příslušné rozhraní k definování nějakého parametru, použijte jej místo třídy implementující dané rozhraní. Nikdy například není zapotřebí napsat metodu přebírající jak vstup Hashtable - místo toho použijte Map. To vám umožní předávat Hashtable, HashMap, TreeMap, podmapu TreeMap nebo jakoukoli implementaci Map, která ještě ani není napsána. Použitím třídy namísto rozhraní omezujete svého klienta na určitou implementaci a vynucujete se zbytečnou a potenciálně náročnou operaci kopírování, pokud náhodou vstupní data existují v nějaké jiné formě.

Používejte funkční objekty soudně (rada 22). Existují určité jazyky, zejména se jedná o Smalltalk a různé dialekty jazyka Lisp, které podněcují takový styl programování, které je bohaté na objekty představující funkce aplikované na další objekty. Programátoři se zkušenostmi s těmito jazyky mohou mít tendenci přijmout podobný styl programování v programovacím jazyku Java, nejdená se však o nic dobrého. Nejsnáze lze funkční objekt vytvořit prostřenictvím anonymní třídy (rada 18), ale i to představuje některé syntaktické nešikovnosti a má svá omezení v síle i výkonnosti v porovnání s řádkovými řídícími konstrukcemi. Navíc proramovací styl, kdy neustále vytváříte funkční objekty a předáváte je z jedné metody do druhé, nespadá do hlavního proudu, takže jiní programátoři budou mít s pochopením vašeho kódu napsaném v takovém stylu problémy. Tím nechci říct, že funkční objekty nemají platná použití; jsou základem mnoha mocných vzorů návrhu, jakými jsou strategie [Gamma95, str. 315] a návštěvník [Gamma95, str. 331]. Funkční objekty je však zapotřebí používat s rozumem.