Использование словарей Action вместо операторов switch
Я просто просматриваю часть своего старого кода (имею некоторое свободное время), и я заметил довольно длинный оператор switch. Из-за получения новых знаний, я с тех пор реорганизовал его в следующей форме:
private Dictionary<string, Action> createView
{
get
{
return new Dictionary<string, Action>()
{
{"Standard", CreateStudySummaryView},
{"By Group", CreateStudySummaryByGroupView},
{"By Group/Time", CreateViewGroupByHour}
};
}
}
Считаете ли вы эту хорошую практику, или это просто случай быть заурядным и ненужным? Я заинтересован в том, чтобы новые методы, которые я изучал, не были умны только ради этого, и что они фактически добавляют преимущество коду.
Спасибо.
Ответы
Ответ 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 также будет хорошим способом поддерживать изменения в поведении.