[C#] Styl i standardy kodowania

0

Witam
zainteresowałem się ostatnio stylem swojego programowania w C#. Znalazłem w necie wile artykułów pdf nawet msdn przeglądałem ale mimo tego pare rzeczy nie daje mi spokoju ponieważ między niektórymi artykułami są rozbierzności

np.
w jednym każą w obrębie klas i metod używać
1.class MyClass
{
public void MyMethod()
{
}
}


natomiast w wypadku instrukcji pętli etc wszytko co w  funkcji sie znajduje w ten sposób
2.<code>if (warunek) {
...
}

inny artykuł natomiast mówi że wszedzie powinno się stosować klamerki z przypadku 1.

do tego dalej nie wiadomo kiedy mam uzywać uniwersalnych typów jak np. Int32 zamiast int, nawet na msdn tego dobrze nie wytłumaczono

jeszcze denerwuje mnie jedno co w przypadku nazewnictwa zmiennych tzn według więkoszsci wszystkie zmienne powino się nazywać według camelStyle czyli np. int myValue, ale właściwe dlaczego wszytkie?
a co w przypadku pól klasy lub paraemetrów danej funkcji wydaje mi się że kod byłby bardziej czytelny gdyby pola klasy np były pisane w ten sposób m_MyVal natomiast paraemetry funkcji p_AnyVal a dopiero zmienne lokalne funkcji camelStyle czyli int myVal

co o tym sądzicie? macie jakieś własne standardy kodowania czy staracie się zachować do ogólnie istniejących już i które tak naprawde są prawdziwe? na msdn nie tłumaczą tego zbyt dobrze szczególnie chodzi mi o uzywanie uniwersalnych typów jak Int32

0

Myślę, że każdy działa jak mu odpowiada - w większym lub mniejszym stopniu przestrzegając pewnego nurtu.

Ja zawsze stosuje klamrę na końcu

public class MyClass {

}

do tego dalej nie wiadomo kiedy mam uzywać uniwersalnych typów jak np. Int32 zamiast int, nawet na msdn tego dobrze nie wytłumaczono

To jest to samo! int jest aliasem, kompilator zamienia to automatycznie na System.Int32. Ja zawsze używam aliasów.

a co w przypadku pól klasy lub paraemetrów danej funkcji wydaje mi się że kod byłby bardziej czytelny gdyby pola klasy np były pisane w ten sposób m_MyVal natomiast paraemetry funkcji p_AnyVal a dopiero zmienne lokalne funkcji camelStyle czyli int myVal

camelStyle po prostu jest wygodniejsze niż m_nazwa. Takie moje zdanie i większości programistów.

0

Dzięki za odpowiedź, tak tez mi sie to wydaje wygodniejsze ale w przypadku gdy czytasz np. swój własny kod/projekt po dłuższym czasie troche mniej jest czytelny bo możesz pola klasy i parametru uzywać w definicji danej funkcji przez co projekt/klasa jest troche mniej czytelny jako całość tak czy inaczej rózne widziałem właśnie projekty niektórzy daja nazwy parametrów poprzedzajac je p a pola klasy m niektorzy wszedzie camelStyle, a co do typów i aliasów to staram się uzywać uniwersalnych tylko w deklaracjach natomiast w definicjach aliasów zeby było jak najkrócej

0

Stosuj się do podobnych standardów jak te poniżej a na pewno unikniesz niepotrzebnej krytyki:

http://blogs.msdn.com/brada/articles/361363.aspx
http://www.tiobe.com/content/paperinfo/gemrcsharpcs.pdf

public class MyClass {

}

To nie jest dobry pomysł. W przypadku klas (i w zasadzie każdy inny blok również) klamra rozpoczynająca powinna być w nowej linii. Polecam narzędzie wspomagające tworzenie i formatowanie kodu: ReSharper - szeroko stosowane w przemyśle i nie tylko.

Jeśli chodzi o pola klasy to nie powinno stosować się żadnych prefiksów. Jedyne co jest dozwolone (i według niektórych standardów zalecane) to stosowanie _ dla oznaczenia pól prywatnych (z czego i ja korzystam). Nazewnictwo pól zgodne z camelCase. Nazewnictwo metod i właściwości (properties) klas zgodne z PascalCase (zarówno prywatne jak i publiczne).

0

Mnie osobiscie zawsze denerwowało stawianie klamry w tym samym wierszu - jak dla mnie to jest w ogole nieczytelne. Visual o ile zauwazylem przy automatycznie generowanym kodzie raz wstawia klamre w tej samej linii a raz w nowej, jednak przewaznie w nowej (przyklad - Add New Item->Class), chociaż pewnie mozna to zmienic w opcjach.

Podobnie wole zapis taki:

MyClass foo = new MyClass()
{
  field1 = "a",
  field2 = "b",
  field3 = "c"
};

Od:

MyClass foo = new MyClass() {field1 = "a",field2 = "b",field3 = "c"};

Z enumami podobnie.
Co do nazw zmiennych i klas - juz bylo o tym duzo na forum, ja preferuje MyClass, MyMethod i myVal

0

Styl do delikatna sprawa. Każdy ma swój, każdy co innego preferuje. Tu nie można mówić, że "tak nie można", a "tak trzeba". Programista musi czuć się dobrze w tym co pisze. Więc na siłę narzucanie komuś stylu, który dla niego będzie niewygodny czy nieczytelny spowoduje jedynie spadek produktywności.
Nieco inaczej sprawa wygląda w teamach, gdzie ustalenie wspólnego stylu jest wskazane, ale wcale nie musi być obligatoryjne. W końcu dla prawie każdego języka programowania istnieją narzędzia, które reformatują źródła. Więc lepiej używać takie narzędzia, niż męczyć się z kodem w którym się "nic nie widzi".

Inne kwestia to niechlujni programiści, co nie trzymają się żadnego ustalonego stylu. Przeważnie w ten sposób sami sobie utrudniają życie. No ale nawet niechlujny programista może być genialnym programistą.

0

jeszcze cos mi nie daje spokoju

if (null == patient)

dlaczego wartość jest przyrównywana do wartości zmiennej czy nie wydaje Wam sie to nienaturalne?
ja zawsze pisalem najpierw zmienna w takim przypadku (niby mała róznica mozna powiedziec że przesadzam ale nie rozumiem bo często bardzo sie spotykam z takim własnie zapisem zupełnie jakby była jakaś niepisana zasada na to bez wytłumaczenia)

for (int i = 0; i < 0; ++i)

ja przyzwyczaiłem się do pisania w ten sposob (szczególnie jesli warunki w petli są dłuższe znacznie)

for (int i=0; i<0; i++)

jak dla mnie nie wiem czemu ale to jest bardziej czytelne zajmuje mniej kolumn poza tym czemu niby ++i a nie i++?

0

W pierwszym przypadku, zgadzam się, dla mnie to też jest mniej naturalny zapis niż odwrotnie. Ale jeśli komuś bardziej naturalny jest taki zapis, to już jego sprawa. Grunt, że działa tak samo.

W drugim zaś przypadku różnica jest nie tylko w zapisie, ale i w zachowaniu pętli. Jeśli użyjesz preinkrementacji, to pętla najpierw zinkrementuje wartość w zmiennej i, a dopiero potem wykona kod umieszczony w bloku pętli. Przy postinkrementacji najpierw wykonywany jest kod w pętli, a dopiero potem inkrementacja. Czasami preinkrementacja lub predekrementacja w pętli for bywa dosyć użyteczna, np. w takim wypadku:

byte[] tablica = { 1, 3, 5, 7, 11, 13, 17 };
for (int i = tablica.Length; i >= 0; --i)
{
	// wykonujemy operacje na tablica[i]
}

// co jest równoznaczne:
for (int i = tablica.Length - 1; i >= 0; i--)
{
	// wykonujemy operacje na tablica[i]
}
0

Ja klamerki zawsze stawiam w nowej linii (no chyba, że w przypadku jakiejś małej anonimowej metody i może jeszcze paru wyjątkach ;P). Tak jest czytelniej, a poza tym VS samo tak formatuje :)
Pola klas zawsze poprzedzam this. - jest to moim zdaniem dużo czytelniejsze niż jakieś durne prefiksy. (I przy okazji bardziej kolorowe ;)).
Zmienne lokalne i argumenty metody to to samo, w sensie obie te rzeczy i tak są używane wewnątrz metod, nietrudno dojść, które jest które :)
Zawsze używam aliasów - są bardziej naturalne, w końcu duża część z nich istnieje w programowaniu od kilkudziesięciu lat. A poza tym nie trzeba do nich dawać using System;

Natomiast:

if (null == patient)

i

for (int i = 0; i < 0; ++i)

to zapewne "naleciałości" z C/C++.

W pierwszym przypadku było to zabezpieczenie przed przypadkowym przypisaniem zamiast przyrównania, które jest możliwe w tych językach.

if(a = 8) //a miało być a == 8!
if(8 = a) //to nie przejdzie

Natomiast w drugim chodzi o wydajność - postinkrementacja powoduje utworzenie zmiennej tymczasowej, co spowalnia wykonanie pętli.

W C# nie ma to raczej żadnego znaczenia - pierwsze jest niewykonalne, a drugie chyba nie jest w ten sposób rozwiązane.

0

Faktycznie, pomyliłem się. Taka preinkrementacja i predekrementacja powoduje jedynie przyspieszenie, i to tylko w języku C/C++. W C# sprawdziłem i choć niektórzy utrzymują, że kod IL w tym przypadku jest wydajniejszy, to niestety, ale u mnie w obu przypadkach kod IL był identyczny. Może w starej wersji kompilatora faktycznie była różnica.

A to o czym pisałem realizuje się nieco inaczej:

byte[] tablica = { 1, 3, 5, 7, 11, 13, 17 };
for (int i = tablica.Length; --i >= 0;)  // <- tak być powinno
{
        // wykonujemy operacje na tablica[i]
}

// co jest równoznaczne:
for (int i = tablica.Length - 1; i >= 0; i--)
{
        // wykonujemy operacje na tablica[i]
}

Mea culpa, skleroza i lenistwo czasem mszczą się na człowieku ;)

0

pre- i postinkrementacja w c++ ma taka sama wydajnosc, to jeden z niezrozumialych dla mnie przesadow ;) W wygenerowanym kodzie rozni sie tylko kolejnoscia operacji, nie iloscia. A co do stylu, to najwazniejsze - trzymac sie jednego. Jedni wola Javowy, inni z Microsoftu, jeszcze inni notacje wegierska. Kazdy z tych ma swoje argumenty za i przeciw, mozna deliberowac jeszcze przez pare lat. Wazne, zeby dalo sie kod czytac bez gubienia watku co 5 linijek, bo ktos nagle przeszedl na inna notacje.

0

Johny - z tego co wiem nie ma takiej samej wydajności dla klas, które przeciążają ten operator. Post inkrementacja musi zwrócić kopie obiektu ze stanu przed inkrementacją, a preikrementacja zwraca po prostu zmodyfikowany obiekt (*this).
A że kod powinien byc generyczny, tak żeby zamiast prostych zmiennych można było wstawić iteratory, to używanie preinkrementacji w jest lepsze.
//quetz: popieram

0

Dla klas przeladowujacych ten operator - owszem. Ale przyklad byl dla typu prostego i do tego inta, a w tym wypadku jest, o ile mnie pamiec nie myli, tak samo wydajnie.

0

a w klasie formy np głownej funkcje private od eventów piszecie na końcu samym czy własne funkcje private na końcu?

0

a w klasie formy np głownej funkcje private od eventów piszecie na końcu samym czy własne funkcje private na końcu?

Funkcje od eventów z kontrolek są o ile się nie myle protected.

