• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[C#] Ważna kwestia czystego kodu - teoria vs praktyka

VPS Starter Arubacloud
+11 głosów
551 wizyt
pytanie zadane 6 czerwca 2020 w C# przez dawid2002 Mądrala (5,190 p.)

Cześć wszystkim!

Ostatnio przeglądałem różne projekty na githubie napisane w C#. Chciałem, zobaczyć jak właściwie pisać kod w tym języku. Kiedyś czytałem książkę "Czysty kod" autorstwa Roberta C. Martina i dzięki tej książce nauczyłem się wiele na temat poprawnego pisania kodu. Na githubie sprawdzałem duże projekty, aby dowiedzieć się coś więcej. Zobaczyłem, że wiele tych zasad z tej książki jest łamanych. Nie wiem, z czego to wynika. Może autor książki się myli lub może wielu programistów po prostu popełnia nieświadomie błędy.

Dlatego też, zgromadziłem sporą ilość pytań odnośnie tego co wywołuje u mnie wątpliwości. Z góry przepraszam jeśli owe pytania dotyczą rzeczy, które są związane z stylem kodowania, a nie z czystym kodem. Bardzo mi zależy, aby się nauczyć jak pisać dobry kod. Wiem, że do tego potrzeba sporo praktyki, ale warto by było na starcie wiedzieć jak do tego dążyć, stosując dobre praktyki.

1. Często widziałem, że w różnych projektach stosowano klamerki do if'ów nawet jeśli była tylko jedna instrukcja. Kiedyś słyszałem, że używanie "nadmiarowych" klamerek jest po to aby zapobiec pomyłkom. Wydaje mi się, że jeśli kod jest dobrze formatowany i stosuje się wcięcia to są one zbędne dla jednej instrukcji. Czy używanie, bądź nie klamerek do jednej instrukcji jest konieczne, czy zależy od stylu?

2. O ile dobrze pamiętam w książce była mowa, że nie należy używać przedrostka "I" do nazw interfejsów, tylko nazywać je normalnie. A klasy, które coś implementują powinny mieć przyrostek "Imp". Ja zauważyłem, że raczej nikt tak nie robi. Jak myślicie o tym?

interface ComputerStudent
class ComputerStudentImp: ComputerStudent

3. Czy używanie przedrostka "_" do prywatnych pól jest dobrą praktyką? Zdaniem, autora książki to jest nadmiarowość, której trzeba unikać. Przypomina to trochę notację węgierską.

4. Czy metody/funkcje mogą być długie? Do tej pory, jakikolwiek projekt na githubie, który przeglądałem, przynajmniej jedną długą metodę miał. Według wujka boba jest to nieprawidłowe, aby metoda miała nawet 100 linijek kodu.

5. Gdzieś przeczytałem, że jedna linijka kodu nie powinna być dłuższa niż 80 znaków/kolumn. Moim zdaniem, że jest to bardzo rygorystyczne. Czy jest to konieczne, aby stosować się do takich ograniczeń?

6. Często widziałem w różnych projektach, nadmiarowe this do prywatnego pola, nawet w konstruktorach, w których parametry miały inne nazwy niż pola. Czy stosowanie dodatkowego this jest dobre?

7. Zdaniem autora książki, nie powinniśmy bezpośrednio wywoływać konstruktorów, tylko używać odpowiednich metod. Ja zauważyłem, że różnie jest to stosowane. Jak wy myślicie?

Citylodz = new City("Łódź");
// zamiast powyższego:
Citylodz = City.FromName("Łódź");

8. W jednym projekcie zauważyłem, że zamiast stworzyć obiekt i przypisać go do zmiennej, potem wywołać odpowiednią metodę to zamiast tego po prostu wywołano konstruktor i po tym metodę. Jest to dobre rozwiązanie?

new EFCommand().Configure(app);

9. Z tego co mi wiadomo test powinien mieć tylko jedną asercję. Poniżej jest fragment kodu, który ma więcej niż jedną asercję. Czy metody testowe mogą mieć kilka asercji? Czy jest to zła praktyka?

[TestCase(TestName = "RectangleShape report accurate distance")]
public void Rectangle()
{
     shape = new RectangleShape(new int2(-123, -456), new int2(100, 100));
     shape.Initialize();

     Assert.That(shape.DistanceFromEdge(new WVec(10, 10, 0)).Length,
          Is.EqualTo(0));

     Assert.That(shape.DistanceFromEdge(new WVec(-100, 50, 0)).Length,
          Is.EqualTo(0));
     // etc.
}

10. Czy poprawne jest stosowanie w metodach testowych ify, switche, pętle, try-catch itd.?

11. W książce było powiedziane, że metoda nie powinna mieć więcej niż 2 lub 3 parametry (nie pamiętam czy 2 czy 3). Zdarzało mi się widzieć, że konstruktory lub metody miały dużą ilość argumentów. Czy można w czystym kodzie stosować takie konstruktory/metody?

public ContrailRenderable(World world, Color color, WDist width, int length, int skip, int zOffset)

12. Nazwy powinny przedstawiać intencję. Czy zatem stosowanie takich zapisów podobnych do poniższych jest dobre w czystym kodzie?

var c = Color.Purple;

var sa = shadowOrigin + psb[0];
var sb = shadowOrigin + psb[2];
var sc = shadowOrigin + psb[1];
var sd = shadowOrigin + psb[3];

foreach (var v in draw)

13. Czy używanie przyrostków  „Manager”, „Processor”, „Data”, „Info” jest złe? Spotykałem nie raz typy z tymi przyrostkami, ale w książce jest mowa, że nic one nie znaczą i należy je unikać.

14. Czy to złe gdy coś podobnie się nazywa? Podobno należy tego unikać, aby nie było w przyszłości nie chcianych błędów.

Student student; 
Student aStudent; 
Student theStudent;

 

Z góry bardzo dziękuje za pomoc!

4
komentarz 6 czerwca 2020 przez Ehlert Ekspert (212,630 p.)

Ogólnie dobre rozkminy, także oby tak dalej yes

2
komentarz 7 czerwca 2020 przez adrian17 Ekspert (344,100 p.)

Tylko komentarz do 2: rób to co jest w praktyce uznanym standardem, a nie to co autorowi się wydaje fajniejsze. (Ogólnie zgadzam się z innymi, że niektóre rady to mocny puryzm autora nie odpowiadający rzeczywistości.)

Nawet sam edytor na Ciebie nakrzyczy jak robisz coś "dziwnie":

komentarz 7 czerwca 2020 przez dawid2002 Mądrala (5,190 p.)
Mam jeszcze pytanie do wszystkich. Zna ktoś jakieś dobre projekty na githubie w C#, aby móc zobaczyć dobrze napisany kod? Ktoś mógłby mi polecić taki projekt do analizy?

PS. Dziękuje bardzo wszystkim za odpowiedzi, komentarze i za pomoc! Te rady na pewno mi się przydadzą oraz innym, którzy to wszystko przeczytają.
komentarz 7 czerwca 2020 przez JakSky Stary wyjadacz (14,770 p.)
Polecam kod źródłowy .Net Core

3 odpowiedzi

+4 głosów
odpowiedź 6 czerwca 2020 przez Ehlert Ekspert (212,630 p.)

Nie piszę w c#, bardziej php, ts, python, więc jeśli da Ci to jakieś rozeznanie na temat pytań które padły... 

  1. Kwestia konwencji. Dodawanie klamer zawsze jest uznawane za dobrą praktykę. 
  2. Te przedrostki i suffixy to imo pozostałości po notacji węgierskiej. Osobiście korzystałem z dodawania słowa Interface na końcu nazwy. Klasa implementująca rozszerzała kontekst swoją nazwą np CacheStoragrInterface + RedisCacheStorage.
  3. Kwestia konwencji. Od razu widać że pole jest prywatne ale jakoś nie widzę takiej konieczności. Jeśli masz kolizję nazwy argumentu metody/zmiennej lokalnej z polem klasy to możesz użyć this/self, ale lepiej przemyśleć czy została zastosowana prawidłowa nomenklatura.
  4. Jak wyrobisz nawyk pisania testów jednostkowych to ogarniesz co wuj miał na myśli. Funkcje powinny być krótkie oraz spójne co do przeznaczenia. 
  5. Wszystko jest kwestią przyjętych standardów ale ten najpowszechniejsze psr, pep itp mają limit długości linii kodu. Nigdy mi to specjalnie nie przeszkadzało. Ze same standardy określają również jak łamać dłuższe linie.
  6. Nie wypowiem się, w php/Pythonie zawsze się go używa. Pamiętam jednak, że kiedy pisałem w Javie i stosowałem takie praktyki kumpel zwracał na to uwagę przy CR. Podejrzewam że jest to nadmiarowe i nie ma wpływu na wydajność ale warto spojrzeć do standardów konkretnego języka i zweryfikować.
  7. Można stosować takie podejście, można użyć wzorca fabryka. 
  8. Skoro sens istnienia instancji ogranicza się do wykonania tej jednej metody to czemu nie.
  9. Temat który ostatnio mnie bardzo zastanawia. Moim zdaniem jest to swego rodzaju objaw puryzmu. Jedna asercja wymusza testowanie tylko jednego konkretnego edge-case'u. Z jednej strony dobra praktyka, z drugiej mógłbym podać przykłady z kilkoma asercjami które również uważam za poprawne. W tym temacie polecałbym Ci trzymać się tego aby test był krótki i jak najbardziej oddawał specyfikację testowanego kodu i jego zachowanie.
  10. Unikałbym. Test dostarcza specyficzny kontekst. Jeśli masz tam ifa to rozbij to na dwa testy. 
  11. Konstruktory to trochę inna sprawa. Ale przy metodach wykonujących logikę przy 4 argumentach należy się zastanowić nad odpowiedzialnością danej funkcji.
  12. Takie nazwy to dramat, szczególnie kiedy complexity rośnie.
  13. Wszystko zależy od konwencji dotyczącej architektury. Jeśli wiemy że projekt jest mały to możemy się umówić że całą logikę zamykamy na poziomie modelu np Product oraz jednemu odpowiadającemu mu serwisowi np ProductService, albo ProductManager. Ale kiedy takie klasy puchną trzeba reagować, wydzielać logikę i używać bardziej sprecyzowanego nazewnictwa, gdyż Manager i Service zupełnie nie oddają swojego przeznaczenia.
  14. ​​​Nie spotkałem się z angielskimi przedrostkami w nazwach zmiennych. Ogólnie im "głębszy" kontekst, tym bardziej opisowa powinna być nazwa zmiennej.
komentarz 6 czerwca 2020 przez dawid2002 Mądrala (5,190 p.)
Wielkie dzięki za rady. Są dla mnie bardzo przydatne i ważne.

Odnośnie 4. uważasz, że są powodu dla których metody mogą być długie?
komentarz 6 czerwca 2020 przez draghan VIP (106,230 p.)

@Ehlert,

10. Unikałbym. Test dostarcza specyficzny kontekst. Jeśli masz tam ifa to rozbij to na dwa testy.

Pamiętaj, że "testy" to nie tylko unit-testy, ale też testy integracyjne, e2e, akceptacyjne... Często implementuje się bardziej złożone scenariusze, niż użycie metody i asercja zwróconego obiektu. :)

