Является ли читабельность допустимой причиной не использовать const в (справочных) параметрах?

24

При написании некоторых функций я нашел ключевое слово const в таких параметрах:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

часто вызывает разделение строки на 2 строки в IDE или vim, поэтому я хочу удалить все ключевые слова const в параметрах:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

это действительная причина не использовать const? Можно ли поддерживать объекты параметров без изменений вручную?

ggrr
источник
110
«Эй, я хочу функционально изменить свою программу», чтобы сделать ее более читаемой, это плохая и плохая причина.
Питер Б
37
Программа все равно не становится более читаемой - как только вы видите, что что-то передается, у constвас есть сильный намек, что вам не нужно беспокоиться о том, как это может быть изменено в функции.
Тофро
43
Лучший способ улучшить читабельность - уменьшить количество аргументов.
5gon12eder
15
«const», возможно, улучшает читабельность. Это утверждение дает понять, что obj не может измениться!
Чарльз
14
Что могло бы помочь читабельности, так это добавление пробела после каждой запятой.
Сэм Хоцевар

Ответы:

182

Читаемость является веской причиной, чтобы научиться использовать пробелы:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

Расположенные там параметры не будут перепутаны с телом функции. Размещая их в другой строке, вам не придется менять положение, когда вы меняете имя myFunctionна более информативное. Пользователи не оценят изменения настроек положения, когда они не изменились.

constчто-то значит Не выбрасывайте это только потому, что у вас нет места и идей. Читаемость - это главное, но ломать голову от ее имени - просто сдаться.

candied_orange
источник
6
«вам не придется перемещать их, когда вы меняете имя myFunction» - хотя в этом случае это выглядит так, как если бы они были расположены примерно на одной линии с отверстием (, и если это так, то вам, возможно, придется изменить положение их, если длина имени класса + функции изменяется более чем на 4 символа. Поэтому, если вы не хотите этого делать, добавьте фиксированное количество уровней отступа, а не число, которое зависит от длины имени функции. Я бы порекомендовал 1 уровень, этот ответ использует 6, но любое фиксированное число достигает поставленной цели :-)
Стив Джессоп
6
@CandiedOrange Я удивлен, что вы не использовали "форму 6" в этом ответе ... это явно менее уродливо!
svidgen
6
Форма 6 для победы. Одно табуляция для одного уровня отступа. Просто и эффективно. Проблема решена :)
Легкость гонок с Моникой
2
Хорошо, хорошо, форма 6 это так. Это вариант, который Джефф Григг упомянул на с2.
candied_orange
4
@ random832 Я думаю, что мы сейчас находимся на территории сарая для велосипедов. Вот правильный способ решения этой проблемы: найдите в своей базе кода примеры, обратитесь к руководству по стилю вашего магазина, спросите разработчиков в своем магазине, и если ничего из этого не дает достоверного ответа, используйте это. Разрешите споры, которые могут пойти в любую сторону с четвертью. Как только четверть заговорила, будьте последовательны!
candied_orange
52

На самом деле проблема читабельности определенно идет в другом направлении. Во-первых, вы можете тривиально решить вашу линию запуска, используя пробелы . Но удаление constне только делает строку короче, но и полностью меняет смысл программы.

Трава Саттер упоминается constв ссылке constкак наиболее важная,const поскольку ссылка на constможет привязать к временному и продлить его срок службы. Lvalue ссылка на non- constnot, вам нужна отдельная переменная.

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

Для удобства использования это означает, что вам придется вводить все эти временные переменные, чтобы иметь возможность вызывать вашу функцию. Это не очень хорошо для читабельности, поскольку эти переменные не имеют смысла и существуют только потому, что ваша подпись неверна.

Барри
источник
6
Ваш второй абзац вызывает у меня головную боль, когда я пытаюсь выяснить, constссылается constили нет на другое constи что constдействительно является самым важнымconst
Mindwin
3
@Mindwin Я думаю, что ирония в том, что мой второй абзац ясен и однозначен, и я понятия не имею, о чем ты говоришь.
Барри
2
@ Барри Это, безусловно, однозначно, но мне потребовалось несколько прочтений этого параграфа, чтобы понять, что это значит. Я думаю, что некоторые проблемы заключаются в том, что он может быть проанализирован: «Херб Саттер относится к const (в отношении const) как к наиболее важному const ...» или «Херб Саттер относится к const в (отсылке к const) как к наиболее важный конст ... "Я считаю, что последнее является единственной действительной группировкой слов, но для ее обработки требуется немного времени. Может быть, есть способ использовать кавычки для устранения неоднозначности?
Cort Ammon - Восстановить Монику
1
Я думаю, что некоторые дефисные соединения прояснят это.
shawnt00
2
или специально использовать, const&а не ссылаться на constсуществительное (-фраза) там
Caleth
21

