Unix编程哲学感悟

来源:互联网 发布:空间金字塔池化网络 编辑:程序博客网 时间:2024/05/19 04:05

随着写的代码越来越多,最近发现《Unix编程艺术》真是本好书。只看了开头部分所归纳的原则,感觉其每一个都非常经典。参照自己过去写代码的经验,只能感叹如果当初早点看到这本书的原则,自己编程的时候能遵从这些原则的话肯定是会少走很多弯路的。

 

先记录经典原则:

 

1.     模块原则:使用简洁的接口拼合简单的部件。

2.     清晰原则:清晰胜于机巧。

3.     组合原则:设计时考虑拼接组合。

4.     分离原则:策略同机制分离,接口同引擎分离。

5.     简洁原则:设计要简洁,复杂度能低则低。

6.     吝啬原则:除非确无它法,不要编写庞大的程序。

7.     透明性原则:设计要可见,以便审查和调试。

8.     健壮原则:健壮源于透明和简洁。

9.     表示原则:把知识叠入数据以求逻辑质朴而健壮。

10.  通俗原则:接口设计要避免标新立异。

11.  缄默原则:如果一个程序没什么好说的,就沉默。

12.  补救原则:出现异常时,马上退出并给出足够错误信息。

13.  经济原则:宁花机器一分,不花程序员一秒。

14.  生成原则:避免手工hack,尽量编写程序去生成程序。

15.  优化原则:雕琢前先要有原型,跑之前先学会走。

16.  多样原则:决不相信所谓“不二法门”的断言。

17.  扩展原则:设计着眼未来,未来总比预想来得快。

 

其中表示原则很有意思,可以广泛应用于3D游戏引擎,因为在优化3D引擎优化方案中,一种是直接用代码优化,另外的是用相关数学推导相应的公式,然后根据已经推导的公式写代码,根据表示原则把知识叠入数据以求逻辑质朴而健壮。所以应该优先考虑后面所述方案。因为推导数学公式不易出错,只要严格遵从数学定理就可以了,根据推导的数学模型公式写代码,这样的代码才健壮。否则的话,直接在代码层面优化,其含义晦涩又容易出BUG。典型的例子就是四元数压缩,在3D游戏中,一个很耗费GPU的就是人物模型动画,我们实现动画都用“骨骼蒙皮”实现。当人运动的时候,关键的骨骼节点变化主要是旋转变化,现在市面上一些教程和程序实现骨骼运动是用简单的旋转矩阵解决问题。如果用旋转矩阵会占用大量的内存且有很多冗余数据。这时候用四元数处理旋转非常好,因为只有4个数(矩阵9个数据),而且可以方便用四元数线性差值。虽然四元数比矩阵少很多数据,还可以对其进行压缩,即把4个浮点类型的四元数压缩为一个32位的整数。例如把一个四元数xyzw 4个浮点类型的数据压缩为一个32位整数的时候,可以用3位表示 x y z 的正负符号。把四元数集合转化为分布在球心在原点的一个球面上。用38种状态判断四元数在哪一卦象解决符号问题的同时,这样只要知道1/8个球面的四元数就可以了。即把四元数集合平均分布映射到1/8球面上,在这1/8球面上平均分布512行和512列点集,其行号和列号分别表示类似于地球表面的纬度和经度。这样四元数表示的角度可以精确到 90/512约为0.175度角,这样角度的精度还是蛮可观的。然后可以行与列的512个数字分别用9位存储转化。这就分配了3+9+9位,剩余的11位全部分配给四元数 W.

例如地球的北极到赤道用512条分布均匀纬线(行号)row表示,当row0表示在北极,当row511表示在赤道位置。如果把笛卡尔坐标轴的Y轴作为地球的自转旋转轴。

 

在这个数学模型中因为: 纬度角/90 = row / 512

 

所以:

row = atan( x / y ) * 512 / 90;

进步优化:row = atan( x/y ) * 0.175781f;

 

 

当然如果是用CPU做简单优化,可以先分配一组内存存储预先计算好的其正弦余弦或正切余切的值,哪个用得多就用哪个。然后代替上式的atan( x/y ),这样直接访问内存的方法就可以去掉反三角函数的计算。在这里用反正切函数纯属为了方便直观表述。

 

以上的简单思路就是先建立推导优化数学模型公式,然后再根据推导出来的数学公式写代码,遵从了表示原则,即把知识叠入数据以求逻辑质朴而健壮。

 

上述罗列的编程原则还是要具体情况具体分析决定。例如我们在写工具的时候就可以遵从经济原则,宁花机器一分,不花程序员一秒。而在一些程序的核心部分追求性能则该忽略它。

 

在《C语言程序设计_现代方法(2)》一书中讲解C语言都还算详细,只是作者谈到C语言不足的时候,作者语气居然抱怨 C语言不能像C++那样写抽象类操作的函数,这点很不好,因为C是面向过程语言,偶尔借鉴C++面向对象思想无可厚非,但总是想把C模拟出C++那样真的很糟糕,之前有段时间是很有热情写C++代码,但到后来用起来感觉蹩脚,而且要改动C++代码是比较难的,应该是由其机制所决定的吧,不像C那样,如果整体设计好的话,到时改变局部对软件全局影响较少,在设计模块的时候,正如《Unix编程艺术》所说,C是属于薄粘合层的,而C++或面向对象语言属于浓厚的粘合层的,所以单凭这点,就觉得CC++好很多。

 

其实从《Unix编程艺术》编程原则可以挖掘深究的东西还有很多,以后有时间再继续