Czy źle jest wypisywać każdy argument funkcji / metody w nowej linii i dlaczego?

22

Pracuję z kimś, kto za każdym razem, gdy wywołuje funkcję, umieszcza argumenty w nowej linii, np

aFunction(
    byte1,
    short1,
    int1, 
    int2,
    int3,
    int4,
    int5
) ;

Uważam to za bardzo irytujące, ponieważ oznacza to, że kod nie jest zbyt kompaktowy, więc muszę skanować więcej w górę i w dół, aby właściwie zrozumieć logikę. Chciałbym wiedzieć, czy to rzeczywiście zła praktyka, a jeśli tak, to jak mogę przekonać ich, aby tego nie robili?

Daniel Ball
źródło
25
+1, nie wiem wystarczająco, aby odpowiedzieć na twoje pytanie, ale też tego nie znoszę. Jeśli jednak masz tyle argumentów w funkcji, to prawdopodobnie twoja funkcja robi zbyt wiele.
wałek klonowy
28
Co więcej, dlaczego wciąż musimy widzieć nawzajem swoje preferencje? dlaczego nasze IDE nie mogą automatycznie prezentować go w dowolnym stylu?
Alex Feinman
5
Mike, podoba mi się, że kod zajmuje minimalną powierzchnię ekranu. Ale to kompromis. Umieszczam {w osobnej linii, ponieważ ułatwia dopasowanie do zamknięcia} i poprawnie rozumiem zakres bloku. Warto stracić linię nieruchomości ekranowych.
Brian Schroth
2
@Alex: Masz całkowitą rację. Myślę, że właściwą rzeczą byłoby posiadanie języka, w którym drzewo parsowania kodu jest przechowywane na dysku i wyświetlane zgodnie z preferencjami użytkownika.
Neil G
1
@maple_shaft Nienawidzę takich oświadczeń. Nie dlatego, że nie ma w tym żadnej prawdy, ale dlatego, że zbyt wiele osób stosuje się do takich rad, nie pozostawiając miejsca na niuanse.
Stijn,

Odpowiedzi:

38

To tylko wytyczne kodowania, które możesz lub nie. Ważne jest to, że ty i twoi koledzy zgadzacie się z niego korzystać, czy nie.

Oczywiście najlepszym sposobem na zwiększenie czytelności jest ograniczenie liczby argumentów.

Martin Wickman
źródło
24
Zbyt wiele osób redukuje argumenty, zrzucając je do tablicy. Wolałbym zobaczyć brzydki bałagan niż przejrzysty kod z ukrytą złożonością.
Satanicpuppy 30.06.11
18
Tablice nie są dobrą drogą. W argumentach może kryć się struktura, a może funkcja robi za dużo i powinna zostać podzielona.
Michael K
4
Uważam, że użycie wielu linii pomaga uczynić kod możliwym do odczytania. JEŻELI parametry są długimi wyrażeniami lub o kilka za dużo. W przeciwnym razie jest to po prostu denerwujące.
PedroC88,
3
Umieszczenie ich w obiekcie do przesyłania danych tylko przenosi problem. Jeśli wszystkie argumenty są wymagane, wszystkie muszą być obowiązkowymi argumentami konstruktora DTO, co oznacza, że ​​wciąż masz tyle argumentów.
Scott Whitlock,
21

To kwestia preferencji. W przypadku skomplikowanych wywołań funkcji, w których chcesz udokumentować każdy parametr lub gdzie zmienne są dość długie i jest ich wiele, może to być dobre.

Na przykład:

