敏捷開發的必要技巧:將注釋轉為代碼

發表于:2007-04-28來源:作者:點擊數: 標簽:敏捷開發轉為必要注釋
示例 這是一個會議管理系統. 在會議中,每個參會者都會戴一個牌子,這牌子上面有這個參會者的信息(比如姓名之類的).在這個系統中,Badge這個類用來存放這個參會者的信息.請看一下下面的代碼跟注釋: //存放參會者身上戴的牌子所顯示的信息. public class Badge {
示例

這是一個會議管理系統. 在會議中,每個參會者都會戴一個牌子,這牌子上面有這個參會者的信息(比如姓名之類的).在這個系統中,Badge這個類用來存放這個參會者的信息.請看一下下面的代碼跟注釋:

    //存放參會者身上戴的牌子所顯示的信息. 
    public class Badge {
        String pid;  //參會者 ID
        String engName; //英文全名
        String chiName; //中文全名
        String engOrgName; //所在部門英文名稱
        String chiOrgName; //所在部門中文名稱
        String engCountry; //部門所在國家的中文名稱
        String chiCountry; //部門所在國家的英文名稱

        //***********************
        //構造函數.
        //根據參會者的id,去數據庫取出該參與者的信息.
        //***********************
       Badge(String pid) {
           this.pid = pid;
           //***********************
           //取出參會者
           //***********************
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(pid);
           if (part != null) {
              //取出參會者的英文全名
              engName = part.getELastName() + ", " + part.getEFirstName();
              //取出參會者的中文全名
              chiName = part.getCLastName()+part.getCFirstName();
              //***********************
              //取出所在部門跟國家.
              //***********************
              OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
              //取出所在部門的id.
              String oid = orgsInDB.getOrganization(pid);
              if (oid != null) {
                  Organization org = orgsInDB.locateOrganization(oid);
                  engOrgName = org.getEName();
                  chiOrgName = org.getCName();
                  engCountry = org.getEAddress().getCountry();
                  chiCountry = org.getCAddress().getCountry();
               }
           }
        }

        ...

    }


將注釋轉換為代碼,讓代碼足夠清楚到可以表示注釋

我們先看一下第一個注釋:

    //存放參會者身上戴的牌子所顯示的信息. 
    public class Badge {

        ...

    }


我們干嘛需要這個注釋呢?因為程序員認為"Badge"這個類名不足以讓讀代碼的人清楚這個類的作用,所以就寫了這個注釋. 那如果我們直接將注釋所表達的一些信息放在類名里面的話,就沒有單獨寫注釋的必要了.比如::

    public class ParticipantInfoOnBadge { 

        ...

    }


其實很多人肯定會問?難道寫注釋不是一個好的編程習慣嗎?這問題很好,我也想知道.在解釋之前,我們先把這個示例中所有的注釋都轉為代碼先.

將注釋轉換為變量名

Consider: 

    public class ParticipantInfoOnBadge {
        String pid;  //參會者 ID
        String engName; //英文全名
        String chiName; //中文全名
        String engOrgName; //所在部門英文名稱
        String chiOrgName; //所在部門中文名稱
        String engCountry; //部門所在國家的中文名稱
        String chiCountry; //部門所在國家的英文名稱

        ...

    }


這里,我們就像對屬性的注釋,轉化為屬性名, 比如:

    public class ParticipantInfoOnBadge { 
        String participantId;
        String participantEngFullName;
        String participantChiFullName;
        String engOrgName;
        String chiOrgName;
        String engOrgCountry;
        String chiOrgCountry;

        ...

     }


對參數的注釋,轉化為參數名

看看:

    public class ParticipantInfoOnBadge { 

        ...

        //***********************
        //構造函數.
        //根據參會者的id,從數據庫取出該參與者的信息.
        //***********************
        ParticipantInfoOnBadge(String pid) {
           this.pid = pid;

            ...

        }
     }


