“ 大家好,这是【产品线工程(PLE)专题】更新的第五篇,上一篇我们介绍了‘特征模型和特征-这是什么’,这一篇我们介绍‘深入产品线的配置管理’”
up-e0a3c22456929850456680799d1e503a3df.jpg

© pure-systems GmbH

      如果您目前已经阅读了我们所有的白皮书,那么您应该了解了特征、特征模型以及变体都不是“版本”。但是这里仍然有一些并未提及的事情:产品线的配置管理。接下来的这篇文章便是就该话题进行讨论。
      产品线的配置管理是一件复杂的事情吗?这是肯定的!产品线的配置管理必须要复杂吗?并不完全是!可以说,单个系统开发的配置管理和产品线开发的配置管理之间没有(重要的)区别,除非您做错了。可能您会对此表示怀疑,那么针对这个观点,我们将会进行更深入的探讨。
配置管理系统的误用及带来的问题
      首先,我将列出大家在产品线实施配置管理时可能会犯的错误,即把它作为一个变异性和变体管理的系统来使用。通常情况下,配置管理系统(又称版本控制系统)提供一个被称为分支的概念。分支意味着创建一组工件的副本并且随后会对其进行独立于原件的修改。分支有许多适当的用途(我们将在后面讲到)和一个相当不恰当的用途:将分支作为资产复用管理的核心。
      如果采用如下方式处理变体,例如首先创建分支,然后使用分支区分不同的产品。那么在大多数情况下,与其他的复用方式相比,这种方式会出现(不必要的)开销,这是因为通常有分支的工件(简单的,我们假设针对单个文件的分支)不会被完全修改,并且在原始和分支副本之间存在一定数量(通常相当大的)相同部分。
  • Q1--您怎么知道什么被复用了,以及在哪里被复用了?
设想一个场景,我们在分支或者原始流中发现了一个问题,(我们假定是在原始版本中发现的)。我们完成了修复工作并且递交到版本管理系统中。目前为止,看起来一切安好。现在,我们需要对这个分支做些事情。首先,我们注意到:分支的工件正在某些产品中使用,那么我们必须对其进行修复。有些版本管理系统支持您在发生变化时,在分支中找到相关的工件。目前看起来不错。在文件的某些部分发现了修复,这些部分在原始文件和分支中看起来都是一样的,似乎很容易简单地复制修复。不过虽然看起来这不是个问题,但它肯定会引起其他问题。
  • Q2--您怎么知道应用的修正是正确的?
      等一下! 您怎么知道在分支中文件的这一部分内容是被允许修改的呢?变体的受管理粒度在文件中,因此,无论是对于版本管理系统还是对于人员,都没有简单的方法去了解分别属于原始和分支文件的多个相同实体(例如,文件中的行)是否应该相同(不是实际变体的一部分,因此应该共享),或者某些实体是否实际属于变体(如分支时所预期的那样)且不得更改。
      我们可以举一个例子,例如配置一个用于设置缓存区大小的常量参数。如果该参数同时在源算法和分支算法中使用,那么在源算法的实现中的修改并不意味着在分支的算法中进行修改,分支中甚至可能不允许修改。因此,即便从技术上,在版本管理中应用某修复程序不会显示产生冲突,您也必须对该修复程序的哪个部分可以应用于分支工件进行检查。在拥有恰当的自动化测试套件的情况下,您必须对包含合并工件的所有产品进行测试,以确保没有产品受到损害。但在其他所有情况下(对于某些领域的自动化测试套件是不可能的),基本上只能依靠工程师的经验。
  • Q3--共享和非共享的资产与变更集