Простой ответ - нет.

Длинный ответ заключается в том, что constключевое слово является частью контракта, который предлагает функция; он говорит вам, что аргумент не будет изменен. Момент, когда вы снимаете constэту гарантию, выходит из окна. Помните, что вы не можете разумно поддерживать константность (или любое другое свойство) чего-либо с помощью документации, соглашений или рекомендаций - если компилятор не обеспечивает константность, кто- то подумает, что он может упростить свою работу, если он возится с параметр "чуть чуть". Рассмотреть возможность:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

Помимо того, что последняя версия является более краткой, она также обеспечивает более сильный контракт и позволяет компилятору поддерживать ваши намерения. Первый не делает ничего, чтобы помешать fna(Foo&)функции изменить передаваемый ей параметр.

Как и в ответе @CandiedOrange, вы можете использовать пробелы для разметки кода и повышения читабельности.

Мэл
источник
14

Удаление constключевого слова удаляет читабельность, поскольку constпередает информацию читателю и компилятору.
Сокращение горизонтальной длины кода - это хорошо (никто не любит боковую прокрутку), но есть нечто большее, constчем просто текст. Вы могли бы переписать это:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Что не меняет контракт, но удовлетворяет необходимость сокращения длины линии. Действительно, я бы посчитал приведенный выше фрагмент менее читабельным и выбрал бы больше пробелов, как уже упоминалось в ответе CandiedOrange.

constэто функциональность самого кода. Вы не сделаете функцию не-членом для удаления MyClass::раздела объявления, поэтому не удаляйтеconst

Эрдрик Айронроуз
источник
4
Я согласен, что предоставленный вами фрагмент менее читабелен. Это заставляет читателя пойти выяснить, что MObjи strесть, и, конечно, поднимает брови. Это особенно странно для типов, чьи имена вы уже контролируете: например, почему вы просто не назвали MyObjectкак MObjдля начала?
Джейсон С
3

Является ли читабельность допустимой причиной не использовать const в параметрах?

Нет. Пропуск constможет изменить функциональность, утратить защиту constи потенциально может создать менее эффективный код.

Можно ли поддерживать объекты параметров без изменений вручную?

Вместо того, чтобы тратить время на форматирование кода вручную

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

Используйте инструменты автоматического форматирования . Напишите функцию в соответствии с ее функциональными требованиями и позвольте автоформатированию обрабатывать презентацию. Ручная настройка форматирования не так эффективна, как использование автоматического форматирования и использование сэкономленного времени для улучшения других аспектов кода.

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}
Chux - Восстановить Монику
источник
-1

Как можно дольше, лучше держать константу видимой. Это значительно улучшает обслуживание кода (без догадок, чтобы увидеть, изменит ли этот метод мои аргументы).

Если я вижу много аргументов в методе, это заставляет меня задуматься о создании jaron на основе проекта (Matrix, Employee, Rectangle, Account), который будет намного короче, легче для понимания (исключает длинный список аргументов методов).

черная ручка
источник
Согласовано. Я не решался указать на это. Таким образом, «крайний случай».
черная ручка
@cmaster Тем не менее, иногда в определенных контекстах, с некоторыми программистами, он может оставаться читаемым. Например, в очень специфическом случае программы, по пояс в вызовах Windows API, с читателем, который привык к этой среде, такие вещи, как, например, typedef Point * LPPOINTи typedef const Point * LPCPOINT, хотя и очень неприятный, по-прежнему несет неявный смысл, потому что это соответствует непосредственным ожиданиям в контексте. Но никогда в общем случае; это просто странное исключение, о котором я могу думать.
Джейсон С
1
Да, когда я увидел вопрос, мне пришло в голову «const unsigned long long int», но это не хороший кандидат, чтобы извлечь выгоду из того, что он «const» или «reference». Typedef решает общую проблему сокращения имен; но не очень хороший дизайн, чтобы скрыть само назначение языковых конструкций (например, «const»).
черная ручка