你是否在线上编程环节中遇到问题?
是否在编程中反反复复的出现BUG?
是否很好奇如何结对编程完成题目?
ThoughtWorks官方攻城狮将进行结对coding直播,解答你的疑问!
1.编写一个失败的单元测试。
2.修改产品代码使之通过单元测试。
3.重构单元测试和产品代码。
是重构吗?
不是,先编写测试,执行,失败了?才可以编写业务代码实现部分,执行,测试通过?是。
是重构,编写业务实现代码,执行,测试通过?是。
**单元测试步骤:**
AAA(Arrange、 Action、Assert) 安排(设置背景)、行动(执行方法,呼叫函数)、断言
working software is based on working test cases 工作软件基于工作测试用例
TDD核心思想
1.除非为了使一个失败的单元测试通过,否则不允许编写任何产品代码
。
2.在一个单元测试
中只允许编写刚好能够导致失败的内容
(编译错误也算失败)。
3.只允许编写刚好能够使一个失败的单元测试通过的产品代码
。
TDD流程
1.编写一个失败的单元测试。
2.修改产品代码使之通过单元测试。
3.重构单元测试和产品代码。
你这种情况可以采用TDD的方式对API进行测试,这也是一种ATDD,验收驱动测试开发。你可以连接真实的数据,也可以用Fake DB,比如内存数据库。
还有一种方式,你按照架构进行分层,比如
只要有测试的地方,都可以采用TDD。
针对你列举的例子,如果站在API的用户角度去思考怎么验收你的API,比如查询文章,那你一开始的验收标准是:一个用户发了某个请求,Response要包含文章内容和请求的用户手否收藏等信息。你就可以一开始写一个这样的测试,然后再去写API功能,让测试通过。你所说的忘记了并不是你TDD出问题,是因为你TDD写的测试没有针对API去测试,而是测试内部实现细节。就好比,用户要一个车,你TDD的时候,你测试目标是覆盖造轮子,造门,你只需要需要加一个覆盖造车的测试就好,而这个测试到实现,完全可以采用TDD的方法。
不知道有没有解答你的问题?
盖房子时,工人师傅砌墙会先用桩子拉上吊线,以吊线为基准,以使砖能够垒的笔直。而测试驱动开发也是如此,先写一个测试,然后研发过程以此为基准,只编写能通过这个测试的功能代码。
顺序颠倒下,先垒砖,再拉吊线看墙面是否笔直,不直的话进行校正。这个过程就像传统的软件开发流程,先写功能代码,然后进行测试,有错误再一点点修改,因此,会严重影响研发效率。
代码整洁可用,是测试驱动开发所追求的目标。但有很多因素会妨碍我们得到整洁的代码,甚至是可用的代码。
如何实现测试驱动开发?
只有自动测试失败时,我们才重写代码;
消除重复设计,优化设计结构
这两条规则实际上也蕴含了开发过程中所经历的阶段。 测试驱动开发的整个流程正是将目标拆分,先达到“可用”目标,再追求“简洁”目标。
首先思考并编写用于定义产品代码 行为的测试
运行测试,发现新增的测试不能通过
编写适当够用的代码
运行测试,直至测试通过
重构代码,以消除重复设计,优化设计结构
运行测试,验证重构是否引入新的错误,直至测试通过且无需再重构
最后重复上述步骤
测试驱动开发其实是戴两顶帽子思考的开发方式:
先戴上实现功能的帽子,在测试的辅助下,快速实现其功能;
再戴上重构的帽子,在测试的保护下,通过去除冗余的代码,提高代码质量。
测试驱动开发,要求测试可以完全自动化运行,在对代码进行重构前后,必须运行测试。
这有助于编写简洁可用和高质量的代码,能快速响应变化,并加速开发过程。
定律一:在编写不能通过的单元测试前,不可编写生产代码。
测试驱动开发主张“测试先行”,这意味着我们必须先写单元测试,并且该单元测试必然失败,才能编写生产代码。
定律二:只允许编写刚好能够导致失败的单元测试,编译失败也属于一种失败。
测试驱动开发鼓励“简单设计”,以很小的增量进行开发,遇到设计问题时能够及时解决,不要期望一个测试能实现多个功能。
定律三:只允许编写刚好能够使得失败的单元测试通过的生产代码。
简洁,尽最大可能减少不必要的工作,也是敏捷基本原则之一。
要避免盲目编写将来有可能需要的代码。
遵循了测试驱动开发的这三条定律,那所有代码都是可测试的了。
“可测试”的另一个词是“解耦”,为了单独测试模块,必须将其分离,所以测试驱动开发强迫分离模块,
迫使大家创建更好、更少耦合的设计。
Kent Beck最早在其极限编程方法论中,向大家推荐“测试驱动”这一最佳实践。极限编程中所有实践方法并不是独立的,而是相辅相成的。欢迎大家关注极限编程系列往期视频,了解更多极限编程实践方法。
是说只编写必要的代码,用最简洁的代码来实现当前的需求,来让程序结构保持最简单、最小、最富表现力。“保持简单、保持笨拙”,这也是著名的KISS(keep it simple, stupid)原则。
很多软件设计很 好地践行了这一原则,例如知名的Unix。Unix 哲学中的很多原则也都体现了简单设计:
1.清晰原则:代码要清晰,避免晦涩难懂,清晰的代码不容易崩溃且容易理解和维护。同时也要重视注释,避免日后阅读、维护艰难;
2.简洁原则:复杂的软件出Bug的概率会更高,所以代码设计要尽可能简洁,从而降低维护成本;
3.组合原则:不同程序之间通过接口相连,而接口之间则用文本格式进行通信,因为文本格式是最易处理,也最通用的格式;
模块原则:每个程序只做一件事,不要试图在单个程序中完成多个任务。例如Unix中的管道文件,管道是一个程序的输出,也是另外一个程序的输入,每个程序只专注在某一个方向;
优化原则:在功能实现之前,不要考虑对它进行优化。毕竟"先求运行,再求正确,最后求快。"
Unix程序员追求简单设计,源于一个注重实效的事实:复杂度就是成本。复杂的软件更难以开发、测试、调试和维护。
Kent Beck 在《解析极限编程——拥抱变化》中,为简单设计制定了按优先级排列的4条原则:
通过所有测试:代码可通过在项目中所编写的各种测试,且最终能被客户验收;
尽可能清晰表达:所有代码都明确表达作者意图,简单说就是要尽可能增加代码的可读性;
尽可能消除重复:重复,意味着低内聚、高耦合。消除重复,才会有助于提升软件的响应力;
更少代码元素:尽可能减少代码元素,保持简洁,来降低代码的复杂度。
极限编程核心价值中的简单和勇气,在简单设计中得到了充分的体现。在实际项目研发过程中,简单设计并不是不为将来考虑,而是面对系统变更时,团队要有足够的勇气和信心,相信我们有能力通过重构,来应对新的挑战和变化。那么,团队该如何重构,我们下个视频见。
是在不改变软件可观察行为的前提下,改善其内部结构。重构的目的是使软件更容易被理解和修改。
重构可以减少技术债务
重构让代码更清晰且容易理解,以便让其他程序员也能更轻松地维护和添加新功能。重构可以避免我们将时间精力过度花在理解系统、寻找重复代码上。
重构改进软件设计
如果没有重构,程序设计会逐渐腐败变质。重构很像是在整理代码,经常性重构可以帮助代码维持自己该有的形态。
重构使软件更容易理解
刚开始进行重构时,虽然代码可以正常运行,但结构可能不够理想。但只要在重构上花一点时间,就可以让代码更好地表达自己的用途。
重构帮助找到Bug
通过不断重构,清楚掌握代码结构,有助于我们快速找出Bug,进而帮助我们更有效地写出更好的代码。
团队不需要单独拿出大块时间来做重构,也不需要为了重构而重构,重构应该随时随地进行。
三次法则
当我们第一次执行某操作时,只管去做,即便代码有待提升;
第二次做类似操作时,代码仍然有待提升,但依旧可以完成;
第三次做类似事情时,请开始重构。
添加功能时重构
为软件添加新功能时,通过重构可以帮助我们更好地理解代码。同时,当发现代码设计无法支持我们添加新功能时,也可以用重构来弥补它。通过重构,使得新特性的添加更顺畅、快捷。
修补错误时重构
调试过程中运用重构,主要是为了让代码更具可读性,以帮助我们找出Bug。比如当系统弹出错误报告时,这其实就是需要重构的信号,因为显然代码还没有清晰到能让我们迅速发现Bug。
代码评审时重构
重构可以帮助我们复审别人的代码。重构前我们可以先阅读并理解代码,提出一些建议。当有新点子时,可以考虑通过重构去实现它,这不仅有助于我们提出更多恰当的建议,还能使代码评审得到更具体的结果。
Kent Beck 提出了“两顶帽子”的比喻。使用重构技术开发软件时,
先戴上实现功能的帽子,在测试的辅助下,快速实现其功能;
再戴上重构的帽子,在测试的保护下,通过去除冗余的代码,提高代码质量。
重构也并非银弹,没有什么银弹流程或实践可以让项目完美运作。欢迎大家关注极限编程系列往期视频,了解更多极限编程实践方法 。
https://www.zentao.net/xp/xp-system-metaphor-80315.html
作为极限编程中的一个工程实践,就是用通俗易懂的语言将原本晦涩难懂的概念或开发过程阐释出来,达到“一说就懂,一听就会”的效果。
隐喻就如同小分队交接的暗号,只有同一阵营中的成员才能明白隐喻指代的是什么。在电影《智取威虎山》中,解放军杨子荣就利用土匪间通用的黑话彻底打消了几个匪徒的怀疑,顺利地混入土匪老巢,最终活捉匪首“座山雕”。
此外,IT行业中也有一些只有行内人才能知晓的隐喻,比如:提到“1024”就能立马联想到程序员节;提到“7*24”,就明白这是为“每周七天,每天二十四小时待岗”的码农们设立的国际运维节等。
实际上,系统隐喻的实践就是为了缩减交互人之间的沟通成本、提高沟通效率。一个合格的隐喻要遵循以下内容:
一个隐喻只涉及一种过程
假设团队A称看板为即时贴,而团队B称看板为白板,当团队A与团队B进行交流的时候,就会产生交流障碍。所以,在软件开发过程中,共享这一过程的开发团队之间要用统一的、被所有人认可的隐喻。
隐喻要得到特定范围内的所有人认可
隐喻是建立在团队的共同认知的基础上的。在某一团队、某一公司甚至某一行业中,隐喻应是这一特定范围内所有人员都熟知的事物或活动,并且需要得到所有人的认可。
在极限编程中,客户以及最终用户需要参与到软件开发过程中,所以为了让这类人员能够真正了解流程,在沟通时要避免使用技术术语以及公司内部的行话,代之以通俗易懂的隐喻。
隐喻要解决问题而不是产生更多问题
隐喻的设置要考虑各方面的因素,比如:日常化、普遍化等,以防止它造成不必要的误解,从而产生更多的问题。
总之,隐喻不像算法那样是可预测的、确定的、不可变化的,相反,隐喻具有随意性。因此,在具体实践中可以用形象的隐喻来描述系统或功能模块是怎样工作的,以帮助参与者都能清楚地理解要完成的客户需求、要开发的系统功能以及开发的总体流程。
https://space.bilibili.com/1611831474
C# Async/Await: 让你的程序变身时间管理大师