文档章节

From Apprentice To Artisan 翻译 01

zgldh
 zgldh
发布于 2014/08/11 14:47
字数 1667
阅读 16125
收藏 20

回到目录

 

Dependency Injection 依赖注入

The Problem 遇到的问题

The foundation of the Laravel framework is its powerful IoC container. To truly understand the framework, a strong grasp of the container is necessary. However, we shold note that an IoC container is simply a convenience mechanism for achieving a software design pattern: dependency injectionl. A container is not necessary to perform dependency injection, it simply makes the task easier.

Laravel框架的基 础是一个功能强大的控制反转容器(IoC container)。 为了真正理解本框架,需要好好掌握该容器。但我们要搞清楚,控制反转容器只是一种用于方便实现“依赖注入”的工具。要实现依赖注入并不一定需要控制反 转容器,只是用容器会更方便和容易一点儿。

 

First, let's explore why dependency injection is beneficial. Consider the following class and method:

首先来看看我们为何要使用依赖注入,它能带来什么好处。 考虑下列代码:

class UserController extends BaseController{
    public function getIndex()
    {
        $users= User::all();
        return View::make('users.index', compact('users'));
    }
}

 

 

 

While this code is concise, we are unable to test it without hitting an actual database. In other words, the Eloquent ORM is tightly coupled to out controller. We have no way to use or test this controller without also using the entire Eloquent ORM, including hitting a live database. This code also violates a software design principle commonly called separation of concerns. Simple put: our controller knows too much. Controllers do not need to know where data comes from, but only how to access it. The controller doesn't need to know that the data is available in MySQL, but only that it is available somewhere.

这段代码很 简短,但我们要想测试这段代码的话就一定会和实际的数据库发生联系。也就是说, Eloquent ORM(译者注:Laravel的数据库对象模型库)和该控制器有着紧耦合。如果不使用Eloquent ORM,不连接到实际数据库,我们就没办法运行或者测试这段代码。这段代码同时也违背了“关注分离”这个软件设计原则。简单讲:这个控制器知道的太多了。 控制器不需要去了解数据是从哪儿来的,只要知道如何访问就行。控制器也不需要知道这数据是从MySQL或哪儿来的,只需要知道这数据目前是可用的。

Separation Of Concerns    关注分离

Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

每一个类都应该有单独的职责,并且该职责应完全被这个类封装。(译者注:我认为就是不要让多个类负责同样的职责)

   

So, it will be beneficial for us to decouple our web layer (controller) from our data access layer completely. This will allow us to migrate storage implementations easily, as well as make our code easier to test. Think of the "Web" as just a transport layer into your "real" application.

关注分离的好处就是能让Web控制器和数据访问解耦。这会使得实现存储迁移更容易,测试也会更容易。“Web”就仅仅是为你真正的应用做数据的传输了。

 

Imagine that your application is like a monitor with a variety of cable ports. You can access the monitor's functionality via HDMI, VGA, or DVI. Think of the Internet as just a cable into your application. The bulk of a monitor's functionality is independent of the cable. The cable is just a transport mechanism just like HTTP is a transport mechanism for your application. So, we don't want to clutter up our transport mechanism (the controller) with application logic. This will allow any transport layer, such as an API or mobile application, to access our application logic.

想象一下你有一个类似于监视器的程序,有着很多线缆接口(HDMI,VGA,DVI等等)。 你可以通过不同的接口访问不同的监视器。把Internet想象成另一个插进你程序线缆接口。大部分显示器的功能是与线缆接口互相独立的。线缆接口只是一 种传输机制就像HTTP是你程序的一种传输机制一样。所以我们不想把传输机制(控制器)和业务逻辑混在一起。这样的好处是很多其他的传输机制比如API调 用、移动应用等都可以访问我们的业务逻辑。

 

So, instead of coupling our controller to the Eloquent ORM, let's inject a repository class.

那么我们就别再将控制器和Eloquent ORM耦合在一起了。 咱们注入一个资料库类。

 

Build A Contract 建立约定

First, we'll define an interface and a corresponding implementation:

首先我们定义一个接口,然后实现该接口。

interface UserRepositoryInterface
{
    public function all();
}
  
class DbUserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all()->toArray();
    }
}

 

 

Next, we'll inject an implementation of this interface into our controller:

然后我们将该接口的实现注入我们的控制器。

 

class UserController extends BaseController
{
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }
  
    public function getIndex()
    {
        $users=$this->users->all();
        return View::make('users.index', compact('users'));
    }
}

 

 

 

Now our controller is completely ignorant of where our user data is being stored. In this case, ignorance is bless! Our data could be coming from MySQL, MongoDB, or Redis. Our controller doesn't know the difference, nor should it care. Just by making this small change, we can test our web layer independent of our data layer, as well as easily switch our storage implementation.

