Хорошая архитектура для одного, если утверждение со многими условиями

У меня есть оператор if, который выглядит так:

if conditionA() || conditionB() || conditionC() || conditionD() || conditionE() || condition()
  #do sth
end
#conditionX() methods return true/false

Это выглядит уродливо. Есть ли какой-либо шаблон дизайна, который упростил бы это?

* Используемый язык: Ruby. Хотя я считаю, что решение должно быть языковым агностиком

Ответ 1

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

  • Группируйте аналогичные условия по их функциональности и называйте эту функциональность.
  • Создайте Boolean методы возврата для каждой группы и вызовите их в блоке if.

Ответ 2

В Agile Programming: дизайн для размещения Изменить, Дейв Томас рекомендует таблицы решений:

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

Они, безусловно, являются агностиками языка, поскольку они использовались с начала 1970-х годов.

Ответ 3

Обычно это switch (C, Java) или операторы case (Ruby):

shouldAct = false
case 
  when <condition A>
    shouldAct = true
  when <condition B>
    shouldAct = true
  when <condition C>
    shouldAct = true
  else
    shouldAct = false
end
doSomething() if shouldAct 

В Python существует сложное решение, использующее кортеж lambdas:

conditions = (
   lambda a : a == 1,
   lambda b : b == 2,
   lambda c : c == 3,
)
# evaluate each condition separately
a,b,c = 1,2,3
if any(map(lambda x, y : x(y), conditions, [a,b,c])):
   soSomething()

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

Ответ 4

Трудно сказать без полного контекста.

Один из вариантов состоит в том, чтобы наследовать от базового класса и иметь условие A(), conditionB() и т.д. - реализации метода base condition(). Это имеет свои преимущества, но может не соответствовать этому примеру.

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