为什么80%的码农都做不了架构师?>>>   

上一篇

Open Closed Principle 开放封闭原则

Introduction 介绍

Over the life time of an application, more time is spent adding to the existing codebase rather than constantly adding new features from scratch. As you are probably aware, this can be a tedious and frustrating process. Anytime you modify code, you risk introducing new bugs, or breaking old functionality completely. Ideally, we should be able to modify an existing codebase as quickly and easily as writing brand new code. If we correctly design our application according to the Open Closed principle, we can just do that!

在一个应用的生命周期里,大部分时间都花在了向现有代码库增加功能,而非一直从零开始写新功能。正像你所想的那样,这会是一个繁琐且令人痛苦的过程。当你修改代码的时候,你可能引入新的程序错误,或者将原来管用的功能搞坏掉。理想情况下,我们应该可以像写全新的代码一样,来快速且简单的修改现有的代码。只要采用开放封闭原则来正确的设计我们的应用程序,那么这是可以做到的!

Open Closed Principle 开放封闭原则

The Open Closed principle of SOLID design states that code is open for extension but closed for modification.

开放封闭原则规定代码对扩展是开放的,对修改是封闭的。

In Action 实践

To demonstrate the Open Closed principle, let's continue working with our OrderProcessor from the previous chapter. Consider the following section of the process method:

为了演示开放封闭原则,我们来继续编写上一章节的OrderProcecssor。考虑下面的process方法:

<!-- lang:php -->
$recent = $this->orders->getRecentOrderCount($order->account);if($recent > 0)
{throw new Exception('Duplicate order likely.');
}

This code is quite readable, and even easy to test since we are properly using dependency injection. However, what if our business rules regarding order validation change? What if we get new rules? In fact, what if, as our business grows, we get many new rules? Our process method will quickly grow into a beast of spaghetti code that is hard to maintain. Because this code must be changed each time our business rules change, it is open for modification and violates the Open Closed principle. Remember, we want our code to be open for extension, not modification.

这段代码可读性很高,且因为我们使用了依赖注入,变得很容易测试。然而,如果我们判断订单的规则改变了呢?如果我们又有新的规则了呢?更进一步,如果随着我们的业务发展,要增加一大堆新规则呢?那我们的process方法会很快变成一坨难以维护的浆糊。因为这段代码必须随着每次业务逻辑的改变而跟着改变,它对修改是开放的,这违反了开放封闭原则。记住,我们希望代码对扩展开放,而不是修改。

Instead of performing all of our order validation directly inside the process method, let's define a new interface: OrderValidator:

不必再把订单验证直接写在process方法里面,我们来定义一个新的接口:OrderValidator

<!-- lang:php -->
interface OrderValidatorInterface {public function validate(Order $order);
}

Next, let's define an implementation that protects against duplicate orders:

下一步我们来定义一个实现接口的类,来预防重复订单:

<!-- lang:php -->
class RecentOrderValidator implements OrderValidatorInterface {public function __construct(OrderRepository $orders){$this->orders = $orders;}public function validate(Order $order){$recent = $this->orders->getRecentOrderCount($order->account);if($recent > 0){throw new Exception('Duplicate order likely.');}}
}

Great! Now we have a small, testable encapsulation of a single business rule. Let's create another implementation that verifies the account is not suspended:

很好!我们封装了一个小巧的、可测试的单一业务逻辑。咱们来再创建一个来验证账号是否停用吧:

<!-- lang:php -->
class SuspendedAccountValidator implements OrderValidatorInterface {public function validate(Order $order){if($order->account->isSuspended()){throw new Exception("Suspended accounts may not order.");}}
}

Now that we have two different implementations of our OrderValidatorInterface, let's use them within our OrderProcessor. We'll simply inject an array of validators into the processor instance, which will allow us to easily add and remove validation rules as our codebase evolves.

现在我们有两个不同的类实现了OrderValidatorInterface接口。咱们将在OrderProcessor里面使用它们。我们只需简单的将一个验证器数组注入进订单处理器实例中。这将使我们以后修改代码时能轻松的添加和删除验证器规则。

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

Next, we can simply loop through the validators in the process method:

然后我们只要在process方法里面循环这个验证器数组即可:

<!-- lang:php -->
public function process(Order $order)
{foreach($this->validators as $validator){$validator->validate($order);}// Process valid order...
}

Finally, we will register our OrderProcessor class in the application IoC container:

最后我们在 IoC 容器里面注册OrderProcessor类:

<!-- lang:php -->
App::bind('OrderProcessor', function()
{return new OrderProcessor(App::make('BillerInterface'),App::make('OrderRepository'),array(App::make('RecentOrderValidator'),App::make('SuspendedAccountValidator')));
});

With these few changes, which took only minimal effort to build from our existing codebase, we can now add and remove new validation rules without modifying a single line of existing code. Each new validation rule is simply a new implementation of the OrderValidatorInterface, and is registered with the IoC container. Instead of unit testing a large, unwieldy process method, we can now test each validation rule in isolation. Our code is now open for extension, but closed for modification.

在现有代码里付出些小努力,做一些小改动之后,我们现在可以添加删除新的验证规则而不必修改任何一行现有代码了。每一个新的验证规则就是对OrderValidatorInterface的一个实现类,然后注册进IoC容器里。不必再为那个又大又笨的process方法做单元测试了,我们现在可以单独测试每一个验证规则。现在,我们的代码对扩展是开放的,对修改是封闭的。

Leaky Abstractions 抽象的漏洞

Watch out for dependencies that leak implementation details. An implementation change in a dependency should not require any changes by its consumer. When changes to the consumer are required, it is said that the dependency is "leaking" implementation details. When your abstractions are leaky, the Open Closed principle has likely been broken.