komentarz 7 czerwca 2020 przez Ehlert Ekspert (212,630 p.)

Oczywiście mam taką świadomość wink​​​​​​

Jeśli jednak złożoność projektu rośnie to można, a wręcz należy wprowadzać dodatkową warstwę do testów. Mam na myśli np ObjectMother pattern, albo własne asercje badające poprawność logiki byznesowej.

komentarz 7 czerwca 2020 przez Ehlert Ekspert (212,630 p.)

@dawid2002, co do długości metod... No jeśli robimy czysty kod to nie bardzo cheeky testy jednostkowe dostarczają dobrych metryk. Jeśli ich kod zaczyna być pogmatwany zawiera mnóstwo mocków ze specyficznym stanem to znaczy, że coś jest nie tak.

+4 głosów
odpowiedź 6 czerwca 2020 przez draghan VIP (106,230 p.)

Cześć! Bardzo dobrze że przejrzałeś kod projektów i zadajesz te pytania, wydaje się że idziesz właściwą ścieżką.

Zanim pokuszę się o odpowiedź na Twoje pytania (może nie na wszystkie jestem kwalifikowany udzielić odpowiedzi), muszę wyartykułować pewną tezę: tzw. "zasady czystego kodu" to tylko zbiór wskazówek. Owszem - dzięki stosowaniu ich kod staje się zazwyczaj lepszy, jednak trzeba zrozumieć że świat i ludzie nie są perfekcyjni. Wpadanie w niekończącą się rutynę refactoru, żeby kod był krystaliczny, może być ok jeśli możesz sobie na to pozwolić (a i tak na końcu zawsze znajdzie się coś do poprawy). Tworzenie oprogramowania zazwyczaj wygląda jak swego rodzaju kompromis - dostarczanie kodu możliwie jak najwyższej jakości przy jednoczesnych ograniczeniach czasowych na dostarczanie działających funkcjonalności. Zawsze masz założone więzy czasowe - nie jest ważne, czy to jakiś komercyjny projekt w którym masz swój udział (tutaj więzy są narzucone przez management, który sypie złotem) czy to Twój prywatny projekt (w najbardziej optymistycznym przypadku masz tylko 24 godziny swojego czasu na dobę). Musisz też zdawać sobie sprawę, że nawet jeśli 4 na 5 członków zespołu stara się wdrażać zasady czystego kodu, to już jedna osoba która mniej dba o kod który pisze, potrafi znacznie obniżyć jakość produktu - zazwyczaj nikogo nie stać na to, żeby przepisywać na nowo 1/5 funkcjonalności już zaraz przy jej kontrybucji.
Warto też zdawać sobie sprawę z tego, że sporo z tych zasad jest subiektywnych - w jednym zespole zaadoptowane w jeden sposób, w innym - inaczej.

