代码的艺术
课程导入
希望能够让大家对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
- 5
好的代码从哪里来
好的代码是多个环节工作的结果
- 编码前 需求分析,系统设计
- 编码中 编写代码,单元测试
- 编码后 集成测试,上线,持续运营/迭代改进
一个好的系统/产品是以上过程持续循环的结果
编码前
- 需求分析
- 系统设计
在前期更多的投入,收益往往最大
需求分析:定义系统/软件黑盒的行为(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个原理
伟大的代码永远是伟大团队精神的反映