solid 程序设计原则_PHP应用程序中的SOLID设计

solid 程序设计原则

Introduction

介绍

A frequently used term in Object-Oriented design is "SOLID" which is a mnemonic acronym that covers five principles of OO design.  These principles do not stand alone; there is interplay among them.  And they are not laws, merely principles, like "an apple a day keeps the doctor away." But they serve to guide us in the right direction as we design and build our systems.

面向对象设计中经常使用的术语是“ SOLID”,这是一个易记的首字母缩写,涵盖了OO设计的五个原则。 这些原则并不孤单。 它们之间存在相互作用。 它们不是法律,而只是原则,例如“一天吃一个苹果会使医生远离”。 但是,当我们设计和构建系统时,它们可以指导我们朝正确的方向发展。

There are no real "shortcuts" here.  As Euclid said to Ptolemy, who wanted to know the easy way to learn geometry, "There is no royal road to geometry."  So, too, there is no royal road to good object-oriented design. But that said, read on for some of the summary and background information that will make your software designs more coherent and easier to build, test, extend and reuse.

这里没有真正的“捷径”。 正如欧几里德对想了解几何学简单方法的托勒密所说的那样,“没有通往几何学的皇家之路。” 因此,良好的面向对象设计也没有皇家之路。 话虽如此,请继续阅读一些摘要和背景信息,这些信息将使您的软件设计更加协调一致,更易于构建,测试,扩展和重用。

Do I Really Have to Learn This?

我真的必须学习吗?

What happens when these principles are ignored?  Some call it software "rot."  I prefer to think of it in terms of fragility and viscosity.  Software that is of fragile design is difficult to extend or modify.  Even simple changes can induce seemingly unrelated entropy elsewhere in the system (Einstein called this, "spooky action at a distance").  Eventually this phenomenon comes to the attention of the business managers, and they become resistant to change.  Developers become frustrated as micromanagement ensues.  Ultimately the system must be scrapped and re-invented.

忽略这些原则会发生什么? 有人称它为“腐烂”软件。 我更喜欢从远处的怪异动作 ”)。 最终,这种现象引起了业务经理的注意,并且他们变得难以改变。 随之而来的微观管理使开发人员感到沮丧。 最终,该系统必须报废并重新发明。

Software that is viscous can be changed, but only slowly and at great cost.  I recently looked at an application that had 479 instances of long-ago deprecated calls to mysql_query().  Imagine the remediation workload! The owner, in complete denial, said he would handle the problem by doing nothing and keeping the current software as long as he could.  Perhaps he will keep it until his competitors have overtaken him and relieved him of his clients!

对mysql_query()的长时间不赞成使用的调用 。 想象一下修复工作量! 所有者完全否认,他将不采取任何措施并尽可能长时间保留当前软件来解决该问题。 也许他会一直坚持下去,直到他的竞争对手超越他并解除他的客户!

Requirements change and designs must change to accommodate the requirements.  If our designs and implementations cannot change in response to the requirements we do our missions a disservice.  This is true whether we are building a small online store or the web network of the US Army.  The principles of OO design allow our software to make room for change.

需求变更和设计必须更改以适应需求。 如果我们的设计和实现不能根据要求进行更改,那么我们的任务就会受到损害。 无论我们是在建立小型在线商店还是美军的网络,都是如此。 面向对象的设计原理使我们的软件有很大的变化空间。

The S in SOLID.

SOLID中的S。

The S stands for Single Responsibility Principle ("SRP" for short).

S代表单一责任原则 (简称“ SRP”)。

The goal of the SRP is to isolate program functionality into small units of code, each with a single and clear purpose.  The reason for this goal is that it helps us make our programming highly modular and testable.  If a class only does one thing, the unit tests can be both simple and highly accurate -- either the thing is done or not.  It also helps us minimize the effects of program changes, because we would only change the software with functionality that directly related to our changed requirements.  We can thereby avoid "spooky action at a distance."

SRP的目标是将程序功能隔离为小的代码单元,每个单元都有一个明确的目的。 实现此目标的原因是,它有助于我们使编程高度模块化且可测试。 如果一个班级只做一件事情,那么单元测试既可以简单又可以非常准确-无论事情完成与否。 它还将帮助我们最大程度地减少程序更改的影响,因为我们只会使用与更改的需求直接相关的功能来更改软件。 因此,我们可以避免“远距离的怪异动作”。

