Я работаю над приложением, которое позволяет стоматологам собирать информацию об определенных клинических действиях. Хотя приложение не очень настраиваемо (нет пользовательских рабочих процессов или форм), оно предлагает некоторые элементарные возможности настройки; клиенты могут выбрать для добавления предопределенных полей формы свои собственные. Существует около полудюжины различных типов полей, которые могут создавать администраторы (т. Е. Текст, дата, числовое значение, DropDown и т. Д.). Мы используем Entity-Attribute-Value (EAV) на стороне персистентности для моделирования этой функциональности.
Одной из других ключевых функций приложения является возможность создавать пользовательские запросы к этим настраиваемым полям. Это достигается с помощью пользовательского интерфейса, в котором может быть создано любое количество правил (Дата <= (сейчас - 5 дней), Текстовый как '444', DropDown == 'ICU'). Все правила объединены для создания запроса. </p>
Текущая реализация (которую я «унаследовал») не является ни объектно-ориентированной, ни тестируемой модулем. По сути, существует один класс «Бог», который компилирует все бесчисленные типы правил непосредственно в сложный динамический оператор SQL (то есть внутренние объединения, внешние объединения и подвыборы). Этот подход проблематичен по нескольким причинам:
- модульное тестирование отдельных правил изолированно
почти невозможно
- Последний пункт также означает добавление дополнительных типов правил в
будущее будет определенно нарушать
Открытый Закрытый Принцип.
- Бизнес-логика и проблемы постоянства смешиваются.
- Медленно выполняющиеся модульные тесты, так как требуется реальная база данных (SQLLite не может проанализировать T-SQL, и анализ парсера будет эээ ... сложным)
Я пытаюсь придумать заменяющий дизайн, который будет гибким, обслуживаемым и тестируемым, при этом сохраняя производительность запросов достаточно быстрой. Этот последний пункт является ключевым, поскольку я полагаю, что реализация на основе OOAD перенесет хотя бы часть логики фильтрации данных с сервера базы данных на сервер приложений (.NET).
Я рассматриваю комбинацию шаблонов командования и цепочки ответственности:
Класс Query содержит коллекцию абстрактных классов Rule (DateRule, TextRule и т. Д.). и содержит ссылку на класс DataSet, который содержит нефильтрованный набор данных. DataSet моделируется в зависимости от постоянства (т.е. нет ссылок или привязок к типам баз данных)
Правило имеет единственный метод Filter (), который принимает DataSet, фильтрует его соответствующим образом и затем возвращает его вызывающей стороне. Класс Query затем просто перебирает каждое правило, позволяя каждому правилу фильтровать DataSet так, как он считает нужным. Выполнение будет остановлено после выполнения всех правил или после того, как DataSet будет отфильтрован до нуля.
Единственное, что меня беспокоит в этом подходе, - это влияние на производительность анализа потенциально большого нефильтрованного набора данных в .NET. Конечно, есть некоторые проверенные и правильные подходы к решению именно такой проблемы, которые предлагают хороший баланс между ремонтопригодностью и производительностью?
Последнее замечание: руководство не разрешит использовать NHibernate. Linq to SQL может быть возможен, но я не уверен, насколько эта технология применима к поставленной задаче.
Большое спасибо, и я с нетерпением жду отзывов всех!
Обновление: все еще ищем решение по этому вопросу.