小心那些缺少实现细节的依赖(译者注:比如上面的RecentOrderValidator)。当一个依赖的实现需要改变时,不应该要求它的调用者做任何修改。当需要调用者进行修改时,这就意味着该依赖遗漏了一些实现的细节。当你的抽象有漏洞的话,开放封闭原则就不管用了。

Before processing further, remember that this principle is not a law. It does not state that every piece of code in your application must be "pluggable". For instance, a small application that retrieves a few records out of a MySQL database does not warrant a strict adherence to every design principle you can imagine. Do not blindly apply a given design principle out of guilt as you will likely create an over-designed, cumbersome system. Keep in mind that many of these design principles were created to address common architectural problems in large, robust applications. That being said, don't use this paragraph as an excuse to be lazy!

在我们继续学习前,要记住这些原则不是法律。这不是说你应用中每一块代码都应该是“热插拔”式的。例如,一个仅仅从MySQL检索几条记录的小应用程序,不值得去严格遵守每一条你想到的设计原则。不要盲目的应用设计原则,那样你会造出一个“过度设计”的繁琐的系统。记住这些设计原则是用来解决通用的架构问题,制造大型容错能力强的应用。我就这么一说,你可别把它当作懒惰的借口!

下一篇

转载于:https://my.oschina.net/zgldh/blog/388557

From Apprentice To Artisan 翻译 17相关推荐

  1. From Apprentice To Artisan 翻译 08

    为什么80%的码农都做不了架构师?>>>    上一篇 As Organizer 作为管理工具 One of the keys to building a well architec ...

  2. From Apprentice To Artisan 翻译 19

    为什么80%的码农都做不了架构师?>>>    上一篇 Interface Segregation Principle 接口隔离原则 Introduction 介绍 The Inte ...

  3. 糖果将推翻译手机php切,全球首款翻译手机糖果S20发布 或将终结翻译机

    本报讯 "未来糖果要做的,不仅仅是单纯终结翻译机的市场,让更多的出境游人群享受沟通无障碍的便利,更希望成为消费者心目当中一个有温度.有情怀的品牌.始终从消费者的角度出发来设计手机和智能设备, ...

  4. Android官方文档training中英文翻译目录大全:29篇已翻译,45篇未翻译

    Android官方文档training中英文翻译目录大全:29篇已翻译,45篇未翻译 1. Getting Started Building Your First App: 原文: https://d ...

  5. 七年级上册第七单元task翻译,七上英语1单元task

    初二上英语unit1 task翻译 译文:Kate是我的朋友和我的邻居,我认识他五年了.Kate又高又瘦,有着长头发,她有一张圆脸和一个小鼻子.我喜欢她的在微笑的眼睛,这样让她显得更漂亮,更亲切. K ...

  6. Laravel深入学习5 - 应用架构

    声明:本文并非博主原创,而是来自对<Laravel 4 From Apprentice to Artisan>阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理 ...

  7. Laravel深入学习10 - 里氏替换原则

    声明:本文并非博主原创,而是来自对<Laravel 4 From Apprentice to Artisan>阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理 ...

  8. php 单一职责原则,Laravel深入学习8 - 单一责任原则

    声明:本文并非博主原创,而是来自对<Laravel 4 From Apprentice to Artisan>阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理 ...

  9. php lumen和laravel,Laravel 还是 Lumen?

    Laravel 还是 Lumen?相信有不少人在纠结这个问题,相对来讲,我并不推荐使用 Lumen,因为作者的更新维护很明显还是偏重于 Laravel 的,还有一个理由就是 Laravel 已经包含了 ...

最新文章

  1. centos7 安装mysql php_Centos7安装mysql与php的方法
  2. CentOS 6.5系统下安装和配置NFS服务
  3. 科学计算机怎么调亮度,LED显示器背光很刺眼怎么办?显示器刺眼如何设置?
  4. Oracle编程入门经典 第3章 建立以及管理用户和表
  5. 前端学习(3290):react hook state-hook传入对象
  6. jsp为什么不加虚拟路径都能访问_JavaWeb学习笔记一(环境配置/jsp基本介绍)
  7. Iview的Tabs定时切换
  8. 凭据分配没有加密oracle_远程连接身份验证错误,又找不到加密Oracle修正
  9. Java中的一些基本转换
  10. AnyLogic 教程JobShop—Prcess Modeling Library
  11. 外贸询盘通开篇我的十年SEO探索路
  12. linux mint字体缺失,WPS for Linux【Debian、Ubuntu、Deepin、Linux Mint】字体缺失解决【批量字体安装】...
  13. Visual SourceSafe中的权限管理(转载,已测试)
  14. html如何制作扑克,用css制作扑克牌
  15. 台式计算机截图快捷键,台式电脑怎么用快捷键截图
  16. 关于SysinternalsSuite全部工具详解
  17. 用ADC0809实现八通道采集
  18. 51单片机+LCD12864的万年历Proteus仿真
  19. 冥想|平静与自由之路,给初学者的冥想教程
  20. K8S系列文章之快速入门K8S

热门文章

  1. linux之软连接和硬连接的区别
  2. 在线十六进制颜色随机生成器
  3. RelativeLayout addRule踩坑之旅
  4. ArrayList如何实现增删元素及其缺陷
  5. tp中url地址大小写问题
  6. 1106冒泡排序语法树
  7. MySQL与Oracle的数据迁移注意事项,另附转换工具链接
  8. Android中文API(134) —— Account
  9. repeater中分页aspnetpager是遇到的问题
  10. 88.http反向代理proxy处理请求的流程