《代码整洁之道》阅读笔记 10类

260 阅读5分钟

SRP(单一职责原则)

1.类的组织

1 ) 类应该从一级变量列表开始,如果有公共静态变量,应该先出现,然后是私有静态变量,以及实体变量,很少会有公共变量

2 ) 公共函数应该跟在变量列表之后

3 ) 我们喜欢保持变量和工具函数的私有性,有时需要用到受保护变量或工具函数,好让测试可以访问到我们首先会想办法使之保有隐私,放松封装总是下策

2.类应该短小

1 ) 第一规则是类应该短小,第二规则是还要更短小

2 ) 衡量方法,计算权责(responsibility)

3 ) 类的名称应当描述其权责,如果无法为某个类命以精确的名称,这个类大概就太长了,类名越含混,该类越有可能拥有过多权责

4 ) 单一权责原则(SRP)认为,类或模块应有且只有一条加以修改的理由

如代码段10.1里面的版本管理,应该可以再独立出一个类。演变为代码段10.2

代码段10.1
public class SuperDashboard extends JFrame implements MetaDataUser {

        public Component getLastFocusedComponent()
        public void setLastFocused(Component lastFocused)
        public int getMajorVersionNumber()
        public int getMinorVersionNumber()
        public int getBuildNumber()
    }
代码段10.2
 public class Version {
        public int getMajorVersionNumber();
        public int getMinorVersionNumber();
        public int getBuildNumber();
    }

而这个创建出的类极有可能在其他地方回得到复用

系统应该由许多短小的类而不是少量巨大的类组成,每个小类封装一个权责, 只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为

5 ) 内聚,类应该只有少量实体变量。类中的每个方法都应该操作一个或多个这种变量。通常而言,方法操作的变量越多,就越黏聚到类上。如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性

保持函数和参数列表短小的策略,有时会导致为一组子集方法所用的实体变量数量增加。出现这种情况时,往往意味着至少有一个类要从大类中挣扎出来。你应当尝试将这些变量和方法分拆到两个或多个类中,让新的类更为内聚

请参考书中代码清单10.5里面的例子(非常经典)

6 ) 将大函数拆为许多小函数,往往也是将类拆分为多个小类的时机

3.为了修改而组织

1.在整洁的系统中,我们对类加以组织,以降低修改的风险

2.开放-闭合原则(OCP):类应当对扩展开放,对修改封闭

public class Sql {
    public Sql(String table, Column[] columns)
    public String create()
    public String insert(Object[] fields)
    public String selectAll()
    private String selectWithCriteria(String criteria)
    private String valuesList(Object[] fields, final Column[] columns)
}

当新增一种语句类型时,就要修改Sql类。改动单个语句类型时,也要进行修改。说明Sql违背了单一职责原则。 并且还出现了与类一小部分有关的私有方法,比如selectWithCriteria() 改进后:

abstract public class Sql {
    public Sql(String table, Column[] columns)
    abstract public String generate();
}
 
public class CreateSql extends Sql {
    public CreateSql(String table, Column[] columns)
    @Override
    public String generate()
}
 
public class InsertSql extends Sql {
    public InsertSql(String table, Column[] columns)
    @Override
    public String generate()
    private String valuesList(Object[] fields, final Column[] columns)
}
 
public class SelectSql extends Sql {
    public SelectSql(String table, Column[] columns)
    @Override
    public String generate()
}

......

如此一来,每个类中的代码都记为简单,函数对于其它函数造成毁坏的风险也变得几乎近无 类与类之间相互隔离了,当需要增加语句时,现存的类无需修改,只需要继承Sql类即可 重构后的Sql遵守单一职责原则,同时也遵守开闭原则 隔离修改

3.在理想系统中,我们通过扩展系统而非修改现有代码来添加新特性

4.依赖倒置原则(Dependency Inversion Principle,DIP),类应该依赖于抽象而不是依赖于具体细节

现在我们实现股票计算相关的代码,构建一个Portfolio类来代表投资组合的价值,如果直接依赖于外部TokyoStockExchanged的API,则测试用例就会受到价值查询连带的影响

与其设计直接依赖于TokyoStockExchange的Portfolio类,不如直接创建StockExchange接口,这个接口呈现的是得到某只股票价格的抽象概念。隔离了询价的特定细节。比如价格计算方法,数据来源等。让TokyoStockExchange来实现这个接口:

代码段10.3
public interface StockExchange {
   Money currentPrice(String symbol};
}

代码段10.4
public class Portfolio {
    private StockExchange exchange;
    //这里依赖了抽象的接口
    public Portfolio(StockExchange exchange) {
        this.exchange = exchange;
        // ...
    }}

通过降低连接度,我们就遵循了另一条设计原则,依赖倒置原则,类应该依赖于抽象而不是依赖于细节

4.参考文献

《代码整洁之道》 blog.csdn.net/pengbo66656… 方法。

关注公众号“程序员面试之道”

回复“面试”获取面试一整套大礼包!!!

本公众号分享自己从程序员小白到经历春招秋招斩获10几个offer的面试笔试经验,其中包括【Java】、【操作系统】、【计算机网络】、【设计模式】、【数据结构与算法】、【大厂面经】、【数据库】期待你加入!!!

1.计算机网络----三次握手四次挥手

2.梦想成真-----项目自我介绍

3.你们要的设计模式来了

4.震惊!来看《这份程序员面试手册》!!!

5.一字一句教你面试“个人简介”

6.接近30场面试分享