许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Fluent界面控件:使用流畅界面设计模式使代码更简洁易读

Fluent界面控件:使用流畅界面设计模式使代码更简洁易读

阅读数 1
点赞 0
article_banner

fluent 界面控件

The Fluent Interface Design Pattern

流利的界面设计模式

You can use the Fluent Interface design pattern to make your PHP code easier to read and maintain.  "Fluent Interface" is an object-oriented design pattern that resembles message handling, where a message is passed from program to program, with each program adding a bit of value to the message.  It was first given its name about a decade ago by Martin Fowler, and is now in wide use in the PHP world, considered a "best practice" by industry leaders.  Fluent design allows us to do rapid application development with Laravel, and facilitates formalized automated application testing with PHPUnit.  One of the defining principles of the design pattern is code that is "primarily designed to be readable and to flow."  One of the most delightful effects of using a Fluent Interface design is the elegant simplicity of method chaining.

您可以使用Fluent Interface设计模式使您PHP代码更易于阅读和维护。 “ Fluent接口”是一种类似于消息处理的面向对象的设计模式,在该模式中,消息从一个程序传递到另一个程序,每个程序都为该消息添加一些值。 它大约是十年前由Martin Fowler命名的,现在在PHP世界中被广泛使用,被业界领导者视为“最佳实践”。 流利的设计使我们能够使用Laravel进行快速的应用程序开发,并借助PHPUnit促进形式化的自动化应用程序测试 。 设计模式的定义原则之一是“最初设计为易于阅读和流动的代码”。 使用Fluent接口设计最令人愉悦的效果之一就是方法链接的优雅简洁性。

Before we see a Fluent Interface in practice, let's look at some programming activities we have all encountered before, and the steps (and missteps) we have used to solve our problems.  A good example is the Address Book or Contact Directory.  When we start writing this application, we think, "Well, I need names and phone numbers."  And that is fine for starters, but right after you get it all set up, the boss comes in.  "Don't forget that you also need email addresses."  

在实践中看到Fluent接口之前,让我们看一下之前所有遇到的编程活动,以及用于解决问题的步骤(和错误步骤)。 通讯录或联系人目录就是一个很好的例子。 当我们开始编写此应用程序时,我们会想到:“好,我需要姓名和电话号码。” 这对初学者来说很好,但是当您完成所有设置后,老板就会加入。“别忘了,您还需要电子邮件地址。”

OK, no problem, we can add that field to our data model.

好的,没问题,我们可以将该字段添加到我们的数据模型中。

Here's what an original data model might look like (in prototype):

这是原始数据模型的外观(在原型中):

<?php$name = 'Ray';$phone = '703.555.1212';$email = 'ray@gmail.com';

Of course, we will need more than one name in our directory.

当然,我们的目录中将需要多个名称。

<?php$name1 = 'Ray';$phone1 = '703.555.1212';$email1 = 'ray@gmail.com'; $name2 = 'Toby';$phone2 = '703.555.1212';$email2 = 'toby@gmail.com'; $name3 = 'Lucky';// NOTICE THAT THERE IS NO PHONE #3$email3 = 'lucky@gmail.com';

Wow, that is going to get unwieldy fast!  Any time you have a proliferation of variables in your code, you know something is wrong.  Usually the first bit of reorganization brings us to an array-related solution.

哇,很快就会变得笨拙! 每当代码中包含大量变量时,您就会知道出了点问题 。 通常,重组的第一步将我们带到与阵列相关的解决方案。

<?php$names = [ 'Ray', 'Toby', 'Lucky' ];$phones = [ '703.555.1212', '703.555.1212' ];$emails = [ 'ray@gmail.com', 'toby@gmail.com', 'lucky@gmail.com' ];

Now if we want to look up the information, we can just assign a number to our search criterion and take that numeric position in each of the arrays.  This works, sort-of.  Where it breaks down is in the phones - we have a missing phone number.  And that means we cannot readily add data to the end of these arrays, because we risk putting the data into the wrong "columns" for want of a better term.  We need to reorganize, and to that end we start thinking about the "objects" of information in our Contact Directory.

