我从高级软件工程师身上学到的那些经验与教训
代码审查是学习中的重要组成部分。审查的过程,就是从编写代码、到了解如何更好地编写代码的反馈循环。我们自己的编码思路,跟其他人的编码思路有何不同?我在每一次代码审查时都会问自己:“他们为什么要这样做?”如果实在找不到合理的答案,我就会跟他们当面聊聊。在第一个月的过渡期结束之后,我开始疯狂地从同事的代码当中查找错误(当然,他们也不会放过我)。真的很疯狂,这也让评审工作变成一项有趣的调剂——或者说像是一种游戏,能够改善我们编码水平的小游戏。 我的心得:在理解代码作用之前,不要轻下断言。 测 试我特别喜欢测试这项工作,事实上如果不加测试,我根本就不愿意直接在代码库中编写代码。 如果您的整个应用程序只需要执行一项任务(我在学校里的实验性项目就是这样),那么手动测试即可解决问题,我以前也一直习惯于这种方式。但是,当应用程序当中包含上百种功能,情况又会如何?我不想拿出大量时间挨个测试,而且我也知道自己肯定会忘掉某些需要测试的部分。这绝对会是一场噩梦。 这时候,我们就该请出测试自动化方案了。 在我看来,测试跟记录文档差不多。测试的过程,就是记录我对于代码的假设是否正确的过程。测试会告诉我,我自己(或者是当初写下代码的开发)当时希望代码如何运行,以及认为哪里有可能出问题。 因此,现在再编写测试时,我会牢记以下两点:
第一条相信很多朋友都能理解,毕竟在大多数情况下,我们需要测试的其实是行为,而非实现。但我个人总会忽略第 2 条,即 bug 可能出现在哪里。 因此,每当我发现 bug 时,我都会确保代码修复程序在相应的测试(也就是回归测试)当中记录下其它有可能引发错误的方式。 当然,编写这类测试本身并不能提供代码质量,只有真正编写代码才会真正影响质量。不过我从阅读测试结果当中获得的见解,确实能够帮助自己编写出更好的代码。 这就是测试的宏观意义。 除此之外,测试还肩负着另一项重要使命:确定部署环境。 大家可能拥有完美的单元测试,但如果没有进行系统测试,就有可能发生以下情况: 锁到底是好的,还是坏的? 对于经过良好测试的代码也是如此:如果您的机器上没有其需要的库,代码就会崩溃。
如果测试与部署机器间的环境不匹配,那一般都会出点问题。而这,正是部署环境的意义所在。我们在自己的机器上使用 docker 构建本地开发环境。 在这套开发环境当中安装有一组库(及开发工具),我们则以此为基础安装已经编写完成的代码。所有与其它依赖系统相关的测试,都在这里完成。 然后是 beta 测试 / 分段环境,其与生产环境完全一致。 最后是生产环境,也就是负责运行代码并为实际客户提供服务的机器。 我们的基本思路是努力捕捉那些不会在单元与系统测试中出现的错误。例如,请求与响应系统之间的 API 不匹配问题。 我猜个人项目或者小型企业的情况可能有所不同,毕竟并不是每个人都有资源来设置自己的一套基础设施。但是,如果大家愿意使用 AWS 以及 Azure 等云服务,这里提到的方法仍然适合各位。大家可以为开发以及生产环境设置单独的集群。AWS ECS 利用 docker 镜像进行部署,因此各环境之间相对一致。比较棘手的部分,就是如果与其它 AWS 服务顺利整合。例如,我们是否从正确的环境中调用了正确的端点? 大家甚至可以更进一步:为其它 AWS 服务下载备用容器镜像,并利用 docker-compose 命令设置完整的本地环境。这样能够加速反馈循环。 如此一来,当我的附带项目启动并开始运行之后,我就能积累到更多经验心得。 消除风险所谓消除风险,就是在部署代码的过程中尽可能降低风险水平的一种艺术。 那么,我们可以采取哪些措施来消除灾难性后果? 如果我们希望推出的一项突破性的变更,那么一旦出现问题,如果确保业务尽可能不受严重影响? “我们不需要对所有的新变化进行全系统部署!”哦,是吗……抱歉,我没想到。 设 计很多朋友可能会问,我为什么要把设计放在编写代码与完成测试之后?好吧,设计在实际流程中可能比较靠前,但如果没有在当前环境中进行编码与测试,我个人很难设计出一套能够与特定环境完美适配的系统。在设计系统时,我们需要考虑很多问题,包括: 资源使用量是多少? 存在多少用户?预计用户会以怎样的速度增长?(这将直接决定未来存在多少数据库行) 未来可能出现的陷阱是什么? 我需要把这些转化成一份名为“要求汇总”的清单。目前我还没有积累到充分的相关经验,根据计划,明年我的工作内容就是着力解决这方面问题。 这个过程有点违背敏捷原则——在开始实施之前,我们能够做出多少设计判断?这是个权衡问题,我们需要选择在怎样的时间点上做什么。我们什么时候该深入剖析,又该在什么时候退后一步进行规划? (编辑:厦门网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |