Подтвердить что ты не робот

Использование словарей Action вместо операторов switch

Я просто просматриваю часть своего старого кода (имею некоторое свободное время), и я заметил довольно длинный оператор switch. Из-за получения новых знаний, я с тех пор реорганизовал его в следующей форме:

private Dictionary<string, Action> createView
    {
        get
        {
            return new Dictionary<string, Action>()
            {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
            };
        }
    }

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

Спасибо.

4b9b3361

Ответ 1

Операторы с длинным переключением являются классическим плохим запахом и всегда являются объектом рефакторинга.

"Стандартный" шаг для выполнения здесь Заменить условный с помощью полиморфизма. Это был один из шагов, перечисленных в книге Мартина Фаулера Рефакторинг (опубликован 11 лет назад в 1999 году).

Теперь, когда так легко обрабатывать такие функции, как объекты (например, с помощью Action), это может быть столь же хорошим решением.

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

Ответ 2

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

public class MyClass 
{
   Dictionary<string, Action> dict = null; 

    private Dictionary<string, Action> createView
    {
        get
        {
            if(dict  == null) 
            {
              dict  = new Dictionary<string, Action>()
              {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
              };
            }

            return dict;
        }
    }

}

ИЗМЕНИТЬ

С концептуальной точки зрения, я заменяю длинный swicth/case на словарь TryGetValue - довольно хорошее решение.

Надеюсь, что это поможет...

Ответ 3

Этот подход превосходный.

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

var filters = new Dictionary<string, Func<MyEntity, bool>>()
{
    // ...
};

var query = entities.Where(filters["X"]);

Ответ 4

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

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

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