A case of PHP refactoring optimization--_php Tutorial of template method pattern application

Source: Internet
Author: User
Recently optimized PHP project, recording the experience, directly on the work ...

PHP is mainly used in the company project for page presentation, the front end has a view,view back end of the service request data, the data transfer format is JSON. Here's a look at the code for the service before optimization:

[PHP]
Require_once ('.. /.. /.. /global.php ');
Require_once (include_path. '/discache/cachermanager.php ');
Require_once (include_path. ' /oracle_oci.php ');
Require_once (include_path. ' /caihui/cwsd.php ');
Header (' Content-type:text/plain; Charset=utf-8 ');
$max _age = isset ($_get[' max-age ')? $_get[' Max-age ']*1:15*60;
if ($max _age < 30) {
$max _age = 30;
}
Header (' cache-control:max-age= '. $max _age);
By hashing the URL as a buffer key
$url = $_server[' http_host '].$_server[' Request_uri '];
$url _hash = MD5 ($url);
echo "/finance/hs/marketdata/segment/${url_hash}.json";
if (! Cachermanager::cachepagestart (Cacher_mongo, "/finance/hs/marketdata/segment/${url_hash}.json", 60*60)) {

Query criteria
$page = isset ($_get[' page ')? $_get[' page ']*1:0;
$count = isset ($_get[' count ')? $_get[' count ']*1:30;
$type = isset ($_get[' type ')? $_get[' type ']: ' query ';
$sort = isset ($_get[' sort ')? $_get[' sort ']: ' symbol ';
$order = isset ($_get[' order ')? $_get[' order ': ' desc ';
$callback = Isset ($_get[' callback ')? $_get[' callback ': null;
$fieldsstring = isset ($_get[' fields ')? $_get[' Fields ']: null;
$querystring = isset ($_get[' query ')? $_get[' query ': null;
$symbol =isset ($_get[' symbol ')? $_get[' symbol ']: ';
$date =isset ($_get[' date ')? $_get[' Date ']: ';

if ($type = = ' query ') {
$QUERYOBJ = Preg_split ('/:|;/', $querystring,-1);
for ($i =0; $i
if (Emptyempty ($QUERYOBJ [$i])) continue;
if ($queryObj [$i]== ' symbol ') {
$symbol = $QUERYOBJ [$i +1];
}
if ($queryObj [$i]== ' date ') {
$date = $QUERYOBJ [$i +1];
}
}
}

Query list
$oci = Ntes_get_caihui_oci ();
$stocklist = Array ();
$CWSD = new NAMESPACE\DAO\CAIHUI\CWSD ($OCI);

$stockcurror = $CWSD->getcznllist ($symbol, $date, $sort, $order, $count * ($page), $count);
$sumrecords = $CWSD->getrecordcount ($symbol, $date);
$i = 0;
Var_dump ($symbol, $date, $sort, $order, $count * ($page), $count);
foreach ($stockcurror as $item) {
$item [' RSMFRATIO1422 ']=isset ($item [' RSMFRATIO1422 '])? Number_format ($item [' RSMFRATIO1422 '],2]. ' %':'--';
$item [' RSMFRATIO1822 ']=isset ($item [' RSMFRATIO1822 '])? Number_format ($item [' RSMFRATIO1822 '],2]. ' %':'--';
$item [' RSMFRATIO22 ']=isset ($item [' RSMFRATIO22 '])? Number_format ($item [' RSMFRATIO22 '],2]. ' %':'--';

$item [' RSMFRATIO10 ']=isset ($item [' RSMFRATIO10 '])? Number_format ($item [' RSMFRATIO10 '],2): '--';
$item [' RSMFRATIO12 ']=isset ($item [' RSMFRATIO12 '])? Number_format ($item [' RSMFRATIO12 '],2): '--';
$item [' RSMFRATIO4 ']=isset ($item [' RSMFRATIO4 '])? Number_format ($item [' RSMFRATIO4 '],2): '--';
$item [' RSMFRATIO18 ']=isset ($item [' RSMFRATIO18 '])? Number_format ($item [' RSMFRATIO18 '],2): '--';
$item [' RSMFRATIO14 ']=isset ($item [' RSMFRATIO14 '])? Number_format ($item [' RSMFRATIO14 '],2): '--';

$item [' CODE ']= $item [' EXCHANGE ']. $item [' SYMBOL '];
$item [' Reportdate ']=isset ($item [' reportdate '])? $item [' Reportdate ']: '--';
$stocklist [$i] = $item;
$i = $i +1;
}


Output results
$result = Array ();
Page number page, count per page, total result, number of pages PageCount, List of results
$result [' page '] = $page;
$result [' count '] = $count;
$result [' order '] = $order;
$result [' total '] = $i;//$stockcurror->count ();
$result [' pagecount '] = ceil ($sumrecords [' Sumrecord ']/$count);
$result [' time '] = Date (' y-m-d h:i:s ');
$result [' list '] = $stocklist;
if (Emptyempty ($callback)) {
echo Json_encode ($result);
}else{
echo $callback. ' ('. Json_encode ($result). ');
}

Cachermanager::cachepageend ();
}
?>
Here's a look at what this service does specifically:

1.6-16 rows, prepare cache parameters, turn on cache.
2.19-41 rows, extract the request parameters.
3.44-49 lines, connect and query the database.
4.50-67 rows to put the database query results into an array.
5.71-84 lines, prepare the JSON data.
6.86-87 lines, close the cache.

If you look at this file only, there are the following issues:
1.19-86 lines, no indentation.
2.44 rows, each request will reconnect to the database.
3.53-61 lines, repetitive logic, can be extracted as a function and then completed by iteration.
If most back-end service uses this structure, then the problem is that all the service needs to go through: Open cache, take parameters, get data, JSON transform, close the cache this series of processes. And in all the process, the other processes are the same except for the logic to get the data. There is a lot of repetitive logic in the code, and even a "copy-and-paste" feel, which is a serious violation of the dry principle (Don ' t Repeat yourself). Therefore, it is necessary to use object-oriented thinking to reconstruct it. And in the course of my refactoring, I always remember a principle-the principle of package change. The so-called package change, is to differentiate the system in the invariant and variable, will be variable package, it is better to deal with the change.
Through the above analysis, only the logic to get the data is changed, the other logic is invariant. Therefore, the logic of acquiring data needs to be encapsulated, and the specific encapsulation can be inherited or combined. I used the inheritance approach, which was to first abstract the service process into:
Service () {
StartCache ();
GetParam ();
GetData (); Abstract methods, implemented by subclasses
ToJson ();
Closecache ();
}
Abstract out the ServiceBase class, subclasses inherit, implement the corresponding data acquisition logic, subclasses do not need to deal with other parameters, caching and other logic, these are servicebase class processing.
[PHP]
Abstract class ServiceBase {
Public function __construct ($cache _path, $cache _type, $max _age, $age _explore) {
GET Request Parameters
$this->page = $this->getqueryparamdefault (' page ', 0, INT);
Omit other logic to get parameters
......

Generate response
$this->response ();
}

/**
*
* Subclass implementation, returning data in array format
*/
Abstract protected function data ();

/**
*
* Subclass implementation, returns the total number of all data
*/
Abstract protected function total ();

Private Function cache () {
$url = $_server[' http_host '].$_server[' Request_uri '];
$url _hash = MD5 ($url);
$key = $this->cache_path. $url _hash. JSON ';
if (! Cachermanager::cachepagestart ($this->cache_type, $key, $this->age_cache)) {
$this->no_cache ();
Cachermanager::cachepageend ();
}
}

Private Function No_cache () {
$data = $this->data ();
$total = $this->total ();
$this->send_data ($data, $total);
}

Private Function Send_data ($data, $total) {
Make JSON conversions, omit specific code
}

Private Function response () {
Header (' Content-type:text/plain; Charset=utf-8 ');
Header (' cache-control:max-age= '. $this->age_explore);
if ($this->cache_type = = NONE | | Self:: $enable _cache = = False) {
$this->no_cache ();
}else{
$this->cache ();
}
}
}
This is the abstract parent class for each service, there are two abstract methods data and Total,data are returned in the array format, Tatol is due to pagination join. As long as the specific service inherits the ServiceBase and implements the data and total methods, the other logic is the reused parent class. In fact, the optimized ServiceBase is to use the template method pattern, the parent class defines the process of the algorithm processing (service processing), and the subclass implements a specific change step (the logic of obtaining data for the specific service). By using the template method pattern, you can ensure that the changes to the steps are transparent to the client and that the logic in the parent class can be reused.

Here's the code for PHP after using servicebase:

[PHP]
Class Cwsdservice extends servicebase{
function __construct () {
Parent::__construct ();
$oci = Ntes_get_caihui_oci ();
$this $CWSD = new NAMESPACE\DAO\CAIHUI\CWSD ($OCI);
}
Public Function data () {
$stocklist = Array ();
$stockcurror = $this->cwsd->getcznllist ($this->query_obj[' symbol '),
$this->query_obj[' symbol ', $sort, $order, $count * ($page), $count);
$filter _list = Array (' RSMFRATIO1422 ', ' RSMFRATIO1822 ', ' RSMFRATIO22 ',
' RSMFRATIO10 ', ' RSMFRATIO12 ', ' RSMFRATIO4 ', ' RSMFRATIO18 ',
' RSMFRATIO14 ');
$i = 0;
foreach ($stockcurror as $item) {
foreach ($filter _list as $k)
$this->filter ($item, $k);
$item [' CODE ']= $item [' EXCHANGE ']. $item [' SYMBOL '];
$stocklist [$i] = $item;
$i = $i +1;
}
return $stocklist;
}
Public Function Total () {
return $sumrecords = $this->cwsd->getrecordcount ($this->query_obj[' symbol '),
$this->query_obj[' symbol ');
}
Private Function Filter ($item, $k) {
Isset ($item [$k])? Number_format ($item [$k],2). ' %':'--';
}
}
New Cwsdservice ('/finance/hs/realtimedata/market/ab ', MONGO, 30, 30);
The amount of code is reduced from 87 to 32 lines, because most of the logic is done by the parent class, and the service needs to focus on its own business logic. It can be seen from the above code that inheritance can implement code reuse, the same logic in multiple subclasses can be extracted to the parent class for reuse purposes, while inheritance also increases the coupling between the parent class and subclass, which is the combination due to inheritance, if this example uses a combination to encapsulate the change, Then the specific implementation is the strategy model, the specific data acquisition logic as a strategy, different service is different strategy, due to time reasons, no longer repeat ...

Excerpt from Chosen0ne's column

http://www.bkjia.com/PHPjc/478442.html www.bkjia.com true http://www.bkjia.com/PHPjc/478442.html techarticle recently optimized PHP project, recording the experience, directly on the work ... PHP in the company project is mainly used for page display, the front end has a view,view back end service request data, data transmission ...

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.