处理特征交叉点


11

我最近目睹了越来越多的问题,这些问题与本文中有关特征交点的解释类似。它的另一个术语是产品线,尽管我倾向于将它们归因于实际上不同的产品,而我通常以可能的产品配置形式遇到这些问题。

这类问题的基本思想很简单:您向产品添加了功能,但是由于其他现有功能的组合,事情变得有些复杂。最终,QA发现了一个罕见的功能组合问题,以前没有人想到过,应该是一个简单的错误修复程序甚至可能变成需要进行重大设计更改的问题。

此特征相交问题的维度令人难以置信。假设当前软件版本具有N功能,并且您添加了一项新功能。让我们通过说每个功能只能打开或关闭来简化事情,那么您已经有2^(N+1)可能要考虑的功能组合。由于缺乏更好的措词/搜索词,我将这些组合的存在称为特征相交问题。(奖励点数包含一个更明确的术语的参考答案。)

现在我要解决的问题是如何在开发过程的每个级别上解决这个复杂性问题。出于明显的成本原因,要想分别解决每个组合问题,直到成为乌托邦式的想法都是不切实际的。毕竟,我们有充分的理由尝试远离指数复杂性算法,但是将开发过程本身变成指数大小的怪物势必会导致彻底失败。

因此,您如何以系统的方式获得最佳结果,而不会花费任何预算,并且以体面,有用和专业上可接受的方式完成。

  • 规范:当您指定一个新功能时,如何确保它与其他所有子功能都能正常使用?

    我看到一个人可以结合新功能来系统地检查每个现有功能-但这将隔离其他功能。考虑到某些功能的复杂性,这种孤立的视图通常已经非常复杂,以至于它本身就需要一种结构化的方法,更不用说2^(N-1)由其他功能引起的因素了,而这些功能是一个人们乐意忽略的。

  • 实施:实施功能时-如何确保代码在所有情况下均正确交互/相交。

    再次,我想知道纯粹的复杂性。我知道有多种技术可以减少两个相交特征的潜在错误,但是没有任何一种能够以任何合理的方式扩展。不过,我确实认为,在规范制定过程中采取好的策略应该可以在实施过程中解决问题。

  • 验证:在测试要素时-如何处理这个事实,即您只能测试该要素相交空间的一小部分?

    很难理解,单独测试一个功能不会保证没有错误的代码,但是当您将其减少到一小部分时2^-N,似乎数百个测试甚至都无法覆盖所有海洋的一滴水。 。更糟糕的是,最有问题的错误是由要素交集引起的,这些错误可能不会导致任何问题-但是,如果您不期望如此强烈的交集,那么如何测试这些错误?

尽管我想听听其他人如何解决这个问题,但我主要对更深入地分析该主题的文学或文章感兴趣。因此,如果您个人遵循某种策略,则在答案中包括相应的来源会很好。


6
合理设计的应用程序体系结构可以容纳新功能,而不会颠覆整个世界。经验是这里的伟大水平。就是说,这种架构在初次尝试时并不总是很容易正确,有时您必须进行困难的调整。如果您知道如何正确封装功能部件并通过适当的单元测试覆盖它们,那么测试问题并不一定就是您所遇到的麻烦。
罗伯特·哈维

Answers:


6

我们已经从数学上知道,由于停顿问题,在最一般的情况下,不可能在有限的时间内对程序进行验证。因此,这种问题并不新鲜。

实际上,好的设计可以提供去耦,使得相交特征的数量远远少于2 ^ N,尽管即使在设计良好的系统中,其数量显然也要高于N。

就消息来源而言,在我看来,几乎每本有关软件设计的书或博客都在有效地尝试尽可能减少2 ^ N,尽管我不知道有什么用您所说的相同的术语来表达这个问题。做。

有关设计如何帮助实现此功能的示例,在本文中提到了一些功能交叉,因为复制和索引都是由eTag触发的。如果他们有另一个通信渠道来分别表示对每个事件的需要,那么他们可能可以更轻松地控制事件的顺序,并且问题更少。

或者可能不是。我对RavenDB一无所知。如果要素之间确实发生了莫名其妙的纠缠,那么架构将无法避免要素交集的问题,而且我们永远也无法事先知道,我们不希望某个要素确实存在2 ^ N交集的最坏情况。但是由于实现问题,架构至少可以限制交叉点。

即使我对RavenDB和eTags错误(并且我只是为了争论而使用它-他们是聪明的人,也许做对了),也应该弄清楚架构如何帮助。人们谈论的大多数模式都是经过明确设计的,目的是减少新功能或不断变化的功能所需的代码更改次数。这可以追溯到例如“设计模式,可重用的面向对象软件的元素”,引言指出:“每个设计模式都使体系结构的某些方面独立于其他方面而变化,从而使系统对特定种类的系统更健壮。更改”。

我的观点是,通过观察实践中发生的事情,人们可以对实践中的特征交点有一个大理解。在研究这个答案时,我发现大多数对功能点/开发工作量(即生产力)的分析都发现,每个功能点的项目工作量线性增长幅度小于线性增长幅度,或者线性增长幅度略高于线性增长幅度。我感到有些惊讶。 这个有一个很好读的例子。

这项研究(以及类似的研究,其中一些使用功能点而不是代码行)并未证明不会发生特征相交并引起问题,但是似乎有合理的证据表明它在实践中不会造成破坏。


0

无论如何,这都不是最好的答案,但是我一直在思考与您的问题相交的某些事情,所以我想我提到它们:

结构支撑

从我所看到的一点来看,当功能存在错误和/或与其他功能无法很好地融合在一起时,很大程度上是由于程序的核心结构/框架为管理/协调它们提供的支持不佳。我认为,花更多的时间充实和完善内核,应该可以简化新功能的添加。

有一件事我发现在我的工作是一个程序的结构,成立了以处理应用程序是共同的一个一类的物体或过程,但很多事情我们已经做或想确实有扩展的与处理许多事情有关类似的事情有关。如果在应用程序设计之初就更多地考虑到这一点,那么它将有助于以后添加这些功能。

当添加对涉及线程/异步/事件驱动代码的多个X的支持时,这变得非常关键,因为这些东西可能很快就变得很糟糕-我很高兴调试了与此相关的许多问题。

但是,要证明这种努力是很困难的,尤其是对于原型或一次性项目-即使其中一些原型或一次性项目可以再次使用或作为最终系统的基础,这意味着从长远来看,这笔支出是值得的。

设计

在设计程序的核心时,从上至下的方法开始可以帮助将事情变成可管理的大块,并使您可以将精力集中在问题领域上。之后,我认为应该使用自下而上的方法 -这将有助于使事情变得更小,更灵活,更好地添加到以后。(如链接中所述,以这种方式处理可使功能的实现更小,这意味着更少的冲突/错误。)

如果您专注于系统的核心构建模块,并确保它们之间的交互良好,那么使用它们构建的任何内容都可能会表现良好,并且应与系统的其余部分更好地集成。

当添加一个新功能时,我认为在设计它时可以采取与设计其余框架相同的方法:分解然后自底向上进行。如果您可以在实现功能时重用框架中的任何原始块,那肯定会有所帮助;完成后,您可以将从功能中获得的所有新块添加到核心框架中已存在的块中,并用原始块集对其进行测试-这样它们将与系统的其余部分兼容并在将来可用功能。

简化!

最近,我一直以简约的态度进行设计,首先是简化问题,然后再简化解决方案。如果可以花一点时间简化项目上的设计迭代,那么以后再添加时,我会发现这非常有用。

无论如何,那是我的2分。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.