最近对一个项目进行重构,使用TDD的方式,在开发过程中,对TDD在真实项目中的应用有一些疑惑,于是在TDD的群里请教了以下,熊大和热心群友给予了解惑,同时还有另外一个哥们也抛出了一些问题,和我在开发过程中所遇到的问题非常相近,所以在这里做个记录
项目简述:
我的问题:
1.在开发过程中,是自顶向下开发,还是应该自底向上开发,及是应该从controller -> app service -> domain逐层展开,还是domain -> appservice -> contoller 逐层完善
答:这个问题和TDD无关,TDD只关心一件事情,没有测试就不能写代码,有了失败的测试才能写代码,应该是先做一个最简单的端到端的架子,再一点点的完善逻辑
2.在自顶向下开发的过程中,比如在TDD controller时,由于appservice还是完成逻辑,是先mock appservice接口,还是先去完成appservice的开发,再回过头来继续开发controller
答:一般非外部接口不mock
另一个哥们的问题 & 具体业务案例:
这个问题也是我在开发过程中所遇到的问题,在快速迭代的环境下如何持续集成,不影响发布。
在这个流程中,熊大指出:
1.应该先做addPoint service,
2.再创建account对象,
3.做界面(接口)
4.添加一个字段,如果这个字段不属于account,添加它应该属于的对象
5. 重复4直到完成需求
要现有界面(接口),如果没有接口,整个流程没有通,添加的所有值对象、所有方法都是无法展示。
熊大的Tasking:
1. 实现空的addpoint服务,验收条件:服务部署上线,可以被调用,有可发布的文档
2. addpoint服务接受一个参数
3. 重复2直到完成需求
伪代码:
account = accountRepository.load(accountId)
account.addPoint()
继续提问:在account的addpoint业务中,需要查询以下加积分的规则(redis/db),然后查已经加了积分的历史,这些都要依赖数据库,应该怎么处理
答:规则属于reference data,在外部查询出来传给它,历史记录可以通过account根找出来。
总结:
1. 先写空的接口,使接口可发布,并且尽快发布,做到有文档可用。空接口可以先hard code 返回一些数据。
2. 充血模型的类,属于对象子的状态,需要对象自己的方法去实现。对这个类的自己业务也使用TDD 驱动出来
3.在实现复杂代码的时候,不要一次全部写完,逐步迭代。保证系统能持续通过测试和发布。
4.service层(顶层)的测试方法,不需要测试所有场景,输入依赖方法的逻辑,单独写测试方法去测试。即只测试属于自己职责的代码。
5.如果domain需要依赖第三方的数据(db/redis/api)可以在service查询出来,然后传给domain去实现逻辑