1. Czy używanie, bądź nie klamerek do jednej instrukcji jest konieczne, czy zależy od stylu?

Jeśli kompilator Ci pozwala na nieużywanie klamerek - to konieczne nie jest, zatem zależy od przyjętej w danym projekcie konwencji. Z mojego doświadczenia - klamerki w tej sytuacji są całkiem spoko. Dodają czytelności, zmniejszają ryzyko pomyłki oraz łatwo jest dorzucić jakąś instrukcję do już istniejącej. Oczywiście nie są to super znaczące korzyści. ;)

2. O ile dobrze pamiętam w książce była mowa, że nie należy używać przedrostka "I" do nazw interfejsów, tylko nazywać je normalnie. A klasy, które coś implementują powinny mieć przyrostek "Imp". Ja zauważyłem, że raczej nikt tak nie robi. Jak myślicie o tym?

Wiem że to nie jest żaden argument, ale osobiście nie widziałem żeby ktoś tak tego używał. :) Aczkolwiek zazwyczaj pracowałem ze starszą bazą kodu, gdzie konwencja była ustalona na długo przed popularyzacją książki Martina. Moje zdanie - dopóki wiadomo co jest czym i nazwy nie wprowadzają konfuzji, jest ok. Ważne żeby były spójne w całym projekcie.

