文档章节

From Apprentice To Artisan 翻译 16

zgldh
 zgldh
发布于 2015/03/17 22:24
字数 1238
阅读 2109
收藏 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
粉丝 95
博文 35
码字总数 46344
作品 2
高级程序员
私信 提问
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
0
4
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
0
0
From Apprentice To Artisan 翻译 08

上一篇 As Organizer 作为管理工具 One of the keys to building a well architected Laravel application is learning to use service providers as an organizational tool. When you are ......

zgldh
2014/12/09
0
0
From Apprentice To Artisan 翻译 02

上一篇 Taking It Further 更进一步 Let's consider another example to solidify our understanding. Perhaps we want to notify customers of charges to their account. We'll define tw......

zgldh
2014/08/22
0
1
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
0
1

没有更多内容

加载失败,请刷新页面

加载更多

Apache日志不记录访问静态文件,访问日志切割,静态元素过期时间设置

Apache配置不记录访问静态文件的日志 网站大多元素为静态文件,如图片、css、js等,这些元素可以不用记录 vhost原始配置 <VirtualHost *:80> ServerAdmin test@163.com DocumentRoo...

野雪球
45分钟前
1
0
聊聊storm的ICommitterTridentSpout

序 本文主要研究一下storm的ICommitterTridentSpout ICommitterTridentSpout storm-core-1.2.2-sources.jar!/org/apache/storm/trident/spout/ICommitterTridentSpout.java public interface......

go4it
50分钟前
2
0
Ubuntu常用操作

查看端口号 netstat -anp |grep 端口号 查看已使用端口情况 netstat -nultp(此处不用加端口号) netstat -anp |grep 82查看82端口的使用情况 查找被占用的端口: netstat -tln netstat -tl...

hc321
昨天
1
0
网站cdn的静态资源突然访问变的缓慢,问题排查流程

1.首先我查看了一下是否自己的网络问题,通过对比其他资源的访问速度和下载速度,确认不是 2.通过ping 和 tracert 判断cdn域名能否正常访问,(最后回想感觉这一步可以省略,因为每次最终能访...

小海bug
昨天
3
0
Mybatis 学习笔记四 MyBatis-Plus插件

Mybatis 学习笔记四 MyBatis-Plus插件 maven依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <ve......

晨猫
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部