本文作者:切莫浮沙筑高台
代码的艺术
百度技术学院-代码的艺术_章淼
课程导入
希望能够让大家对Software Engineer(软件工程师) 有更新的认识;
建立正确的意识;
明确修炼的方向。
写代码,学校和公司有很大的不同
学校:作业?实验室的项目?
公司:工业级的产品
所以,需要提供更高质量的代码
消除误解
程序员!=码农
建立正确的意识
知和行,哪个更重要?
明确修炼方向
艺术品是由艺术家创造的
艺术家是有道的
代码的艺术
什么是艺术?
代码到底是不是艺术?
软件工程师只需要会写代码?
写代码都有哪些内涵?
代码可以成为艺术
借助计算机系统
工具
激情
创造性
代码是人类智慧的结晶
代码反映了一个团队/人的精神
Coding is NOT so easy
Coding 的过程
无序->有序
现实世界中的问题->数字世界的模型
一个认识的过程
未知->已知
Coding的过程中需要的能力:
把握问题的能力
建立模型的能力
沟通协助的能力
编码执行的能力
软件工程师!=码农
软件工程师应该具有综合的素质
技术
编码能力,数据结构,算法
系统结构,操作系统,计算机网络,分布式系统
产品
对业务的理解
交互设计
产品数据统计
产品/业务运营
项目管理
研究和创新
R&D:Research and Development
综上所述:一个系统工程师的培养需要至少8-10年的时间,不仅仅只会写代码就可以了
如何理解艺术
作为观众,看就可以了
作为软件工程师,需要去创造
写好代码需要首先建立品味
什么是品味,就是我们首先要知道什么是好的代码,什么是不好的代码,我们才能去不断地调整自己的行为,去学习,去提高我们的编码能力
什么是好代码
什么是好的代码,好的代码有哪些标准?
好的代码是从哪儿来的?
一流代码的特性
高效 fast
鲁棒 solid and robust
简洁 maintainable and simple
简短 small
共享 re-usable
可测试 testable
可移植 portable
可监控 monitorable
可运维 operational
可扩展 scalable & extensible
对以上做下总结就是:
1. 正确和性能
2. 可读和可维护
3. 运维和运营
4. 共享和重用
1
2
3
4
好的代码从哪里来
好的代码是多个环节工作的结果
编码前 需求分析,系统设计
编码中 编写代码,单元测试
编码后 集成测试,上线,持续运营/迭代改进
一个好的系统/产品是以上过程持续循环的结果
编码前
需求分析
系统设计
在前期更多的投入,收益往往最大
需求分析:定义系统/软件黑盒的行为(external,what)
系统设计:设计系统/软件白盒的机制(internal,how&why)
需求分析
需求需要用精确的数字来刻画,量变导致质变
系统设计
什么 是系统架构(System Architecture)?
A system architecture is the conceptual model that defines the structure,behavior,and mor views of a system.几个要素
系统要完成那些功能
系统如何组成
功能在这些组成部分之间如何划分
系统设计的约束
计算
存储
IO/网络
资源的限制
需求是系统设计决策的来源
在设计中,经常需要做Trade-off,需求是make decision的重要依据
系统设计的风格和哲学
在同样的需求下,可能出现不同的设计
每个组件(子系统/模块)的功能都应该足够的专注和单一
功能的单一是复用和扩展的基础
子系统/模块之间的关系应该简单而清晰
软件中最复杂的是耦合(为什么全局变量是要极力避免的?)
好的系统是在合适假设下的精准平衡,一个通用的系统,在某个方面是不如专用系统的
关于接口
系统对外的接口,比系统实现本身还要更重要
这个问题被太多人所忽视
Why?
接口定义了功能:如果功能不正确,系统就没有用
接口决定了外部关系:相对于内部,外部关系确定后非常难以修改
设计和修改接口,需要考虑的非常清楚
合理,好用
修改时需要尽量向前兼容
代码也是一种表达方式
模块
数据类的模块
过程类的模块
模块的重要性
类和函数
关于Object Oriented
模块内部的组成
文件头的例子
代码也是一种表达方式
编程规范,一般包含的内容
代码如何规范表达
一些语言相关的注意事项
理想的场景
看别人的代码感觉和看自己的代码一样
看代码时能够专注于逻辑,而不是格式方面
Don’t make me think
模块
模块是程序的基本组成单位
一个py/go/c文件就是一个模块
模块需要有明确的功能
紧内聚,松耦合
怎样切分模块是一个需要慎重考虑的事情
切分模块的一种角度
数据类、过程类
数据类的模块
主要完成对数据的封装
模块内部变量
类的内部变量
对外提供明确的数据访问接口
数据结构和算法属于模块内部的工作
写程序要以数据为中心考虑
很多程序最后不好维护都是数据封装没做好
过程类的模块
本身不含数据
调用数据类模块或过程类模块
好的模块划分是软件架构稳定的基础减少模块间的耦合->降低软件复杂性清晰的模块有利于代码的复用
类和函数
类和函数是两种不同的模型,有它们各自适用的范围
尽力想用一种方式来描述整个世界,这可能不是一个好主意
Java的设计是一个反例:试图用对象来统一描述
推荐:和类的成员变量无关的函数,作为一个独立的函数
不建议实现为类的成员函数来写
便于未来的复用
面向对象
OO是一个好主意,但是真正理解的人不多
有太多的人,使用OO的语言,写着非OO思想的程序
OO的本质是数据封装
写程序应该从Data开始想问题
但是,周围有太多人是从执行过程开始考虑的
悖论:很好的继承模型需要对需求的准确把握;而在初始设计阶段往往对需求不会有很好的理解
- 问题:系统从开始就设计好的,还是逐步发展和改造好的?
模块内部的组成
文件头
模块的说明:模块功能的简要说明
修改历史:时间,修改人,修改内容
其他必要的、模块级的说明
模块内,内容的顺序尽量保持一致
怎样写好代码
函数
函数描述的三要素
功能描述:这个函数是做什么的
返回值描述:各种可能性
传入参数描述:含义,限制条件
函数的规模要足够短小
python:尽量在一屏内完成
写好程序的一个秘诀:把函数写的短一些
函数的返回值
每个函数应该有足够明确的语义
True false:逻辑判断型的函数,表示真或假
OK,ERROR:操作型的函数,表示成功或失败
Data,None:获取数据型的函数,表示有数据或无数据/获取数据失败
基于函数的语义,函数返回值有三种类型
函数头:对函数的语义做出清晰和准确的说明
函数,单入口单出口是一种推荐的方式
代码块
讨论范围:一个函数内的代码实现
思路:把代码的段落分清楚
形式的背后是逻辑(划分,层次)
Don’t make me think
一眼看过去,如果无法看清楚逻辑,这不是好代码
好的代码不需要你思考太多
一定记住:代码更是写给别人看的
注释不是补出来的,写代码之前首先就是写注释
命名
系统
子系统
模块
函数
常量、变量
望名生义是人的自然反应
概念是建立模型的出发点(概念,逻辑推理=>模型体系)
命名不是一件很容易的事情
要求:准确,易懂
起一个好名字很多时候需要经过推敲
名字的可读性:下划线,驼峰
怎样修炼成为优秀的软件工程师
学习-思考-实践
学习
软件编写有太多的经验可以被借鉴
途径:书,开源代码
有hungry和foolish的感觉才会去学习
最忌井底之蛙、夜郎自大
思考
学而不思则罔
不经过思考,不能形成自己的思想,等于白学和白干
实践
知行合一谓之善
所有重要的进步,都来源于失败和挫折的经历
知识-方法-精神
知识是过时最快的
最根本的能力,分析问题,解决问题的能力才是最重要的
Research:To Identify the fundamental problem,and solve it.
精神:人类总是在神性和兽性间不断斗争,进步往往来自于对理想的追求
自由精神,独立思想;
Don’t Follow;
对完美的不懈追求。
基础乃治学之根本
诫子书,非宁静无以致远
于敏本性沉静好思,喜欢寻根问底。在耀华中学时期他逐渐形成了自己的思维模式和学习方法,善于薄书厚读,再由博而约,由厚而薄,融汇贯通,得其精髓。他非常喜欢魏征谏唐太宗的两句话:求木之长者,必固其根本;欲流之远者,必浚其泉源,深知基础乃治学之根本。
数据结构,算法,操作系统,系统结构,计算机网络
软件工程,编程思想
逻辑思维能力,归纳总结能力,表达能力
研究能力,分析问题,解决问题能力
Symmary
软件工程师!=码农,是一个很有深度的职业代码可以是艺术品,也可以是垃圾
不要忘记我们为什么出发,我们的目的是改变世界,而不是学习编程、或炫耀技术
好的代码来源 不是 写好代码
好代码是一系列工作的结果
代码是写给别人看的
别人看不懂的代码是失败的
写好代码是有道德,系统工程师至少需要8-10年的积累,沉下心来,把自己的基础打好
推荐阅读
代码大全
Rapid development
人月神话
201个原理
伟大的代码永远是伟大团队精神的反映