3. Czy używanie przedrostka "_" do prywatnych pól jest dobrą praktyką? Zdaniem, autora książki to jest nadmiarowość, której trzeba unikać.

Taka sama nadmiarowość, jak dodawanie przedrostka I lub przyrostka Imp do interfejsu / implementacji. Najważniejsze żeby było spójnie. Ja osobiście nie mam preferencji w tym zakresie. Taki przedrostek w zasadzie szkodliwy nie jest (forma '_' jest dużo lepsza niż np. 'm', które już dodaje literę do identyfikatora i może zaciemnić jego znaczenie), a pomaga na pierwszy rzut oka rozróżnić, czy pracujemy aktualnie z czymś dostępnym publicznie. No i np. w Pythonie to jest systemowe rozwiązanie na ukrycie części składowych.

4. Czy metody/funkcje mogą być długie?

Długie metody nie są fajne pod względem utrzymania, ale czasami się zdarzają z powodów o których pisałem we wstępie. No i zdarza się że refactor takiej metody jest kłopotliwy: jeśli mam przerabiać całą architekturę klas, żeby pozbyć się jednej długiej metody gdzieś na krańcu projektu, gdzie zagląda ktoś raz na ruski rok, to wolę zrobić coś bardziej pożytecznego, np. załatać jakiegoś uciążliwego buga. ;)