do_complex_op(
      0, //Starting state, always 0, ask Joe why
      X, //X-coord of thingy
      y, //Y-coord of thingy
      73, //in this case, we don't want to use Z but want constant 
      dlogMessageTitle, //message for dialogue title
      dlogMessageText, //message for dialogue contents, don't care about this.
      SomethingIP, //IP of something-or-other server, can be NULL, won't crash.
      someObject.childObject.getValue(key1).HVAL, //very long path to HVAL
      someObject.childObject.getValue(key1).LVAL, //very long path to LVAL
      this.parentWindow.owner.mainTextBox.text.value.trim, //get the trimmed text, untrimmed text causes weird output
      pvrMainSettingForLongBlahs.getObjectByPath(somePath),
      pvrMainSettingForLongBlahs.K_TCA_UPPER_LIMIT,
      pvrMainSettingForLongBlahs.K_ENDPOINT_COMPLIANCE_LEVEL,
 );

W przypadku języków, które pozwalają na nazwane parametry, jest to częstsze, jeśli używasz nazw parametrów (przykład jest w PL / SQL):

PKG_SOME_TEST_CODE.FN_DO_SOMETHING( in_text => 'test text',
                                    in_id => v_id,
                                    in_ref_id => v_ref_id,
                                    out_array_for_storage => v_bArray); 

Ale zgadzam się z tobą, że jeśli wywołanie funkcji jest proste i nie ma zbyt wielu parametrów, może to być denerwujące, takie jak:

setColour (
    r,
    g,
    b
 );

Uważam, że jest dużo łatwiejszy do odczytania jako

 setColour(r,g,b);

W przypadku @ammoQ:

rc=a(b,c(d,e(f)))

rc=a(
     b,
     c(
       d,
       e(
         f
        )
      )
    )
FrustratedWithFormsDesigner
źródło
11
Pierwszy przykład to zła odpowiedź na prawdziwy problem. Dlaczego nie użyć w pierwszej kolejności wyraźnych zmiennych?
deadalnix
@deadalnix: Dobra uwaga, trochę to posprzątałem.
FrustratedWithFormsDesigner
1
Prawdziwe. Jednak nie zawsze jest to problem z nazwami zmiennych. Ma to więcej wspólnego z długimi nazwami zmiennych, argumentami z wartościami domyślnymi itp.
inspectorG4dget
4
Argumentowałbym, że lepszym rozwiązaniem tego problemu jest refaktoryzacja do_complex_op (), więc przyjmuje ona strukturę jako parametr. Następnie możesz to zrobić do_complex_op(new paramStruct { StartingState = 0, XCoord = xcoord }), a następnie staje się ono
samok
1
@KallDrexx: Zgadzam się, ale czasami zmiana kodu nie jest opcją, na przykład gdy jest funkcją w bibliotece innej osoby. Jasne, mógłbym to zrobić, ale nadal będę musiał wywołać ich pierwotną funkcję.
FrustratedWithFormsDesigner
10

IMO wszystko, co rzadkie, jest złą praktyką, chyba że można pozytywnie udowodnić wyższość nad zwykłym stylem. „Kwestia gustu” to kiepska wymówka dla pisania kodu, który jest trudniejszy do odczytania niż jest to konieczne dla większości programistów, ponieważ pewnego dnia biedna dusza, nie przyzwyczajona do tego stylu, będzie musiała zachować ten kod.

Udowodnienie, że jest to rzadkie, jest stosunkowo łatwe, pokaż źródło przykładów w MSDN lub podobnych witrynach, pokaż duże bazy kodu open source itp. Pokaż wyniki beautifier kodu. Ostatecznie pokaż, jak wszyscy inni w twoim zespole to robią. Nie akceptuj złego stylu tylko dlatego, że ktoś jest zbyt uparty.

użytkownik 281377
źródło
Hm ... przy takim podejściu, jak moglibyśmy kiedykolwiek wprowadzić nową najlepszą praktykę (lub gramatycznie poprawną: lepszą praktykę )?
Treb
2
Treb: Jasne, po prostu pokaż, że lepsza praktyka jest w rzeczywistości lepsza , a nie tylko inna .
user281377,
4
Ale „trudniejsze do odczytania” jest samo w sobie subiektywne i zależy od opinii. Dla mnie jeden argument w wierszu jest łatwiejszy do analizy wizualnej niż dwa, trzy lub cztery argumenty w wierszu. I zawsze przerywam połączenie na wiele linii, jeśli wykracza ono poza około 100 znaków w edytorze.
Toby
2
Meh „Trudniejsze do odczytania” można zmierzyć obiektywnie. Po prostu tak nie jest. Kłócenie się jest przyjemniejsze.
JasonTrue
1
można to zmierzyć obiektywnie, ale nie niezależnie od osoby czytającej.
jk.
9