比如:

    public class ParticipantInfoOnBadge { 

        ...

        //***********************
        //構造函數.
        //從數據庫取出該參與者的信息.
        //***********************
        ParticipantInfoOnBadge(String participantId) {
           this.participantId = participantId;

            ...

        }
     }


將注釋轉換為方法的一部分

上面的構造函數中,有兩句注釋,第一句我們已經解決了,那么還有"從數據庫取出該參與者的信息"?  這句注釋描述了,這個構造函數是如何實現的(就是從數據庫里面取出信息),我們將這句話轉化:

    public class ParticipantInfoOnBadge { 

        ...

        //***********************
        //構造函數.
        //***********************
        ParticipantInfoOnBadge(String participantId) {
           loadInfoFromDB(participantId);//現在,看一下這個構造函數內部,我們就能知道這個構造函數是做什么了吧.
        }
        void loadInfoFromDB(String participantId) {
           this.participantId = participantId;

            ...

        }
     }


刪掉沒用的注釋

有時候,我們會碰到一些注釋,很明顯沒什么用處的,比如:

    public class ParticipantInfoOnBadge { 

        ...

        //***********************
        //構造函數.
        //***********************
        ParticipantInfoOnBadge(String participantId) {

            ...

        }
     }


就算去掉這些注釋,我們也能看得出來,這是個構造函數.這個注釋并沒什么用處.
什么樣的類是看代碼的人最喜歡的?那就是簡單易看的類.一個設計得好的類,能夠讓人家一眼就能出你這個類都有些什么東西,明白你這個類都做了一些什么事.如果看這個類的時候,要不停的將屏幕滾來滾去,而思維還要隨屏幕的滾動跳轉,無形中,看懂這個類需要花的時間就多了.
一個屏幕,差不多只能顯示20行左右的代碼,而這個沒用的注釋,一下子就占用了3行的代碼,一些有用的信息反而被擠掉了(比如說代碼),得不償失啊!我看還是趕緊移除這個注釋:

    public class ParticipantInfoOnBadge {

        ...

        ParticipantInfoOnBadge(String participantId) {

            ...

        }
     }


將一部分代碼重構成方法,用方法名來表達注釋的意思

先看看下面這個注釋:

        void loadInfoFromDB(String participantId) { 
           this.participantId = participantId;
           //***********************
           //取得參會者的全名.
           //***********************
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(participantId);
           if (part != null) {
               //取得參會者的英文全名.
               engFullName = part.getELastName() + ", " + part.getEFirstName();
               //取得參會者的中文全名.
               chiFullName = part.getCLastName()+part.getCFirstName();
               //***********************
               //取得參會者所在部門和國家.
               //***********************
               OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
               //取得參會者被雇傭部門的id.
               String oid = orgsInDB.getOrganization(participantId);
               if (oid != null) {
                  Organization org = orgsInDB.locateOrganization(oid);
                   engOrgName = org.getEName();
                   chiOrgName = org.getCName();
                   engOrgCountry = org.getEAddress().getCountry();
                   chiOrgCountry = org.getCAddress().getCountry();
               }
            }
        }


現在我們已經看清這段注釋要表達一些什么信息,如果要使代碼跟注釋一樣清楚,我們可以將注釋所解釋的那部分代碼抽取出來,做成一個方法,然后讓方法名來表達注釋的意思.如果可以的話,我們就不需要額外的注釋了:

        void loadInfoFromDB(String participantId) { 
           this.participantId = participantId;
           getParticipantFullNames(); //(取得參會者的全名,注意,我們已經將注釋去掉了.)
            //***********************
            //取得參會者所在部門和國家.
            //***********************
            //取得參會者被雇傭部門的id.
           OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
           String oid = orgsInDB.getOrganization(participantId);
           if (oid != null) {
               Organization org = orgsInDB.locateOrganization(oid);
               engOrgName = org.getEName();
               chiOrgName = org.getCName();
               engOrgCountry = org.getEAddress().getCountry();
               chiOrgCountry = org.getCAddress().getCountry();
            }
        }
        void getParticipantFullNames() {
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(participantId);
           if (part != null) {
               //取得參會者的英文全名.
               engFullName = part.getELastName() + ", " + part.getEFirstName();
               //取得參會者的中文全名.
               chiFullName = part.getCLastName()+part.getCFirstName();
            }
        }


此外,還有一個注釋:"取得參會者所在部門和國家",也是可以重構在方法名里面的:

        void loadInfoFromDB(String participantId) { 
           this.participantId = participantId;
           getParticipantFullNames();
           getOrgNameAndCountry(); //又抽取掉了一個注釋
        }
        void getParticipantFullNames() {
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(participantId);
           if (part != null) {
               //取得參會者的英文全名.
               engFullName = part.getELastName() + ", " + part.getEFirstName();
               //取得參會者的中文全名.
               chiFullName = part.getCLastName()+part.getCFirstName();
            }
        }
        void getOrgNameAndCountry() {
           OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
           //取得參會者被雇傭部門的id.
           String oid = orgsInDB.getOrganization(participantId);
           if (oid != null) {
               Organization org = orgsInDB.locateOrganization(oid);
               engOrgName = org.getEName();
               chiOrgName = org.getCName();
               engOrgCountry = org.getEAddress().getCountry();
               chiOrgCountry = org.getCAddress().getCountry();
            }
        }


抽取出方法,放于另一個類

請看一下下面這兩個注釋:

    public class ParticipantInfoOnBadge { 

        ...

        void getParticipantFullNames() {
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(participantId);
           if (part != null) {
               //取得參會者的英文全名.
               engFullName = part.getELastName() + ", " + part.getEFirstName();
               //取得參會者的中文全名.
               chiFullName = part.getCLastName()+part.getCFirstName();
            }
        }
     }


因為程序員覺得,這些代碼片段還是不夠清楚,所以還是要用注釋還解釋它們. 但這回移除注釋時,我們會將抽取出來的方法,放到Participant這個類里面,而不是ParticipantInfoOnBadge了:

    public class ParticipantInfoOnBadge { 

        ...

        void getParticipantFullNames() {
           ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
           Participant part = partsInDB.locateParticipant(participantId);
           if (part != null) {
               engFullName = part.getEFullName(); //將職責交給domain自己,也就是Participant.
               chiFullName = part.getCFullName();
            }
        }
     }
    public class Participant {
        String getEFullName() {
           return getELastName() + ", " + getEFirstName();
        }
        String getCFullName() {
           return getCLastName() + getCFirstName();
        }
     }


用注釋去命名一個已經存在的方法

請看下面的注釋,也是這個例子中的最后一個注釋了:

    public class ParticipantInfoOnBadge { 

        ...

        void getOrgNameAndCountry() {
           OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
           //取得參會者被雇傭部門的id.
           String oid = orgsInDB.getOrganization(participantId);
           if (oid != null) {
               Organization org = orgsInDB.locateOrganization(oid);
               engOrgName = org.getEName();
               chiOrgName = org.getCName();
               engOrgCountry = org.getEAddress().getCountry();
               chiOrgCountry = org.getCAddress().getCountry();
            }
        }
     }


我們之所以要用這個注釋"取得參會者被雇傭部門的id",是因為這個方法名"getOrganization"取得不夠清楚. 所以,我們將注釋表達的信息,放在這個方法名里面:

    public class ParticipantInfoOnBadge { 

        ...

        void getOrgNameAndCountry() {
           OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
           String oid = orgsInDB.findOrganizationEmploying(participantId);
           if (oid != null) {
               Organization org = orgsInDB.locateOrganization(oid);
               engOrgName = org.getEName();
               chiOrgName = org.getCName();
               engOrgCountry = org.getEAddress().getCountry();
               chiOrgCountry = org.getCAddress().getCountry();
            }
        }
     }

    public class OrganizationsInDB {

        ...

        void findOrganizationEmploying(String participantId) {

            ...

        }
     }


pdf下載http://www.blogjava.net/Files/Wingel/敏捷開發的必要技巧第1,2章.rar

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97