5. Gdzieś przeczytałem, że jedna linijka kodu nie powinna być dłuższa niż 80 znaków/kolumn. Moim zdaniem, że jest to bardzo rygorystyczne. Czy jest to konieczne, aby stosować się do takich ograniczeń?

Jak wszystkie te zasady - nie jest to konieczne. O ile oczywiście konwencja w danym projekcie na to pozwala. Są takie które nie przyjmą kodu gdzie chociaż jeden znak wystaje za margines, są też takie w których programiści kierują się raczej zdrowym rozsądkiem i jeśli zdarzy się że coś tam trochę wystaje, a nie zaburza to czytelności, kod jest akceptowany.

6. Często widziałem w różnych projektach, nadmiarowe this do prywatnego pola, nawet w konstruktorach, w których parametry miały inne nazwy niż pola. Czy stosowanie dodatkowego this jest dobre?

Wskazanie explicite że modyfikuje się część aktualnej instancji nikomu jeszcze nie zaszkodziło, a w drugą stronę - na pewno się zdarzyło.

7. Zdaniem autora książki, nie powinniśmy bezpośrednio wywoływać konstruktorów, tylko używać odpowiednich metod. Ja zauważyłem, że różnie jest to stosowane. Jak wy myślicie?

Drugi sposób jest nieco bardziej elastyczny, bo wprowadza dodatkową warstwę abstrakcji. Jednakże wszystkiego trzeba używać z głową. Gdzieś ten konstruktor i tak musi zostać wywołany; a jeśli masz jakąś prostą klasę narzędziową z dwoma atrybutami i jednym konstruktorem, zastanów się czy jest w ogóle sens ukrywać wołanie c-tora i wprowadzać taką dodatkową warstwę.

8. W jednym projekcie zauważyłem, że zamiast stworzyć obiekt i przypisać go do zmiennej, potem wywołać odpowiednią metodę to zamiast tego po prostu wywołano konstruktor i po tym metodę. Jest to dobre rozwiązanie?

Rozwiązanie jest tak dobre lub złe zależnie od kontekstu. Jeśli ktoś nie potrzebował przechowywać instancji, tylko chciał otrzymać wynik działania jakiejś metody którą oferowała klasa, to dlaczego miał tego nie zrobić w taki sposób? ;) Pozostaje pytanie, czy ta metoda nie powinna dostać statycznego odpowiednika, jeśli pojawiło się zapotrzebowanie na jej zawołanie bez potrzeby przechwycenia obiektu.

9. Z tego co mi wiadomo test powinien mieć tylko jedną asercję. Poniżej jest fragment kodu, który ma więcej niż jedną asercję. Czy metody testowe mogą mieć kilka asercji?

Szczerze - nie wyobrażam sobie tego w praktyce. Wyobraź sobie scenariusz, w którym testujesz czy jakiś obiekt stworzył się poprawnie. Czy napiszesz kilka(naście) metod testowych gdzie w każdej z nich zawrzesz tworzenie danego obiektu w taki sam sposób oraz asercję jednego atrybutu stworzonego obiektu? A co jeśli sama kreacja danego obiektu nie jest tania? Jasne - im mniej asercji w metodzie, tym bardziej zwarty kod i mniejsze ryzyko błędu, ale zawsze trzeba podchodzić do wszystkiego z głową, biorąc pod uwagę kontekst w którym się pracuje.

10. Czy poprawne jest stosowanie w metodach testowych ify, switche, pętle, try-catch itd.?

Im prostszy scenariusz testowy, tym lepiej. Jednak testy to jest też oprogramowanie i czasami się bez tego nie da poprawnie zaimplementować testu.

11. W książce było powiedziane, że metoda nie powinna mieć więcej niż 2 lub 3 parametry (nie pamiętam czy 2 czy 3). Zdarzało mi się widzieć, że konstruktory lub metody miały dużą ilość argumentów. Czy można w czystym kodzie stosować takie konstruktory/metody?

Tutaj tak samo jak z długością metody - raczej nie powinno się. Ale znów: jeśli miałbym zrobić refactor i wprowadzić dodatkowe 2 klasy tylko po to, żeby zredukować liczbę argumentów jednej metody z 4 do 2, to zadałbym sobie najpierw pytanie, czy to się rzeczywiście opłaca. ;)

