Причина розміщення типу функції та назви методу на різних рядках у C


16

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

void foo() {
}

повинно бути це

void
foo() {
}

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


3
Це в стандарті GNU (не обов'язково говорити, що це хороша річ, стиль дужки дивний). gnu.org/prep/standards/standards.html#Formatting
Готьє

Відповіді:


19

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

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

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

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


2
Я думаю, він також пов'язаний з лінією обмеження 80 символів, яка все ще використовується і захищається багатьма програмістами. Якщо ви хочете мати обмеження в 80 знаків і хочете використовувати описовий метод / назви функцій, вам доведеться піти на компроміс. Розщеплення заголовка методу є одним з них.
Султан

Декларація також може бути довшою - подумайте про різні (нестандартні) модифікатори, наприклад, виклик ідентифікаторів конвенції (stdcall тощо), інформацію про видимість символів (DLLEXPORT) або __attributes. І тоді, дивлячись на C ++, ви можете мати відносно складні типи повернення, тож десь потрібно додати розрив рядка.
johannes

@Sulthan Цікаво, що це не просто програмісти (які використовуються для термінальних вікон та використання термінальних редакторів). При наборі 72-80 символів, як правило, вважається ідеальною шириною для стовпця тексту з точки зору читабельності. (Отже, чому TeX та його похідні за замовчуванням відповідають тим, що деякі люди вважають дивно вузькими колонками.)
JAB,

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

1
"Ще одна причина полягає в тому, що назви функцій завжди починаються в першому стовпці [і так] простіше знайти." І це набагато більше, ніж просто візуальна користь: тепер ми можемо шукати регулярний вираз ^start_of_a_long_funcі негайно переходити до функції, яку ми шукаємо.
підкреслити_3

7

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

Добре розробити мову програмування, щоб імена відображалися в послідовному положенні в деклараціях / визначеннях. Обґрунтування зрозуміло: у вас є приємний візуальний якір (фігурна дужка або просто висячий відступ), який ви можете використати, щоб негайно знайти початок назви. Вам не потрібно насправді розбирати мову під час сканування через файл, знайти ім'я.

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

Ранній C мав дуже стислі підписи: типи повернення були необов’язковими, а типи аргументів оголошувались після підпису. Імена також були дуже короткими. Це зменшило вплив випадкового повернення типу, що компенсує ім'я.

double dot(x, y);

Досі досить засвоюється.

C ++ зробило це трохи гірше. Він перемістив специфікації типу аргументів у підписи, зробивши підписи довшими. Цей синтаксис пізніше був прийнятий під час стандартизації С.

static struct origin *find_origin(struct scoreboard *sb,
                  struct commit *parent,
                  struct origin *origin)

менш засвоюваний, але не надто поганий. (Уривок з Git)

Тепер розглянемо сучасну практику програмування з довгими описовими іменами та параметризованими типами та подивимось, як цей вибір став катастрофічним. Приклад із заголовка Boost:

template <class A1, class A2, class A3, class A4, class A5, class A6>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
{ 
   typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
   return result_type(); 
}

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

Зрозуміло, що C, C ++ та їх похідні, Java та C #, є винятками із наявності читаних декларацій / визначень. Їх популярні попередники та однолітки (Fortran, ALGOL, Pascal) розміщували імена перед типами результатів, і, на щастя, багато хто з їхніх наступників (Go, Scala, TypeScript і Swift для того, щоб назвати декілька) також вибрали більш читаються синтаксиси.


1
Будьте вдячні, що вам не доведеться писати програми Fortran. Кажу вам, окремо заявивши, що аргументи вашої функції наберуться на нерви досить швидко, як тільки ви змушені це робити. Особливо, намагаючись прочитати підпис функції, щоб зрозуміти, які аргументи її очікують: C ++ ставить типи туди, куди вони належать, Fortran змушує вас почати візуальний пошук за ключовим словом для назви змінної, щоб визначити її тип.
cmaster - відновити моніку

2
Чи було розміщення типів у декларації функції справді винайдене C ++? Я ніколи не чув, щоб це було так, і я намагаюся знайти цитати.
підкреслюй_

1
Див в розвиток мови C . У розділі стандартизації Річі згадує, що синтаксис був запозичений із C ++.
user2313838

5

Я вперше зустрів цей стиль приблизно 19-го року, працюючи з C&C ++. Був дуже здивований тим, як хтось може вигадати цю злу річ.

Єдиний (потенційно) позитивний момент, який я міг знайти, - це те, що ви можете знайти визначення funciton за допомогою grep ^ FuncName. Можливо, це був би релевантний фактор десятиліття тому в деяких реальних спільнотах ненависних інструментів ... Там, де я бачив, він застосовувався до C ++ та функціонерів учасників класу, які вбивають навіть цей атрибут.

Вгадайте мою думку. :)


1
grep -P '^(\w+::)?FuncName'
Кайл Странд

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