我有一个非常奇特的数据源我必须使用(实际上是一个会计应用程序的接口)。虽然它非常强大,但我必须跳过很多箍来获取我想要的数据。例如,如果我想获取表的内容并指定它应该返回哪些列,我必须遍历.Columns集合并调用.SetVisible()到我想要的那些。
目前我们有一个包装它的方法,允许我们以更简单的方式指定事物,但是该函数的参数列表正在快速增长,并且大多数时候我们只需要指定其中的一些我们称之为。简而言之 - 这是一个不灵活的解决方案。
我想到的第一个解决方案是这样的:
DataTable result = DataSourceWrapper.StartQuery("TableName")
.SetVisibleColumns("Col1", "Col2", "Col3")
.SetCriteria("CriteriaName", "Param1Name", CriteriaParam1, "Param2Name", CriteriaParam2)
.SetFilter("Col4 = ? AND Col5 = ?", FilterParam1, FilterParam2)
.SetReportParams("Param1Name", ReportParam1, "Param2Name", ReportParam2)
.Execute();
Criteria,Filters和ReportParams是应用程序特有的一些东西,我不会在这里讨论它们。但总体思路是这样的。它实际上类似于调用方法,除了您可以选择要指定的参数(通过调用特定方法)并获得更多的IntelliSense帮助。您还可以使用方法调用的顺序。
请注意SetFilter()
有一个要解析的表达式。这是DataSource难以实现的另一件事 - 它可以很好地处理表达式,但是你必须将它们作为特殊对象的树传递,这也是相当冗长的写入。在previous question我请求解析这些表达式的帮助。当前的wrapper-method有一个自制的表达式解析器,它可以解析简单的表达式,但我想让它们的支持更加完整。
在那个问题中,提出了Irony项目。检查后我决定它确实适合这种需要。但过了一会儿,我突然明白,它比那更强大。为什么不使我自己的查询语言适合这个任务呢?以上将如下所示:
DataTable result = DataSourceWrapper.Query(@"
SELECT Col1, Col2, Col3
FROM TableName
WITH CRITERIA CriteriaName(Param1Name={0}, Param2Name={1})
WITH REPORTPARAMS (Param1Name={2}, Param2Name={3}
WHERE Col4 = {4} AND Col5 = {5}",
CriteriaParam1, CriteriaParam2,
ReportParam1, ReportParam2,
FilterParam1, FilterParam2
);
但是......这不是一种矫枉过正吗?这两种方法的优点和缺点是什么?我看到的是:
Pro DSL:
Pro方法:
已添加:为了澄清,这两种方法仅供编码员使用。外部人员和业务分析师不会使用它。
答案 0 :(得分:2)
你必须小心你所谓的DSL。见Martin Fowler's Bliki post on DSL。您链接方法的示例非常接近内部DSL。略微修改它是:
DataTable result = DataSourceWrapper.Query("TableName")
.With(new Columns("Col1", "Col2", "Col3"))
.Where(new AndCritera("CriteriaName",
new Criterion("Param1Name", CriteriaParam1),
new Criterion("Param2Name", CriteriaParam2))
.Filter(
new Filter("Col4").Equals(FilterParam1),
new Filter("Col5").Equals(FilterParam2))
.With(
new ReportParam("Param1Name", ReportParam1),
new ReportParam("Param2Name", ReportParam2));
话虽这么说,这仍然在C#领域内,只有程序员才能编写这些查询。如果您的要求促使您向非程序员提供查询,那么您可能会考虑按照第二个示例中的指定继续创建外部DSL。
答案 1 :(得分:0)
我选择DSL方法。
原因: 1它更贴近领域专家,从个人经验来看,BAs就像DSL形式的东西一样,它打破了商业头脑的人和开发人员之间的沟通障碍,使得编写技术规范变得更加容易 2通过使用像Irony这样的工具,您的DSL将被很好地定义,并且是测试驱动开发的良好候选者 3实现DSL确实需要对开发人员进行一些初步学习(我使用javacc,它甚至比Irony更不友好)但是一旦你掌握了这些想法,就变得容易了,你的代码变得非常通用,因为你卸载了逻辑进入DSL。