前言:前面0-1完整讲解了TennisGame的重构过程。本节将以一个Insurance的例子继续。本节将使用到一点点无伤大雅的PHPUnit。
注意:PHPUnit的安装过程略过,我使用的是PHP7.1,所以,用到了PHPUnit 7.5.20的安装包。而且,不同版本的PHPUnit的手册差异比较大,在展示的代码或许无法在你的PHP环境中正确运行。这部分的PHPUnit可以忽略。
原始代码
注意:这里的原始代码中的链接是一个无意义的链接,仅为了演示代码重构使用,关键是var_dump返回的那个array
<?php class Insurance{ public function quote($providers = null) { if(!$providers){ $providers = ['bank','insurance-company']; }else{ $providers = [$providers]; } $quote = array(); $bank_url = 'https://www.baidu.com/'; for($i = 0;$i<count($providers);++$i){ switch($providers[$i]){ case 'bank': $prices = file_get_contents($bank_url); case 'insurance-company': $curl = curl_init(); curl_setopt_array($curl,array( CURLOPT_RETURNTRANSFER=>1, CURLOPT_URL=>'HTTP://123.COM/', CURLOPT_POST=>1, CURLOPT_POSTFIELDS=>array( 'month'=>3, ) )); $prices = json_decode(curl_exec($curl)); curl_close($curl); } $quote[$providers[$i]] = $prices; } return $quote; } } $insurance = new Insurance(); $quote = $insurance->quote(); var_dump($quote); ?>可以使用命令行php Insurance.php测试一下。
与之对应的文档test文件是InsutanceTest.test.php
<?php class InsuranceTest extends PHPUnit_Framework_TestCase{ public function testQuoteNotNull(){ require './Insurance.php'; $insurance = new Insurance(); $quote = $insurance->quote(); $this->assertNotNull($quote['bank']); $this->assertNotNull($quote['insurance-company']); } } ?>命令行输入phpunit InsuranceTest.test.php测试一下。
Step 0:构造函数,以及providers 的 OOP化
通过这个construct方法,就可以把如下内容取代:
if(!$providers){ $providers = ['bank','insurance-company']; }else{ $providers = [$providers]; } <?php class Insurance{ protected $providers; public function __construct(Provider $provider = null){ $this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()]; } public function quote($providers = null) { $quote = array(); $bank_url = 'https://www.baidu.com/'; for($i = 0; i<count($this->providers);++$i){ // foreach($this->providers as $provider){ switch($this->providers[$i]){ case 'bank': $prices = file_get_contents($bank_url); case 'insurance-company': $curl = curl_init(); curl_setopt_array($curl,array( CURLOPT_RETURNTRANSFER=>1, CURLOPT_URL=>'HTTP://123.COM/', CURLOPT_POST=>1, CURLOPT_POSTFIELDS=>array( 'month'=>3, ) )); $prices = json_decode(curl_exec($curl)); curl_close($curl); } $quote[$this->getName()] = $this->provides[$i]->getPrices(); } return $quote; } } abstract class Provider{ } class BankProvider extends Provider{ } class InsuranceCompanyProvider extends Provider{ } $insurance = new Insurance(); $quote = $insurance->quote(); var_dump($quote); ?>Step 1: bank类型prices的OOP化,顺便把for改成foreach
<?php class Insurance{ protected $providers; public function __construct(Provider $provider = null){ $this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()]; } public function quote($providers = null) { $quote = array(); foreach($this->providers as $privder){ // foreach($this->providers as $provider){ $quote[$privider->getName()] = $provide->getPrices(); } return $quote; } } abstract class Provider{ abstract function getPrices(); abstract function getName(); } class BankProvider extends Provider{ public function getName(){ return 'bank'; } public function getPrices(){ $bank_url = 'https://www.baidu.com/'; $prices = file_get_contents($bank_url); return $prices; } } class InsuranceCompanyProvider extends Provider{ public function getName(){ return 'insurance-company'; } public function getPrices(){ $curl = curl_init(); curl_setopt_array($curl,array( CURLOPT_RETURNTRANSFER=>1, CURLOPT_URL=>'HTTP://123.COM/', CURLOPT_POST=>1, CURLOPT_POSTFIELDS=>array( 'month'=>3, ) )); $prices = json_decode(curl_exec($curl)); curl_close($curl); return $prices; } } $insurance = new Insurance(); $quote = $insurance->quote(); var_dump($quote); ?>可以测试一下
Step 2:进一步把curl解决掉
这个步骤也就是让大家看个思路,由于我没有找到合适的json服务器,所以无法演示器结果。
<?php class Insurance{ protected $providers; public function __construct(Provider $provider = null){ $this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()]; } public function quote($providers = null) { $quote = array(); foreach($this->providers as $privder){ // foreach($this->providers as $provider){ $quote[$privider->getName()] = $provide->getPrices(); } return $quote; } } abstract class Provider{ protected $url = 'https://www.baidu.com/'; abstract function getPrices(); abstract function getName(); } class BankProvider extends Provider{ public function getName(){ return 'bank'; } public function getPrices(){ $url = $this->url.'/bank'; $prices = Curl::exec($url); return $prices; } } class Curl{ public static function exec($url,$opt = []){ $curl = curl_init(); $options = [ CURLOPT_RETURNTRANSFER=>1, CURLOPT_URL=>$url, ]; if($opt){ $options[CURLOPT_POST] = 1; $options[CURLOPT_POSTFIELDS] = http_build_query($opt); } curl_setopt_array($curl,$options); $result = curl_exec($curl); curl_close($curl); return $result; } } class InsuranceCompanyProvider extends Provider{ public function getName(){ return 'insurance-company'; } public function getPrices(){ $url = $this->url.'/insurance'; $prices = Curl::exec($url,[ 'month'=>3 ]); return $prices; } } $insurance = new Insurance(); $quote = $insurance->quote(); var_dump($quote); ?>Step 3: 最后一步
<?php class Insurance{ protected $providers; protected $curl; public function __construct(ICurl $curl, Provider $provider = null){ $this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()]; $this->curl = $curl; } public function quote($providers = null) { $quote = array(); foreach($this->providers as $provider){ $quote[$provider->getName()] = $provide->getPrices($this->curl); } return $quote; } } abstract class Provider{ protected $url = 'https://www.baidu.com/'; abstract function getPrices(ICurl $curl); abstract function getName(); } class BankProvider extends Provider{ public function getName(){ return 'bank'; } public function getPrices(ICurl $curl){ $url = $this->url.'/bank'; $prices = $curl->exec($url); return $prices; } } interface ICurl{ public function exec($url, $opt=[]); } class Curl implements ICurl{ public function exec($url,$opt = []){ try{ $curl = curl_init(); $options = [ CURLOPT_RETURNTRANSFER=>1, CURLOPT_URL=>$url, ]; if($opt){ $options[CURLOPT_POST] = 1; $options[CURLOPT_POSTFIELDS] = http_build_query($opt); } curl_setopt_array($curl,$options); $result = curl_exec($curl); curl_close($curl); return $result; }catch(Exception $e){ throw new Exception($e); } } } class InsuranceCompanyProvider extends Provider{ public function getName(){ return 'insurance-company'; } public function getPrices(ICurl $curl){ $url = $this->url.'/insurance'; $prices = $curl->exec($url,[ 'month'=>3 ]); return $prices; } } $curl = new Curl(); $insurance = new Insurance($curl); $quote = $insurance->quote(); var_dump($quote); ?> <?php require './Insurance.php'; class InsuranceTest extends PHPUnit_Framework_TestCase{ public function testQuoteNotNull(){ require './Insurance.php'; $curl = new Curl(); $insurance = new Insurance($curl); $quote = $insurance->quote(); $this->assertNotNull($quote['bank']); $this->assertNotNull($quote['insurance-company']); } public function testCurlSuccess(){ require './Insurance.php'; $curl = new CurlSuccess(); $insurance = new Insurance($curl); $quote = $insurance->quote(); $this->assertNotNull($quote['bank']); $this->assertNotNull($quote['insurance-company']); } public function testCurlFail(){ require './Insurance.php'; $curl = new CurlSuccess(); $insurance = new Insurance($curl); $this->exceptException(Exception::class); $quote = $insurance->quote(); } } class CurlSuccess implements ICurl{ public function exec($url, $opt = []) { return ['success']; } } class CurlFail implements ICurl{ public function exec($url, $opt = []) { throw new Exception('Failed'); } } ?>后记:这篇blog写得太痛苦了,大家讲究看吧。完工
