程序设计启示 (摘记)

刚开始看代码大全,真是大部头,不知道毕业之前能不能看完,或者看完的时候有没有毕业…(泪)。应该是还没有看到干货部分,不过对于程序设计里的问题,有很多很好的总结,所以摘录一点在这里。这部分原文是 Design Heuristics,直译应该是“设计启示”,可是我觉得应该算是一些心得。想起来以前在图书馆见过有一本书叫做《软件启示录》,按照当年的习惯,应该看过并且仅看过前言 ^^

罗列一下书上的总结,就不瞎翻译了。

Major Heuristics

  • Find Real-World Objects
  • Form Consistent Abstraction
  • Encapsulate Implementation Details
  • Inherit When Possible
  • Hide Secrets (Information Hiding)
  • Identify Areas Likely to Change
  • Keep Coupling Loose
  • Look for Common Design Patterns

Useful Heuristics

  • Aim For Strong Cohesion
  • Build Hierarchies
  • Formalize Class Contracts
  • Assign Responsibilities
  • Design for Test
  • Avoid Failure
  • Choose Binding Time Consciously
  • Make Central Points of Control
  • Consider Using Brute Force
  • Draw a Diagram
  • Keep Your Design Modular

封装、抽象和解耦合是时时记住的准则。但是我没有系统地学过设计模式,这部分要去补习了。

第二个列表提到了层次 (Hierarchies),最近感觉层次是方法,但是也是问题。有时候是为了解耦,有时候单纯为了处理重复代码,很容易就会增加抽象层次,结果就是代码越写越厚,为了保持各层之间独立,新增加底层功能要暴露给上面的代码需要修改很多地方。深以为是自己做的不对,每次大改完之后会好一些,但是层次的增加似乎真是不可避免。想到最近云风大喷C++的时候说C++会引导程序员增加层次,不知道是不是我现在遇到的情况。

最近这次改代码,尽量做到扁平,最理想的情况其实是各个功能可以独立出来,像EM、聚类这些算法可以随时独立的拿到其他工程里去用,但是除非是大量的用代码生成代码 (刚刚想到,不知道可不可行),否则就得手动处理很多重复代码。所以,我觉得库都要有支持基本类型的结构,可以把float*、int*很方便的、高效地转成它们的基本类,否则如果只需要用到库的一小部分功能就要以库里的类型渗透到所有的代码逻辑里为代价,就太不划算了。

还有一点有同感的就是 Make Central Points of Control 这一点,写实验的时候这一点太重要了。实验里有很多参数、设置都放到一个地方直观而且不容易出错。我之前的做法是非常简单的config类,然后是 key-value 来存取值,但是当配置躲起来的时候,一则 key 太多放在一起很没有逻辑,二则 key 是没有类型的,如果程序里到处都是valueOfKey()这种调用,很容易出错。为了把key-value和对应的模块放到一起,又需要有一些结构做配置之上的封装,形成像em的配置、取特征的配置这类的结构。现在的问题就是,如果要增减一个配置结构里面的内容,需要改动至少两个不同的地方。感觉这个是老问题,应该有现成的解决方法,但还是没有找到。

配置文件的另外一个问题就是需要有东西生成配置文件,现在用bash写configuration文件,然后C++读,所以C++需要和bash共享一部分内容,比如key-value pairs的key。现在的做法是类似用bash读一个config.h。所以bash脚本就必须知道源文件的位置,不知道有没有更好的解决方法。

本来就想写个笔记,没想到吐槽了一大堆。在实验室写代码的好处就是可以自己控制整个工程,虽然工作量大一点,也没有测试帮忙保证质量,但是可以默默地改代码,满足一下码农的完美主义。