现在我们的控制器就完全和数据层面无关了。在这里无知是福!我们的数据可能来自MySQL,MongoDB或者Redis。我们的控制器不知道也不需要知道他们的区别。仅仅做出了这么小小的改变,我们就可以独立于数据层来测试Web层了,将来切换存储实现也会很容易。

Respect Boundaries 严守边界

Remember to respect responsibility boundaries. Controllers and routes serve as a mediator between HTTP and your application. When writing large applications, don't clutter them up with your domain logic.

记得要保持清晰的责任边界。 控制器和路由是作为HTTP和你的应用程序之间的中间件来用的。当编写大型应用程序时,不要将你的领域逻辑混杂在其中(控制器、路由)。

 

To solidify our understanding, let's write a quick test. First, we'll mock the repository and bind it to the application IoC container. Then, we'll ensure that the controller properly calls the repository:

为了巩固学到的知识,咱们来写一个测试案例。首先,我们要模拟一个资料库然后绑定到应用的IoC容器里。 然后,我们要保证控制器正确的调用了这个资料库:

 

public function testIndexActionBindsUsersFromRepository()
    {    
        // Arrange...
        $repository = Mockery::mock('UserRepositoryInterface');
        $repository->shouldReceive('all')->once()->andReturn(array('foo'));
        App::instance('UserRepositoryInterface', $repository);
        // Act...
        $response  = $this->action('GET', 'UserController@getIndex');
        
        // Assert...
        $this->assertResponseOk();
        $this->assertViewHas('users', array('foo'));
    }

Are you Mocking Me 你在模仿我么?

In this example, we used the `Mockery` mocking library. This library provides a clean, expressive interface for mocking your classes. Mockery can be easily insalled via Composer.

在上面的例子里, 我们使用了名为`Mockery`的模仿库。 这个库提供了一套整洁且富有表达力的方法,用来模仿你写的类。 Mockery可以通过Composer安装。

 下一章:https://my.oschina.net/zgldh/blog/305556 

© 著作权归作者所有

共有 人打赏支持
zgldh
粉丝 96
博文 36
码字总数 47009
作品 2
高级程序员
私信 提问
加载中

评论(6)

北极熊没穿毛衣
关于关注分离那个“译者注 ”我认为应该是:一个类只实现单一功能,不要在一个类中实现过多用途不一致的方法。单一类单一用途。
7
736074781
内容很赞,建议加一个下一篇的链接,或者在侧边加个目录,这样翻篇就很方便了
杨立景
杨立景
👍
奋斗的快意
奋斗的快意
好文章,对于深入理解面向对象和Laravel框架大有裨益!
苏生不惑
苏生不惑
赞+1
Yuansir
Yuansir
很赞,等翻译完搞个PDF版就完美了
From Apprentice To Artisan 翻译 16

上一篇 Single Responsibility Principle 单一职责原则 Introduction 介绍 The "SOLID" design principles, articulated by Robert "Uncle Bob" Martin, are five principles that provide ......

zgldh
2015/03/17
0
0
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
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
0
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
0
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
0
4

没有更多内容

加载失败,请刷新页面

加载更多

EOS docker开发环境

使用eos docker镜像是部署本地EOS开发环境的最轻松愉快的方法。使用官方提供的eos docker镜像,你可以快速建立一个eos开发环境,可以迅速启动开发节点和钱包服务器、创建账户、编写智能合约....

汇智网教程
今天
3
0
《唐史原来超有趣》的读后感优秀范文3700字

《唐史原来超有趣》的读后感优秀范文3700字: 作者:花若离。我今天分享的内容《唐史原来超有趣》这本书的读后感,我将这本书看了一遍之后就束之高阁了,不过里面的内容一直在在脑海中回放,...

原创小博客
今天
6
0
IC-CAD Methodology知识图谱

CAD (Computer Aided Design),计算机辅助设计,指利用计算机及其图形设备帮助设计人员进行设计工作,这个定义同样可以用来近似描述IC公司CAD工程师这个岗位的工作。 早期IC公司的CAD岗位最初...

李艳青1987
今天
7
0
CompletableFuture get方法一直阻塞或抛出TimeoutException

问题描述 最近刚刚上线的服务突然抛出大量的TimeoutException,查询后发现是使用了CompletableFuture,并且在执行future.get(5, TimeUnit.SECONDS);时抛出了TimeoutException异常,导致接口响...

xiaolyuh
今天
5
0
dubbo 搭建与使用

官网:http://dubbo.apache.org/en-us/ 一,安装监控中心(可以不安装) admin管理控制台,monitor监控中心 下载 bubbo ops 这个是新版的,需要node.js环境,我没有就用老版的了...

小兵胖胖
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部