如何写好代码

1,616 阅读11分钟

内容提纲:

  • 树立正确的职业观
  • 编码与设计
  • 编程价值观
  • 什么是好的代码
  • 代码的坏味道
  • 如何重构

一、树立正确的职业观

1)写代码这份工作,可以干多久?

问:是吃青春饭的玩意 答:我马上就不编码了,没意思!

甲:你工作多久了? 乙:六年吧! 甲:靠,六年了,你还在写代码啊? 乙:汗。。。。。。

2)写代码的,就是软件蓝领?

甲:最近,混得怎么样?听说,你还在写代码啊? 乙:滚,你才在写代码呢,你全家都在写代码!

3)写代码的,路在何方?

  • 不要被成为项目经理,不要被成为架构师
  • 其实,我们可以一直在编码!

二、编码与设计

1)设计高于代码?

甲(架构师):这个设计我已经全部完成了,你们编码吧!这个星期完成! 乙们:大哥,一个星期搞不定啊! 甲:为什么? 乙们:这个设计,有点好像问题啊??按照你的设计,有很多细节,没考虑到啊。 甲:细节?那是你们程序员的事情。我是做架构的! 乙们:无语了:cry::cry::cry:(再问就继续被鄙视了)

2)最好的设计经常是在编码阶段产生的

编程前做设计这种思路是没错的 , 然而设计后不应该就认为该模型就是任务的最好设计 . 你会发现最好的设计是你在编码阶段 , 一步一步逐渐形成的 。

3)真正的牛人是怎么说的:

  • 设计看做软件开发的关键环节, 而把编程看做机械式的低级劳动 。设计就像画工程图纸而编码就像施工 。但是这是错误的 !!!!! 软件的可塑性更强 ,而且完全是思想产品。
  • 一些项目中,设计也许可能会详细到能够让编码工作近乎机化,但很少有如此完整的设计 —— 程序员 ( 指编程 ) 通常也要部分程序进行设计,也许是正式的,也许不是。
  • 有了设计 , 我可以编程更快 , 但其中充满小漏洞 -Alistar Cockburn
    在这里插入图片描述
  • 什么是软件设计? -- 代码也是设计 © Jack W.Reeves , 1992
  • 软件系统源代码是它的主要设计文档 , 用来描述源代码的图示只是设计的附属物而不是设计本身 . 你不应该认为设计就是一组和代码分离的 UML 图 .
  • 在这里插入图片描述

三、 编程价值观

1)评价标准的背后动机-----关注开发总成本

==Costtotal=Costdevelop+Costmaintain==

----Edward Yourdon&Larry L. Constantine

2)软件系统维护工作量所占的比重超出想象!!!!!!!!

==Costmaintain=Costunderstand+Costchange+Costtest+Costdeploy== ==Costmaintain>>Costdevelop==

3)代码要人能够读懂------Martion Fowler

任何一个傻瓜都能写出机器能懂的代码,好的程序员应该写出人 能懂的代码。

----Martin Fowler 《重构》

4)程序员要有这种意识------"写烂代码要遭报应!!!!!!!!!"

编程的时候,总是想着那个维护你代码的人会是一个知道你住在 哪儿的有暴力倾向的精神病患者。

----Martin Golding

5)软件代码3项职责------Robert C Martin <敏捷软件开发>

  • 第1职责:运行起来所完成的功能,这是模块存在的原因。
  • 第2职责:要和阅读它的人进行沟通,对模块不熟悉的人员应该能够比较容易理解。
  • 第3职责:它要应对变化,因为软件要变化,开发者保证应该尽可能的简单。

6)价值观是编程过程的统一支配性主题.有3个价值观:

  • 沟通:珍视与他人沟通的重要性
  • 简单:把多余的的复杂性去掉
  • 灵活:保持开放,应对变化

——Kent Beck

7)整洁代码------百家争鸣

随着年龄的增长,我逐渐意识到编程不仅仅是让程序运行而已; 编程是创造一个易于理解的、可以维护的、高效的作品。一般来 说,干净整洁的代码,往往运行起来更快。这与流行观点正好相 反。而且即使它们不快,也可以很容易地让它们变快。正如人们 所说的,优化正确的代码比改正优化过的代码容易多了。

---- Google公司首席Java架构师Joshua Bloch

我喜欢优雅和高效的代码。代码逻辑应当直截了当,叫缺陷难 以隐藏;尽量减少依赖关系,使之便于维护;依据某种分层战 略完善错误处理代码;性能调至最优,省得引诱别人做没规矩 的优化,搞出一堆混乱来。整洁的代码只做好一件事。

----Bjarne Stroustrup, inventor of C++ and author of The C++

整洁的代码简单直接。整洁的代码如同优美的散文。整洁的代 码从不隐藏设计者的意图,充满了干净利落的抽象和直截了当 的控制语句

----Grady Booch,Object Oriented Analysis and Design with Applications

p整洁的代码应可由作者之外的开发者阅读和增补。它应当有单 元测试和验收测试。它使用有意义的命名。它只提供一种而非 多种做一件事的途径。它只有尽量少的依赖关系,而且要明确 地定义和提供清晰、尽量少的API。代码应通过其字面表达含 义,因为不同的语言导致并非所有必需信息均可通过代码自身 清晰表达

----“老大”Dave Thomas,OTI公司创始人,Eclipse战略教父

我可以列出我留意到的整洁代码的所有特点,但其中有一条是根 本性的。整洁的代码总是看起来像是某位特别在意它的人写的。 几乎没有改进的余地。代码作者什么都想到了,如果你企图改进 它,总会回到原点,赞叹某人留给你的代码—全心投入的某人留 下的代码。

----Michael Feathers,Working Effectively with Legacy Code

四、什么是好的代码

1)为什么要写好的代码

几种想法:
  • 我马上就离职了,反正,这块代码我不维护了

出来混迟早是要还的,你总有一天会维护到同样的代码

  • 本来这个就不应该是我做的,我已经很疲惫了

软件开发界的另外一个小秘密是:编写优秀代码和糟糕代码所花费的时间是一样多。一位训练有素的工程师,他/她会从第一行代码开始就考虑可维护性和代码 的演化。没有任何理由编写“丑陋”的代码、长达数页的函数,或是稀奇古怪的变量名。

  • 我就这水平,还不知道如何写出好的代码

看书、学习、多实战

2)好代码的重要性

  • 降低维护成本
  • 有助于程序员自身成长
  • 有效促进团队合作,加深小伙伴友谊

3)到底什么是好的代码?

  不坏的代码就是好代码-----这不是废话

五、代码的坏味道

