Це погана ідея перераховувати кожен аргумент функції / методу в новому рядку і чому?


22

Я працюю з тим, хто щоразу, коли вони викликають функцію, вони ставлять аргументи на новий рядок, наприклад

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

Мені це дуже дратує, оскільки це означає, що код не дуже компактний, тому мені потрібно сканувати вгору і вниз більше, щоб насправді мати сенс логіки. Мені цікаво знати, чи це насправді погана практика, і якщо так, то як я можу переконати їх цього не робити?


25
+1, я не знаю достатньо, щоб відповісти на ваше запитання, але я також ненавиджу це. Якщо у вас є стільки аргументів у функції, то, можливо, ваша функція робить занадто багато.
maple_shaft

28
Більш суттєво, чому ми все ще мусимо бачити один одного вподобання щодо цього? чому наші IDE не можуть автоматично представити їх у будь-якому стилі, який ми хочемо?
Алекс Фейнман

5
Майк, мені подобається, що код займає мінімальну нерухомість екрана. Але це компроміс. Я розміщую {на окремому рядку, тому що це полегшує співставлення із закриттям} та правильно зрозуміти область блоку. Варто компромісувати втрату рядка екранної нерухомості.
Брайан Шрот

2
@Alex: Ви абсолютно праві. Я думаю, що правильним було б мати мову, де дерево розбору коду зберігається на диску та відображається відповідно до вподобань користувача.
Ніл G

1
@maple_shaft Я зневажаю такі заяви. Не тому, що в цьому немає правди, а тому, що занадто багато людей дотримуються таких порад, не залишаючи місця для нюансів.
Штійн

Відповіді:


38

Це просто керівництво щодо кодування, яке вам може не сподобатися. Важливим є те, що ви та ваші колеги погоджуєтесь використовувати його чи ні.

Очевидно, що найкращим способом підвищення читабельності є обмеження кількості аргументів.


24
Занадто багато людей зменшують аргументи, скидаючи їх у масив. Я вважаю за краще потворний безлад, ніж чистіший вигляд коду з прихованою складністю.
Satanicpuppy

18
Масиви - це не шлях. Може бути структура, яка ховається в аргументах, або, можливо, ця функція робить занадто багато, і її слід розділити.
Майкл К

4
Я вважаю, що використання декількох рядків допомагає зробити код читабельним, якщо параметри IF мають тривале вираження або кілька занадто багато. Інакше це просто дратує.
PedroC88

3
Поміщення їх в об’єкт передачі даних просто пересуває проблему. Якщо всі аргументи потрібні, то всі вони повинні бути обов’язковими аргументами конструктора DTO, а це означає, що у вас ще є стільки аргументів.
Скотт Вітлок

21

Це питання переваги. Для складних викликів функцій, де потрібно задокументувати кожен параметр, або де змінні досить довгі і їх багато, це може бути добре.

Наприклад:

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,
 );

З мовами, які дозволяють іменовані параметри, це частіше, якщо ви використовуєте імена параметрів (приклад є в 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); 

Але я згоден з вами, що якщо виклик функції простий і не надто багато параметрів, це може набриднути, наприклад:

setColour (
    r,
    g,
    b
 );

Мені набагато легше читати як

 setColour(r,g,b);

Для @ammoQ:

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

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

11
Перший приклад - неправильна відповідь на реальну проблему. Чому б в першу чергу не використовувати явні змінні аніми?
deadalnix

@deadalnix: Добрий момент, трохи почистив.
FrustratedWithFormsDesigner

1
Правда. Однак це не завжди проблема зі змінними іменами. Це більше стосується довгих імен змінних, аргументів із значеннями за замовчуванням тощо
inspectorG4dget

4
Я б заперечував, що кращим рішенням проблеми є рефактор do_complex_op (), тому він приймає структуру як параметр. Потім ви можете це зробити do_complex_op(new paramStruct { StartingState = 0, XCoord = xcoord }), тоді це стає
самодокументуванням

1
@KallDrexx: Я згоден, але іноді зміна коду - це не варіант, наприклад, коли це функція в чужій бібліотеці. Звичайно, я міг би зробити його обгорткою, але мені все одно доведеться зателефонувати в їх початкову функцію.
FrustratedWithFormsDesigner

10

ІМО все, що є рідкістю, є поганою практикою, якщо тільки перевагу над звичайним стилем не можна позитивно довести. "Питання смаку" - це поганий привід для написання коду, який важче прочитати, ніж це потрібно більшості програмістів, тому що одного дня бідній душі, що не звикла до цього стилю, доведеться підтримувати цей код.

Довести, що це рідко, досить просто, покажіть джерело прикладів на MSDN або подібних сайтах, покажіть великі бази відкритого коду тощо. Покажіть вихід красувачів коду. Зрештою, покажіть, як хтось інший у вашій команді це робить. Не сприймайте поганий стиль лише тому, що хтось занадто впертий.


Гм ... з таким підходом, як ми могли коли-небудь запровадити нову найкращу практику (або, граматично правильно: кращу практику )?
Треб

2
Треб: Звичайно, просто покажіть, що краща практика насправді краща , а не просто інша .
користувач281377

4
Але "важче читати" - це сам по собі суб'єктивний і питання думки. Для мене один аргумент на рядок простіше проаналізувати візуально, ніж два, три чи чотири аргументи на рядок. Я завжди розбиваю виклик на кілька рядків, якщо він перевищує позначку 100 символів у редакторі.
Toby

2
Мех. "Важко читати" можна виміряти об'єктивно. Це просто не буває. Сперечатися про це веселіше.
JasonTrue

1
його можна вимірювати об'єктивно, але не незалежно від того, хто читає.
jk.

9

Ну ось ось якась прищепка. Мене ніколи не звинувачували у виконанні популярної речі. Ясна річ, якщо речі вміщуються в одній лінії, то добре, підходять вони в одну лінію.

Але моя головна турбота - не те, чи код "потворний" чи "гарний". Моя головна турбота - як легко зрозуміти та внести зміни, не роблячи помилок.

Якщо аргументи довгі і їх дуже багато, чому б не викласти їх в окремі рядки? На мій погляд, це полегшує бачити, що вони є, і легше змінювати їх у разі потреби. Це також дає мені можливість прикласти коментар до кожного аргументу, якщо я хочу.

Я також хочу мінімізувати ймовірність помилки, якщо додати або видалити аргумент до функції, що швидше трапиться в кінці списку аргументів, ніж на початку. З цієї причини я вважаю за краще ставити кому (,) на початку рядка, ніж наприкінці. Потім, якщо, наприклад, я хочу видалити або додати аргумент в кінці списку, це однорядне редагування. Мені не доводиться поспішати з комою, яка повинна проходити в кінці всіх рядків, але останній, де останній повинен закінчуватися дужками.

Тож (хлопче, мене за це спалахнуть) я пишу так:

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

Коли є функція з п’ятьма до двадцяти аргументів, функція не стала таким чином все відразу. З часом вона зростала, тобто було багато змін. Будь-яке редагування не завершено - це синтаксична помилка або помилка. Тому я не стверджую, що це досить. Я стверджую, що це допомагає в правильному редагуванні.

(А для тих, хто каже, що я повинен передати структуру замість цього, все, що є, змістить проблему, тому що для заповнення структури вам потрібна купа рядків коду, не кажучи вже про додатковий код, щоб заявити і розподілити його.)


1
Я особисто думаю, що це чудова відповідь, тому що ви дуже добре пояснили свої міркування. Гарна робота Майк.
Йорданія

8

Я б також не називав це. Найкраща практика, де я працював, зазвичай, щоб виклики функцій були усі на одній лінії, якщо тільки вам не доведеться горизонтально прокручувати якусь значну суму, щоб побачити весь виклик. Його рішення закликає, але я б точно сказав, що ставити всі подібні функції не в порядку, якщо це не стандарт, встановлений вашою організацією.

Ось чому організація є хорошою практикою створити набір посібників, яких повинні дотримуватися всі програмісти. Це все про послідовність і читабельність.


5

Це полегшує:

  • Перестановити аргументи.
  • Коментуйте або відключайте аргументи.
  • Подивіться, який саме аргумент змінився, коли у вашій системі управління версіями розглядаються відмінності
  • Під час додавання або вилучення аргументу чи зміни назви функції уникайте повторного відступу та загортання слів. (Навіть якщо ваш редактор автоматично відступає, ви все ще створюєте безліч корисних змін пробілу, які ускладнюють слідкувати за змінами у вашій системі управління версіями.)

4

Я б сказав, що виклики функцій повинні бути в одному рядку, якщо вони значно перевищують стандартну ширину коду (часто 80 символів, часто є причиною аргументів :-).

Я не бачу жодної переваги в цьому стилі. Це виглядає суб'єктивно некрасиво, і я вважаю це болем при пошуку коду. Наприклад, ви можете швидко здійснити пошук і побачити, чи функціонує коли-небудь з певним параметром, переданим як NULL. Це візуально легко, коли всі параметри знаходяться на одній лінії, і складніше, коли вони розбиті таким чином.


Ця річ з 80 символів повинна пройти, просто немає жодних технічно обґрунтованих причин для цього. Зараз ми живемо в епоху моніторів 19xx X 16xx та регульованих шрифтів та розмірів шрифтів.
анонс

4
@anon: Вагомі причини цього? Чому, на вашу думку, текст друкується стовпцями, а книги вужчими, ніж вони могли бути? Тому що людське око втрачає слід, читаючи через дуже довгі рядки.
Zan Lynx

4
@anon: Також я люблю використовувати свій широкоекранний екран, щоб два або три файли були відкриті в горизонтальному розділі, який повертається до 80-100 символів у рядку.
Зан Лінкс

4
@anon: Технічно ні, практично: пекло ТАК. Зан Lynx цілковиту рацію, а також є додаткові причини: злиття, диф, використовуючи утиліти командного рядка ... Ох , і удачі з акцентом на 8р шрифту , як ви стаєте старше: о)
MaR

3

Я часто бачив цей стиль у деклараціях функцій або визначеннях , але ніколи на дзвінку (до цих пір). Там є сенс іноді, оскільки це дозволяє чіткіше додати коментар до окремих параметрів. Схоже, він скопіював цей стиль на дзвінки, не знаючи причин, що стоять за ним. Ви маєте хороший аргумент проти, і він, схоже, не має для цього хорошого, тому ви маєте мій голос, але я не той, кого ви повинні переконати.


Бачу обох на дзвінках. Якщо список параметрів занадто довгий, його слід розбити на кілька рядків. Якщо параметри не групуються зазвичай в межах ширини, я очікую, що вони будуть в окремих рядках. Якщо назви функцій та параметрів добре вписуються в один рядок, я часто бачу їх таким чином.
BillThor

2

Це проти стандартів кодування компанії?

Якщо ні, то ініціюйте дискусію про стандарти та те, що люди хотіли б побачити зміни. Переконайтеся, що ви сприймаєте це як одну з речей, які ви хочете змінити.

Проведіть повну дискусію про те, чому ви не вважаєте, що це корисно, і, сподіваємось, ви виграєте день. Ви ніколи не знаєте, що ваш колега може переконати вас, що його шлях найкращий зрештою;)

Після того, як ви отримаєте оновлений стандарт, тоді буде задокументовано, що потрібно кодувати всім, тому, якщо ваш колега буде наполягати на цьому, ви можете підняти його у своїх оглядах коду.


2

Це може здатися вам приємним, але це полегшує роботу над кодом. Під час рефакторингу ви можете легко коментувати окремі аргументи та перевіряти свій рефактор перед тим, як фактично видаляти речі. Ви також можете коментувати та тимчасово замінювати типи досить легко.

Це також легше читати, ніж:

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

Я не настільки екстремальний, як ви показуєте (оскільки немає імен в параметрах, він не сильно використовує), але я потрапив у звичку або розділяти кожен параметр за власним рядком, або взагалі не робити розбиття.

Важлива частина полягає в тому, що ваш код можна роздрукувати або відображати на стандартних 80-ти колькових дисплеях і залишатись розбірливим.


2

Ви дуже рідко отримаєте від програміста чесну відповідь на щось подібне. Кожен просто відповість тим, що робить чи не віддасть перевагу. Правда полягає в тому, що, скільки ми всі боремося з цим часом, єдиною «поганою практикою» тут є ваша власна негнучкість.

Ви повинні бути жорстоко чесними до себе, щоб мати можливість розрізняти речі, які насправді погані, і речі, які просто вас дратують. Правда полягає в тому, що в C / C ++ і подібних мовах ви рідко зустрінете практику відступу, яка відчутно вплине на зрозумілість коду. Більшість дискусій про подібні речі просто мають обидві сторони, коли люди роблять смішні, недоброзичливі аргументи, щоб спробувати виправдати власні особисті переваги.

На мій прочитання ... це саме те, що ви вимагаєте в цьому запитанні: смішний, сумлінний аргумент, щоб виправдати свої особисті переваги.


0

Якщо чесно, це залежить від людини. Я б сказав, що для складних функцій, як це продемонстрував перший приклад FrustratedWithForms, то так; інакше великий НІ. Потім знову це питання, чому я вважаю за краще застосовувати функціональність IDE коду довільно.


0

"Мені цікаво знати, чи це насправді погана практика ..."

Так, це погана практика, за винятком випадків, коли список змінних аномально довгий. Але в цьому випадку проблема, ймовірно, пов'язана з конструкцією функції. Чому б не передати об’єкт, який інкапсулює багато параметрів?

"... і якщо так, то як я можу переконати їх цього не робити?"

Зв’яжіть їх і продовжуйте лоскотати, поки вони не погодиться припинити це лайно.


"Чому б не передати об'єкт, який інкапсулює багато параметрів?" Гаразд, тепер ви перенесли проблему на цей новий об’єкт. Він як і раніше потребує однакової кількості параметрів (наприклад, через його конструктор), тому у вас все ще є та сама проблема.
Штійн

-2

Чому ви витрачаєте цикли на таку банальну проблему? Просто запустіть ваш надійний IDE, відкрийте файл та переформатуйте. Вуаля! Це буде в будь-якій формі, яку ви хочете.

Тепер перейдемо до дійсно важливого питання - vi або emacs, LOL.


І тоді, коли ви приїдете перевірити це на контроль джерел?
pdr

-2

Я б сказав, якщо аргументи вмістяться в одному рядку, зробіть так. Якщо ні, то один аргумент на рядок забезпечує велику читабельність.

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

vs.

foo(
    arg1=arg1,
    arg2=arg2,
    arg3=arg3,
    arg4=arg4,
    arg5=arg5,
    arg6=arg6,
    arg7=arg7
)

3
це, здається, не пропонує нічого суттєвого щодо питань, викладених та пояснених у попередніх 14 відповідях
gnat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.