下面的内容是我在作为一名程序员入职之前阅读的由Gergely Orosz写的The Software Engineer’s Guidebook。我将将阅读时得到的重要的信息总结成中文以供大家分享。
作为一位称职的软件开发人员,你会希望编写具有正确抽象层次的代码,能够可靠地运行,考虑到潜在的错误情况。这当然也包括代码的可读性,我们在这一节之前已经提到过这点。
在结构化代码时,你会创建抽象的类。这些类将实现细节从代码的其他部分抽象出来。例如,你可能会遇到一个名为“PaymentsIntent”的类,它在一个文件中实现以下功能:
这个类并不做很多事情,但你可能会决定将第2个功能——将JSON转换为PaymentsResponse对象——抽象成自己的类。
接着,PaymentsIntent将这样做:
为什么我们要抽象出解析付款响应JSON的过程呢?有几个原因:
在《软件设计哲学》一书中,作者约翰·奥斯特豪特描述了信息隐藏的好处:
“信息隐藏以两种方式减少复杂性。首先,它简化了模块[或类]的接口。接口反映了模块功能的更简单、更抽象的视角,并隐藏了细节;这降低了使用该模块的开发人员的认知负担。其次,信息隐藏使系统更容易演化。如果一部分信息被隐藏了,那么在包含该信息的模块之外就不会有该信息的依赖,因此与该信息相关的设计变更只会影响一个模块。”
以合适的抽象层次构建系统是一个你通过实践不断提升的过程。毕竟,你不希望将系统拆分成太多小块,因为过多数量的微小类会增加不必要的认知负担。
据我个人经验,许多故障都可以追溯到代码的错误处理不正确。作为软件开发者,编写代码时需要考虑可能出现的问题,并在错误处理上投入足够的时间和精力。拥有一套一致的错误处理策略很重要。当遇到可能是错误的情况时,你会怎么做?会抛出异常、记录错误、两者兼而或其他方式?你应该能够解释自己是如何处理错误的;最好与团队中的其他人保持一致。记录错误是一个明智的策略,你应该设定记录的策略。其中提供了一个在第五部分:《软件工程》中给出的策略。当怀疑时,使用 防御性编程 。这意味着其他部分代码的输入是不可靠且可能恶意的。在这种思维模式下,你会开始质疑然后验证系统、类甚至函数的输入。以下是一些防御性编程的方法:
有时候你可能不需要使用防御性编程。例如,当使用一个类时,其中所有的输入都经过设计验证。而且,当在强类型语言或者函数声明可能抛出的异常时,你可能不太需要担心防御性编程。语言对错误处理有更多约束时,编译器可以更多地警告不正确的假设。
一个令人惊讶的常见问题是API响应与成功或失败代码的映射,以及如何处理“未知”情况。例如,一个用于发起支付请求的支付API可以返回“okay”、“资金不足”或“API暂时不可用”等响应。你需要在代码中将这些响应映射为“成功”或“失败”。你知道支付API可能会后续添加或删除响应,因此你希望构建一个足够健壮的系统,以处理API可能引入一个名为“需要用户操作”的新代码情况。以下是两种常见的做法: