分享

《软件开发沉思录》读书笔记 - JavaEye技术网站

 zhongfeiying 2010-12-16

《软件开发沉思录》读书笔记

文章分类:IT生活



这本书非常薄, 里面的作者却不少, 来自thoughtworks的各个层面, 其中心就是围绕敏捷这个东西在说事儿, 没有必要从头看到尾, 各取所需吧. 比如对我来说, 只有"对象健身操"这一章勉强是看完了的.

优秀设计背后的核心理念其实并不高深. 比如内聚性, 松耦合, 零重复, 封装, 可测试性, 可读性以及单一职责. 这七条差不多是放之四海而皆准的准则了.

理解了封装就是隐藏"数据, 实现细节, 类型, 设计或者构造", 这只是设计出良好封装的代码的第一步而已.

最"极端", 最"变态"的准则:
  • 方法只使用一级缩进
  • 拒绝使用else关键字
  • 封装所有的原生类型和字符串
  • 一行代码只有一个"."运算符
  • 不要使用缩写
  • 保持实体对象简单清晰
  • 任何类中的实体变量都不要超过两个.
  • 使用一流的集合
  • 不使用任何的getter/setter/property


庞大的方法通常缺少内聚性, 一个常见的原则就是将方法的行数控制在5行之类.

对于简单的条件判断, 我们可以使用卫语句和提前返回替换它.

如果代码的每一行都有多个".", 那么这个行为就可能是发生错误的位置了, 也许你的对象需要同时与另外两个对象打交道. 而且这些过量的"."说明你破坏了封装性. 尝试让对象为你做一些事情, 而不要窥视对象内部的细节. 封装的主要含义就是, 不要让类的边界跨入到它不应该知道的类型中.
比如一个采用多点的类:
Java代码 复制代码
  1. public class Board {   
  2.     class Price {   
  3.         String representation;   
  4.     }   
  5.   
  6.     class Location {   
  7.         Price current;   
  8.     }   
  9.   
  10.     String boardRepresentation() {   
  11.         StringBuffer sb = new StringBuffer();   
  12.         for (Location l : sequares()) {   
  13.             sb.append(l.current.representation.substring(01));   
  14.         }   
  15.         return sb.toString();   
  16.     }   
  17.   
  18.     private Location[] sequares() {   
  19.         return null;   
  20.     }   
  21. }  


重构之后:
Java代码 复制代码
  1. public class RefactorBoard {   
  2.     class Price {   
  3.         String representation;   
  4.   
  5.         String character() {   
  6.             return representation.substring(01);   
  7.         }   
  8.   
  9.         void addTo(StringBuffer sb) {   
  10.             sb.append(character());   
  11.         }   
  12.     }   
  13.   
  14.     class Location {   
  15.         Price current;   
  16.   
  17.         void addTo(StringBuffer sb) {   
  18.             current.addTo(sb);   
  19.         }   
  20.     }   
  21.   
  22.     String boardRepresentation() {   
  23.         StringBuffer sb = new StringBuffer();   
  24.         for (Location l : sequares()) {   
  25.             l.addTo(sb);   
  26.         }   
  27.         return sb.toString();   
  28.     }   
  29.   
  30.     private Location[] sequares() {   
  31.         return null;   
  32.     }   
  33. }  


我们总会不知觉的在类名, 方法名或者变量名中使用缩写. 请抵制这个诱惑. 缩写会令人困惑, 也容易隐藏一些更严重的问题.

想想你为什么要使用缩写, 因为你厌倦了一遍又一遍的敲打单词, 如果是这种情况, 也许你的方法调用过于频繁, 你是不是应该停下来消除一下重复了? 因为方法的名字太长? 这可能意味着有些职责没有放在正确的位置或者有缺失的类.

尽量保持类名和方法名中只包含一到两个单词, 避免在名字中重复上下文信息. 比如某个类是Order, 那么方法名就不必叫做shipOrder()了, 把它简化成ship().

每个类的长度都不能超过50行, 每个包中包含的文件不超过10个.

代码超过50行的类所做的事情通常都不止一件, 这回导致他们难以被理解和重用. 小于50行的代码的类还有一个妙处: 它可以在一屏显示, 不需要滚屏, 这样程序员可以很容易, 很快速地熟悉这个类.

创建这样的小类会有什么挑战呢? 通常会有很多成组的行为, 它们逻辑上是应该在一起的, 这时就需要使用包机制来平衡, 随着类变得越来越小, 职责越来越少, 加之包的大小也受到限制, 你就会逐渐注意到, 包中的类越来越集中, 他们就能够协作完成一个相同的目标. 包和类一样, 也应该是类聚的, 有一个明确的意图. 保证这些包足够小, 就能使它们有一个真正的标识.

大多数的类应该只负责处理单一的状态变量, 有时候也可以拥有两个状态变量, 每当为类添加一个实例变量, 就会立即降低类的内聚性. 一般而言, 编程如果遵守这些规则, 你就会发现只有两种类, 一种只负责维护一个实例变量的状态; 另一种类只负责协调两个独立的变量. 不要让这两种职责同时出现在一个类中.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多