代码的整洁之道——简单设计四规则

1. 运行所有测试
2. 不可重复
3. 表达了程序员的意图
4. 尽可能减少类和方法的数量

不可重复
重复有多种表现,极其雷同的代码当然是重复,类似的代码往往可以调整的更相似,这样就能更容易的进行重构

重复也有实现上的重复等其他一些形态。例如,在某个群集类中可能会有两个方法

int size() {}
boolean isEmpty() {}

这两个方法可以分别实现,isEmpty方法跟踪一个布尔值,而size方法则跟踪一个计数器
或者也可以通过isEmpty中使用size方法来消除重复

boolean isEmpty(){
  return 0 == size();
}

要想创建整洁的系统,需要有消除重复的意愿,即使对于短短几行也是如此,例如如下代码:

public void scaleToOneDimension(float desireDimension,float imageDimension) {
    if(Math.abs(desiredDimension - imageDimension) < errorThreshold)
    return;
    float scalingFactor = desiredDimension / imageDimension;
    scalingFactor = (float)(Math.floor(scalingFactor * 100) * 0.01f);

    RenderedOp newImage = ImageUtilities.getScaledImage(image,scalingFactor,scalingFactor);
    image.dispose();
    System.gc();
    image = newImage;
}

public synchronized void rotate(int degrees){
   RenderedOp newImage = ImageUtilities.getRotatedImage(image,degrees);
   image.dispose();
   System.gc();
   image = newImage;
}

要保证系统整洁,应该消除scaleToOneDimension和rotate方法里面的少量重复;

public void scaleToOneDimension(float desireDimension,float imageDimension) {
    if(Math.abs(desiredDimension - imageDimension) < errorThreshold)
    return;
    float scalingFactor = desiredDimension / imageDimension;
    scalingFactor = (float)(Math.floor(scalingFactor * 100) * 0.01f);
    replaceImage(ImageUtilities.getScaledImage(image,scalingFactor,scalingFactor));
}

public synchronized void rotate(int degrees){
  replaceImage(ImageUtilities.getRotatedImage(image,degrees));
}

private void replaceImage(RenderedOp newImage){
   image.dispose();
   System.gc();
   image = newImage;
}

做了一点点共性抽取后,我们意识到已经违反了SRP原则(单一职责原则)
scaleToOneDimension方法负责根据指定的维度缩放图像。
rotate方法负责旋转图像。
replaceImage方法不仅替换了图像,还调用了System.gc()来进行垃圾回收。
所以可以把一个新方法分解到另外的类中(专门处理内存管理的类),从而提升可见性。

另外,模版设计模式是一种移除高层级重复的通用技巧。

表达力
写出自己能理解的代码很容易,因为在写这些代码时,我们正深入要解决的问题。
代码的其他维护者不会那么深入,也就不易理解代码

软件项目的主要成本在于长期维护,为了在修改时尽量降低出现缺陷的可能性,很有必要理解系统是做什么的。
当系统变得越来越复杂,开发者就需要越来越多的时间来理解它,而且也极有可能误解。
所以,代码应当清晰地表达其作者的意图,作者把代码写的越清晰,其他人花在理解代码上的时间也就越少,从而减少缺陷,缩减维护成本

可以通过选用好名称来表达,短小的类和函数通常易于命名,易于编写,易于理解

还可以通过采用标准命名法来表达。例如设计模式很大程度上就关乎沟通和表达,通过在实现这些模式的类的名称中采用标准模式名,就能充分地向其他开发者描述你的设计,例如
如果你实现了一个单例模式的类,可以将类命名为 SingletonDatabase,这样其他开发人员在看到这个类的名称时,就能马上明白这是一个单例模式的数据库类。

如果你实现了一个观察者模式的类,可以将类命名为 ObserverNotifier,这样可以很清楚地表明这个类的功能是通知观察者。

编写良好的单元测试也具有表达性,不过,做到表达力的最重要方式却是尝试。有太多时候,我们写出能工作的代码,就转移到下一个问题上,没有下足功夫调整代码,让后来者易于阅读。记住,下一位读代码的人最有可能是你自己
所以,多少花一点点时间在每个函数和类上。选用较好的名称,将大函数切分为小函数,时时照拂自己创建的东西,用心是最珍贵的资源

尽可能少的类和方法
即便是消除重复、代码表达力和SRP等最基础的概念也会被过度使用。为了保持类和函数短小,我们可能会造出太多的细小类和方法。所以这条规则也主张函数和类的数量要少
我们的目标是在保持函数和类短小的同时,保持整个系统短小精悍,不过要记住,这在关于简单设计的四条规则里面是优先级最低的一条,所以尽管使类和函数的数量尽量少是很重要的,但更重要的却是测试、消除重复和表达力

posted @ 2024-07-19 16:32  狗狗没有坏心眼  阅读(1)  评论(0编辑  收藏  举报