<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 3, 文章 - 152, 評論 - 17, 引用 - 0
    數據加載中……

    TDD(2) --轉自http://m.tkk7.com/yandazhi

    重構以兩種方式和TDD密切相關。

    在以盡可能簡單的手段通過測試之后,(在這個過程中違反了任何編碼規則)我們就進行重構清理。大部分是除去我們為了通過測試而帶來的重復。

    如果我們是按TDD行事,那么我們就有了適當的測試的安全網,這使得我們有信心進行重構。   

    何時重構?

    1  重復的時候

    public boolean save() throws IOException {
      
    if (outputFile == null{
        
    return false;
      }


      FileWriter writer 
    = new FileWriter(outputFile);
      movies.writeTo(writer);
      writer.close();
      
    return true;
    }


    public boolean saveAs() throws IOException {
      outputFile 
    = view.getFile();
      
    if (outputFile == null{
        
    return false;
      }


      FileWriter writer 
    = new FileWriter(outputFile);
      movies.writeTo(writer);
      writer.close();
      
    return true;
    }


    替代成

    public boolean saveAs() throws IOException {
      outputFile 
    = view.getFile();
      save();
    }


    2  我們發現代碼,或者/并且它的意圖不清楚的時候。、

    代碼是最重要的交付產品,必須盡可能清楚和可理解。

    3  我們嗅到代碼味道,微妙的(或者不那么微妙的)跡象表明代碼有問題。

    代碼味道不一定總是表明有問題,但是代碼味道表明我們應該仔細察看一下,是否有問題。

    如何重構?

    析取類
    看看下面的例子

    public void writeTo(Writer destination) throws IOException {
      Iterator movieIterator 
    = movies.iterator();
      
    while (movieIterator.hasNext()) {
        Movie movieToWrite 
    = (Movie)movieIterator.next();;
        destination.write(movieToWrite.getName());
        destination.write(
    '|');
        destination.write(movieToWrite.getCategory().toString());
        destination.write(
    '|');

        
    try {
          destination.write(Integer.toString(movieToWrite.getRating()));
        } 
    catch (UnratedException ex) {
          destination.write(
    "-1");
        }
        destination.write(
    '\n');
      }
    }

    MovieList不恰當的包含了太多Movie的特性


    public class MovieList {
      
    //
      public void writeTo(Writer destination) throws IOException {
        Iterator movieIterator 
    = movies.iterator();
        
    while (movieIterator.hasNext()) {
          Movie movieToWrite 
    =(Movie)movieIterator.next();;
          movieToWrite.writeTo(destination);
        }
    }

    public classMovie {
      
    //

      
    public void writeTo(Writer destination) {
        destination.write(getName());
        destination.write(
    '|');
        destination.write(getCategory(). toString());
        destination.write(
    '|');c

        
    try {
          destination.write(Integer.toString(getRating()));

        } 
    catch (UnratedException ex) {
          destination.write(
    "-1");
        }

        destination.write(
    '\n');
      }
    }


     寫電影列表的工作放在MovieList和Movie當中,應該抽象出來。

    public class MovieListWriter 
    {
      Writer destination 
    = null;

      
    public MovieListWriter(Writer aWriter) {
        destination 
    = aWriter;
      }

      
    public void writeMovieList(MovieList aList) throws IOException {
        Iterator movieIterator 
    = aList.getMovies().iterator();
        
    while (movieIterator.hasNext()) {
          Movie movieToWrite 
    = (Movie)movieIterator.next();;
          writeMovie(movieToWrite);
        }

      
    private void writeMovie(Movie aMovie) {
        destination.write(aMovie.getName());
        destination.write(
    '|');
        destination.write(aMovie.getCategory().toString());
        destination.write(
    '|');

        
    try {
          destination.write(Integer.toString(aMovie.getRating()));

        } 
    catch (UnratedException ex) {
          destination.write(
    "-1");
        }
        destination.write(
    '\n');
      }
    }


    寫電影列表的代碼集中起來。而且只有writeMovieList()方法暴露出來,其他的細節都封裝起來。

    析取接口

    下面是一個有形的類,非常簡單
    public class MovieList {
      
    private Collection movies = new ArrayList();


      
    public int size() {
        
    return movies.size();
      }

      
    public void add(Movie movieToAdd) {
        movies.add(movieToAdd);
      }

      
    public boolean contains(Movie movieToCheckFor) {
        
    return movies.contains(movieToCheckFor);
      }
    }

    如果需要模擬他,我們應該析取接口

    public interface IMovieList {
      
    int size();
      
    void add(Movie movieToAdd);
      boolean contains(Movie movieToCheckFor);
    }




    public class MovieList implements IMovieList {
      
    //
    }


    析取方法

    過于龐大的方法,應該進行拆分。下面的方法,每個注釋出現的地方可以析取出來
    public void init() {
      
    // set the layout
      getContentPane().setLayout(new FlowLayout());

      
    // create the list
      movieList = new JList(myEditor.getMovies());
      JScrollPane scroller 
    = new JScrollPane(movieList);
      getContentPane().add(scroller);

      
    // create the field
      movieField = new JTextField(16);
      getContentPane().add(movieField);

      
    // create the add button
      addButton = new JButton("Add");
      addButton.addActionListener(
    new ActionListener() {
        
    public void actionPerformed(ActionEvent e) {
          myEditor.add(movieField.getText());
          movieList.setListData(myEditor.getMovies());
        }
      });
      getContentPane().add(addButton);
    }


    分解和命名為成一些不證自明的方法。

    public void init() {
      setLayout();
      initMovieList();
      initMovieField();
      initAddButton();
    }

    private void setLayout() {
      getContentPane().setLayout(
    new FlowLayout());
    }

    private void initMovieList() {
      movieList 
    = new JList(getMovies());
      JScrollPane scroller 
    = new JScrollPane(movieList);
      getContentPane().add(scroller);
    }

    private void initMovieField() {
      movieField 
    = new JTextField(16);
      getContentPane().add(movieField);
    }

    private void initAddButton() {
      addButton 
    = new JButton("Add");
      addButton.addActionListener(
    new ActionListener() {
        
    public void actionPerformed(ActionEvent e) {
          myEditor.add(movieField.getText());
          movieList.setListData(getMovies());
        }
      });
      getContentPane().add(addButton);
    }


    用子類代替類型代碼

    public class Employee {
      
    // 0 - engineer, 1 - salesman, 2 - manager
      private int employeeType;

      
    //..
      }


    替代成

    abstract public class Employee {
      
    //. . .
    }

    public class Engineer extends Employee {
      
    //. . .
    }

    public class Salesman extends Employee 
    {
      
    //. . .
    }

    public class Manager extends Employee 
    {
      
    //. . .
    }


    用多態來替代條件(開關)語句

    public class Employee {
      
    // 0 - engineer, 1 - salesman, 2 - manager
      private int employeeType;

      
    public String departmentName() {
        
    switch (employeeType) {
          
    case 0:
            
    return "Engineering";
          
    case 1:
            
    return "Sales";
          
    case 2:
            
    return "Management";
          
    default:
            
    return "Unknown";
        }
      }
    }


    替代為
    abstract public class Employee {
      
    public abstract String departmentName();
    }


    public class Engineer extends Employee {
      
    public String departmentName() {
        
    return "Engineering";
      }
    }


    public class Salesman extends Employee {
      
    public String departmentName() {
        
    return "Sales";
    }
    }


    public class Manager extends Employee {
      
    public String departmentName() {
        
    return "Management";
      }
    }


    模板方法

    public class Engineer extends Employee {
      
    public String asXML() {
        StringBuffer buf 
    = new StringBuffer();
        buf.append(
    "<employee name=\"");
        buf.append(getName());
        buf.append(
    "\" department=\"Engineering\">");
        //
        return buf.toString();
      }
      
    //. . .
    }





    public class Salesman extends Employee {
      
    public String asXML() {
        StringBufer buf 
    = new StringBuffer();
        buf.append(
    "<employee name=\"");
        buf.append(getName());
        buf.append(
    "\" department=\"Sales\">");
        //. . .
        return buf.toString();
      }
      
    //
    }


    public class Manager extends Employee {
      
    public String asXML() {
        StringBufer buf 
    = new StringBuffer();
        buf.append(
    "<employee name=\"");
        buf.append(getName());
        buf.append(
    "\" department=\"Management\">");
        //. . .
        return buf.toString();
      }
      
    //
    }


    用employee很好地解決了問題

    public class Employee {
      
    public String asXML() {
        StringBuffer buf 
    = new StringBuffer();
        buf.append(
    "<employee name=\"");
        buf.append(getName());
        buf.append(
    "\" department=\"");
        buf.append(departmentName());
        buf.append(
    "\">");
        //
        return buf.toString();
      }
      
    //. . .
    }



    引入解釋變量

    public Money calculateTotal() {
      
    return getSubtotal().plus((getTaxableSubtotal().times(0.15))).minus((getSubtotal().asDouble()> 100.0)?(getSubtotal().times(0.10)):0);

    public Money calculateTotal() {
      Money subtotal 
    = getSubtotal();
      Money tax 
    = getTaxableSubtotal().times(0.15);
      Money total 
    =subtotal.plus(tax);
      boolean qualifiesForDiscount 
    = getSubtotal().asDouble() 
    > 100.0;
      Money discount 
    = qualifiesForDiscount
                             
    ?subtotal.times(0.10)
                             :newMoney(
    0.0);
      
    return total.minus(discount);

    用工廠方法替代構造函數

    public classRating {
      
    private int value = 0;
      
    private String source = null;
      
    private String review = null;

      
    public Rating(int aRating) {
        
    this(aRating, "Anonymous""");
      }

      
    public Rating(int aRating, String aRatingSource) {
        
    this(aRating, aRatingSource, "");
      }

      
    public Rating(int aRating, String aRatingSource, String aReview) {
        value 
    = aRating;
        source 
    = aRatingSource;
        review 
    = aReview;
      }

      
    //
    }



    public static Rating newAnonymousRating(int value) {
      
    return new Rating(value, "Anonymous""");
    }

    public static Rating newRating(int value, String source) {
      
    return new Rating(value, source, "");
    }

    public static Rating newReview(int value, String source, String review) {
      
    return new Rating(value, source, review);
    }

    private Rating(int aRating, String aRatingSource, String aReview) {
      value 
    = aRating;
      source 
    = aRatingSource;
      review 
    = aReview;
    }


    用代理代替繼承

    public class Department extends Vector {
    }

    public class Department {
      
    private Vector employees = new Vector();

      
    public void hire(Employee newHire) {
        employees.add(newHire);
      }

      
    public DepartmentIterator iterator() {
        
    return new DepartmentIterator();
      }

      
    public class DepartmentIterator {
        Iterator underlying 
    = employees.iterator();

        
    public boolean hasNext() {
          
    return underlying.hasNext();
        }

        
    public Employee next() {
          
    return (Employee)underlying.next();
        }
      }
    }


    posted on 2005-07-25 12:26 閱讀(237) 評論(0)  編輯  收藏 所屬分類: Test-Driven Development

    主站蜘蛛池模板: 99re热免费精品视频观看 | 99精品视频免费在线观看| 久久国产精品免费专区| 999任你躁在线精品免费不卡| 伊人久久大香线蕉亚洲五月天| 亚洲成人精品久久| 精品日韩99亚洲的在线发布| 亚洲AV综合色区无码一二三区 | 久久精品无码专区免费| 四虎影视在线影院在线观看免费视频| 四虎影视大全免费入口| 国产成人精品曰本亚洲79ren| 亚洲视频一区在线| 一级做a爰片久久毛片免费陪 | 亚洲欧洲春色校园另类小说| 美女视频黄.免费网址| 51视频精品全部免费最新| 亚洲AⅤ永久无码精品AA| 亚洲精品在线免费观看视频| 国产精品偷伦视频免费观看了| 成人毛片免费观看视频大全| 亚洲ⅴ国产v天堂a无码二区| **一级一级毛片免费观看| 亚洲人成免费网站| 特级精品毛片免费观看| 亚洲免费福利视频| 又大又粗又爽a级毛片免费看| 久久久国产亚洲精品| 日本一区午夜艳熟免费| 又粗又硬又大又爽免费视频播放| aa毛片免费全部播放完整| 亚洲国产精品免费视频| a级片免费在线播放| 亚洲综合无码AV一区二区| 最近中文字幕无免费| 亚洲国产精品lv| 插B内射18免费视频| 一级毛片**免费看试看20分钟| 日韩成人免费视频播放| 亚洲av永久无码嘿嘿嘿| 亚洲精品无码激情AV|