方法如何长达3行?

时间:2012-08-29 08:54:33

标签: refactoring

我正在读一本关于清洁编码的书,还有示例代码。

作者说他的书几乎所有方法都不到5行。


这是一个看似难以理解的无意义的代码。

  public static String testableHtml(
    PageData pageData,
    boolean includeSuiteSetup
  ) throws Exception {
    WikiPage wikiPage = pageData.getWikiPage();
    StringBuffer buffer = new StringBuffer();
    if (pageData.hasAttribute("Test")) {
      if (includeSuiteSetup) {
        WikiPage suiteSetup =
          PageCrawlerImpl.getInheritedPage(
                  SuiteResponder.SUITE_SETUP_NAME, wikiPage
          );
        if (suiteSetup != null) {
          WikiPagePath pagePath =
            suiteSetup.getPageCrawler().getFullPath(suiteSetup);
          String pagePathName = PathParser.render(pagePath);
          buffer.append("!include -setup .")
                .append(pagePathName)
                .append("\n");
        }
      }
      WikiPage setup = 
        PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);
      if (setup != null) {
        WikiPagePath setupPath =
          wikiPage.getPageCrawler().getFullPath(setup);
        String setupPathName = PathParser.render(setupPath);
        buffer.append("!include -setup .")
              .append(setupPathName)
              .append("\n");
      }
    }
    buffer.append(pageData.getContent());
    if (pageData.hasAttribute("Test")) {
      WikiPage teardown = 
        PageCrawlerImpl.getInheritedPage("TearDown", wikiPage);
      if (teardown != null) {
        WikiPagePath tearDownPath =
          wikiPage.getPageCrawler().getFullPath(teardown);
        String tearDownPathName = PathParser.render(tearDownPath);
        buffer.append("\n")
              .append("!include -teardown .")
              .append(tearDownPathName)
              .append("\n");
      }
      if (includeSuiteSetup) {
        WikiPage suiteTeardown =
          PageCrawlerImpl.getInheritedPage(
                  SuiteResponder.SUITE_TEARDOWN_NAME,
                  wikiPage
          );
        if (suiteTeardown != null) {
          WikiPagePath pagePath =
            suiteTeardown.getPageCrawler().getFullPath (suiteTeardown);
          String pagePathName = PathParser.render(pagePath);
          buffer.append("!include -teardown .")
                .append(pagePathName)
                .append("\n");
        }
      }
    }
    pageData.setContent(buffer.toString());
    return pageData.getHtml();
  }

上面的代码重构如下。

 public static String renderPageWithSetupsAndTeardowns(
    PageData pageData, boolean isSuite
  ) throws Exception {
    boolean isTestPage = pageData.hasAttribute("Test");
    if (isTestPage) {
      WikiPage testPage = pageData.getWikiPage();
      StringBuffer newPageContent = new StringBuffer();
      includeSetupPages(testPage, newPageContent, isSuite);
      newPageContent.append(pageData.getContent());
      includeTeardownPages(testPage, newPageContent, isSuite);
      pageData.setContent(newPageContent.toString());
    }
    return pageData.getHtml();
  }

最后变得像这样

 public static String renderPageWithSetupsAndTeardowns(
    PageData pageData, boolean isSuite) throws Exception {
    if (isTestPage(pageData))
      includeSetupAndTeardownPages(pageData, isSuite);
    return pageData.getHtml();
  }

我可以认识到这三个代码在重构时更好。

即使它长3或4行,最后一个名为 includeSetupAndTeardownPages(pageData,isSuite)或其内部方法的方法可能超过5行......

这看起来与我相矛盾,还是我错误地思考?

3 个答案:

答案 0 :(得分:2)

我个人认为将方法分解为5行是没有意义的。它应该是有道理的:

  • 该功能可以拆分,里面有一些常规任务。例如。几个模块的初始化。在那里打破它如此小的功能是有意义的,这只涉及一个模块。
  • 多次使用的单独代码。例如。计算一些日期差异,或者你必须检查空值。

将每个方法分解为仅仅5行是我认为不好的。所以你必须跳过代码才能看到真正发生的事情。此外,如果这不是现代编译的主题,你有更多的跳转到你的代码,这可能会使你的代码更慢...好吧可能只有几纳秒,但在这里也有一些困难的实时问题。

总的来说,我听过几次(我也是这么认为),最好不要编写比屏幕更长的代码(函数/方法)。这样您就可以在不滚动的情况下阅读代码。

答案 1 :(得分:1)

清洁代码不应包含超过5行的方法的标准不一定好。

在我的观点中,应该

  • 尝试封装代码的许多部分中常用的功能/更频繁,因此您可以编写更少的代码行。这使得代码不易出错,调试更容易!节省了大量时间。
  • 组合属于一个逻辑执行块的代码,这使得阅读代码更易于理解。一个好的结构是值得的,特别是在与大项目合作时!
  • 以一种让阅读代码更易于理解的方式命名函数!!!
  • 彻底记录函数,参数,变量和代码,这样您就可以使用doxygen等工具轻松生成可打印的文档。当有不止一个开发人员处理您的代码时,就会出现。

所以,不要坚持使用固定数字,而是要求可理解性和结构!

答案 2 :(得分:0)

我想作者正在将1种方法分解为2,3,4或更多种方法来实现这一目标。我不认为干净的代码是一个代码,其方法的长度少于5行。