版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第第1章章重構(gòu)與代碼味道重構(gòu)與代碼味道劉劉 偉偉 (Sunny)weiliu_內(nèi)容w 重構(gòu)w 代碼味道w 代碼味道識(shí)別工具重構(gòu) 軟件開(kāi)發(fā)方法學(xué)的泰山北斗,是最早研究軟件開(kāi)發(fā)模式和重構(gòu)的人之一,軟件開(kāi)發(fā)方法學(xué)的泰山北斗,是最早研究軟件開(kāi)發(fā)模式和重構(gòu)的人之一,是是敏捷開(kāi)發(fā)的開(kāi)創(chuàng)者之一敏捷開(kāi)發(fā)的開(kāi)創(chuàng)者之一,更是,更是極限編程極限編程(XP)和測(cè)試驅(qū)動(dòng)開(kāi)發(fā)和測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD)的的創(chuàng)始人創(chuàng)始人,同時(shí)還是,同時(shí)還是JUnit的作者,對(duì)當(dāng)今世界的軟件開(kāi)發(fā)影響深遠(yuǎn)。的作者,對(duì)當(dāng)今世界的軟件開(kāi)發(fā)影響深遠(yuǎn)。重構(gòu)國(guó)際著名面向?qū)ο髮<?,敏捷開(kāi)發(fā)方法的創(chuàng)始人之一,是國(guó)際著名面向?qū)ο髮<?,敏捷開(kāi)發(fā)方法的創(chuàng)始人之一,是
2、面向?qū)ο蠓治雒嫦驅(qū)ο蠓治鲈O(shè)計(jì)、設(shè)計(jì)、UML、模式、軟件開(kāi)發(fā)方法學(xué)、模式、軟件開(kāi)發(fā)方法學(xué)、XP、重構(gòu)、重構(gòu)等領(lǐng)域的世界頂級(jí)專家,等領(lǐng)域的世界頂級(jí)專家,現(xiàn)為現(xiàn)為Thought Works公司的首席科學(xué)家。主要著作包括公司的首席科學(xué)家。主要著作包括分析模式分析模式、企業(yè)應(yīng)用架構(gòu)模式企業(yè)應(yīng)用架構(gòu)模式、UML精粹精粹和和重構(gòu)重構(gòu)等。等。重構(gòu)w 何謂重構(gòu)(Fowlers Definition)重構(gòu)(名詞):重構(gòu)(名詞):對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。低其修改成
3、本。Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.重構(gòu)w 何謂重構(gòu)(Fowlers Definition)重構(gòu)(動(dòng)詞):重構(gòu)(動(dòng)詞):使用一系列重構(gòu)手法,在不改變軟件可使用一系列重構(gòu)手法,在不改變軟件可觀察行為的前提下,調(diào)整其結(jié)構(gòu)。觀察行為的前提下,調(diào)整其結(jié)構(gòu)。Refactor (verb): to restr
4、ucture software by applying a series of refactorings without changing its observable behavior.重構(gòu)w 何謂重構(gòu)(Fowlers Definition)重構(gòu)w 何謂重構(gòu)重構(gòu)重構(gòu)是是在不改變軟件現(xiàn)有功能的基礎(chǔ)上,通過(guò)調(diào)整程序在不改變軟件現(xiàn)有功能的基礎(chǔ)上,通過(guò)調(diào)整程序代碼改善軟件的質(zhì)量、性能,使程序的設(shè)計(jì)和架構(gòu)更趨代碼改善軟件的質(zhì)量、性能,使程序的設(shè)計(jì)和架構(gòu)更趨合理,進(jìn)而提高軟件的擴(kuò)展性和維護(hù)性合理,進(jìn)而提高軟件的擴(kuò)展性和維護(hù)性。 重構(gòu)w 重構(gòu)小實(shí)例(漫畫)重構(gòu)w 重構(gòu)小實(shí)例(漫畫)重構(gòu)w 為何重構(gòu)重構(gòu)改進(jìn)
5、軟件設(shè)計(jì)重構(gòu)改進(jìn)軟件設(shè)計(jì)(Refactoring Improves the Design of Software)重構(gòu)使軟件更容易理解重構(gòu)使軟件更容易理解 (Refactoring Makes Software Easier to Understand)重構(gòu)幫助找到缺陷重構(gòu)幫助找到缺陷 (Refactoring Helps You Find Bugs)重構(gòu)提高編程速度重構(gòu)提高編程速度 (Refactoring Helps You Program Faster)重構(gòu)w 何時(shí)重構(gòu)添加功能時(shí)重構(gòu)添加功能時(shí)重構(gòu) (Refactor When You Add Function)修補(bǔ)錯(cuò)誤時(shí)重構(gòu)修補(bǔ)錯(cuò)誤時(shí)重
6、構(gòu) (Refactor When You Need to Fix a Bug)復(fù)審代碼時(shí)重構(gòu)復(fù)審代碼時(shí)重構(gòu)(Refactor As You Do a Code Review)Three strikes and you refactor.代碼味道w 代碼味道代碼味道:代碼壞味道,代碼味道:代碼壞味道,Bad Smells in Code在在重構(gòu):改善既有代碼的設(shè)計(jì)重構(gòu):改善既有代碼的設(shè)計(jì)一書(shū)一書(shū)中,中,Kent Beck和和Martin Fowler一共一共定義了定義了22種種常用的代碼味道常用的代碼味道代碼味道是指程序中存在的一些代碼味道是指程序中存在的一些不良的不良的編程或設(shè)計(jì)方案編程或設(shè)計(jì)
7、方案代 碼 味 道 可 以 作 為代 碼 味 道 可 以 作 為 重 構(gòu) 的 指 示 劑重 構(gòu) 的 指 示 劑 (indicator)代碼味道w 代碼味道代碼味道w 代碼味道分類1. 類內(nèi)味道類內(nèi)味道1.1 Measured Smells(可度量的味道)(可度量的味道)1.2 Unneccessary Complexity(不必要的復(fù)雜性)(不必要的復(fù)雜性)1.3 Duplication(重復(fù))(重復(fù))1.4 Conditional Logic(條件邏輯)(條件邏輯)代碼味道w 代碼味道分類2. 類間味道類間味道2.1 Data(數(shù)據(jù))(數(shù)據(jù))2.2 Inheritance(繼承)(繼承)2.
8、3 Responsibility(職責(zé))(職責(zé))2.4 Accommodating Change(協(xié)調(diào)變化)(協(xié)調(diào)變化)2.5 Library Classes(庫(kù)類)(庫(kù)類)代碼味道w 1. 類內(nèi)味道1.1 可度量的味道可度量的味道1.1.1 Long Method(過(guò)長(zhǎng)函數(shù))(過(guò)長(zhǎng)函數(shù))1.1.2 Large Class(過(guò)大類)(過(guò)大類)1.1.3 Long Parameter List(過(guò)長(zhǎng)參數(shù)列)(過(guò)長(zhǎng)參數(shù)列)1.1.4 Comments(過(guò)多的注釋)(過(guò)多的注釋)1.2 不必要的復(fù)雜性不必要的復(fù)雜性1.2.1 Speculative Generality(夸夸其談的未來(lái)(夸夸其談的未
9、來(lái)性)性)代碼味道w 1. 類內(nèi)味道1.3 重復(fù)重復(fù)1.3.1 Duplicated Code(重復(fù)代碼)(重復(fù)代碼)1.3.2 Alternative Classes with Different Interfaces(異曲同工的類)(異曲同工的類)1.4 條件邏輯條件邏輯1.4.1 Switch Statements(Switch驚悚現(xiàn)身)驚悚現(xiàn)身)代碼味道w 2. 類間味道2.1 數(shù)據(jù)數(shù)據(jù)2.1.1 Primitive Obsession(基本類型偏執(zhí))(基本類型偏執(zhí))2.1.2 Data Class(純稚的數(shù)據(jù)類)(純稚的數(shù)據(jù)類)2.1.3 Data Clumps(數(shù)據(jù)泥團(tuán))(數(shù)據(jù)泥團(tuán)
10、)2.1.4 Temporary Field(令人迷惑的暫時(shí)值域)(令人迷惑的暫時(shí)值域)代碼味道w 2. 類間味道2.2 繼承繼承2.2.1 Refused Bequest(被拒絕的遺贈(zèng))(被拒絕的遺贈(zèng))2.2.2 Inappropriate Intimacy(狎昵關(guān)系)(狎昵關(guān)系)2.2.3 Lazy Class(冗贅類)(冗贅類)2.3 職責(zé)職責(zé)2.3.1 Feature Envy(依戀情節(jié))(依戀情節(jié))2.3.2 Message Chains(過(guò)度耦合的消息鏈)(過(guò)度耦合的消息鏈)2.3.3 Middle Man(中間轉(zhuǎn)手人)(中間轉(zhuǎn)手人)代碼味道w 2. 類間味道2.4 協(xié)調(diào)變化協(xié)調(diào)變
11、化2.4.1 Divergent Change(發(fā)散式變化)(發(fā)散式變化)2.4.2 Shotgun Surgery(霰彈式修改)(霰彈式修改)2.4.3 Parallel Inheritance Hierarchies(平行繼(平行繼承體系)承體系)2.5 庫(kù)類庫(kù)類2.5.1 Incomplete Library Class(不完善的程序(不完善的程序庫(kù)類)庫(kù)類)代碼味道代碼味道w 1.1.1 過(guò)長(zhǎng)函數(shù)(Long Method)代碼味道w 1.1.1 過(guò)長(zhǎng)函數(shù)(Long Method)代碼味道w 1.1.1 過(guò)長(zhǎng)函數(shù)(Long Method)代碼味道w 1.1.1 過(guò)長(zhǎng)函數(shù)(Long Met
12、hod) 描述描述 A method is too long.(方法太長(zhǎng)。)(方法太長(zhǎng)。) 重構(gòu)手段重構(gòu)手段 把函數(shù)變?。喊押瘮?shù)變?。篍xtract Method(提煉函數(shù))(提煉函數(shù)) 函數(shù)內(nèi)有大量的參數(shù)和臨時(shí)變量:函數(shù)內(nèi)有大量的參數(shù)和臨時(shí)變量:Replace Temp with Query(以查(以查詢?nèi)〈R時(shí)變量)詢?nèi)〈R時(shí)變量) 參數(shù)太多:參數(shù)太多:Introduce Parameter Object(引入?yún)?shù)對(duì)象)、(引入?yún)?shù)對(duì)象)、Preserve Whole Object(保持對(duì)象完整)(保持對(duì)象完整) 太多臨時(shí)變量和注釋:太多臨時(shí)變量和注釋:Replace Method wit
13、h Method Object(以函(以函數(shù)對(duì)象取代函數(shù))數(shù)對(duì)象取代函數(shù)) 條件表達(dá)式和循環(huán):條件表達(dá)式和循環(huán):Decompose Conditional(分解條件表達(dá)式)(分解條件表達(dá)式)代碼味道w 1.1.1 過(guò)長(zhǎng)函數(shù)(Long Method)代碼味道w 1.1.2 過(guò)大類(Large Class) 描述描述 A class is trying to do too much, it often shows up as too many instance variables.(一個(gè)類試圖做太多的事情,通常(一個(gè)類試圖做太多的事情,通常會(huì)出現(xiàn)太多的實(shí)例變量。)會(huì)出現(xiàn)太多的實(shí)例變量。) 重構(gòu)手段
14、重構(gòu)手段 太多實(shí)例變量或太多代碼:太多實(shí)例變量或太多代碼:Extract Class(提煉類)、(提煉類)、Extract Subclass(提煉子類)(提煉子類) 確定客戶端如何使用:確定客戶端如何使用:Extract Interface(提煉接口)(提煉接口) 把數(shù)據(jù)和行為移到一個(gè)獨(dú)立的領(lǐng)域?qū)ο?,但需要保留一些重?fù)把數(shù)據(jù)和行為移到一個(gè)獨(dú)立的領(lǐng)域?qū)ο螅枰A粢恍┲貜?fù)數(shù)據(jù):數(shù)據(jù):Duplicate Observed Data(復(fù)制(復(fù)制“被監(jiān)視數(shù)據(jù)被監(jiān)視數(shù)據(jù)”)代碼味道w 1.1.2 過(guò)大類(Large Class) 實(shí)例實(shí)例public class JTable extends JCom
15、ponent implements Accessible, CellEditorListener, ListSelectionListener, Scrollable, TableColumnModelListener, TableModelListener/ Constantspublic static final int AUTO_RESIZE_ALL_COLUMNSpublic static final int AUTO_RESIZE_LAST_COLUMNpublic static final int AUTO_RESIZE_NEXT_COLUMNpublic static final
16、 int AUTO_RESIZE_OFFpublic static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS/ Constructorspublic JTable()public JTable(TableModel, TableColumnModel)public JTable(TableModel, TableColumnModel, ListSelectionModel)public JTable(int, int)public JTable(Object, Object)public JTable(java.util.Vector, java.ut
17、il.Vector)/ Methodspublic void addColumn(TableColumn column)public void addColumnSelectionInterval(int start, int finish)public void addNotify()public void addRowSelectionInterval(int start, int finish)public void clearSelection()public void columnAdded(TableColumnModelEvent event)public void column
18、AtPoint(Point p)public void columnMarginChanged(ChangeEvent event)public void columnMoved(TableColumnModelEvent event)public void columnRemoved(TableColumnModelEvent event)public void columnSelectionChanged(ListSelectionEvent event)public void convertColumnIndexToModel(int viewColumn)public void con
19、vertColumnIndexToView(int modelColumn)public void createDefaultColumnsFromModel()public boolean editCellAt(int row, int column)public boolean editCellAt(int row, int column, EventObject event)public void editingCanceled(ChangeEvent event)public void editingStopped(ChangeEvent event)public Accessible
20、Context getAccessibleContext()public boolean getAutoCreateColumnsFromModel()public int getAutoResizeMode()public TableCellEditor getCellEditor()public TableCellEditor getCellEditor(int row, int column)public Rectangle getCellRect(int row, int column, boolean includeSpacing)public boolean getCellSele
21、ctionEnabled()public TableColumn getColumn(Object object)public Class getColumnClass(int column)public int getColumnCount()public TableColumnModel getColumnModel()public String getColumnName(int column)public Boolean getColumnSelectionAllowed()public TableCellEditor getDefaultEditor(Class class)publ
22、ic TableCellRenderer getDefaultRenderer(Class class)public int getEditingColumn()public int getEditingRow()public Component getEditorComponent()public Color getGridColor()public Dimension getIntercellSpacing()public TableModel getModel()public Dimension getPreferredScrollableViewportSize()public int
23、 getRowCount()public int getRowHeight()public int getRowMargin()public Boolean getRowSelectionAllowed()public int getScrollableBlockIncrement(Rectangle visible, int orientation, int direction)public Boolean getScrollableTracksViewportHeight()public Boolean getScrollableTracksViewportWidth()public in
24、t getScrollableUnitIncrement(Rectangle visible, int orientation, int direction)public int getSelectedColumn()public int getSelectedColumnCount()public int getSelectedColumns()public int getSelectedRow()public int getSelectedRowCount()public int getSelectedRows()public Color getSelectionBackground()p
25、ublic Color getSelectionForeground()public ListSelectionModel getSelectionModel()public Boolean getShowHorizontalLines()public Boolean getShowVerticalLines()public JTableHeader getTableHeader()public String getToolTipText(MouseEvent event)public TableUI getUI()public String getUIClassID()public Obje
26、ct getValueAt(int row, int column)public Boolean isCellEditable(int row, int column)public Boolean isCellSelected(int row, int column)public Boolean isColumnSelected(int column)public Boolean isEditing()public boolean isManagingFocus()public Boolean isRowSelected(int row)public void moveColumn(int c
27、olumn, int newColumn)public Component prepareEditor(TableCellEditor editor, int row, int column)public Component prepareRenderer(TableCellRenderer renderer, int row, int column)public void removeColumn(TableColumn column)public void removeColumnSelectionInterval(int column1, int column2)public void
28、removeEditor()public void removeRowSelectionInterval(int row1, int row2)public void reshape(int x, int y, int width, int height)public int rowAtPoint(Point point)public void selectAll()public void setAutoCreateColumnsFromModel(Boolean doAutoCreate)public void setAutoResizeModel(int mode)public void
29、setCellEditor(TableCellEditor editor)public void setCellSelectionEnabled(Boolean maySelect)public void setColumnModel(TableColumnModel model)public void setColumnSelectionAllowed(Boolean maySelect)public void setColumnSelectionInterval(int column1, int column2)public void setDefaultEditor(Class clas
30、s, TableCellEditor editor)public void setDefaultRenderer(Class class, TableCellRenderer renderer)public void setEditingColumn(int column)public void setEditingRow(int row)public void setGridColor(Color color)public void setIntercellSpacing(Dimention dim)public void setModel(TableModel model)public v
31、oid setPreferredScrollableViewportSize(Dimension dim)public void setRowHeight(int height)public void setRowMargin(int margin)public void setRowSelectionAllowed(Boolean maySelect)public void setSelectionBackground(Color background)public void setSelectionForeground(Color foreground)public void setSel
32、ectionMode(int mode)public void setSelectionModel(ListSelectionModel model)public void setShowGrid(Boolean showing)public void setShowHorizontalLines(Boolean b)public void setShowVerticalLines(Boolean b)public void setTableHeader(JTableHeader header)public void setUI(TableUI ui)public void setValueA
33、t(Object value, int row, int column)public void sizeColumnsToFit(int resizingColumn)public void tableChanged(TableModelEvent event)public void updateUI()public void valueChanged(ListSelectionEvent)/ plus 22 protected variables/ plus 10 protected methods/ plus 97 methods inherited from JComponent (an
34、d fields etc.)/ plus about 35 methods from Container/ plus about 85 methods from Component/ plus 11 methods from Object代碼味道w 1.1.3 過(guò)長(zhǎng)參數(shù)列(Long Parameter List)描述描述 A method needs passing too many parameters.(一(一個(gè)方法需要傳遞太多的參數(shù)。)個(gè)方法需要傳遞太多的參數(shù)。)重構(gòu)手段重構(gòu)手段 向已有對(duì)象發(fā)出一條請(qǐng)求就可以取代一個(gè)參數(shù):向已有對(duì)象發(fā)出一條請(qǐng)求就可以取代一個(gè)參數(shù):Replace Para
35、meter with Method(以函數(shù)取代參數(shù))(以函數(shù)取代參數(shù)) 參數(shù)缺乏合理的對(duì)象歸屬:參數(shù)缺乏合理的對(duì)象歸屬:Introduce Parameter Object(引(引入?yún)?shù)對(duì)象)入?yún)?shù)對(duì)象) 將來(lái)自同一個(gè)對(duì)象的一堆參數(shù)收集起來(lái):將來(lái)自同一個(gè)對(duì)象的一堆參數(shù)收集起來(lái):Preserve Whole Object(保持對(duì)象完整)(保持對(duì)象完整)代碼味道w 1.1.3 過(guò)長(zhǎng)參數(shù)列(Long Parameter List)實(shí)例實(shí)例 java.swing.CellRendererPane public void paintComponent (Graphics gr, Component re
36、nderer, Container parent, int x, int y, int width, int height, Boolean shouldValidate) java.awt.Graphics public Boolean drawImage (Image image, int x1Dest, int y1Dest, int x2Dest, int y2Dest, int x1Source, int y1Source, int x2Source, int y2Source, Color color, ImageObserver obs)代碼味道w 1.1.4 過(guò)多的注釋(Com
37、ments)描述描述 Do not write comments when it is unnecessary. When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous.(在非必要的情況下不要寫注釋。當(dāng)你覺(jué)(在非必要的情況下不要寫注釋。當(dāng)你覺(jué)得需要去寫一段注釋時(shí),你首先應(yīng)該嘗試去重構(gòu)代碼,得需要去寫一段注釋時(shí),你首先應(yīng)該嘗試去重構(gòu)代碼,這將使任何注釋都變得是多余的。)這將使任何注釋都變得是多余的。)代碼味道w 1.1.4 過(guò)
38、多的注釋(Comments)重構(gòu)手段重構(gòu)手段 需要注釋來(lái)解釋一塊代碼做了什么:需要注釋來(lái)解釋一塊代碼做了什么:Extract Method(提煉函數(shù))(提煉函數(shù)) 函數(shù)已經(jīng)提煉出來(lái),但還是需要注釋來(lái)解釋其行為:函數(shù)已經(jīng)提煉出來(lái),但還是需要注釋來(lái)解釋其行為:Rename Method(函數(shù)改名)(函數(shù)改名) 需要注釋來(lái)說(shuō)明某些系統(tǒng)的需求規(guī)格:需要注釋來(lái)說(shuō)明某些系統(tǒng)的需求規(guī)格:Introduce Assertion(引入斷言)(引入斷言)代碼味道w 1.1.4 過(guò)多的注釋(Comments)實(shí)例實(shí)例public class Matcher public Matcher() public boole
39、an match(int expected, int actual, int clipLimit, int delta) / Clip too-large values for (int i = 0; i clipLimit) actuali = clipLimit; / Check for length differences if (actual.length != expected.length) return false; / Check that each entry within expected +/- delta for (int i = 0; i delta) return
40、false; return true; 代碼味道w 1.2.1 夸夸其談的未來(lái)性(Speculative Generality)描述描述 If a machinery was being used, it would be worth it. But if it is not, it is not. The machinery just gets in the way, so get rid of it.(如果一個(gè)裝置(如果一個(gè)裝置【一個(gè)設(shè)計(jì)或一個(gè)設(shè)計(jì)或?qū)崿F(xiàn)方案實(shí)現(xiàn)方案】會(huì)被用到,那就值得去做;如果用不到,就會(huì)被用到,那就值得去做;如果用不到,就不值得。用不到的裝置會(huì)成為攔路石,因此需要將它搬
41、不值得。用不到的裝置會(huì)成為攔路石,因此需要將它搬移。)移。)代碼味道w 1.2.1 夸夸其談的未來(lái)性(Speculative Generality)重構(gòu)手段重構(gòu)手段 某個(gè)抽象類沒(méi)有太大作用:某個(gè)抽象類沒(méi)有太大作用:Collapse Hierarchy(折疊繼承體(折疊繼承體系)系) 不必要的委托:不必要的委托:Inline Class(將類內(nèi)聯(lián)化)(將類內(nèi)聯(lián)化) 函數(shù)的某些參數(shù)未被使用:函數(shù)的某些參數(shù)未被使用:Remove Parameter(移除參數(shù))(移除參數(shù)) 函數(shù)名稱帶有多余的抽象涵義:函數(shù)名稱帶有多余的抽象涵義:Rename Method(函數(shù)改名)(函數(shù)改名) 對(duì)于無(wú)用的函數(shù):對(duì)于
42、無(wú)用的函數(shù):Inline Method(內(nèi)聯(lián)函數(shù))、(內(nèi)聯(lián)函數(shù))、Remove Method(移除函數(shù))(移除函數(shù))代碼味道w 1.2.1 夸夸其談的未來(lái)性(Speculative Generality)實(shí)例:如果函數(shù)或類的實(shí)例:如果函數(shù)或類的唯一用戶是測(cè)試用例唯一用戶是測(cè)試用例(Test Cases),這就飄出了壞味道,這就飄出了壞味道Speculative Generality。如果你發(fā)現(xiàn)這樣的函數(shù)或類,請(qǐng)把它們連同其測(cè)試用例如果你發(fā)現(xiàn)這樣的函數(shù)或類,請(qǐng)把它們連同其測(cè)試用例一并刪掉。但如果它們的用途是幫助測(cè)試用例檢測(cè)正當(dāng)一并刪掉。但如果它們的用途是幫助測(cè)試用例檢測(cè)正當(dāng)功能,當(dāng)然必須刀下留人
43、。功能,當(dāng)然必須刀下留人。代碼味道w 1.3.1 重復(fù)代碼(Duplicated Code)描述描述 Same code structure happens in more than one place.(在一個(gè)以上的地方發(fā)現(xiàn)相似的代碼結(jié)構(gòu)。)(在一個(gè)以上的地方發(fā)現(xiàn)相似的代碼結(jié)構(gòu)。)類型類型類型一:類型一:除空格、布局和注釋不同之外,其余部分都相同的代碼片段除空格、布局和注釋不同之外,其余部分都相同的代碼片段類型二:類型二:除標(biāo)識(shí)符、字面量、類型、空格、布局和注釋外,語(yǔ)法結(jié)構(gòu)相同的代除標(biāo)識(shí)符、字面量、類型、空格、布局和注釋外,語(yǔ)法結(jié)構(gòu)相同的代碼片段碼片段類型三:類型三:除標(biāo)識(shí)符、字面量、類型、
44、空格、布局和注釋外,進(jìn)一步對(duì)重復(fù)代碼除標(biāo)識(shí)符、字面量、類型、空格、布局和注釋外,進(jìn)一步對(duì)重復(fù)代碼段進(jìn)行改動(dòng),例如修改、增加或者刪除語(yǔ)句段進(jìn)行改動(dòng),例如修改、增加或者刪除語(yǔ)句類型四:類型四:兩個(gè)或多個(gè)代碼片段執(zhí)行相同的計(jì)算(功能),但是語(yǔ)法結(jié)構(gòu)的實(shí)現(xiàn)兩個(gè)或多個(gè)代碼片段執(zhí)行相同的計(jì)算(功能),但是語(yǔ)法結(jié)構(gòu)的實(shí)現(xiàn)方式不同方式不同代碼味道w 1.3.1 重復(fù)代碼(Duplicated Code)重構(gòu)手段重構(gòu)手段 同一個(gè)類的一個(gè)同一個(gè)類的一個(gè)/兩個(gè)方法含有相同的代碼:兩個(gè)方法含有相同的代碼: Extract Method(提煉函數(shù))(提煉函數(shù)) 兩個(gè)互為兄弟的子類含有相同的代碼:兩個(gè)互為兄弟的子類含有相
45、同的代碼:Extract Method(提煉函數(shù))、(提煉函數(shù))、Pull Up Method(函數(shù)上(函數(shù)上移)、移)、Form Template Method(塑造模板函數(shù))(塑造模板函數(shù)) 兩個(gè)毫不相關(guān)的類含有相同的代碼兩個(gè)毫不相關(guān)的類含有相同的代碼 :Extract Class(提煉類)(提煉類)代碼味道w 1.3.1 重復(fù)代碼(Duplicated Code)w 實(shí)例實(shí)例代碼味道w 1.3.2 異曲同工的類(Alternative Classes with Different Interfaces)描述描述Classes are doing similar things but wi
46、th different signatures. (不同的類做相同的事情,卻(不同的類做相同的事情,卻擁有不同的簽名,主要是指方法簽名不同。)擁有不同的簽名,主要是指方法簽名不同。)代碼味道w 1.3.2 異曲同工的類(Alternative Classes with Different Interfaces)重構(gòu)手段重構(gòu)手段 兩 個(gè) 函 數(shù) 做 同 一 件 事 , 卻 有 著 不 同 的 簽 名 :兩 個(gè) 函 數(shù) 做 同 一 件 事 , 卻 有 著 不 同 的 簽 名 :Rename Method(函數(shù)改名)(函數(shù)改名) 將某些行為移入類,直到兩者的協(xié)議一致為止:將某些行為移入類,直到兩者的
47、協(xié)議一致為止:Move Method(搬移函數(shù))(搬移函數(shù)) 必須重復(fù)而冗贅地移入代碼才能實(shí)現(xiàn)上述重構(gòu):必須重復(fù)而冗贅地移入代碼才能實(shí)現(xiàn)上述重構(gòu):Extract Superclass(提煉超類)(提煉超類)代碼味道w 1.3.2 異曲同工的類(Alternative Classes with Different Interfaces)實(shí)例實(shí)例代碼味道w 1.4.1 Switch驚悚現(xiàn)身(Switch Statement)描述描述Switch statements often lead to duplication. Most times you see a switch statement w
48、hich you should consider as polymorphism.(Switch語(yǔ)句通常會(huì)導(dǎo)致代碼重復(fù)。大多數(shù)時(shí)候,一看到語(yǔ)句通常會(huì)導(dǎo)致代碼重復(fù)。大多數(shù)時(shí)候,一看到Switch語(yǔ)句你應(yīng)該考慮使用多態(tài)來(lái)替換。)語(yǔ)句你應(yīng)該考慮使用多態(tài)來(lái)替換。)代碼味道w 1.4.1 Switch驚悚現(xiàn)身(Switch Statement)重構(gòu)手段重構(gòu)手段 與類型碼相關(guān)的函數(shù)或類:與類型碼相關(guān)的函數(shù)或類:Extract Method(提煉函數(shù))、(提煉函數(shù))、Move Method(搬移函數(shù))、(搬移函數(shù))、Replace Conditional with Polymorphism(以多態(tài)取代條件表
49、達(dá)式)、(以多態(tài)取代條件表達(dá)式)、Replace Type Code with Subclass(以子類取代類型碼)、(以子類取代類型碼)、Replace Type Code with State/Strategy(以(以State/Strategy取代類型碼)取代類型碼) 只在單一函數(shù)中有一些選擇事件,且不想改動(dòng)它們:只在單一函數(shù)中有一些選擇事件,且不想改動(dòng)它們:Replace Parameter with Explicit Methods(以明確函數(shù)取代參數(shù))(以明確函數(shù)取代參數(shù)) 選擇條件之一是選擇條件之一是null:Introduce Null Object(引入(引入Null對(duì)象)對(duì)
50、象)代碼味道w 1.4.1 Switch驚悚現(xiàn)身(Switch Statement)實(shí)例實(shí)例/電影票類class MovieTicket private double price; /電影票價(jià)格 private String type; /電影票類型 /計(jì)算打折之后的票價(jià) public double calculate() /學(xué)生票折后票價(jià)計(jì)算 if(this.type.equalsIgnoreCase(student) System.out.println(學(xué)生票:); return this.price * 0.8; /兒童票折后票價(jià)計(jì)算 else if(this.type.equalsI
51、gnoreCase(children) & this.price = 20 ) System.out.println(兒童票:); return this.price - 10; /VIP票折后票價(jià)計(jì)算 else if(this.type.equalsIgnoreCase(vip) System.out.println(VIP票:); System.out.println(增加積分!); return this.price * 0.5; else return this.price; /如果不滿足任何打折要求,則返回原始票價(jià) 代碼味道代碼味道w 2.1.1 基本類型偏執(zhí)(Primiti
52、ve Obsession)描述描述Primitive types are overused in software. Small classes should be used in place of primitive types in some situations.(在軟件中,基本類型(在軟件中,基本類型被過(guò)度使用。在某些場(chǎng)合下,應(yīng)該使用一些小的類被過(guò)度使用。在某些場(chǎng)合下,應(yīng)該使用一些小的類來(lái)代替這些基本類型。)來(lái)代替這些基本類型。)代碼味道w 2.1.1 基本類型偏執(zhí)(Primitive Obsession) 重構(gòu)手段重構(gòu)手段將原本單獨(dú)存在的數(shù)據(jù)值替換成對(duì)象:將原本單獨(dú)存在的數(shù)據(jù)值替換成
53、對(duì)象:Replace Data Value with Object(以對(duì)象取代數(shù)據(jù)值)(以對(duì)象取代數(shù)據(jù)值)如果想要替換的數(shù)據(jù)值是類型碼,而它并不影響行為:如果想要替換的數(shù)據(jù)值是類型碼,而它并不影響行為:Replace Type Code with Class(以類取代類型碼)(以類取代類型碼)如果有與類型碼相關(guān)的條件表達(dá)式:如果有與類型碼相關(guān)的條件表達(dá)式: Replace Type Code with Subclass(以子類取代類型碼)、(以子類取代類型碼)、 Replace Type Code with State/Strategy(以(以State/Strategy取代類型碼)取代類型碼
54、)如果有一組應(yīng)該總是被放在一起的字段:如果有一組應(yīng)該總是被放在一起的字段: Extract Class(提煉類)提煉類)如果在參數(shù)列中看到基本類型的數(shù)據(jù):如果在參數(shù)列中看到基本類型的數(shù)據(jù): Introduce Parameter Object(引入?yún)?shù)對(duì)象)(引入?yún)?shù)對(duì)象)發(fā)現(xiàn)自己正從數(shù)組中挑選數(shù)據(jù):發(fā)現(xiàn)自己正從數(shù)組中挑選數(shù)據(jù): Replace Array with Object(以對(duì)象取(以對(duì)象取代數(shù)組)代數(shù)組)代碼味道w 2.1.1 基本類型偏執(zhí)(Primitive Obsession)實(shí)例實(shí)例public class Person private String name; private
55、 int birthdayDay; private int brithdayMonth; private int brithdayYear; private String addressNationality; private String addressProvince; private String addressCity; private String addressStreet; 代碼味道w 2.1.2 純稚的數(shù)據(jù)類(Data Class)描述描述 These are classes that have fields, getting and setting methods for t
56、he fields, and nothing else. Such classes are dumb data holders and are almost certainly being manipulated in far too much detail by other classes.(這(這些類擁有一些字段些類擁有一些字段【成員變量成員變量】,并提供了對(duì)應(yīng)的,并提供了對(duì)應(yīng)的Getter和和Setter方法,除此以外一無(wú)所有。這些類只是一些不會(huì)說(shuō)話的方法,除此以外一無(wú)所有。這些類只是一些不會(huì)說(shuō)話的數(shù)據(jù)容器,數(shù)據(jù)容器, 而且它們必定會(huì)被其他類過(guò)分瑣細(xì)地操作。)而且它們必定會(huì)被其他類過(guò)分瑣
57、細(xì)地操作。)代碼味道w 2.1.2 純稚的數(shù)據(jù)類(Data Class)重構(gòu)手段重構(gòu)手段對(duì)于對(duì)于public字段:字段: Encapsulate Field(封裝字段)(封裝字段)如果一個(gè)類內(nèi)含容器類的字段,如果沒(méi)有得到恰當(dāng)?shù)姆庋b:如果一個(gè)類內(nèi)含容器類的字段,如果沒(méi)有得到恰當(dāng)?shù)姆庋b: Encapsulate Collection(封裝集合)(封裝集合)對(duì)于那些不該被其他類修改的字段:對(duì)于那些不該被其他類修改的字段:Remove Setting Method(移除(移除設(shè)值函數(shù))設(shè)值函數(shù))找出找出Getter/Setter函數(shù)被其他類運(yùn)用的地點(diǎn):函數(shù)被其他類運(yùn)用的地點(diǎn):Move Method(搬
58、移函(搬移函數(shù))數(shù))如果無(wú)法搬移整個(gè)函數(shù):如果無(wú)法搬移整個(gè)函數(shù):Extract Method(提煉函數(shù))(提煉函數(shù))將將Getter/Setter函數(shù)隱藏起來(lái):函數(shù)隱藏起來(lái):Hide Method(隱藏函數(shù))(隱藏函數(shù))代碼味道w 2.1.2 純稚的數(shù)據(jù)類(Data Class)實(shí)例實(shí)例package net.sf.robocode.serialization;/* * author Pavel Savara (original) */public class SerializableOptions public boolean skipExploded;public boolean skip
59、Names;public boolean skipVersion;public boolean skipDebug;public boolean skipTotal;public boolean trimPrecision;public boolean shortAttributes;public SerializableOptions(SerializableOptions src) skipExploded = src.skipExploded;skipNames = src.skipNames;skipVersion = src.skipVersion;skipDebug = src.s
60、kipDebug;skipTotal = src.skipTotal;trimPrecision = src.trimPrecision;shortAttributes = src.shortAttributes;public SerializableOptions(boolean skipAllDetails) if (skipAllDetails) skipExploded = true;skipNames = true;skipVersion = true;skipDebug = true;skipTotal = true;trimPrecision = true;shortAttributes
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 師范生頂崗實(shí)習(xí)報(bào)告匯編五篇
- 加入學(xué)生會(huì)自我介紹15篇
- 某建筑公司安全生產(chǎn)文明目標(biāo)及措施
- 2025年部編版新教材語(yǔ)文一年級(jí)下冊(cè)第七單元教案
- 動(dòng)物生理學(xué)-第十二章-生殖生理課件
- 后備干部培養(yǎng)工作參考計(jì)劃
- 個(gè)人租車給公司合同協(xié)議范本
- 個(gè)人房屋租賃合同書(shū)模板
- 2025年醫(yī)護(hù)管理通訊裝置項(xiàng)目發(fā)展計(jì)劃
- 2025年水性色漿項(xiàng)目發(fā)展計(jì)劃
- 政治-2025年八省適應(yīng)性聯(lián)考模擬演練考試暨2025年四川省新高考教研聯(lián)盟高三年級(jí)統(tǒng)一監(jiān)測(cè)試題和答案
- 2024年中國(guó)醫(yī)藥研發(fā)藍(lán)皮書(shū)
- 坍塌、垮塌事故專項(xiàng)應(yīng)急預(yù)案(3篇)
- 品管圈PDCA獲獎(jiǎng)案例-心內(nèi)科降低心肌梗死患者便秘發(fā)生率醫(yī)院品質(zhì)管理成果匯報(bào)
- 2023年初級(jí)會(huì)計(jì)師《初級(jí)會(huì)計(jì)實(shí)務(wù)》真題及答案
- 2024-2025學(xué)年三年級(jí)上冊(cè)道德與法治統(tǒng)編版期末測(cè)試卷 (有答案)
- 2025蛇年學(xué)校元旦聯(lián)歡晚會(huì)模板
- 陜西省安康市2023-2024學(xué)年高一上學(xué)期期末考試 生物 含解析
- WPS Office辦公軟件應(yīng)用教學(xué)教案
- 2024年度租賃期滿退房檢查清單:租戶與房東的交接確認(rèn)單
- 第八版糖尿病
評(píng)論
0/150
提交評(píng)論