12. Nazwy powinny przedstawiać intencję. Czy zatem stosowanie takich zapisów podobnych do poniższych jest dobre w czystym kodzie?

Nie, taki kod jaki pokazałeś na 99% nie przeszedłby pozytywnie przez moje review. Aczkolwiek należy pamiętać że wszystkie identyfikatory są zawsze użyte w jakimś kontekście. Jeśli w danej domenie powszechnie wiadomo co to jest `sa` czy `psb`, to to jest ok.

13. Czy używanie przyrostków  „Manager”, „Processor”, „Data”, „Info” jest złe? Spotykałem nie raz typy z tymi przyrostkami, ale w książce jest mowa, że nic one nie znaczą i należy je unikać.

A co zatem zrobisz, jeśli Twoim zadaniem będzie napisać procesor tekstu? ;D

14. Czy to złe gdy coś podobnie się nazywa? Podobno należy tego unikać, aby nie było w przyszłości nie chcianych błędów.

Wszystko z głową. Generalnie to stworzenie sobie takich 3 zmiennych to proszenie się o kłopoty - programista może się pomylić, reviewer nie wychwycić błędu... Jeśli zajdzie potrzeba stworzenia sobie takich trzech zmiennych służących do przechowania jakichś 3 instancji, może lepiej nadać im jakieś bardziej rozpoznawalne nazwy, np. firstStudent, secondStudent lub spiąć je w jakąś listę / tablicę.

 

komentarz 7 czerwca 2020 przez DragonCoder Nałogowiec (36,500 p.)

Drugi sposób jest nieco bardziej elastyczny, bo wprowadza dodatkową warstwę abstrakcji. Jednakże wszystkiego trzeba używać z głową. Gdzieś ten konstruktor i tak musi zostać wywołany; a jeśli masz jakąś prostą klasę narzędziową z dwoma atrybutami i jednym konstruktorem, zastanów się czy jest w ogóle sens ukrywać wołanie c-tora i wprowadzać taką dodatkową warstwę.

Ale tworzenie zalozmy 50 setterow, tylko bo to, zeby zastapic c-tor chyba jest bez sensu i namdierna iloscia kodu? Wiec kiedy uzyc drugiej metody?

 

komentarz 7 czerwca 2020 przez draghan VIP (106,230 p.)

Ale tworzenie zalozmy 50 setterow, tylko bo to, zeby zastapic c-tor chyba jest bez sensu i namdierna iloscia kodu? Wiec kiedy uzyc drugiej metody?

Trzeba tu rozgraniczyć settery od statycznych metod konstruujących, bo to dwie różne sprawy. Setterami nie zastąpisz konstruktora, bo nie do tego one służą. :) Konstruktor (lub statyczna metoda fabrykująca) służy do poprawnego stworzenia i zainicjalizowania obiektu, settery służą do ustawienia parametrów już istniejącego obiektu. Generalnie - dobrze jest stworzyć tyle setterów, żeby każda właściwość która ma sens być ustawiana samodzielnie przez użytkowników klasy, miała swój setter, ale to taka dość oczywista oczywistość.

Zajrzałem sobie do książki Martina i poszukałem tego konkretnego aspektu. Mówi on, że jeśli konstruktor jest przeciążony, tzn. jeśli pozostawimy w klasie do wyboru kilka konstruktorów, to lepiej ukryć takie konstruktory pod zasłoną niepubliczną i utworzyć metody które nazwą odpowiednio taki konstruktor. Podany przykład:

// this code:
Complex fulcrumPoint = new Complex(23.0);
// ...could be replaced with more descriptive factory method:
Complex fulcrumPoint = Complex.FromRealNumber(23.0);

 

2
komentarz 7 czerwca 2020 przez Szfierzak Gaduła (3,750 p.)

@DragonCoder, Myślę, że z klasy ze zbyt dużą ilością setterów da się wyodrębnić kilka innych mniejszych klas. Trzeba Pamiętać, że duża klasa to kłopoty, najczęściej łamana jest wtedy zasada pojedynczej odpowiedzialności i utrzymanie tego robi się tym trudniejsze im większa klasa. Jeżeli jest już konieczność zbudowania tak dużej klasy to najlepiej do tego użyć jakiegoś wzorca, np. buildera.

komentarz 7 czerwca 2020 przez dawid2002 Mądrala (5,190 p.)

