注1:只看了书的前十章注2:原书使用的语言为Java,我改成了JavaScript
代码就是衔接人脑理解需求的含糊性和机器指令的精确性的桥梁。哪怕未来会有对现在高级编程语言的再一次抽象——但这个抽象规范自身仍旧是代码。
所以既然代码会一直存在下去,且自己都干了程序员这一行了,就好好的对待它吧。
糟糕的代码会导致项目的难以维护。而当你正在写糟糕的代码的时候,心里却圣洁的想:“有朝一日再回来整理”。但现实是残酷的,正如勒布朗(LeBlanc)法则:稍后等于永不(Laterequalsnever)
大师级程序员把系统当作故事来讲,而不是当作程序来写。
(×)图表:mapTable
(√)图表:chart
constvar=0;
XYZControllerForEfficientKeepingOfStrings
XYZControllerForEfficientHoldingOfStrings
如果是一个数组类型,就没必要叫ProductArray
如果返回值就是数据,就没必要叫ProductData
(×)
if(team.length===3)(√)
constMAX_NUM_OF_TEAM=3;……if(team.length===MAX_NUM_OF_TEAM)MAX_NUM_OF_TEAM比3好检索
早期流行一种匈牙利语标记法:
如arru8NumberList的前缀"arru8"表示变量是一个无符号8位整型数组;
类名、参数名用名词:
memberleader
方法名用动词:
getTeam
根据Javabean的标准,方法名可以加上getsetis前缀
getfetch选一个,不要混着用
如果你要记录member的详细住址,会设置了如下几个变量:
addrStreetaddrHouseNumberaddrCityaddrState(√)
newAddress{street,houseNumber,city,state}第三章函数尽量短小函数的缩进层级尽量控制在1-3层
例如要依次读取A、B、C三个文件:
functiontest(){readFileA(function(err,data){//todoreadFileB(function(err,data){//todoreadFileC(function(err,data){//todo//……});});});}(√)
functiontest(){try{letre_a=awaitreadFileA();letre_b=awaitreadFileB();letre_c=awaitreadFileC();}catch(err){}}只做一件事判断标准:是否可以再拆出一个函数
functiontest(){//......Session.save();//......}(√)
functiontest(){//......saveSession();//......}functionsaveSession(){Session.save();}每个函数即是一个抽象层,如上面的例子,Session跟test函数不是一个抽象层,所以抽离出来。
长且具有描述性的名字比描述性的长注释好
//取出所有满员的团getSpecialGroup()(√)
getGroupOfFullMember()参数顺序太多记不住怎么办?方法一:体现在函数名上(×)assertEqual(expected,actual)
(√)assertExpectedEqualsActual(expected,actual)
现代IDE已经具有鼠标移在调用函数名上可以浮窗显示形参列表了。
functiongetMember({isNew=false,isActivate=false}){console.log("isNew:"+isNew,",isActivate:"+isActivate)}getMember({isNew:true,isActivate:false})//isNew:true,isActivate:false//不会因为传参的顺序记错而出错getMember({isActivate:false,isNew:true})//isNew:true,isActivate:false//也支持默认参数getMember({})//isNew:false,isActivate:false这里用到了ES6的新特性:解构赋值
letobj={a:1,b:2};let{a,b}=obj; //a=1,b=2方法三:减少参数最理想的参数数量<3,最好不用输入参数。
A、布尔值参数一拆二
(×)getMember(isNew)
(√)getNewMember()getOldMember()
这里的前提是获取新、老会员的方法体代码不一样,不然还是共用在一个方法通过布尔值比较好。
B、二元函数变一元
否则得修改多处地方
(1)每个函数都应该有一个入口和一个出口
关于(只能有一个return语句,在结尾处/尽快return,即有多个return语句)的争论:
《结构化编程》的建议:
functiontest(is){letresult;if(is){result=true;}else{result=false;}returnresult;}《重构》的建议:
(2)循环中尽量避免有break或continue,而且决不能出现goto语句。
就像上文提到的用详尽的函数名代替注释,或者:
//代码过于追求简洁而导致这里要加详细的注释if(smodule.getDependSubsystems().contains(subSysMod.getSubSytem()))//还不如这里做拆分,取易懂的变量名方便理解,就可以不用加注释或者少加ArrayListmoduleDependees=smodule.getDependSubsystems();StringourSubSystem=subSysMod.getSubSystem();if(moduleDependees.contains(ourSubSystem))原因是:注释存在的越久,随着代码的不断迭代,会离代码的距离越来越远,这个时候好的做法是同时维护代码+注释,而注释越多越复杂,维护的成本自然就上升了。
注释不能美化糟糕的代码,尽量去优化代码
(2)对意图的解释
(3)警示
(4)TODO注释
(1)只有自己看得懂
(2)多余的注释
a、不能提供比代码更多的信息
(3)歧义性
(4)循规蹈矩的注释
例如用第三方工具生成的注释,很多都是累赘的废话
(5)日志式、署名式注释
//writebycolin//fix#201bug(√)交给git记录
(6)慎用位置标记
//**********************及时清理不需要的注释(1)越堆越多
(2)导致以后因看不懂而不敢删
(1)从上往下读,从左往右读
(2)源文件在最顶端给出高层次的概念和算法,细节往下逐次展开,直到最底层的函数和细节。
(1)善用空白行:人会更容易将目光聚焦到空白行之后的那一行
(2)函数:调用者放在被调用者上面
(1)缩进
(2)IDE中不会出现横向滚动条
数据结构和对象的区别
数据结构暴露其数据,没有提供有意义的函数。
对象把数据隐藏在抽象之后,暴露操作数据的函数。
(上文有述)
如引用了一个第三方库,它会throw自己的几种异常值,但我们可以定义一个异常类,封装好它的几种异常值为一种专门异常,然后再二次throw交给上层捕获。
null值会造成很多不必要的if判断
functiongetCurrentMember(){leta=DB.getCurrentMember();if(a){returna;}else{returnnull;}}方法一:抛异常
functiongetCurrentMember(){leta=DB.getCurrentMember();if(a){returna;}else{throwError("nomember")}}