Cóż, oto przynęta negatywna. Nigdy nie byłem oskarżany o robienie popularnych rzeczy. Oczywiście, jeśli rzeczy pasują do jednej linii, to dobrze, dopasuj je do jednej linii.

Ale moim głównym zmartwieniem nie jest to, czy kod jest „brzydki” czy „ładny”. Moim głównym zmartwieniem jest to, jak łatwo jest zrozumieć i wprowadzać zmiany bez popełniania błędów.

Jeśli argumenty są długie i jest ich dużo, dlaczego nie umieścić ich w osobnych wierszach? Moim zdaniem dzięki temu łatwiej jest zobaczyć, jakie są, i w razie potrzeby łatwiej je zmienić. Daje mi również miejsce na dołączenie komentarza do każdego argumentu, jeśli chcę.

Chcę również zminimalizować ryzyko popełnienia błędu, jeśli dodam lub usunę argument do funkcji, co jest bardziej prawdopodobne na końcu listy argumentów niż na początku. Z tego powodu wolę umieszczać przecinek (,) na początku wiersza, niż na końcu. Następnie, jeśli na przykład chcę usunąć lub dodać argument na końcu listy, jest to edycja jednowierszowa. Nie muszę majstrować przy przecinku, który musi znajdować się na końcu wszystkich wierszy, ale ostatni, gdzie ostatni musi kończyć się nawiasami.

Więc (chłopcze, zostanę za to podpalony) Piszę tak:

nameOfFunction(firstArgument
    , secondArgument // optional comment
       ...
    , lastArgument   // optional comment
    );

Kiedy jest funkcja zawierająca od pięciu do dwudziestu argumentów, funkcja nie otrzymała tego od razu. Rozrastało się z czasem, co oznaczało, że wprowadzono wiele zmian. Każda niezakończona edycja jest błędem składniowym lub błędem. Więc nie twierdzę, że to ładne. Twierdzę, że pomaga to w poprawnym wprowadzeniu zmian.

(A dla tych, którzy twierdzą, że powinienem przekazać strukturę, wystarczy usunąć problem, ponieważ potrzebujesz kilku wierszy kodu do wypełnienia struktury, nie wspominając o dodatkowym kodzie, aby go zadeklarować i przydzielić.)

Mike Dunlavey
źródło
1
Osobiście uważam, że to świetna odpowiedź, ponieważ bardzo dobrze wyjaśniłeś swoje rozumowanie. Dobra robota Mike.
Jordan
8

Nie nazwałbym tego też. Najlepszą praktyką, w której pracowałem, było zwykle, aby wywołania funkcji znajdowały się na jednej linii, chyba że musiałbyś przewijać w poziomie każdą znaczącą ilość, aby zobaczyć całe wywołanie. Jest to wezwanie do osądu, ale zdecydowanie powiedziałbym, że umieszczenie wszystkich takich funkcji jest niezgodne, chyba że jest to standard ustanowiony przez twoją organizację.

Dlatego dobrą praktyką dla organizacji jest ustanowienie zestawu przewodników, do których powinni się stosować wszyscy programiści. Chodzi przede wszystkim o spójność i czytelność.

Jarrod Pokrzywy
źródło
5

Ułatwia to:

  • Zmień kolejność argumentów.
  • Komentuj lub wyłącz argumenty.
  • Zobacz dokładnie, który argument zmienił się podczas przeglądania różnic w systemie kontroli wersji
  • Unikaj ponownego wcięcia i zawijania tekstu podczas dodawania lub usuwania argumentu lub zmiany nazwy funkcji. (Nawet jeśli edytor automatycznie wcina się, nadal tworzysz wiele nieprzydatnych zmian białych znaków, które utrudniają śledzenie zmian w systemie kontroli wersji.)
