TDD和封装优先级冲突

Han*_*seh 4 php tdd phpunit unit-testing encapsulation

我刚开始在我的项目中练习TDD.我正在开发一个项目,现在使用php/zend/mysql和phpunit/dbunit进行测试.我对封装和测试驱动方法的想法有点分心.封装背后的想法是隐藏对多个对象功能的访问.为了使其更清晰,私有和受保护的函数不能直接测试(除非您将创建一个公共函数来调用它).

所以我最终将一些私有和受保护的函数转换为公共函数,以便能够测试它们.我真的违反了封装原则,让位于微功能可测试性.这是正确的做法吗?

Car*_*ter 8

在TDD圈子中有一个非常标准的答案.如果一个类中有功能你想要隐藏和直接测试,你应该发布一个具有该功能的类.这是TDD如何改进您的设计的一个很好的例子.

在原始类中,无关的功能已经消失,包含在发芽类中,因此原始类的设计更简单,更好地符合单一责任原则.在发芽类中,提取的功能是它的存在理由,因此它适合于公开,因此它是可测试的,没有仅测试修改.

  • 这样做的好书是:**有效地使用遗留代码.** (2认同)

小智 7

尊重卡尔·曼纳斯特的好答案,在走上卡尔建议的道路之前,你应该至少考虑一些缺点.

其中最重要的是:我们使用封装来最小化带有最大变化传播概率的潜在依赖关系的数量.在您的情况下,您在类中封装了私有方法:它们不可用于其他类,因此不存在对它们的潜在依赖性:您对它们所做的任何更改的成本都会降至最低,并且传播到其他类的可能性很低.类.

似乎Carl建议将一些私有方法从您的类中移动到一个新类中,并将这些方法公开(以便您可以测试它们).(顺便说一句,为什么不在原来的课堂上公开呢?)

通过这样做,您可以消除其他类对这些方法形成依赖关系的障碍,如果任何其他类使用它们,这可能会增加对这些方法进行查询的成本.

你可以判断这个未成年人的未成年人和一个有价值的价格,以便能够测试你的私人方法,但至少要注意它.在少数情况下,它确实是值得的,但如果您在整个代码库中实现这一点,那么您将大大增加这些依赖关系形成的可能性,从而将维护周期的成本增加到未知程度.

出于这些原因,我不同意Carl的观点,他的建议是"...... TDD如何改善您的设计的一个很好的例子."

此外,他表示,"在原始课程中,无关的功能已经消失,包含在萌芽的课程中,因此原始课程的设计更简单,更好地符合单一责任原则."

我认为移动的功能根本不是,"无关紧要."而且,"更简单",是一个定义不明确的:当然可能是类的简单性与其大小成反比但不是意味着最简单的类系统将是最简单的系统:如果是这种情况,所有类只包含一个方法,系统将拥有大量的类; 可以认为,删除这种类内多个方法的层次结构会使系统更加复杂.

此外,单一责任原则(SRP)是众所周知的主观因素,完全取决于观察者的抽象程度.完全不是从类中删除方法会自动改进其与SRP的一致性.具有10种方法的Printer类具有在类的抽象级别进行打印的单一职责.其中一个方法可能是checkPrinterConnected(),一个可能是checkPaper(); 在方法层面,这些显然是单独的职责,但它们并不自动建议将该类分解为更多的类.

Carl完成了,"在萌芽阶层,提取的功能是它的存在理由,因此它适合公开,因此它是可测试的,没有仅测试修改."功能的重要性(它是存在的理由 - ness)不是公开适当性的基础.功能公开的适当性的基础是最小化暴露给客户端的接口,使得类的功能可用,同时客户端的功能实现的独立性最大化.当然,如果你只是将一个方法移动到发芽类中,那么它必须是公共的.但是,如果要移动多种方法,则必须将这些方法公之于众,这对于客户成功使用该类是必不可少的:这些公共方法可能远远不如您希望屏蔽您的某些私有方法重要.客户.(无论如何,我不喜欢这个,"Raison-d'etre",因为方法的重要性也没有明确定义.)

Carl建议的另一种方法取决于您设想的系统增长程度.如果它将增长到少于几千个类,那么您可能会考虑使用脚本将源代码复制到新目录,在该复制的源中更改所有"private","public"的出现,然后编写对复制的源进行测试.这具有复制代码所需的时间的缺点,但保留封装原始源的好处,但使所有方法在复制版本中可测试.

以下是我为此目的使用的脚本.

问候,

埃德柯万

!/斌/庆典

rm -rf代码复制

echo创建代码复制...

mkdir代码复制

cp -r ../www code-copy /

因为我find code-copy -name "*php" -follow; 做

sed -i 's/private/public/g' $i
Run Code Online (Sandbox Code Playgroud)

DONE

php run_tests.php