当你编码时
当你编码时
注重实效的程序员 批判的思考所有的代码,包括我们自己的。
靠巧合编程
我们应该避免靠巧合编程——依靠运气和偶然的成功,而应该生思熟虑的编程。
怎样靠巧合编程
不知道代码为什么能够工作 也不知道代码为什么突然失败。
实现的偶然
那些只是因为现在的编写方式才得以发生的事情。你最后会依靠没有计入文档的错误或是边界条件。
我们需要思考代码:
- 它也许不是真正的工作
- 你依靠边界条件也许只是一个偶然
- 没有计入文档的行为可能会随着库的下一次发布而变化
- 多余的调用还会增加引入它们自己新的bug的风险
语境的偶然
隐含的假定
怎么样深思熟虑的编程
- 总是意识到你在做什么
- 不要盲目的编程
- 按照计划行事
- 依赖可靠的事物
- 为你的假定建立文档
- 不要只是测试你的代码,还要测试你的假定
- 为你的工作划分优先级
- 不要做历史的奴隶
算法的速率
注重实效的程序员:估算算法使用的资源——时间,处理器,内存等等
O()表示法
O()表示法 是处理近似计算的一种数学途径。
一些常见的O()表示法
-
$ O(1)$ 常量型 (访问数组元素 简单语句)
-
O ( l o g 2 ( n ) ) O(log_2(n)) O(log2(n)) 对数型(二分查找)
-
O ( n ) O(n) O(n) 线性型(顺序查找)
-
O ( n l o g 2 ( n ) ) O(nlog_2(n)) O(nlog2(n)) 比线型差 但不会差太多(快速排序 堆排序的平均运行时间)
-
O ( n 2 ) O(n^2) O(n2) 平方律型(选择和插入排序)
-
O ( n 3 ) O(n^3) O(n3)立方型( 2 n × n 2n\times n 2n×n矩阵相乘)
-
O ( C n ) O(C^n) O(Cn) 指数型(旅行商问题,集合划分)
常识估算
-
简单循环 时间随着n线性增加 O ( n ) O(n) O(n)
-
套嵌循环 O ( m × n ) O(m \times n) O(m×n) 比如冒泡排序 O ( n 2 ) O(n^2) O(n2)
-
二分法 O ( l o g 2 ( n ) ) O(log_2(n)) O(log2(n))
-
分而治之 划分其输入,并独立的在两个部分上面进行计算,最后把结果组合起来的算法可能是 O ( n l o g 2 ( n ) ) O(n log_2(n)) O(nlog2(n)) 经典的例子:快速排序
-
组合 只要算法考虑到事物的排列,其运行时间就可能失控。
重构
重写,重做和重新架构代码合起来,称为重构(refactoring
)
何时重构
代码具有以下特征时考虑重构
- 重复
- 非正交设计
- 过时的设计
- 性能
怎样重构
- 不要试图在重构的同时增加功能
- 在重构之前 保证拥有良好的测试
- 采取短小 深思熟虑的步骤
易于测试的代码
单元测试
软件的单元测试是对模块进行演练的代码
针对合约进行测试
我们常常喜欢把单元测试视为针对合约的测试
编写单元测试
使用测试装备
测试装备具有以下功能
- 用以指定设置与清理的标准途径
- 用以选择个别或所有可用的测试的方法
- 分析输出是否预期结果的手段
- 标准化的故障报告形式
参考JUnit的使用
邪恶的导向
Don’t Use Wizard Code You Don’t Understand
不要使用你不理解的导向代码
考虑Lombok javaGenerator