每日博客之十一月读书笔记1

《程序员的修炼之道——从小工到专家》

*弯曲,或折断

解耦:任何一个单独的模块尽量不要依赖其他模块的特性,除了有些特殊情况下会违背这个原则换取一定的效率。

元数据:用于将代码功能灵活化。将容易改变的、不确定的数据用“元数据”进行配置而不要固定地编织到代码中;可以将某些并非模块固定功能的逻辑(比如客户的个性化需求)通过配置而非代码的方式表示,这样就不用反复为了适应需求而修改代码、重新编译。可以时不时检查加载新的配置以免修改配置便需要重启的麻烦状况。

时间的解耦:进行流程分析,分析各任务时间上的相互依赖,进行并发编程,可以提高程序的效率。要对全局变量、静态数据的访问与调用进行保护。接口要设计得更整洁,避免接口对调用时间的依赖。

发布/订阅协议:某个模块只关心特定的事件,并对不同事件分别作出响应。模块通过“订阅”(subscribe)某个事件对事件作出响应。而模块引发某个事件时,依次调用各个订阅者通知事件发生。

MVC:将Model(数据模型), View(视图)和Controller(视图控制器)解耦。MVC模型虽然用于GUI开发,但可以更泛化地理解为Model为抽象数据模型;View为解释模型的方式,向Model与Controller订阅事件;Controller控制View并向Model提供新数据,向Model与View发布事件。

黑板:将各个信息放在一个信息流里,各模块与信息流进行交互,从而可以达到统一简便的交互,而不需要在各个模块之间两两规定严密的发布/订阅协议,发布者与订阅者不需要了解对方。

这个设计用于较为复杂,每个模块的行为都会带来新的改变,随时有可能有事件发生并引起其他模块的行为的系统,此时在各个模块之间一一设计接口几乎不可能。

这个设计很优美,但我产生了两个疑惑:这样大的数据量是否会对数据的维护和模块的查找带来负担?是否会出现信息泄漏的风险?对于第一个问题,维护问题我没有想好,但查找可以通过良好地组织数据结构简化;对于第二个问题,可以通过限制权限得到改善,但似乎还是会有风险。

 

*当你编码时

编码过程中应该遵循的原则。

靠巧合编程:不可靠。不要使模块可能依赖特定的输入数据、语境,否则模块的正常工作可能只是偶然。积极地查找可能的问题并修改。

为了避免这个问题,编码过程中要依靠可靠的、了解的东西,而不要碰巧拼凑一些代码,希望它能成功。比如如果不会使用某个第三方库,应该去学习而非随意堆积代码,试图得到希望得到的结果。为模块编写文档有利于发现隐藏的假设和巧合。

不要让自己成为过去的代码的奴隶,尤其是在开发阶段。对于模棱两可、可能出问题的代码,要积极地进行检查与重构。

算法速率:这里讲到了对算法运行时间进行O( )的估算,即数据结构课程中提到的时间复杂度。算法速率的估算可以通过常识估算。如果算法有多重循环,达到了O(n^2)甚至O(n^3)的时间复杂度,就要试着用分治法等方法将时间复杂度降低。不过算法速率的估算是理论的极端情况,实际的算法速率要通过测试来获取。可以使用code profiler这一工具获得算法中不同步骤的执行次数。

不过快的算法速率并不一定是好的。有时数据集很小,O(n)与O(ln n)级的算法差别很小,算法速率反而受常数影响更大。这时花过多的时间构想一个高效的算法是没有实际意义的,根据实用主义的原则不必这么做。当然如果随着系统的增加该算法成了效率瓶颈,进行优化就很有必要。

重构:重写、重做及重新架构代码。在出现这些情况时需要重构:代码有自重复、功能不正交、性能不够、内容过时。重构可能是痛苦的,但不要为了一时的痛苦放弃重构,因为有问题的代码可能带来更多问题。重构是将原本能够工作的代码进行修改,所以很可能是危险的。重构要遵循以下原则:不能加入新功能。保持有一系列良好的测试,这样出现任何问题时都可以快速发现。将重构拆分成许多个短小的重构,并在进行每个小改动之后进行测试,以发现可能的错误。

易于测试的代码:进行模块的组装前,对模块进行单元测试,检查其在各种情况下的行为非常重要。对于有依赖关系的模块,从最小的模块向上层层单元测试可以更容易定位错误。建议根据合约对代码进行测试,利用合约的前条件、后条件和不变量设置可以很容易确定测试内容。

编写代码的同时就应该编写代码的单元测试。

编写大型项目时,为了方便单元测试,应该使用测试装备以动态构建测试。比如可以编写一个类,负责测试的常用功能。测试装备有必要提供以下功能:用以指定设置测试条件与清理测试现场的方法,用以选择个别或全部测试的方法,分析输出是否是预期结果的方法,生成标准化错误输出的方法。测试应该是可组合的。

在编写代码的过程中,常会加入一些即兴调试,如printf语句。不要抛弃这些调试语句,将它们加入单元测试。编码过程中出现过问题的部分在运行中可能会再出问题。

代码部署好之后也不要忘记测试。要构建运行日志以方便记录运行状态,日志应该风格良好以方便解析。要构建可用于诊断运行状态的服务。

邪恶的向导:依靠开发环境提供的“向导”进行编码是依靠巧合而编程。可以使用封装良好的第三方库,但在不理解gui生成的“向导代码”时不要使用它,因为它会变成代码有机的一部分,并随时可能带来问题。

posted @ 2020-11-16 21:11  谦寻  阅读(61)  评论(0编辑  收藏  举报