18、代码开发与测试相关探讨及环境搭建指南

代码开发与测试相关探讨及环境搭建指南

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 则更适合大型项目和专业开发。我们应该根据自己的需求和项目特点,选择合适的开发方式和工具。同时,要不断实践和探索,找到最适合自己的开发模式。

总之,代码开发是一个不断学习和进步的过程,我们要保持开放的心态,不断尝试新的技术和方法,提高自己的开发能力。

先展示下效果 https://pan.quark.cn/s/a4b39357ea24 遗传算法 - 简书 遗传算法的理论是根据达尔文进化论而设计出来的算法: 人类是朝着好的方向(最优解)进化,进化过程中,会自动选择优良基因,淘汰劣等基因。 遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。 进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择、杂交等。 搜索算法的共同特征为: 首先组成一组候选解 依据某些适应性条件测算这些候选解的适应度 根据适应度保留某些候选解,放弃其他候选解 对保留的候选解进行某些操作,生成新的候选解 遗传算法流程 遗传算法的一般步骤 my_fitness函数 评估每条染色体所对应个体的适应度 升序排列适应度评估值,选出 前 parent_number 个 个体作为 待选 parent 种群(适应度函数的值越小越好) 从 待选 parent 种群 中随机选择 2 个个体作为父方和母方。 抽取父母双方的染色体,进行交叉,产生 2 个子代。 (交叉概率) 对子代(parent + 生成的 child)的染色体进行变异。 (变异概率) 重复3,4,5步骤,直到新种群(parentnumber + childnumber)的产生。 循环以上步骤直至找到满意的解。 名词解释 交叉概率:两个个体进行交配的概率。 例如,交配概率为0.8,则80%的“夫妻”会生育后代。 变异概率:所有的基因中发生变异的占总体的比例。 GA函数 适应度函数 适应度函数由解决的问题决定。 举一个平方和的例子。 简单的平方和问题 求函数的最小值,其中每个变量的取值区间都是 [-1, ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值