zoukankan      html  css  js  c++  java
  • Clean Code – Chapter 3: Functions

    • Small

      • Blocks and Indenting

        The blocks within if statements, else statements, while statements, and so on should be one line long. Probably that line should be a function call.

        Functions shouldn't be large enough to hold nested structures. The indent level of a function should not be greater than one or two.

    • Do One Thing

      Functions should do one thing. They should do it well. They should do it only.

      Describe a function as a brief TO paragraph to see, if a function does only those steps that are one level below the stated name of the function.

      • Sections within Functions

        Functions that do one thing cannot be reasonably divided into sections.

    • One Level of Abstraction per Function

      • Reading Code from Top to Bottom: The Stepdown Rule

    • Switch Statements

      Make sure that each switch statement is buried in a low-level class and is never repeated. (Do this with polymorphism .)

    • Use Descriptive Names

      The smaller and more focused a function is, the easier it is to choose a descriptive name.

      A long descriptive name is better than a long descriptive comment.

      Be consistent in your names.

    • Function Arguments

      The ideal number of arguments for a function is zero(niladic).

      Arguments are hard. They take a lot of conceptual power.

      Arguments are even harder from a testing point of view.

      Output arguments are harder to understand than input arguments.

      • Common Monadic Forms

        Ask a question about that argument: boolean fileExists("myFile").

        Operate on that argument, transform it into something else and return it: InputStream fileOpen("myFile").

        (less common)Interpret the function call as an event and use the argument to alter the state of the system: void passwordAttemptFailedNtimes(int attempts).

      • Flag Arguments

        Passing a boolean into a function is a truly terrible practice. It proclaims that this function does more than one thing.

      • Dyadic Functions

        Ordered components of a single value: Point(x, y).

      • Argument Objects

        When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own.

      • Argument Lists

        If the variable arguments are all treated identically, then they are equivalent to a single argument of type List.

      • Verbs and Keywords

        In the case of a monad, the function and argument should form a very nice verb/noun pair: write(name).

        Encode the names of the arguments into the function name: assertExpectedEqualsActual(expected, actual).

    • Have No Side Effects

      Avoid temporal couplings and order dependencies.

      • Output Arguments

        If function must change the state of something, have it change the state of its owning object: public void appendFooter(StringBuffer report) ==> report.appendFooter.

    • Command Query Separation

      Functions should either do something or answer something, but not both. Either your function should change the state of an object, or it should return some information about that object.

      e.g.

      Bad code:

      public boolean set(String attribute, String value)...
      ...
      if(set("username", "unclebob"))...

      Good code:

      if(attributeExists("username")){
          setAttribute("username", "unclebob");
      }
    • Prefer Exceptions to Returning Error Codes

      • Extract Try/Catch Blocks

        Extract the bodies of the try and catch blocks out into functions of their own.

      • Error Handing Is One Thing

        A function that handles errors should do nothing else.

      • The Error.java Dependency Magnet

        Use exceptions rather than error codes, then new exceptions are derivatives of the exception class. They can be added without forcing any recompilation or redeployment.

    • Don't Repeat Yourself

      Duplication may be the root of all evil in software.

    • Structured Programming

      Every function, and every block within a function, should have one entry and one exist. Following these rules means that there should only be one return statement in a function, no break or continue statements in a loop, and never, ever, any goto statements. (used in larger functions)

    Writing software is like any other kind of writting. Get your thoughts down first, then massage it until it reads well.

    附上本章最后的一个类文件的源代码,读起来真的犹如一篇优美的文章。

    // Clean Code
    // Listing 3-7
    // SetupTeardownIncluder.java
    
    package fitnesse.html;
    
    import fitnesse.responders.run.SuiteResponder;
    import fitnesse.wiki.*;
    
    public class SetupTeardownIncluder {
        private PageData pageData;
        private boolean isSuite;
        private WikiPage testPage;
        private StringBuffer newPageContent;
        private PageCrawler pageCrawler;
    
        public static String render(PageData pageData) throws Exception {
            return render(pageData, false);
        }
    
        public static String render(PageData pageData, boolean isSuite)
        throws Exception {
            return new SetupTeardownIncluder(pageData).render(isSuite);
        }
    
        private SetupTeardownIncluder(PageData pageData) {
            this.pageData = pageData;
            testPage = pageData.getWikiPage();
            pageCrawler = testPage.getPageCrawler();
            newPageContent = new StringBuffer();
        }
    
        private String render(boolean isSuite) throws Exception {
            this.isSuite = isSuite;
            if (isTestPage())
                includeSetupAndTeardownPages();
            return pageData.getHtml();
        }
    
        private boolean isTestPage() throws Exception {
            return pageData.hasAttribute("Test");
        }
    
        private void includeSetupAndTeardownPages() throws Exception {
            includeSetupPages();
            includePageContent();
            includeTeardownPages();
            updatePageContent();
        }
    
        private void includeSetupPages() throws Exception {
            if (isSuite)
                includeSuiteSetupPage();
            includeSetupPage();
        }
    
        private void includeSuiteSetupPage() throws Exception {
            include(SuiteResponder.SUITE_SETUP_NAME, "-setup");
        }
    
        private void includeSetupPage() throws Exception {
            include("SetUp", "-setup");
        }
    
        private void includePageContent() throws Exception {
            newPageContent.append(pageData.getContent());
        }
    
        private void includeTeardownPages() throws Exception {
            includeTeardownPage();
            if (isSuite)
                includeSuiteTeardownPage();
        }
    
        private void includeTeardownPage() throws Exception {
            include("TearDown", "-teardown");
        }
    
        private void includeSuiteTeardownPage() throws Exception {
            include(SuiteResponder.SUITE_TEARDOWN_NAME, "-teardown");
        }
    
        private void updatePageContent() throws Exception {
            pageData.setContent(newPageContent.toString());
        }
    
        private void include(String pageName, String arg) throws Exception {
            WikiPage inheritedPage = findInheritedPage(pageName);
            if (inheritedPage != null) {
                String pagePathName = getPathNameForPage(inheritedPage);
                buildIncludeDirective(pagePathName, arg);
            }
        }
    
        private WikiPage findInheritedPage(String pageName) throws Exception {
            return PageCrawlerImpl.getInheritedPage(pageName, testPage);
        }
    
        private String getPathNameForPage(WikiPage page) throws Exception {
            WikiPagePath pagePath = pageCrawler.getFullPath(page);
            return PathParser.render(pagePath);
        }
    
        private void buildIncludeDirective(String pagePathName, String arg) {
            newPageContent
                .append("
    !include ")
                .append(arg)
                .append(" .")
                .append(pagePathName)
                .append("
    ");
        }
    }
  • 相关阅读:
    matlab中size函数总结
    sudo apt-get install ubuntu-desktop, Error: unable to locate package
    java打包打包
    java2exe exe4j crack
    java程序换图标
    jQuery学习——CSS
    jQuery学习——属性
    jQuery学习——表单
    jQuery学习——内容筛选&可见性筛选
    jQuery学习——基本筛选
  • 原文地址:https://www.cnblogs.com/gumuyueying/p/cleancode-ch3.html
Copyright © 2011-2022 走看看