翻譯|使用教程|編輯:吳園園|2019-08-14 14:38:09.590|閱讀 1405 次
概述:作為開發人員,我們經常重構代碼。要有效地重構代碼,我們必須知道: 為什么,何時以及如何重構它。IntelliJ IDEA通過為您自動化各種重構選項起著至關重要的作用。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
內聯方法重構的思想很簡單 - 用其內容替換方法調用。它仍然非常強大。但要了解它的力量,你需要知道它的用例。
讓我們了解為什么,何時以及如何應用內聯方法重構以及IntelliJ IDEA如何幫助您入門。
一個方法的流程中斷
當方法調用中斷方法中的流而不是簡化它時,您可以考慮應用內聯方法。在下面的代碼中,對方法的調用是在方法compareRatingWithMethodParameter()中插入不必要的間接方法scheduleSession()。
public class Talk {
int rating;
LocalTime scheduleSession() {
return compareRatingWithMethodParameter(3) ?
LocalTime.of(9, 0) :
LocalTime.of(10, 0);
}
private boolean compareRatingWithMethodParameter(int param) {
return rating < param;
}
}通過內聯方法可以簡化上面的代碼compareRatingWithMethodParameter():

但是,您不必內聯每個只定義一行代碼的方法。決定應取決于它是否有助于您了解方法中的流程。
代碼遷移,或使用最新的Java語言功能
將代碼遷移到以后的Java版本時,您可能希望內聯幾種方法,以便可以將操作應用于多個方法的代碼。
雖然在方法中的代碼getSortedListOfNames()看起來可讀,通過內聯方法extractNamesFromSpeakerList()和sortSpeakerNames(),你可以重構它使用Java流,而不是使用for循環和Collections.sort單獨的方法。這是原始代碼:
List getSortedListOfNames(List speakers) {
List speakerNames = extractNamesFromSpeakerList(speakers);
sortSpeakerNames(speakerNames);
return speakerNames;
}
private void sortSpeakerNames(List speakerNames) {
Collections.sort(speakerNames);
}
private List extractNamesFromSpeakerList(List speakers) {
List result = new ArrayList<>();
for (Speaker speaker : speakers) {
result.add(speaker.getName());
}
return result;
}以下是如何內聯方法并重構生成的代碼:

這是重構的代碼,您可以與原始代碼進行比較:
List getSortedListOfNames(List speakers) {
return speakers.stream()
.map(Speaker::getName)
.sorted()
.collect(Collectors.toList());
}一組嚴重重構的方法
程序員通常最終難以應用重構實踐。例如,在下面的代碼中,程序員似乎已經對每個單獨的代碼行應用了“Extract Method Refactoring”。
雖然它看起來仍然可讀,但是內聯其中一些方法并將一個或多個方法的代碼組合到另一個方法中,然后進行(合理的)重構,可以改善代碼的意圖:
List getPanelists(Track track, List speakerList) {
outputTrackName(track);
outputSpeakerList(speakerList);
List panelists = filterSpeakersWithoutTracks(speakerList);
panelists = findSpeakerSpeakingOnTrack(track, panelists);
return panelists;
}
private void outputTrackName(Track track) {
System.out.println("Looking for panelists for track : " + track);
}
private void outputSpeakerList(List list) {
list.forEach(System.out::println);
}
private List filterSpeakersWithoutTracks(List list) {
return list.stream().
filter(s -> s.speakingOn != null)
.collect(Collectors.toList());
}
private List findSpeakerSpeakingOnTrack(Track track, List list) {
return list.stream()
.filter(s -> s.isSpeakingOn(track))
.collect(Collectors.toList());
}讓我們看看我們如何重新組織代碼。讓我們內聯幾個方法,然后將代碼提取到方法中,使代碼簡潔易讀。

