Formatowanie kodu: Klamry, a Sprawa Polska

0

Wrzuciłem do offtopicu, bo to bardziej kwestia na "rozważania filozoficzne".

Gdziekolwiek czytam kod w necie, większość ludzi pisze w ten sposób:

void MojaKlasa::mojaMetoda(int argument) {
    cosTamZrob();
    if (warunek()) {
        zrobCosJeszcze();
        iJeszcz();
    }
    else
        blaBlaBla();
}

Za to ja stosuję takie formatowanie:

void MojaKlasa::mojaMetoda(int argument)
{
    cosTamZrob();
    if (warunek()) 
    {
        zrobCosJeszcze();
        iJeszcz();
    }
    else
        blaBlaBla(); //ewentualnie dodaję klamry także dla pojedynczych instrukcji, aby w razie czego można było szybko dopisać drugą instrukcję do else
}

Dla mnie to jest oczywiste: klamra otwierająca i zamykając w tej samej kolumnie, łatwo widzę zakresy bloku itp. Nie wiem, może to nawyk z Pascala.

Ostatnio wziąłem się za lekturę "Czystego kodu" R. C. Martina, gdzie jest rozdział o formatowaniu kodu. Autor napisał, że należy stosować formatowanie jak w wersji 1, którą przedstawiłem, lecz nie wyjaśnił dokładnie czemu akurat tak.

Czy ktoś wie, czemu niemal wszyscy stosują tą metodę formatowania, każdy ją poleca i w czym ona jest lepsza od "wersji 2" ?

0

jeden krok dalej

 void MojaKlasa::mojaMetoda(int argument) {
    cosTamZrob();
    if (warunek()) {
        zrobCosJeszcze();
        iJeszcz(); }
    else
        blaBlaBla();}

7 wierszy zamiast 11, to nie jest 11-4, to jest 11 podzielić przez prawie 2

0

no i co z tego? Nie masz miejsca na pliki źródłowe?? Przecież dla pliku wynikowego to jeden h** ile białych znaków jest w pliku źródłowym a czyta się dużo lepiej wersję Rafała.

0

Dla mnie to jest oczywiste: klamra otwierająca i zamykając w tej samej kolumnie, łatwo widzę zakresy bloku itp. Nie wiem, może to nawyk z Pascala.

Do pokazania zakresów służy IDE/edytor. Kiedyś nie było dobrych edytorów to taki argument był słuszny dzisiaj już jest nieaktualny.
Ja stosuje zawsze pierwszą wersję. Wynika to stąd, że jest zwolennikiem dawania klamer do każdej konstrukcji if, for, itd.
nawet jeżeli w ciele jest jedna linijka. Jak dla mnie

if (a == 0) {
 doSth1();
} else if(a == 1) {
 doSth2();
}

wygląda znacznie lepiej niż

if(a == 0)
{
 doSth1()
}
else if(a == 1)
{
 doSth2();
}
0

Wersja nr 2 jest lepsza, bardziej czytelna co przy dużej ilości kodu bardzo pomaga... Może to przez visuala, który wymusza użycie takie formatowania :P

0

Gdyby wszyscy uczyli jednego sposobu kodowania pewnie nie byłoby z tym problemu, ale w różnych książkach sam spotykam się z różnymi sposobami formatowania kodu (dotyczy to nie tylko sposobu stawiania klamerek, ale też nazewnictwa, np. moja_klasa, mojaKlasa, moja_Klasa). Ja osobiście piszę w ten sposób:

void MojaKlasa::mojaMetoda(int argument) {
    cosTamZrob();
    if (warunek()) {
        zrobCosJeszcze();
        iJeszcz();
    }
    else
        blaBlaBla();
}

bo tak już się nauczyłem. Ty pisz jak Tobie jest wygodniej.

0

Do pokazania zakresów służy IDE/edytor. Kiedyś nie było dobrych edytorów to taki argument był słuszny dzisiaj już jest nieaktualny.

Kod nie zawsze oglądam w IDE, które go stworzyło. Argument jest więc nadal aktualny. (Czasem np. wklejam kod na forum.)

Ja stosuje zawsze pierwszą wersję. Wynika to stąd, że jest zwolennikiem dawania klamer do każdej konstrukcji if, for, itd.
nawet jeżeli w ciele jest jedna linijka.

Nie dostrzegam związku logicznego między stosowaną wersję a wstawianiem klamer.
Jestem zwolennikiem wstawiania "niepotrzebnych" klamer i stosuję zawsze drugą wersję.

0

Wydaje mi się, że nie ma co przesadzać i specjalnie zacząć pisać metodą 1 gdy jest nam wygodniej pisać inaczej. Ważne jedynie jest to by trzymać się swojej konwencji. To samo dotyczy nazewnictwa. Nie możesz pisać raz metodą 1 raz 2, ale to chyba oczywiste :)

