zoukankan      html  css  js  c++  java
  • 代码简洁之三:减少注释 增加代码可读性

    最近一直在研读《代码简洁之道》这本书,里面很多非常细致的对代码重构和简化的好的思想和方法值得学习,我做了一些笔记,在之前的一些博客中也有涉及。

    关于注释,各家有各家的想法。有人认为注释越详细越好,从目的到参数含义,无微不至的去写注解,比如api接口之类的。也有人认为,涉及复杂的业务逻辑,需要写必要注释(之前我也是这么认为的)。也有人认为注释是罪恶根源,不该写任何注释,应该让清晰易懂的代码自己说话。

    我想起了很久之前看涵哥写的api项目,里面几乎没有什么冗余的注释,代码简洁到了极致,每一步都像在读一句诗。而且大量使用componets方式,用大量组合对象去单独处理,减少耦合。当时我问过他为何看不到什么注释,他答:代码是最好的注释。

    以前不是非常认同,还是认为注释不能缺少,特别是业务非常复杂,注释甚至能帮助理清逻辑业务,也作为思路的一种记录。

    博客园上已经出现了一篇不错的文章,讲不要滥用注释:

    http://www.cnblogs.com/leotsai/p/anti-code-comment.html

    而《代码简洁之道》讲的更透彻,妙语连珠,下面是我记录的一些笔记:

    注释的唯一恰当的用处在于弥补我们用代码解析意图所遭遇的失败。

    注释存在时间越久,它和真实代码之间的关系就越来越淡,最终甚至全错。

    应该把主要精力用在写清晰的代码上,直接保证无须编写注释。

    注释不能美化糟糕的代码。

    注释协助如何改写代码,让注释消失,让代码更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:
    odejschapterUrls.txt');
    $urls = array_unique(explode("
    ", $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];
        
        
        // &nbsp;&nbsp;&nbsp;&nbsp;
        
        
        $allContents = $title . "<br/>". $content;
        $filePath = './juewangjiaoshi/' . $title . '.html';
        if(!file_exists($filePath)) {
            $analyzer->storeToFile($filePath, $allContents);
        } else {
            continue;
        }
        echo 'down the url:' , $url , "
    ";
       /* $sql = "insert into desks (title,content) values('" . $title . "','" . "$content')";
        $fn = fopen('sql.txt', 'a+');
        fwrite($fn, $sql . "
    ");
        fclose($fn);
        echo $sql;die();
        mysqli_query($conn, $sql);*/
    }
    
    $end = microtime(true);
    $cost = $end - $start;
    echo "total cost time:" . round($cost, 3) . " seconds
    ";
    View Code

    由于我不小心,把文件的中文注释搞成乱码了,又没法恢复,大家将就着看。里面充斥着命名不规范的变量和多余的废话似的注释,还有一些因为为了考虑未来需求而冗余的代码(如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:
    odejschapterUrls.txt');
    $urls = array_unique(explode("
    ", $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 , "
    ";
    }
    
    $end = microtime(true);
    $cost = $end - $start;
    echo "total cost time:" . round($cost, 3) . " seconds
    ";

    从之前的160+行缩减到116行。

    1.把一些变量命名修改成更易读的,比如$oriUrl不明所以,改为$refererUrl.

    2.将一些组装和处理参数的过程重新extract method,将putRequest之类的删去,把整个类变得更干净。

    3.把在foreach中的new Analyzer()移出去,防止重复去new。

    4.删除调试和被注释掉的代码,让一切不使用的代码都灰飞烟灭吧!

    我依然保留了一些注释,我认为足够精准,且有引导作用。我不完全赞同0注释,我更倾向于极简的代码+必要补充性注释。

    关于减少注释或者说完全消灭注释,要根据情况和项目而定。如果是个人项目,建议可以尽量减少不必要注释,用代码可读性去代替注释作用。但是由于很多项目是多人合作,每个人对英文的掌握能力和理解能力等编程相关能力各不同,一味追求0注释,可能造成代码和业务更难被熟悉和理解。在一些复杂业务中,良好的注释不可或缺,比如繁琐的结算,比如验证规则多样,都需要有对业务的分析和总结的注释来引导理解代码逻辑。

    总之,减少为了弥补代码写得不清不楚或抽象层分层不清晰的注释,保留和优化补充和提示性的注释,同时持续保持代码最简。

  • 相关阅读:
    Jquery ajax异步传值的两个实用的方法,你看后肯定会用第二个
    C# ASP.NET 转换为int型的方法 很实用
    NetCore 发送邮件
    解决Visual Studio For Mac Restore失败的问题
    (转)JSONObject的toBean 和 fromObject
    javax.servlet不存在的问题
    关于范式的解说
    在远程连接mysql数据库出现问题怎么办
    (二)SpringCloud学习系列-SpringCloud
    (一)SpringCloud学习系列-微服务
  • 原文地址:https://www.cnblogs.com/freephp/p/5112135.html
Copyright © 2011-2022 走看看