superword中一次精彩的重構

咱們先來看看須要重構的功能是一個下拉選擇框,可任意選擇11部詞典中的一部,訪問地址:http://123.56.99.179/select/dictionary-select.jsp?dict=RANDOMHOUSE,在HTML中的效果以下圖所示:html

HTML代碼以下:java

<select name="dict" id="dict" onchange="update();">

    <option value="ICIBA">iCIBA</option>
    <option value="YOUDAO">Youdao</option>
    <option value="COLLINS">Collins</option>
    <option value="WEBSTER">Webster's</option>
    <option value="OXFORD">Oxford</option>
    <option value="CAMBRIDGE">Cambridge</option>
    <option value="MACMILLAN">Macmillan</option>
    <option value="HERITAGE">Heritage</option>
    <option value="WIKTIONARY">Wiktionary</option>
    <option value="WORDNET">WordNet</option>
    <option value="RANDOMHOUSE" selected="selected">RandomHouse</option>

</select>


咱們接下來看看最初的JSP代碼是如何實現這個功能的:git

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apdplat.superword.tools.WordLinker" %>
<%@ page import="org.apdplat.superword.tools.WordLinker.Dictionary" %>

        <select name="dict" id="dict" onchange="update();">
    <%
        if (Dictionary.ICIBA==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA" selected="selected">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.YOUDAO==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO" selected="selected">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.COLLINS==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS" selected="selected">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.WEBSTER==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER" selected="selected">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.OXFORD==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD" selected="selected">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.CAMBRIDGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE" selected="selected">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.MACMILLAN==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN" selected="selected">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.HERITAGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE" selected="selected">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.WIKTIONARY==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY" selected="selected">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
            <%
    } else if (Dictionary.WORDNET==WordLinker.getValidDictionary(request.getParameter("dict"))) {
            %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET" selected="selected">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.RANDOMHOUSE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">愛詞霸</option>
            <option value="YOUDAO">有道</option>
            <option value="COLLINS">柯林斯</option>
            <option value="WEBSTER">韋氏</option>
            <option value="OXFORD">牛津</option>
            <option value="CAMBRIDGE">劍橋</option>
            <option value="MACMILLAN">麥克米倫</option>
            <option value="HERITAGE">美國傳統</option>
            <option value="WIKTIONARY">維基詞典</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE" selected="selected">RandomHouse</option>
    <%
    }
    %>
        </select>


這段代碼有什麼問題呢?程序員

若是咱們一次寫好後就不須要維護和更改這段代碼,那麼根據本身的經驗知識和理解快速實現功能,知足要求便可。github

可是,若是須要維護代碼和擴展功能呢?好比,我如今要把選項顯示的全部的中文所有改成英文,那麼就變成以下代碼了:設計模式

        <select name="dict" id="dict" onchange="update();">
    <%
        if (Dictionary.ICIBA==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA" selected="selected">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.YOUDAO==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO" selected="selected">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.COLLINS==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS" selected="selected">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.WEBSTER==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER" selected="selected">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.OXFORD==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD" selected="selected">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.CAMBRIDGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE" selected="selected">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.MACMILLAN==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN" selected="selected">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.HERITAGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE" selected="selected">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.WIKTIONARY==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY" selected="selected">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
            <%
    } else if (Dictionary.WORDNET==WordLinker.getValidDictionary(request.getParameter("dict"))) {
            %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET" selected="selected">WordNet</option>
            <option value="RANDOMHOUSE">RandomHouse</option>
    <%
    } else if (Dictionary.RANDOMHOUSE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
    %>
            <option value="ICIBA">iCIBA</option>
            <option value="YOUDAO">Youdao</option>
            <option value="COLLINS">Collins</option>
            <option value="WEBSTER">Webster's</option>
            <option value="OXFORD">Oxford</option>
            <option value="CAMBRIDGE">Cambridge</option>
            <option value="MACMILLAN">Macmillan</option>
            <option value="HERITAGE">Heritage</option>
            <option value="WIKTIONARY">Wiktionary</option>
            <option value="WORDNET">WordNet</option>
            <option value="RANDOMHOUSE" selected="selected">RandomHouse</option>
    <%
    }
    %>
        </select>


