关于 Carl Manaster 的精彩回答,在开始 Carl 建议的道路之前,您至少应该考虑一些缺点。
其中最重要的一点是:我们使用封装来最小化具有最大更改传播概率的潜在依赖项的数量。在您的情况下,您在类中封装了私有方法:它们对其他类不可用,因此对它们没有潜在的依赖关系:您对它们所做的任何更改的成本都被最小化并且传播到其他类的概率很低类。
Carl 似乎建议将一些私有方法从您的类移到一个新类中,并将这些方法公开(以便您可以测试它们)。 (顺便说一句,为什么不在原来的课堂上公开它们呢?)
通过这样做,您消除了其他类对这些方法形成依赖关系的障碍,如果任何其他类使用这些方法,这可能会增加更改这些方法的成本。
您可能会认为这种不利的次要因素是值得为能够测试您的私有方法而付出的代价,但至少要意识到这一点。在少数情况下,这可能确实是值得的,但如果您在整个代码库中实施此操作,那么您将大大增加这些依赖关系形成的可能性,从而将您的维护周期成本增加到未知的程度。
出于这些原因,我不同意 Carl 的建议,即“...... TDD 如何改进您的设计的一个很好的例子。”
此外,他表示,“在原始类中,多余的功能已经消失,包装在新类中,因此原始类的设计更简单,更符合单一职责原则。”
我认为被移动的功能根本不是“无关的”。此外,“更简单”是一个没有明确定义的情况:一个类的简单性与其大小成反比,但这并不意味着最简单的类系统将是最简单的系统:如果在这种情况下,所有的类将只包含一个方法,而一个系统将有大量的类;可以说,删除这个类内多方法的分层层会使系统变得更加复杂。
此外,单一职责原则 (SRP) 是出了名的主观,完全取决于观察者的抽象级别。从类中删除方法并不会自动提高其对 SRP 的一致性。具有 10 个方法的 Printer 类只负责在类的抽象级别进行打印。它的一种方法可能是 checkPrinterConnected(),一种可能是 checkPaper();在方法级别,这些显然是独立的职责,但它们不会自动建议应将类分解为更多类。
Carl 总结道,“在萌芽类中,提取的功能是它存在的理由,因此它适合公开,因此无需仅测试修改即可测试。”功能的重要性(它的存在理由)并不是其是否公开的基础。功能公开的适当性的基础是最小化暴露给客户端的接口,以便在最大化客户端对功能实现的独立性的同时,可以使用类的功能。当然,如果您只是将一种方法移动到发芽类中,那么它必须是公共的。但是,如果您要移动多个方法,则必须将那些对客户成功使用该类至关重要的方法公开:这些公共方法可能远不如您希望屏蔽的一些私有方法重要客户。 (无论如何,我不喜欢“存在理由”这个短语,因为方法的重要性也没有明确定义。)
Carl 建议的另一种方法取决于您设想系统增长到多大。如果它会增长到少于几千个类,那么您可能会考虑使用一个脚本将您的源代码复制到一个新目录,将复制的源代码中所有出现的“私有”更改为“公共”,然后编写您的针对复制的源进行测试。这样做的缺点是复制代码需要时间,但好处是保留了原始源的封装,同时使所有方法都可以在复制的版本中进行测试。
以下是我为此目的使用的脚本。
问候,
艾德·柯万
!/bin/bash
rm -rf 代码复制
echo 创建代码副本 ...
mkdir 代码复制
cp -r ../www 代码复制/
对于我在find code-copy -name "*php" -follow;做
sed -i 's/private/public/g' $i
完成
php run_tests.php