单元测试有时候反而破坏程式码的易读性和维护性
因为要做到单元测试,就得断开所有的相依性
而对抗相依性,作法就是引入 DI。但是 DI 就会增加代码阅读和维护的复杂度。
举例来说,如果代码内有时间上的相依性,例如用了 DateTime 物件取得现在时间做某些
判断,原本可以很简单的写出易于阅读和维护的逻辑:
If (DateTime.Now > 12:00:00) then return “PM” else return “AM”;
为了让单元测试可以控制验证条件,只能
Interface IDateProvider { virtual GetNow(); }
Class DateMock : IDateProvider { GetNow() { return 13:00 }
IDateProvider dateProvider = container.Build(....);
If (dateProvider.GetNow > 12:00:00) then return “PM” else return “AM”;
然后再搞个 config 想办法让程式吃到你写的 DateMock 类别....
上面是sudo code 就不用讨论语法细节
这就是单元测试的代价!程式真的会比较容易阅读吗?
单元测试要花在切除相依性的条件花费的成本时间远高于撰写production code
而且你的 production code 能不能赚钱还不知道咧?
到底需不需要单元测试和 clean code ? 先搞清楚写的用途和目的,你写的东西有没有
真正的商业价值再说吧。
不要把 clean code 和 TDD 无限上纲了
工程师最容易自嗨就是这样,还会自以为“这是专业”?
乞丐的乞讨专业比我们强也不会产生“价值”。
※ 引述《banqhsia (BEN)》之铭言:
: ※ 引述《peanut97 (丁守中)》之铭言:
: : 大家中秋节快乐,快收心了。
: : 想问一个假设性问题,大家在工作上,如果有一份专案的 code 是某位前人一手写的
: : 后来新人加入,变成前人带新人,此时继续维护那份code。
: : 但再过一阵子,前人离职了,唯一的创始者走了。
: : 新人把旧 code 重构,或是砍掉重炼的机率高吗?
: 先跟主管、老板提,确认有人支持你,不然你会被当成怪物
: “为什么要改?”
: “系统好好的干麻改?”
: “改了有好处吗?”
: “会花多久时间?”
: “时间剩不多,要动不动随便你,不要影响到时程”
: : 我的想像是,如果一份code是出自于1个人之手
: : 我的想像是,如果一份code是出自于1个人之手
: : 那么code就是他的世界观、他的切入点
: : 那么code就是他的世界观、他的切入点
: : 后面的人看着他的世界观,有时候不一定能全部接受
: : 而有人的地方就有政治
: : 当他还在的时候,当然就不会乱动。
: : 而当他走了的时候,后面的人,一看不爽,就可能改写成自己看得爽的、
: : 好改的code。
: : 如果是一个团队,那当然要好好讨论为什么要改
: : 哪些因素造成现在不好的情况,以及主管同不同意改等等的。
: : 只是我很好奇,1,2人的专案,改的机率高吗?
: : 是不是,code只能是“现在还存在公司的人”能控制的才行。
: 我们公司的经验,以前因为很多原因 (十几年前的 code)
: 导致系统没有测试、没有严谨的 coding style、方法注解也很少
: copy paste 是基本,没有遵照 SOLID
: 错误不是丢 null 就是 false (欸! 我的 Exception 呢?
: 每个 team 成员想怎么写就怎么写,不管后续的涟漪
: 反正东西交出来就好 多棒
: 然后中间当然成员就是来来去去的
: 我看这之中大概也是 有人进来 -> 看 code -> what the fuck? -> 离职
: 大概就是这种循环
: 因为自己痛过,知道 clean code、设计模式 的重要性
: 进公司没多久就跟主管说这 code 不能搞,一定要重构
: 每个工程师一定看不爽前人的 code XD
: 但是不是说说而已,总是要提出改善的方法
: 理所当然地,你前面那些问题我都被问过
: 幸好我的主管与老板也是支持我这件事情
: 但是我们讨论的结果,现在的 code 也没办法全部翻掉,怎么办
: 在那个时候刚好要把原本的系统生出一套 API
: 原本的系统是 server-side template render,模板与资料、样式高耦合
: 这个没办法改成 API
: 我们的作法是,把原本 DAO 抽出来,放进框架里当成 library
: 然后加一层 Adaptor 让新系统相容旧模组
: 旧的 DAO 逻辑怎样就不去动他,要改一律在 Adapter 里面改
: (就算 method rename 也是)
: 在这个新系统,以 SOLID 与设计模式为基楚
: controller 与逻辑之间,包装成 service 呼叫 (一律把该写的东西放在该去的地方)
: service 只准有抽象的叙述,实作的部分写成接口去依赖,由子类别注入 service
: 使用 DI Container 自动注入依赖的类别,不准直接 new (方便替换测试)
: 提交功能分支以前,要一并提交单元测试与 functional test,否则不准进 develop
: 这些都是规定好写在专案文件里面的 (以前没有的文件,现在开始留下记录)
: 接着就是重头戏的部分