m如果分支的工件基本上代表了一个变体,并且(几乎)不包含任何共享的代码,那么这个问题的讨论就不存在了。这意味着变体在文件的颗粒度上被适当地封装了。在这种情况下,一个文件在原始副本和分支副本之间或者被共享,或者不被共享。如果所有的文件都如此,那么您只须处理包含了共享文件和非共享文件的变更集即可,但必须把它们分成只与共享文件有关的变更集和针对单一分支的变更集。
      对于包含共享文件的变更集,必须对所有共享文件的实例进行变更。但是如果您后来从以前的分支副本中创建了一个新的分支,该分支副本与原始的分支副本共享,但没有与原始副本共享,那么情况就会变得复杂。再强调一次,在版本控制系统中跟踪处理这种情况会很复杂。
  • Q4--它不只发生在文件上
      到目前为止,我一直在谈论“一个文件”,但实际上,可能会存在成百上千的问题件。而且,因为对于每一个变化,您都必须对每个分支进行同样的处理,所以随着分支数量的增加,工作量也会急剧增加。虽然针对少量共享工件和少量的分支而言是可行的,但是少量的共享工件限制了可重用工件的数量,而少量的分支则限制了变体的数量。我们可以通过一张图看到其复杂性。图1显示了一个典型的(简化的)来自版本控制系统的分支/合并日志(时间从左到右进行)。使用典型的“分支&合并”策略,即创建现有系统的克隆,之后通过独立维护的方式来管理七个产品(P1-P7)。显然,使所有分支实例保持变化同步是一项相当大的任务。由于进行合并需要工作量,因此在大多数情况下,只有“成对的”合并发生,即从另一个产品中直接挑选一些部件,从而导致系统性的复用却看起来互不相同。
up-359d963315b2096dc91b29c85d5e374161c.png
图1 © pure-systems

  • 关于误用的结论
      总结一下,除非版本管理中工件颗粒度与变体颗粒度基本一致,否则版本管理中的分支并不利于表达变体。因此,无论您的版本管理系统的供应商多么强调其处理变化的能力,您都需要注意颗粒度是否匹配。并且在工件是文件的情况下,出现颗粒度不匹配的情况几乎是不可避免的。但是,也请不要误会我的意思:您必须使用适当的版本管理来跟踪您的工件在其生命周期内的变化。只是不要将变体和变体管理混在其中。变体管理是一个独立的、正交的维度,表达了在某一特定时间点可用于和被用于变体的内容。

正确使用产品系列的配置管理系统
      如果您现在想知道哪些分支在产品线开发中是有用的,可以这样描述它们——在单个产品开发中,分支只适用于两件事:将独立开发活动与主开发分支(通常称为“功能分支”)进行短期解耦,以及将(即将发布的)版本与主分支上正在进行的更改(通常称为“发布分支”)解耦。这两个概念的描述可以在一些版本管理的电子书中看到(描述大多数独立于版本,只需要将“trunk”替换为“主开发分支”即可)。应用这些概念可以绘制一个相对于图1而言更加清晰和美观的图(见图2)。主开发流上方的分支(在下图中称为"集成")表示为发布创建的分支,下面的分支用于开发新功能。通常,分支要短得多,合并主要从开发分支到主(集成)开发流,很少从(或到)发布分支。
up-a77c3fc9eba8cdc2f340c4b8b7667345161.png
图2 © pure-systems

      这种方法不仅使画面更美观,也使真正的复用变得更容易实现。在图中,您看到的是变体(V1-V4),而不是产品,它们来自同一个共同的基础。从共享库中实际派生变体这一动作将作为独立活动执行,且通常通过配置或使用适当的可变性和变体管理工具(如 pure::variants)来实现。关键点在于此派生/实例化活动是在受版本控制的工件之上完成的,因此版本控制系统可用于记录实例,但不提供变体点机制。

总结
      这让我回到了我最初的主张:如果可变性和变体的表示没有通过版本管理来实现(通过版本管理实现是个好主意,如上文),那么当涉及到产品线时,除了性能和可扩展性(由于更多的用户和更多的变化)之外,版本管理没有什么特别之处。

作者:Danilo Beuche
翻译:经纬恒润

【产品线工程(PLE)专题】下期预告:企业需要什么——以及他们在哪里
* 如果您对PLE或pure::variants感兴趣,可以通过拨打电话与我们取得联系,同时还能获得pure::variants30天的试用申请哦~