Chapter 1 of refactoring-experience reconstruction magic RefactorSample, magic baby logging experience

Source: Internet
Author: User

Chapter 1 of refactoring-experience reconstruction magic RefactorSample, magic baby logging experience

The lab has been settled, and the environment and atmosphere are very good. Today, the teacher invited Sun, manager of Zhuo Er in Beijing, to talk a lot. The biggest surprise is that Mr. Ren is a cloud computing engineer, java is bound to be connected to cloud computing.

After a month, I did not write my blog seriously, nor did I study it seriously. The learning progress of the database has been dragging on and on until now. sad... After receiving a task, I wrote a Web-based internal laboratory management system and used it to train my hands. After that, I was a module of a CC call center for the Enterprise Project, which was connected to Zhuo and first came into contact with the actual project, nothing else, but excited. However, the heat of learning re-ignited together. Come on.


Today, I read the first chapter of refactoring, which is deeply attracted ....

Let's go. Let's go into the world of reconstruction together!


Example

Scenario: Customers rent a movie. There are three types of movies, including children's tickets, normal films, new films, and children's films. The fee is less than 1.5 yuan in two days. If the fee is more than two days, the fee is charged at 1.5 yuan per day, for normal movies, 2 yuan is less than 3 days, more than two days, and 2 yuan is added per day. For new movies, 3 yuan is collected every day, and movie credits are added per rent. For new movies, the rent period exceeds 2 days, points plus two.

Analysis:

It uses object-oriented ideology analysis, involving customers, films, and a leasing class as the bridge between customers and films.

Write code

Movie class (Movie ):

Public class Movie {public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private int movType; public Movie (String name, int movType) {this. name = name; this. movType = movType;} name: set and get Methods movType: set and get Methods}

To save space, the Movie class name, movType set, and get will not be pasted.

Leasing class (Rental Al ):

Public class every Al {private Movie movie; private int every days; public every Al (Movie movie, int every days) {this. movie = movie; this. specified days = specified days;} set and get methods of movie and specified days

Customer ):

Public class Customer {private String name; private ArrayList <Marshal> als = new ArrayList <Marshal> (); public Customer (String name) {this. name = name;} public void addRent (Region Al r) {region ALS. add (r);} public String getName () {return name;} public void setName (String name) {this. name = name;} public String statement () throws Exception {String result = "Marshal report for" + getName () + "\ n "; Double totalAmount = 0; int frequent = 0; for (Marshal r: als) {double thisAmount = 0; switch (r. getMovie (). getMovType () {case Movie. CHILDRENS: thisAmount + = (r. getlifecycle days ()> 2 )? (R. getexpiration days ()-2) * 1.5 + 1.5): 1.5; break; case Movie. REGULARS: thisAmount + = (r. getexpiration days ()> 3 )? (R. getexpiration days ()-3) * 2 + 2): 2; break; case Movie. NEW_RELEASE: thisAmount + = r. getexpiration days () * 3; break; default: throw new Exception ("type Exception");} totalAmount + = thisAmount; frequent + = (r. getMovie (). getMovType () = Movie. NEW_RELEASE & r. getlifecycle days ()> 2 )? 2: 2; result + = "\ t" + r. getMovie (). getName () + "\ t" + String. valueOf (thisAmount) + "\ n";} result + = "Amount is" + String. valueOf (totalAmount) + "Yuan \ n"; result + = "frequent is" + String. valueOf (frequent) + "Minute"; return result ;}}

Compile the test code:

