http://chenyu-hz.iteye.com/blog/1005302
Java重构示例一
本文通过Java示例代码片段展示了常用重构原则和技巧,供初级开发人员参考。精致的代码能够清楚传达作者的意图,精致的代码是最好的注释,精致的代码非常容易维护和扩展。程序员阅读精致的代码如同大众欣赏优美的散文一样享受。
1 尽量简洁
1.1 重构前
if ( flag == 1 ){ return true; } else{ return false; }
|
1.2 重构后
return flag == 1;
|
2 使用三位运算符
2.1 重构前
if ( "Male".equals(gender) ) { return "Mr."; } else{ return "Mrs."; }
|
2.2 重构后
return "Male".equals(gender) ? "Mr." : "Mrs.";
|
3 使用常量替换硬编码
3.1 重构前
for (int i = 0; i < 12; i++) { this.getDays(i); //skip... }
|
3.2 重构后
int YEAR_MONTHS = 12; for (int month = 0; month < Month.YEAR_MONTHS; month++) { this.getDays(month); //skip... }
|
4 使用方法替换反复出现的表达式
4.1 重构前
public boolean isStartAfter(Date date) { Calendar calendar = BusinessCalendar.getCalendar(); calendar.setTime(date); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE);
return ( (hour<fromHour) || ( (hour==fromHour) && (minute<=fromMinute) ) ); }
public boolean includes(Date date) { Calendar calendar = BusinessCalendar.getCalendar(); calendar.setTime(date); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE);
return ( ( (fromHour<hour) || ( (fromHour==hour) && (fromMinute<=minute) ) ) && ( (hour<toHour) || ( (hour==toHour) && (minute<=toMinute) ) ) ); }
|
4.2 重构后
private boolean tailGreatHead(int headHour, int headMinute, int tailHour, int tailMinute, boolean includeEqual) { boolean tailGreatHeadHour = (headHour < tailHour); boolean tailEqualHeadHour = (headHour == tailHour); boolean tailGreatHeadMinute = (headMinute < tailMinute); boolean tailEqualHeadMinute = (headMinute == tailMinute);
boolean tailGreatEqualHeadMinute = tailGreatHeadMinute || includeEqual && tailEqualHeadMinute;
return (tailGreatHeadHour || (tailEqualHeadHour && tailGreatEqualHeadMinute)); }
private boolean tailGreatHead(int headHour, int headMinute, int tailHour, int tailMinute) { return tailGreatHead(headHour, headMinute, tailHour, tailMinute, false); }
private boolean tailGreatEqualHead(int headHour, int headMinute, int tailHour, int tailMinute) { return tailGreatHead(headHour, headMinute, tailHour, tailMinute, true); }
public boolean isStartAfter(Date date) { Calendar calendar = BusinessCalendar.getCalendar(); calendar.setTime(date); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE);
return this.tailGreatEqualHead(hour, minute, fromHour, fromMinute); }
public boolean includes(Date date) { Calendar calendar = BusinessCalendar.getCalendar(); calendar.setTime(date); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE);
return this.tailGreatEqualHead(fromHour, fromMinute, hour, minute) && this.tailGreatEqualHead(hour, minute, toHour, toMinute); }
|
5 及早结束非正常逻辑
5.1 重构前
int count = 0; if(taskList != null && !taskList.isEmpty()){
//skip...
return count; } else { return count; }
|
5.2 重构后
int count = 0; if(taskList == null || taskList.isEmpty()){ return 0; }
//skip...
return count;
|
6 满足条件立即跳出循环
6.1 重构前
public boolean contain(int year, Month month, int day) { boolean found = false; for (IPolyDate date : dateList) { if (date.same(year, month.getMonth(), day)) { found = true; break; } }
return found; }
|
6.2 重构后
public boolean contain(int year, Month month, int day) { for (IPolyDate date : dateList) { if (date.same(year, month.getMonth(), day)) { return true; } }
return false; }
|
7 使用表结构分离公共逻辑,避免重复(坚持DRY原则)
7.1 重构前
public void testGetIntPart() throws Exception { assertEquals("0", digitTransform.getIntPart("0.01"); assertEquals("1", digitTransform.getIntPart("1.2"); assertEquals("1234", digitTransform.getIntPart("1234"); assertEquals("1", digitTransform.getIntPart("1.01"); assertEquals("0", digitTransform.getIntPart("0.01"); assertEquals("11111", digitTransform.getIntPart("11111"); assertEquals("1000", digitTransform.getIntPart("1000.11"); }
|
7.2 重构后
public void testGetIntPart() throws Exception { String[][] cases = new String[][] { { "0.01", "0" }, { "1.2", "1" }, { "1234", "1234" }, { "1.01", "1" }, { "0", "0" }, { "11111", "11111" }, { "1000.11", "1000" } };
for (int i = 0, len = cases.length; i < len; i++) { assertEquals(cases[i][1], digitTransform.getIntPart(cases[i][0])); } }
|
8 分离变化参数,使用格式化方法
8.1 重构前
public class ExceedMaxWeekIndexOfMonthException extends IndexOutOfBoundsException {
private static final long serialVersionUID = 1L;
public ExceedMaxWeekIndexOfMonthException(String message) { super(message); }
}
|
8.2 重构后
public class ExceedMaxWeekIndexOfMonthException extends IndexOutOfBoundsException {
private static final long serialVersionUID = 1L;
public ExceedMaxWeekIndexOfMonthException(int index, int maxCountOfWeekDay, Month month) { super(formatMessage(index, maxCountOfWeekDay, month)); }
private static String formatMessage(int index, int maxCountOfWeekDay, Month month) { return "Arguement index[" + index + "] exceeds max week index[" + maxCountOfWeekDay + "] of month[" + month.toString() + "]."; }
}
|
9 使用方法抽取公共逻辑
9.1 重构前
public int getYear() { Calendar date = this.getCalendarDate();
return date.get(Calendar.YEAR); }
public int getMonth() { Calendar date = this.getCalendarDate();
return date.get(Calendar.MONTH); }
public int getDay() { Calendar date = this.getCalendarDate();
return date.get(Calendar.DAY_OF_MONTH); }
public int getHour() { Calendar date = this.getCalendarDate();
return date.get(Calendar.HOUR_OF_DAY); }
public int getMinute() { Calendar date = this.getCalendarDate();
return date.get(Calendar.MINUTE); }
public int getSecond() { Calendar date = this.getCalendarDate();
return date.get(Calendar.SECOND); }
public int getMillisSecond() { Calendar date = this.getCalendarDate();
return date.get(Calendar.MILLISECOND); }
|
9.2 重构后
private int get(int field) { Calendar date = this.getCalendarDate();
return date.get(field); }
public int getYear() { return this.get(Calendar.YEAR); }
public int getMonth() { return this.get(Calendar.MONTH); }
public int getDay() { return this.get(Calendar.DAY_OF_MONTH); }
public int getHour() { return this.get(Calendar.HOUR_OF_DAY); }
public int getMinute() { return this.get(Calendar.MINUTE); }
public int getSecond() { return this.get(Calendar.SECOND); }
public int getMillisSecond() { return this.get(Calendar.MILLISECOND); }
|
10 尽量使用已有的Java API
10.1 重构前
protected String[] getConfigLocations() { String[] baseCfgs = this.getBaseCfgs(); String[] extra = this.getExtraCfgs(); if (extra != null && extra.length > 0) { int baseCfgLen = baseCfgs.length; int extraLen = extra.length; String[] cfgLocations = new String[baseCfgLen + extraLen]; for(int i = 0; i < baseCfgLen; i++){ cfgLocations[i] = baseCfgs[i]; }
for(int i = 0; i < extraLen; i++){ cfgLocations[baseCfgLen + i] = extra[i]; }
return cfgLocations; } else { return baseCfgs; } } |
10.2 重构后
protected String[] getConfigLocations() { String[] baseCfgs = this.getBaseCfgs(); String[] extra = this.getExtraCfgs(); if (extra != null && extra.length > 0) { int baseCfgLen = baseCfgs.length; int extraLen = extra.length; String[] cfgLocations = new String[baseCfgLen + extraLen; System.arraycopy(baseCfgs, 0, cfgLocations, 0, baseCfgLen); System.arraycopy(extra, 0, cfgLocations, baseCfgLen, extraLen;
return cfgLocations; } else { return baseCfgs; } }
|
11 使方法通用化
11.1 重构前
public DayPart[] sortDayPart() { if (dayParts == null || dayParts.length == 0) { return dayParts; } List<DayPart> dayPartList = Arrays.asList(dayParts);
Collections.sort(dayPartList, new Comparator<DayPart>() { public int compare(DayPart o1, DayPart o2) { if (o1.getIndex() < o2.getIndex()) { return -1; } else if (o1.getIndex() > o2.getIndex()) { return 1; } else { return 0; } } });
return dayPartList.toArray(new DayPart[dayPartList.size()]); }
|
11.2 重构后
public DayPart[] sortDayPart() { return this.sortDayPart(SortMode.ASC); }
public DayPart[] sortDayPart(final SortMode sortMode) { if (dayParts == null || dayParts.length == 0) { return dayParts; } List<DayPart> dayPartList = Arrays.asList(dayParts);
Collections.sort(dayPartList, new Comparator<DayPart>() { public int compare(DayPart o1, DayPart o2) { if (o1.getIndex() < o2.getIndex()) { return sortMode.isAsc() ? -1 : 1; } else if (o1.getIndex() > o2.getIndex()) { return sortMode.isAsc() ? 1 : -1; } else { return 0; } } });
return dayPartList.toArray(new DayPart[dayPartList.size()]); }
|
12 避免空语句
12.1 重构前
public int getRemainMinutes(int hour, int minute) { int startHour = fromHour; int startMinute = fromMinute; if (this.fromAfterEqual(hour, minute)) { // ------from-------position------to-------- ;//use default init value } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- startHour = hour; startMinute = minute; } else { // --------from-------to--------position------- startHour = toHour; startMinute = toMinute; }
return this.getMinutes(startHour, startMinute, toHour, toMinute); }
|
12.2 重构后
public int getRemainMinutes(int hour, int minute) { // --------from-------to--------position------- int startHour = toHour; int startMinute = toMinute;
if (this.fromAfterEqual(hour, minute)) { // ------position------from-------to-------- startHour = fromHour; startMinute = fromMinute; } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- startHour = hour; startMinute = minute; }
return this.getMinutes(startHour, startMinute, toHour, toMinute); }
|
13 公共逻辑后置
13.1 重构前
public int getRemainMinutes(int hour, int minute) { if (this.fromAfterEqual(hour, minute)) { // ------position------from-------to-------- return (toHour * 60 + toMinute) - (fromHour * 60 + fromMinute); } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- return (toHour * 60 + toMinute) - (hour * 60 + minute); } else { // --------from-------to--------position------- return 0; //(toHour * 60 + toMinute) - (toHour * 60 + toMinute); } }
|
13.2 重构后
private int getMinutes(int startHour, int startMinute, int endHour, int endMinute) { int minutes = 0; minutes = (endHour * 60 + endMinute) - (startHour * 60 + startMinute);
return minutes; }
public int getRemainMinutes(int hour, int minute) { // --------from-------to--------position------- int startHour = toHour; int startMinute = toMinute;
if (this.fromAfterEqual(hour, minute)) { // ------position------from-------to-------- startHour = fromHour; startMinute = fromMinute; } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- startHour = hour; startMinute = minute; }
return this.getMinutes(startHour, startMinute, toHour, toMinute); }
|
14 公共逻辑前置
14.1 重构前
private StringBuffer transformDialect(String intPart, String fracPart) { StringBuffer cn = new StringBuffer();
if (isIntegerZero(intPart)) { return cn; }
if (this.isFractionZero(fracPart)) { // 无小数,增加附加信息(整) cn.append("元").append("整"); } else { // 有小数,增加附加信息(零) cn.append("元").append("零"); }
return cn; }
|
14.2 重构后
private StringBuffer transformDialect(String intPart, String fracPart) { StringBuffer cn = new StringBuffer();
if (isIntegerZero(intPart)) { return cn; }
cn.append("元"); if (this.isFractionZero(fracPart)) { // 无小数,增加附加信息(整) cn.append("整"); } else { // 有小数,增加附加信息(零) cn.append("零"); }
return cn; }
|
15 使用清晰的布尔型变量替换逻辑表达式
15.1 重构前
public boolean tailGreatHead(int headHour, int headMinute, int tailHour, int tailMinute, boolean includeEqual) {
return ((headHour < tailHour) || ((headHour == tailHour) && ((headMinute < tailMinute) || includeEqual && (headMinute == tailMinute)))); }
|
15.2 重构后
public boolean tailGreatHead(int headHour, int headMinute, int tailHour, int tailMinute, boolean includeEqual) { boolean tailGreatHeadHour = (headHour < tailHour); boolean tailEqualHeadHour = (headHour == tailHour); boolean tailGreatHeadMinute = (headMinute < tailMinute); boolean tailEqualHeadMinute = (headMinute == tailMinute);
boolean tailGreatEqualHeadMinute = tailGreatHeadMinute || includeEqual && tailEqualHeadMinute;
return (tailGreatHeadHour || (tailEqualHeadHour && tailGreatEqualHeadMinute)); }
|
16 减少重复计算
16.1 重构前
if(list != null && list.size() > 0){ for(int i = 0; i < list.size(); i++){ //skip... } }
|
16.2 重构后
if(list != null){ for(int i = 0, len = list.size(); i < len; i++){ //skip... } }
|
17 何时需要何时创建
17.1 重构前
public static Date parseDate(String date) throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
if ((date == null) || (date.equals(""))) { return null; } else { try { return formatter.parse(date); } catch (ParseException pe) { throw new ParseException(pe.getMessage(), pe.getErrorOffset()); } } }
|
17.2 重构后
public static Date parseDate(String date) throws ParseException { if ((date == null) || (date.equals(""))) { return null; } else { try { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); return formatter.parse(date); } catch (ParseException pe) { throw new ParseException(pe.getMessage(), pe.getErrorOffset()); } } }
|
18 利用已有的计算结果
18.1 重构前
public static final String DAY = "DAY"; public static final String MONTH = "MONTH"; public static final String YEAR = "YEAR"; public static final String HOUR = "HOUR"; public static final String MINUTE = "MINUTE"; public static final String SECOND = "SECOND"; public static final String WEEK = "WEEK";
public long toMilliseconds(String unit) { if (unit == null) { return 0L; } else if (unit.equals(SECOND)) { return 1 * 1000L; } else if (unit.equals(MINUTE)) { return 60 * 1000L; } else if (unit.equals(HOUR)) { return 60 * 60 * 1000L; } else if (unit.equals(DAY)) { return 24 * 60 * 60 * 1000L; } else if (unit.equals(WEEK)) { return 7 * 24 * 60 * 60 * 1000L; } else if (unit.equals(MONTH)) { return 30 * 24 * 60 * 60 * 1000L; } else if (unit.equals(YEAR)) { return 365 * 24 * 60 * 60 * 1000L; } else { return 0L; } }
|
18.2 重构后
public class Unit { private static final long SECOND_MILLIS = 1000; private static final long MINUTE_MILLIS = 60 * SECOND_MILLIS; private static final long HOUR_MILLIS = 60 * MINUTE_MILLIS; private static final long DAY_MILLIS = 24 * HOUR_MILLIS; private static final long WEEK_MILLIS = 7 * DAY_MILLIS; private static final long MONTH_MILLIS = 30 * DAY_MILLIS; private static final long YEAR_MILLIS = 365 * DAY_MILLIS; private static final long CENTURY_MILLIS = 100 * YEAR_MILLIS;
static Map<String, Unit> units = new HashMap<String, Unit>();
public static final Unit SECOND = new Unit(SECOND_MILLIS, "SECOND"); public static final Unit MINUTE = new Unit(MINUTE_MILLIS, "MINUTE"); public static final Unit HOUR = new Unit(HOUR_MILLIS, "HOUR"); public static final Unit DAY = new Unit(DAY_MILLIS, "DAY"); public static final Unit WEEK = new Unit(WEEK_MILLIS, "WEEK"); public static final Unit MONTH = new Unit(MONTH_MILLIS, "MONTH"); public static final Unit YEAR = new Unit(YEAR_MILLIS, "YEAR"); public static final Unit CENTURY = new Unit(CENTURY_MILLIS, "CENTURY");
static { units.put(SECOND.name, SECOND); units.put(MINUTE.name, MINUTE); units.put(HOUR.name, HOUR); units.put(DAY.name, DAY); units.put(WEEK.name, WEEK); units.put(MONTH.name, MONTH); units.put(YEAR.name, YEAR); units.put(CENTURY.name, CENTURY); }
private long millis; private String name;
private Unit(long millis, String name) { this.millis = millis; this.name = name; }
public long getMillis() { return millis; }
public String getName() { return name; }
public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(this.getName()); buffer.append("["); buffer.append(this.getMillis()); buffer.append("]"); return buffer.toString(); } }
public long toMilliseconds(Unit unit) { return unit.getMillis(); }
|
19 替换switch结构
19.1 重构前
public boolean isLeap(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
public static int getMonthDays(int year, int month) { int numberDays = 0;
switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numberDays = 31; break;
case 4: case 6: case 9: case 11: numberDays = 30; break;
case 2: numberDays = isLeap(year) ? 29 : 28; break; }
return numberDays; }
|
19.2 重构后
public boolean isLeap(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
private int getFebruaryDays(int year) { return this.isLeap(year) ? 29 : 28; }
public int getMonthDays(int year, int month) { int[] months = new int[] { 31, this.getFebruaryDays(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
return months[month]; }
|
20 避免对参数赋值
20.1 重构前
public Date getStartTime(Date date) { date.setMinutes(fromMinute); date.setDate(fromHour); date.setDate(fromHour); date.setSeconds(0);
return date; }
|
20.2 重构后
public Date getStartTime(final Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, fromHour); calendar.set(Calendar.MINUTE, fromMinute); calendar.set(Calendar.SECOND, 0);
return calendar.getTime(); }
|
21 使用类替换类型代码
21.1 重构前
public class LabelComparator implements Comparator, Serializable {
private static final long serialVersionUID = 1L;
public static final int ASC = 1; public static final int DESC = 2;
private int sortType = ASC;
public LabelComparator() { }
public LabelComparator(int sortType) { this.sortType = sortType; }
public int compare(Object o1, Object o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return -1; }
if (((Label) o1).getIndex() < ((Label) o2).getIndex()) { return (sortType == ASC) ? -1 : 1; } else if (((Label) o1).getIndex() > ((Label) o2).getIndex()) { return (sortType == ASC) ? 1 : -1; } else { return 0; } } }
|
21.2 重构后
public final class SortMode implements Serializable {
private static final long serialVersionUID = 1L;
private static final Map<String, SortMode> INSTANCES = new HashMap<String, SortMode>();
private final int type; private final String name;
private SortMode(int type, String name) { this.type = type; this.name = name; }
public String toString() { return name; }
public static final SortMode ASC = new SortMode(1, "ASC");
public static final SortMode DESC = new SortMode(2, "DESC");
static { INSTANCES.put(ASC.name, ASC); INSTANCES.put(DESC.name, DESC); }
public boolean isAsc() { return ASC.type == this.type; }
public boolean isDesc() { return DESC.type == this.type; }
private Object readResolve() { return INSTANCES.get(name); }
public static SortMode parse(String name) { return (SortMode) INSTANCES.get(name); }
public boolean equals(Object obj) { if (obj instanceof SortMode) { SortMode that = (SortMode) obj; if (that.type == this.type) { return true; } return false; } else { return false; } } }
public class LabelComparator implements Comparator, Serializable {
private static final long serialVersionUID = 1L; public SortMode mode = SortMode.ASC;
public LabelComparator() { }
public LabelComparator(SortMode mode) { this.mode = mode; }
public int compare(Object o1, Object o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return -1; }
if (((Label) o1).getIndex() < ((Label) o2).getIndex()) { return mode.isAsc() ? -1 : 1; } else if (((Label) o1).getIndex() > ((Label) o2).getIndex()) { return mode.isAsc() ? 1 : -1; } else { return 0; } } } |
22 使用对象封装参数
22.1 重构前
public int getRemainMinutes(int hour, int minute, int fromHour, int fromMinute int toHour, int toMinute) { // --------from-------to--------position------- int startHour = toHour; int startMinute = toMinute;
if (this.fromAfterEqual(hour, minute)) { // ------position------from-------to-------- startHour = fromHour; startMinute = fromMinute; } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- startHour = hour; startMinute = minute; }
return this.getMinutes(startHour, startMinute, toHour, toMinute); }
|
22.2 重构后
public class DayPart implements Serializable {
int fromHour = -1; int fromMinute = -1; int toHour = -1; int toMinute = -1;
public int getFromHour() { return fromHour; }
public void setFromHour(int fromHour) { this.fromHour = fromHour; }
public int getFromMinute() { return fromMinute; }
public void setFromMinute(int fromMinute) { this.fromMinute = fromMinute; }
public int getToHour() { return toHour; }
public void setToHour(int toHour) { this.toHour = toHour; }
public int getToMinute() { return toMinute; }
public void setToMinute(int toMinute) { this.toMinute = toMinute; } }
public int getRemainMinutes(int hour, int minute, DatePart datePart) { int fromHour = datePart.getFromHour(); int fromMinute = datePart.getFromMinute(); int toHour = datePart.getToHour(); int toMinute = datePart.getToMinute();
// --------from-------to--------position------- int startHour = toHour; int startMinute = toMinute;
if (this.fromAfterEqual(hour, minute)) { // ------position------from-------to-------- startHour = fromHour; startMinute = fromMinute; } else if (this.toAfterEqual(hour, minute)) { // ------from-------position------to-------- startHour = hour; startMinute = minute; }
return this.getMinutes(startHour, startMinute, toHour, toMinute); }
|
23 封装集合操作
23.1 重构前
public Class Group{
private List<User> userList = new ArrayList<User>();
public void setUserList(List<User> userList){ this.userList = userList; }
public List<User> getUserList(){ return this.userList; } }
|
23.2 重构后
public Class Group{
private List<User> userList = new ArrayList<User>();
public void setUserList(List<User> userList){ this.userList = userList; }
public List<User> getUserList(){ return this.userList; }
public void addUser(User user){ this.getUserList().add(user); user.setGroup(this); }
public void removeUser(User user){ this.getUserList().remove(user); user.setGroup(null); } }
|
24 避免一次性临时变量
24.1 重构前
public int countWeekDay(Month month, WeekDay weekDay) { int count = 0; int[][] weeks = this.getDates()[month.getMonth()]; for (int week = 0, weekLen = weeks.length; week < weekLen; week++) { int date = weeks[week][weekDay.getDay()]; if (date > 0) { count++; } }
return count; }
|
24.2 重构后
public int countWeekDay(Month month, WeekDay weekDay) { int count = 0; int[][] weeks = this.getDates()[month.getMonth()]; for (int week = 0, weekLen = weeks.length; week < weekLen; week++) {
|
25 一个变量一种作用
25.1 重构前
public IPolyDate getIndexWeekDay(Month month, int index, WeekDay weekDay) { |
25.2 重构后
|