在软件开发过程中,代码生成是一个既复杂又充满挑战的话题。本文旨在提供一些思考的食粮,以帮助在不同层面上规划代码生成。
如果参与的应用程序包含大量的某些元素,那么使用某种形式的代码生成可能是可行的。代码生成可以应用于许多方面,而且大多数(如果不是全部的话)都已经实现。软件中可能成为代码生成候选的一些常见项目包括:
显然,还有更多。代码生成只有两个基本要求。计划生成的内容需要以某种格式提供,并且计划生成的内容需要具有某种重复性。
最常见的生成对象是业务对象。它们往往非常重复,并且由于它们是某种编程语言的一部分,通常生成简单的文本就足够了。如果应用程序基于某种关系数据库,甚至可以利用数据库中的元数据作为生成业务对象的来源。
当考虑代码生成时,首先要做的是设定目标。意思是,应该不仅考虑将要生成的内容,还要考虑为什么。生成的代码只是一个起点,永远不会重新生成吗?或者是否有兴趣在某个时候重新生成代码?对这些问题的回答将对生成过程产生重大影响。
如果只生成一次,需要确保生成过程中使用的任何元数据都是确定的。经验告诉这几乎是不可能的,所以至少确保变更的影响尽可能小,并且确保生成的代码是可读的。
如果要重新生成,请考虑不仅要运行过程并确保不会丢失对生成代码的任何自定义,还需要确保再次使用任何元数据源。稍后会有更多关于这方面的内容。重新生成时的另一个关注点是集成测试。当重新生成应用程序源代码的一部分时,已经更改了所有源代码,很可能由于这个原因,某些东西会失败。确保考虑至少测试失败,或者更好的是,从一开始就防止失败。
可能或可能不需要在组织中推销代码生成,但应该始终为代码生成过程准备一个商业案例。意思是,至少应该对构建生成过程所需的工作量以及最终可以节省多少时间有所了解。基本上,需要在投入大量时间之前,至少为自己进行一次投资回报率计算。知道一开始可能不会投入太多,但相信,最终可能至少会花费最初估计的两倍时间。
在查看这个商业案例时,请确保不仅包括显而易见的内容。每个人都可以计算出不必编写特定数量的代码可以节省多少时间。经常被忽略的是生成的代码质量。它是一致的,这意味着可以测试代码的一个实例,就会知道其余的将如何工作。这也意味着它减少了错误数量,如果发现生成的代码中的错误,它减少了修复这些错误所需的工作量。
在不同的角色中为几家软件公司工作过,经验告诉,拥有更少的错误比节省编写代码的钱更有价值。拥有错误不仅会花费金钱,还会影响声誉和客户满意度。对每个人来说,拥有更少的错误都是好事。
显然,不能生成应用程序中的每一段代码,但中的许多人在某个时候会尝试生成一些难以生成的代码。最难生成的代码之一是GUI的一部分。
假设正在构建一个业务线应用程序,该应用程序中有一百个表单用于数据输入。这显然是一个非常常见的场景。没有多少开发人员喜欢去构建那么多表单。如果工作是自动化重复性任务,那么做重复性工作就感觉愚蠢。
然而,这里还有更多。假设想为Silverlight应用程序这样做。乍一看,需要为每个表单生成一些XAML,并且它需要包含一些TextBlock来包含标签和一些其他控件用于输入。到目前为止一切似乎都很好。
现在考虑实际需要生成的元数据。可能会说已经有了,因为它与用于生成业务对象的元数据相同。是吗?怀疑。业务对象唯一告诉是它包含哪些字段以及它们的类型。它们不会告诉它们在表单中的位置。没有关于这个特定控件需要与大多数其他控件不同的任何特殊行为的信息。
所有这些额外的信息都需要来自功能设计师,无论是某个应用程序专家还是团队中的开发人员。现在假设以某种可用的形式拥有这些元数据。仍然无法生成一个功能性的表单。现在需要绑定到业务对象。最初这并不难,但当数据模型发展或者功能设计师决定在同一表单上链接来自其他业务对象的某个字段时,事情开始变得复杂,因为对用户来说这更容易。
现在假设甚至已经控制了这一点。现在仍然需要输入行为。需要附加事件,这意味着还需要为应用程序生成代码背后的代码,但也希望能够在某个时候扩展代码背后的代码。需要这个过程的元数据最终必须来自开发人员。
如果现在从生成XAML表单的大局来看,不仅仅有一个,而是有三个元数据源:
这三个信息源需要结合起来,以便它们可以用于单一的生成过程。构建类似的东西很快成为一个项目,而不仅仅是一个手段。
那么,应该这样做吗?这是一个很好的问题,没有简单的是或否的答案。这一切都归结为之前解释过的ROI计算。构建和实施这种构建GUI的方式需要多少努力?以及与传统方式相比,节省了多少努力?
显然,如果有一个非常大的应用程序,这实际上可能会奏效,但另一个可能奏效的情况是如果是一个单枪匹马的表演者。如果进行数据建模、功能设计并开发应用程序,那么这可能值得努力。原因是控制了所有变量,没有团队需要检查如何使用这个。