SRP is formally described by saying that an object should never have more than one responsibility, and that there should never be more than one reason for an object to change.  Corollaries to these rules include, "just because you can doesn't mean you should."  Related concepts include cohesion and coupling.  

SRP的正式描述是,一个对象永远不应该承担一个以上的责任,并且一个对象发生变化的理由也不应不止一个 。 这些规则的推论包括:“仅因为您不能代表您应该这样做”。 相关概念包括内聚和耦合。

Cohesion tells us how strongly-related and focused are the responsibilities of a module (acknowledging that while we want a single responsibility, we will build our collection of objects into modules and systems of multiple functions and responsibilities).  High cohesion is good; our code focuses on only the important things.  

内聚性告诉我们模块的职责与关联和关注度有多紧密(认识到虽然我们只需要一个职责,但我们会将对象集合构建为具有多个功能和职责的模块和系统)。 高内聚性好; 我们的代码只关注重要的事情。

Coupling tells us the degree to which each program module relies on the behavior or internal structure of other modules.  Low coupling is good; our code is written in such a way that we can swap objects or modules with minimal risk that a swap will disrupt the system.  In all things there is a separation of concerns.

耦合告诉我们每个程序模块在多大程度上依赖于其他模块的行为或内部结构。 低耦合好 ; 我们的代码以这样的方式编写:我们可以交换对象或模块,而将交换破坏系统的风险降至最低。 在所有情况下,关注点都是分离的。

The O in SOLID.

SOLID中的O。

The O stands for Open / Closed Principle ("OCP" for short).

O代表开放/封闭原则 (简称“ OCP”)。

The goal of the OCP is to allow us to introduce new behaviors into our system without having to change existing behaviors.  Each change may introduce bugs and requires re-testing, therefore we want to avoid changes that affect the current working parts of our system.  Writing new classes is less likely to introduce intractable problems when compared to changing existing classes.

OCP的目标是允许我们在不更改现有行为的情况下将新行为引入系统。 每次更改都可能会引入错误,并需要重新测试,因此,我们希望避免影响系统当前工作部分的更改。 与更改现有课程相比,编写新课程不太可能带来棘手的问题。

The OCP tells us that our code should be open for extension, but closed for modification.  Code is open to extension if new behavior can be added in the future via extension and inheritance.  Code is closed to modification if new behavior can be added without changing any existing code.

OCP告诉我们,我们的代码应该开放以进行扩展,而封闭以进行修改。 如果将来可以通过扩展和继承添加新行为,则代码对扩展开放。 如果可以在不更改任何现有代码的情况下添加新行为,则该代码不可修改。

How can we change behavior without changing code?  We can rely on abstractions and class extension.  We can couple our code to an interface instead of to a concrete class.  In procedural code, some level of the OCP can be achieved by using parameters that guide different behaviors in a piece of software.  The PHP function library is full of functions that change behaviors when you change parameters.  Do you think these functions adopt the OCP but violate the SRP?  I do!

我们如何在不更改代码的情况下改变行为? 我们可以依靠抽象和类扩展。 我们可以将代码耦合到接口而不是具体的类。 在过程代码中,可以通过使用指导软件中不同行为的参数来实现一定程度的OCP。 PHP函数库充满了可以在更改参数时更改行为的函数。 您是否认为这些功能采用了OCP但违反了SRP? 我做!

To put it another way, once you have written and tested and deployed a class, you're done with it and you should never have to go back to change the class.  If you need more functionality you can extend the class.  See how this plays with the SRP?  If your class is misdesigned and does many things, you might find yourself having to go back into the code to make modifications.  Every such modification requires a new round of testing and risks introducing unwanted side effects ("bugs").

换句话说,一旦编写,测试并部署了一个类,就完成了,并且您永远不必回头更改类。 如果您需要更多功能,则可以扩展该类。 看看SRP如何运作? 如果您的班级设计错误并且做了很多事情,您可能会发现自己不得不回到代码中进行修改。 每一次这样的修改都需要新一轮的测试,并有引入不良副作用(“错误”)的风险。

When we think about programming with the OCP in mind, we often think about writing our programs as if they are intended not only for ourselves, but also for others to use.  We separate our functionality at the obvious points of interface. Perhaps more than any other principle, this states the goal of OO design.

在考虑使用OCP进行编程时,我们经常会考虑编写程序,就像它们不仅是为我们自己,而且还供其他人使用一样 。 我们在界面的明显位置分离了我们的功能。 也许比任何其他原则都更重要,这表明了OO设计的目标。

The L in SOLID.

SOLID中的L。

The L stands for the Liskov Substitution Principle ("LSP" for short).

L代表Liskov替代原理 (简称“ LSP”)。

The goal of the LSP is to allow any module that uses a parent class to also use any derived child class that extends the parent class.  Programming written this way will play well with the OCP and will generally make sense to any programmer who comes to look at the code.  Specifically, child classes must not remove base class behavior or violate base class principles.  If the child class replaces a method of the parent class, the method must still work correctly for all objects created from either the child or parent class.

LSP的目标是允许使用父类的任何模块也可以使用扩展父类的任何派生子类。 以这种方式编写的程序将与OCP配合良好,并且通常对于任何看代码的程序员都有意义。 具体而言,子类不得删除基类行为或违反基类原则。 如果子类替换了父类的方法,则该方法对于从子类或父类创建的所有对象仍然必须正确工作。

The LSP states that subtypes must be substitutable for their base types.  Note that this is not to say that each child "is-a" version of the parent.  It says that each child "is substitutable for" or "behaves like" the parent.  To be effective in substitution, the interfaces between objects should be small and concise.

LSP声明子类型必须可以替代其基本类型。 注意,这并不是说每个孩子都是父母的“是”版本。 它说每个孩子都“可以代替”或“表现得像”父母。 为了有效替代,对象之间的接口应该小而简洁。

Consider refactoring when you find that you have two classes that share a lot of behavior but are not LSP-interchangeable.  Maybe you can think of a third class that both can derive from. 考虑进行重构 。 也许您会想到两者都可以衍生的第三类。

A closely related principle is "Design by Contract," a process that uses preconditions and postconditions to assert the change in state that will be induced by invoking a piece of software.  This is made somewhat more difficult in PHP because of its limited type-hinting abilities.

一个紧密相关的原则是“ 按合同设计 ”,该过程使用前提条件和后置条件来声明状态的变化,该状态变化将由调用某个软件引起。 由于其有限的类型提示功能,这在PHP中变得有些困难。

The I in SOLID.

SOLID中的I。

The I stands for the Interface Segregation Principle ("ISP" for short).

I代表接口隔离原理 (简称“ ISP”)。

The goal of ISP is to keep our code down to the minimum required to provide the required functionality.  "Fat" interfaces are a disadvantage because the implementing classes contain too much code and may be slow to load or difficult to test.

ISP的目标是使我们的代码降至提供所需功能所需的最低限度。 “胖”接口是一个缺点,因为实现类包含太多代码,并且可能加载缓慢或难以测试。

Clients should not be forced to depend on information or methods they do not use.  A classic example is the reliance on a large configuration settings class, when all a web page really needs is the Title and the name of the Author.  The web page is coupled to unnecessary information, reducing speed, flexibility, and maintainability.  ISP code smells include unimplemented interface methods.  They often violate the LSP, too.  A good way forward when you encounter ISP smells might be to create a new, smaller interface.  Since PHP has extendable interfaces, we have a good tool available for designs that need interface segregation.

不应强迫客户依赖他们不使用的信息或方法。 一个典型的例子是,当一个网页真正需要的是标题和作者姓名时,就依赖于大型配置设置类。 网页与不必要的信息耦合,从而降低了速度,灵活性和可维护性。 ISP代码的气味包括未实现的接口方法。 它们也经常违反LSP。 遇到ISP气味时,一种好的解决方法可能是创建一个新的较小的接口。 由于PHP具有可扩展的接口 ,因此我们为需要接口隔离的设计提供了一个很好的工具。

The D in SOLID.

SOLID中的D。

The D stands for the Dependency Inversion Principle ("DIP" for short).

D代表依赖倒置原则 (简称“ DIP”)。

At the time it was coined, "dependency inversion" was so named because hard-coupled dependencies were the norm in programming, and the principle inverted that norm.  Today, I would call it the "dependency independence principle."  If OCP states the goal of OO design, then DIP teaches us how to achieve that goal.  Formally stated, "High-level modules should not depend on low-level modules; both should depend on abstractions.  And abstractions should not depend on details; details should depend on abstractions."  The goal here is to produce software that is loosely coupled and not brittle or rigid.  

当时,“依赖倒置”之所以被命名是因为硬耦合的依赖是编程中的规范,而原理则颠倒了该规范。 今天,我将其称为“依赖独立性原则”。 如果OCP规定了OO设计的目标,那么DIP会教我们如何实现该目标。 正式声明:“高级模块不应依赖于低级模块;两者都应依赖于抽象。抽象不应依赖于细节;细节应依赖于抽象。” 这里的目标是生产松散耦合且不易碎或不牢固的软件。

The classic analogy of depending on an abstracted interface is the notion of a lamp and an electrical supply in your home.  You could solder the lamp wires to the electrical wires and the lamp would work, but there is a better way through the interface that is provided by the electrical outlet.  The lamp makers agree with the home builders on the design of the interface.  Lamps come with plugs, homes come with sockets.  The resulting implementation is flexible; any lamp can work in any room of the house.  

依赖抽象接口的经典比喻是您家中的灯和电源的概念。 您可以将灯丝焊接到电线上,然后灯可以工作,但是有一种更好的方法可以通过电源插座提供的接口。 灯具制造商在接口的设计上与房屋建筑商一致。 灯带有插头,房屋带有插座。 最终的实现是灵活的; 任何灯都可以在房屋的任何房间工作。

To see this in software, consider a User class that runs a Database query; the User and Database are tightly coupled.  A change in the Database will necessitate a change in the User.  These separate responsibilities can be decoupled and made independent with an interface.  Properly designed, the User class does not need to know where the user information came from (it could come from any correct version of the acceptable data source), it only needs to know that its data source conforms to the interface.

要在软件中查看此信息,请考虑运行数据库查询的User类; 用户和数据库紧密耦合。 数据库中的更改将有必要更改用户。 这些单独的职责可以通过接口分离并独立。 经过适当设计的User类不需要知道用户信息来自何处(它可以来自可接受数据源的任何正确版本 ),只需要知道其数据源符合该接口即可。

Classes should declare their need for dependencies.  A class that contains the keyword "new" inside the constructor has created an internal dependency on a low-level module.  These classes become difficult or impossible to test without violating the OCP.  In contrast, a class that uses dependency injection can be tested with mock objects.  Though beyond the scope of this article, you might want to learn more about 类应该声明对依赖的需求 。 在构造函数内部包含关键字“ new”的类已在低级模块上创建了内部依赖项。 在不违反OCP的情况下,很难测试或无法测试这些类。 相反,可以使用模拟对象测试使用依赖注入的类。 尽管超出了本文的范围,您可能想了解更多有关 Inversion of Control Containers. Inversion of Control Containers的信息

Summary

摘要

In the decades since software development began, we have come upon several inflection points that mark giant leaps forward in the state of the art.  Early compilers moved our work beyond "machine language" and thereby engendered one of these paradigm shifts.  The development of object-oriented programming and the discernment of the SOLID principles are among today's most important advances in the field.

自软件开发开始以来的几十年中,我们遇到了几个转折点,这标志着巨人在最新技术水平上的飞跃。 早期的编译器使我们的工作超出了“机器语言”的范围,从而引发了这些范式转变之一。 面向对象编程的开发和SOLID原理的识别是该领域当今最重要的进步。

References and Further Reading

参考资料和进一步阅读

http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf http://blog.ircmaxell.com/ http://blog.ircmaxell.com/ http://www.pmg.csail.mit.edu/barbara_liskov.html http://www.pmg.csail.mit.edu/barbara_liskov.html http://www.objectmentor.com/omTeam/martin_r.html http://www.objectmentor.com/omTeam/martin_r.html http://www.brandonsavage.net/category/solid/ http://www.brandonsavage.net/category/solid/ http://www.martinfowler.com/articles/injection.html http://www.martinfowler.com/articles/injection.html

Please give us your feedback!

请给我们您的反馈意见!

If you found this article helpful, please click the "thumb's up" button below. Doing so lets the E-E community know what is valuable for E-E members and helps provide direction for future articles.  If you have questions or comments, please add them.  Thanks!

如果您发现本文有帮助,请单击下面的“竖起大拇指”按钮。 这样做可以使EE社区了解对EE成员有价值的内容,并为将来的文章提供指导。 如果您有任何问题或意见,请添加。 谢谢!

翻译自: https://www.experts-exchange.com/articles/18329/SOLID-Design-in-PHP-Applications.html

solid 程序设计原则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值