你可能說,我只須要執行 CTRL+R 11次,沒啥問題啊?其實這偏偏就是問題,由於一樣的字符串重複了11次。架構

改爲了英文名稱以後,接下來,若是咱們要新增一個選項怎麼辦呢?咱們不但須要複製粘貼代碼來新增一個ELSE IF代碼塊,咱們還須要修改既有的11個IF代碼塊,都新增一個option。這不但違反了DRY原則,也違反了開閉原則。下面開始來改造,改造後的代碼以下:dom

    <select name="dict" id="dict" onchange="update();">
        <%
        if (Dictionary.ICIBA==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="ICIBA" selected="selected">iCIBA</option>
        <%
        } else {
        %>
        <option value="ICIBA">iCIBA</option>
        <%
        }
        if (Dictionary.YOUDAO==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="YOUDAO" selected="selected">Youdao</option>
        <%
        } else {
        %>
        <option value="YOUDAO">Youdao</option>
        <%
        }
        if (Dictionary.COLLINS==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="COLLINS" selected="selected">Collins</option>
        <%
        } else {
        %>
        <option value="COLLINS">Collins</option>
        <%
        }
        if (Dictionary.WEBSTER==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="WEBSTER" selected="selected">Webster's</option>
        <%
        } else {
        %>
        <option value="WEBSTER">Webster's</option>
        <%
        }
        if (Dictionary.OXFORD==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="OXFORD" selected="selected">Oxford</option>
        <%
        } else {
        %>
        <option value="OXFORD">Oxford</option>
        <%
        }
        if (Dictionary.CAMBRIDGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="CAMBRIDGE" selected="selected">Cambridge</option>
        <%
        } else {
        %>
        <option value="CAMBRIDGE">Cambridge</option>
        <%
        }
        if (Dictionary.MACMILLAN==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="MACMILLAN" selected="selected">Macmillan</option>
        <%
        } else {
        %>
        <option value="MACMILLAN">Macmillan</option>
        <%
        }
        if (Dictionary.HERITAGE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="HERITAGE" selected="selected">Heritage</option>
        <%
        } else {
        %>
        <option value="HERITAGE">Heritage</option>
        <%
        }
        if (Dictionary.WIKTIONARY==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="WIKTIONARY" selected="selected">Wiktionary</option>
        <%
        } else {
        %>
        <option value="WIKTIONARY">Wiktionary</option>
        <%
        }
        if (Dictionary.WORDNET==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="WORDNET" selected="selected">WordNet</option>
        <%
        } else {
        %>
        <option value="WORDNET">WordNet</option>
        <%
        }
        if (Dictionary.RANDOMHOUSE==WordLinker.getValidDictionary(request.getParameter("dict"))) {
        %>
        <option value="RANDOMHOUSE" selected="selected">RandomHouse</option>
        <%
        } else {
        %>
        <option value="RANDOMHOUSE">RandomHouse</option>
        <%
        }
        %>
    </select>


重構代碼後是否是可讀性下降了?原來的代碼雖然違反了DRY原則開閉原則,可是可讀性倒是極好的。即便如此,重構後的代碼倒是很是容易擴展,新增選項只須要增長一個IF代碼塊便可,不須要修改現有的IF代碼塊,符合了開閉原則,同時移除了重複了11次的option,因此雖然可讀性下降了,可是卻完美達成了DRY原則開閉原則jsp

這個例子說明了一個很是重要的道理,具體的東西更容易讓人理解,而更抽象的東西理解起來就要更費勁,因此,咱們在寫代碼的時候,一開始徹底沒有必要滿腦子的各類最佳實踐,各類設計模式,各類架構模式,最佳實踐設計模式架構模式都有限制的場景,他們都應該是重構天然而然的結果,一開始就考慮這些東西,不但會拖慢功能實現的速度,並且每每會陷於「過分設計」「不成熟的優化」的泥淖。優化

