一、导言
以下导言的内容,有必要随同这个系列的每一次更新,这次也不破例。
《代码整齐之道》这本书提出了一个观念:代码质量与其整齐度成正比,洁净的代码,既在质量上牢靠,也为后期保护、晋级奠定了杰出基础。书中介绍的规矩均来自作者多年的实践经历,包括从命名到重构的多个编程方面,虽为一“家”之言,然诚有可资学习的价值。
但咱们知道,许多时分,抱负很饱满,实践很骨感,也知道人在江湖,情不自禁。由于项目的紧迫性,需求的多样性,咱们无法时时刻刻都写出整齐的代码,坚持自己输出的都是高质量、高雅的代码。
但若咱们理解了代码整齐之道的精华,咱们会知道怎样让自己的代码愈加高雅、整齐、易读、易扩展,知道真实整齐的代码应该是怎么样的,或许就会逐渐养成持续输出整齐代码的习气。
并且或许你会发现,若你一向坚持输出整齐代码的习气,长时间来看,会让你的全体功率和代码质量大大提高。
二、本文触及知识点思想导图
国际惯例,先放出这篇文章所触及内容知识点的一张思想导图,就开端正文。咱们若是疲于阅览文章正文,直接看这张图,也是能够Get到本文的首要知识点的大约。
三、整齐代码的函数书写准则
1 矮小
函数的榜首规矩是要矮小。第二规矩仍是要矮小。
《代码整齐之道》一书作者Bob大叔写道,“近40年来,我写过各种长度不同的函数。我写过令人憎恨的长达3000行的厌物,也写过许多100行到300行的函数,还写过20行到30行的。通过绵长的试错,经历告诉我,函数就该矮小”。
那么函数应该有多矮小适宜呢?一般来说,应该短于如下这个函数:
[cpp] view plain copy print?
public static StringrenderPageWithSetupsAndTeardowns
(PageData pageData, boolean isSuite
)throws Exception
{
booleanisTestPage = pageData.hasAttribute("Test");
if(isTestPage) {
WikiPagetestPage = pageData.getWikiPage( );
StringBuffernewPageContent = new StringBuffer( );
includeSetupPages(testPage,newPageContent, isSuite);
newPageContent.append(pageData.getContent());
includeTeardownPages(testPage,newPageContent, isSuite);
pageData.setContent(newPageContent.toString());
}
returnpageData.getHtml( );
}
而其实,最好应该缩短成如下的姿态:
[csharp] view plain copy print?
public static StringrenderPageWithSetupsAndTeardowns(
PageDatapageData, boolean isSuite) throws Exception
{
if(isTestPage(pageData))
includeSetupAndTeardownPages(pageData,isSuite);
returnpageData.getHtml( );
}
总归,十行以内是整齐的函数比较适宜的长度,若没有特殊情况,咱们最好将单个函数操控在十行以内。
谈论区有一些评论,也放到正文来吧。
“函数是否应该满意矮小,算是《代码整齐之道》中最具争议的议题之一。
书写矮小函数的时分,其实咱们不要疏忽一点,那便是,函数称号号自身就具描述性。矮小的函数构成,假如要追根溯源了解内部完成,天然需求一层层找到终究的完成。但若是想大致知道这个函数究竟做了什么,结合这个矮小函数体内具描述性的一些函数名,应该也就一望而知了。试想,当你眼前的这个函数是几十上百上千行的庞然大物的时分,你能做到一眼就一望而知,将其大约做了什么了然于心吗?函数矮小的一方面长处,在这里就体现出来了。
函数应该矮小这个议题,仁者见仁智者见智,在实践编码过程中任何人都很难做到严格遵守,但大的方向,若想写出整齐的代码,应该去向矮小的函数挨近,对吧?”
2 单一责任
函数应该只做一件作业。只做一件事,做好这件事。
规划形式中有单一责任准则,咱们能够把这条准则理解为代码整齐之道中的函数单一责任准则。
要判别函数是不是只做了一件作业,还有一个办法,便是看能否再拆出一个函数,该函数不只仅仅单纯地从头诠释其完成。
3 命名适宜且具描述性
“假如每个例程都让你感到深合己意,那便是整齐的代码。”要遵照这一准则,多半作业都在于为只做一件事的小函数取个好名字。函数越矮小,功用越会集,就越便于取个好名字。
别惧怕长称号。长而具有描述性的称号,比短而令人费解的称号好。并且长而具有描述性的称号,比描述性的长注释要好。且挑选描述性的称号能理清你关于模块的规划思路,并帮你改善之。当然,假如短的称号现已满意阐明问题,仍是越短越好。
命名方法要坚持一致。运用与模块名一脉相承的短语、名词和动词给函数命名。比方,includeSetupAndTeardownPages,includeSetupPages, includeSuiteSetupPage, and includeSetupPage等。这些名词运用了相似的遣词,依序叙述一个故事,便是是比较推重的命名方法了。
4 参数尽或许少
最抱负的函数参数形状是零参数,其次是单参数,再次是双参数,应尽量防止三参数及以上参数的函数,有满意的理由才能用三个以上参数(多参数函数)。
函数参数中呈现标识符参数是十分不推重的做法。有标识符参数的函数,很有或许不止在做一件事,标明假如标识符为true将这样做,标识符为false将那样做。正确的做法应该将有标识符参数的函数一分为二,对标识符为true和false分别开一个函数来处理。
5 防止重复
重复的代码会导致模块的臃肿,整个模块的可读性或许会应该重复的消除而得到提高。
其实能够这样说,重复或许是软件中一切凶恶的本源,许多准则与实践规矩都是为操控与消除重复而创立的。细心想一想,面向对象编程是怎么将代码会集到基类,然后防止了冗余的。而面向方面编程(Aspect Oriented Programming)、面向组件编程(ComponentOriented Programming)多少也是消除重复的一种战略。这样看来,自子程序创造以来,软件开发范畴的一切立异都是在不断测验从源代码中消除重复。
重复而烦琐的代码,乃万恶之源,咱们要极力防止。
四、典范
有必要贴出一段书中推重的整齐代码作为本次函数书写准则的典范。
[csharp] view plain copy print?
using System;
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");
}
}
上面这段代码,满意了函数书写矮小、单一责任、命名适宜、参数尽或许少、不重复烦琐这几条准则。整齐的函数代码大致如此。
五、小结
大师级程序员把体系当作故事来讲,而不是作为程序来写。这是之前现已提到过的一个观念。
本文叙述了怎么编写杰出函数的一些准则,假如你遵照这些准则,函数就会矮小,有个好名字,并且被很好的归置。不过永久不要忘掉,咱们真实的方针在于叙述体系的故事,而你编写的函数有必要洁净利落的拼装到一同,构成一种准确而明晰的言语,协助你讲故事。
程序员,其实是故事家。
六、本文触及知识点提炼收拾
整齐代码的函数书写,能够遵照如下几个准则:
榜首准则:矮小。若没有特殊情况,最好将单个函数操控在十行以内。
第二准则:单一责任。函数应该只做一件作业。只做一件事,做好这件事。
第三准则:命名适宜且具描述性。长而具有描述性的称号,比短而令人费解的称号好。当然,假如短的称号现已满意阐明问题,仍是越短越好。
第四准则:参数尽或许少。最抱负的函数参数形状是零参数,其次是单参数,再次是双参数,应尽量防止三参数及以上参数的函数,有满意的理由才能用三个以上参数。
第五准则:极力防止重复。重复的代码会导致模块的臃肿,整个模块的可读性或许会应该重复的消除而得到提高。
本文就此结束。
下篇文章,咱们将持续《代码整齐之道》的精读与演绎,讨论更多的内容。
Best Wish~