第一级
  • Duplicated Code(重复代码)
  • Long Method(过长函数)
  • Large Class(过大类)
  • Long Parameter List(过长参数)
  • Comments(过多的注释)
  • Temporary Field(令人迷惑的暂时值域)
  • Primitive Obsession(基本型别偏执狂)
  • Switch Statements(Switch惊悚现身)
  • Divergent Change(发散式变化)
  • Shotgun Surgery(散弹式修改
第二级
  • Data Clumps(数据泥团)
  • Data Class(幼稚的数据类)
  • Feature Envy(依恋情结)
  • Refused Bequest(被拒绝的遗赠)
  • Message Chains(过度耦合的消息链)
  • Middle Man(中间转手人)
  • Inappropriate Intimacy(狎昵关系)
  • Lazy Class(冗余类)
第三级
  • Parallel Inheritance Hierarchies(平行继承)
  • Speculative Generality(理论上的一般性)
  • Alternative Classes with Different Interfaces(异曲同工类)
  • Incomplete Library Class(不完美的程序库类)

六、如何重构

代码的坏味道 一般重构方法 使用模式重构
重复代码 提炼方法 构造Template Method
以Composite取代一/多之分
引入Null Object
用Adapter统一接口
用Fatory Method引入多态创建
提取类
方法上移
替换算法
链构造方法
过长方法 提取方法 转移聚集操作到Vistor
以Strategy取代条件逻辑
以Command取代条件调度程序
转移聚集操作到Collecting Parameter
组合方法
以查询取代临时变量
引入参数对象
保持对象完整
过长参数列 以方法取代参数
引入参数对象
保持对象完整
条件逻辑过度复杂 分解条件式 以Strategy取代条件逻辑
转移装饰功能到Decorator
以State取代状态改变条件语句
引入Null Object
合并条件式
合并重复的条件片段
移除控制标记
以卫语句取代嵌套条件式
以多态取代条件式
引入断言
分支语句 提取方法 以State/Strategy取代类型代码
引入Null Object
以Command替换条件调度程序
转移聚集操作到Visitor
转移方法
以子类取代类型代码
以多态取代条件式
已明确方法取代参数
基本类型迷恋
程序代码过于依赖基本类型(int,string,double,array等低层次语言要素)
以对象取代数据值 以State取代状态改变条件语句
以Strategy取代条件逻辑
以Composite取代隐含树
以Interpreter取代隐式语言
转移装饰功能到Decorator
用Builder封装Composite
以类型取代类型代码
以子类取代类型代码
提取类
引入参数对象
以对象取代数组
数据泥团
在类的字段和参数列中,总是一起出现的数据
提取类
引入参数对象
保持对象完整
令人迷惑的临时字段 提取类 引入Null Object
组合爆炸
许多段代码使用不同种类或数量的数据
或对象做同样的事情(例如使用特定条件和数据库查询)
以Interpreter取代隐式语言
过大类 提取类 以Command取代条件调度程序
以State取代状态改变条件语句
以Interpreter取代隐式语言
提取子类
提取接口
复制被监视数据
冗赘类
不再做很多工作或没有用的类
折叠继承关系
内联Singleton
不恰当的暴露
在客户代码中不应看到类的字段和方法,却是公开可见的
封装字段 用Factory封装类
封装群集
移除设置方法
隐藏方法
发散式变化
类经常因为不同的原因在不同方向上发生变化,显然是违反了单一职责原则
提取类
霰弹式修改
如果遇到变化,必须在不同的类中作出相应的修改
转移方法 将创建知识搬移到Factory
转移字段
内联类
依恋情结
方法对于某个类的兴趣高过对自己所处的宿主类
转移方法 引入Strategy
引入Visitor
提取方法
平行继承体系
当为一个类增加一个子类时,也必须在另一个类中增加一个相应的子类
转移方法
转移字段
夸夸其谈未来性 折叠继承关系
内联类
移除参数
移除方法
过度耦合的消息连
不断的向一个对象索求另一个对象
隐藏委托 使用抽象引入Chain Of Responsibility
提取方法
转移方法
中间转手人
类之间彼此依赖于其private成员
移除中间转手人
内联方法
以继承取代委托
狎昵关系
类之间彼此依赖于其private成员
转移方法
将双向关联改为单向
提取类
隐藏委托
以继承取代委托
异曲同工的类 重命名方法 用Adapter统一接口
转移方法
提取超类
不完善的程序库类 引入外加方法 用Adapter统一接口
用Facade封装类
引入本地扩展
纯稚的数据类
只拥有字段的数据类
封装字段
封装集合
移除设置方法
转移方法
隐藏方法
被拒绝的遗赠
继承父类时,子类想要选择继承的成员
以委托取代继承
过多的注释
为糟糕的代码写大量的注释
使用一起重构方法,使方法本身达到自说明的效果,让注释显得多余
怪异解决方案
在同一系统中使用不同的方式解决同一问题
替换算法 用Adapter统一接口

介绍几本好书:

  • 《代码整洁之道》----Robert C. Martin
  • 《敏捷软件开发:原则、模式与实践》----Robert C. Martin
  • 《代码大全》 ----Steve McConnell
  • 《重构——改善既有代码的设计》 ----Martin Fowler