问题重复一次,但我仍然在问,因为通过使用解决方案中建议的方法,我无法显着降低复杂性。 函数复杂度为28,我必须将其降低到10以下。
private void adjustViewport(IEditorPart editorPart, LineRange range,
TextSelection selection) {
ITextViewer viewer = EditorAPI.getViewer(editorPart);
if (viewer == null) +1
return; +1
IDocument document = viewer.getDocument();
LineRange viewportOfViewer = EditorAPI.getViewport(viewer);
if (viewportOfViewer == null || document == null) +1 +1
return; +1
int lines = document.getNumberOfLines();
int rangeTop = 0;
int rangeBottom = 0;
int selectionTop = 0;
int selectionBottom = 0;
if (selection != null) { +1
try {
selectionTop = document.getLineOfOffset(selection.getOffset());
selectionBottom = document.getLineOfOffset(selection
.getOffset() + selection.getLength());
} catch (BadLocationException e) { +1
// should never be reached
LOG.error("Invalid line selection: offset: "
+ selection.getOffset() + ", length: "
+ selection.getLength());
selection = null;
}
}
if (range != null) { +1
if (range.getStartLine() == -1) { +1
range = null;
} else {
rangeTop = Math.min(lines - 1, range.getStartLine());
rangeBottom = Math.min(lines - 1,
rangeTop + range.getNumberOfLines());
}
}
if (range == null && selection == null) +1 +1
return; +1
// top line of the new viewport
int topPosition;
int localLines = viewportOfViewer.getNumberOfLines();
int remoteLines = rangeBottom - rangeTop;
int sizeDiff = remoteLines - localLines;
// initializations finished
if (range == null || selection == null) { +1 +1
topPosition = (rangeTop + rangeBottom + selectionTop + selectionBottom) / 2;
viewer.setTopIndex(topPosition);
return; +1
}
/*
* usually the viewport of the follower and the viewport of the followed
* user will have the same center (this calculation). Exceptions may be
* made below.
*/
int center = (rangeTop + rangeBottom) / 2;
topPosition = center - localLines / 2;
if (sizeDiff <= 0) { +1
// no further examination necessary when the local viewport is the
// larger one
viewer.setTopIndex(Math.max(0, Math.min(topPosition, lines)));
return; +1
}
boolean selectionTopInvisible = (selectionTop < rangeTop + sizeDiff / 2);
boolean selectionBottomInvisible = (selectionBottom > rangeBottom
- sizeDiff / 2 - 1);
if (rangeTop == 0 +1
&& !(selectionTop <= rangeBottom && selectionTop > rangeBottom +1 +1
- sizeDiff)) {
// scrolled to the top and no selection at the bottom of range
topPosition = 0;
} else if (rangeBottom == lines - 1 +1
&& !(selectionBottom >= rangeTop && selectionBottom < rangeTop +1 +1
+ sizeDiff)) {
// scrolled to the bottom and no selection at the top of range
topPosition = lines - localLines;
} else if (selectionTopInvisible && selectionBottom >= rangeTop) { +1 +1
// making selection at top of range visible
topPosition = Math.max(rangeTop, selectionTop);
} else if (selectionBottomInvisible && selectionTop <= rangeBottom) { +1 +1
// making selection at bottom of range visible
topPosition = Math.min(rangeBottom, selectionBottom) - localLines
+ 1;
}
viewer.setTopIndex(Math.max(0, Math.min(topPosition, lines)));
}
编辑:我已将复杂度降低到11.我应该如何减少它的作用?
private int setTopPositionUtil(int sizeDiff, int rangeTop, int rangeBottom, int selectionTop, int selectionBottom) {
boolean selectionTopInvisible = (selectionTop < rangeTop + sizeDiff / 2);
boolean selectionBottomInvisible = (selectionBottom > rangeBottom - sizeDiff / 2 - 1);
if (rangeTop == 0 && !(selectionTop <= rangeBottom && selectionTop > rangeBottom - sizeDiff)) { // +1 +1 +1
// scrolled to the top and no selection at the bottom of range
topPosition = 0;
} else if (rangeBottom == lines - 1 && !(selectionBottom >= rangeTop && selectionBottom < rangeTop + sizeDiff)) { // +1 +1 +1
// scrolled to the bottom and no selection at the top of range
topPosition = lines - localLines;
} else if (selectionTopInvisible && selectionBottom >= rangeTop) { // +1 +1
// making selection at top of range visible
topPosition = Math.max(rangeTop, selectionTop);
} else if (selectionBottomInvisible && selectionTop <= rangeBottom) { // +1 +1
// making selection at bottom of range visible
topPosition = Math.min(rangeBottom, selectionBottom) - localLines + 1;
}
return topPosition;
}
private int setTopPosition(int localLines, int rangeTop, int rangeBottom,int selectionTop, int selectionBottom) {
// top line of the new viewport
int topPosition;
int remoteLines = rangeBottom - rangeTop;
int sizeDiff = remoteLines - localLines;
// initializations finished
/*
* usually the viewport of the follower and the viewport of the followed
* user will have the same center (this calculation). Exceptions may be
* made below.
*/
int center = (rangeTop + rangeBottom) / 2;
topPosition = center - localLines / 2;
if (sizeDiff > 0) { // +1
setTopPositionUtil(sizeDiff, rangeTop, rangeBottom, selectionTop, selec);
}
return Math.max(0, Math.min(topPosition, lines)); // +1
}
private void adjustViewport(IEditorPart editorPart, LineRange range,TextSelection selection) {
ITextViewer viewer = EditorAPI.getViewer(editorPart);
if (viewer != null) { // +1
IDocument document = viewer.getDocument();
LineRange viewportOfViewer = EditorAPI.getViewport(viewer);
if (viewportOfViewer != null && document != null) { // +1 +1
int lines = document.getNumberOfLines();
int rangeTop = 0;
int rangeBottom = 0;
int selectionTop = 0;
int selectionBottom = 0;
if (selection != null) { // +1
try {
selectionTop = document.getLineOfOffset(selection.getOffset());
selectionBottom = document.getLineOfOffset(selection
.getOffset() + selection.getLength());
} catch (BadLocationException e) { // +1
// should never be reached
LOG.error("Invalid line selection: offset: " +
selection.getOffset() + ", length: " +
selection.getLength());
selection = null;
}
}
if (range != null) { // +1
if (range.getStartLine() == -1) { // +1
range = null;
} else {
rangeTop = Math.min(lines - 1, range.getStartLine());
rangeBottom = Math.min(lines - 1,
rangeTop + range.getNumberOfLines());
}
}
if (range != null && selection != null) { // +1 +1
viewer.setTopIndex(setTopPosition(viewportOfViewer.getNumberOfLines(),
rangeTop, rangeBottom, selectionTop, selectionBottom));
} else {
viewer.setTopIndex((rangeTop + rangeBottom + selectionTop + selectionBottom) / 2);
}
}
}
}
注意:代码现在包含3种方法。第二个和第三个的复杂度低于10,但setTopPositionUtil的复杂性仍为11.任何帮助?
对不起缩进。
答案 0 :(得分:1)
您的问题非常广泛,但为了让您前进,您应该执行以下操作:
换句话说:您编写了如此多的测试用例,您完全确信您对生产代码中的每个和任何方面进行了测试。
然后你开始重构。而且你一直在运行你的测试套件;确保你不破坏任何东西。并且您继续运行复杂度量标准工具;确保你朝着正确的方向前进。
当问题是:我如何重构,然后转向Fowler的Refactoring或Martin的Clean Code等经典。
一般情况下,我认为您也会关注错误的主题:主要目标应该是创建可读代码很容易遵循。我的建议是将这个巨大的方法进一步切成一些较小的方法。
答案 1 :(得分:0)
正如GhostCat已提到的那样,您需要创建一系列单元测试来测试重构。
关于我所做的重构的一些注意事项:
setTopPosition
更好地命名为calculateTopPosition
)viewer
不再传递给方法calculateTopIndex
,因为它只需要它的结果。下面你可以看到解决问题的方法之一:
private void adjustViewport(IEditorPart editorPart, LineRange range, TextSelection selection) {
ITextViewer viewer = EditorAPI.getViewer(editorPart);
if (viewer == null) return; // +1
IDocument document = viewer.getDocument();
LineRange viewportOfViewer = EditorAPI.getViewport(viewer);
if (viewportOfViewer == null || document == null) return; // +1
viewer.setTopIndex(calculateTopIndex(document, viewportOfViewer, range, selection);
}
private int calculateTopIndex(IDocument document, LineRange viewportOfViewer, LineRange range, TextSelection
selection) {
int selectionTop = 0;
int selectionBottom = 0;
if (selection != null) { // +1
try {
selectionTop = document.getLineOfOffset(selection.getOffset());
selectionBottom = document.getLineOfOffset(selection
.getOffset() + selection.getLength());
} catch (BadLocationException e) { // +1
// should never be reached
LOG.error("Invalid line selection: offset: " +
selection.getOffset() + ", length: " +
selection.getLength());
selection = null;
}
}
if (!isRangeValid(range)) { // +1
return (selectionTop + selectionBottom) / 2;
}
int lines = document.getNumberOfLines();
int rangeTop = Math.min(lines - 1, range.getStartLine());
int rangeBottom = Math.min(lines - 1,
rangeTop + range.getNumberOfLines());
boolean isSelectionPresent = selection != null;
if (isSelectionPresent) { // +1
return setTopPosition(viewportOfViewer.getNumberOfLines(), rangeTop, rangeBottom, selectionTop,
selectionBottom);
} else {
return (rangeTop + rangeBottom) / 2;
}
}
private boolean isRangeValid(LineRange range) {
return (range != null && range.getStartLine() != -1);
}