Где обернуть строку кода, особенно длинные списки аргументов?
Как вы предпочитаете переносить строки кода, особенно когда речь идет о длинных списках аргументов?
Было несколько вопросов, касающихся переноса строк (например, когда вы пишете код: перенос текста или нет? И стандарт форматирования ширины строки), но мне не удалось найти тот, который описывает, где переносить строку кода.
Допустим, у нас есть строка кода, которая продолжает работать, как в следующем примере:
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1, Argument2, Argument3, Argument4);
Как это должно быть завернуто?
Вот несколько способов, которые я могу придумать, и некоторые их недостатки:
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1, Argument2,
Argument3, Argument4);
Лично я не предпочитаю эту опцию, потому что форматирование, кажется, визуально отделяет список аргументов от метода, который я пытаюсь вызвать, тем более, что прямо над несвязанными аргументами в новой строке стоит знак равенства присвоения ("=").
Итак, какое-то время я придерживался следующего подхода:
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1,
Argument2,
Argument3,
Argument4);
Здесь все аргументы связаны друг с другом, все на стороне первого аргумента метода. Однако, одна загвоздка в том, что список аргументов не всегда выстраивается во второй строке и далее из-за количества пробелов, которые отступает вкладка. (И ввод дополнительных пробелов для форматирования будет слишком трудоемким.)
Ответ на один из предыдущих вопросов предложил следующий формат:
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1,
Argument2,
Argument3,
Argument4
);
Мне действительно нравится этот формат из-за его визуальной привлекательности, но он также визуально отделяет аргументы от метода, которому принадлежит список. Кроме того, я предпочитаю, чтобы один вызов метода не занимал слишком много строк.
Итак, мой вопрос заключается в том, что, не вдаваясь в проблему предотвращения слишком длинного кода строки, как бы вы порекомендовали перенос строк кода? В частности, где можно разбить строку кода, когда речь идет о длинных списках аргументов?
14 ответов
int SomeReturnValue = SomeMethodWithLotsOfArguments
( Argument1,
Argument2,
Argument3,
Argument4
);
Предложенный вариант 3
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1,
Argument2,
Argument3,
Argument4
);
это лучший способ, так как он дает хорошее чувство. Если длина аргументов более или менее одинакова, то мы можем собрать их вместе, например, чтобы они выстроились в таблицу
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1, Argument2, Argument3, Argument4,
Argument005, Argument006, Argument7, Argument8
);
Я предпочитаю этот способ:
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1, Argument2,
Argument3, Argument4);
Где строка заканчивается ближе всего к вашей текущей максимальной ширине линии (независимо от того, что это), а следующая строка имеет отступ от вашего обычного уровня отступа (независимо от того, что это) относительно знака равенства.
Не знаю почему, но я думаю, что это наиболее читаемый вариант в большинстве ситуаций. Тем не менее, я предпочел не быть педантичным в отношении этих вещей, и я всегда предпочитаю то, что наиболее читабельно для данного раздела кода, даже если это может нарушить некоторые правила отступа или форматирования (в определенных пределах, конечно).
Одним из примеров этого может быть, если функция требует много аргументов или аргументов, которые сами по себе сложны, тогда я мог бы выбрать что-то вроде этого:
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1 + Expression1 + Expression2,
Argument2 - Expression3 * Expression4,
Argument3,
Argument4 * Expression5 + Expression6 - Expression7);
Конечно, если выражения аргументов очень длинные или сложные, было бы лучше выполнить вычисления перед вызовом функции и использовать временные значения для сохранения результатов.
Я стараюсь держать линии короткими. В этом случае я бы нарушил перед присваиванием и после каждого параметра. Я также ставлю запятую в начале строки, чтобы было проще добавлять новые аргументы:
int SomeReturnValue
= SomeMethodWithLotsOfArguments(
Argument1
, Argument2
, Argument3
, Argument4
);
Использование такого типа компоновки - большая работа в Visual Studio, но Emacs делает ее автоматической для меня.
Первый
Если арги достаточно короткие и имеют (почти) одинаковую длину, я думаю, что ниже визуально достаточно хорошо
int variable_with_really_long_name = functionWhichDoMore(Argument1, ArgumentA2,
ArgumentA3, Argument4,
ArgumentA5, Argument6);
второй
Когда становится хуже, один столбец аргумента действительно помогает
int variable_with_really_long_name = somefunctionWhichDoMore(Argument_Expand1,
Argument2,
Argument_Expand3,
Argument_Expand4,
Argument_Expand5,
Argument6);
В третьих
Но, теперь, Как, если это ухудшится! Что теперь? Попробуй это
int variable_with_really_long_name = someFunctionWhichDoMore
(
Argument_Expand_More1,
Argument_Expand_More2,
Argument_Expand3, Argument4,
Argument_Expand_More5, Argument6
);
Кстати, если вы хотите последовательный вид, используйте третий во всех условиях выше.
Обоснуйте: аккуратно наденьте, и мы знаем, что это вызов функции с большим количеством (6) аргументов. И мне нравится мой код выглядит аккуратно и !(so_ugly)
,
Критики приветствуются. Пожалуйста, прокомментируйте.
Лично мне не нравится второй вариант, слишком близкий к искусству Ascii, с его неудобствами в коде: измените имя функции, вы должны заново сделать отступы для всех аргументов. И как-то это раздувает файл. Кроме того, это не работает, если вы используете жесткие вкладки в коде.
Большую часть времени я использую первый вариант, но я принял правило Eclipse для двух отступов для строк продолжения, так как оно лучше, чем обычные отступы (особенно если вы разделяете условные инструкции).
Иногда я использую второй вариант, например. если открывающая скобка уже близка к моему пределу длины строки...
Преимущество: вы можете добавить комментарий к строке после каждого параметра.
Или мне нравится Dheer, группирующий аргументы, пока они не заполнят ширину строки.
Тот факт, что аргументы отделены от имени функции, никогда не беспокоил меня, они все еще рядом и довольно сгруппированы. В худшем случае я могу поставить пустые строки вокруг вызова функции.
В функциях с длинным списком параметров я оборачиваю после каждого одного или двух параметров для удобства чтения (всегда сохраняя одинаковое количество параметров в каждой строке):
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1,
Argument2,
Argument3,
Argument4);
ИЛИ ЖЕ
int SomeReturnValue = SomeMethodWithLotsOfArguments(Argument1, Argument2,
Argument3, Argument4);
в зависимости от длины списка / параметра.
Для меня нет однозначного ответа. Я делаю это на индивидуальной основе. Если имя функции длинное, я определенно не делаю отступ для других аргументов в том же столбце, что и предыдущие аргументы. Если имя функции короткое, я обычно делаю следующие аргументы для одного и того же столбца, собирая столько аргументов, сколько могу в одной строке (не один аргумент = одна строка). Но если есть какая-то приятная симметрия, как в
int a = foo(a + b,
c + d);
я бы, вероятно, нарушил это правило и имел бы одинаковое количество аргументов в каждой строке.
Для меня это зависит от длины списка аргументов. Мне не очень нравится конец строки, и он почти требует поддержки редактора (например, emacs), чтобы сделать это хорошо.
Если вызов метода достаточно короткий, чтобы поместить его в одну строку, я сделаю это:
int SomeReturnValue =
SomeMethodWithLotsOfArguments(Argument1, Argument2, ...);
Если метод и переменная помещаются в одну строку, а аргументы в другую, я сделал это:
int SomeReturnValue = SomeMethodWithLotsOfArguments
(Argument1, Argument2, ... );
Это заставляет мое сердце LISPy улыбаться, но сводит моих коллег с ума, поэтому я уступил:
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1, Argument2, ... );
Полагаю, я просто пытаюсь сказать, что не нашел решения, которым я действительно доволен, хотя в некоторых случаях это очень привлекательно из-за сходства с тем, как мы выкладываем фигурки:
int SomeReturnValue = SomeMethodWithLotsOfArguments(
Argument1,
Argument2,
);
Я всегда ломаюсь перед назначением, если это оставляет правую сторону неповрежденной. Это полезно в таких языках, как Java, где вы должны явно объявить тип назначенного значения.
SomeVeryVerboseTypeName SomeReturnValue
= SomeMethodWithLotsOfArguments(Argument1, Argument2, ...);
Большинство из них сделали отличные предложения по отступам, и это отлично подходит для функций API, которые вы не контролируете. Если вы управляете API, я бы предложил, чтобы после того, как у вас было более 3 аргументов, вы должны создать некоторую форму структуры и передать ее в рутину. Как только вы получите более 3 аргументов, вероятность передачи их в неправильном порядке возрастает. Это также дает больше видимости для типа и значения параметров.
someStruct.x = somevalue;
somestruct.y = someothervalue;
int someResturnValue - SomeMethod(somestruct);
Предупреждение: я использую IDE. Если вы не пользователь IDE, просто пропустите это.
При работе с другими:
Я склонен придерживаться любого соглашения, принятого в настоящее время командой. Еще лучше, если команда использует IDE с поддержкой формата кода. Всегда придерживайтесь правил формата команды /IDE. Не могу сказать, сколько раз я был сожжен "version-contro-diff-hell-for-reformats"
Работая в одиночку:
Я включаю метод, длина строки для меня не проблема. У меня есть хороший широкоэкранный монитор, и по какой-то причине были изобретены горизонтальные полосы прокрутки. Кроме того, навигация по исходному коду теперь представляет собой нечто большее, чем просто визуальную прокрутку, поскольку многие IDE имеют такие утилиты, как деревья вызовов, ссылки на поиск и инструменты рефакторинга.
Я также использую "непротиворечивый вариант отступа", как его цитирует Эдвард Кметт. Если есть много аргументов, я стараюсь сгруппировать их по родству, где это возможно.
Но для этого конкретного примера я бы, вероятно, оставил его в одной строке, это не так долго.
Я терпеть не могу формат "висящей обертки", поскольку он может легко создать визуальную путаницу, конфликтующую с (гораздо более важным) отступом. Оборванные обертки в настоящее время считаются стилем по умолчанию для многих языков, но я не знаю, как это получилось. Это ИМХО ужасно.
Я предпочитаю следующее
int variable_with_really_long_name = functionWhichDoMore(
Argument1, ArgumentA2, ArgumentA3, Argument4,
ArgumentA5, Argument6);
int i = foo(Argument1, ArgumentA2, ArgumentA3, Argument4,
ArgumentA5, Argument6);
Оба соответствуют друг другу, при достижении 80 символов я перехожу на следующую строку и размещаю 2 отступа по 4 пробела каждый. Моя аргументация для этого заключается в следующем:
Я использую 2 отступа по 4 пробела в каждом, чтобы наглядно увидеть тот факт, что это касается обернутой строки, а не блока кода с отступом.
Этот способ отступа сохраняет код с хорошим отступом, потому что он всегда следует одному и тому же шаблону отступа, 2 отступа для переноса строк, 1 отступ для блоков кода.
Размещение каждого аргумента в отдельной строке может привести к очень большим методам, поэтому я предпочитаю аргументы последовательно в одной или нескольких строках.
Этот способ переноса строк можно настроить в среде IDE, например Eclipse, предоставляя возможность автоматического форматирования.
Однако есть одно важное замечание, могут быть исключительные случаи, когда происходит следующее:
int variable_with_really_long_name = functionWhichDoMore(arg1,
arg2)
Я постараюсь избежать этого, если это произойдет, я сделаю следующее
int variable_with_really_long_name = functionWhichDoMore(arg1, arg2)
Да, я сделаю максимум 120 символов. Соглашение о длине строки кода, мое соглашение на самом деле гибкое, максимум от 120 до 140 символов, обычно я оборачиваюсь после 120, однако в этом случае я перейду к макс. 140 символов Недостатком этого является, конечно, то, что он не может быть настроен для автоматического форматирования в среде IDE, такой как eclipse.
пс. Я знаю, что некоторые люди думают, что 120 символов - это очень много для длины строки кода, но это совсем другое обсуждение. Вышеуказанные условные обозначения могут, конечно, также применяться для 80 / 100 символов.