(1)问题
在实际开发中,高质量编程大多数情况下难以实现。
一方面,大部分年轻的程序员开发经验少(初级程序员),写程序仅仅是满足设计文档上的功能性要求,离高质量程序相差甚远。
另一方面,程序员离最终用户距离较远,对程序上线后出现的很多问题并没有切身体会,无法编写出一些 看似稀奇古怪 却又合乎常理的需求。
(2)实际编码中的差异
【差异:】 对于同一个功能需求,高手 与 菜鸟 的差异将非常明显: 高手 代码量 会明显低于 菜鸟 的代码量。 高手 编码效率 会明显高于 菜鸟 的效率。 高手 代码性能 明显高于 菜鸟 的性能。 高手 代码可阅读性、安全性、可靠性 明显高于 菜鸟的代码。 注: 高质量编程 是每个优秀的程序员应该具备的。 每个程序员都经历过 菜鸟 的阶段,有的很快能够蜕变,而有的却一直无法改变, 那么如何令自己具备这种能力呢? 最重要的还是 培养自己的意识(学习优秀代码的思想,总结自己代码的不足)。 正所谓:学而不思则罔,思而不学则殆。 【程序员的变化:】 菜鸟: 能力:能够编写基本符合功能需求的程序。 态度:追求交差。 老手: 能力:能够长期稳定编写出高质量的程序。 态度:追求卓越。 高手: 能力:能够长期稳定编写出高质量、高难度的程序。 态度:追求完美。
(1)高质量编程具体是什么?
【高质量编程:】 可以从三个方面(编程风格、程序运行、后期拓展)来 描述 高质量编程。 编程风格: 整齐、简洁、易读。 程序运行: 正确运行、可靠、安全、高效、兼容 后期拓展: 可移植、可复用、可维护、可拓展。
(2)编程风格
【整齐:】 统一缩进: 通过缩进可以明确看出代码的层次结构。 合理分段: 可使用空行分隔 代码逻辑,将逻辑不紧密的代码隔开。 【简洁:】 减少冗余: 对于重复的代码,可以将其抽取成一个共通方法进行调用。 避免重复造轮子: 熟悉常用的库函数 以及 项目中自定义的 共同方法,避免重复编码(减少代码冗余)。 删除无用代码: 对于无用代码可以直接删除,无需在源文件中保留无用代码。 git、svn 等版本控制系统中会有历史提交记录,通过历史记录可以很方便的查看修改情况。 精简代码: 在保证解决需求的情况下,尽量优化代码,以较少的代码解决实际需求。 【易读:】 合理注释: 编写代码时添加上适当注释,方便 自己 或者 其他人 理解代码的含义。 合理命名: 根据命名规约,正确拼写。 合理规划项目结构: 使用合理的目录层次划分代码、文件,不同目录应具备不同的意义。 合理规划代码内部结构: 代码内部适当换行,避免 函数、代码 在一行上过长。 统一代码编写风格(比如:规定变量声明必须在函数或者方法第一行,避免在任意位置声明变量)。
(3)程序运行
【正确运行:】 满足基本需求: 能够满足基本设计需求。 满足默认规则: 满足有些属于软件常规操作但没有在设计中描述的需求。比如:TAB 键在页面上的顺序。 【可靠:】 持续稳定运行: 保证一些异常出现后,程序仍能正常运行(可以处理异常),不会崩溃。 并发安全: 保证程序并发执行时,系统内部执行逻辑不会出错。 无资源泄露: 持续工作时,不会出现内存溢出、内存泄露等不断消耗系统资源的问题。 【安全:】 完善日志处理: 对于核心操作,需要进行日志记录,确保修复 Bug 时可以快速定位错误位置。 保护敏感信息: 对于 用户密码 等敏感信息进行加密处理,不以明文方式进行保存。 防范常见攻击: SQL 注入。 XSS 攻击(指的是 Cross Site Scripting,即 跨站脚本)。 CSRF 攻击(指的是 Cross Site Request Forgery,即 跨站请求伪造)。 【高效:】 循环代替递归: 递归资源消耗较大,尽量改为 循环实现。 精简循环代码: 循环无关代码 提取到 循环外,避免重复执行。 选取合适算法、数据结构: 根据数据特点,选取合适的数据结构以及算法 进行编码。 根据实际需求,尽量在 时间效率 以及 空间效率 上取得平衡。 发现并改善性能瓶颈: 比如采用 缓存机制 提高查询效率。 【兼容:】 确认程序运行环境: 使用兼容的 库函数 以及 API,保证程序在 各平台上兼容。 使用可兼容的组件: 为了保证可移植性,在技术选型时选择 具备良好兼容性的 组件、库函数 等。
(4)后期拓展
【可移植】 移植到不同的平台: 使用兼容性良好的组件、库函数等,通过较少修改保证程序正常运行。 资源独立: 进行国际化处理,保证 语言容易被提取、翻译、转换。 【可复用】 接口通用: 程序接口经过良好设计,具备通用性,不经修改即可用于其他系统。 【可维护】 完善日志机制: 根据日志信息定位错误地方,方便排查错误。 【可拓展】 良好程序结构: 定义良好程序结构,通过修改配置 或者 简单修改 即可应用 新添加的功能。
(5)如何实现高质量编程
【如何实现?】 编码前 需要仔细阅读 编码规约,保证编码风格一致(多人开发,风格难免有差异)。 编码时 需要不断自测,不能盲目自信(老子代码天下无敌 是不可取的)。 编码完成后 先自己思考一下能否继续优化,进一步可以请别人 来指点一下是否有更好的代码。 注: 要下意识的学习优秀代码的思想,总结自己代码的不足。
(1)举个例子
【举个例子:(仅供娱乐、参考)】 现有 A、B 两个人,A 向 B 提问:你的梦想是什么? A 回答说:金钱和女人。 ... B 愣了一会儿说:这个答案有点肤浅了,请你重新组织语言,再次回答。 ... A 思考了一会后,回答说:事业和爱情。 注: A 的两个回答,尽管表达的都是同一个意思,但是第二种回答 貌似比 第一种回答 更优雅一点。 这就是重构。
(2)代码重构
【代码的重构:】 在不改变代码原有功能的基础上,调整代码的内部结构,提高代码的可理解性,降低维护成本。 注: 代码重构后,基本功能肯定是与 原来的代码 一样的, 但是重构后,代码肯定优于 原来的代码,否则重构没有任何意义。 所以重构 是有一定的 难度的,需谨慎(开发一时爽、重构火葬场)。 【为什么进行代码的重构:】 不重构代码可能遇到的问题: 随着项目迭代、添加新功能,不同的开发人员进行 一系列 猛如虎的操作后,项目代码难免会臃肿、复杂、逻辑不清。 而这又导致项目难以理解、维护起来麻烦,增加了开发难度。 而进行重构后: 可以改进项目设计,给项目一个起死回生的机会(整理代码,使代码整体逻辑清晰)。 代码逻辑清晰后,便于阅读、理解代码,从而提高编程效率(排查 Bug 的效率也提高了)。 【重构的流程:】 Step1: 读懂代码,知道代码的功能。 Step2: 重构代码,保证原有功能。 Step3: 进行单元测试,保证代码原有功能不能消失。
(1)什么时候需要重构?
对于首次开发的项目,经常会遇到重复性代码操作,此时就需要考虑是否进行重构,复用一些代码。
对于维护、迭代的项目,添加一个功能困难时,就得考虑是否需要进行重构,保证原有功能的基础上拓展新功能。
Debug 排错时,若不能一眼发现错误所在位置,就得考虑是否需要重构,使代码逻辑清晰。
代码审查时,若发现可以优化的代码,就得考虑是否需要重构,减少 BUG、提高执行效率。
(2)什么时候不能重构?
代码混乱、设计错误时,此时重构 将会带来很多问题,慎重重构。
代码发布期临近,重构会消耗大量时间时,慎重重构。
(3)需要重构代码的特征
【特征:】 重构很重要,那么如何重构? 当发现代码不对劲时,就说明需要重构了。 注: 此处不对劲指的是 代码可以被优化。 即需要重构的代码 具有某种可以被优化的特征。 比如: 重复代码。 类过大。 函数过长、函数参数列过长等。 【重复代码:】 重复代码指的是 在多个地方看到相同的代码段。 比如: 同一个类中存在两个以上相同代码段。 重构: 将代码抽取成一个共通方法,并调用。 【函数过长:】 函数过长指的是 很多功能均写在一个函数中,使函数变得复杂。 重构: 将函数中复杂的过程分解成若干个小函数。 注: 函数命名需要见名知意。最好做到 不阅读函数内部代码,仅通过函数名就能了解函数的功能。 函数功能最好单一,太复杂了可将其进行拆分。
......高质量编程当然不是这么简单说说就了事了。
吾日三省吾身,想要代码技术过硬,多学、多思考、多总结 是必备的。