Ja np nie używam klamer gdy mamy jednolinijkowego if-a albo for-a. Inni zaś dodają. Wszystko zależy od konwencji.
Grunt by było czytelne.

A ogólnie piszę metodą 2

0

można tu gadać i gadać... tylko po co?

Ważne, żeby konsekwentnym i trzymać się standardów w danej firmie jeśli są ; )

0

Ja rowniez zawsze i wszedzie korzystam ze sposobu nr 2. Niezaleznie od jezyka programowania ;) Uwazam, ze umieszczanie klamri w osobnych linijkach jest duzo czytelniejsze. Co prawda wowczas ilosc linii jest wieksza... ale co z tego? Na dysku mi miejsca nie brakuje ... ;)

0

Kod nie zawsze oglądam w IDE, które go stworzyło. Argument jest więc nadal aktualny. (Czasem np. wklejam kod na forum.)

Kawałki kodu na forum są na tyle małe, że bez problemu widać gdzie się kończą i zaczynają bloki nawet gdy autor stosuje mniej czytelne wersje niż 1 i 2. Poza tym jak to aż tak bardzo przeszkadza to możesz sobie wkleić do edytora.

Nie dostrzegam związku logicznego między stosowaną wersję a wstawianiem klamer.
Jestem zwolennikiem wstawiania "niepotrzebnych" klamer i stosuję zawsze drugą wersję.

Stosunek liczby linii niepotrzebne/potrzebne:

  • wersja 1: 1:4
  • wersja 2: 4:4

Teraz widzisz?

0
0x200x20 napisał(a)

Stosunek liczby linii niepotrzebne/potrzebne:

  • wersja 1: 1:4
  • wersja 2: 4:4

Teraz widzisz?

Pytam raz jeszcze CO Z TEGO? Oszczędzasz miejsce na plikach źródłowych?? Zrzucimy się po 10zł i kupisz sobie większy dysk...

0
0x200x20 napisał(a)

Stosunek liczby linii niepotrzebne/potrzebne:

  • wersja 1: 1:4
  • wersja 2: 4:4

Teraz widzisz?

ja nigdy nie używałem "argumentu ilości linii" - ważniejsza jest czytelność i łatwość zrozumienia za jakiś czas tego co się napisało.

0
if (a == 0) {doSth1();} else if(a == 1) {doSth2();}

idac tokiem rozumowania "im mniej linii tym lepiej" to mozna wszystko w jednej linii pisac ; )

0

Wszystko da się doprowadzić do skrajnośći. To ma być jakiś argument?
A dla mnie czytelny kod to taki, który zawiera jak najmniej zbędnych linii. Kod 2 również (jak się poprawnie formatuje) bardziej przypomina kod Pythona, które jak dla mnie jest liderem jeżeli chodzi o czytelnoć.

0

wersja 4

void MojaKlasa::mojaMetoda
    (
        int argument
    ) 
{
    cosTamZrob
        (
        );
    if (
            warunek
                (
                    jakisParametr
                )
        ) 
            {
                zrobCosJeszcze
                    (
                    );
                iJeszcz
                    (
                    ); 
            }
    else
        blaBlaBla
            (
            );
} 

Nie to ładne co ładne, ale co się komu podoba.

0

@Xitami:
To żaden argument, bo takie argumenty można dać do każdego sposobu formatowania kodu.

Nie to ładne co ładne, ale co się komu podoba.

Z tym się w stu procentach zgadzam.

0

Dla mnie pierwsza wersja jest czytelniejsza, za otwarcie traktuje "if", "while", początek funkcji itd. klamra na ich wysokości oznacza zamkniecie bloku, nie widzę sensu podwójnego znaczenia, że zaczyna sie jakiś blok poprzez dodawanie "{" w nowej linii. W ogóle dla mnie robienie klamry otwierającej blok w nowej linii to tak jak by oddzielając zdania pisać przecinek na początku nowej linii a nie na końcu poprzedniej.

0

Piszesz sam formatujesz jak ci wygodnie. Piszesz w zespole, formatujesz jak ci karzą.
Obie wersje są dobre i równie czytelne! Zwykła kwestia przyzwyczajenia, jak każą ci zmienić przyzwyczajenia, to przez pierwszy tydzień będziesz narzekał, potem nie będziesz czuł różnicy, a po 2 mc poprzedni sposób formatowania będzie cię drażnił.

W poprzednim miejscu wytyczne co do kodowani miałem bardzo sztywne. Poza właściwym pozycjonowaniu klamer, liczba spacji miała się zawsze zgadzać, spacja miała być tylko po lewej stronie znaków '&' i '*' (referencja/wskaźnik), miedzy nazwą funkcji a nawiasami miła być spacja przy deklaracji/definicji, przy użyciu funkcji nie miało być spacji itd itp.