@draghan, dzięki wielkie za te rady.

@Szfierzak, też tak uważam.

+1 głos
odpowiedź 7 czerwca 2020 przez Aisekai Nałogowiec (42,190 p.)
1. Kwestia wyboru teamu lub preferencji autora. Sam jednak wolę, żeby te klamerki były, dla mnie jest to bardziej przejrzyste.

2. "Czysty kod" jest pisany na podstawie Javy, większość zasad jednak można wykorzystać w różnych językach, natomiast konwencja nazewnictwa interfejsów z przedrostkiem "I" wynika od Microsoftu https://docs.microsoft.com/pl-pl/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces

3. W językach w którychssą modyfikatory dostępu - raczej zbędne. W Js do pewnego momentu nie było modyfikatora private, więc niektórzy radzili sobie z tym wykorzystując właśnie "_".

4. Metody nie powinny być długie, tak samo nie powinno być wielopoziomowych zagnieżdżeń w metodzie. Tam gdzie można logikę porozbijać na klasy/prywatne metody, warto to zrobić. Od razu będzie widać po nazwie metody i jej parametrach, co ona robi.

5.  Ekrany były mniejsze i było to raczej podyktowane tym, że powyżej 80 znaków nazwa metody nie mieściła się w ekranie. Teraz raczej można więcej znaków, np. w defaultowym configu TS - ustawionw jest na 140 znaków.

6. Imo - nikomu nie zaszkodziło, a wręcz przeciwnie bardziej pomaga. W JS - musisz zastosować "this" jeśli odnosisz się do pola/metody w klasie. W Javie istnieją importy statyczne które pozwalają na pominięcie wywolania statycznych metod "na klasie" (dobre np w unit testach bo nie trzeba pisać Assert.equals() tylko można equals()). W C# - nie wiem. Dużo tez zależy od przyjętej konwencji.

7.  Tak jak Ehlert napisał i Draghan napisał.

8. Bez znaczenia.

9. Jeżeli asercje odnoszą się do jednego przypadku, raczej można ale też nie przesadzajmy. W tym przypadku raczej do rozbicia na dwa testy.

10.  Jeżeli masz ify-switche to rozbić na inne testy. Jeżeli masz pętle, to raczej obstawiam że wszystkie testy w pętli są jednego typu - nie pokrywają różnych edge-case'ow.

11. Parametry można grupować w klasy dla przejrzystości. Można stosować różne wzorce - np buildera do tworzenia obiektów. Jednakże jeżeli konstruktor przyjmuje za dużo parametrów, można przemyśleć czy nie lepiej wydzielić ich do osobnych klas. Tutaj raczej bym to zostawił tak jak jest, ew jakiegoś buildera dodał.

12. Nazwy ogólnie powinny mówić o tym czym jesf dana metoda/pole. Jeżeli sa/sb jest zlepkiem nic nieznaczących liter to niepoprawne. Jeżeli pisałbyś program do obsługi np Wyborów, to PKW już dużo mówi.

13. Imo nie jest złe, widać mniej więcej co klasa robi. Do tego dokładasz pakietowanie per funkcjonalność i masz jeszcze bardziej to przejrzyste. Jeżeli masz pakietowanie per warstwa - mało co to daje. Ogólnie dodając sufiksy będące nazwa np wzorca od razu mówi czym jest klasa a przy okazji - rozwiązuje problem z wymyślaniem dobrej nazwy.

14. Jest to złe, bo nie widzisz od razu jakie zastosowanie w programie ma każdy z tych trzeb obiektów.

 

Ogółem tak jak Draghan napisał: clean code to wskazówki, bardziej istotna jest przyjeta konwencja.
komentarz 7 czerwca 2020 przez dawid2002 Mądrala (5,190 p.)
Dzięki wielkie za rady! Przyda mi się bardzo.

Podobne pytania

0 głosów
1 odpowiedź 1,192 wizyt
pytanie zadane 18 stycznia 2020 w C# przez dawid2002 Mądrala (5,190 p.)
0 głosów
0 odpowiedzi 118 wizyt
+1 głos
2 odpowiedzi 500 wizyt
pytanie zadane 10 stycznia 2020 w C# przez dawid2002 Mądrala (5,190 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...