S 单一原则

public class UserInfo {
    private Long userId;
    private String username;

    private String email;

    private String telephone;

    private Long createTime;

    private Long lastLoginTime;

    private String avatarUrl;
    /**
     * 省
     */
    private String provinceOfAddress;
    /**
     * 市
     */
    private String cityOfAddress;
    /**
     * 区
     */
    private String regionOfAddress;
    /**
     * 详细地址
     */
    private String detailedAddress;
    //省略其他属性和方法...
}

这个类足够单一吗?

对于这个类有两种观点:

  1. 这个类包含的根用户相关的信息,所以属性和方法都是隶属于用户这样一个业务模型,满足单一职责
  2. 这个类中地址信息所占比的中较高,应该将根地址相关的属性重新拆分成一个独立的UserAddress类,UserInfo只保留除Address之外的其他信息,拆分之后两个类的职责更加单一

实际上,要从中做出选择,要具体根据实际的业务场景来区分。在社交产品中,用户的信息只是单纯的为了展示,而不做过多业务,那么UserInfo当前的设计就是合理的。但是,如何这个社交产品后期反正得不较好,之后又在产品中新增了电商模块,用户的地址信息还会用在电商物流中,那我们最好将地址信息从UserInfo中拆分出来,独立成用户物流信息(或者叫地址信息、收货信息等)


我们在进一步延伸一下,如果这个社交产品的公司发展的越来越好,公司内部又开发出了很多产品(APP),公司希望支持统一账号登录,也就是用户一个账号可以在公司内部所有的产品进行登录。这个时候我们就需要继续对UserInfo进行拆分,将根身份认证相关的信息(比如,email、telephone等)抽取成独立的类


从这个例子,可以总结出:

  • 对单一职责的的确定性,在不同的应用场景、不同的需求背景下,对同一个类的职责是否单一的判定,可能都是不一样的。
  • 在某种应用场景或当下的需求背景下,一个类的设计可能已经满足单一职责原则了,但如果换个应用场景或着在未来的某个需求背景下,可能就不满足了,需要继续拆分更细粒度的类。
  • 综上所述,评价一个类的职责是否足够单一,我们并没有一个非常明确的、可以量化的标准,可以说,这是件非常主观、仁者见仁智者见智的事情。实际上,在真正的软件开发中,我们也没必要过于未雨绸缪,过度设计。所以,我们可以先写一个粗粒度的类,满足业务需求。随着业务的发展,如果粗粒度的类越来越庞大,代码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类。这就是所谓的持续重构

    听到这里,你可能会说,这个原则如此含糊不清、模棱两可,到底该如何拿捏才好啊?我这里还有一些小技巧,能够很好地帮你,从侧面上判定一个类的职责是否够单一。而且,我个人觉得,下面这几条判断原则,比起很主观地去思考类是否职责单一,要更有指导意义、更具有可执行性:

  • 类中的代码行数、函数或属性过多,会影响代码的可读性和可维护性,我们就需要考虑对类进行拆分;
  • 类依赖的其他类过多,或者依赖类的其他类过多,不符合高内聚、低耦合的设计思想,我们就需要考虑对类进行拆分;
  • 私有方法过多,我们就要考虑能否将私有方法独立到新的类中,设置为 public 方法,供更多的类使用,从而提高代码的复用性;
  • 比较难给类起一个合适名字,很难用一个业务名词概括,或者只能用一些笼统的 Manager、Context 之类的词语来命名,这就说明类的职责定义得可能不够清晰;
  • 类中大量的方法都是集中操作类中的某几个属性,比如,在 UserInfo 例子中,如果一半的方法都是在操作 address 信息,那就可以考虑将这几个属性和对应的方法拆分出来

重点回顾今天的内容到此就讲完了。我们来一块总结回顾一下,你应该掌握的重点内容。

  1. 如何理解单一职责原则(SRP)?

    一个类只负责完成一个职责或者功能。不要设计大而全的类,要设计粒度小、功能单一的类。单一职责原则是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。

  2. 如何判断类的职责是否足够单一?

    不同的应用场景、不同阶段的需求背景、不同的业务层面,对同一个类的职责是否单一,可能会有不同的判定结果。实际上,一些侧面的判断指标更具有指导意义和可执行性,比如,出现下面这些情况就有可能说明这类的设计不满足单一职责原则:

    • 类中的代码行数、函数或者属性过多;类依赖的其他类过多,或者依赖类的其他类过多;
    • 私有方法过多;
    • 比较难给类起一个合适的名字;
    • 类中大量的方法都是集中操作类中的某几个属性。
  3. 类的职责是否设计得越单一越好?

    单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、低耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。

最后修改:2023 年 03 月 02 日
如果觉得我的文章对你有用,请随意赞赏