0

formatowanie typu

if(coś)
{
//więcej niż 1 linia kodu
}
else
{
//więcej niż 1 linia kodu
}

duużo wygodniej się czyta,zwłaszcza gdy blok jest wielkości przekraczającej wysokość ekranu,poza tym pisząc w taki sposób trudniej o zgubienie klamer-ja pisząc pętlę czy ifa wpierw wpisuję if(),potem enter i {},i wracam do (),a zgodność par nawiasów pięknie widać wówczas ;P
Co do krótkich instrukcji,zwykle stosuję w 1 linii np:

if(coś)
{
//zrób parę rzeczy
}
else return;

Za to używanie klamer zawsze i wszędzie nawet do 1 linijki przydaje się,jak przychodzi pora wstawienia debuga w to miejsce ;]
Ale tutaj to też zależy od stosowanego IDE i docelowej platformy,np pisząc w visualu na desktopa bez problemu odpalimy sobie debugger,z kolei jak pisałem na embedded linuksa to wtedy trza było debugi stosować.

Generalnie,każdy będzie pisał jak lubi,i to tyle w temacie

0

Ja stosuję 1 i 2 w jednym :)
przyklad:

UINT16 calc_block_crc ( BYTE *ptr, int size )
{
    CRCHI = CRCLO = 0;
    while ( size-- ) {
        Crc_CCITT ( *ptr++ );
    }
    return (CRCHI << 8) | CRCLO;
}

Przyzwyczaiłem się i nie zamierzam tego zmieniać. W ogóle to spieracie się o pierdoły.

0

Ja osobiście stosuję schemat nr 2.
Ale domyślam się skąd kiedyś przeświadczenie o wyższości wersji 1. Dziś mamy wielkie monitory z środowiskami graficznymi, które wyświetlają nam nawet przeszło 100 linii kodu na jednym ekranie. Że już nie wspomnę o myszce i generalnie wygodzie środowisk graficznych.
Weźcie pod uwagę że 20 lat temu klepało się w trybie tekstowym, gdzie mieściło się max 25 linii kodu na ekranie. Z tego punktu widzenia oszczędność miejsca była istotna i pisanie klamerki otwierającej blok w nowej linii było rozrzutnością :) A nawet jak już były środowiska graficzne to pod systemy z X w nazwie często pisało się nadal w trybie tekstowym.
Ale na szczęście czasy się zmieniają... :)

0

Ja stosuje jedno u drugie. Pierwszą metodę gdy ciało pętli/warunku ma jedną linię (wstawiam klamry ale w tej wersji "oszczędnej"). Drugi sposób do sytuacji gdy kod między klamrami ma więcej niż jeden wiersz. Gdy kodzę w zespole to się dostosowywuję, najczęściej jest to formatowanie pierwsze ale z klamrami nawet dla jednolinijkowych pętli czy warunków.

0

Zawsze wersja 2. Dlaczego? Ano dlatego, że nawet jeżeli teraz wydaje ci się, że w danym ifie będzie tylko jedna linijka, więc można napisać:
if (cos) zrobcos;
To wcale nie znaczy, że za godzinę szef ci nie powie, że rozbudowujemy funkcjonalność i trzeba zrobić coś jeszcze. Zawsze staram się mieć kod przygotowany do rozbudowy.

if (cos)
{
    zrobcos;
    icosjeszcze;
    icosjeszcze;
    ...
}

To znaczy to był argument za wkładaniem w klamry ZAWSZE.
Drugi jest taki:

if (straszenie długi mega mega warunek
    || ktory musisz podzielić na kilka linii 
    || bo inaczej wyjezdza za monitor)
    wywolajFunkcjeKtora(Ma, Mega, Duzo, Argumentow,
            i, tez, musisz, podzielic, na, kilka linii);
ATuDrugaFunkcja(ktora, juz, nie, jest, w, tym, ifie);
AleNieKazdySkumaTo(od, razu);
ACzyByCieBolalo(gdyby, ludzie, kumali, od, razu?);

I co, też czytelne? Kupa, i tyle. Klamry tu powinno dać się klamry, żeby było przejrzyściej, żeby było od razu wiadomo, gdzie się blok zaczyna a gadzie kończy.

Argument o ilości linii niepotrzebnych jest po prostu śmieszny. Cały program można walnąć w jedną linię i dobiero będzie lepiej - szybciej się kompiluje jak się wywali białe znaki, nie? :>
A tak serio - co to komu robi, czy projekt ma 100 000 linii kodu, czy 100 500...? Przy takich projektach nie dba się o ilość linii napisanych, tylko o ich przejrzystość...
Pamiętajcie, że ktoś potem będzie ten kod utrzymywał. Naprawdę szkoda, że niektórzy w ogóle o tym nie myślą.
Są języki bez dobrego IDE, które ci od razu klamerki podświetli. Czasem trzeba zedytować coś w notatniku. Zlitujcie się.

