代码精进之路(内容提取自极客时间课程)

为一名软件工程师,我们该怎么快速成长,并且保持长久的竞争力
解决这个问题的终极方法,只有一个,那就是持续地交付优秀的结果。宜早不宜迟

写出优秀的代码是我们每一个程序员的毕生追求,我们没有理由不去思考如何写出优秀、让人惊叹的代码
坚持使用最直观的编码方式,而不是追求代码简短,真的可以避免很多不必要的错误
好的代码应该:
1. 容易理解;
2. 没有明显的安全问题;
3. 能够满足最关键的需求;
4. 有充分的注释;
5. 使用规范的命名;
6. 经过充分的测试。
优秀的代码是“经济”的代码
指的是使用较少的人力、物力、财力、时间、空间,来获取较大的成果或收益 
越成熟的软件开发机制越容易写出优秀的代码。但是,最适合当前现实环境的代码,才是最优秀的代码。

没有人是完美的,人人都会犯错误。这应该是一个共识
对于一个团队,我们首先要思考如何提供一种机制,以减少此类错误的发生
把错误关在笼子里
1,提高程序员的修养,是一个永不过时的课题。从别人的失败和自己的失败中学习、积累、提高,是一个程序员成长的必修课
优秀的代码源于我们对细节的热情和执着,如果你能够找到哪怕仅仅是一个小问题的一个小小的改进办法,都有可能会给你的代码质量带来巨大的提升和改变
2,编译器在代码质量方面,作为机器,恪尽职守,它可以帮助我们清除很多错误,对于编译器的警告,我们一定要非常警觉。能消除掉所有的警告,你就应该消除掉所有的警告。就算实在没有办法消除掉编译警告,那你也一定要搞清楚警告产生的原因,并确认编译警告不会产生任何后续问题
3,回归测试
4,代码评审是一个有效的在软件研发过程中抵御人类缺陷的制度,通过更多的眼睛检查软件代码,被忽视的错误更容易被逮住,更好的设计和实现更容易浮现出来
5,代码分析,借助第三方代码分析软件,检查代码缺陷

优秀程序员六个特质
1,掌握一门编程语言
2,解决现实的问题
程序员的存在不是为了写代码,而是为了解决现实问题,实现现实价值
花样的工具是外家功夫,思维能力和行为能力可以算是内功
3,发现关键的问题
能够发现关键的问题,意味着我们可以从一个被动的做事情的程序员,升级为一个主动找事情的程序员
4,沉静的前行者
首先,优秀的程序员,一定是懂得妥协,懂得选择,一步一步把事情沉静地朝前推动的人
5,可以依赖的伙伴
其次,优秀的程序员是他人可以依赖的伙伴
6,时间管理者,要做只有你才能做的事情,要坚持做需要做的事情
优秀的程序员可以熟练地使用必要的工具,
发现和解决复杂的现实问题;优秀的程序员可以在一个团队里,高效沉静地把项目和团队一步一步地朝前推进。

编码规范
编码规范指的是针对特定编程语言约定的一系列规则,通常包括文件组织、缩进、注释、声明、语句、空格、命名约定、编程实践、编程原则和最佳实践等
一旦学会了编码规范,并且严格地遵守它们,可以让我们的工作更简单,更轻松,少犯错误。
规范的代码,可以降低代码出错的几率,在编码的时候,我们应该尽量使代码风格直观、逻辑简单、表述直接
一件东西,无论其实用性多强,终究比不上让人心情愉悦更为实用
严格地遵守编码规范,可以使我们的工作更简单,更轻松,更愉快。 记住,优秀的代码不
光是给自己看的,也是给别人看的,而且首先是给别人看的

