0

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

作者说他书中几乎所有的方法都可能少于 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 行...

这对我来说看起来很矛盾,还是我想错了?

4

3 回答 3

2

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

  • 该功能可以拆分,里面有一些通用任务。例如几个模块的初始化。在那里,将它分解为只涉及一个模块的较小功能是有意义的。
  • 多次使用的单独代码。例如计算一些日期差异,您必须检查空值。

在我看来,将每种方法都分解为 5 行是不好的。所以你必须跳过代码才能看到真正发生了什么。此外,如果这不是现代编译的主题,那么您的代码会有更多的跳转,这可能会使您的代码变慢......好吧,也许只是几纳秒,但也有一些重要的实时问题。

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

于 2012-08-29T09:06:59.103 回答
1

干净的代码不应包含超过 5 行的方法的标准不一定是好的。

在我看来,一个人应该

  • 尝试封装在代码的许多部分中常用的功能/更频繁地编写代码行数。这使得代码更不容易出错并且调试更容易!节省大量时间。
  • 合并属于一个逻辑执行块的代码,使阅读代码更容易理解。一个好的结构物超所值,尤其是在处理大型项目时!
  • 以使阅读代码更易于理解的方式命名函数!!!
  • 彻底记录函数、参数、变量和代码,这样您就可以使用 doxygen 等工具轻松生成可打印的文档。当不止一个开发人员在处理您的代码时,它就派上用场了。

因此,与其坚持一个固定的数字,不如追求可理解性和结构!

于 2012-08-29T09:14:14.590 回答
0

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

于 2012-08-29T08:59:23.470 回答