上面的代碼還不夠完全,還存在重複,接着重構來貫徹DRY原則

    <select name="dict" id="dict" onchange="update();">
        <%
        Dictionary selectedDictionary = WordLinker.getValidDictionary(request.getParameter("dict"));
        if (Dictionary.ICIBA == selectedDictionary) {
        %>
            <option value="ICIBA" selected="selected">iCIBA</option>
        <%
        } else {
        %>
            <option value="ICIBA">iCIBA</option>
        <%
        }

        if (Dictionary.YOUDAO == selectedDictionary) {
        %>
            <option value="YOUDAO" selected="selected">Youdao</option>
        <%
        } else {
        %>
            <option value="YOUDAO">Youdao</option>
        <%
        }

        if (Dictionary.COLLINS == selectedDictionary) {
        %>
            <option value="COLLINS" selected="selected">Collins</option>
        <%
        } else {
        %>
            <option value="COLLINS">Collins</option>
        <%
        }

        if (Dictionary.WEBSTER == selectedDictionary) {
        %>
            <option value="WEBSTER" selected="selected">Webster's</option>
        <%
        } else {
        %>
            <option value="WEBSTER">Webster's</option>
        <%
        }

        if (Dictionary.OXFORD == selectedDictionary) {
        %>
            <option value="OXFORD" selected="selected">Oxford</option>
        <%
        } else {
        %>
            <option value="OXFORD">Oxford</option>
        <%
        }

        if (Dictionary.CAMBRIDGE == selectedDictionary) {
        %>
            <option value="CAMBRIDGE" selected="selected">Cambridge</option>
        <%
        } else {
        %>
            <option value="CAMBRIDGE">Cambridge</option>
        <%
        }

        if (Dictionary.MACMILLAN == selectedDictionary) {
        %>
            <option value="MACMILLAN" selected="selected">Macmillan</option>
        <%
        } else {
        %>
            <option value="MACMILLAN">Macmillan</option>
        <%
        }

        if (Dictionary.HERITAGE == selectedDictionary) {
        %>
            <option value="HERITAGE" selected="selected">Heritage</option>
        <%
        } else {
        %>
            <option value="HERITAGE">Heritage</option>
        <%
        }

        if (Dictionary.WIKTIONARY == selectedDictionary) {
        %>
            <option value="WIKTIONARY" selected="selected">Wiktionary</option>
        <%
        } else {
        %>
            <option value="WIKTIONARY">Wiktionary</option>
        <%
        }

        if (Dictionary.WORDNET == selectedDictionary) {
        %>
            <option value="WORDNET" selected="selected">WordNet</option>
        <%
        } else {
        %>
            <option value="WORDNET">WordNet</option>
        <%
        }

        if (Dictionary.RANDOMHOUSE == selectedDictionary) {
        %>
            <option value="RANDOMHOUSE" selected="selected">RandomHouse</option>
        <%
        } else {
        %>
            <option value="RANDOMHOUSE">RandomHouse</option>
        <%
        }
        %>
    </select>


此次,咱們把重複的代碼抽取爲一個變量,並在IF代碼塊前面加了一個空行,看上去是否是可讀性提升了?這也說明了DRY原則對於代碼的簡潔易讀是有幫助的,同時也說明了咱們編寫的代碼的換行縮進等風格對可讀性也是有影響的,做爲一個有尊嚴的程序員,須要注意這些細節,細節決定成敗,成功者每每只是比對手多作了一點而已,而多作的這一點,每每就是在細節上面。

雖然易讀性有了提升,可是仍是比較糟糕,離生成的HTML的差距還很大,下面繼續重構,結果以下:

