演化架构与紧急设计: 语言、表达性与设计:第 1 部分
2009-09-12 00:00:00 来源:WEB开发网新属性处理 DSL 的第一部分,of 方法是惟一剩余的部分。of 也是添加到 Integer 的方法,它出现在清单 12 中。该方法接受单个参数,指定原料名称,设置数量并返回新创建的原料对象。
清单 12. 添加到 Integer 中的 of 方法
Integer.metaClass.of { name ->
def ingredient = new Ingredient(name);
ingredient.quantity = delegate
ingredient
}
清单 10 的代码中存在的微妙之处被 清单 12 中的代码公开了。尽管 DSL 的第一行(recipe.add 1.gram.of("Nutmeg"))现在工作得很好,第二行因为我定义的 of 方法不再适用而失败了。一旦对 of 的调用出现在样例行 recipe.add 2.lbs.of("Flour") 中,调用类型就从 Integer 变成了 BigDecimal(Groovy 对于浮点数字的默认格式)。这是怎么回事呢?在对 pounds 的调用中,返回类型现在是浮点数字 (2 * 453.29)。因此我需要将额外的 of 方法附加到 BigDecimal,如 清单 13 所示:
清单 13. 添加到 BigDecimal 的 of 方法
BigDecimal.metaClass.of { name ->
def ingredient = new Ingredient(name);
ingredient.quantity = delegate
ingredient
}
令人惊讶地是,这个问题在 DSL 实现中经常出现。很多 DSL 需要表示量的东西:1 周、2 磅、6 美元。向 Integer 添加方法允许您创建更具表达性的代码,因为您可以使用真实的数字表示数值。DSL 中很多代码行经常以数量开始,调用一些中间方法来完成工作并最终返回有趣的最后一个类型的实例。在 清单 10 中,数量开始方法调用,开始是 Integer,然后是 BigDecimal,最后返回 Ingredient。DSL 旨在创建更精简的代码,去除了无用的冗长的语法。删除语法有助于改善可读性,从而使您更容易发现隐藏在代码中的设计元素,这些设计元素往往为必要但又杂乱的语法所遮挡。
结束语
在本文中,我介绍了语言的表达性,它会影响代码的可读性和发现(从而积累)代码中惯用模式(要发现和重用的真正设计元素)的能力。我介绍了如何用更具表达性的语言(比如 Groovy)实现几个四人组模式。在第 2 部分中,我将继续讨论表达性与语言的交集,更好地表达正式设计模式的方式,以及某些语言如何为您赋予在表达性不好的语言中根本不存在的能力。
更多精彩
赞助商链接