现在,如果要查找信息,我们可以为搜索条件分配一个数字,并在每个数组中占据该数字位置。 这样工作,有点。 发生故障的地方是电话-我们缺少电话号码。 这意味着我们不能轻易将数据添加到这些数组的末尾,因为我们可能会出于缺乏更好的条件而将数据放入错误的“列”中的风险。 我们需要进行重组,为此,我们开始考虑联系目录中信息的“对象”。

Each object represents a person we might want to contact.  We might represent them with a PHP class like this.

每个对象代表一个我们可能想联系的人。 我们可以用这样PHP类来表示它们。

<?phpClass Person{    public $name, $phone, $email;}

Using that data model for one person, we can easily see that our contact directory can be organized into an array or a database table that will hold an unlimited number of independent data objects.  And since each person is represented by a uniquely isolated data structure, we don't have to worry about partial or missing data - errors and omissions in one object do not affect the validity of other objects.

使用一个人的数据模型,我们可以轻松地看到我们的联系人目录可以组织成一个数组或数据库表,该表或数据库表将容纳无限数量的独立数据对象。 而且由于每个人都由一个唯一的隔离数据结构表示,所以我们不必担心部分或丢失数据-一个对象中的错误和遗漏不会影响其他对象的有效性。

This is a very simple example, but if you started adding more data elements to the data model you would find that your collection of properties could grow quite large.  And every time more data elements were added, you would have to consider ways to keep the existing data models up to date with the newer, more fully completed models.

这是一个非常简单的示例,但是如果您开始向数据模型中添加更多数据元素,则会发现您的属性集合可能会变得很大。 而且,每当添加更多数据元素时,您就必须考虑如何使现有数据模型与更新,更完整的模型保持最新。

Let's examine how an ordinary program might look.  If we wanted to create a new Person object we might expect to do it like this:

让我们研究一下普通程序的外观。 如果我们想创建一个新的Person对象,我们可能希望这样做:

<?php$person = new Person;$name   = 'Ray';$phone  = '703.555.1212';$email  = 'ray@gmail.com';$person->setName($name);$person->setPhone($phone);$person->setEmail($email);$per_id = $person->save();

We can do that, but it's several lines of code when many fewer lines could do the same thing.  And with fewer lines we would have a more readable way of expressing the same idea.  In a fluent interface we might write something like this.  Notice how easily it reads from left to right:

我们

<?php$person = new Person;$person->name('Ray')->phone('703.555.1212')->email('ray@gmail.com')->save();

There are two important concepts (and one simple concept) in play when we try to write fluent code.

当我们尝试编写流畅的代码时,有两个重要的概念(和一个简单的概念)在起作用。

The first concept is method chaining.  While there are more complex ways to do this, our example takes advantage of the simplest case.  When our method is complete, instead of returning some isolated data element, we simply return the entire object.  This means that the object is implicitly available to each new method call.   So instead of having to write many lines of code, we can put all of our method calls into a single statement.   They can be chained together because each method receives the object that was returned from the previous method.  Almost magic!

第一个概念是方法链接 。 尽管有更复杂的方法可以执行此操作,但我们的示例利用了最简单的情况。 当我们的方法完成后,我们只

The second concept is the magic method.  Whenever a PHP class method is called and the method does not exist on the class, PHP will raise a fatal error.  But before that error occurs, PHP will first substitute the name __call() for the missing method. We can write our code to take advantage of this automatic method substitution.  Again, almost magic!

第二个概念是魔术方法 每当调用PHP类方法而该类上不存在该方法时,PHP都会引发致命错误。 但是在发生该错误之前,PHP首先将名称__call()替换为缺少的方法。 我们可以编写代码来利用这种自动方法替换的优势。 再次,

There is a third concept in play here, too.  We want to know what properties exist (since these are almost certainly column names in a database table).  Our class constructor creates these properties and our magic method __call() checks that the properties exist and throws an error or exception if they do not exist.  This prevents the accidental injection of unwanted properties into our object, and in turn prevents a database error.

这里也有第三个概念。 我们想知道存在哪些属性(因为这些属性几乎肯定是数据库表中的列名)。 我们的类构造函数创建这些属性,我们的魔术方法__call()检查属性是否存在,如果属性不存在,则抛出错误或异常。 这样可以防止将不想要的属性意外注入到我们的对象中,进而防止数据库错误。

