文档章节

From Apprentice To Artisan 翻译 16

zgldh
 zgldh
发布于 2015/03/17 22:24
字数 1238
阅读 2529
收藏 1

上一篇

Single Responsibility Principle 单一职责原则

Introduction 介绍

The "SOLID" design principles, articulated by Robert "Uncle Bob" Martin, are five principles that provide a good foundation for sound application design. The five principles are:

罗伯特“鲍勃叔叔”马丁阐述了名为“坚实”的一些设计原则(译者注:看下面五个原则的首字母正是 SOLID)。这些都是制作完善的程序设计的优秀基础,一共有五个原则:

  • The Single Responsibility Principle 单一职责原则
  • The Open Closed Principle 开放封闭原则
  • The Liskov Substitution Principle 里氏替换原则
  • The Interface Segregation Principle 接口隔离原则
  • The Dependency Inversion Principle 依赖反转原则

Let's explore each of these principles in more depth, and look at some code examples illustrating each principle. As we will see, each principle compliments the others, and if one principle falls, most, if not all, of the others do as well.

让我们深入探索一下,再看点代码样例来说明各个原则。我们将看到,每个原则之间都有联系。如果其中一个原则没有被遵循,那么其他大部分(可能不会是全部)的原则也会出问题。

In Action 实践

The Single Responsibility Principle states that a class should have one, and only one, reason to change. In other words, a class' scope and responsibility should be narrowly focused. As we have said before, ignorance is bliss when it comes to class responsibilities. A class should do its job, and should not be affected by changes to any of its dependencies.

单一职责原则规定一个类有且仅有一个理由使其改变。换句话说,一个类的功能边界和职责应当是十分狭窄且集中的。我们之前就提到过,在类的职责问题上,无知是福。一个类应当做它该做的事儿,并且不应当被它的依赖的任何变化所影响到。

Consider the following class:

考虑下列类:

<!-- lang: php -->
class OrderProcessor {
    public function __construct(BillerInterface $biller)
    {
        $this->biller = $biller;
    }
    public function process(Order $order)
    {
        $recent = $this->getRecentOrderCount($order);
        if($recent > 0)
        {
            throw new Exception('Duplicate order likely.');
        }
        
        $this->biller->bill($order->account->id, $order->amount);
        
        DB::table('orders')->insert(array(
            'account'    =>    $order->account->id,
            'amount'    =>    $order->amount,
            'created_at'=>    Carbon::now()
        ));
    }
    protected function getRecentOrderCount(Order $order)
    {
        $timestamp = Carbon::now()->subMinutes(5);
        return DB::table('orders')->where('account', $order->account->id)
                                                ->where('created_at', '>=', $timestamps)
                                                ->count();
    }
}

What are the responsibilities of the class above? Obviously, its name implies that it is responsible for processing orders. But, based on the getRecentOrderCount method, we can also see that it is responsible for examining an account's order history in the database in order to detect duplicated orders. This extra validation responsibility means that we must change our order processor when our data store changes, as well as when our order validation rules change.

上面这个类的职责是什么?很显然顾名思义,它是用来处理订单的。不过由于getRecentOrderCount这个方法的存在,这个类就有了在数据库中审查某帐号订单历史来看有没有重复订单的职责。这个额外的验证职责意味着当我们的存储方式改变或当订单验证规则改变时,我们的这个订单处理器也要跟着改变。

We should extract this responsibility into another class, such as an OrderRepository:

我们必须将这个职责抽离出来放到另外的类里面,比如放到OrderRepository

<!-- lang:php -->
class OrderRepository {
    public function getRecentOrderCount(Account $account)
    {
        $timestamp = Carbon::now()->subMinutes(5);
        return DB::table('orders')->where('account', $account->id)
                                                ->where('created_at', '>=', $timestamp)
                                                ->count();
    }

    public function logOrder(Order $order)
    {
        DB::table('orders')->insert(array(
            'account'    =>    $order->account->id,
            'amount'    =>    $order->amount,
            'created_at'=>    Carbon::now()
        ));
    }
}

Then, we can inject our repository into the OrderProcessor, alleviating it of the responsibility of researching an account's order history:

然后我们可以将我们的资料库(译者注:OrderRepository )注入到OrderProcessor里,帮后者承担起对账户订单历史的处理责任:

<!-- lang:php -->
class OrderProcessor {
    public function __construct(BillerInterface $biller, OrderRepository $orders)
    {
        $this->biller = $biller;
        $this->orders = $orders;
    }

    public function process(Order $order)
    {
        $recent = $this->orders->getRecentOrderCount($order->account);

        if($recent > 0)
        {
            throw new Exception('Duplicate order likely.');
        }

        $this->biller->bill($order->account->id, $order->amount);

        $this->orders->logOrder($order);
    }
}

Now that we have abstracted our order data gathering responsibilities, we no longer have to change our OrderProcessor when the method of retrieving and logging orders changes. Our class responsibilities are more focused and narrow, providing for cleaner, more expressive code, and a more maintainable application.

现在我们提取出了收集订单数据的责任,当读取和写入订单的方式改变时,我们不再需要修改OrderProcessor这个类了。我们的类的职责更加的专注和精确,这提供了一个更干净、更有表现力的代码,同时也是更容易维护的代码。

Keep in mind, the Single Responsibility Principle isn't just about less line of code, it's about writing classes that have a narrow responsibility, and a cohesive set of available methods, so make sure that all of the methods in a class are aligned with the overall responsibility of that class. After building a library of small, clear classes with well defined responsibilities, our code will be more decoupled, easier to test, and friendlier to change.

请记住,单一职责原则的关键不仅仅是让函数变短,而是写出职责更精确更高内聚的类,所以要确保类里面所有的方法都属于该类的职责之下的。在建立一个小巧、清晰且职责明确的类库以后,我们的代码会更加解耦,更容易测试,并且更易于更改。

下一篇

© 著作权归作者所有

zgldh
粉丝 102
博文 36
码字总数 47009
作品 2
高级程序员
私信 提问
From Apprentice To Artisan 翻译 10

上一篇 Application Structure 应用结构 Introduction 介绍 Where does this class belong? This question is extremely common when building applications on a framework. Many develope......

zgldh
2014/12/29
12K
1
From Apprentice To Artisan 翻译 04

上一篇 Reflect Resolution 反射解决方案 One of the most powerful features of the Laravel container is its ability to automatically resolve dependencies via reflection. Reflection......

zgldh
2014/10/08
3.3K
0
From Apprentice To Artisan 翻译 03

上一篇 The IoC Container 控制反转容器 Basic Binding 基础绑定 Now that we've learned about dependency injection, let's explore inversion of control containers.IoC containers make......

zgldh
2014/09/08
6.2K
0
From Apprentice To Artisan 翻译 20

上一篇 Dependency Inversion Principle 依赖反转原则 Introduction 介绍 We have reached our final destination in our overview of the five SOLID design principles! The final princip......

zgldh
2015/03/19
2.1K
5
From Apprentice To Artisan 翻译 17

上一篇 Open Closed Principle 开放封闭原则 Introduction 介绍 Over the life time of an application, more time is spent adding to the existing codebase rather than constantly addi......

zgldh
2015/03/18
2.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

iptables删除命令中的相关问题

最近在做一个中间件的配置工作,在配置iptables的时候,当用户想删除EIP(即释放当前连接),发现使用iptables的相关命令会提示错误。iptables: Bad rule (does a matching rule exist in t...

xiangyunyan
54分钟前
4
0
IT兄弟连 HTML5教程 HTML5表单 新增的表单属性1

HTML5 Input表单为<form>和<input>标签添加了几个新属性,属性如表1。 1 autocomplete属性 autocomplete属性规定form或input域应该拥有自动完成功能,当用户在自动完成域中开始输入时,浏览器...

老码农的一亩三分地
今天
7
0
OSChina 周五乱弹 —— 葛优理论+1

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐# 分享米津玄師的单曲《LOSER》: mv中的舞蹈诡异却又美丽,如此随性怕是难再跳出第二次…… 《LOSER》-...

小小编辑
今天
1K
23
nginx学习笔记

中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。 是连接两个独立应用程序或独立系统的软件。 web请求通过中间件可以直接调用操作系统,也可以经过中间件把请求分发到多...

码农实战
今天
7
0
Spring Security 实战干货:玩转自定义登录

1. 前言 前面的关于 Spring Security 相关的文章只是一个预热。为了接下来更好的实战,如果你错过了请从 Spring Security 实战系列 开始。安全访问的第一步就是认证(Authentication),认证...

码农小胖哥
今天
16
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部