0

To z ciekawości podłącze jeszcze temat wywołań funkcji i pisania atrybutów.
Czasem spotykam się że ludzie piszą każdy atrybut wywoływanej funkcji w nowej linii. O ile podzielenie atrybutów na kilka linii czasem ma sens, bo jest ich zwyczajnie dużo i żeby nie przewijać ekranu horyzontalnie, ale ogólnie taki sposób wyjątkowo mnie irytuje. A was? :)
przykład:

object.SomeMethod(1,
                              "foo",
                              parent,
                              1.23,
                              "grrrrr");
0
aurel napisał(a)

Zawsze wersja 2. Dlaczego? Ano dlatego, że nawet jeżeli teraz wydaje ci się, że w danym ifie będzie tylko jedna linijka, więc można napisać:
if (cos) zrobcos;
To wcale nie znaczy, że za godzinę szef ci nie powie, że rozbudowujemy funkcjonalność i trzeba zrobić coś jeszcze. Zawsze staram się mieć kod przygotowany do rozbudowy.

if (cos)
{
    zrobcos;
    icosjeszcze;
    icosjeszcze;
    ...
}

Chyba nie doczytałeś, w obu sposobach chodzi o dodawanie klamry, tyle że w innym miejscu, dla wersji 1. No chyba że masz na myśli ten komentarz w drugim kodzie, który powinien też znaleźć się w wersji 1. W końcu i w jedym i w drugim przypadku stosuje sie wariant z tworzeniem lub nie klamer dla jednolinijkowych wersji.

if (cos) {
 zrobcos;
}

Wiec to wyżej na pewno nie jest argumentem wyższości wersji 2 nad wersje 1.

0

Dodam, że wg. standardu kodowania w Javie, opublikowanego przez Suna (aka Oracle), powinno się używać zawsze pierwszej wersji. Używanie w Javie drugiej wersji jest dosyć dziwne.
Oczywiście C/C++ nie ma takich zaleceń.
Pytanie dla zwolenników wersji 2: skoro sposób 1 jest nieczytelny to co powiecie na Pythona, który w ogóle nie używa klamer do zaznaczania bloków? Python jest nieczytelny? :P

0

A ja dam przykład kodu w C++ stworzonego przez Microsoft 12 lat temu. Jest to część sterownika działającego w kernel-mode.

Mamy tutaj dwuargumentową funkcję, a w środku 5 linijek faktycznego kodu. Generalnie środowisko programistów zgadza się, że Microsoft tworzy.. dobry kod.

//=============================================================================
NTSTATUS AddDevice
( 
    IN  PDRIVER_OBJECT          DriverObject,
    IN  PDEVICE_OBJECT          PhysicalDeviceObject 
)
/*++

Routine Description:

  The Plug & Play subsystem is handing us a brand new PDO, for which we
  (by means of INF registration) have been asked to provide a driver.

  We need to determine if we need to be in the driver stack for the device.
  Create a function device object to attach to the stack
  Initialize that device object
  Return status success.

  All audio adapter drivers can use this code without change.
  Set MAX_MINIPORTS depending on the number of miniports that the driver
  uses.

Arguments:

  DriverObject - pointer to a driver object

  PhysicalDeviceObject -  pointer to a device object created by the
                            underlying bus driver.

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    NTSTATUS                    ntStatus;

    DPF(D_TERSE, ("[AddDevice]"));

    // disable prefast warning 28152 because 
    // DO_DEVICE_INITIALIZING is cleared in PcAddAdapterDevice
#pragma warning(disable:28152)

    // Tell the class driver to add the device.
    //
    ntStatus = 
        PcAddAdapterDevice
        ( 
            DriverObject,
            PhysicalDeviceObject,
            PCPFNSTARTDEVICE(StartDevice),
            MAX_MINIPORTS,
            0
        );

    return ntStatus;
} // AddDevice
0

Haskell jest czytelniejszy!

0

Argument z liczeniem linii jest dość głupi. To wszystko można by napisać w jednej linii - wtedy to dopiero zajebisty bilans by wyszedł. Ale CO Z TEGO? To może stawiajmy jeszcze średniki i piszmy w jednej linii, żeby linia nie była za krótka. I obliczajmy statystyki. Trochę głupie, nieprawdaż?

Poza tym.. sprawa polska? Nie sądzę - większość znanych mi ide domyślnie formatuje kod sposobem 2 (C++ Builder, Visual Studio, QT Creator), a dopiero gdy ktoś się uprze to może sobie to przestawic w opcjach. Czyli poniekąd "lansowany" jest sposób 2, zresztą całkiem słusznie.

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