Friday, September 25, 2015

The Clean Coder:A Code of Conduct for Professional Programmers



http://www.wklken.me/posts/2013/11/24/the-clean-coder.html
相比问题本身,解决问题的方式、步骤以及反思深度都体现出一个人的职业素养

职业素养: 它体现了能力和素质,又强调了持续的积累和养成

"专业主义"就意味着担当责任
1.3 首先,不行损害之事

1.3.1 不要破坏软件的功能
要做得专业,就不能留下bug
要对自己的不完美负责
所谓专业人士,就是能对自己犯下的错误负责的人,哪怕那些错误实际上是在所难免的
你有责任让失误率无限接近0

所有软件项目的根本指导原则是,软件要易于修改
如果你希望自己的软件灵活可变,那就应该时常修改它: 要证明易于修改,唯一办法就是做些实际的修改
"无情重构",每次读、修改代码,就要比原来更简洁
不要害怕修改代码,(有一套完整测试,你就根本不会害怕)

1.4.1 了解你的领域
1.设计模式
2.设计原则。必须了解SOLID原则,而且要深刻理解组件设计原则
3.方法。必须了解XP/Scrum/精益/看板/瀑布/结构化分析/结构化设计
4.实践。TDD、OOP、结构化编程、持续集成和结对编程
5.工件、UML/DFD/结构图/Petri网络图/状态迁移图表、流程图和决策表

1.4.7 与雇主/客户保持一致
必需弄明白雇主的真正问题, 站在其角度思考.
1.4.8 谦逊

要学会说"不"

第三章 说“是”
3.1 承诺用语
口头上说自己将会去做
心里认真对待做出的承诺
真正付诸行动
当我们承诺某事时,必须认证对待承诺

第四章 编码
具备"出错感知力", 说明你已经能够非常迅速地获得反馈, 能够更为快速地从错误中学习.

要精熟掌握每项技艺, 关键都是要具备"信心"和"出错感知"能力

1.代码必须能够正常工作
2.代码必须能够帮你解决客户提出的问题
3.代码必须能和现有系统结合得天衣无缝
4.其他程序员必须能读懂你的代码

管理延迟的秘诀, 便是早期检测和保持透明.
三个考虑到多种因素的期限:乐观预估,标称预估,悲观预估


4.6.1 期望
调整和确认期望

4.6.4 交付失误
最糟糕:明知道没有完成任务却宣称已经完成

第九章 时间管理
9.1 会议

关于会议,有两条真理

1.会议是必须的
2.会议浪费了大量的时间
专业开发人员同样清楚会议额的高昂成本。所以,如果会议没有现实且显著的成效,他们会主动拒绝

9.1.1 拒绝

邀请你参加会议的人并不负责管理你的时间,为时间负责的人只有你

理智地使用时间,谨慎选择,应当参加哪些会议,礼貌拒绝哪些会议

领导的最重要责任之一, 就是帮你从某些会议脱身. 好的领导一定会主动维护你拒绝出席的决定, 因为她和你一样关心你的时间


站立会议

1.我昨天做了什么
2.今天打算做什么
3.我遇到了什么问题
每个人发言不超过1分钟

9.4 要避免的行为
优先级错乱:提高某个任务优先级来借口推迟真正急迫的任务
专业开发人员会评估每个人物的优先级,排除个人喜好和需求,按照真实的紧急程度来执行任务

9.5 死胡同
慎重的态度和积累的经验可以帮你避免某些死胡同,但无法避免所有
在走入死胡同时,要迅速意识到,并有足够的勇气走回头路
坑法则,The Rule of Holes:如果你掉进坑里,别挖

第十二章 协作
大多数软件都是有团队开发出来的
单打独斗与有利于团队之外都是不专业的表现.

12.1 程序员与人
12.1.1 程序员与雇主
专业程序员的首要职责是满足雇主的需求
专业程序员会花时间去理解业务

