仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 643|回复: 8
打印 上一主题 下一主题

[学习教程] PHP教程之谈一谈PHP的代码重构

[复制链接]
只想知道 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:13:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
你的留言本应该加入注册以及分页功能了,而如果你更强的话,UI(用户界面)也可以加强,完成之后,感觉是不是特有成就感?不管怎么样,咱好歹是写了一个动态网站程序了,放在自己的网站上耍耍吧。跟着PHP从一种复杂的剧本言语变化为一种成熟的编程言语,一个典范的PHP使用程序的代码库的庞大性也随之增年夜。为了把持对这些使用程序的撑持和保护,我们可使用各类测试工具来主动化该流程。个中一种是单位测试,它同意您间接测试所编写代码的准确性。但是,一般遗留代码库是不合适举行这类测试的。本文将先容对包括罕见成绩的PHP代码的重构战略,以便简化利用盛行的单位测试工具举行测试的历程,同时削减改善代码库的依附性。简介回忆PHP15年的开展过程,我们发明它已从一个复杂的用来替换事先盛行的CGI剧本的静态剧本言语酿成一种成熟的古代编程言语。跟着代码库的增加,手动测试已酿成不成能完成的义务,不管是年夜是小,一切代码的变更城市对全部使用程序发生影响。这些影响大概小到只是影响某个页面的加载或表单保留,也多是发生难以检测的成绩,大概发生只在特定前提下才会呈现的毛病。乃至,它大概会使之前修复的成绩从头呈现在使用程序中。为此开辟了许多测试工具来办理这些成绩。个中一种盛行的办法是所谓的功效或验收测试,它会经由过程使用程序的典范用户交互来测试这个使用程序。这是一种很合适测试使用程序中各个历程的办法,可是测试历程大概十分慢,并且一样平常没法测试底层的类和办法是不是按请求一般事情。这时候,我们必要利用另外一种测试办法,那就是单位测试。单位测试的方针是测试使用程序底层代码的功效,包管它们实行后发生准确的了局。一般,这些“不休增年夜”的Web使用程序会渐渐呈现愈来愈多一朝一夕难以测试的遗留代码,这使开辟团队很难包管使用程序测试的掩盖率。这一般被称为“不成测试代码”。如今让我们看看怎样辨认使用程序中的不成测试代码,和修复这些代码的办法。辨认不成测试的代码关于代码库不成测试性的成绩域一般在编写代码时是不分明的。当编写PHP使用程序代码时,人们偏向于依照Web哀求的流程来编写代码,这一般就是在使用程序计划时接纳一种加倍流程化的办法。急于完成项目或疾速修复使用程序都大概促使开辟职员“走捷径”,以便疾速完成编码。之前,编写不妥大概凌乱的代码大概会减轻使用程序中的不成测试性成绩,由于开辟职员一般会举行风险最小的修复,即便它大概发生后续的撑持成绩。这些成绩域都是没法经由过程一样平常的单位测试发明的。依附全局形态的函数全局变量在PHP使用程序中很便利。它们同意您在使用程序中初始化一些变量或工具,然后在使用程序的其他地位利用。但是,这类天真性是有价值的,过分利用全局变量是不成测试代码的一个通病。我们能够在清单1中看到这类情形。清单1.依附于全局形态的函数<?phpfunctionformatNumber($number){global$decimal_precision,$decimal_separator,$thousands_separator;if(!isset($decimal_precision))$decimal_precision=2;if(!isset($decimal_separator))$decimal_separator=.;if(!isset($thousands_separator))$thousands_separator=,;returnnumber_format($number,$decimal_precision,$decimal_separator,$thousands_separator);}这些全局变量带来了两个分歧的成绩。第一个成绩是您必要在测试中思索一切这些全局变量,包管给它们设置了函数可承受的无效值。第二个成绩更加严峻,那就是您没法修正后续测试的形态并使它们的了局有效,您必要包管将全局形态重置为测试运转之前的形态。PHPUnit有一些工具能够帮您备份全局变量并在测试运转后恢复它们的值,这些工具可以匡助办理这个成绩。但是,更好的办法是使测试类可以间接给办法传进这些全局变量的值。清单2显现了接纳这类办法的一个例子。清单2.修正这个函数以撑持重写全局变量<?phpfunctionformatNumber($number,$decimal_precision=null,$decimal_separator=null,$thousands_separator=null){if(is_null($decimal_precision))global$decimal_precision;if(is_null($decimal_separator))global$decimal_separator;if(is_null($thousands_separator))global$thousands_separator;if(!isset($decimal_precision))$decimal_precision=2;if(!isset($decimal_separator))$decimal_separator=.;if(!isset($thousands_separator))$thousands_separator=,;returnnumber_format($number,$decimal_precision,$decimal_separator,$thousands_separator);}如许做不但使代码变得更具可测试性,并且也使它不依附于办法的全局变量。这使得我们可以对代码举行重构,不再利用全局变量。没法重置的单一实例单一实例指的是旨在让使用程序中一次只存在一个实例的类。它们是使用程序顶用于全局工具的一种罕见形式,如数据库毗连和设置设置。它们一般被以为是使用程序的忌讳,由于很多开辟职员以为创立一个老是可用的工具用途不年夜,因而他们其实不太注重这一点。这个成绩次要源于单一实例的过分利用,由于它会形成大批不成扩大的所谓godobjects的呈现。可是从测试的角度看,最年夜的成绩是它们一般是不成变动的。清单3就是如许一个例子。清单3.我们要测试的Singleton工具<?phpclassSingleton{privatestatic$instance;protectedfunction__construct(){}privatefinalfunction__clone(){}publicstaticfunctiongetInstance(){if(!isset(self::$instance)){self::$instance=newSingleton;}returnself::$instance;}}您能够看到,当单一实例初次实例化以后,每次挪用getInstance()办法实践上前往的都是统一个工具,它不会创立新的工具,假如我们对这个工具举行修正,那末便可能形成很严峻的成绩。最复杂的办理计划就是给工具增添一个reset办法。清单4显现的就是如许一个例子。清单4.增添了reset办法的Singleton工具<?phpclassSingleton{privatestatic$instance;protectedfunction__construct(){}privatefinalfunction__clone(){}publicstaticfunctiongetInstance(){if(!isset(self::$instance)){self::$instance=newSingleton;}returnself::$instance;}publicstaticfunctionreset(){self::$instance=null;}}如今,我们能够在每次测试之前挪用reset办法,包管我们在每次测试过程当中城市先实行singleton工具的初始化代码。总之,在使用程序中增添这个办法是很有效的,由于我们如今能够轻松地修正单一实例。利用类机关函数举行单位测试的一个优秀做法是只测试必要测试的代码,制止创立不用要的工具和变量。您创立的每个工具和变量都必要在测试以后删除。这关于文件和数据库表等贫苦的项目来讲成为一个成绩,由于在这些情形下,假如您必要修正形态,那末您必需更当心地在测试完成以后举行一些清算操纵。保持这一划定规矩的最年夜停滞在于对象自己的机关函数,它实行的一切操纵都是与测试有关的。清单5就是如许一个例子。清单5.具有一个年夜singleton办法的类<?phpclassMyClass{protected$results;publicfunction__construct(){$dbconn=newDatabaseConnection(localhost,user,password);$this->results=$dbconn->query(selectnamefrommytable);}publicfunctiongetFirstResult(){return$this->results[0];}}在这里,为了测试工具的fdfdfd办法,我们终极必要创建一个数据库毗连,给表增加一些纪录,然后在测试以后扫除一切这些资本。假如测试fdfdfd完整不必要这些器材,那末这个历程大概太甚于庞大。因而,我们要修正清单6所示的机关函数。清单6.为疏忽一切不用要的初始化逻辑而修正的类<?phpclassMyClass{protected$results;publicfunction__construct($init=true){if($init)$this->init();}publicfunctioninit(){$dbconn=newDatabaseConnection(localhost,user,password);$this->results=$dbconn->query(selectnamefrommytable);}publicfunctiongetFirstResult(){return$this->results[0];}}我们重构了机关函数中大批的代码,将它们移到一个init()办法中,这个办法默许情形下仍旧会被机关函数挪用,以免损坏现有代码的逻辑。但是,如今我们在测试过程当中只可以传送一个布尔值false给机关函数,以免挪用init()办法和一切不用要的初始化逻辑。类的这类重构也会改善代码,由于我们将初始化逻辑从工具的机关函数分别出来了。经硬编码的类依附性正如我们在前一节先容的,形成测试坚苦的大批类计划成绩都会合在初始化各类不必要测试的工具上。在后面,我们晓得沉重的初始化逻辑大概会给测试的编写形成很年夜的包袱(出格是当测试完整不必要这些工具时),可是假如我们在测试的类办法中间接创立这些工具,又大概形成另外一个成绩。清单7显现的就是大概形成这个成绩的示例代码。清单7.在一个办法中间接初始化另外一个工具的类<?phpclassMyUserClass{publicfunctiongetUserList(){$dbconn=newDatabaseConnection(localhost,user,password);$results=$dbconn->query(selectnamefromuser);sort($results);return$results;}}假定我们正在测试下面的getUserList办法,可是我们的测试存眷点是包管前往的用户清单是按字母按次准确排序的。在这类情形下,我们的成绩不在因而否可以从数据库猎取这些纪录,由于我们想要测试的是我们是不是可以对前往的纪录举行排序。成绩是,因为我们是在这个办法中间接实例化一个数据库毗连工具,以是我们必要实行一切这些烦琐的操纵才干够完成办法的测试。因而,我们要对办法举行修改,使这个工具能够在两头拔出,如清单8所示。清单8.这个类有一个办法会间接实例化另外一个工具,可是也供应了一种重写的办法<?phpclassMyUserClass{publicfunctiongetUserList($dbconn=null){if(!isset($dbconn)!($dbconninstanceOfDatabaseConnection)){$dbconn=newDatabaseConnection(localhost,user,password);}$results=$dbconn->query(selectnamefromuser);sort($results);return$results;}}如今您能够间接传进一个工具,它与预期数据库毗连工具相兼容,然后间接利用这个工具,而非创立一个新工具。您也能够传进一个摹拟工具,也就是我们在一些挪用办法中,用硬编码的体例间接前往我们想要的值。在这里,我们能够摹拟数据库毗连工具的查询办法,如许我们就只必要返回了局,而不必要真正地往查询数据库。举行如许的重构也可以改善这个办法,由于它同意您的使用程序在必要时拔出分歧的数据库毗连,而不是只绑定一个指定的默许数据库毗连。可测试代码的优点明显,编写更具可测试性的代码一定可以简化PHP使用程序的单位测试(正如您在本文展现的例子中所看到的),可是在这个过程当中,它也可以改善使用程序的计划、模块化和不乱性。我们都已经看到过“spaghetti”代码,它们在PHP使用程序的一个次要流程中充溢了大批的营业和体现逻辑,这毫无疑问会给那些利用这个使用程序的天然成严峻的撑持成绩。在使代码变得更具可测试性的过程当中,我们对后面一些有成绩的代码举行了重构;这些代码不但计划上有成绩,功效上也有成绩。经由过程使这些函数和类的用处更普遍,和经由过程删除硬编码的依附性,我们使之更简单被使用程序其他部分重用,我们进步了代码的可重用性。别的,我们还将编写不妥的代码交换成更优良的代码,从而简化未来对代码库的撑持。停止语在本文中,经由过程PHP使用程序中一些典范的不成测试代码示例,我们懂得了怎样改善PHP代码的可测试性。我们还先容了这些情形是怎样呈现在使用程序中的,然后先容了怎样得当地修复这些成绩代码来便于举行测试。我们还懂得了这些代码的修正不但可以进步代码的可测试性,也可以广泛改善代码的质量,和进步重构代码的可重用性。兴趣可能会慢慢消亡,所以适当培养兴趣会激发自己无线的乐趣,有了乐趣,编程有啥难的。
灵魂腐蚀 该用户已被删除
沙发
发表于 2015-1-20 18:17:31 | 只看该作者
首推的搜索引擎当然是Google大神,其次我比较喜欢 百度知道。不过搜出来的结果往往都是 大家copy来copy去的,运气的的概率很大。
山那边是海 该用户已被删除
板凳
发表于 2015-1-29 14:08:20 | 只看该作者
要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。
飘飘悠悠 该用户已被删除
地板
发表于 2015-2-6 01:55:31 | 只看该作者
最后祝愿,php会给你带来快乐的同时 你也会给他带来快乐。
因胸联盟 该用户已被删除
5#
发表于 2015-2-14 21:43:46 | 只看该作者
曾经犯过一个很低级的错误,我在文件命名的时候用了一个横线\\\\\\\'-\\\\\\\' 号,结果找了好几个小时的错误,事实是命名的时候 是不能用横线 \\\\\\\'-\\\\\\\' 的,应该用的是下划线  \\\\\\\'_\\\\\\\' ;
不帅 该用户已被删除
6#
发表于 2015-3-4 10:44:20 | 只看该作者
,熟悉html,能用div+css,还有javascript,优先考虑linux。我在开始学习的时候,就想把这些知识一起学习,我天真的认为同时学习能够互相呼应,因为知识是相通的。
飘灵儿 该用户已被删除
7#
发表于 2015-3-11 18:25:09 | 只看该作者
遇到出错的时候,我经常把错误信息直接复制到 google的搜索栏,一般情况都是能搜到结果的,不过有时候会搜出来一大片英文的出来,这时候就得过滤一下,吧中文的弄出来,挨着式方法。
变相怪杰 该用户已被删除
8#
发表于 2015-3-19 07:29:40 | 只看该作者
当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标,
小魔女 该用户已被删除
9#
发表于 2015-3-27 13:10:04 | 只看该作者
我还是推荐用firefox ,配上firebug 插件调试js能省下不受时间。谷歌的浏览器最好也不少用,因为谷歌的大侠们实在是太天才啦,把一些原来的js代码加了一些特效。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 22:49

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表