Является ли определение переменной для именования аргумента метода хорошей практикой?


73

Для удобства чтения я часто определяю временные переменные при вызове функций, таких как следующий код

var preventUndo = true;
doSomething(preventUndo);

Короче версия этого к этому будет,

doSomething(true);

Но когда я возвращаюсь к коду, я часто задаюсь вопросом, к чему это trueотносится. Существует ли соглашение для такого рода головоломки?


5
Вы используете какую-то IDE? У большинства будет какой-то способ указать, какие параметры у функции, которую вы вызываете, что несколько сводит на нет необходимость делать это.
Мэтью Шарли

4
Я не использую IDE, но даже тогда я полагаю, что подсказка потребует каких-то действий (наведение мыши или перемещение к строке). Мне нравится знать, что делает мой код, просто взглянув на него.
methodofaction

11
Если язык поддерживает это, вы можете использовать перечисление, такое какdoSomething( Undo.PREVENT )
Джеймс П.

4
Но вы можете определить Undo = { PREVENT = true, DONT_PREVENT = false }. Но в JavaScript принято делать так: function myFunction( mandatoryArg1, mandatoryArg2, otherArgs ) { /*...*/ }а потом myFunction( 1, 2, { option1: true, option2: false } ).
xavierm02

6
Это определенно зависит от языка. Если бы это был, например, python, я бы предложил использовать только ключевые аргументы, напримерdoSomething(preventUndo=True)
Джоэль Корнетт

Ответы:


117

Объясняя переменные

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

Код хорошего качества сообщает о намерениях читателю; и как профессиональный разработчик удобочитаемость и удобство обслуживания являются вашими целями # 1.

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

editButton.Enabled = (_grid.SelectedRow != null && ((Person)_grid.SelectedRow).Status == PersonStatus.Active);

по сравнению с немного дольше, но, возможно, яснее:

bool personIsSelected = (_grid.SelectedRow != null);
bool selectedPersonIsEditable = (personIsSelected && ((Person)_grid.SelectedRow).Status == PersonStatus.Active)
editButton.Enabled = (personIsSelected && selectedPersonIsEditable);

Булевы параметры

Ваш пример на самом деле подчеркивает, почему логические значения в API часто являются плохой идеей - на вызывающей стороне они ничего не делают, чтобы объяснить, что происходит. Рассмотреть возможность:

ParseFolder(true, false);

Вы должны посмотреть, что означают эти параметры; если бы они были перечислениями, было бы намного яснее:

ParseFolder(ParseBehaviour.Recursive, CompatibilityOption.Strict);

Редактировать:

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


28
Если вы не используете именованные параметры (именованные аргументы в .NET Framework), в этом случае doSomething(preventUndo: true);достаточно ясно. Кроме того, создание перечисления для каждого логического в вашем API? Шутки в сторону?
Арсений Мурзенко

12
@MainMa: Если используемый вами язык недостаточно крутой для поддержки именованных аргументов, использование enum является хорошим вариантом. Это не означает, что вы должны систематически вводить перечисления везде.
Джорджио

18
@MainMa - Чтобы ответить на этот вопрос, суть в том, что у вас не должно быть логических значений в ваших API (по крайней мере, в ваших открытых). Вам нужно изменить синтаксис на именованный аргумент, который, возможно, не является идиоматическим (на момент написания), и в любом случае логический параметр почти всегда означает, что ваш метод выполняет две функции, и вы позволяете вызывающей стороне выбирать. Но смысл моего ответа состоял в том, что нет ничего плохого в использовании объясняющих переменных в вашем коде; на самом деле это очень хорошая практика.
Даниэль Б

3
Это постоянная часть языка C #, что еще нужно для «основного принятия»? Даже для тех, кто еще не знает о конструкции (что означает, что ваши разработчики C # даже не читали документы по C #), вполне очевидно, что она делает.
Нейт СК

3
Вот почему MS выпускает эти приятные резюме всех новых вещей, которые они добавляли в каждую версию, я не думаю, что это создает много работы для чтения одного из них каждые пару лет: msdn.microsoft.com/en- us / library / bb383815% 28v = vs.100% 29.aspx
Нейт

43

Не пишите код, который вам не нужен.

Если вам doSomething(true)трудно понять, вы должны добавить комментарий:

// Do something and prevent the undo.
doSomething(true);

или, если язык поддерживает это, добавьте имя параметра:

doSomething(preventUndo: true);

В противном случае положитесь на вашу среду IDE, чтобы получить подпись вызванного метода:

введите описание изображения здесь

Случаи, когда это полезно

Помещение дополнительной переменной может быть полезно:

  1. Для целей отладки:

    var productId = this.Data.GetLastProductId();
    this.Data.AddToCart(productId);
    

    Один и тот же код может быть записан в одну строку, но если вы хотите установить точку останова перед добавлением товара в корзину, чтобы проверить правильность идентификатора продукта, лучше написать две строки вместо одной.

  2. Если у вас есть метод с большим количеством параметров, и каждый параметр идет из оценки. В одной строке это может стать совершенно нечитаемым.

    // Even with indentation, this is unreadable.
    var doSomething(
        isSomethingElse ? 0 : this.getAValue(),
        this.getAnotherOne() ?? this.default,
        (a + b + c + d + e) * f,
        this.hello ? this.world : (this.hello2 ? this.world2 : -1));
    
  3. Если оценка параметра слишком сложна. Пример кода, который я видел:

    // Wouldn't it be easier to have several if/else's (maybe even in a separate method)?
    do(something ? (hello ? world : -1) : (programmers ? stackexchange : (com ? -1 : 0)));
    

Почему не в других случаях?

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

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

  2. Но из-за риска диссоциации имени вы дадите переменной имя параметра.

    Пример:

    Допустим, оригинальный код:

    void doSomething(bool preventUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code:
    var preventUndo = true;
    doSomething(preventUndo);
    

    Позже, разработчик, работающий над doSomethingзамечаниями, которые недавно, история отмены представил два новых метода:

    undoHistory.clearAll() { ... }
    undoHistory.disable() { ... }
    

    Теперь, preventUndoкажется, не очень понятно. Значит ли это, что будет предотвращено только последнее действие? Или, может быть, это означает, что пользователь больше не сможет использовать функцию отмены? Или что история отмен будет очищена? Более понятные имена будут:

    doSomething(bool hideLastUndo) { ... }
    doSomething(bool removeAllUndo) { ... }
    doSomething(bool disableUndoFeature) { ... }
    

    Итак, теперь у вас есть:

    void doSomething(bool hideLastUndo)
    {
        // Does something very interesting.
        undoHistory.removeLast();
    }
    
    // Later in code, very error prone, while the signature of the method is clear:
    var preventUndo = true;
    doSomething(preventUndo);
    

Как насчет перечислений?

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

enum undoPrevention
{
    keepInHistory,
    prevent,
}

void doSomething(undoPrevention preventUndo)
{
    doTheJob();
    if (preventUndo == undoPrevention.prevent)
    {
        this.undoHistory.discardLastEntry();
    }
}

doSomething(undoPrevention.prevent);

Проблемы с этим:

  1. Это слишком много кода. if (preventUndo == undoPrevention.prevent)? Шутки в сторону?! Я не хочу писать такие ifкаждый раз.

  2. Добавление элемента в перечисление очень заманчиво позже, если я использую то же самое перечисление где-нибудь еще. Что, если я изменю это так:

    enum undoPrevention
    {
        keepInHistory,
        prevent,
        keepButDisable, // Keeps the entry in the history, but makes it disabled.
    }
    

    Что теперь будет? Будет ли doSomethingметод работать так, как ожидалось? Чтобы предотвратить это, потребуется написать этот метод с самого начала так:

    void doSomething(undoPrevention preventUndo)
    {
        if (![undoPrevention.keepInHistory, undoPrevention.prevent].contains(preventUndo))
        {
            throw new ArgumentException('preventUndo');
        }
    
        doTheJob();
        if (preventUndo == undoPrevention.prevent)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

    Вариант, который использует логические выражения, начинает выглядеть так красиво!

    void doSomething(bool preventUndo)
    {
        doTheJob();
        if (preventUndo)
        {
            this.undoHistory.discardLastEntry();
        }
    }
    

3
«Это слишком много кода. If (protectUndo == undoPrevention.prevent)? Серьезно ?! Я не хочу писать такие if каждый раз.»: Как насчет использования старого доброго оператора switch? Кроме того, если вы используете логическое значение, вам все равно понадобится оператор if. Честно говоря, ваша критика в этом вопросе кажется мне несколько искусственной.
Джорджио

1
Мне не хватает альтернативного решения здесь. Вы говорите, что он должен придерживаться ничего не говорящего, истинного и ложного и полагаться на IDE (которую он не использует)? Комментарий может гнить как имя переменной.
Безопасное

2
@superM: мне не так сложно изменить имя временной переменной, используемой только для вызова. Если имя enum изменяется, то это даже лучше, потому что код вызова больше не запускается и выдает ошибку прямо в лицо. Если функциональность функции радикально изменена расширением enum, вам придется пересмотреть все вызовы для дальнейшей корректности, в любом случае, иначе вы программируете на надежде, а не на логике. Даже не думать об изменении значения, например , отрицая , preventUndoчтобы allowUndoв подписи ...
Secure

4
@superM. Синхронизация комментариев с кодом действительно очень проблематична, поскольку ваш компилятор не помогает в поиске несоответствий.
Буб

7
«… полагайтесь на свою IDE, чтобы дать вам подпись вызываемого метода» - это полезно, когда вы пишете код, но не так сильно, когда вы читаете его. Когда я читаю код для класса, я хочу знать, что он делает, просто взглянув на него. Если вам нужно полагаться на IDE для удобства чтения, ваш код не самодокументируется.
Фил

20

Также вы не должны писать методы с логическими флагами.

Цитируя Роберта К. Мартина, он говорит в своей книге «Чистый код» (ISBN-13 978-0-13-235088-4): «Передавать логическое значение в функцию - это действительно ужасная практика».

Перефразируя его, рассуждение состоит в том, что тот факт, что у вас есть переключатель истина / ложь, означает, что ваш метод, скорее всего, выполняет две разные вещи (например, «Делать что-то с отменой» и «Делать что-то без отмены») и поэтому должен быть разделить на два разных метода (которые могут вызывать одно и то же).

DoSomething()
{...

DoSomethingUndoable()
{....

7
По этой логике мой единственный конструктор HotDog должен был бы иметь около 16 различных методов: HotDogWithMustardRelishKrautOnion (), HotDogWithMustardNorelishKrautOnion () и так далее. Или это могут быть простые HotDogWithOptions (int options), в которых я интерпретирую параметры как битовое поле, но затем мы возвращаемся к одному методу, который делает несколько предположительно разных вещей. Поэтому, если я выберу первый вариант, нужно ли писать большое условное выражение, чтобы определить, какой конструктор вызывать, основываясь на тех вещах, которые в противном случае были бы логическими параметрами? И если Q использует int, этот A не отвечает на Q.
Калеб

4
После прочтения всех ответов и просмотра моего кода, я прихожу к выводу, что это правильный способ сделать это. doSomethingUndoable()может зафиксировать изменения и затем вызватьdoSomething()
methodofaction

1
Поэтому, если у меня есть функция, которая выполняет большую часть обработки и имеет возможность отправлять электронную почту, когда она будет завершена, у меня не должно быть логического аргумента, который может помешать отправке электронной почты, я должен создать отдельную функцию?
якатц

2
@Caleb В этом случае я бы либо сделал хот-дог и добавил ингредиенты один за другим, либо на языке со строгой типизацией я бы передал объект HotDogSettings, в котором я бы установил все логические флаги. У меня не было бы 15 различных истинных / ложных флагов, которые было бы кошмаром для поддержания. помните, что код - это обслуживание, а не запись, так как это 80% стоимости приложения. var hd = MakeHotDog (); hd.Add (Onion); ...
Ник Б.

2
@Caleb Я думаю, что различие заключается в том, что ваш пример использует логические значения в качестве фактического поля данных, в то время как большинство его применений для управления потоком выполнения; следовательно, дядя Боб против этого. Кроме того, его советы немного экстремальны - следующие несколько строк в книге запрещают иметь более двух параметров, что, возможно, является еще более экстремальной позицией. Есть метод к безумию, хотя. Вы абсолютно правы, что он не отвечает на вопрос, хотя я допустил ошибку в своем собственном ответе.
Даниэль Б

5

Когда вы посмотрите на два класса, чтобы увидеть, насколько они связаны, одна из категорий - это соединение данных , которое относится к коду в одном классе, вызывающему методы другого класса и просто передающему данные, например, за какой месяц вы хотите получить отчет, а другой Категория - это управление связью , вызов методов и передача чего-то, что управляет поведением метода. Пример, который я использую в классе - это verboseфлаг или reportTypeфлаг, но preventUndoэто также отличный пример. Как вы только что продемонстрировали, связывание управления затрудняет чтение кода вызова и понимание происходящего. Это также делает вызывающий код уязвимым к изменениям, doSomething()которые используют один и тот же флаг для управления отменой и архивированием, или добавляют другой параметр вdoSomething() контролировать архивирование, таким образом нарушая ваш код и так далее.

Проблема в том, что код слишком тесно связан. Передача bool для контроля поведения, по моему мнению, является признаком плохого API. Если у вас есть API, измените его. Два метода, doSomething()и doSomethingWithUndo(), было бы лучше. если вы не владеете им, напишите два метода-обертки самостоятельно в собственном коде, и пусть один из них вызовет, doSomething(true)а другой вызовет doSomething(false).


4

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

Переменная должна быть названа в честь их роли в текущей области видимости. Не Объем, куда они отправлены.


1
роль переменной в текущей области видимости заключается в том, чтобы указать, для чего она используется. Я не вижу, как это противоречит использованию OP временных переменных.
СуперМ

4

В JavaScript я бы сделал так, чтобы функция принимала объект в качестве единственного параметра, примерно так:

function doSomething(settings) {
    var preventUndo = settings.hasOwnProperty('preventUndo') ? settings.preventUndo : false;
    // Deal with preventUndo in the normal way.
}

Затем позвоните с помощью:

doSomething({preventUndo: true});

HA !!! Мы оба сделали doSomething(x)метод! лол ... я даже не заметил твой пост до сих пор.
плоть

Что произойдет, если я передам строку "noUndo", и как человеку, использующему вашу подпись, будет понятно, какие настройки должны содержаться, не заглядывая в реализацию?
Ник Б.

1
Документируйте свой код. Это то, что делают все остальные. Это облегчает чтение вашего кода, писать его нужно только один раз.
ridecar2

1
@NickB. Конвенция является мощным. Если большая часть вашего кода принимает объекты с аргументами, это понятно.
orip

4

Я люблю использовать возможности языка, чтобы помочь ясности сам. Например, в C # вы можете указать параметры по имени:

 CallSomething(name: "So and so", age: 12, description: "A random person.");

В JavaScript я обычно предпочитаю использовать объект параметров в качестве аргумента по этой причине:

function doSomething(args) { /*...*/ }

doSomething({ name: 'So and so', age: 12, description: 'A random person.' });

Это только мое предпочтение, хотя. Я полагаю, что это будет сильно зависеть от вызываемого метода и от того, как IDE поможет разработчику понять сигнатуру.


1
Это «оборотная сторона» для слабо типизированных языков. Вы не можете навязать подпись без проверки. Я не знал, что вы можете добавить такие имена в JS.
Джеймс П.

1
@JamesPoulson: Вы, наверное, знали, что можете сделать это в JS, и просто не осознавали этого. Все закончилось в JQuery: и $.ajax({url:'', data:''})т.д. и т.п.
blesh

Правда. На первый взгляд это кажется необычным, но похоже на встроенные псевдообъекты, которые могут существовать в некоторых языках.
Джеймс П.

3

Я считаю, что это самый простой и легкий для чтения:

enum Undo { ALLOW, PREVENT }

doSomething(Undo u) {
    if (Undo.ALLOW == u) {
        // save stuff to undo later.
    }
    // do your thing
}

doSomething(Undo.ALLOW);

MainMa это не нравится. Возможно, нам придется согласиться не соглашаться или мы можем использовать решение, которое предлагает Джошуа Блох:

enum Undo {
    ALLOW {
        @Override
        public void createUndoBuffer() {
            // put undo code here
        }
    },
    PREVENT {
        @Override
        public void createUndoBuffer() {
            // do nothing
        }
    };

    public abstract void createUndoBuffer();
}

doSomething(Undo u) {
    u.createUndoBuffer();
    // do your thing
}

Теперь, если вы когда-нибудь добавите Undo.LIMITED_UNDO, ваш код не скомпилируется, если вы не реализуете метод createUndoBuffer (). А в doSomething () нет if (Undo.ALLOW == u). Я сделал это обоими способами, и второй метод довольно тяжелый и немного сложный для понимания, когда перечисление Undo распространяется на страницы и страницы кода, но это заставляет задуматься. Я обычно придерживаюсь более простого метода, чтобы заменить простое логическое значение на 2-значное перечисление, пока у меня не появится причина для изменения. Когда я добавляю третье значение, я использую свою IDE для «Find-usages» и исправляю все тогда.


2

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

Я могу думать о двух альтернативах, которые не включают дополнительную переменную:

1. Используйте дополнительный комментарий

doSomething(/* preventUndo */ true);

2. Используйте двухзначное перечисление вместо логического

enum Options
{
    PreventUndo,
    ...
}

...

doSomething(PreventUndo);

Вы можете использовать альтернативу 2, если ваш язык поддерживает перечисления.

РЕДАКТИРОВАТЬ

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

Что касается дополнительного кодирования, необходимого перечислениям, оно действительно кажется мне незначительным. Вместо

if (preventUndo)
{
    ...
}

у вас есть

if (undoOption == PreventUndo)
{
    ...
}

или же

switch (undoOption)
{
  case PreventUndo:
  ...
}

И даже если он немного больше печатает, помните, что код пишется один раз и читается много раз, поэтому стоит набрать немного больше сейчас, чтобы через полгода найти более читаемый код.


2

Я согласен с тем, что @GlenPeterson сказал:

doSomething(Undo.ALLOW); // call using a self evident enum

но интересным было бы следующее, так как мне кажется, что есть только две возможности (истинные или ложные)

//Two methods    

doSomething()  // this method does something but doesn't prevent undo

doSomethingPreventUndo() // this method does something and prevents undo

2
Хорошая идея - я не думал об этом. Когда вы усложняете работу, например, doSomething (String, String, String, boolean, boolean, boolean), единственное разумное решение - именованные константы. Ну, Джош Блох предлагает объект фабрики и конструктора, как в: MyThingMaker thingMaker = MyThingMaker.new (); thingMaker.setFirstString ( "Привет"); thingMaker.setSecondString ( "Там"); и т.д ... Thing t = thingMaker.makeIt (); t.doSomething (); Это просто намного больше работы, так что оно того стоит.
ГленПетерсон

Одна из проблем, связанных с последним подходом, состоит в том, что это затрудняет написание метода, который использует, doSomethingно позволяет вызывающей стороне выбирать, разрешать ли отмену. Средство может состоять в том, чтобы иметь перегрузку, которая принимает булеву опцию, но также иметь версии-оболочки, которые вызывают предыдущую версию с параметром всегда true или всегда false.
суперкат

@GlenPeterson Фабрика возможна и возможна в Javascript (упоминается OP).
Джеймс П.

2

Поскольку вы спрашиваете в основном о javascript, используя coffeescript, вы можете получить именованный аргумент, такой как синтаксис, очень просто:

# declare method, ={} declares a default value to prevent null reference errors
doSomething = ({preventUndo} = {}) ->
  if preventUndo
    undo = no
  else
    undo = yes

#call method
doSomething preventUndo: yes
#or 
doSomething(preventUndo: yes)

компилируется в

var doSomething;

doSomething = function(_arg) {
  var preventUndo, undo;
  preventUndo = (_arg != null ? _arg : {}).preventUndo;
  if (preventUndo) {
    return undo = false;
  } else {
    return undo = true;
  }
};

doSomething({
  preventUndo: true
});

doSomething({
  preventUndo: true
});

Повеселитесь на http://js2coffee.org/, чтобы попробовать возможности


Я использую coffeeScript только тогда, когда мне нужно избежать безумия ООП JavaScript. Это хорошее решение, которое я мог бы использовать при кодировании в одиночку, коллегам было бы трудно оправдать, что я передаю объект вместо логического значения для удобства чтения!
methodofaction

1

Просто для менее традиционного решения, и поскольку OP упомянул Javascript, можно использовать ассоциативный массив для отображения значений. Преимущество перед единственным логическим значением заключается в том, что вы можете иметь столько аргументов, сколько захотите, и не беспокоиться об их последовательности.

var doSomethingOptions = new Array();

doSomethingOptions["PREVENTUNDO"] = true;
doSomethingOptions["TESTMODE"] = false;

doSomething( doSomethingOptions );

// ...

function doSomething( doSomethingOptions ){
    // Check for null here
    if( doSomethingOptions["PREVENTUNDO"] ) // ...
}

Я понимаю, что это рефлекс кого-то со строго типизированным фоном, и он может быть не очень практичным, но считаю это оригинальностью.

Другая возможность состоит в том, чтобы иметь объект, и это также возможно в Javascript. Я не уверен на 100%, что это правильно. Взгляните на шаблоны, такие как Фабрика для дальнейшего вдохновения.

function SomethingDoer( preventUndo ) {
    this.preventUndo = preventUndo;
    this.doSomething = function() {
            if( this.preventUndo ){
                    // ...
            }
    };
}

mySomethingDoer = new SomethingDoer(true).doSomething();

1
Я думаю, что это может быть лучше написано в точечной нотации ( doSomethingOptions.PREVENTUNDO) вместо записи доступа к массиву.
Paŭlo Ebermann

1

Фокус вашего вопроса и других ответов - улучшение читабельности при вызове функции, с чем я согласен. Любые конкретные указания, событие «без логических аргументов», всегда должны функционировать как средство для достижения этой цели, а не становиться и заканчиваться собой.

Я думаю, что полезно отметить, что эта проблема в основном предотвращается, когда язык программирования поддерживает именованные аргументы / ключевые слова-аргументы, как в C # 4 и Python, или когда аргументы метода чередуются в имени метода, как в Smalltalk или Objective-C.

Примеры:

// C# 4
foo.doSomething(preventUndo: true);
# Python
foo.doSomething(preventUndo=True)
// Objective-C
[foo doSomethingWith:bar shouldPreventUndo:YES];

0

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

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


Таким образом, вы бы преобразовали функцию с логическим аргументом в две функции, которые отличаются только крошечной частью их кода (где оригинал будет иметь if(param) {...} else {...})?
Paŭlo Ebermann

-1
int preventUndo = true;
doSomething(preventUndo);

Хороший компилятор для языков низкого уровня, таких как C ++, оптимизирует машинный код выше 2 строк, как показано ниже:

doSomething(true); 

так что это не имеет значения в производительности, но повысит читабельность.

Также полезно использовать переменную на случай, если она станет переменной позже и может принимать и другие значения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.