唯's Blog

笔者是一个热爱编程的 Java 程序员。

0%

平常开发中的一些感悟

平常开发中的一些代码设计感悟

代码设计原则 SOLID ,迪米特原则(Law of Demeter)

其中迪米特原则又叫最少知识原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息。还有一个更简单的定义:只与直接朋友通信。

在平时开发中,在类,方法的设计上也尽量保持这个原则。A依赖B对象,A不直接调用B对象中依赖的对象,但完全参考这个原则开发,会导致类内部方法的膨胀。因此在设计需要自己做出权衡,但是其中的平衡点并不好找。后面读了《代码简洁之道》第六章中也有提到迪米特原则,说明了某些场景并不需要遵守这个原则,或者说该原则不适用这种场景,例如:A类依赖B类,B类可能是个数据结构,无对象行为,那么直接调用B内部的数据是可以的。然而在 Java 中因为定义私有变量的原因(内聚、封装),提供了大量的访问方法(get)、该值方法(set)

其中还提到了 隐藏结构,接着上面那个例子,假设 A 依赖 B,B就是具有行为的对象,我们在定义 B 对外的行为,应该更加符合我们系统的业务行为。比如:

1
2
3
4
5
6
// A 拿到的B的某个值(可能在B内部经过大量计算)
int s = A.B.getxxx
s....
// 好的定义,应该定义好对象行为
A.B.craeatexxx

这样满足了 迪米特原则,也不会导致 B 对象暴露内部过多的数据结构。

好的代码

  • 通常说到好的代码,指的都是:好的可读性,好的命名,干脆的抽象,应用设计模型,选择适合的架构,兼顾 可扩展、高可用、可监控等等。
  • 我想说的是,要编写好的代码的前提一定是 开发者要用心,用心 便会思考命名、抽象、充分酌量架构的取舍,用心便会写出好的代码。

系统架构

  • 系统架构,应该区分核心功能,附加功能,前期针对核心功能定义好架构、模型、流程。核心功能的定义决定了系统的稳定性,好的定义对于系统设计也就成功一半了,额外功能、边角功能也就水到渠成了。
  • 避免过度设计,不要先做大的设计。
  • 一个好的系统,一定离不开一套好的模型定义。梳理清楚系统中的核心模型,清楚的定义每个方法的类归属,无论对于代码的可读性、可交流性,还是和产品沟通,都有着莫大的好处。

整洁代码

  • 不要重复代码,只做一件事,表达力,小规模抽象

怎么理解重构?

重构不是把整个系统推到重来,把一个功能代码重新设计也是重构,提取一个方法也是重构。

重构是研发最重要的能力,重构的目的就是让代码符合设计原则,例如:单一原则。所有的方法可以是单一职责,即使是复杂的业务方法也是单一职责,那就是分发与聚合,典型的便是策略模式。

抽象

我的理解:抽象的本质是找事务的共性,找到共性便能抽取、抽象。

之前做的导出报表的功能,Release 有 操作时间、操作人、操作类型,Confirm 也有操作时间、操作人、操作类型(approve同理),这里就能找到Release、Confirm、Approve针对报表导出这个功能的共性,进行抽象

不要盲目追求性能,所谓的流行架构 (KISS[保持简单])

之前有个项目需要导出很全面的报表、还存在汇总计算的需求。因为当时项目牵扯到多方的数据源,如果实时去查询多个数据库聚合会导致接口响应慢,同时存在数据量大的情况甚至会拉垮服务。

我们当时想了一套方案:建立一个新的数据源(MongoDB),通过 ETL 清洗一份新的数据结构存储在数据源。

这里存在数据同步实时的问题,我们使用 Job 去同步新的数据源数据则会存在不准确。正对这个问题我们又想到 Flink 分布式实时处理引擎。

仔细一想,我们需要实时吗?我们沟通了需求,报表的内容一般是只会查看上个月的项目信息。因此实时是个伪需求,不要为了用新技术,而新技术,技术是用来服务业务的。

Unix哲学

  • 程序应该只关注一件事,并把做好。

引申出来的关于程序设计的格言:

  • 过早的优化是一切罪恶的来源
  • 尽量使用简单的算法和数据结构
  • 数据决定一切,选择对的数据结构,算法就无关痛痒了