Булевские переменные как недопустимые аргументы метода? [закрытый]

Я думаю, вы можете сделать это так:

    int x = 20;
    StringBuilder evenNumberStringBuilder = new StringBuilder();
    StringBuilder oddNumberStringBuilder = new StringBuilder();
    for(int i =0 ; i<x+1; i++){
        if(i % 2 == 0)evenNumberStringBuilder.append(i);
        else oddNumberStringBuilder.append(i);
    }

    System.out.println(evenNumberStringBuilder);
    System.out.println(oddNumberStringBuilder);

Вывод:

02468101214161820
135791113151719
122
задан Thomas Koschel 25 September 2008 в 20:55
поделиться

24 ответа

Булевская переменная представляет "да/нет" выбор. Если Вы хотите представить "да/нет", то используйте булевскую переменную, это должно быть очевидно.

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

130
ответ дан 24 November 2019 в 01:21
поделиться

Если в методе задается вопрос, такой как:

KeepWritingData (DataAvailable());

, где

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

булевы аргументы метода, кажется, имеют абсолютно смысл.

2
ответ дан 24 November 2019 в 01:21
поделиться

В то время как это верно, что во многих случаях перечисления более читаемы и более расширяемы, чем булевские переменные, абсолютное правило, что "булевские переменные не приемлемы", ненормально. Это негибко и контрпродуктивно - это не оставляет комнату для человеческого решения. Они - фундаментальное, созданное в типе на большинстве языков, потому что они полезны - рассматривают применение его к другому созданному в типах: высказывание, например, "никогда не использует интервал в качестве параметра", просто было бы сумасшедшим.

Это правило является просто вопросом стиля, не потенциала для ошибок или производительности во время выполнения. Лучшее правило было бы, "предпочитают перечисления булевским переменным по причинам удобочитаемости".

Взгляд на платформу .NET. Булевские переменные используются в качестве параметров на довольно многих методах..Net API не прекрасен, но я не думаю, что использование булевской переменной как параметры является большой проблемой. Подсказка всегда дает Вам название параметра, и можно создать этот вид руководства также - заполняют XML-комментарии на параметрах метода, они подойдут в подсказке.

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

, Например, если Ваш класс имеет свойства как

public bool IsFoo
public bool IsBar

И это - ошибка иметь их обоих верных одновременно, что Вы на самом деле получили, три допустимых состояния, лучше выраженные как что-то как:

enum FooBarType { IsFoo, IsBar, IsNeither };
4
ответ дан 24 November 2019 в 01:21
поделиться

Перечисления обладают определенным преимуществом, но Вы should't просто идете, заменяя все Ваши булевские переменные перечислениями. Существует много мест, где истинный/ложный на самом деле лучший способ представить то, что продолжается.

Однако использование их как аргументы метода является немного подозреваемым, просто потому что Вы не видите, не роя в вещи, что они, как предполагается, делают, поскольку они позволяют Вам видеть то, что истинное/ложное на самом деле средства

Свойства (особенно с инициализаторами объекта C#3) или аргументы ключевого слова (а-ля рубин или Python) являются намного лучшим способом пойти, где Вы иначе использовали бы булев аргумент.

пример C#:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

пример Ruby

validates_presence_of :name, :allow_nil => true

пример Python

connect_to_database( persistent=true )

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

4
ответ дан 24 November 2019 в 01:21
поделиться

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

7
ответ дан 24 November 2019 в 01:21
поделиться

Булевские переменные могут быть в порядке на языках, которые назвали параметры, как Python и Objective C, так как имя может объяснить, что делает параметр:

file.writeData(data, overwrite=true)

или:

[file writeData:data overwrite:YES]
6
ответ дан 24 November 2019 в 01:21
поделиться

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

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

dim append as boolean = true
file.writeData( data, append );

или я предпочитаю более общий

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );
115-секундный: Перечислимый пример, который Вы дали, только "лучше", потому что Вы передаете КОНСТАНТУ, Скорее всего, в большей части приложения по крайней мере некоторые, если не большую часть времени параметрами, которые передаются функциям, являются ПЕРЕМЕННЫЕ. в этом случае мой второй пример (предоставление переменных с хорошими именами) намного лучше, и Перечислимый принес бы Вам мало пользы.