Here is a line-by-line annotation of the code sample below:

这是下面的代码示例的逐行注释:

Line 11: The class constructor furnishes the names of the properties we can inject; this is a whitelist (line 14)

第11行:类构造函数提供了我们可以注入的属性的名称; 这是白名单(第14行)

Line 23: A stub function (placeholder) for what will eventually become our data base update

第23行:一个存根函数(占位符),该函数最终将成为我们的数据库更新

Line 37: Our magic method that updates the property of the same name, subject to whitelist filtering

第37行:我们的魔术方法可以更新相同名称的属性,但需要进行白名单过滤

Line 43: Our return statement simply returns the entire object

第43行:我们的return语句仅返回整个对象

<?php // demo/magic_call.phperror_reporting(E_ALL); Class Person{    /** * The constructor for the class - assigns the properties from the data model * @param none * @return none */    public function __Construct()    {        // STUB FUNCTION: SIMULATE GETTING THE STRUCTURE OF THE DATA MODEL        $this->name = $this->phone = $this->email = NULL;    }     /** * Save the data model by inserting or replacing its row in the database * * @param none * @return id The id of the row in the database */    public function save()    {        // STUB FUNCTION: SIMULATE SAVING THE MODEL        return 1;    }     /** * Magic Setter for any Object Property * * @see http://php.net/manual/en/language.oop5.overloading.php * @param $argname The property to be set (must exist) * @return $this The existing object returns itself * @error E_USER_ERROR if the named property does not exist */    public function __call($argname, array $arglist)    {        if ( ! property_exists($this, $argname) )            trigger_error("Property <b><i>$argname</i></b> is undefined on the " . __CLASS__ . " data model", E_USER_ERROR);         $this->$argname = $arglist[0];        return $this;    }}  // DEMONSTRATE$p  = new Person;$id = $p->name('Ray')->phone('703')->email('EE')->save(); // SHOW THE DATA STRUCTURESvar_dump($id, $p);

And that's it -- a simple design pattern that makes for compact, readable code.

就是这样-一个简单的设计模式可以生成紧凑,易读的代码。

There are arguments both for and against this kind of code.  One of the "against" arguments suggests that you have to know the structure of the class to understand what methods can be called on the objects and in what order these methods can be called (see Demeter Chains).  I respect the argument, and in my experience as a professional programmer, I find that you cannot simultaneously understand a system and avoid the knowledge that the Demeter Law says you should avoid.  So I willingly choose compact readable code.

有支持和反对此类代码的论点。 “反对”论点之一建议您必须了解类的结构,以了解可以在对象上调用哪些方法以及可以按什么顺序调用这些方法(请参阅Demeter Chains )。 我尊重论点,以我作为专业程序员的经验,我发现您无法同时理解系统,也无法避免Demeter Law规定您应该避免的知识。 因此,我愿意选择紧凑的可读代码。

Here are some references and further reading to help complete the picture:

以下是一些参考资料和进一步的阅读资料,以帮助您理解完整的图片:http://martinfowler.com/bliki/FluentInterface.htmlhttp://martinfowler.com/bliki/FluentInterface.htmlhttp://stackoverflow.com/a/17940086/1907917http://stackoverflow.com/a/17940086/1907917http://go.aopphp.com/blog/2013/03/19/implementing-fluent-interface-pattern-in-php/http://go.aopphp.com/blog/2013/03/19/implementing-fluent-interface-pattern-in-php/http://c2.com/cgi/wiki?LawOfDemeterhttp://c2.com/cgi/wiki?LawOfDemeterhttp://docs.mockery.io/en/latest/reference/demeter_chains.htmlhttp://docs.mockery.io/en/latest/reference/demeter_chains.html

Just for fun, here's a contrasting point of view from a fellow that says the Fluent Interface rustles his jimmies.

只是为了好玩,这是来自一个家伙的相反观点,他说Fluent Interface 沙沙作响

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/18161/Using-the-Fluent-Interface-Design-Pattern-to-Make-Code-more-Concise-and-Readable.html

fluent 界面控件


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删


相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空