<%
    Dictionary selectedDictionary = WordLinker.getValidDictionary(request.getParameter("dict"));
    String ICIBA = "";
    String YOUDAO = "";
    String COLLINS = "";
    String WEBSTER = "";
    String OXFORD = "";
    String CAMBRIDGE = "";
    String MACMILLAN = "";
    String HERITAGE = "";
    String WIKTIONARY = "";
    String WORDNET = "";
    String RANDOMHOUSE = "";
    String selected = "selected=\"selected\"";
    switch (selectedDictionary){
        case ICIBA:
            ICIBA = selected; break;
        case YOUDAO:
            YOUDAO = selected; break;
        case COLLINS:
            COLLINS = selected; break;
        case WEBSTER:
            WEBSTER = selected; break;
        case OXFORD:
            OXFORD = selected; break;
        case CAMBRIDGE:
            CAMBRIDGE = selected; break;
        case MACMILLAN:
            MACMILLAN = selected; break;
        case HERITAGE:
            HERITAGE = selected; break;
        case WIKTIONARY:
            WIKTIONARY = selected; break;
        case WORDNET:
            WORDNET = selected; break;
        case RANDOMHOUSE:
            RANDOMHOUSE = selected; break;
    }
%>
<select name="dict" id="dict" onchange="update();">
    <option value="ICIBA" <%=ICIBA%>>iCIBA</option>
    <option value="YOUDAO" <%=YOUDAO%>>Youdao</option>
    <option value="COLLINS" <%=COLLINS%>>Collins</option>
    <option value="WEBSTER" <%=WEBSTER%>>Webster's</option>
    <option value="OXFORD" <%=OXFORD%>>Oxford</option>
    <option value="CAMBRIDGE" <%=CAMBRIDGE%>>Cambridge</option>
    <option value="MACMILLAN" <%=MACMILLAN%>>Macmillan</option>
    <option value="HERITAGE" <%=HERITAGE%>>Heritage</option>
    <option value="WIKTIONARY" <%=WIKTIONARY%>>Wiktionary</option>
    <option value="WORDNET" <%=WORDNET%>>WordNet</option>
    <option value="RANDOMHOUSE" <%=RANDOMHOUSE%>>RandomHouse</option>
</select>


此次重構事後,看起來是否是跟最終生成的HTML差異已經不大了?易讀性有了質的飛躍,可是你有沒有發現,這裏面仍是有不少重複,並且存在着模式和規律,咱們能夠再繼續重構嗎?

確定能夠,直接看重構後的結果吧:

    <select name="dict" id="dict" onchange="update();">
        <%
        Dictionary selectedDictionary = WordLinker.getValidDictionary(request.getParameter("dict"));
        for(Dictionary dictionary : Dictionary.values()){
            if (dictionary == selectedDictionary) {
        %>
            <option value="<%=dictionary.name()%>" selected="selected"><%=dictionary.getDes()%></option>
        <%
            } else {
        %>
            <option value="<%=dictionary.name()%>"><%=dictionary.getDes()%></option>
        <%
            }
        }
        %>
    </select>


此次,咱們直接遍歷數據模型Dictionary,從而徹底消除了重複,同時在開閉原則上也有了新的高度,之後當咱們須要擴展新的選項的時候,咱們已經再也不須要修改哪怕一行代碼了。


那若是咱們不是須要Dictionary的全部選項怎麼辦呢?這確定也不是問題,解決方法以下:

<%!
    private static final List<Dictionary> DICTIONARIES = Arrays.asList(Dictionary.ICIBA, Dictionary.YOUDAO, Dictionary.WEBSTER, Dictionary.OXFORD);
%>
<select name="dictionary" id="dictionary" onchange="update();">
    <%
        Dictionary selectedDictionary = WordLinker.getValidDictionary(request.getParameter("dictionary"));
        for(Dictionary dictionary : DICTIONARIES){
            if (dictionary == selectedDictionary) {
    %>
    <option value="<%=dictionary.name()%>" selected="selected"><%=dictionary.getDes()%></option>
    <%
    } else {
    %>
    <option value="<%=dictionary.name()%>"><%=dictionary.getDes()%></option>
    <%
            }
        }
    %>
</select>


一次完美的重構就此結束,要想嘗試更多的重構工做,敬請加入到superword的重構中來:https://github.com/ysc/superword

相關文章
相關標籤/搜索