Public class Test {public static void main (String [] args) throws Exception {Movie m1 = new Movie ("huluwa", 0 ); // children's film Movie m2 = new Movie ("Condor Heroes", 1); // common film Movie m3 = new Movie ("", 2 ); // new film Customer c = new Customer ("Zhu Xiaomei"); c. addRent (new marshal (m1, 2); // 1.5 c. addRent (new marshal (m2, 2); // 2 c. addRent (new marshal (m3, 3); // 9 System. out. println (c. statement ());}}

The above code has completed the sample requirement, but the code is too bad. This is exactly what I wrote myself... What should I do if the code is bad? Rebuild!

Step 1: Change the test code once and for all


To facilitate the test, we save the printed result as a string.

Public class Test {public static void main (String [] args) throws Exception {Movie m1 = new Movie ("huluwa", 0 ); // children's film Movie m2 = new Movie ("Condor Heroes", 1); // common film Movie m3 = new Movie ("", 2 ); // new film Customer c = new Customer ("Zhu Xiaomei"); c. addRent (new marshal (m1, 2); // 1.5 c. addRent (new marshal (m2, 2); // 2 c. addRent (new marshal (m3, 3 )); // 9 String result = "Marshal report for Zhu Xiaomei \ n" + "\ t huluwa \ t1.5 \ n" + "\ t Condor Heroes \ t2.0 \ n" + "\ t he in the condition that the volume operated by Mo \ t9.0 \ n "+" Amount is 12.5 yuan \ n "+" frequent is 4 points "; system. out. println (c. statement (). equals (result ));}}

In future test results, true indicates that the modification is correct, and false indicates that the modification fails.


Step 2: one stone and two birds-decomposition of the customer statement Method


Throughout all the code, the statement code of the customer class is the most messy and annoying. The switch function is to calculate a temporary variable thisAmount, the more temporary variables, the more error-prone a program will be. Since errors are easy, what are the use of totalAmount and frement? What are they doing? Take them away and encapsulate them separately.

Modified customer class:

Public class Customer {private String name; private ArrayList <Marshal> als = new ArrayList <Marshal> (); public Customer (String name) {this. name = name;} public void addRent (Region Al r) {region ALS. add (r);} public String getName () {return name;} public void setName (String name) {this. name = name;} public String statement () throws Exception {String result = "Marshal report for" + getName () + "\ n "; For (Marshal r: marshals) {result + =" \ t "+ r. getMovie (). getName () + "\ t" + String. valueOf (amountFor (r) + "\ n";} result + = "Amount is" + String. valueOf (getTotalAmount () + "Yuan \ n"; result + = "frequent is" + String. valueOf (getTotalFrequent () + "points"; return result;} private double getTotalAmount () throws Exception {double totalAmount = 0; for (Marshal r: marshals) {totalAmount + = amountFor (r );} Return totalAmount;} private int getTotalFrequent () {int frequent = 0; for (Marshal r: marshals) {frequent + = (r. getMovie (). getMovType () = Movie. NEW_RELEASE & r. getlifecycle days ()> 2 )? 2:1;} return frequent;} private double amountFor (Marshal r) throws Exception {double thisAmount = 0; switch (r. getMovie (). getMovType () {case Movie. CHILDRENS: thisAmount + = (r. getlifecycle days ()> 2 )? (R. getexpiration days ()-2) * 1.5 + 1.5): 1.5; break; case Movie. REGULARS: thisAmount + = (r. getexpiration days ()> 3 )? (R. getexpiration days ()-3) * 2 + 2): 2; break; case Movie. NEW_RELEASE: thisAmount + = r. getexpiration days () * 3; break; default: throw new Exception ("type Exception");} return thisAmount ;}}


In this way, the statement method is huge and the problem of many temporary variables is solved. perform the test, true, and correct modification.

Step 3: Do what you need


Review the customer class and you will find that it is a lot of things that it should not do. switch to calculate the cost of a single lease and points, you should do it for the movie class, how much is the cost, how much is the score, movie itself is the clearest

The problem still exists in the switch. It is best not to use the switch based on the attribute of another object. If you have to use the switch, it should also be used on the object's own data, rather than on others' data.

Add the getOneMoney and getOneFre methods to the marshal class, delete the amountFor method from the customer class, modify the getTotalFrequent method, and switch to the Movie class.

Modified customer class

Only the getTotalFrequent Method for loop is changed.

Public class Customer {private String name; private ArrayList <Marshal> als = new ArrayList <Marshal> (); public Customer (String name) {this. name = name;} public void addRent (Region Al r) {region ALS. add (r);} public String getName () {return name;} public void setName (String name) {this. name = name;} public String statement () throws Exception {String result = "Marshal report for" + getName () + "\ n"; for (Marshal r: marshals) {result + = "\ t" + r. getMovie (). getName () + "\ t" + String. valueOf (r. getOne () + "\ n";} result + = "Amount is" + String. valueOf (getTotalAmount () + "Yuan \ n"; result + = "frequent is" + String. valueOf (getTotalFrequent () + "points"; return result;} private double getTotalAmount () throws Exception {double totalAmount = 0; for (Marshal r: marshals) {totalAmount + = r. getOne () ;}return totalAmount;} private int getTotalFrequent () {int frequent = 0; for (Marshal r: marshals) {frequent + = r. getOneFre () ;}return frequent ;}}

The changed Marshal serves as a bridge.

public class Rental {        private Movie movie;        private int rentDays;        public Rental(Movie movie,int rentDays) {            this.movie = movie; this.rentDays = rentDays;        }    public int getRentDays() {        return rentDays;    }    public void setRentDays(int rentDays) {        this.rentDays = rentDays;    }    public Movie getMovie() {        return movie;    }    public double getOne() throws Exception {        return  getMovie().getMoney(rentDays) ;    }    public int getOneFre(){        return  getMovie().getFrequent(rentDays);    }    public void setMovie(Movie movie) {        this.movie = movie;    }}

The changed movie class finally started to work.

/*** Created by Kevy on 2015/1/21. * // * compile the Movie Code */public class Movie {public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private int movType; public Movie (String name, int movType) {this. name = name; this. movType = movType;} public int getMovType () {return movType;} public void setMovType (int movType) {this. MovType = movType;} public String getName () {return name;} public void setName (String name) {this. name = name;} public double getMoney (int Expiration days) throws Exception {double thisAmount = 0; switch (getMovType () {case Movie. CHILDRENS: thisAmount + = (Expiration days> 2 )? (RentDays-2) * 1.5 + 1.5): 1.5; break; case Movie. REGULARS: thisAmount + = (days> 3 )? (RentDays-3) * 2 + 2): 2; break; case Movie. NEW_RELEASE: thisAmount + = Expiration days * 3; break; default: throw new Exception ("type Exception");} return thisAmount;} public int getFrequent (int interval days) {return (getMovType () = NEW_RELEASE & lifecycle days> 2 )? 2:1 ;}}

Test OK, no problem.


Step 4 Use Polymorphism

Currently, all classes are doing their own work. The amount of code in the getMoney method of the movie class is still not very good. Since the three types of movies are just different, abstract classes can be extracted and used up for a long time..

public interface Type {    public int getType();    public double getMovMeony(int days);}

public class ChildrenMov implements Type {    public int getType() {        return 0;    }    public double getMovMeony(int days) {        return (days>2)?((days-2)*1.5+1.5):1.5;    }}

public class RegularMov implements Type {    public int getType() {        return 1;    }    public double getMovMeony(int days) {        return (days>3)?((days-3)*2+2):2;    }}

public class NewMov implements Type {    public int getType() {        return 2;    }    public double getMovMeony(int days) {        return days * 3;    }}

Complete code:

Import java. util. arrayList;/*** Created by Kevy on 2015/1/21. */public class Customer {private String name; private ArrayList <Marshal> als = new ArrayList <Marshal> (); public Customer (String name) {this. name = name;} public void addRent (Region Al r) {region ALS. add (r);} public String getName () {return name;} public void setName (String name) {this. name = name;} public String statement () throws Exception {String result = "Marshal report for" + getName () + "\ n"; for (Marshal r: marshals) {result + = "\ t" + r. getMovie (). getName () + "\ t" + String. valueOf (r. getOne () + "\ n";} result + = "Amount is" + String. valueOf (getTotalAmount () + "Yuan \ n"; result + = "frequent is" + String. valueOf (getTotalFrequent () + "points"; return result;} private double getTotalAmount () throws Exception {double totalAmount = 0; for (Marshal r: marshals) {totalAmount + = r. getOne () ;}return totalAmount;} private int getTotalFrequent () {int frequent = 0; for (Marshal r: marshals) {frequent + = r. getOneFre () ;}return frequent ;}}

/** * Created by Kevy on 2015/1/21. */public class Rental {        private Movie movie;        private int rentDays;        public Rental(Movie movie,int rentDays) {            this.movie = movie; this.rentDays = rentDays;        }    public int getRentDays() {        return rentDays;    }    public void setRentDays(int rentDays) {        this.rentDays = rentDays;    }    public Movie getMovie() {        return movie;    }    public double getOne() throws Exception {        return  getMovie().getMoney(rentDays) ;    }    public int getOneFre(){        return  getMovie().getFrequent(rentDays);    }    public void setMovie(Movie movie) {        this.movie = movie;    }}

/*** Created by Kevy on 2015/1/21. * // * compile the Movie Code */public class Movie {public static final int CHILDRENS = 0; public static final int REGULARS = 1; public static final int NEW_RELEASE = 2; private String name; private Type t; public Movie (String name, int movType) throws Exception {this. name = name; setT (movType);} public String getName () {return name;} public void setName (String name) {this. na Me = name;} public double getMoney (int Expiration days) {return t. getMovMeony (lifecycle days);} public int getFrequent (int lifecycle days) {return (t. getType () = NEW_RELEASE & lifecycle days> 2 )? 2:1;} public void setT (int d) throws Exception {switch (d) {case CHILDRENS: t = new ChildrenMov (); break; case REGULARS: t = new RegularMov (); break; case NEW_RELEASE: t = new NewMov (); break; default: throw new Exception ("type error ");}}}

Import sun. plugin2.message. modalityChangeMessage;/*** Created by Kevy on 2015/1/21. * // * write the Test code */public class Test {public static void main (String [] args) throws Exception {Movie m1 = new Movie ("huluwa", 0 ); // children's film Movie m2 = new Movie ("Condor Heroes", 1); // common film Movie m3 = new Movie ("", 2 ); // new film Customer c = new Customer ("Zhu Xiaomei"); c. addRent (new marshal (m1, 2); // 1.5 c. addRent (new marshal (m2, 2); // 2 c. addRent (new marshal (m3, 3 )); // 9 String result = "Marshal report for Zhu Xiaomei \ n" + "\ t huluwa \ t1.5 \ n" + "\ t Condor Heroes \ t2.0 \ n" + "\ t he in the condition that the volume operated by Mo \ t9.0 \ n "+" Amount is 12.5 yuan \ n "+" frequent is 4 points "; system. out. println (c. statement (). equals (result ));}}

So far, a simple code refactoring example is completed.

The greatest inspiration for refactoring is testing, minor changes, testing, and minor changes ....


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.