跳转至

编程智慧-编程鬼才的经验和思考

1. 手头的代码

1.1 资源管理

Q: 对于一个特定的任务,使用多少内存是合适的?

A: 软件工程是关于权衡的研究。针对不同的设备,使用不同的策略。

1.2 大内存

Q: 自己管理内存还是垃圾回收器?

A: 垃圾回收之前,会忘记删除一个对象;垃圾回收之后,必须管理对对象的引用。

1.3 代码排列

写得好的软件要按照便于他人使用的方式进行排列。

Q: 如何解决应用程序的程序员绕过库直接跟硬件对话?

A: 找出他们为什么会绕过它,并尝试满足他们的需求,库是为他们服务的。

1.4 代码滥用

一个程序员的扩展就是另一个程序员的滥用。

Q: 库被不按照所期望的去使用,而是被滥用。

A: 即使在说明中清楚地标注出如何正确使用所编写的API,但这些警告就像黄色警示带,不能阻止乱穿马路。

1.5 嵌套倾向

Q: 在一个C文件中包含另一个C文件,是错了还是仅仅不正规?

A: 如果在两个地方使用同一段代码,不要在两个地方 #Include 它,而是把它单独作为模块来构建。

1.6 令人窒息的变化

Q: 单次代码签入的最佳规模应该多大?

A: 如果你更改了一个 API,那么一次性更新它和它的所有调用方。如果你修复了三个bug并添加了一个功能,则需要进行四次不同的签入。

1.7 被诅咒的代码

Q: 是否可以在代码中使用”丰富的隐喻“?

A: 其他人员不仅会看代码,也会看留下的注释和其它东西。因此,不要在代码中添加 joke 或者 *uck。

1.8 强制异常

Simple Testing Can Prevent Most Critical Failures: An Analysis of Production Failures in Distirbuted Data-Intensive Systems. 2016.

  • 异常处理肯定是需要的,对于编写健壮性的软件;要么不处理,要么好好处理。

Q: 为什么92%的灾难性故障都是由于未能处理好非致命错误造成的?

A: 对于你试图强加给别人的事情,如果可能的话,他们都会努力避免。Java 编译器要求开发人员捕获所有受检异常,但是在处理这些错误时往往草草了事。

1.9 一段不错的代码

Q: 推荐阅读 IP防火墙(IPFW)代码

A: 采用伯克利数据包过滤器(BPF),使用操作码和状态机对数据包进行分类;复用内核的路由表代码来存储它自己的地址查询表。

1.10 一些恶臭的东西

Q: 清晰、简介、写的很好的 Linux 中的 clocksoure.h。

A: 结构很好由相互协作的小组件构建而成,不会彼此接触或违反分层规则;以清晰和整洁的风格编写并记录。

1.11 日志系统

Q: 如何编写扩展性好的日志系统?

A: 1) 任何日志输出的第一列都应该时精确到秒的日期和时间,更容易写分析脚本;2)在行尾添加新的信息或者使用全新的信息行,兼容原先的处理脚本。

1.12 丢失

Q: 我似乎永远也找不到我自己写的代码,这不是指的是源服务器上的工作代码,而是个人写的其它用途的代码。

A: 私有服务器/公有云盘,Check In 自己在乎的一切内容,并使用正确的目录名去管理他们。

1.13 复制

软件由库和函数构成,应用复用而不是复制。

Q: 复制引起的问题?

A: bug 会被复制,修改需要维护多处代码。

1.14 五大编程问题

  1. 糟糕的注释:无意义的注释等;
  2. 空悬 else 问题;
  3. 幻数:魔法常量;
  4. 怪里怪气的代码:如一大段注释掉的代码;
  5. 全局变量。

1.15 语言上的迷失

Q: shell/python/c++ 该用什么语言完成工作?

A: 1)shell 脚本不被用于超过 100行的代码;2)Python 用于替换数百个类似的、曲折的shell脚本;3)阅读 The Practice of Programming

1.16 签入注释

Q: 多年后,如何记得被注释修改过的代码在哪个版本呢?

A: 签入代码时,加上适当的注释,这些注释可以被检索。签入注释的要求:1)BUG:问题是什么,如何修复的?2)Feature: 功能是什么,如何工作,如何使用?

2. 编程难题

2.1 方法的颂歌

假设是解决问题的一种可检验的想法。

Q: 你怎么知道这个已经修复了?质疑对系统所做的每一个改动!

A: 解决一个问题时,以科学方法的方式去做。把问题出在哪,作为理论写下来,基于理论提出假设,并保留已证实和已否定的假设。

2.2 C++里的“+”有多少

Q: 什么时候使用 C,什么时候使用 C++?

A: 1)C 也是一种面向对象的语言,如 Vnode 文件系统;2)C++代码不一定会比C乱。根据1)团队的技术栈;2)语言特性;来选择。

2.3 时尚而现代的事务

Q: 新的语言新的技术,对于使用这些的人有什么建议?

A: 区分好坏代码的因素与语言本身几乎没有关系。好的代码会使用语言的主流表达,以便于让其他人理解。

2.4 缓存缺失

Q: 为了节省指令使得代码混乱?

A: 性能优化以 benchmark 为准。现代编译器会进行很多优化。另外现代CPU最宝贵的资源不是指令,而是处理数据的缓存。一次缓存的缺失,会在一个3GHz的处理器上损失约100个周期,比许多指令都要昂贵。

2.5 代码探索

Q: 如何处理大型的、不熟悉的源码库?

A: 借用各种工具。除了linux 命令行工具,IDE编辑器之外,还有 Global(gtags/htags),ctags,cscope等。

性能工具:gprof, ktrace, dtrace。内存泄漏:valgrind。

2.6 输入验证

Q: 输入验证的相关bug,如CSRF/SQL注入等,解决一个同代码会出现一些其它问题,如何解决?

A: 1)不要相信任何人;2)不要相信自己。建议使用白名单而不是黑名单,白名单会进行严格限制,只允许特定的内容。

2.7 与文档打交道