什么是高质量代码,如何定义?
没有最好的代码,只有被吐槽的代码,吐槽的的程度与频次,决定了代码质量的高低。
不被吐槽的代码不一定是高质量代码,但是被吐槽的代码一定不是高质量代码。
如何编写少被吐槽的代码
视觉和逻辑上的整洁
要有一定的代码洁癖: 变量命名规则、常量定义、格式规约等层面,可参考阿里巴巴java开发规范手册。
代码尽可能简单,遵循KISS原则(Keep It Simple and Stupid)
- 程序员写的代码其实并不是给机器看的,而是给人看的。是不是高质量代码,在机器看来,撇开效率而言并没有太大的区别。
- 写代码不是炫技,不需要为了使用某种新潮的技术或者语法糖写出一段难读的代码,毕竟你写的代码会被团队其他同学阅读或者修改,由于团队内的每个同学针对问题的思考角度、思路可能都不相同,所以有时候最简单的代码反而是最好的代码,不要觉得简单的东西就没有技术含量。反而越是能用简单的方法解决复杂的问题,越能体现一个人的能力。
如何写出满足
KISS
原则的代码? - 实现代码避免使用其他同学可能不懂或者不熟悉的技术
- 避免过度设计与优化
- 避免重复造轮子,善于使用现有组件库或者工具库
避免写重复代码,遵循DRY原则(Don’t Repeat Yourself)
换句话说也就是提高代码复用性,那如何提高呢?
- 减少代码耦合
- 满足单一职责原则
- 通用代码抽离、抽象与封装
- 模块化、组件化
- 设计模式搞起来...等等
添加高质量注释
通常我们要求方法的命名能够见名知意,如果通过代码的命名能直接反映出来其作用的话,就不需要用注释去表达,因为看代码一下就能明白,注释反而多此一举。
我们应该多写当前代码是为了解决什么问题或者为了修复什么不易考虑到的case相关的注释,这样能为后来的维护者提供了一定的上下文信息,不至于让其看不懂,不敢动。
慎用继承,多用组合
继承是面向对象的三大特性之一,用来表示类之间的 is-a 关系,可以解决代码复用的问题。虽然继承有诸多作用,但继承层次过深、过复杂,也会影响到代码的可维护性。
类的继承层次会越来越深、继承关系会越来越复杂。而这种层次很深、很复杂的继承关系,一方面,会导致代码的可读性变差。因为我们要搞清楚某个类具有哪些方法、属性,必须阅读父类的代码、父类的父类的代码……一直追溯到最顶层父类的代码。另一方面,这也破坏了类的封装特性,将父类的实现细节暴露给了子类。子类的实现依赖父类的实现,两者高度耦合,一旦父类代码修改,就会影响所有子类的逻辑。
如何判断该用组合还是继承?
尽管鼓励多用组合少用继承,但组合也并不是完美的,继承也并非一无是处。继承改写成组合意味着要做更细粒度的类的拆分。这也就意味着,我们要定义更多的类和接口。类和接口的增多也就或多或少地增加代码的复杂程度和维护成本。所以,在实际的项目开发中,我们还是要根据具体的情况,来具体选择该用继承还是组合。
如果类之间的继承结构稳定(不会轻易改变),继承层次比较浅(比如,最多有两层继承关系),继承关系不复杂,我们就可以大胆地使用继承。反之,系统越不稳定,继承层次很深,继承关系复杂,我们就尽量使用组合来替代继承。
设计适合当前业务的架构,避免生搬硬套
比如说在代码架构设计层面,不管是MVC、MVP还是MVVM都是基于业务逐渐演变的的一种软件设计模式,所谓更明显的分层体现,很难合适的套用在所有的代码中,举个例子,在客户端和后端层面就有所不同,后端代码趋向于逻辑代码,大部分的维护都是基于逻辑上的改动,界面层面的很少,而移动端则不同,UI与逻辑相互作用,大部分的需求迭代都是基于UI层面的迭代修改。所以在后端架构中通过MVC等分层架构进行解耦,有利于整体逻辑的维护与扩展,但在客户端层面来说,就没办法生硬的套用,而是要针对特定的使用场景灵活变换姿势。
总的来说移动端的业务场景,大致可以分为两类,业务逻辑代码(View层)和功能逻辑代码,其中功能逻辑层面可以选择合适的架构思想及设计模式,使该功能模块的逻辑更加健壮,易于维护与扩展,而针对业务逻辑层面(View层)来说,通常不应包含太多复杂的逻辑,如果有复杂逻辑存在,则应适当地拆分到功能逻辑层面处理,根据场景选择合适的设计模式,不需要硬套用某种分层架构。
总结
- 没有最好的代码,只有被吐槽的代码,我们的目标是写出少被吐槽的代码,用简单的方法解决复杂的问题也是一种能力的体现。
- 任何架构模式都没有最好、最优,只有最适合当前业务的才是好架构。
- 避免过度设计。