12.1.2 程序员与程序员

1.代码个体所有
不正常团队的糟糕症状
2.协作性的代码共有权
共有, 每个人都可以做出合适的修改
3.结对
12.2 小脑

专业人士会共同工作

有些时候,单独工作是正确的。但是一般来说,和他人紧密协作,在大部分时间段中结对工作,是最好的做法

http://boxingp.github.io/blog/2015/02/02/the-clean-coder-reading-notes/
http://game-lab.org/posts/zoc-cleancode-1/
http://game-lab.org/posts/zoc-cleancode-2/

1. 原则:名副其实

  • 选名字是件严肃的事情,选个好名字很重要。
  • 如果名字需要注释来补充,那就不是个好名字。
  • 最重要的是要名副其实,名字能表达出概念和意图。
BAD:

int t = currentTime.elapse(e); // 消逝的时间,以毫秒计
...
if (t > timeout_value)
{
   Zebra::logger->debug("---一次循环用时 %u 毫秒-----", t);
}

GOOD:
int elapsed_ms = currentTime.elapse(e);
...
if (elapsed_ms > timeout_value)
{
   Zebra::logger->debug("-----一次循环用时 %u 毫秒---", elapsed_ms);
}

2. 原则:避免误导

  • 必须避免留下掩藏代码本意的错误线索
  • 避免使用与本意相悖的词
  • 提防使用不同之处较小的名称
  • 拼写前后不一致就是误导
BAD:
std::vector<int> account_list; // _list就是一个误导, accounts会更好

bool sendToZoneServer(); // 和下面的函数差别很小
bool sendToZoneServers(); // sendToAllZoneServers会好点

3. 原则:做有意义的区分

  • 代码是写给人看的,仅仅是满足编译器的要求,就会引起混乱
  • 以数字系列命名(a1,a2,…),纯属误导
  • 无意义的废话: a, an, the, Info, Data
BAD:
void copy(char a1[], char a2[]) {
  for (size_t i = 0; a1[i] != '\0'; i++)
     a2[i] = a1[i];
}
GOOD:
void copy(char source[], char dest[]) {
  for (size_t i = 0; source[i] != '\0'; i++)
     dest[i] = source[i];
}

4. 原则:使用可读的名字

  • 避免过度使用缩写
  • 可读的名字交流方便

5. 原则:使用可搜索的名字

  • 避免使用Magic Number
  • 避免使用单字母,或出现频率极高的短字母组合(注意度的把握)
BAD:
if (obj->base->id == 4661) // 4661是啥玩意?
{
   usetype = Cmd::XXXXXXX;
}

int e; // 怎么查找?
XXXX:iterator it; // 变量作用的范围比较大的时候,也不见得是个好名字

6. 原则:避免使用编码”

  • 匈牙利标记法:
    • Windows API时代留下的玩意
    • 形如:wdXX, dwXXX, strXXX
    • 类型变换导致名不副实,就有可能出现明明是个DWORD,变量名却是qwNum
PS.匈牙利命名对于我们这些在Linux下摸爬滚打的好多年的来说,看着真心别扭。
  • 成员前缀:
    • 形如:m_name, m_xxx
    • 基本上都无视,为何要多次一举
PS.说到这一点,可能有些同学有不同意见了,“我这样写是为了区分成员变量和临时变量啊!”,好像这样写也没什么大不了,遵循代码规范即可。如Google的C++代码规范,私有变量形如:xxx_,加后缀_,其目的除了让你知道这货是个私有变量,还有一点就是防止有些人图省事把带私有变量直接public掉,因为谁也不喜欢在代码里面看到大量这些带把的玩意。
  • 接口和实现:
    • 接口名形如:IXXX, I-接口修饰前缀
    • 类名形如:CXXX, C-类修饰前缀
    • 这些修饰多数时候都是废话

7. 原则:名字尽量来自解决方案领域或问题领域

  • 使用解决方案领域名称:
写代码的同学多数都是都出自CS,术语、算法名、模式名、数学术语尽管用。如AccountVisitor:Visitor模式实现的Account类。
  • 使用问题领域的名称
我们代码里面多数都是这些名称,不明白找策划问问,基本上都是功能相关的名称。

8. 原则:适当使用有意义的语境

  • 良好命名的类、函数、名称空间来放置名称,给读者提供语境
  • 只有两三个变量,给名称前加前缀
  • 事不过三,变量超过三个考虑封装成概念,添加struct或class
BAD:
// 看着整齐?使用方便?
DWORD love_ensure_type_;  //当前的爱情保险类型
DWORD love_ensure_ret_; //购买爱情保险回应标示
DWORD love_ensure_total_; //现在已经盖章数目
DWORD love_ensure_..._;  //...
DWORD love_ensure_..._;  //...

  • 写下任何一行代码的时候,心里都要想着自己的代码是给别人看的。
  • 为函数、变量、类取个好名字,遵循规范和原则。
  • 见到不符合规范和原则的名字,确毫不留情的干掉它,特别是功能性的代码。
http://game-lab.org/posts/zoc-cleancode-3/
这些超大号函数是怎么来得呢?
  • 直接从别处COPY一段代码,随便改改即可,造成大量重复代码。
  • 缺少封装,甚至说就没有封装,完全就是随意乱加一气,造成各个抽象层次的代码混合在一起,混乱不堪。
  • 成篇的异常处理和特殊处理,核心逻辑或许就是函数体开头、中间或结束那么几行而已。

原则:取个描述性的名字

  • 取个一眼就看出函数意图的名字很重要
  • 长而具有描述性的名称,要比短而让人费解的好(长度适中,也不能过分长)

2. 原则:保持参数列表的简洁

  • 无参数最好,其次一元,再次二元,三元尽量避免
  • 尽量避免标识参数
  • 使用参数对象
  • 参数列表
  • 避免输出和输入混用,无法避免则输出在左,输入在右
bool isBossNpc();
void summonNpc(int id);
void summonNpc(int id, int type);
void summonNpc(int id, int state, int type); // 还能记得参数顺序吗?

void showCurrentEffect(int state, bool show); // Bad!!!
void showCurrentEffect(int state); // Good!!
void hideCurrentEffect(int state); // 新加个函数也没多难吧?

bool needWeapon(DWORD skillid, BYTE& failtype); // Bad!!!


    3. 原则:保持函数短小

    4. 原则:只做一件事
    5. 原则:每个函数位于同一抽象层级
    要确保函数只做一件事,函数中的语句都要在同一个抽象层级上
    自顶下下读代码
    6. 原则:无副作用

    8. 原则:使用异常来代替返回错误码

    • 抽离try-cacth
    • 错误处理也是一件事情,也应该封装为函数

    9. 原则:减少重复代码”

    重复是一些邪恶的根源!!!

    10. 原则:避免丑陋不堪的switch-case

    • 天生要做N件事情的货色
    • 多次出现就要考虑用多态进行重构
    当在添加新函数的时候:
    • 刚下手时违反规范和原则没关系
    • 开发过程中逐步打磨
    • 保证提交后的代码是整洁的即可
    重构现有的函数,有下面情况的,见一个消灭一个:
    • 冗长而复杂
    • 有太多缩进和嵌套循环
    • 参数列表过长
    • 名字随意取
    • 重复了三次以上
    在C++语言中,既可以使用使用过程式的struct来做数据抽象,同时也可以使用面向对象的class来做抽象。在语言层面上,struct和class除了默认访问权限不一样,其它都是一样,但本文中区别对待之,一般使用struct时代表的是数据,Plain Of Data,即就是所谓的POD类型,可以直接存档和在网络上传输。而class代表的是对象的类,支持面向对象中的各种用法。


    Labels

    Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

    Popular Posts