Jak psát „Čistý kód“ A hlavně se v něm pak neztratit Jan Pospíšil Senior Technology
SOLID SOLID: SRP - OCP - LSP - ISP - DIP SRP - Single Responsibility Principle OCP - Open Closed Principle LSP - Liskov Substitution Principle ISP - Interface Segregation Principle DIP - Dependency Inversion Principle IoC/DI - Inversion of Control/ D epen dency Injection
Single Responsibility Principle ● Blok kódu (třída, funkce) musí dělat jen jednu věc a dělat jí dobře. ● Počet public parametrů či atributů by neměl překročit 5. ● Funkci nebo třídu musí jít snadno, krátce a výstižně pojmenovat. ● Definice třídy, nebo kód fce by se měl vejít na jednu obrazovku a na první pohled musí být jasné co dělá. ● Jen jedna úroveň abstrakce.
Open Closed Principle ● Programové entity (třídy, moduly, funkce, apod.) by měly být otevřeny pro rozšiřování, ale uzavřeny pro modifikaci. ● Otevřený pro rozšiřování - Chování entity může být dále rozšiřováno. Tím je zajištěna reakce na změnu požadavků v aplikaci. Rešením je použití interface a proxy tříd. ● Uzavřený pro modifikaci - Zdrojový kód entity je nedotknutelný. Nikdo nemá povoleno kód změnit. Zejména kvůli dopadům v místech kde je kód použit. ● Navržené rozhraní musí být univerzální, ale minimalistické.
Liskov Substitution Principle ● Je-li třída B potomkem třídy A, pak musí být třída B použitelná všude, kde je vyžadována třída A bez toho, aniž by o tom nadřazená třída věděla. ● Rodiče lze kdekoliv nahradit potomkem, aniž by to způsobilo chybu. ● Odvozené třídy nesmí nikdy vyžadovat více a poskytovat méně než bázová třída. ● Tento princip neplatí u neveřejné dědičnosti.
Interface Segregation Principle ● Více menších specializovaných rozhraní je lepší než jedno velké generické rozhraní. ● Rozhraní musí být co nejmenší možné a třídy by neměly být nuceny používat rozhraní, která nepotřebují. ● Musí pomáhat porozumění abstrakce, ne komplikovat implementaci. ● Uživatelé třídy by pak měli záviset pouze na těch rozhraních, která používají. ● Rozhraní musí držet jen jeden business význam a jednu úroveň abstrakce.
Dependency Inversion Principle ● Konkrétní musí záviset na abstraktním, nikoliv naopak. ● Když třída potřebuje využít jinou třídu, deklaruje že bude potřebovat využívat dané rozhraní a o dodání implementace se postará vyšší moc. ● SOLIDní aplikace pak vypadá tak, že každá třída implementuje nějaké rozhraní a sama používá jiná rozhraní. ● Žádná třída nezná žádnou jinou třídu – ví jen o rozhraních.
Inversion of Control ● Spřažení objektů probíhá až při runtime. ● Běh programu je řízen interakcí instancí objektů mezi sebou na základě abstraktní mapy interakcí definované pomocí rozhraní. ● Obrácené řízení. Neřešíme běh programu, řešíme jen dílčí úlohy. ● Aplikaci reprezentuje kontainer dodaný FWem. ● Příkladem jsou WEB aplikace. Kontainerem je web server, který volá jednotlivé stránky dle URL pro obsloužení požadavku.
Dependency Injection ● DI odebírá třídám zodpovědnost za získávání objektů, hodnot a všeho co potřebují pro svou činnost. ● Constructor dependency Veškeré závislé objekty, hodnoty,... jsou předány jako parametry konstruktoru. ● Property dependency Veškeré závislé objekty, hodnoty,... jsou předány skrze public property.
Pište kód tak, jak byste ho chtěli dostat od ostatních.
Smysluplné pojmenovávání mdlMainMathConversionToIntegralTrue () mdlMainMathConversionTakeOutDecimal () Round() Trunc() Zaokrouhli() Orizni()
Smysluplné pojmenovávání public List GetAll(Item[] i) {{ List list1 = new List (); foreach (Item t in i) { if(t.crd < 8) { list1.Add(t); } return list1; }} public List GetAccountsHavingLowCredit(Account[] accounts) {{ List lowCreditAccounts =new List (); foreach (Account account in accounts) { if(account.Credit < AccountCreditThreshold) { lowCreditAccounts.Add(account); } return lowCreditAccounts; }}
Smysluplné pojmenovávání 0,O,1,l int 每周五天 = 5; Mix jazyků Maďarská notace, prefixy
Smysluplné pojmenovávání Názvy třídy by měly být podstatné jména Account, Customer, AddressParser Pozor na pojmenování Data, Info, Processor Názvy metod by měly být slovesa post..., delete..., save... get..., set..., is... Přetížené konstruktory Ideální je použití statických metod Complex.FromRealNumber(...)
Smysluplné pojmenovávání Používejte vždy jen jedno pojmenování pro stejnou věc fetch, retrieve, get controller, manager Definujte si kdo bude číst váš kód Používejte jen obecně známé termíny Pro združení parametrů je vhodné používat kontext addrFirstname, addrLastname, addrStreet, addrState...
Smysluplné pojmenovávání Vlastní složité konstrukce a pojmenování není znakem geniality, ale arogance.
Funkce Funkce max na 1 stránku (24x80) Bloky a odsazení Nebojte se rozložení Funkce by měla dělat jen jednu věc Zapomeňte že existuje SWITCH Lepší návratová hodnota, než výstupní parameter Bez vedlejších efektů Exceptions vs. Return Error Code
Neopakujte se Nikdy nepsat stejný kód dvakrát Problém hlavně kódu svázaného s UI a/nebo eventy Deklarace konstant Pokud se používají konstanty, mít je deklarované a ideálně v jediné statické třídě. Načítání konfigurace Jediná statická třída v aplikaci Jeden vstup, jeden výstup Každá fce by měla mít jen jeden výstup (jen jediné return)
Jan Pospíšil – Senior Technology