Jeśli chodzi o prywatne metody - staram się je pisać zawsze na końcu. Ogólnie w klasach stosuje kolejność:

  • pola/właściwości statyczne (jeśli są)
  • pola/właściwości instancji
  • konstruktory
  • metody statyczne (jeśli są)
  • metody public
  • metody private (bez pisania słowa private)

Tak mi wygodniej - pewnie są inne nawyki, jak mówię - kwestia przyzwyczajenia.

Przykład mojego formatowania: http://pastebin.com/f498dc75c

0
Deti napisał(a)

Funkcje od eventów z kontrolek są o ile się nie myle protected.

private void button1_Click(object sender, EventArgs e)

o te mi chodzi private VS samo generuje takie

0

W zwykłych klasach piszę metodę public, zaś w przypadku klas "okienkowych" najpierw metodę obsługującą zdarzenie, a za nią jej funkcje pomocnicze private, potem całość zawijam w region. Czasem też zawijam w regiony oddzielnie wszystkie metody obsługujące przyciski, oddzielnie te od DGV, oddzielnie inne, itd... - to zależy od tego ile jakich metod jest i jak bardzo są złożone. Metody prywatne wspólne dla kilku metod publicznych daję na końcu.

0

Do VS jest też dodatek StyleCop, który sprawdza styl podczas pisania kodu. Można sobie dowolnie ustawić jaki styl kodowania ma być przestrzegany.

0

somekind, tak samo jak Ty nie uzywam zadnych prefixow, tylko jesli odwoluje sie do zmiennych klasy to uzywam zawsze this, jesli sa to lokalne to wystarczy dla nich sensowna nazwa (wkoncu co to jest to wystarczy f12 wcisnac i przeniesc sie te pare linijek wyzej).
Jakos kolory mocno na mnie wplywaja i kod staje sie o wiele bardziej przejszysty :) Dlatego tez np uzywam String.Empty :)

Kolejnosc kodowania metod w klasie identyczna jak Deti + zawijanie w regiony.

public, protected, internal private... prawda jest taka, ze protected i internal przy kodowaniu w jednym assembly nie roznia sie prawie niczym od public i private (sam przed dlugi czas na poczatku je pomijalem stosujac tylko public i private). Dopiero jak projekt rozbije sie na kilka warstw, a kazda warstwe da do osobnej assembly i zacznie uzywac dziedziczenia w sensowny sposob (np tworzac klase bazowa dla repozytorium), wowczas protected i internal staja sie naprawde nieocenione :)

Dodatkowo polecam prefixy do kontrolek. Ja sie jakos przyzwyczailem do uzywania tbx dla textBox'ow, ddl dla dropDownList, lv dla listView, grid dla GridView, l dla labeli itd... ot, takie najbardziej mi sie kojarza z takimi kontrolkami... w sumie bez roznicy kto jakie uzywa, wazne by je uzywac, bo potem naprawde jest o wiele latwiej sie odnalezc.

W sumie bardziej znaczace niz styl programowania jest uzywanie wzorcow projektowych... bo zdecydowanie wole kod w brzydkim stylu napisany acz z sensem, niz pieknie fajnie... ale zrobienie jakiejs zmiany to katorga i modyfikacja polowy kodu.

0
wasiu napisał(a)

Dodatkowo polecam prefixy do kontrolek. Ja sie jakos przyzwyczailem do uzywania tbx dla textBox'ow, ddl dla dropDownList, lv dla listView, grid dla GridView, l dla labeli itd... ot, takie najbardziej mi sie kojarza z takimi kontrolkami... w sumie bez roznicy kto jakie uzywa, wazne by je uzywac, bo potem naprawde jest o wiele latwiej sie odnalezc.

ja podobnie.. za to, kiedy juz myslalem ze mnie nic wiecej nie zdziwi w sposobach unieczytelaniania kodu, trafilem na osobe, ktora z uporem maniaka stosowala konwencje odwrotna!

snip z .Designer.cs:

System.Windows.Forms.Button dalejB;
System.Windows.Forms.Button wsteczB;
System.Windows.Forms.DataGridView zdarzeniaGridView;
itd

jakos mnie przyzwyczajonemu do wegierskiego (d)gvZdarzenia, az oczy bola :/

0

Spokojnie. Miałem do czynienia z programem, który miał kilkanaście zakładek, na każdej po kilkanaście, a nawet kilkadziesiąt kontrolek. Sęk w tym, że każda kontrolka miała nadal taką samą nazwę jaką nadał jej designer w VS... Program - kilkanaście tys. linii, a w nim wszystko wyglądało mniej więcej tak:

textBox21.Text = "jakiś tekst";
// ...
private void button65_OnClick(object sender, EventArgs e)
{
    label34.Text = comboBox12.SelectedText;
}

Chyba trzy dni musiałem zmieniać nazwy, żeby zacząć orientować się w kodzie... Nie wspomnę już o innych nazwach i kosmicznej architekturze...
Program nie działał świetnie, jak się można łatwo domyślić, ale i tak zadziwiająco sporo rzeczy działało, więc szakunec dla autora, że się jakoś w tym orientował...

//quetz: true, takie przypadki to wrecz klasyka .net forms.. choelrny designer powienien pytac o nazwe za kazdym razem, to moze by sie ludzie nauczyli..

0

quatzalcoatl tez takie postfixy widzialem. Pytanie za 100pkt to po co? Chyba o to chodzi by to byly prefixy by wpisujac takie btn intelisense pokazywal mi liste wszystkich buttonow, a nie musze zgadywac jak ktos dana kontrolke nazwal... prefixy naprawde bardzo ulatwiaja sprawe.
//q: dokladnie, dokladnie po to prefiksy..

0

@wasiu, w minimalnym stopniu, ale zawsze wskazują co się pod nazwą znajduje. W pewnym stopniu pomaga to w orientowaniu się w kodzie. Ale fakt faktem, postfixy nie zawsze są dobrym pomysłem (ale nie oznacza to, że się wcale nie przydają).

[@Q, fajnie, że możesz edytować wypowiedzi innych, ale dobrym zwyczajem jest stosowanie tego przywileju tylko do pouczania, a nie do odpowiadania w temacie. Dzisiaj mamy szybkie komputery i spore dyski, więc baza wytrzyma każdy dodatkowy, nawet krótki post. Metoda, którą stosujesz, powoduje jedynie zamieszanie.]

0

doczepiam swoja linijke do postu innej osoby tam, gdzie uwazam, ze linijka owa nie jest na tyle istotna aby dostapic zaszczytu bycia osobnym postem i daje w ten sposob autorowi postu mozliwosc wywalenia jej wedle wlasnego uznania. zwroc uwage, ze nigdy nie doczepiam do czyjegos postu uwagi, na ktora jest sens w ogole odpisywac, czy ktora jest na tyle istotna ze warto aby ona podciagnela watek do gory lub go oznaczyla innym jako 'nieprzeczytany'. zeby bylo jeszcze ciekawiej - uwagi dolepiane zazwyczaj wyrazaja zgode/aprobate co do jakiejs kwestii, zas jesli mam kogos o czyms pouczyc, zazwyczaj pisze to wlasnie w osobnym poscie, aby watek sie odswiezyl i widac bylo ze jest cos do przeczytania.

jesli Cie to irytuje - ok, Twoje posty moge omijac w tej kwestii szerokim lukiem, mam jednak wrazenie, ze piszac tę uwage miałeś na wątrobie coś innego? użyj do tego maila albo wiadomosci prywatnej, i mow smialo, nie mam w zwyczaju wykorzystywac 'uprawnien', za co zreszta paradoksalnie czasem mi sie obrywa od gory..

0

kiedy juz myslalem ze mnie nic wiecej nie zdziwi w sposobach unieczytelaniania kodu, trafilem na osobe, ktora z uporem maniaka stosowala konwencje odwrotna!

