外观
04.敏捷调试、敏捷协作
约 4938 字大约 16 分钟
项目管理devops敏捷开发个人
2022-06-05
第7章:敏捷调试
记录解决问题的日志。
警告就是错误。
对于问题各个击破。
报告所有异常。
提供有用的错误信息。
记录问题解决日志
不要在同一处跌倒两次。
每日日志
- 问题发生日期。
- 问题简述。
- 解决方案详细描述。
- 引用文章或网址,以提供更多细节或相关信息。
- 任何代码片段、设置或对话框的截屏,只要它们是解决方案的一部分,或者可以帮助更深入地理解相关细节。
维护一个问题及其解决方案的日志。保留解决方案是修复问题过程的一部分,以后发生相同或类似问题时,就可以很快找到并使用了。
平衡的艺术
- 记录问题的时间不能超过在解决问题上花费的时间。要保持轻量级和简单,不必达到对外发布式的质量。
- 找到以前的解决方法非常关键。使用足够的关键字,可以帮助你在需要的时候发现需要的条目。
- 如果通过搜索Web,发现没人曾经遇到同样的问题,也许搜索的方式有问题。
- 要记录发生问题时应用程序、应用框架或平台的特定版本。同样的问题在不同的平台或版本上可能表现得不同。
- 要记录团队做出一个重要决策的原因。否则,在6~9个月之后,想再重新回顾决策过程的时候,这些细节就很难再记得了,很容易发生互相指责的情形。
警告就是错误
将警告视为错误。签入带有警告的代码,就跟签入有错误或者没有通过测试的代码一样,都是极差的做法。签入构建工具中的代码不应该产生任何警告信息。
平衡的艺术
- 虽然这里探讨的主要是编译语言,解释型语言通常也有标志,允许运行时警告。使用相关标志,然后捕获输出,以识别并最终消除警告。
- 由于编译器的bug或是第三方工具或代码的原因,有些警告无法消除。如果确实没有应对之策的话,就不要再浪费更多时间了,但是类似的状况根少发生。
- 应该经常指示编译器:要特别注意别将无法避免的警告作为错误进行提示,这样就不用费力去查看所有的提示,以找到真正的错误和警告。
- 弃用的方法被弃用是有原因的。不要再使用它们了。至少,安排一个迭代来将它们(以及它们引起的警告信息)安全地移除掉。
- 如果将过去开发完成的方法标记为弃用方法,要记录当前用户应该采取何种变通之策,以及被弃用的方法将会在何时一起移除。
对问题各个击破
可以先使用调试器,逐行执行代码,并试图隔离问题。
用原型进行分离:识别复杂问题的第一步,是将它们分离出来。
如果可以隔离出发生问题的模块,也更容易修复发生问题的代码。
最好花一些时间把已关注的代码提取出来,而且创建一个可让其工作的测试环境。
对问题各个击破,这样做有很多好处:
通过将问题与应用其他部分隔离开,可以将已关注点直接放在与问题相关的议题上;可以通过多种改变,来接近问题发生的核心—你不可能针对正在运行的系统来这样做。可以更快地发现问题的根源所在,因为只与所需最小数量的相关代码发生关系。
隔离问题不应该只在交付软件之后才着手。在构建系统原型、调试和测试时,各个击破的战略都可以起到帮助作用。
对问题各个击破。在解决问题时,要将问题域与其周边隔离开,特别是在大型应用中。
平衡的艺术
- 如果将代码从其运行环境中分离后,问题消失不见了,这有助于隔离问题。
- 另一方面,如果将代码从其运行环境中分离后,问题还在,这也有助于隔离问题。
- 以二分查找的方式来定位问题是很有用的。也就是说,将问题空间分为两半,看看哪一半包含问题。再将包含问题的一半进行二分,并不断重复这个过程。在向问题发起攻击之前,先查找你的问题解决日志。
- 在向问题发起攻击之前,先查找你的问题解决日志。
报告所有的异常
都要考虑事物正常状况下是如何运作的。不过更应该想一想,当出现问题—也就是事情没有按计划进行时,会发生什么。
处理或是向上传播所有的异常。不要将它们压制不管,就算是临时这样做也不行。在写代码时要估计到会发生的问题。
平衡的艺术
- 决定由谁来负责处理异常是设计工作的一部分。
- 不是所有的问题都应该抛出异常。
- 报告的异常应该在代码的上下文中有实际意义。在前述的例子中,抛出一个NullPointerException看起来也许不错,不过这就像抛出一个null对象一样,起不到任何帮助作用。
- 如果代码中会记录运行时调试日志,当捕获或是抛出异常时,都要记录日志信息;这样做对以后的跟踪工作很有帮助。
- 检查异常处理起来很麻烦。没人愿意调用抛出31种不同检查异常的方法。这是设计上的问题:要把它解决掉,而不是随便打个补丁就算了。
- 要传播不能处理的异常。
提供有用的错误信息
程序缺陷。
环境问题。如果提供足够详细的信息,系统管理员应该可以解决这些问题。
用户错误。程序员与系统管理员不必担心这些问题。在告知是哪里操作的问题后,用户可以重新来过。
切身感受
错误信息有助于问题的解决。
第8章:敏捷协作
首先要做的是定期安排会面时间。
架构师必须写代码。
实行代码集体所有制。
成为指导者,允许大家自己想办法。
准备好后再共享代码。
做代码复查。
及时通报进展与问题。
定期安排会面时间
要保证会议议题不会发散,每个人都应该只回答下述三个问题:
- 昨天有什么收获?
- 今天计划要做哪些工作?
- 面临着哪些障碍?
一般来说,在大家到公司之后的半个小时到一个小时之内举行,是个不错的选择。
只有团队成员 — 开发人员、产品所有者和协调者可以发言
每日立会有诸多好处。
- 让大家尽快投入到一天的工作中来。
- 如果某个开发人员在某一点上有问题,他可以趁此机会将问题公开,并积极寻求帮助。
- 帮助团队带头人或管理层了解哪些领域需要更多的帮助,并重新分配人手。
- 让团队成员知道项目其他部分的进展情况。
- 帮助团队识别是否在某些东西上有重复劳动而耗费了精力,或者是不是某个问题有人已有现成的解决方案。
- 通过促进代码和思路的共享,来提升开发速度。
- 鼓励向前的动力:看到别人报告的进度都在前进,会对彼此形成激励。
使用立会。立会可以让团队达成共识。保证会议短小精焊不跑题。
平衡的艺术
- 会议会占用开发时间,所以要尽量保证投入的时间有较大的产出。立会的时间最长不能超出30分钟,10~15分钟比较理想。
- 如果要使用需提前预定的会议室,就把预定的时间设定为一个小时吧。这样就有机会在15分钟的立会结束后,马上召开更小规模的会议。
- 虽然大多数团队需要每天都碰头,但对于小型团队来说,这样做可能有点过头了。不妨两天举行一次,或者一周两次,这对小团队来说足够了。
- 要注意报告的细节。在会议中要给出具体的进度,但是不要陷入细节之中。例如,“我在开发登录页面”就不够详细。“登录页面目前接受guest/guest作为登录用户名和密码,我明天会连接数据库来做登录验证”,这样的详细程度才行。
- 迅速地开始可以保证会议短小。不要浪费时间等着会议开始。
- 如果觉得立会是在浪费时间,那可能是大家还没有形成真正的团队意识。这并不是坏事,有利于针对问题进行改进。
架构师必须写代码
负责设计和指导。
作为设计人员,如果不能理解系统的具体细节,就不可能做出有效的设计。只通过一些高度概括的、粗略的设计图无法很好地理解系统。
指导开发团队,提升他们的水平,以解决更为复杂的问题。架构师最重要的任务是:通过找到移除软件设计不可逆性的方式,从而去除所谓架构的概念。增强可逆性是注重实效的软件实现方式的关键构成部分。
实行代码集体所有制
不要无意间丧失了团队的专家技能。如果某个开发人员在某个领域中极其精通,不妨让他作为这方面的驻留专家,而且系统的其他部分代码也对他开放,这样对团队和项目都很有帮助。
要强调代码的集体所有制。让开发人员轮换完成系统不同领域中不同模块的不同任务。
平衡的艺术
- 不要无意间丧失了团队的专家技能。如果某个开发人员在某个领域中极其精通,不妨让他作为这方面的驻留专家,而且系统的其他部分代码也对他开放,这样对团队和项目都很有帮助。
- 在大型项目中,如果每个人都可以随意改变任何代码,一定会把项目弄得一团糟。代码集体所有制并不意味着可以随心所欲、到处破坏。
- 开发人员不必了解项目每一部分的每个细节,但是也不能因为要处理某个模块的代码而感到惊恐。
- 有些场合是不能采用代码集体所有制的。也许代码需要某些特定的知识、对特定问题域的了解,比如一个高难度的实时控制系统。这些时候,人多了反而容易误事。
- 任何人都可能遭遇到诸如车祸等突发的灾难事故,或者有可能被竞争对手雇佣。如果不向整个团队分享知识,反而增加了丧失知识的风险。
成为指导者
成为指导者。分享自己的知识很有趣 - 付出的同时便有收获。还可以激励别人获得更好的成果,而且提升了整个团队的实力。
平衡的艺术
- 如果一直在就同一个主题向不同的人反复阐述,不妨记录笔记,此后就此主题写一篇文章,甚至是一本书。
- 成为指导者是向团队进行投资的一种极佳的方式。
- 结对编程是一种进行高效指导的、很自然的环境。
- 如果总是被一些懒于自己寻找答案的人打扰。
- 为团队成员在寻求帮助之前陷入某个问题的时间设定一个时限,一个小时应该是不错的选择。
允许大家自己想办法
告诉团队成员解决问题的方法,也要让他们知道如何解决问题的思路,这也是成为指导者的一部分。
这样做有下面几点好处。
- 你在帮助他们学会如何解决问题。
- 除了答案之外,他们可以学到更多东西。
- 他们不会再就类似的问题反复问你。
- 这样做,可以帮助他们在你不能回答问题时自己想办法。
- 他们可能想出你没有考虑到的解决方法或者主意。这是最有趣的 - 你也可以学到新东西。
作为指导者,应该鼓励、引领大家思考如何解决问题。
准备好后再共享代码
通常情况下,提交的文件应该与一个特定的任务或是一个bug的解决相关。而且应该是同时提交相关的文件,并注有日志信息,将来也能够知道修改了哪些地方,以及为什么要做修改。一旦需要对变更采取回滚操作,这种“原子”提交也是有帮助的。
要保证在提交代码之前,所有的单元测试都是可以通过的。使用持续集成是保证源代码控制系统中代码没有问题的一种良好方式。
代码不执行提交操作的其他安全选择
- 使用远程访问。
- 随身携带。
- 使用带有底座扩展的笔记本电脑。
- 使用源代码控制系统的特性。
准备好后再共享代码。绝不要提交尚未完成的代码。故意签入编译未通过或是没有通过单元测试的代码,对项目来说,应被视作玩忽职守的犯罪行为。
平衡的艺术
- 有些人希望代码在提交之前可以进行复查操作。只要不会过久拖延提交代码的时间就没有问题。如果流程的某个部分产生了拖延,那就修正流程吧。
- 仍然应该频繁提交代码。不能用“代码尚未完成”作为避免提交代码的借口。
做代码复查
代码复查或许是找到并解决问题的最佳方式。然而,有时很难说服管理层和开发人员使用它来完成开发工作。
那该如何进行代码复查呢?可以从下面这些不同的基本方式中进行选择。
- 通宵复查。
- 捡拾游戏。当某些代码编写完成、通过编译、完成测试,并已经准备签入时,其他开发人员就可以“捡拾”起这些代码开始复查。
- 结对编程。进行持续的代码复查活动,也就不必安排单独的特定复查时间了。
一个可供启动的最基本的检查列表:
- 代码能否被读懂和理解?是否有任何明显的错误?
- 代码是否会对应用的其他部分产生不良影响?是否存在重复的代码(在复查的这部分代码中,或是在系统的其他部分代码)?
- 是否存在可以改进或重构的部分?
Similarity Analyzer或Jester这样的代码分析工具。如果这些工具产生的静态分析结果对项目有帮助,就把它们集成到持续构建中去吧。
平衡的艺术
- 不进行思考、类似于橡皮图章一样的代码复查没有任何价值。
- 代码复查需要积极评估代码的设计和清晰程度,而不只是考量变量名和代码格式是否符合组织的标准。
- 同样的功能,不同开发人员的代码实现可能不同。差异并不意味着不好。除非你可以让某段代码明确变得更好,否则不要随意批评别人的代码。
- 如果不及时跟进讨论中给出的建议,代码复查是没有实际价值的。可以安排跟进会议,或者使用代码标记系统,来标识需要完成的工作,跟踪已经处理完的部分。
- 要确保代码复查参与人员得到每次复查活动的反馈。作为结果,要让每个人知道复查完成后所采取的行动。
及时通报进展与问题
接受一个任务,也就意味着做出了要准时交付的承诺。
由于技术上的难题,看起来不能准时完成了。如果这时积极通知其他相关各方,就等于给机会让他们提前找出解决问题的方案。也许他们可以向另外的开发人员寻求帮助,也许他们可以将工作重新分配给更加熟悉相关技术的人,也许他们可以提供更多需要的资源,或者调整目前这个迭代中要完成的工作范围。客户会愿意将这个任务用其他同等重要的任务进行交换的。
及时通报进展与问题,有情况发生时,就不会让别人感到突然,而且他们也很愿意了解目前的进展状况。他们会知道何时应提供帮助,而且你也获得了他们的信任。
平衡的艺术
- 每日立会,可以让每个人都能明确了解最新的进展和形势。
- 在展示进度状况时,要照顾到受众已关注的细节程度。举例来说,CEO和企业主是不会关心抽象基类设计的具体细节的。
- 别花费太多时间在进展与问题通报上面,还是应该保证开发任务的顺利完成。
- 经常抬头看看四周,而不是只埋头于自己的工作
