代码开发与测试相关探讨及环境搭建指南
1. Lambda 表达式与代码实现
在代码实现中,有这样一段代码:
total = functools.reduce(operator.add,
map(lambda m: bank.convert(m, currency), self.moneys), 0)
Lambda 表达式有其局限性,由于其应用方式,我们无法编写条件代码。不过,如果我们通过加法运算符,将转换后的货币对象和多次调用
Bank.convert
方法返回的任何缺失汇率累加起来,这是可行的,但需要对
Bank.convert
的签名进行更改,并覆盖
__add__
方法,使其能够处理
(Money, string)
元组。是否建议这样做并没有绝对的对错答案。软件的阅读频率远高于编写频率,我们应该先编写代码,再形成强烈的观点。即便编写完成后,也很难确定哪种风格(使用或不使用 lambda)“更好”,因为即使经过复杂度、内聚性和耦合性等可衡量指标的筛选,主观性依然存在。
2. 测试驱动开发(TDD)是否已死
经常能看到宣称测试驱动开发(TDD)已死的文章,技术会议上也有人宣称 TDD 不仅作为一种仪式,而且作为一种实践都存在危害,希望它尽快消亡。然而,认为 TDD 已死的报告是不成熟且夸大的。
TDD 是一种设计和构建代码的技术,其目标是促进代码的简洁性并增强对代码的信心。在 TDD 过程中编写的单元测试只是实现这一目标的手段,而非目的本身。从最终用户的需求来看,只有生产代码会被打包和部署,而不是测试代码。
可以将单元测试类比为建筑施工中的脚手架。有价值的是建筑本身,脚手架只是在施工期间用于搭建和支撑建筑。不同的是,建筑完工后脚手架通常会被拆除,因为预计外部架构不会有变化,但代码很少能有这样的保证,任何正在使用的软件都在不断变化。因此,保留单元测试、通过 CI/CD 服务器定期执行并随着生产代码的演进而改进它们是必不可少的。
Kent Beck 在 Stack Overflow 上的回答明确指出:“我靠能运行的代码赚钱,而不是靠测试,所以我的理念是尽可能少地进行测试,以达到一定的信心水平(我怀疑这个信心水平比行业标准要高,但也可能是自负)。如果我通常不会犯某种错误(比如在构造函数中设置错误的变量),我就不会针对它进行测试。我倾向于理解测试错误,所以在处理具有复杂条件的逻辑时会格外小心。在团队编码时,我会调整策略,仔细测试我们集体容易出错的代码。”
不同的人会基于这一理念制定不同的测试策略,鉴于目前对测试如何更好地融入编码内循环的理解还不成熟,这似乎是合理的。未来十到二十年,可能会有更通用的理论来指导哪些测试该写、哪些不该写以及如何区分。在此之前,实验是必要的。
3. 开发环境搭建
设置开发环境是编写代码的前提条件,如今设置可靠的开发环境比以往更容易,而且会越来越容易。
3.1 在线 REPL
REPL 即“Read - Eval - Print Loop”,是一个交互式的顶级 shell,允许直接轻松地编写短程序。在 REPL 中编写的代码会被读取、评估(根据语言进行解析、编译和/或解释,然后执行),最后输出结果,整个过程循环进行,可随时编辑和运行程序。
在线 REPL 有很多优点,如免费使用、只需有网络浏览器和稳定网络连接的计算机,其交互性和快速详细的反馈使其成为学习新编程语言的理想环境。但使用在线 REPL 编写大量代码也有一些挑战:
-
代码组织困难
:可能难以按自己的意愿组织源文件到文件夹中(如 LeetCode 免费版),也可能难以按需求命名文件(如在 Repl.it 中编写 Go 代码时,无法删除或重命名
main.go
文件)。
-
导入外部包困难
:例如 LeetCode 允许导入 Go 标准库中的包,但导入外部包并非易事。
-
代码量限制
:在线 REPL(尤其是免费版)通常会限制可编写和在线存储的代码量。
-
代码隐私受限
:使用在线 REPL 编写的代码存储在其服务器上(云端),尤其是免费版,往往需要将代码仓库公开。随着程序规模增大,尤其是编写专有代码时,可能希望控制对代码仓库的访问,而在线 REPL 可能使这更难实现。
-
代码丢失风险
:由于浏览器崩溃等原因,存在代码丢失的风险。
以下是一些可以帮助你以最少的先决条件开始的在线 REPL:
| 在线 REPL 名称 | 特点 | 使用说明 |
| ---- | ---- | ---- |
| Repl.it | 支持多种语言,包括常用的三种语言,免费版功能丰富 | 运行 Go 代码:不能删除
main.go
文件,留空即可;按 Go 命名约定创建测试文件,如
money_test.go
;运行测试时,切换到右侧的 Shell 标签,输入
go test -v <name_of_test_file>.go
并回车。运行 JavaScript 代码:切换到右侧的 Shell 标签,输入
node <name_of_test_file>.js
并回车。运行 Python 代码:切换到右侧的 Shell 标签,输入
python <name_of_test_file>.py
并回车。 |
| LeetCode | 鼓励开发者通过编码竞赛、挑战和讨论进行社交互动,“Playground” 功能支持多种语言 | 免费版限制 Playground 数量为 10 个,付费订阅可移除限制并提供调试和自动完成等功能。Go 语言导入标准库外的包或通过
go test
运行测试有困难,Python 使用
unittest
包运行测试不明显。 |
| CoderPad | 适合代码的实时协作,如结对或团队编程,常用于技术面试 | 支持多种语言,但导入 Go 标准库外的包并非易事。 |
| Go Playground | 专门为 Go 编程语言设计的 REPL | 可以创建代码片段的永久链接,便于分享代码,完全免费。可以编写单元测试和生产代码并直接运行测试,还能组织代码到多个文件中,可像在 IDE 中一样从公共仓库(如 GitHub.com)导入包。 |
graph LR
A[开始] --> B[选择在线 REPL]
B --> C{选择语言}
C -->|Go| D[按对应说明运行 Go 代码]
C -->|JavaScript| E[按对应说明运行 JavaScript 代码]
C -->|Python| F[按对应说明运行 Python 代码]
D --> G[结束]
E --> G
F --> G
4. 集成开发环境(IDEs)
在线 REPL 适合入门,但要进行大量的严肃编码,需要在计算机上设置合适的开发环境。IDEs 是设置开发环境的可靠方式,以下是一些选择:
-
Visual Studio Code
:开发示例代码时使用的 IDE,有插件可同时配置多种语言(包括常用的三种语言),可在 Windows、macOS 和 Unix 操作系统上使用。微软以 MIT 许可证将其作为开源产品发布,开发者编写并公开分享的扩展数量众多,是开发者中最受欢迎的 IDE 之一。
-
IntelliJ IDEA
:由捷克软件公司 JetBrains 开发的一系列 IDE 之一。Ultimate 版(需购买许可证)支持 Go、JavaScript 和 Python(原生或通过可安装的插件)。免费的 Community 版也支持多种语言,但不支持 Go 或 JavaScript。JetBrains 还提供支持 Python 的社区版 PyCharm,但截至 2021 年年中,Go 开发只有商业版的 GoLand。
建议先从一个 IDE 开始,熟悉后再尝试其他的。即使使用 IDE,也需要为使用的每种语言安装运行时环境(RTE),然后配置 IDE 以便轻松使用这些语言。
代码开发与测试相关探讨及环境搭建指南(续)
5. 在线 REPL 与 IDE 的对比及选择建议
在线 REPL 和 IDE 各有其优势和适用场景,下面通过表格进行对比:
| 对比项 | 在线 REPL | IDE |
| ---- | ---- | ---- |
| 入门难度 | 低,无需安装复杂环境,有浏览器和网络即可开始 | 相对较高,需要安装运行时环境和 IDE 本身,并进行配置 |
| 代码组织 | 困难,可能无法按意愿组织文件和命名 | 方便,可以轻松创建项目结构,管理文件 |
| 功能完整性 | 有限,部分功能缺失,如导入外部包困难 | 强大,提供丰富的功能,如调试、代码自动完成等 |
| 协作性 | 部分支持实时协作,如 CoderPad | 可通过版本控制系统实现协作 |
| 代码隐私 | 免费版通常难以保证代码隐私 | 可自行控制代码仓库的访问权限 |
根据上述对比,给出以下选择建议:
-
初学者
:如果是刚开始学习编程,建议先使用在线 REPL 快速上手,熟悉基本语法和代码运行方式。例如,使用 Repl.it 尝试不同语言的代码示例。
-
小型项目或快速验证
:对于小型项目或需要快速验证想法的场景,在线 REPL 可以满足需求。比如,在 LeetCode 的 Playground 上练习算法题。
-
大型项目和专业开发
:如果要进行大型项目的开发,或者需要专业的开发功能,如调试、代码重构等,建议使用 IDE。例如,使用 Visual Studio Code 进行多语言项目的开发。
graph LR
A[选择开发方式] --> B{项目规模和需求}
B -->|初学者或小型验证| C[在线 REPL]
B -->|大型项目或专业开发| D[IDE]
C --> E[选择合适的在线 REPL 并使用]
D --> F[选择合适的 IDE 并配置]
6. 测试驱动开发的实践要点
测试驱动开发虽然有其价值,但在实践中也需要注意一些要点:
-
明确测试目的
:测试是为了确保代码的正确性和可靠性,而不是为了测试而测试。根据 Kent Beck 的观点,要根据自己或团队容易犯的错误来确定测试的范围。
-
合理安排测试时间
:在项目开发过程中,要合理安排测试的时间,避免过度测试或测试不足。可以采用迭代开发的方式,在每个迭代中进行测试和代码优化。
-
持续改进测试用例
:随着代码的不断演进,测试用例也需要不断改进。要及时更新测试用例,确保其能够覆盖代码的各种情况。
以下是一个简单的测试驱动开发流程:
1.
编写测试用例
:根据需求编写一个简单的测试用例,此时测试用例应该是失败的。
2.
编写实现代码
:编写足够的代码使测试用例通过。
3.
重构代码
:在测试用例通过后,对代码进行重构,提高代码的质量和可维护性。
4.
重复上述步骤
:不断重复上述步骤,直到完成整个项目的开发。
7. 总结
在代码开发过程中,我们面临着多种选择,包括代码实现方式、测试策略和开发环境的选择。Lambda 表达式在某些场景下有其局限性,但在合适的场景下也能发挥作用。测试驱动开发虽然存在争议,但仍然是一种有效的开发方法,可以帮助我们编写更简洁、可靠的代码。
在开发环境方面,在线 REPL 适合初学者和快速验证,而 IDE 则更适合大型项目和专业开发。我们应该根据自己的需求和项目特点,选择合适的开发方式和工具。同时,要不断实践和探索,找到最适合自己的开发模式。
总之,代码开发是一个不断学习和进步的过程,我们要保持开放的心态,不断尝试新的技术和方法,提高自己的开发能力。
超级会员免费看
1184

被折叠的 条评论
为什么被折叠?



