2

我必须使用一个相当特殊的数据源(实际上是会计应用程序的接口)。虽然它非常强大,但我必须跳过很多圈才能从中获取我想要的数据。例如,如果我想获取一个表的内容并指定它应该返回哪些列,我必须遍历 .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 造成困难的另一件事 - 它可以很好地处理表达式,但是您必须将它们作为特殊对象树传递,这又是相当冗长的编写。在上一个问题中,我寻求有关解析此类表达式的帮助。当前的 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
);

但是……这不是矫枉过正吗?两种方法的优缺点是什么?我看到的是:

专业 DSL:

  • 查询更简洁;

专业方法:

  • 更多智能感知支持;
  • 方法名称/参数名称(和注释)减少了对文档的需求(必须彻底记录 DSL);
  • 可能会更快创建?我从来没有创建过自己的 DSL,所以我不知道有多少工作量。讽刺似乎从我肩上卸下了很多担子,但还剩下多少呢?

补充:为了澄清,这两种方法都只能由编码人员使用。外部人员和业务分析师不会使用它。

4

2 回答 2

2

您必须小心所谓的 DSL。请参阅Martin Fowler 在 DSL 上的 Bliki 帖子。您的方法链接示例非常接近内部 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。

于 2009-04-22T18:39:16.860 回答
0

我会选择 DSL 方法。

原因:1 更接近领域专家,从个人经验来看,BA 喜欢 DSL 形式的东西,它打破了有业务头脑的人和开发人员之间的沟通障碍,并且使编写技术规范变得更加容易 2 通过使用类似的工具讽刺的是,你的 DSL 将被很好地定义,并且是测试驱动开发的一个很好的候选人 3 实现 DSL 确实需要对开发人员进行一些初步学习(我使用了 javacc,它比 Irony 更不友好)但是一旦你掌握了这些想法,它变得容易,并且您的代码变得非常通用,因为您将逻辑卸载到 DSL 中。

于 2009-04-22T18:35:06.883 回答