Design patterns 如何说服团队成员不要使用单例?
我是这个团队的一员,在过去两年里,这个团队有了长足的发展。“老团队”的三名成员已经在一个图书馆工作了两年多,现在团队的其他成员不得不使用这个图书馆。他们在那个图书馆投入了大量的精力。不幸的是,那里到处都是单身汉 单例使我们无法编写可测试代码。TDD对一些团队成员来说很重要,但只有三个库创建者才能容忍。到目前为止,我们已经尝试了以下方法来说服他们摆脱单身汉:Design patterns 如何说服团队成员不要使用单例?,design-patterns,Design Patterns,我是这个团队的一员,在过去两年里,这个团队有了长足的发展。“老团队”的三名成员已经在一个图书馆工作了两年多,现在团队的其他成员不得不使用这个图书馆。他们在那个图书馆投入了大量的精力。不幸的是,那里到处都是单身汉 单例使我们无法编写可测试代码。TDD对一些团队成员来说很重要,但只有三个库创建者才能容忍。到目前为止,我们已经尝试了以下方法来说服他们摆脱单身汉: 指出了单例的问题(全局状态、紧密耦合、难以测试) 反对意见被拒绝,因为当前代码有效 证明了我们的测试(使用库/单例)有时会失败 被拒
- 指出了单例的问题(全局状态、紧密耦合、难以测试)
- 反对意见被拒绝,因为当前代码有效李>
- 证明了我们的测试(使用库/单例)有时会失败
- 被拒绝,因为我们显然“不知道如何处理单身”
- 提供了替代实施方案
- 已拒绝,因为其当前代码已生效
- 与上级讨论问题
- Superior不是软件开发人员,必须在问题的两种“有效”观点之间进行选择。更信任年长的团队成员
// Existing code
public class FooSingleton
{
public static FooSingleton Instance { get { ... } }
public void Bar()
{
...
}
}
public interface IFoo
{
void Bar();
}
public class SingletonDelegatingFoo : IFoo
{
public void Bar()
{
FooSingleton.Instance.Bar();
}
}
然后,您使用普通的依赖注入(或其他)使您自己的代码可测试,只依赖于IFoo
——并且在运行整个系统时注入SingletonDelegatingFoo
(顺便说一句,这些单例模式的实现是否正确?如果你能证明单例模式不仅从测试的角度看很糟糕,而且可能实现得很糟糕,那么你可能会得到更多的认同……(您尚未说明您的语言或平台,因此我将以C#为例。不过,我希望同样的原则也适用于其他人。)
您是否可以创建自己的接口以及适当授权的接口实现?即使库设计人员不愿意实现接口,您也可以始终授权:
// Existing code
public class FooSingleton
{
public static FooSingleton Instance { get { ... } }
public void Bar()
{
...
}
}
public interface IFoo
{
void Bar();
}
public class SingletonDelegatingFoo : IFoo
{
public void Bar()
{
FooSingleton.Instance.Bar();
}
}
然后,您使用普通的依赖注入(或其他)使您自己的代码可测试,只依赖于IFoo
——并且在运行整个系统时注入SingletonDelegatingFoo
(顺便说一句,这些单例模式的实现是否正确?如果你能证明单例模式不仅从测试的角度看很糟糕,而且还可能实现得很糟糕,那么你可能会得到更多的认同。)有经验的开发人员通常的做法是更新他们的简历/简历,并开始四处寻找另一份工作,然后才意识到系统无法可靠地交付,无论如何都会交付,并成为一个永无止境的垃圾桶,需要有人持续维护。“某人”应该是其中之一拥有40年养老金保障权的老年开发商——“他/她无法拒绝的提议”
也许我太愤世嫉俗了,因为我的最新项目在一次无害的改变后,一夜之间就变成了一堆金子,也许我还记得几十年前我在一次审查会议上站起来说“这项工作不可能按设计的那样工作”时发生的事情,(从那次经历开始,我就早早地离开了,或者是作为一份合同工作).一个有经验的开发人员通常的做法是更新他们的简历,并开始四处寻找另一份工作,然后才意识到这个系统不能足够可靠地交付,无论如何都要交付,并成为一个永无止境的瓦罐,而不是一个人必须不断维护的金子。这个“人”应该是其中之一e有40年养老金保障权的老年开发商——“他/她不能拒绝的提议”
也许我太愤世嫉俗了,因为我的最新项目在一次无害的改变后,一夜之间就变成了一堆金子,也许我还记得几十年前我在一次审查会议上站起来说“这项工作不可能按设计的那样工作”时发生的事情,(从那次经历开始,我就早早地离开了,或者把它作为一项合同工作来完成)。在我看来,您必须将该库视为代码的外部依赖项(就像第三方库),并相应地编写代码 这意味着,正如Jon Skeet所提到的,将代码设计为在没有外部库的情况下隔离和可测试的它捕获了您期望他们履行的必要契约,还编写了两个集成测试,用于测试代码与该库之间的通信。理想情况下,通信面应尽可能小,可能仅限于实现接口的两个适配器或桥接器 然后就变成了一个“契约”协商的问题,你会指出库中的某些部分没有按预期工作,并(希望)等待修复或相应地修改你的代码。你可能会以这种方式暴露错误和语义不匹配,这可能会促进代码和库的并行演化
如果您的代码是该库的唯一使用者,那么您应该指定对它的期望,并且它应该适应您的需求,而不是相反。如果他们随后提供您期望的服务,那么他们使用单例或其他什么的事实就变得无关紧要了。在我看来,您必须将该库视为一个ext