最近一直在研讀《代碼簡潔之道》這本書,裏面不少很是細緻的對代碼重構和簡化的好的思想和方法值得學習,我作了一些筆記,在以前的一些博客中也有涉及。php
關於註釋,各家有各家的想法。有人認爲註釋越詳細越好,從目的到參數含義,無微不至的去寫註解,好比api接口之類的。也有人認爲,涉及複雜的業務邏輯,須要寫必要註釋(以前我也是這麼認爲的)。也有人認爲註釋是罪惡根源,不應寫任何註釋,應該讓清晰易懂的代碼本身說話。html
我想起了好久以前看涵哥寫的api項目,裏面幾乎沒有什麼冗餘的註釋,代碼簡潔到了極致,每一步都像在讀一句詩。並且大量使用componets方式,用大量組合對象去單獨處理,減小耦合。當時我問過他爲什麼看不到什麼註釋,他答:代碼是最好的註釋。node
之前不是很是認同,仍是認爲註釋不能缺乏,特別是業務很是複雜,註釋甚至能幫助理清邏輯業務,也做爲思路的一種記錄。mysql
博客園上已經出現了一篇不錯的文章,講不要濫用註釋:web
http://www.cnblogs.com/leotsai/p/anti-code-comment.html。sql
而《代碼簡潔之道》講的更透徹,妙語連珠,下面是我記錄的一些筆記:編程
註釋的惟一恰當的用處在於彌補咱們用代碼解析意圖所遭遇的失敗。api
註釋存在時間越久,它和真實代碼之間的關係就愈來愈淡,最終甚至全錯。app
應該把主要精力用在寫清晰的代碼上,直接保證無須編寫註釋。curl
註釋不能美化糟糕的代碼。
註釋協助如何改寫代碼,讓註釋消失,讓代碼更readable.
儘可能利用函數名來傳遞信息。
甚至todo註釋也成了罪惡的替罪羊,也不是允許咱們寫糟糕代碼的藉口。
每一個函數都須要註釋太迂腐,盡力仍是判斷。杜絕那種看起來像廢話同樣的註釋,若是代碼足夠清晰就不要寫多於的註釋。
用好的代碼替換廢話註釋,讓本身也變得更加輕鬆和優秀。
歸屬和署名都應該交給版本控制而不是寫在註釋裏面。除非你一直不去動那些代碼,不然你沒法保證這段代碼究竟是誰該負責
被註釋掉的代碼應刪了,留着給人迷惑,還認爲可能某天還會用到。
若是必定要加註釋,請讓它離它解釋的代碼足夠近
註釋要足夠容易懂,若是註釋還須要解釋,那麼就太失敗了。
我不喜歡數學上那種死死的公理定理,可是這些思想是能夠指導咱們更好的改善代碼,讓後面的工做變得輕鬆。
惟一靠譜能提升編程質量和速度的方法就是:時刻保持代碼簡潔。
我以此思想和方法從新review了我去年11月寫的一個採集小說的腳本,源碼寫得很low:
<?php /** * @author freephp * @date 2015-11-13 * */ class MyCurl { private static $url = ''; private static $oriUrl = ''; // referer url private static $data = array(); // ���ܷ��������� post,put private static $method; // ���ʷ�ʽ��Ĭ����GET���� public static function send($url, $data = array(), $method = 'get') { if (!$url) exit('url can not be null'); self::$url = $url; self::$method = $method; $urlArr = parse_url($url); self::$oriUrl = $urlArr['scheme'] .'://'. $urlArr['host']; self::$data = $data; if ( !in_array( self::$method, array('get', 'post', 'put', 'delete') ) ) { exit('error request method type!'); } $func = self::$method . 'Request'; return self::$func(self::$url); } /** * ��������curl������ * @param int $is_post �Ƿ���post���� */ private function doRequest($is_post = 0) { $ch = curl_init();//��ʼ��curl curl_setopt($ch, CURLOPT_URL, self::$url);//ץȡָ����ҳ curl_setopt($ch, CURLOPT_AUTOREFERER, true); // ��Դһ��Ҫ���ó����Ա�վ curl_setopt($ch, CURLOPT_REFERER, self::$oriUrl); /** * special settings about headers * */ $headers = array( 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding:gzip, deflate, sdch', 'Accept-Language:zh-CN,zh;q=0.8', 'Cache-Control:max-age=0', 'Connection:keep-alive' ); curl_setopt($ch, CURLOPT_HEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//Ҫ����Ϊ�ַ������������Ļ�� if($is_post == 1) curl_setopt($ch, CURLOPT_POST, $is_post);//post�ύ��ʽ if (!empty(self::$data)) { self::$data = self::dealPostData(self::$data); curl_setopt($ch, CURLOPT_POSTFIELDS, self::$data); } $data = curl_exec($ch);//����curl curl_close($ch); return $data; } /** * ����get���� */ public function getRequest() { return self::doRequest(0); } /** * ����post���� */ public function postRequest() { return self::doRequest(1); } /** * �������get����Ĵ������� * * @param array $postData */ public function dealPostData($postData) { $postStr = ''; if (!is_array($postData)) exit('post data should be array'); foreach ($postData as $k => $v) { $postStr .= "$k=" . urlencode($v) . "&"; } return substr($postStr, 0, -1); } /** * ����put���� */ public function putRequest($param) { return self::doRequest(2); } /** * ����delete���� */ public function deleteRequest($param) { return self::doRequest(3); } } function url_exists($url) { $head = @get_headers($url); return ($head[0] == 'HTTP/1.1 404 Not Found') ? false : true; } /* $curl = new MyCurl('http://www.jumei.com',array(), 'get'); $res = $curl->send(); */ /* $res = MyCurl::send('http://www.ipip.net/ip.html',array('ip' => '61.142.206.145'),'post'); */ $pageNum = 941672; //$pageNum = 1323233; set_time_limit(0); require 'Analyzer.php'; $start = microtime(true); $contents = file_get_contents('E:\nodejs\chapterUrls.txt'); $urls = array_unique(explode("\r\n", $contents)); /** * ����� */ /*$conn = mysqli_connect('127.0.0.1', 'root', '12345','novel');*/ $analyzer =new Analyzer(); foreach ($urls as $url) { $res = MyCurl::send($url,array(),'get'); $title = $analyzer->getTitle($res)[1]; //var_dump($title);die(); $content = $analyzer->getContent('div', 'content', $res)[0]; // $allContents = $title . "<br/>". $content; $filePath = './juewangjiaoshi/' . $title . '.html'; if(!file_exists($filePath)) { $analyzer->storeToFile($filePath, $allContents); } else { continue; } echo 'down the url:' , $url , "\r\n"; /* $sql = "insert into desks (title,content) values('" . $title . "','" . "$content')"; $fn = fopen('sql.txt', 'a+'); fwrite($fn, $sql . "\r\n"); fclose($fn); echo $sql;die(); mysqli_query($conn, $sql);*/ } $end = microtime(true); $cost = $end - $start; echo "total cost time:" . round($cost, 3) . " seconds\r\n";
因爲我不當心,把文件的中文註釋搞成亂碼了,又無法恢復,你們將就着看。裏面充斥着命名不規範的變量和多餘的廢話似的註釋,還有一些由於爲了考慮將來需求而冗餘的代碼(如putRequest,delRequst),還有一些調試信息被註釋,而沒被刪除。
個人修改以後的代碼以下:
<?php /** * Class MyCurl * * @date review at 2016-01-07 * @author freephp<fightforphp@gmail.com> */ class MyCurl { private static $url = ''; private static $refererUrl = ''; private static $data = array(); // the data from post,put method private static $method; // request method public static function send($url, $method = 'get', $data = array()) { if (!$url) exit('url can not be null'); list (self::$url, self::$method, self::$data) = [$url, $method, $data]; self::$refererUrl = self::_getPureUrl(); if (!self::_isValidMethod()) { exit('error request method type!'); } return self::doRequest(); } private static function _getPureUrl() { $urlArr = parse_url(self::$url); return $urlArr['scheme'] .'://'. $urlArr['host']; } private static function _isValidMethod() { return (in_array(self::$method, array('get', 'post', 'put', 'delete')))? true : false; } /** * make curl request */ private function doRequest() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, self::$url);// set the url curl_setopt($ch, CURLOPT_AUTOREFERER, true); // set the referer url,some website will check this param curl_setopt($ch, CURLOPT_REFERER, self::$refererUrl); /** * special settings about headers * */ $headers = array( 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding:gzip, deflate, sdch', 'Accept-Language:zh-CN,zh;q=0.8', 'Cache-Control:max-age=0', 'Connection:keep-alive' ); curl_setopt($ch, CURLOPT_HEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// set the curl return the transfer if(self::$method == 'post') curl_setopt($ch, CURLOPT_POST, 1);//if use post method,set the flag if (!empty(self::$data)) { self::$data = self::buildPostStr(self::$data); curl_setopt($ch, CURLOPT_POSTFIELDS, self::$data); } $data = curl_exec($ch); curl_close($ch); return $data; } /** * make the post data to string. * * @param array $postData * @return string */ public function buildPostStr($postData) { $postStr = ''; if (!is_array($postData)) exit('post data should be array'); foreach ($postData as $k => $v) { $postStr .= "$k=" . urlencode($v) . "&"; } return substr($postStr, 0, -1); } } /** * client to run */ set_time_limit(0); require 'Analyzer.php'; $start = microtime(true); $urls = file_get_contents('E:\nodejs\chapterUrls.txt'); $urls = array_unique(explode("\r\n", $urls)); $analyzer =new Analyzer(); foreach ($urls as $url) { $res = MyCurl::send($url, 'get'); $title = $analyzer->getTitle($res)[1]; $content = $analyzer->getContent('div', 'content', $res)[0]; $allContents = $title . "<br/>". $content; $filePath = './juewangjiaoshi/' . $title . '.html'; if(!file_exists($filePath)) { $analyzer->storeToFile($filePath, $allContents); } else { continue; } echo 'down the url:' , $url , "\r\n"; } $end = microtime(true); $cost = $end - $start; echo "total cost time:" . round($cost, 3) . " seconds\r\n";
從以前的160+行縮減到116行。
1.把一些變量命名修改爲更易讀的,好比$oriUrl不明因此,改成$refererUrl.
2.將一些組裝和處理參數的過程從新extract method,將putRequest之類的刪去,把整個類變得更乾淨。
3.把在foreach中的new Analyzer()移出去,防止重複去new。
4.刪除調試和被註釋掉的代碼,讓一切不使用的代碼都灰飛煙滅吧!
我依然保留了一些註釋,我認爲足夠精準,且有引導做用。我不徹底贊同0註釋,我更傾向於極簡的代碼+必要補充性註釋。
關於減小注釋或者說徹底消滅註釋,要根據狀況和項目而定。若是是我的項目,建議能夠儘可能減小沒必要要註釋,用代碼可讀性去代替註釋做用。可是因爲不少項目是多人合做,每一個人對英文的掌握能力和理解能力等編程相關能力各不一樣,一味追求0註釋,可能形成代碼和業務更難被熟悉和理解。在一些複雜業務中,良好的註釋不可或缺,好比繁瑣的結算,好比驗證規則多樣,都須要有對業務的分析和總結的註釋來引導理解代碼邏輯。
總之,減小爲了彌補代碼寫得不清不楚或抽象層分層不清晰的註釋,保留和優化補充和提示性的註釋,同時持續保持代碼最簡。