DSL与方法调用:优点和缺点

时间:2009-04-22 18:15:56

标签: c# .net dsl

我有一个非常奇特的数据源我必须使用(实际上是一个会计应用程序的接口)。虽然它非常强大,但我必须跳过很多箍来获取我想要的数据。例如,如果我想获取表的内容并指定它应该返回哪些列,我必须遍历.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方法:

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

已添加:为了澄清,这两种方法仅供编码员使用。外部人员和业务分析师不会使用它。

2 个答案:

答案 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。