一点点萤火之光,不算什么成体系的想法。
编程在做什么?
我认为程序描述的是数据状态之间的转换。编程某种意义上等同于实现一条逻辑链条使得数据状态(输入)不断地转换成其它数据状态直至数据状态(输出)。
我一般会这么做来编写一段涉及到多个变量的程序:
- 明确程序要做的事情,输入输出和程序处理该事情的逻辑
- 设计合适的数据结构表达程序逻辑过程中的各个数据状态,包括输入,输出和过程中涉及的变量,明晰这些数据结构的范围和属性,以及相互的关系
- 将处理逻辑等价转换为对应数据状态的改变,用代码实现一个数据状态到另外一个数据状态的改变。
那么这样,如果程序出现bug,可以肯定地找到对应的出现问题的数据结构,然后回溯,观察这问题是数据结构转换(逻辑)的问题,还是数据结构的定义问题。前者,需要思考逻辑的正确或错误,后者需要思考数据结构设计的问题,引用的问题或者类型的问题,很多时候也包括输入的数据异常问题。
程序的另外一方面则是实现的效率,即空间复杂度和时间复杂度。就我的实践经验来看,空间复杂度主要和数据的解耦程度相关,在一些读表写表中很容易出现相关的问题。比如说,属性A有少量不同值,但每个值的占据空间都很大。同时有很多实例,每个实例都具有属性A,如果将属性A都存放到实例中存储,会带来空间的浪费。空间意义上更好的做法是为这些属性A的值建立索引,然后把属性A对应值的索引存放到实例中。
在我实践时,时间复杂度主要和算法以及各种数据结构的遍历,查询相关。优秀的算法不必多言。有一个insight:感觉优秀的算法比一般的算法使用了更少的数据结构描述问题,并且数据结构之间的关系更精确和精炼。又比如遍历查询,比如给我们一张较大的表,将属性A相同的行统一使用某函数处理聚合。笨的方法是,对属性A的每一个值都在表中遍历筛选相同的行,其时间复杂度是 属性A的不同值的数量乘以表的长度。好的方法是,遍历表的行索引和属性A,建立字典——属性A的某个值:属性A为该值的行索引,然后再遍历该字典,取出相关相关索引,读取对应的行,时间复杂度是 表的长度