给你的代码起好名字
名字就是沟通的方式,错误的命名很难让我们清楚地理解代码真实的意图。所以,混淆的命名很难让我们阅读和理解代码
1. 为标识符提供附加的信息,赋予标识符现实意义。帮助我们理顺编码的逻辑,减少阅读
和理解代码的工作量
2. 使代码审核变得更有效率,专注于更重要的问题,而不是争论语法和命名规范这类小细
节,提高开发效率;
3. 提高代码的清晰度、可读性以及美观程度;
4. 避免不同产品之间的命名冲突
有哪些常见的命名方法?
1. 驼峰命名法(CamelCase)
有两种格式:大驼峰命名法(UpperCamelCase)和小驼峰命名法(lowerCamelCase)
2. 蛇形命名法(snake_case)
在蛇形命名法中,单词之间通过下划线“_”连接,比如“out_of_range”。
3. 串式命名法(kebab-case)
在蛇形命名法中,单词之间通过连字符“-”连接,比如“background-color”。
4. 匈牙利命名法
标识符由一个或者多个小写字母开始,这些字母用来标识标识符的类型或者用途。标识符的剩余部分,可以采取其他形式的命名法,比如大驼峰命名法
怎么取好名字?
1. 要有准确的意义
2. 严格遵守命名规范
3. 可读性优先
简言之,取名字要做到“信、达、雅”(准确、直观、优美)。“信”和“达”是基本要求,有才气的你可以有“雅”的追求

给代码分块
程序代码分块时,我们需要注意以下三个点
1. 保持代码块的单一性,一个代码块只能有一个目标
2. 注意代码块的完整性
3. 代码块数量要适当
使用空白空间
给代码分块的办法之一,就是有效地使用空白空间。空白的空间虽然没有内容,但会给我们重要的信息提示
代码的分块,通过空格、缩进和空行来整理,或者分割。
其中空格可以进行逻辑区隔,用于同一行代码内部的信息分块。
缩进用于水平分割,用于表示代码块的级别。
空行用于垂直分割,用于分开同级别的不同代码块
同级别代码块靠左对齐
同级别代码块空行分割
下一级代码块向右缩进
同行内代码块空格区隔
一行一个行为

写好注释
顾名思义,注释就是对代码的解释。注释不需要运行,它是用来提高代码的可读性和可维护性的。
不好的注释会使代码变得更糟糕,使人更抓狂
因为注释不需要运行,所以没有常规的办法来测试它
注释难以维护,这是使用注释带来的最大的麻烦。
几种常见注释类型:
第一种类型,是记录源代码版权和授权的 使用一般的星号注释符(/-/)
第二种类型,是用来生成用户文档的 使用 Javadoc 要求的格式,文档注释符(/-*/)
第三种类型,是用来解释源代码的 只使用行注释符(//)
如果一段代码不再需要,我会清理掉代码,而不会保留这个注释掉的代码块。不要在源代码里记录代码历史,那是代码版本管理系统该干的事情
注释的三项原则
1. 准确,错误的注释比没有注释更糟糕。
2. 必要,多余的注释浪费阅读者的时间。
3. 清晰,混乱的注释会把代码搞得更乱。

写好声明
写好声明的“八项纪律”
取一个好名字
一行一个声明
局部变量需要时再声明
类属性要集中声明
声明时就初始化
尾随的花括号
1. 左括号不要单独成行,要紧随在语句尾部,以一个空格隔开;
2. 右括号单独一行
靠紧的小括号
搜索优化的换行

使用好JAVA注解
Java 注解是 Java 1.5 引入的一个工具,类似于给代码贴个标签,通过注解可以为代码添加标签信息。这些标签信息可以添加在字段、方法和类上
写规范的代码时,该怎么合理地使用注解,具体就是 Override、Deprecated、SuppressWarnings 这三个注解
通常如果一个方法是重写方法,一定要使用 Override 注解,清楚地标明这个方法是重写的方法
如果接口的设计存在不合理性,或者新方法取代了旧方法,我们应该尽早地废弃该接口,需要我们使用 Deprecated注解,并且用一切可以使用的办法,广而告之
如果我们在现有的代码中使用了废弃的接口,要尽快转换、使用替换的方法
如果看到了使用 SuppressWarnings 的代码,我们要尽可能地想办法把相关的警告消除掉、把这个注解去掉,越快越好
1. 重写的方法,总是使用;
2. 过时的接口,尽早废弃;
3. 废弃的接口,不要使用

异常处理
正常的状况和异常的状况一定要分开、分清,不能混用
1. 不要使用异常机制处理正常业务逻辑;
2. 异常的使用要符合具体的场景;
3. 具体的异常要在接口规范中声明和标记清楚。

设计一个简单又直观的接口
要从真实的问题开始
相互独立,完全穷尽,从问题开始,是为了让我们能够找到一条主线。然后,围绕这条主线,去寻找解决问题的办法,而不是没有目标地让思维发散。这样,也可以避免需求膨胀和过度设计
一个接口一件事情
减少依赖关系
使用方式要“傻”,方便、皮实的接口,才是好用的接口
1. 从真实问题开始,把大问题逐层分解为“相互独立,完全穷尽”的小问题;
2. 问题的分解过程,对应的就是软件的接口以及接口之间的联系;
3. 一个接口,应该只做一件事情。如果做不到,接口间的依赖关系要描述清楚。

多线程减少阻塞时间的一个办法,就是只同步和共享资源变化相关的逻辑

具有规模扩张能力的软件的一些最佳实践
1. 把无状态数据分离出来,单独提供无状态服务;
2. 把最基本的服务状态封装起来,利用客户端的缓存,实现无状态服务;
3. 小心使用服务状态,编码时要考虑服务状态的规模水平扩张能力。

尽量“不写”代码:
当我们使用类似的代码或者类似的功能超过两次时,就应该考虑这样的代码是不是可以复用了
代码的修改都有哪些需要注意的地方呢?
代码规范方面的修改,可以大胆些。比如命名规范、代码整理,这些都动不了代码的逻辑,是安全的修改
代码逻辑方面的修改,要特别小心,除了有明显的问题,我们都尽量避免修改代码的逻辑
关键的有三点:
1. 要提高代码的复用比例,减少编码的绝对数量;
2. 要复用外部的优质接口,并且推动它们的改进;
3. 烂代码该放手时就放手,以免引起不必要的兼容问题;

安全的代码:
1. 不起眼的小问题,也会有巨大的安全缺陷,造成难以估量的损失;
2. 编写安全的代码,是我们必须要掌握的基础技能;
3. 安全问题,既是技术问题,也是管理问题。
1. 第一时间知道出现了安全漏洞;
2. 快速寻找、部署漏洞修复的临时方案。

整数运算存在的安全漏洞
1. 数值运算,理论结果可能会超出数值类型许可的空间,进而发生实际结果的溢出。
2. 抽象的数据一旦有了现实意义,便有了具体的现实约束,我们一定要考虑这些约束。
3. 很多问题和我们的习惯并不相符,要通过制度设置来减少由于人的固有缺陷带来的经常
性问题。

变量的拷贝,有浅拷贝和深拷贝两种形式;可变量的浅拷贝无法解决竞态危害的威胁

敏感信息的处理
第一件事情,就是定义权限
第二件事情,就是定义权限的主体
第三件事情,就是要定义权限的归属
针对敏感信息的操作,需要特殊的处理和特殊的技术
异常信息可能携带敏感数据,导致敏感数据通过异常信息泄露

继承所带来的安全隐患
1. 一个可扩展的类,子类和父类可能会相互影响,从而导致不可预知的行为,要极其谨慎小心
2. 涉及敏感信息的类,增加可扩展性不一定是个优先选项,要尽量避免父类或者子类的影
响。

边界,信任的分水岭
无法识别来源的数据,不应该是可信任的数据
区分内部数据、外部数据的依据,是数据的最原始来源,而不是数据在代码中的位置
1. 外部输入数据,需要检查数据的合法性;
2. 公开接口的输入和输出数据,还要考虑可变量的传递带来的危害。

关于序列化
大约有一半的 Java 漏洞和序列化技术有直接或者间接的关系
1. 序列化技术不是一个有安全保障的技术,序列化数据的传输和拆解过程都可能被攻击者利用;
2. 要尽量避免敏感信息的序列化。

代码权力控制
最小限度的授予
越开放的权限越需要控制,越封闭的权限越容易维护
1. 在编码的过程中,要考虑代码的权力;
2. 权力的设计和使用,要遵循“优先最小权限”的原则。

预案,纵深防御
1. 尽管我们无法预料未来可能出现的风险,但是软件的设计和实现依然要考虑抗风险的能力。
2. 对于生死攸关的风险点,我们既要有长期的双引擎设计的意识,也要有权宜的应急预案;
3. 敏感数据归零是纵深防御体系中,非常具有深度的一个防线,但并不是唯一的防线
任何一道防线都不会自动发挥作用,除非我们设置了让防线良性运转的机制
每一道防线都考虑决策、执行、监督这三项权力的分配,以及计划、执行、检查、纠正这四项操作的实际执行

Run slowly, and you will get there faster
要学习一点难的东西,这样才能走到更远的地方

转载于:https://my.oschina.net/u/3519302/blog/3093522

你可能感兴趣的:(代码精进之路(内容提取自极客时间课程))