同樣,這是您與初始代碼進行比較的最終代碼:
List getPanelists(Track track, List speakerList) {
outputParamValues(track, speakerList);
return speakerList.stream().
filter(s -> s.speakingOn != null && s.isSpeakingOn(track))
.collect(Collectors.toList());
}
private void outputParamValues(Track track, List speakerList) {
System.out.println("Looking for panelists for track : " + track);
speakerList.forEach(System.out::println);
}內聯方法改進
(IntelliJ IDEA 2019.2中的新功能)
IntelliJ IDEA 2019.2包含對Inline Method重構的重大改進。
通過定義多個return語句,方法可能包含多個出口點。當您在IntelliJ IDEA 2019.2中內聯這樣的方法時,可以修改它以僅以單個return語句的形式定義一個退出點,以退出該方法。IntelliJ IDEA將此稱為“轉換為單一退出點”功能。
在下面的代碼中,當您內聯方法時isBreakRequiredBetweenSession(),該過程會引入變量結果。多個return語句將替換為變量的賦值,最后result只有一個return語句:
void outputBreak() {
boolean breakReq = isBreakRequiredBetweenSession();
System.out.println("Break required = " + breakReq);
}
private boolean isBreakRequiredBetweenSession() {
if (isWeekend())
if (isDurationGreaterThan50min())
return true;
else
return false;
else
return false;
}讓我們內聯方法isBreakRequiredBetweenSession():

如您所見,修改后的代碼更容易遵循 - 因為它沒有多個退出點。這是您與初始代碼進行比較的最終代碼:
void outputBreak() {
boolean breakReq;
if (isWeekend())
if (durationGreaterThan50min())
breakReq = true;
else
breakReq = false;
else
breakReq = false;
System.out.println("Break required = " + breakReq);
}開發人員通常return在方法中定義多個語句,這些語句從各種控制語句(如if,for和其他語句)返回值。通常這種方法最后還包括一個return陳述。這是一個示例,它acceptSpeaker()使用行尾注釋在方法中定義多個出口點:
boolean acceptSession(Speaker speaker, Talk talk) {
List days = List.of(DayOfWeek.SUNDAY, DayOfWeek.SATURDAY);
if (speaker.getName().equals("JavaGuru"))
return true; // Exit Point 1
if (talk.getTrack() == Track.SCALA) {
return false; // Exit Point 2
}
for (DayOfWeek day : days) {
if(talk.date.getDayOfWeek().equals(day)) {
return true; // Exit Point 3
}
}
return false;
}
boolean submitTalk(Speaker speaker, Talk talk) {
System.out.println("Received another submission");
boolean isAccepted = acceptSession(speaker, talk);
if (isAccepted) {
// Update website
}
return isAccepted;
}當您在內聯方法acceptSession()時submitTalk(),IntelliJ IDEA將檢測其多個退出語句并相應地修改代碼:

以下是您要比較的最終代碼(為方便起見添加了行尾注釋):
boolean submitTalk(Speaker speaker, Talk talk) {
System.out.println("Received another submission");
boolean isAccepted = false;
List days = List.of(DayOfWeek.SUNDAY, DayOfWeek.SATURDAY);
if (speaker.getName().equals("JavaGuru")) {
isAccepted = true; // Assignment
} else {
if (talk.getTrack() != Track.SCALA) {
for (DayOfWeek day : days) {
if (talk.date.getDayOfWeek().equals(day)) {
isAccepted = true; // Assignment
break; // break statement added
}
}
}
}
if (isAccepted) {
// Update website
}
return isAccepted; // single return statement
}具有否定的內聯方法
(IntelliJ IDEA 2019.2中的新功能)
通過IntelliJ IDEA 2019.2的增強功能,內聯方法重構還支持呼叫站點的否定。在下面的代碼中,當您在方法中check()使用否定方法內聯方法時isValidName(),它將不會被修改為“單個退出點”:
boolean check(Speaker speaker) {
if (speaker == null) return false;
String name = speaker.name.trim();
if (name.isEmpty()) return false;
return name.length() % 2 == 0;
}
boolean isValidName(Speaker speaker) {
return !check(speaker);
}這是內聯代碼被否定的方式 - 注意返回值的反轉和條件(name.length() % 2 == 0)到(name.length() % 2 != 0):

以下是修改后的代碼,供您與原始代碼進行比較:
boolean isValidName(Speaker speaker) {
if (speaker == null) return true;
String name = speaker.name.trim();
if (name.isEmpty()) return true;
return name.length() % 2 != 0;
}快樂的編碼和合理的重構!
IntelliJ IDEA為您自動化各種重構選項起著至關重要的作用。感興趣的朋友趕快下載體驗吧~
想要購買IntelliJ IDEA正版授權的朋友可以。

本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@ke049m.cn
文章轉載自: