Сокращение объектов до категорий на основе произвольной логики
Этот вопрос может быть субъективным. Я не уверен, принадлежит ли он здесь или программистам
Скажем, у меня есть тип данных, X
(подумайте о бизнес-объектах, построенных из реляционной базы данных). Моя конечная цель - представить множество экземпляров этого типа в таблице для отчета, причем каждый экземпляр находится под одним из нескольких разных заголовков.
Заголовок для отображения объекта под выбран на основе произвольной логики, передаваемой из управления, с которым любой, кто занимался разработкой корпоративного программного обеспечения, будет знаком:
Примеры:
If the instance has a FooID of 6 and a BarFactor of < 0.5, place it under the "Borked" heading.
или же
If the Weight is > 0, and the CreatedDate is before Midnight but after 3PM, and today is not the 3rd Wednesday of the month, the object should be categorised as "Fluffy".
Мой вопрос: есть ли идиома для того, чтобы взять пример X
, применяя потенциально вызывающее головную боль количество логики к состоянию экземпляра и получая категорию / строку / произвольное значение из результата этой логики?
Мои идеи до сих пор были:
Функция, которая принимает
X
и возвращаетString
, Я мог легко видеть, что это превращается в Мегамота, и я должен поддерживать его, поскольку требования постоянно меняются.Определить
Heading
абстрактный тип и фабричная функция, которая дает мне экземплярHeading
сToString
метод корректно перегружен. Я думаю, что эта техника будет преследовать те же проблемы, что и идея нет. 1.Иерархия функций, каждая из которых разделяет проблему немного дальше, пока мы не придем к правильному заголовку.
Например:
public String GetHeading(X x)
{
if (x.Weight > 0)
return WeightGreaterThanZero(x);
else if (x.Weight < 0)
return WeightLessThanZero(x);
else
return WeightIsZero(x);
}
Три функции "Вес" будут проверять дальнейшие условия, пока мы не получим значение. Проблема, которую я вижу здесь, заключается в том, что нам нужно отследить, какая функция называется какой. FooIDIs6
функция должна знать, была ли она вызвана WeightIsZero
или какая-то другая функция, иначе любые предыдущие решения потенциально бессмысленны. Мы в конечном итоге с чем-то вроде WeightIsGreaterThanZero_FooIDIs6_GrandmotherIsOlderThan100
и т. д.
2 ответа
Я не уверен, что это в полной мере относится к тому, что вы пытаетесь выполнить, но всякий раз, когда мы сталкиваемся с этим типом "веселья", мы заканчиваем тем, что предоставляем бизнес-пользователям пользовательский интерфейс для определения своих правил, а затем просто пишем достаточно кода для применения. правила для конкретных объектов.
Например, в одном из наших приложений мы позволяем пользователю указывать набор условий, которые при оценке в true будут создавать определяемые пользователем выходные данные.
Для этого мы сохраняем одну запись в базе данных для каждой части оператора IF. В каждой записи указывается имя свойства в классе, действие сравнения (<, =, <>и т. Д.), Значение сравнения, независимо от того, начинается или заканчивается ли оператор группа (т. Е. Parens), и как присоединяется текущий оператор. со следующим (И или ИЛИ).
Так что вы бы
Heading Record (Parent record, which defines the heading to be used)
Heading Selector (Child records which define the if statement)
Мы также можем поддерживать определяемые пользователем приоритеты в родительской записи, чтобы, если у данной записи было несколько совпадений, пользователь должен определить наилучшее совпадение посредством правильного применения приоритетов.
Во время выполнения вы просто создаете оператор для оценки условий, введенных пользователем. Мы используем отражение, чтобы нам не приходилось жестко кодировать имена свойств.
Кроме того, тот же код конфигурации можно использовать для генерации операторов SQL в тех случаях, когда более целесообразно выполнять логику выбора в SQL.
Мы широко использовали этот механизм и обнаружили, что он является очень мощным подходом к удовлетворению частых и разнообразных требований наших клиентов.
Как насчет набора классов категорий, который принимает X и указывает, является ли это правильной категорией для этого X? Что-то вроде:
var categories = new Category[] { new FooCategory(), new BarCategory(), new FluffyCategory() };
foreach( var x in myListOfXs ) {
var cat = categories.FirstOrDefault(c => c.Matches(x));
if( cat != null ) {
x.Category = cat.Name;
}
}