Jedni ich nie lubią wcale, ja regiony sobie chwalę.
Nie mam zamiaru nikogo indoktrynować. Nie mam zamiaru dyskutować o wyższości tego nad tym i owego nad tamtym. Zamierzam natomiast przedstawić parę zalet regionów oraz powód, dla którego podobają się właśnie mi.
A skoro już zdradziłem, że wpis jest subiektywny i tendencyjny ;), to zacznę właśnie od tego powodu.
Z urodzenia jestem pascalowcem, czyli był to pierwszy język, w którym zacząłem programować. Miałem też krótki i przelotny romans z C++, z racji jego wykładania na studiach. Niestety fascynację pewnymi jego przymiotami szybko zdeprecjonował bezmiar jego ekstrawagancji – to nie był związek dla mnie. Aż pojawił się C#, który był bardzie stonowany, a już na pewno nie ekstrawagancki. Dodatkowo był nowoczesny, szczególnie w kwestiach obiektowych, zaś pascalowej obiektowości brakowało subtelności, odnosiło się wrażenie, że jest w nim niczym proteza.
Pascal miał jednak jedną, niezaprzeczalną – zastrzegam, że dla mnie – zaletę: uporządkowany kod. Deklaracje typów, stałych i zmiennych były oddzielone od samych instrukcji przetwarzania, co dawało rozpoznawalną schematyczność kodu, tworzyło jego mapę. Podświadomie programista dążył do zgodności z tą schematycznością i grupował oddzielnie właściwości i oddzielnie metody, same te grupy zaś dzieląc dodatkowo wg zakresu widzialności ich elementów (w pascalu nie trzeba powtarzać modyfikatorów public, private, ich działanie obowiązuje dopóki nie nastąpi użycie innego z modyfikatorów zakresu). Krótko mówiąc w kodzie panował porządek, naturalnym było, że najpierw wystąpią deklaracje stałych, które są niezbędne do definiowania typów, potem zaś deklaracje typów, być może kolejne stałe, a potem zmienne globalne i wreszcie deklaracje procedur, funkcji oraz program główny. Ponieważ kod pascala zakładał, że nie może w nim wystąpić nic, co nie zostało dotychczas zdefiniowane, kod zaczynał się od najbardziej prymitywnych bytów, by skończyć na tych, które z owych prymitywów korzystały.
Inaczej ma się jednak sprawa w C# – tu można układać kod dowolnie, m.in. mieszać deklarację zmiennych i kodu na nich operującego, ale to akurat nie jest niedogodnością. Rzecz w tym, że w obrębie klasy można np. zdefiniować pole, zaraz po nim jakąś prywatną metodę, a potem … no dobrze niech teraz będzie konstruktor … o potrzebna jest właściwość i jeszcze pole do metody, która będzie za chwilę. Mnie osobiście ciężko było się w czymś takim połapać. Pewnie wynikało to z przyzwyczajenia do uporządkowania kodu, ale możliwe (liczę tutaj na odzew w komentarzach), nie o przyzwyczajenia tu chodzi, lecz o potrzebę porządku jako taką.
I tutaj z pomocą przyszły regiony. Wystarczyło bowiem stworzyć sobie chociażby taki szablon:
#region konstruktory #endregion #region właściwości #endregion #region metody #endregion #region zdarzenia #endregion #region pola #endregion #region stałe #endregion
aby uzyskać zawsze taki sam układ kodu. W ten sposób każdy programista w zespole umieści pola w tym samym miejscu (tutaj na końcu kodu klasy) nie musząc pamiętać, gdzie powinny się one znajdować (tj. na końcu, na początku, przed właściwościami, po właściwościach, itp.). To właśnie jedna z zalet regionów – pozwalają one utrzymać porządek w kodzie. Wszystko zgodnie z ustaloną mapą.
Drugą zaletą jest to, że można grupować metody bądź właściwości o pewnym konkretnym przeznaczeniu. Tak jest w przypadku implementacji interfejsów. Jeżeli klasa implementuje jakiś interfejs, to zazwyczaj jego składowe nie są obejmują kompletu metod i właściwości tejże klasy, ale jedynie pewien wybrany jej fragment. Zatem region doskonale nadaje się do tego, aby kod taki odpowiednio wyróżnić. Pozostaje tylko kwestia ustalenia, czy podział nadrzędny dotyczy rodzajów elementów kodu (czyli tak jak w przykładzie powyżej) czy np. najpierw dzielimy kod na klasowy i interfejsowy, a potem na metody, właściwości, pola, itd.
Kolejna zaleta to możliwość otoczenia w metodzie kodu, który jako całość odpowiada za jakieś działanie. I – co ważne, zaznaczam – nie jest to kod, który da lub opłaca się wyodrębnić do oddzielnej metody (bo np. wówczas trzeba by było tylko dla tego kodu wyodrębnić zmienne lokalne do pól klasy).
Jeszcze jedna przydatna funkcja regionów to możliwości zawarcia w kodzie (np. na jego końcu) pewnych informacji w postaci tekstowej, które rozszerzają wiedzę programisty na temat danego pliku z kodem źródłowym, bez konieczności odwoływania się do dokumentacji. Może on sobie pozostawać zwinięty w regionie nie utrudniając czytania kodu.
Oczywiście jest też ciemna strona mocy ;). To oczywiście wykorzystanie regionów do celu, do którego powinny zostać użyte zasady SOLID. Ale tak to już z narzędziami bywa – wszystko zależy od ich użytkownika. Jak to mówią – daj małpie brzytwę to się pokaleczy ;).