设计原则——单一职责原则

单一职责原则

单一职责(Single Responsibility Principle)指的是: 一个类或者一个模块只负责完成一个职责。这个原则描述的对象有两个,一个是类(class),一个是模块(module)

模块的概念:

  • 模块可以看成比类增加抽象的概念,类也可以看成模块
  • 模块可以看成比类更加粗粒度的代码块,模块中可以包含多个类

单一职责的定义非常简单,一个类只负责一个职责或者功能,不能设计大而全的类,而是要设计粒度小、功能单一的类。如果一个类包含了两个或者两个以上业务不相干的功能,那么它的职责就不够单一,应该把它拆分成多个粒度更细、功能更加单一的类。

比如: 一个类里既包含订单的一些操作,又包含用户的一些操作。而订单和用户是两个独立的业务领域模型,我们将两个不相干的功能放到同一个类中,那就违反了单一职责原则。为了满足单一职责原则,我们需要将这个类拆分成两个粒度更细、功能更加单一的两个类:订单类和用户类

单一职责的应用

判断类的设计是否符合单一职责

例如在一个社交产品中,我们使用UserInfo类来记录用户的信息,那么这个UserInfo类是否符合单一职责原则呢?

class UserInfo
{
private:
     long user_id;
     long create_time;
     long last_login_time;
     std::string user_name;
     std::string email;
     std::string telephone;
     std::string avatar_url;
     //省
     std::string province;
     //市
     std::string city;
     //区
     std::string region;
     //详细地址
     std::string detaile_address;
};

对于这个问题,有两种不同的观点。一种观点是:UserInfo类中包含的都是和用户相关的信息,所有的属性和方法都隶属于用户这样一个业务模型,满足单一职责原则。另一种观点是:地址信息在UserInfo类中,所占比重较高,可以继续拆分成独立的UserAddress类,拆分之后的两个类的职责更加单一。

实际上要从中做出选择,不能脱离具体的应用场景,如果这个在社交产品中,用户的地址信息和其他信息一样,只是单纯地用来展示,那么UserInfo现在的设计就是合理的。但是,如果这个产品发展的比较好,之后又在产品中添加了电商模块,用户的地址信息还会在电商物流中,那么最好将地址信息从UserInfo类中拆分出来。

终上所述,评价一个类的职责是否足够单一,我们并没有一个非常明确的,可以量化的标准,可以说,这是件非常主观、仁者见仁智者见智的事情,在软件开发中,我们也没必要过于未雨绸缪,过度设计。所以,我们可以先写一个粗粒度的类,满足业务需求、随着业务发着,如果组粒度的类越来越大,代码越来越多,这个时候我们就可以将这个粗粒度的类,拆分成几个更细粒度的类,这就是持续重构

判断原则

下面这几条判断原则,比起很主观地去思考类是否职责单一,要更有指导意义、更具有可执行性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值