繁杂的场景下如何坚守 “单一职责准则” (上)?

作者 : 开心源码 本文共3445个字,预计阅读时间需要9分钟 发布时间: 2022-05-13 共234人阅读

设计准则能够帮助我们发现程序中的问题,并能够促使程序代码看上去清晰明了。

设计准则有很多,经常用到的有以下5个:

1. 单一职责准则;2. 开放封闭准则;3. 里氏替换准则;4. 依赖倒置准则;5. 接口隔离准则;

在实践中发现TDD的开发方式能够更容易维护一个相对单一的职责。相关阅读:《为什么那些人选择TDD这种方式开发?》

这些准则的组合使用,能够实现代码上的高内聚、低耦合、易修改。这篇文章将聚焦设计准则中的单一职责准则。

单一职责准则指对一个类或者者一个方法而言,引起其变化的只有一个起因。

什么是职责?

职责可以被定义为“变化的起因”,假如你能够想到多于一个动机去改变类,那么这类就具备多于一个的职责。这是较为严格的定义。

知易行难,工作中我们会遇到多种场景,以下列举了3中场景:

1. 有的场景由于简单我们会始终坚持单一职责准则;2. 有的场景略微复杂,注意力有可能就被转移到某个环节,而忽略了单一职责准则;3. 还有少量场景,对这是一个类或者者一个方法是职责是一个还是多个会犹豫不决。

我们不妨通过一个例子来看看如何保持一个类或者者方法的职责单一。

需求

这是一个被简化了的需求

创立订单:将商品,收件人名称、电话、地址保存到订单信息

实现

单考虑单一职责准则,我们可以用下面的实现方法。

Order.java

public class Order {    private String id;    private String productId;    private String consignee;    private String consigneePhoneNumber;    private String consigneeAddress;}

OrderService.java

@Servicepublic class OrderService {    @Autowired    private OrderRepository orderRepository;        public void createOrder(Order order) {        orderRepository.save(order);    }}

在上面的例子中,OrderService.java包含一个方法createOrder职责算是单一的,由于引起变化的起因和订单订单相关。

由于上面的场景足够的简单,所以很容易表现单一职责准则。那么,更具业务稍加修改就能让这个类的职责不在再是职责单一的类。

假设新需求要求,创立订单前应该扣减库存,你会怎样改这段代码呢?

下面我列举了三种常见的修改代码的方法,你看看哪种符合单一职责准则。

修改方法一

假如你只是在createOrder中增加几行,例如下面的代码

    public void createOrder(Order order) {        Product product = productRepository.findOne(order.getProductId());        product.setCount(product.getCount()--);        productRepository.save(product);            orderRepository.save(order);    }

是不是着个方法职责变多了。查询商品,扩建商品数量,保存商品最新信息,保存订单。引起这个类变化的起因不再是order了,同时product相关信息的变化都会引起变化。

修改方法二

方法一,中有一扣减库存的实现不应该出现在OrderService中,应该单独抽离抽离出去,修改方法是这样的。

@Servicepublic class OrderService {    @Autowired    private OrderRepository orderRepository;        @Autowired    private ProductService productService;        public void createOrder(Order order) {        productService.deductInventory(order.getProductId());        orderRepository.save(order);    }}

ProductService.java

@Servicepublic class ProductService {    @Autowired    product ProductRepository productRepository;        public void deductInventory(String productId) {        Product product = productRepository.findOne(order.getProductId());        product.setCount(product.getCount()--);        productRepository.save(product);    }}

这个修改方法的确将扣减库存的职责抽离了出去,由ProductService来承担变化的响应。但是OrderService中的createOrder方法仍旧职责不够单一,方法二相比于方法二,只是职责上转变了,由方法一的维护扣减逻辑过程变成了调度扣减,所以一旦发生发辫一起OrderService发生变化的依旧不止一个。那么再来看看方法三。

修改方法三

在《Clean Code》中形容方法职责的形容:

方法应该只做一件事,做好一件事,只做一件事。

翻译的这么重复,就是在强调一个方法只做一件事。假如不加任何限制,你会发现这一件事可大可小,事情太大仍旧是职责不单一。那么怎样办呢?

假如方法只做了该方法名下同一个笼统层及上的步骤,则函数还是只做了一件事。

为了更好的了解这句话,一上面的需求为例,创立订单可以认为是经历了两个步骤:扣减商品库存、保存订单信息。所以这两个步骤应该是在一个笼统层级上的。而具体扣减逻辑、订单保存的实现都是另外一个更细粒度的层级上的。

OrderContext.java

@Servicepublic class OrderContext {    @Autowired    private OrderService orderService;        @Autowired    private productService productService;        public void generateOrder(Order order) {        productService.deductInventory(order.getProductId());                orderService.createOrder(order);    }}

OrderService.java

@Servicepublic class OrderService {    @Autowired    private OrderRepository orderRepository;        @Autowired    private ProductService productService;        public void createOrder(Order order) {        orderRepository.save(order);    }}

ProductService.java

@Servicepublic class ProductService {    @Autowired    product ProductRepository productRepository;        public void deductInventory(String productId) {        Product product = productRepository.findOne(order.getProductId());        product.setCount(product.getCount()--);        productRepository.save(product);    }}

通过上面的OrderService和ProductService保持单一的职责。但是OrderContext保持了相对单一则职责:创立订单是调度作用。但是似乎也并不完美,由于造成修改的起因不止一个。

那么不得不说方法四了,使用观察者模式。建议不对职责进行拆分。因为时间起因,暂时不上代码,后续将代码不上。

为了更加真实,我准备了下面这样一个场景,后续会更上代码和分析,现在就当作一道思考题吗,假如面对下面这个场景,你如何组织代码,保持单一职责准则?

需求场景:订单下单时涉及到以下相关业务操作:1. 价格计算;2. 优惠券扣除;3. 积分扣除;4. 新积分计算;5. 新积分添加;6. 将订单中的商品从购物车商品消除;7. 生成订单;8. 启动30分钟反馈记时。

假如上文中有什么不对的地方,欢迎指正~。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 繁杂的场景下如何坚守 “单一职责准则” (上)?

发表回复