Do konwencji odwrotnej mozna wymyslic tyle samo argumentów za co do twojej - jezeli chcemy szukac przez intellisence to mozna szukac i po funkcjonalnosci - załóżmy ze mam w oknie 100 pól edit, a jedno do wpisywania ip - wtedy łatwiej odnaleźć wymagany obiekt gdy typ jest doklejony na końcu.

Także wszystko zalezy od przyzwyczajeń, bo trudno znaleźć obiektywne argumenty dlaczego prefixy mają być lepsze niż postfiksy i na odwrót. Jednak warto przyjąć jakiś regularny schemat nazywania kontrolek tak, aby można było łatwo odnaleźć odpowiednią bez sprawdzania w designerze jak się nazywa.

Chyba trzy dni musiałem zmieniać nazwy, żeby zacząć orientować się w kodzie...

Dlaczego? O ile się dobrze orientuję, to Visual sam uaktualni wszystkie odwołania do kontolek po zmianie ich nazw w designerze. No chyba że kontrolki ręcznie tworzone, ale wtedy wystarcza Replace In Files, ewentualnie z regexem jako wzorzec.

0

@quetzalcoatl, bez obawy, to nic z "wątrobą" wspólnego nie ma. Po prostu piszę jak jest. Na mój gust tworzy to dezorientację. To była zwykła sugestia, a nie jestem tu nikim, komu dane byłoby o czymkolwiek decydować, więc to tylko Twoja sprawa jak ją potraktujesz. I choć nie jestem fanem takiego podejścia, to nie będę przecież z tego powodu robił jakichkolwiek wyrzutów.

Dlaczego? O ile się dobrze orientuję, to Visual sam uaktualni wszystkie odwołania do kontolek po zmianie ich nazw w designerze. No chyba że kontrolki ręcznie tworzone, ale wtedy wystarcza Replace In Files, ewentualnie z regexem jako wzorzec.
Oczywiście, że robi to z automatu. Nie napisałem przecież, że 100% czasu w ciągu tych trzech dni tylko zmieniałem nazwy. Pewien % czasu analizowałem również kod. A poza tym, stwórz formę, wrzuć na nią kilkaset kontrolek, utwórz kilka klas / plików .cs, każdy średnio po kilka tysięcy linii i zobacz jak wtedy szybko VS na 2GHz procesorze będzie wyszukiwał odwołania i odświeżał designera. Po godzinie i 10 kontrolkach będziesz miał szczerze dosyć.

0
othello napisał(a)

Do konwencji odwrotnej mozna wymyslic tyle samo argumentów za co do twojej - jezeli chcemy szukac przez intellisence to mozna szukac i po funkcjonalnosci - załóżmy ze mam w oknie 100 pól edit, a jedno do wpisywania ip - wtedy łatwiej odnaleźć wymagany obiekt gdy typ jest doklejony na końcu.

Więc wpisujemy kilka znaków prefiksu (żeby wybrać kontrolkę wg typu), dalej szukamy po nazwie funkcjonalności. Szybko i czytelnie, bo kontrolki jednego typu są w Intellisense blisko siebie.

0

jeszcze cos mi przyszlo do głowy, jak wiadomo w delphi nie mamy mozliwości deklaracji zmiennych w definicji funkcji natomiast w C# tak tylko czy Waszym zdaniem nie wpływa na na mniejszą czytelność kodu? tzn. załóżmy że deklaruje każda zmienna w funkcji linijke przed zanim ją uzyje jezeli jeszcze nie zostala zadeklarowana? mozna oczywiście deklarować wszystkie uporządkowane typami na początku danej definicji funkcji a w daleszej cześci kodu dopiero uzywać i np krótko opisać komentarzem, jakt o jest w Waszym przypadku?

0

a co do notacji dla zmiennych wydaje mi sie ze nie ma sensu używać skoro w visual studio wystarczy najechać kursorem na dana zmienna i wyświetli czy to lokalna jaki typ i nazwe

1 użytkowników online, w tym zalogowanych: 0, gości: 1