Miroslav Holec
Premium

Čistý kód a praktiky od vývojářů z Microsoftu

Miroslav Holec   16. února 2016  update 29. března 2016

Tento článek byl napsán v roce 2016. Vývojářské technologie se neustále inovují a článek již nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.

Vývojářský tým Microsoftu tráví poslední měsíce přepisováním celého .NET frameworku a to včetně řady souvisejících produktů (například Entity Frameworku). Protože je prakticky všechno související s .NET Core open source, má každý možnost insipirovat se tím, jak píše software vývojářský tým Microsoftu, jak má nastavené jmenné konvence a jaké používá nástroje pro řešení různých problémů. Nenechte se ale zkratovitě unést vidinou, že tak jak se píše kód v Microsoftu, se musí psát všude :)

Struktura adresářů

Skrze prakticky všemi projekty udržuje Microsoft jednotnou strukturu adresářů. V základu se tak setkáme s následujícími root adresáři (tučně jsou ty, které prakticky nikdy nechybí)

  • build (výstupy, nuget packages)
  • samples (příklady použití)
  • src (zdrojové kódy)
  • test (testy pro src)
  • tools (různé nástroje, executables

Samozřejmě u specifických projektů může být struktura jiná. Dost podobně to řeším i u současných solutions s tím, že pro zachování pořádku v solution reflektuji adresářovou strukturu pomocí solution folders.

Solution Folders

ReSharper

Při zkoumání kódu Entity Framework Core 1.0 jsem našel důkaz toho, že i vývojáři v Microsoftu používají pro zefektivnění práce ReSharper. Například snippet

public virtual ModelBuilder HasAnnotation([NotNull] string annotation, [NotNull] object value)
{
....

přímo používá namespace JetBrains.Annotations. Anotace v tomto případě umožňují zlepšovat schopnosti inspekce kódu. Scott Hanselman mi později potvrdil, že vývojářský tým Entity Frameworku v čele s Rowanem Millerem skutečně JetBrains nástroje používají. U ostatních týmů je to prý různé.

Jmenné konvence a best practices

Přestože většina jmenných konvencí je dnes již ustálená, v některých panují nekonečné rozepře napříč vývojářským .NET světem. Důvodem je samozřejmě velmi často souboj akademické správnosti a praktické použitelnosti nebo ignorace "chytrých" nástrojů jako ReSharper.

Projekty a NuGet balíčky

Microsoft se drží jednoduché konvence, kdy pro každý logický celek (službu / řešení) vytváří samostatný projekt. Je to něco, co hodně týmů opomíjí a místo toho snippety kódu pouze kopíruje do dalších solutions mezi aplikacemi. V jednu chvíli pak tým objeví a opraví bug, ale v dalších solutions bug stále zůstává.

Máte vlastní třídu, která má za úkol pracovat s obrázky? Udělejte z toho projekt. A následně NuGet balíček. Udržováním jednoho projektu a NuGetu si snadno zajistíte jeho aktuálnost ve všech solutions. Navíc obecné projekty můžete publikovat na GitHubu a nechat ostatní vývojáře, aby je nadále rozšiřovali nebo nasadili v praxi a odhalili další případné nedostatky.

Interface prefixing

Přestože mám rád knihu Clean Code od Uncle Boba a doporučuji ji každému přečíst, jsem zastáncem uvádět názvy interfaces s prefixem I. Je to vyloženě klíčová identifikace, která (například na rozdíl od privátních proměnných) má větší vliv na to, co je uvnitř třídy. A naštěstí stejně to vidí i vývojáři v Microsoftu.

public class ProductRepository : IProductRepository
{
}

Kolik zmatků by způsobilo, kdyby byl vývojář nucen interface pojmenovat jinak? A hlavně, jak?

Závorkování

Mohlo by se zdát, že čitelnost kódu zvýší menší počet řádků, ale opak je někdy pravdou. Přestože je možné jednořádkové podmínky (i cykly) nezavírat do složených závorek, konvence je to doporučená a vede k podstatně lepší čitelnosti:

if (SupportedEncodings.Count > 0)
{
    return SupportedEncodings[0];
}

Klíčové slovo this

Vývojáři v MS se snaží zachovat čistý a čitelný kód. Proto nepoužívají klíčové slovo this (pokud to není nevyhnutelně nutné). Největší problém je podle mého názoru notorické thisování všude kde to jde. Setkal jsem se s tím hned na několika projektech a nic se nevyrovná čistému:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

čili bez obskurního this.View();

Privátní proměnné

V případě inicializace proměnných skrze konstruktor tým MS upřednostňuje underscore notation a v podstatě všechny private proměnné zapisuje s podtržítkem. Je to mimochodem změna oproti posledním rokům, kdy se v kódu MS často objevovalo klíčové slovo this.

string _text = string.Empty;
public Neco(string text)
{
	_text = text;
}

Více na toto téma jsem psal v článku Válka dvou jmenných konvencí v C#, byť dnes už jsem zrovna k této konvenci podstatně tolerantnější a s underscore notation tak zásadní problém nemám.

Eliminace negativních scénářů

Spíše než o konvenci se jedná o styl vývoje, který při vykonávání kódu od shora eliminuje negativní scénáře a ukončí / přesměruje běh kódu někam jinam. Lze to vzít samozřejmě i z opačné stránky a naopak odklonit výkon kódu jinam, pokud je již daný problém vyřešen. Příkladem může být něco takového:

public Result DoSomething(MyClass instance)
{
	if (instance == null)
	{
		throw new ArgumentNullException();
	}

	var settings = settingsProvider.GetSettings();

	if (settings == null)
	{
		throw new ApplicationException();
	}

	var someObject = someRepository.GetById(instance.SomeId);

	if (someObject == null)
	{
		return Result.Error("Object is null");
	}

	return Result.Success(someObject);
}

Důležité je, že v tomto případě jsou různé související zdroje přinačítány nebo vykonány až pokud jsou eliminovány negativní scénáře. V příkladu se tedy nejprve ověří předaná instance třídy MyClass. Teprve pokud není NULL, má smysl pokusit se získat nastavení aplikace.

Bez regionů

Každý C# soubor (a zároveň třída) by měl držet jednotnou strukturu a pořadí typů členů od konstant, přes privátní proměnné, konstruktory, properties až po různé typy metod. Pak není problém se v souborech orientovat.

Regiony v C# jsou zbytečné, otravné a neměly vůbec nikdy vzniknout

Strukturu souborů dnes umí hlídat ReSharper, StyleCop i další extensions.

Var

Implicitní typování proměnných pomocí klíčového slova var používají vývojáři v Microsoftu velmi rádi (všude a na všechno). Mně osobně přijde zápis pomocí tohoto klíčového slova lepší až na případy primitivních typů. U nich nepřináší zkrácení názvu obvykle žádné výhody a naopak typ je lepší na první pohled vidět.

Závěr

V tomto článku jsem poukázal na několik zajímavých coding practices, které vývojáři v Microsoftu dodržují, dávají mi smysl, ale zároveň jsou často opomíjeny.

A jaké vývojářské praktiky při psaní kódu se osvědčily vám?