Kochasz pisać kod? Ja tak, uwielbiam. Jest to pewny rodzaj sztuki. Sztuki komunikacji człowieka z komputerem. Sztuki czytelności naszej komunikacji. Sztuki przejrzystości. Sztuki architektury. Sztuki minimalizacji. Sztuki napisania/opowiedzenia wszystkiego w jak najkrótszej możliwej formie.
Osiągniecie większości efektów zajmuje czas – naszej praktyki, prób i błędów. Im więcej piszemy tym lepiej potrafimy pewne rzeczy opisać. Praktyka czyni z nas mistrzów – lokalnych, regionalnych, światowych. A im więcej czasu spędzamy z kodem, tym bardziej dążymy do minimalizmu – to przejrzystości, łatwości przyswajania i czystości kod.
Czasami jednak w dążeniu do perfekcji gubimy się. Tracimy horyzont. Zaczynamy inaczej postrzegać pewne hasła, wzorce, zalecenia. Jednym z takich zaleceń/wzorców jest Don’t Repeat Yourself (DRY). Bardzo często traktujemy to jako wyznacznik, czyli jak napiszemy raz pewny kod pobierający dane z bazy to możliwe, że to będziemy chcieli wykorzystać go w innym miejscu. Zaczynamy jak szaleni wyciągać wszystko przed nawias twierdząc, że tak trzeba, nie rozumiejąc co tak naprawdę siedzi pod powtarzalnością. Często patrzymy na nasz kod dostępu do danych, logiki w danym miejscu, logiki w kontrolerze itp. i wyciągamy to tak by “się kod nie powtarzał”.
Popełniamy wtedy błąd, wyciągamy coś co jest specyficzne dla danego kontrolera w danej chwili. Sądząc, że to się nie zmieni i że wszystkie kontrolery będą się tak samo zachowywać. Nic bardziej mylnego. W każdej chwili dany kontroler może będzie musiał zwracać inaczej dane? Wykonać inne zadanie? To się może zmienić. I ma prawo się zmienić. A skoro może i ma prawo, to się zmieni :)
Zaś to co jest w naszym kodzie powtarzalne, jest niezauważalne. Te fragmenty które najczęściej wykorzystujemy to są fragmenty porównywania pewnych wartości do siebie, formatowania, pobierania daty w formacie lokalnym, mnożenia, konwersji, ustawiania globalnych wartości itp. Wszystkie te fragmenty kodów istnieją wielokrotnie skopiowane, często prowadzące do kłopotów błędnego jednego zapisu (testy pomagają).
Dla przykładu:
if(x == TestEnum.Open|| x == TestEnum.InProgress) {} // in every action ViewBag.UserId = "test"; string.Format("{0}, {1}", v1, v2);
Większość tych rzeczy jesteśmy wstanie z refaktoryzować pod nasz projekt. Skoro wiemy, że dla każdej akcji ustawiamy ViewBag
, to może warto to wrzucić globalnie – jako konwencja, nawet jak będzie widok który nie będzie potrzebował UserId
to nic się nie stanie jak UserId
zostanie ustawiony na Guid.Empty
. Często porównujemy czy coś ma dwie konkretne wartości? To czemu nie napisać rozszerzenia załatwiającego tego za nas? Jeżeli cały czas wykonujemy ?:
to może warto to zamienić na extension method ValueOrDefault
() ?
Nie tylko nasz kod stanie się czytelniejszy, nabierze on zupełnie innego znaczenia, dla przykładu:
if(x == TestEnum.Open|| x == TestEnum.InProgress) {} if(x.IsActive()) {} string.Format("{0}, {1}", v1, v2); "{0}, {1}.Format(v1, v2); string.Format("{0} {1}", user.FirstName, user.LastName); user.FullName()
Po tych zmianach zyskamy coś jeszcze, single point of failure dla każdego z przypadków. Jeżeli wiemy, że FullName
jest źle formatowy, wiemy gdzie i jak mamy to zmodyfikować. Nie musimy szukać tysięcy miejsc w kodzie gdzie tak się dzieje. Dosłownie tak samo wiemy co znaczy IsActive
.
Takie małe refaktoringi jesteśmy wstanie wprowadzać wszędzie. Daje to przejrzystość i czytelność jak i ułatwia zrozumienie kodu przez zastosowanie odpowiednich nazw funkcji. Nie wierzycie? Sprawdźcie u siebie w projekcie. Ile macie takich miejsc które w ten sposób można z optymalizować? Najlepsze jest to, że to jest tak naprawdę ten, powtarzalny kod, ten który możemy i powinniśmy się pozbyć.
Jak wam idzie stosowanie się do DRY, co robicie by nie było duplikacji i co uważacie za duplikacje?