4
ответ дан 24 November 2019 в 01:21
поделиться

Существует две причины, я столкнулся с этим являющимся плохой вещью:

  1. , поскольку некоторые люди запишут методы как:

    ProcessBatch(true, false, false, true, false, false, true);
    

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

  2. , поскольку, управляя процессом выполнения программы простым да/нет ответвление могло бы означать, у Вас есть две совершенно различных функции, которые обернуты в одного awkard способом. Например:

    public void Write(bool toOptical);
    

    Действительно, это должно быть двумя методами

    public void WriteOptical();
    public void WriteMagnetic();
    

    , потому что код в них мог бы совершенно отличаться; им, возможно, придется сделать все виды другой обработки ошибок и проверки, или возможно даже иметь для форматирования исходящих данных по-другому. Вы не можете сказать, что только при помощи Write() или даже Write(Enum.Optical) (хотя, конечно, у Вас мог быть любой из тех методов просто, называют внутренние методы WriteOptical/Mag, если Вы хотите).

я предполагаю, что это просто зависит. Я не сделал бы слишком большим из соглашения об этом за исключением № 1.

13
ответ дан 24 November 2019 в 01:21
поделиться

Помните вопрос Adlai Stevenson, изложенный послу Zorin в ООН во время Кубинский ракетный кризис ?

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

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

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

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

13
ответ дан 24 November 2019 в 01:21
поделиться

Я думаю, что Вы почти ответили на это сами, я думаю, что цель конца состоит в том, чтобы сделать код более читаемым, и в этом случае перечисление сделало это, IMO его всегда лучший, чтобы посмотреть на цель конца, а не всеохватывающие нормы, возможно, думать о нем больше как об инструкции, т.е. перечисления часто более читаемы в коде, чем универсальный bools, ints и т.д., но всегда будут исключения из правила.

13
ответ дан 24 November 2019 в 01:21
поделиться

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

50
ответ дан 24 November 2019 в 01:21
поделиться

Используйте тот что лучшие модели Ваша проблема. В примере Вы даете, перечисление является лучшим выбором. Однако были бы другие времена, когда булевская переменная лучше. Который имеет больше смысла Вам:

lock.setIsLocked(True);

или

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

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

32
ответ дан 24 November 2019 в 01:21
поделиться

Использование перечислений вместо булевских переменных в Вашем примере действительно помогает сделать вызов метода более читаемым. Однако это - замена для моего любимого объекта желания в C#, параметров, передаваемых по имени в вызовах метода. Этот синтаксис:

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

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

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

-1
ответ дан 24 November 2019 в 01:21
поделиться

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

-1
ответ дан 24 November 2019 в 01:21
поделиться

По моему скромному мнению, кажется, что перечисление было бы очевидным выбором для любой ситуации, где больше чем два варианта возможны. Но определенно СУЩЕСТВУЮТ ситуации, где булевская переменная - все, в чем Вы нуждаетесь. В этом случае я сказал бы, что использование перечисления, где bool будет работать, было бы примером использования 7 слов, когда 4 сделает.

1
ответ дан 24 November 2019 в 01:21
поделиться

Иногда просто более просто смоделировать другое поведение с перегрузками. Продолжаться от Вашего примера было бы:

file.appendData( data );  
file.overwriteData( data );

Этот подход ухудшается, если у Вас есть несколько параметров, каждый позволяющий фиксированный набор опций. Например, метод, который открывает файл, мог бы иметь несколько перестановок режима файла (открываются/создают), доступ к файлу (чтение-запись), режим совместного использования (none/read/write). Общее количество конфигураций равно Декартовым произведениям отдельных опций. Естественно в таких случаях несколько перегрузок не являются соответствующими.

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

Часто булев параметр добавляется к списку параметров как новая перегрузка. Один пример в.NET:

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

последняя перегрузка стала доступной в более поздней версии платформы.NET, чем первое.

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

<час>

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

В более новых версиях C# возможно использовать параметры, передаваемые по имени, которые, IMO, могут сделать код вызова более четким таким же образом, что перечисления могут. Используя тот же пример как выше:

Enum.Parse(str, ignoreCase: true);
0
ответ дан 24 November 2019 в 01:21
поделиться

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

Тем не менее можно также использовать Ложь и Верный (булевская переменная 0 и 1) и затем если Вы нуждаетесь в большем количестве значений позже, расширяетесь, функция для поддержки пользовательских значений (скажите, 2 и 3), и старые значения 0/1 портируют приятно, таким образом, код не должен повреждаться.

0
ответ дан 24 November 2019 в 01:21
поделиться

Перечисления могут, конечно, сделать код более читаемым. Существует все еще несколько вещей не упустить (в .NET, по крайней мере)

, поскольку базовая система хранения перечисления является интервалом, значение по умолчанию будет нулем, таким образом, необходимо будет удостовериться, что 0 разумное значение по умолчанию. (Например, структуры имеют все поля, обнуленные при создании, таким образом, нет никакого способа указать значение по умолчанию кроме 0. Если у Вас нет 0 значений, Вы не можете даже протестировать перечисление, не бросая к интервалу, который был бы плохим стилем.)

, Если Ваше перечисление является частным к Вашему коду (никогда не выставляемый публично) затем, можно прекратить читать здесь.

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

я могу по закону записать

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

Для борьбы с этим, любой код, который использует перечисление, в котором Вы не можете быть уверены (например, общедоступный API) должен проверить, допустимо ли перечисление. Вы делаете это через [1 117]

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

, единственный протест Enum.IsDefined состоит в том, что это использует отражение и медленнее. Это также переносит проблему управления версиями. Если бы необходимо часто проверять перечисление значений, Вы были бы более обеспечены следующее:

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

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

существует еще больше забавы, которую можно сделать с [Flags] перечисления, и код доступа для этого немного отличается.

я также отмечу, что для мобильности, необходимо использовать вызов ToString() на перечислении и использовании Enum.Parse(), когда чтение их въезжает задним ходом. И ToString() и Enum.Parse() может обработать [Flags] перечисление также, таким образом, нет никакой причины не использовать их. Обратите внимание, это - еще одна ловушка, потому что теперь Вы не можете даже изменить имя перечисления, возможно не взламывая код.

Так, иногда необходимо ли взвеситься все вышеупомянутое, когда Вы спрашиваете себя , мне может сойти с рук просто bool?

2
ответ дан 24 November 2019 в 01:21
поделиться

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

2
ответ дан 24 November 2019 в 01:21
поделиться

Это зависит от метода. Если метод делает что-то, что является очень, очевидно, истинной/ложной вещью затем, он прекрасен, например, ниже [хотя не я не говорю, что это - лучший дизайн для этого метода, это - просто пример того, где использование очевидно].

CommentService.SetApprovalStatus(commentId, false);

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

2
ответ дан 24 November 2019 в 01:21
поделиться

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

другое преимущество Перечисления, это легче считать.

3
ответ дан 24 November 2019 в 01:21
поделиться

To me, neither using boolean nor enumeration is a good approach. Robert C. Martin captures this very clearly in his Clean Code Tip #12: Eliminate Boolean Arguments:

Boolean arguments loudly declare that the function does more than one thing. They are confusing and should be eliminated.

If a method does more than one thing, you should rather write two different methods, for example in your case: file.append(data) and file.overwrite(data).

Using an enumeration doesn't make things clearer. It doesn't change anything, it's still a flag argument.

13
ответ дан 24 November 2019 в 01:21
поделиться

Некоторые правила, которых может лучше придерживаться ваш коллега:

  • Не будьте категоричны в своем дизайне.
  • Выберите то, что больше всего подходит для пользователей вашего кода.
  • Не пытайтесь воткнуть звездообразные колышки в каждую дырку только потому, что вам нравится форма в этом месяце!
4
ответ дан 24 November 2019 в 01:21
поделиться

Только булевы значения true/false. Поэтому неясно, что они представляют. Enum может иметь осмысленное имя, например, OVERWRITE, APPEND и т.д. Поэтому перечисления лучше.

-1
ответ дан 24 November 2019 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: