TDD:它是否妨碍了良好的API设计?

dsi*_*cha 46 api tdd

我从来没有写过TDD代码,但我在SO上已经看过很多关于它的讨论.我最担心的是,似乎一般良好的API设计(灵活性,易用性,界面简洁性和性能)有时会使代码可模仿,超模块超出任何API使用所需的范围例如,TDD支持者经常建议将事物作为参数传递,从API抽象的角度来看,被调用的方法应该"只知道",或者以一种使测试变得简单的方式考虑类和方法,这不一定是最能与问题领域相关的方式.

对于TDD和API设计更有经验的人:您是否发现TDD经常妨碍良好的API设计?如果是这样,你怎么反击这个?

Jon*_*eet 33

不,我发现TDD通常鼓励良好的设计.易于测试的东西通常也很容易在生产中使用......因为在进行测试时,你会想,"接下来我想做什么?" 然后让它工作.

在练习TDD时,您不得不考虑API的"用例",程序员将如何使用类/方法,最终会得到一个非常有用的框架.如果你有打造百年FooFactoryBarAuthenticatorS,或像你说的API正在成为"超模块化",你可能会在该拿起一边写测试代码,并考虑如何简化它.

至于参数和依赖注入 - 我通常发现使用TDD的依赖关系变得更加清晰.它们通常是构造函数参数而不是方法参数,但要明确API实现需要验证器,随机源等,这对于理解它正在做什么很有用.您可以确定代码不会在某个地方访问网络或远程数据库,因为它将这些内容隐藏在其实现中.这些隐藏的细节是使API难以在测试环境中使用的原因.

请注意,当依赖项是构造函数调用的一部分时,它不是类可能实现的接口的一部分 - 接口中的依赖项通常是隐藏的,但TDD意味着实现以明显的方式公开它们.

有关依赖注入和TDD的良好信息来源可以在Google测试博客上找到.要特别注意由柱MISKO Hevery或看一些他在Youtube上的视频:不要看的东西更多.

  • @dsimcha:您期望这个样板代码在哪里?使用依赖注入的情况非常少 - 您可以使用可模拟的依赖项而不是硬编码的可测试代码.这是一个双赢的局面.对于从未使用过TDD的人来说,你似乎非常确信它会导致一个糟糕的API ...... (5认同)
  • @dsimcha:您需要区分创建接口实例的内容(需要提供依赖项)和*使用*实例(不需要关心). (4认同)
  • @dsimcha:如果给定系统的API需要依赖关系,它将使用TDD来实现.您没有公开实现细节,但暴露了依赖项.有一个很大的不同. (2认同)

小智 13

TDD 一种API设计技术.每次编写单元测试时,您要么是第一次创建API,要么是使用以前创建的API.这些测试中的每一个都让您"感觉"API的使用容易程度或难度.每个新测试都会迫使您从新的角度考虑API.很难有更好的方法来设计API,而不是像TDD强迫你那样详尽地使用它们.

实际上,这就是TDD被认为是一种设计技术而不是测试技术的原因.练习TDD时,不要在真空中设计API.你用它们设计它们!


Mik*_*nty 12

TDD导致紧急设计,最终产生一个非常有用和可扩展的API.TDD不是关于测试.它是关于在代码中创建接缝,您可以在发现有关项目的更多信息时添加行为.


Len*_*ate 12

我已经使用TDD好几年了,我发现它从一开始就为API提供了两个不同的客户端,从而推动API设计朝着更实用的设计方向发展; 你有生产代码和测试代码,两者都想以不同的方式驱动API.

确实,有时我为了更容易测试API而添加东西,但我几乎总是发现,我认为我为了可测试性而放入的东西实际上对于监视目的非常有用.因此,例如,一个FooAllocator可能最终会有一个可选的构造函数参数,它是一个监视接口(IMonitorFooAllocations),这对于在测试期间进行模拟非常有用,使我可以在内部查看,但是当你突然发现时它也非常有用你必须在生产过程中向世界其他地方公开一些分配指标.我现在倾向于考虑我可能想要添加的额外位,以便在可选生产监控的双重用途方面实现简单测试.我通常编写服务器代码并能够公开事物的内部因为perfmon计数器非常有用......

同样,你说组成API的对象通常可以明确地使用其他对象而不是从一个已知位置伸出来获取它们是正确的,但这是一件好事.相信我,一旦你习惯了处理明确的依赖关系,你就不想再回到课堂上去深入了解Widgets当你在API中没有提示他们想要做什么以及为什么你正在访问活动目录时这样的事情.通常情况下,您在设计和测试期间打破这些依赖关系,然后在将所有部分放在一起时再次隐藏它们.您仍然可以"从上面进行参数化",但通常情况下,API的对象模型可能意味着您从未真正将"上方"视为API的用户.你最终得到一个地方来配置它需要的东西,并且通常这看起来没有什么不同,如果你有大量的单身人士和全局和隐藏的依赖关系.

但请记住,TDD是一种工具,当它不适合时不要使用它.


phi*_*red 7

大多数被列为TDD缺点的东西被许多人认为是优秀设计的元素.

如果特别注意传递某些东西的想法而不是某种方法应该"只知道" - 后者通常会导致单身人士或其他反衔接设计.

虽然你可能最终会得到一个设计,其中某些方面只是支持可测试性,但这不一定是坏事.

但是,作为一项规则,如果你必须重新考虑你的设计以使其可测试,你将会得到一个在凝聚力和适用性方面更好的设计- 同时仍然是灵活的,因为它可以很容易地改为无论你未来的需求是通过重构,因为你在那里进行了测试,让你有信心快速做出改变.


tva*_*son 6

我使用TDD并认为它在API构造方面运行良好,但我认为API,尤其是那些暴露给外部客户的API,在这些领域中,您需要比使用TDD时更典型的前端设计.TDD严重依赖于重构,就像测试优先一样.使用API​​,您并不总是能够重构方法签名并保持简洁的设计.如果你不小心预先设计你的界面,你会发现自己有一个丑陋的界面,支持多种方法做非常相似的事情,只是为了保持与现有API的向后兼容性,同时推动你的设计.

如果我有一个API,我知道我会向外部用户公开,我通常会花更多的时间来考虑签名,并在开始开发过程之前尽可能接近"正确".我也会尽早向客户展示它以获得反馈,以便我们尽快融合到稳定的界面.在幕后重构以改进实现而不改变界面并不是一个问题,但我希望能够快速获得稳定的界面,并愿意提前投资以获得它.