我正在研究一个应用程序,允许牙医捕获有关某些临床活动的信息。虽然应用程序不是高度可定制的(没有自定义工作流程或表单),但它确实提供了一些基本的定制功能;客户可以选择用自己定制的表单域来扩充它们。管理员可以创建大约六种不同的字段类型(即文本,日期,数字,下拉等)。我们在持久性方面使用实体属性值(EAV)来模拟此功能。设计面向对象和单元测试友好查询系统
该应用程序的其他主要功能之一是能够根据这些自定义字段创建自定义查询。这可以通过一个UI来完成,其中可以创建任意数量的规则(日期< =(现在-5天),文字像'444',DropDown =='ICU')。所有规则都安排在一起产生一个查询。
当前的实现(我“继承”)既不是面向对象也不是单元可测试的。从本质上讲,有一个单独的“上帝”类将所有无数的规则类型直接编译成复杂的动态SQL语句(即内部联接,外部联接和子选择)。这种方法是很麻烦的有以下几个原因:在隔离
- 单元测试单独的规则几乎是不可能的
- 最后一点也意味着在 未来增加额外的规则类型,肯定会违反 的开闭原则。
- 业务逻辑和持久性问题正在混合在一起。
- 慢速运行单元测试由于需要一个真正的数据库(SQLLite无法解析T-SQL和嘲讽出来一个解析器会嘘......硬)
我试图拿出一个更换设计灵活,可维护且可测试,同时仍然保持查询性能相当快。最后一点是关键,因为我认为基于OOAD的实现会将至少一些数据过滤逻辑从数据库服务器移动到(.NET)应用程序服务器。
我考虑了指挥链方面的责任模式的组合:
查询类包含抽象规则类的集合(DateRule,TextRule等)。并拥有对包含未过滤数据集的DataSet类的引用。 DataSet以持久性不可知的方式建模(即没有引用或钩入数据库类型)
规则具有一个Filter()方法,它接受DataSet,对其进行适当筛选,然后将其返回给调用者。 Query类比简单地迭代每个Rule,允许每个Rule按照它认为合适的方式过滤DataSet。一旦执行完所有规则或一旦数据集被过滤到无,执行就会停止。
让我担心这种方法的一件事是在.NET中解析一个潜在的大型未过滤数据集的性能影响。对于解决这种问题,在可维护性和性能之间提供一个很好的平衡,肯定有一些尝试和真正的方法?
最后一点:管理层不允许使用NHibernate。 Linq to SQL可能是可能的,但我不确定该技术对手头任务的适用性。
非常感谢,我期待着大家的反馈!
更新:仍在寻找解决方案。
嘻嘻 - 不妨问他“你试过javascript吗?” – 2009-09-16 03:15:50
Tim, 感谢您的回复。我不认为你有任何我可以学习的示例代码(除了你提到的Dynamic LINQ示例以外)? – 2009-09-25 03:24:45