• 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("\n!include ")
.append(arg)
.append(" .")
.append(pagePathName)
.append("\n");
}
}

Clean Code – Chapter 3: Functions的更多相关文章

  1. Clean Code – Chapter 4: Comments

    “Don’t comment bad code—rewrite it.”——Brian W.Kernighan and P.J.Plaugher The proper use of comments ...

  2. Clean Code–Chapter 7 Error Handling

    Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...

  3. Clean Code – Chapter 6 Objects and Data Structures

    Data Abstraction Hiding implementation Data/Object Anti-Symmetry Objects hide their data behind abst ...

  4. Clean Code – Chapter 5 Formatting

    The Purpose of Formatting Code formatting is about communication, and communication is the professio ...

  5. Clean Code – Chapter 2: Meaningful Names

    Use Intention-Revealing Names The name should tell you why it exists, what it does, and how it is us ...

  6. “Clean Code” 读书笔记序

    最近开始研读 Robert C.Martin 的 “Clean Code”,为了巩固学习,会把每一章的笔记整理到博客中.而这篇博文作为一个索引和总结,会陆续加入各章的笔记链接,以及全部读完后的心得体会 ...

  7. 《Clean Code》一书回顾

    <Clean Code>一书从翻开至今,已经差不多两个月的时间了,尽管刨去其中的假期,算下来实在是读得有点慢.阅读期间,断断续续的做了不少笔记.之前,每每在读完了一本技术书籍之后,其中的诸 ...

  8. [转]Clean Code Principles: Be a Better Programmer

    原文:https://www.webcodegeeks.com/web-development/clean-code-principles-better-programmer/ ----------- ...

  9. 代码整洁之道Clean Code笔记

    @ 目录 第 1 章 Clean Code 整洁代码(3星) ?为什么要整洁的代码 ?什么叫做整洁代码 第 2 章 Meaningful Names 有意义的命名(3星) 第 3 章 Function ...

随机推荐

  1. Python学习笔记—itertools模块

    这篇是看wklken的<Python进阶-Itertools模块小结> 学习itertools模块的学习笔记 在看itertools中各函数的源代码时,刚开始还比较轻松,但后面看起来就比较 ...

  2. R语言的一些笔记

    (1)包中函数必须在NAMESPACE中进行标记导出,否则就不认识了: 例如叫做rtest.Model.LogisticreRression 就能识别,而叫做Model.LogisticreRress ...

  3. 【BZOJ】1006: [HNOI2008]神奇的国度 弦图消除完美序列问题

    1006: [HNOI2008]神奇的国度 Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则. 他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的 ...

  4. Class.forName()的作用与使用总结(转载)

    转载自:Class.forName()的作用与使用总结 1.Class类简介: Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识.这项信息纪录了每个对象所属的类.虚拟机 ...

  5. 来自内部的XSS攻击的防范

    来自内部的XSS攻击的防范 引入:前面我们分2篇文章分别探讨了来自外部的XSS攻击和来自内部的XSS攻击,现在我们来专门探讨如何防范来自内部的XSS攻击. 实践:其实从 http://www.2cto ...

  6. nutch 生产者队列的大小如何控制 threadcount * 50

    如果topN 设置为1000万 ,不会这1000万都放到QueueFeeder(内存)中,而是从文件系统中(hdfs)中迭代不断填充QueueFeeder.队列中默认存放 threadcount * ...

  7. 在Eclipse中添加添加一些有助于开发的插件

    Eclipse不像MyEclipse那样高度的继承了很多插件,Eclipse需要使用什么插件可以自己进行添加,添加tomcatPlugin插件,成功之后你的Eclipse中就会多了几个图标. 参照文章 ...

  8. 9个Java性能优化工具汇总

    本文来自blog.idrsolutions.com 1.NetBeans profiler NetBeans Profiler是一个模块化的添加,为NetBeans IDE提供分析功能,它是一个开源的 ...

  9. M-JPEG和MPEG-4的区别 M-JPEG VS MPEG

    http://blog.sina.com.cn/s/blog_4b357b300100gre9.html M-JPEG VS MPEG http://blog.csdn.net/bluesky_sun ...

  10. usb cdc 协议

    什么是CDC类 (Communication Device Class) USB的CDC类是USB通信设备类 (Communication Device Class)的简称.CDC类是USB组织定义的 ...