Graham Borland
źródło
4

Powiedziałbym, że wywołania funkcji powinny znajdować się w jednym wierszu, chyba że znacznie przekraczają standardową szerokość kodu (często 80 znaków, często przyczyną argumentów :-).

Nie widzę żadnej korzyści z tego stylu. Wygląda subiektywnie brzydko, a szukanie kodu sprawia mi ból. Na przykład możesz chcieć szybko wyszukać i sprawdzić, czy funkcja jest kiedykolwiek wywoływana z określonym parametrem przekazanym jako NULL. Jest to łatwe wizualnie, gdy wszystkie parametry są w jednej linii, a trudniejsze, gdy są podzielone w ten sposób.

Luke Graham
źródło
Ta 80-osobowa rzecz musi odejść, po prostu nie ma już uzasadnionych technicznie powodów. Żyjemy obecnie w erze monitorów 19xx X 16xx i regulowanych czcionek ORAZ rozmiarów czcionek.
anon
4
@anon: Ważne powody? Jak myślisz, dlaczego tekst jest drukowany w kolumnach, a książki są węższe niż mogłyby być? Ponieważ ludzkie oko traci orientację podczas czytania wzdłuż bardzo długich linii.
Zan Lynx
4
@anon: Lubię też używać mojego ekranu szerokoekranowego, aby dwa lub trzy pliki były otwarte w układzie poziomym, który wraca do 80-100 znaków w linii.
Zan Lynx
4
@anon: Technicznie nie, praktycznie: piekło TAK. Zan Lynx ma całkowitą rację, a ponadto istnieją dodatkowe powody: łączenie, porównywanie, używanie narzędzi wiersza poleceń ... Och, powodzenia w czcionce 8p, gdy się zestarzejesz: o)
MaR
3

Często widziałem ten styl w deklaracjach lub definicjach funkcji , ale nigdy w wywołaniu (do tej pory). Czasami ma to sens, ponieważ pozwala wyraźniej dodać komentarz do poszczególnych parametrów. Wygląda na to, że skopiował ten styl do połączeń, nie wiedząc jednak, jakie są tego przyczyny. Masz dobry argument przeciwko, a on wydaje się nie mieć dobrego, więc masz mój głos, ale nie jestem tym, którego musisz przekonać.

Karl Bielefeldt
źródło
Widzę oba na telefonach. Jeśli lista parametrów jest zbyt długa, należy ją podzielić na wiele wierszy. Jeśli parametry nie grupują się normalnie w granicach szerokości, spodziewam się, że będą w osobnych wierszach. Jeśli nazwy funkcji i parametrów dobrze pasują do jednego wiersza, często widzę je ułożone w ten sposób.
BillThor
2

Czy jest to niezgodne ze standardami kodowania w firmie?

Jeśli nie, zainicjuj dyskusję na temat standardów i tego, co ludzie chcieliby zobaczyć zmienione. Upewnij się, że poruszasz to jako jedną z rzeczy, które chcesz zmienić.

Przeprowadź pełną dyskusję na temat tego , dlaczego uważasz, że nie jest to przydatne, i mam nadzieję, że wygrasz ten dzień. Nigdy nie wiadomo, że twój kolega może cię przekonać, że jego droga jest jednak najlepsza;)

Kiedy już zaktualizujesz standard, zostanie udokumentowane, do czego wszyscy powinni kodować, więc jeśli twój kolega nadal to robi, możesz go podnieść w swoich recenzjach kodu.

ChrisF
źródło
2

Może ci się to wydawać funky, ale ułatwia pracę nad kodem. Podczas refaktoryzacji możesz bardzo łatwo komentować poszczególne argumenty i sprawdzić swój refaktor przed faktycznym usunięciem rzeczy. Możesz także łatwo komentować i tymczasowo zamieniać typy.

Jest także łatwiejszy do odczytania niż:

int f(int, int, int,
      char, double, int
      X const&, Y)
{}

Nie poszedłem tak ekstremalnie, jak pokazujesz (ponieważ nie ma nazw w parametrach, nie ma to większego zastosowania), ale mam nawyk dzielenia każdego parametru na osobnej linii lub w ogóle go nie dzielę.

Ważną częścią jest to, że Twój kod może być wydrukowany lub wyświetlony na standardowych wyświetlaczach 80col i nadal jest czytelny.

Edward Strange
źródło
2

Rzadko otrzymasz od programisty uczciwą odpowiedź na coś takiego. Wszyscy odpowiedzą tylko tym, co robią lub czego nie preferują. Prawda jest taka, że ​​o ile wszyscy czasem się z tym zmagamy, jedyną „złą praktyką” tutaj jest twoja własna nieelastyczność.

Musisz być wobec siebie brutalnie szczery, aby móc odróżnić rzeczy, które są naprawdę złe od rzeczy, które cię denerwują. Prawda jest taka, że ​​w C / C ++ i podobnych językach rzadko można znaleźć praktykę wcięcia, która ma konkretny wpływ na zrozumiałość kodu. W większości dyskusji na temat tego rodzaju rzeczy obie strony układają się w stosy, przy czym ludzie przedstawiają absurdalne, nieszczere argumenty, próbując uzasadnić swoje osobiste preferencje.

Co do mojego czytania ... jest dokładnie tym, o co prosisz w tym pytaniu: absurdalny, nieuczciwy argument uzasadniający twoje osobiste preferencje.

Dan Olson
źródło
0

Szczerze mówiąc, zależy to od osoby. Powiedziałbym, że dla złożonych funkcji, jak wykazał FrustratedWithForms, pierwszy przykład, a następnie tak; w przeciwnym razie duże NIE. Z drugiej strony dlatego wolę dowolnie stosować funkcję IDE kodu.

Dark Star1
źródło
0

„Chcę wiedzieć, czy to rzeczywiście zła praktyka ...”

Tak, to zła praktyka, z wyjątkiem sytuacji, gdy lista zmiennych jest nienormalnie długa. Ale w takim przypadku problem prawdopodobnie wynika z projektu funkcji. Dlaczego nie przekazać obiektu, który zawiera wiele parametrów?

„... a jeśli tak, to jak mogę ich przekonać, żeby tego nie robili?”

Zwiąż je i łaskocz, aż zgodzą się powstrzymać to gówno.

ybakos
źródło
„Dlaczego nie przekazać obiektu, który zawiera wiele parametrów?” OK, teraz przeniosłeś problem do tego nowego obiektu. Nadal potrzebuje tej samej liczby parametrów (na przykład za pośrednictwem konstruktora), więc nadal masz ten sam problem.
Stijn,
-2

Dlaczego marnujecie cykle na tak banalną sprawę? Po prostu uruchom zaufane IDE, otwórz plik i sformatuj ponownie. Voila! Będzie w dowolnej formie.

Przejdźmy teraz do naprawdę ważnej kwestii - vi lub emacs, LOL.

SnoopDougieDoug
źródło
A kiedy przyjdziesz to sprawdzić w kontroli źródła?
pdr
-2

Powiedziałbym, że jeśli argumenty pasują do jednej linii, zrób to. Jeśli nie, to jeden argument w wierszu zapewnia doskonałą czytelność.

foo(arg1, arg2, arg3, arg4, arg5)

vs.

foo(
    arg1=arg1,
    arg2=arg2,
    arg3=arg3,
    arg4=arg4,
    arg5=arg5,
    arg6=arg6,
    arg7=arg7
)
użytkownik271413
źródło
3
wydaje się, że nie oferuje to nic istotnego w porównaniu z punktami przedstawionymi i wyjaśnionymi w poprzednich 14 odpowiedziach
komnata