Clean Code – Chapter 3: Functions
Small
Blocks and Indenting
The blocks within
ifstatements,elsestatements,whilestatements, 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
switchstatement 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
tryandcatchblocks 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
returnstatement in a function, nobreakorcontinuestatements in a loop, and never, ever, anygotostatements. (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的更多相关文章
- Clean Code – Chapter 4: Comments
“Don’t comment bad code—rewrite it.”——Brian W.Kernighan and P.J.Plaugher The proper use of comments ...
- Clean Code–Chapter 7 Error Handling
Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...
- Clean Code – Chapter 6 Objects and Data Structures
Data Abstraction Hiding implementation Data/Object Anti-Symmetry Objects hide their data behind abst ...
- Clean Code – Chapter 5 Formatting
The Purpose of Formatting Code formatting is about communication, and communication is the professio ...
- 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 ...
- “Clean Code” 读书笔记序
最近开始研读 Robert C.Martin 的 “Clean Code”,为了巩固学习,会把每一章的笔记整理到博客中.而这篇博文作为一个索引和总结,会陆续加入各章的笔记链接,以及全部读完后的心得体会 ...
- 《Clean Code》一书回顾
<Clean Code>一书从翻开至今,已经差不多两个月的时间了,尽管刨去其中的假期,算下来实在是读得有点慢.阅读期间,断断续续的做了不少笔记.之前,每每在读完了一本技术书籍之后,其中的诸 ...
- [转]Clean Code Principles: Be a Better Programmer
原文:https://www.webcodegeeks.com/web-development/clean-code-principles-better-programmer/ ----------- ...
- 代码整洁之道Clean Code笔记
@ 目录 第 1 章 Clean Code 整洁代码(3星) ?为什么要整洁的代码 ?什么叫做整洁代码 第 2 章 Meaningful Names 有意义的命名(3星) 第 3 章 Function ...
随机推荐
- jquery 循环显示div的示例代码
我们用一个语句就让下面五个div显示成功,具体实现如下,感兴趣的朋友可以参考下 直接看例子 复制代码代码如下: for(var p=1; p<=5; p++){ $("#proper ...
- PHP程序员的技术成长规划(送给迷茫的你)
按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...
- 技术名词解释——Camus
由LinkedIn公司开发的消息队列同步框架,提供将Kafka(一种消息队列框架)的数据装载到Hadoop分布式文件系统(HDFS)的功能. 英文版原文出处:http://docs.confluent ...
- 转:testlink 环境搭建(傻瓜版)
testlink 环境搭建(傻瓜版) 2011-11-24 22:23 by 虫师, 12322 阅读, 4 评论, 收藏, 编辑 今天抽了点时间把testlink 环境搭建了一下,一直觉得这东西不怎 ...
- 【加密】RSA加密之算法
RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的. RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥, ...
- Git的一些基本概念
Git的一些基本概念 设置自己的用户名和邮箱git config –global user.name "Your Name"git config –global user.emai ...
- CSS content内容生成技术以及应用(转)
一.哗啦哗啦的简介 zxx://这里“哗啦哗啦”的作用是为了渲染一种氛围.content属性早在 CSS2.1的时候就被引入了,可以使用:before以及:after伪元素生成内容.此特性目前已被大部 ...
- csuoj 1352: New Sorting Algorithm
因为每个元素都是移动到比它小1位的元素的后面: 这样的话以后的一定就可以把他们两个打包: 所以用这种方法最多扫一遍就可以了: 但是最小的那个数要不要移动呢? 如果最小的数后面的数都是升序的,那么一直扫 ...
- 1012: [JSOI2008]最大数maxnumber
单点更新,区间求最大值的题: 可以使用树状数组和线段树: #include<cstdio> #include<cstring> #include<algorithm> ...
- [Gauss]POJ1222 EXTENDED LIGHTS OUT
题意:给一个5*6的矩阵 1代表该位置的灯亮着, 0代表该位置的灯没亮 按某个位置的开关,可以同时改变 该位置 以及 该位置上方.下方.左方.右方, 共五个位置的灯的开.关(1->0, 0-&g ...