翻译|使用教程|编辑:吴园园|2019-08-14 14:38:09.590|阅读 1333 次
概述:作为开发人员,我们经常重构代码。要有效地重构代码,我们必须知道: 为什么,何时以及如何重构它。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@cahobeh.cn
文章转载自: