При программировании против перечисления в операторе переключения этот путь состоит в том, чтобы сделать?

Если имя может встречаться в JSON только один раз или если все вхождения должны быть заменены, если их больше, быстрое и грязное - это просто replace() в тексте:

UPDATE elbat
       SET value = replace(value::text, '"values"', '"breakdown"')::jsonb;

( Замените jsonb на json, если тип столбца json, а не jsonb.)

10
задан Jon Limjap 11 March 2009 в 07:47
поделиться

12 ответов

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

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

Что-то как

[Test]
public void ShouldOnlyHaveFourStates()
{
    Assert.That(Enum.GetValues( typeof( DrivingState) ).Length == 4, "Update unit tests for your new DrivingState!!!");
}
7
ответ дан 3 December 2019 в 13:35
поделиться

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

Я прочитал код однажды, и я понял это. Так, по моему скромному мнению Ваш код является примером хорошего стиля кодирования.

16
ответ дан 3 December 2019 в 13:35
поделиться

Существует альтернатива этому, которое должно использовать что-то подобное перечислениям Java. Частные вложенные типы допускают "более строгое" перечисление, где единственное "недопустимое" значение, доступное во время компиляции, null. Вот пример:

using System;

public abstract class DrivingState
{
    public static readonly DrivingState Neutral = new NeutralState();
    public static readonly DrivingState Drive = new DriveState();
    public static readonly DrivingState Parking = new ParkingState();
    public static readonly DrivingState Reverse = new ReverseState();

    // Only nested classes can derive from this
    private DrivingState() {}

    public abstract void Go();

    private class NeutralState : DrivingState
    {
        public override void Go()
        {
            Console.WriteLine("Not going anywhere...");
        }
    }

    private class DriveState : DrivingState
    {
        public override void Go()
        {
            Console.WriteLine("Cruising...");
        }
    }

    private class ParkingState : DrivingState
    {
        public override void Go()
        {
            Console.WriteLine("Can't drive with the handbrake on...");
        }
    }

    private class ReverseState : DrivingState
    {
        public override void Go()
        {
            Console.WriteLine("Watch out behind me!");
        }
    }
}
8
ответ дан 3 December 2019 в 13:35
поделиться

Это выглядит довольно разумным мне. Существуют некоторые другие опции, как a Dictionary<DrivingState, Action>, но то, что Вы имеете, более просто и должно быть достаточным для самых простых случаев. Всегда предпочитайте простой и читаемый;-p

4
ответ дан 3 December 2019 в 13:35
поделиться

Я использовал бы NotSupportedException.

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

3
ответ дан 3 December 2019 в 13:35
поделиться

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

Таким образом, возможно, Вы не должны прокладывать себе путь во-первых. Как насчет:

interface IDrivingState
{
    void Do();
}

Сохраните текущее состояние (объект, который реализует IDrivingState) в переменной, и затем выполните его как это:

drivingState.Do();

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

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

Обновление в ответ на комментарий:

С использованием enum/switch, когда Вы добавляете новое перечисление значений, теперь необходимо найти каждое место в коде, где то перечисление значений еще не обрабатывается. Компилятор не знает, как помочь с этим. Существует все еще "контракт" между различными частями кода, но это неявно и невозможно для компилятора проверить.

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

4
ответ дан 3 December 2019 в 13:35
поделиться

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

Меня, я использовал бы значение по умолчанию drivingstate для значения по умолчанию (как нейтральный / остановка) и зарегистрировал бы пропавших без вести driverstate (потому что это - Вы, которые пропустили drivingstate, не клиента),

Это похоже на реальный автомобиль, CPU решает, что это отсутствует для включения световых сигналов, что делает это делает, выдает исключение и "освобождается" от всего контроля, или отступает к известному состоянию, которое безопасно и дает предупреждение драйверу "oi, у меня нет световых сигналов"

1
ответ дан 3 December 2019 в 13:35
поделиться

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

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

A default случай только с a break не очень хорошо пахнет. Я удалил бы это, чтобы указать, что переключатель не обрабатывает все значения и возможно добавляет комментарий, объясняющий почему.

1
ответ дан 3 December 2019 в 13:35
поделиться

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

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

перечисления и переключатели сделаны друг для друга.

1
ответ дан 3 December 2019 в 13:35
поделиться

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

Это может быть сделано в C#?

0
ответ дан 3 December 2019 в 13:35
поделиться

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

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

Я не соглашаюсь с решением Jon Skeet, которое замораживает много состояний, если это не действительно необходимо.

0
ответ дан 3 December 2019 в 13:35
поделиться

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

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

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

0
ответ дан 3 December 2019 в 13:35
поделиться