Если имя может встречаться в JSON только один раз или если все вхождения должны быть заменены, если их больше, быстрое и грязное - это просто replace()
в тексте:
UPDATE elbat
SET value = replace(value::text, '"values"', '"breakdown"')::jsonb;
( Замените jsonb
на json
, если тип столбца json
, а не jsonb
.)
Мне не нравится этот подход, потому что случай по умолчанию непригоден для тестирования. Это приводит к уменьшенному покрытию в Ваших модульных тестах, которое, в то время как не обязательно конец света, раздражает обсессивно-компульсивный меня.
Я предпочел бы просто модульному тесту каждый случай и имел бы дополнительное утверждение, что существует только четыре возможных случая. Если бы кто-либо когда-нибудь добавлял новые перечислимые значения, то модульный тест повредился бы.
Что-то как
[Test]
public void ShouldOnlyHaveFourStates()
{
Assert.That(Enum.GetValues( typeof( DrivingState) ).Length == 4, "Update unit tests for your new DrivingState!!!");
}
Ваш вопрос был довольно неопределенен, но насколько я понимаю, Вы спрашиваете нас, если Ваш стиль кодирования хорош. Я обычно сужу стиль кодирования по тому, насколько читаемый это.
Я прочитал код однажды, и я понял это. Так, по моему скромному мнению Ваш код является примером хорошего стиля кодирования.
Существует альтернатива этому, которое должно использовать что-то подобное перечислениям 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!");
}
}
}
Это выглядит довольно разумным мне. Существуют некоторые другие опции, как a Dictionary<DrivingState, Action>
, но то, что Вы имеете, более просто и должно быть достаточным для самых простых случаев. Всегда предпочитайте простой и читаемый;-p
Я использовал бы NotSupportedException
.
NotImplementedException
для опций, не реализованных, но случай по умолчанию реализован. Вы просто приняли решение не поддерживать его. Я только рекомендовал бы бросить NotImplementedException во время разработки для тупиковых методов.
Это, вероятно, идет вне темы, но возможно нет. Причина, которой должна быть проверка, состоит в том в случае, если дизайн развивается, и необходимо добавить новое состояние к перечислению.
Таким образом, возможно, Вы не должны прокладывать себе путь во-первых. Как насчет:
interface IDrivingState
{
void Do();
}
Сохраните текущее состояние (объект, который реализует IDrivingState) в переменной, и затем выполните его как это:
drivingState.Do();
По-видимому, у Вас был бы некоторый путь к состоянию для перехода к другому состоянию - возможно, Do
возвратил бы новое состояние.
Теперь можно расширить дизайн, не делая недействительным весь существующий код вполне так.
Обновление в ответ на комментарий:
С использованием enum
/switch
, когда Вы добавляете новое перечисление значений, теперь необходимо найти каждое место в коде, где то перечисление значений еще не обрабатывается. Компилятор не знает, как помочь с этим. Существует все еще "контракт" между различными частями кода, но это неявно и невозможно для компилятора проверить.
Преимущество полиморфного подхода состоит в том, что конструктивные изменения первоначально вызовут ошибки компилятора. Ошибки компилятора хороши! Компилятор эффективно дает Вам контрольный список мест в коде, который необходимо изменить для преодоления конструктивного изменения. Путем разработки кода тот путь Вы получаете помощь мощной "поисковой системы", которая может понять Ваш код и помочь Вам развить его путем нахождения проблем во время компиляции, вместо того, чтобы оставить проблемы до времени выполнения.
Я предложил бы использовать или NotImplementedException или лучше пользовательский DrivingStateNotImplementedException, если Вам нравится выдавать исключения.
Меня, я использовал бы значение по умолчанию drivingstate для значения по умолчанию (как нейтральный / остановка) и зарегистрировал бы пропавших без вести driverstate (потому что это - Вы, которые пропустили drivingstate, не клиента),
Это похоже на реальный автомобиль, CPU решает, что это отсутствует для включения световых сигналов, что делает это делает, выдает исключение и "освобождается" от всего контроля, или отступает к известному состоянию, которое безопасно и дает предупреждение драйверу "oi, у меня нет световых сигналов"
Что необходимо сделать, если Вы встречаетесь, необработанное перечисление значений, конечно, зависит от ситуации. Иногда совершенно законно только обработать некоторые значения.
Если это - ошибка, что у Вас есть значение недескрипторов, необходимо определенно выдать исключение точно так же, как Вы делаете в примере (или обработайте ошибку некоторым другим способом). Никогда не нужно глотать состояние ошибки, не производя признак, что существует что-то не так.
A default
случай только с a break
не очень хорошо пахнет. Я удалил бы это, чтобы указать, что переключатель не обрабатывает все значения и возможно добавляет комментарий, объясняющий почему.
Ясный, очевидный и правильный способ пойти. Если DrivingState должен измениться, Вы, возможно, должны осуществить рефакторинг.
Проблема со всеми сложными полиморфными ужасами выше, они вызывают инкапсуляцию в класс или требуют дополнительные классы - хорошо, когда существует только DrivingState. Диск () метод, но все это повреждается, как только у Вас есть DrivingState. Сериализируйте () метод, который сериализирует к где-нибудь зависящему от DrivingState или любого другого реального условия.
перечисления и переключатели сделаны друг для друга.
Я - программист C, не C#, но когда у меня есть что-то вроде этого, мне установили мой компилятор для предупреждения меня, если не все перечислимые случаи обрабатываются в переключателе. После установки этого (и установки предупреждений поскольку ошибки), я не беспокоюсь проверками на этапе выполнения на вещи, которые могут быть пойманы во время компиляции.
Это может быть сделано в C#?
Я никогда не использую переключатель. Код, подобный тому, что Вы показываете, всегда был главной болевой точкой в большинстве платформ, которые я использовал - нерасширяемый и фиксированный к ограниченному количеству предопределенных случаев.
Это - хороший пример того, что может быть сделано с простым полиморфизмом хорошим, чистым и расширяемым способом. Просто объявите основу DrivingStrategy
и наследуйте всю версию ведущей логики от него. Это не сверхразработка - если бы у Вас было два случая, то это было бы, но четыре уже показывают потребность в том, что, особенно если каждая версия Делает..., называет другие методы. По крайней мере это - мой личный опыт.
Я не соглашаюсь с решением Jon Skeet, которое замораживает много состояний, если это не действительно необходимо.
Я думаю, что с помощью перечислимых типов и поэтому операторы переключения для реализации состояния (также Шаблон разработки состояния) не являются особенно хорошей идеей. По моему скромному мнению, это подвержено ошибкам. Поскольку реализовываемый Конечный автомат становится сложным, код будет прогрессивно менее читаем Вашими коллегами - программистами.
В настоящее время это довольно чисто, но не зная точное намерение этого перечисления трудно сказать, как это разработает со временем.
Кроме того, я хотел бы спросить Вас здесь - сколько операций будет применимыми к DrivingState наряду с Выполненным ()? Если несколько и если бы Вы собираетесь в основном копировать этот оператор переключения неоднократно, он кричал бы сомнительного дизайна по меньшей мере.