Как написать код, логика которого защищена от будущих дополнительных перечислений?

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

// original code
enum Fruit
{ 
    Apple,
    Orange,
    Banana,
}

...

Fruit fruit = acquireFruit();
if (fruit != Fruit.Orange && fruit != Fruit.Banana)
    coreFruit();
else
    pealFruit();
eatFruit();

Теперь представьте, что годы разработки проходят с этими тремя типами. Различные варианты вышеупомянутой логики распространяются на хранимые процедуры, пакеты SSIS, приложения для Windows, веб-приложения, приложения Java, сценарии Perl и т. Д.

Наконец:

// new code
enum Fruit
{ 
    Apple,
    Orange,
    Banana,
    Grape,
}

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

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

I ' Мы сделали снимок в темноте:

# 1 Избегайте "Not In Logic" вроде этого

// select fruit that needs to be cored
select Fruit from FruitBasket where FruitType not in(Orange, Banana)

# 2 При необходимости используйте тщательно сконструированные методы NotIn ()

internal static class EnumSafetyExtensions
{
    /* By adding enums to these methods, you certify that 1.) ALL the logic inside this assembly is aware of the
     * new enum value and 2.) ALL the new scenarios introduced with this new enum have been accounted for.
     * Adding new enums to an IsNot() method without without carefully examining every reference will result in failure. */

    public static bool IsNot(this SalesOrderType target, params SalesOrderType[] setb)
    {
        // SetA = known values - SetB

        List<SalesOrderType> seta = new List<SalesOrderType>
        {
            SalesOrderType.Allowance,
            SalesOrderType.NonAllowance,
            SalesOrderType.CompanyOrder,
            SalesOrderType.PersonalPurchase,
            SalesOrderType.Allotment,
        };
        setb.ForEach(o => seta.Remove(o));

        // if target is in SetA, target is not in SetB
        if (seta.Contains(target))
            return true;

        // if target is in SetB, target is not not in SetB
        if (setb.Contains(target))
            return false;
        // if the target is not in seta (the considered values minus the query values) and the target isn't in setb
        // (the query values), then we've got a problem.  We've encountered a value that this assembly does not support.

        throw new InvalidOperationException("Unconsidered Value detected: SalesOrderType." + target.ToString());
    }
}

Теперь я могу безопасно использовать такой код, как this:

bool needsCoring = fruit.IsNot(Fruit.Orange, Fruit.Banana);

Если этот код будет распространен по всей системе, исключения будут выброшены, когда Grape прибудет в город (qa поймает их всех).

Таков план в любом случае. Проблема кажется очень распространенной, но я не могу найти ничего в Google (вероятно, моя вина).

Как вы все справляетесь с этим?

ОБНОВЛЕНИЕ:

Я чувствую ответ Для решения этой проблемы необходимо создать механизм «ловить все остальное», который останавливает обработку и предупреждает тестировщиков и разработчиков о том, что новое перечисление требует рассмотрения. "switch ... default" отлично, если он у вас есть.

If C # didn ' t имеет переключатель ... по умолчанию, мы могли бы исправить приведенный выше код следующим образом:

Fruit fruit = acquireFruit();
if (fruit != Fruit.Orange && fruit != Fruit.Banana)
    coreFruit();
else if(fruit == Fruit.Apple)
    pealFruit();
else
    throw new NotSupportedException("Unknown Fruit:" + fruit)
eatFruit();

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ:

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

19
задан Robert H. 4 October 2010 в 18:42
поделиться