Przerwanie linii przed / za operatorem [zamknięte]

29

Podczas gdy konwencja kodu Java firmy Sun sugeruje umieszczenie podziału linii przed operatorem, wiele innych wytycznych nie zgadza się z tym. Nie widzę żadnych oczywistych zalet i wad, więc czy są zalety korzystania z jednego z tych stylów nad innym?

String longVarName = a + b + c + d +
          e + f;

vs

String longVarName = a + b + c + d
          + e + f;
Nutel
źródło
Czy możesz napisać prosty przykład kodu pokazujący obie konwencje?
Michael
Najpierw spróbuję uniknąć tej sytuacji, używając czegoś takiego: download.oracle.com/javase/1.4.2/docs/api/java/lang/…
Job
Link jest zepsuty.
Florian F

Odpowiedzi:

14

Pozostawiłbym to w jednej linii i wolę myśleć o czytelności w kategoriach nazw zmiennych (i funkcji) ujawniających intencje.

Gdy robi się bałagan, czas na refaktoryzację :

  • zmień nazwę vars
  • wprowadzić nowe zmienne / funkcje

Przykład

subtotal = price * (100 + tax_ratio) / 100`

vs.

tax = price * tax_ratio / 100
subtotal = price + tax
Kamil Tomšík
źródło
2
Formuła po lewej jest niepoprawna. Powinno być albo jedno, price * (100 + tax_ratio) / 100albo tylko price * (1 + tax_ratio), w zależności od tego, czy tax_ratiojest procentowe czy ułamkowe.
Rufflewind
4
To nie odpowiada na pytanie. Powinny istnieć przepisy prawne dotyczące tego rodzaju odpowiedzi.
Edward D'Souza
@ EdwardD'Souza Czuję to samo. Ale dlaczego odpowiedź została zaakceptowana?
Rudy Vissers,
@RudyVissers odpowiedź rozwiązuje problem na głębszym poziomie. Rozwiązuje przede wszystkim problem konieczności przerywania linii. Z tej perspektywy PO może uznać to za odpowiedź na swój problem, ale nadal nie jest właściwe z tego punktu widzenia, że ​​jest to wiki społeczności.
Edward D'Souza
hej, już mnie tu nie ma, ale to naprawdę proste - jeśli znajdziesz się w takiej sytuacji, prawdopodobnie robisz to źle i powinieneś raczej pomyśleć o refaktoryzacji kodu - lub inaczej: po 15 latach programowania I po prostu nie przejmuję się już takimi rzeczami, zamiast tego dbam o przejrzystość kodu, prostotę i ułatwianie innym ludziom pomocy
Kamil Tomšík
36

Mogę sobie wyobrazić czytelność jako argument

result = longidentifier +
   short -
   alittlelonger -
   c;

przeciw

result = longidentifier
   + short
   - alittlelonger
   - c;

W drugim przykładzie operatory są ładnie ustawione w linii i można łatwo zobaczyć, z którym znakiem zmienna wchodzi do równania. Myślę, że ma to również sens dla operatorów binarnych, ale w przypadku stężeń itp. Powinieneś po prostu robić wszystko, co jest bardziej zrozumiałe.

Otto Allmendinger
źródło
4
W sytuacjach, w których operatory są ważne (takie jak wyrażenia matematyczne itp.), Wybrałbym numer dwa, ponieważ, jak powiedziałeś, jest on znacznie bardziej czytelny. Ale dla łańcuchów wybrałbym pierwsze opcje, ponieważ operatory są „bez znaczenia”. Nie robią nic oprócz łączenia ciągów, a ponieważ ciągi są ważnym bitem, wolałbym pierwsze opcje.
Niklas H
Oba przypadki mają swoje zalety. Oba przypadki są lepsze niż umieszczenie wszystkiego na jednej bardzo długiej linii! Preferuję użycie otwierającego wspornika na początku (nawet jeśli nie jest to potrzebne), a następnie umieszczenie pod nim wszystkiego. To sprawia, że ​​jest to o wiele bardziej oczywiste.
szybko_nie
35

Zwykle stosuję się do najczęściej używanych wskazówek dotyczących stylu lub określonych standardowych narzędzi do kodowania. Zaletą używania często używanego stylu są korzyści, gdy czytasz kod innej osoby lub uczestniczysz w projekcie open source, w którym ustalone są wytyczne dotyczące stylu.

Najpopularniejsze style, które widziałem, to drugi styl w pytaniu. Zobacz ich listę poniżej:

Przewodnik po stylu Google :

Gdy linia jest przerywana u operatora nieprzypisania, przerwa następuje przed symbolem.

Konwencja Sun Coding :

Przerwa przed operatorem

Checkstyle operator owinąć czeku „s wartość domyślna to nl:

Operator musi być na nowej linii

pułapy
źródło
2
Zaktualizowałem moją odpowiedź ze względu na przejrzystość + konwencję kodowania Sun.
ceilfors
google.github.io/styleguide/javaguide.html (link w odpowiedzi jest uszkodzony)
Martin Pfeffer
10

W kodzie zwykle umieszczam przerwę po operatorze:

foo = some_long_expression() +
      some_other_long_expression();

Tutaj ten zwisający operator na końcu wiersza stanowi dużą wskazówkę dla czytelnika, że ​​kod jest kontynuowany. W językach, które nie mają terminatorów instrukcji, ten zwisający operator może służyć jako wystarczająca wskazówka dla kompilatora / interpretera, że ​​kod kontynuuje (w przeciwnym razie musiałbym użyć brzydkiej konstrukcji linii kontynuacji).

Dokumentując to wyrażenie (jeśli potrzebuje dokumentacji), zwykle stawiam przerwę przed operatorem.

David Hammen
źródło
Przynajmniej niektóre języki (np. Python) nie biorą końcowego operatora binarnego jako wskazówkę, że linia jest kontynuowana, ale wymagają więcej. Zauważ, że nowe linie w parenach zwykle nie są liczone, więc nie potrzebujesz wyraźnego (i podatnego na błędy) znaku kontynuacji linii.
3

Dopóki pozostajesz konsekwentny, wiedz, że nie ma żadnej realnej przewagi. Jest to szczególnie ważne przy rozważaniu scalania kodu i białych znaków.

Martijn Verburg
źródło
3

Uważam, że linia powinna zaczynać się od najwyższego symbolu w drzewie analizy instrukcji, którą chcesz złamać. Podkreśla operatora, który jest najważniejszy w wyrażeniu. Jest to ten sam powód, dla którego umieściłeś inny na początku linii, a nie na końcu poprzedniej linii.

W poniższym przykładzie, skanując lewy margines, widzisz strukturę instrukcji jako OR 3 wyrażeń.

if (ch>='A' && ch<='Z'
    || ch>='a' && ch<='z'
    || ch>='0' && ch<='9')
{...}

Poniżej || operatorzy są mniej wyróżnieni. Jest mniej oczywiste, że jest to || wyrażeń. Zwłaszcza jeśli linie miały różne długości.

if (ch>='A' && ch<='Z' ||
    ch>='a' && ch<='z' ||
    ch>='0' && ch<='9')
{...}

I tylko w celach informacyjnych, to bardzo źle. || operatorzy w ogóle nie są podświetleni.

if ( ch>='A' && ch<='Z' || ch>='a'
     && ch<='z' || ch>='0' && ch<='9')
{...}

Lubię nawet wstawiać przecinki na początku wiersza, chociaż rzadko to widzę. Powstrzymuję się od robienia tego na wspólnym kodzie.

var note:Object =
    { key: key
    , type: 'P'
    , text: someLongProcedureCallGettingTheUserInitials()
       + ": " + getTheTextThatWasTyped()
    };
Florian F.
źródło
2

W przypadku długich równań arytmetycznych zwykle robię jedną z dwóch rzeczy.

zostaw wszystko w jednym wierszu:

foo = bar + baz - fizz + buzz + alpha - beta;

Zazwyczaj robię to dla równań zawierających tylko dodawanie i odejmowanie, bardzo łatwo jest napisać literówkę z mnożeniem i dzieleniem, które mogą poważnie zepsuć zakres operatora.

drugi format, którego używam, to operatory progresywne:

foo = bar;
foo += baz;
foo -= fizz;
foo += buzz;
foo /= alpha - beta;
foo *= spiff;

Nie widzę powodu, aby skracać go do jednej linii, chyba że można udowodnić, że poprawia wydajność w zauważalny sposób. Ponadto nie ma wątpliwości co do tego, co się dzieje, i istnieje mniejsza szansa na zgubienie nawiasu dla operatorów /i *.

zzzzBov
źródło
2

Umieszczenie znaku konkatenacji (lub dowolnego operatora) na początku wiersza poprawia czytelność. Skanujemy kod, koncentrując się na początku każdej linii. Kiedy linia zaczyna się od operatora, czytelnik może stwierdzić, że linia jest kontynuacją poprzedniej instrukcji, skanując ten jeden znak.

Długie wyrażenia matematyczne są zawsze składane, dzięki czemu każda nowa linia zaczyna się od operatora. Nie ma powodu, dla którego kod nie powinien być zgodny z tą konwencją.

Kevin Cline
źródło
0

Pozostaw wyrażenie w jednym wierszu, a jeśli stanie się zbyt długie, podziel je na mniejsze wyrażenia:

days = ((year * months_per_year) + month) * days_per_month + day

staje się:

months = year * months_per_year + month
days = months * days_per_month + day

Jeśli nie jest to możliwe, uważam, że łatwiej jest złamać się przed operatorem i pozwolić operatorowi rozpocząć bezpośrednio poniżej poprzedniego zadania (umieszczenie go poniżej zmiennej zmusza mnie do myślenia i wyśrodkowania, co jest denerwujące, biorąc pod uwagę, że cel jest ułatwienie czytania):

random = years * months_per_year 
         + month * days_per_month 
         + day * hours_per_day 
         + hour * minutes_per_hour 
         + minute * seconds_per_minute 
         + second
Joel
źródło
1
Ta odpowiedź nie dodaje nic nowego do tego, co zostało już powiedziane.
Martijn Pieters,