文章

开源框架中常见的命名习惯

开源框架中常见的命名习惯

开源框架中常见的命名习惯

为了让大家更好的理解命名的套路,我借鉴了最流行的 Java 接开源软件( spring 系列,netty, libgdx , guava , logback 等等),总结了10类常见的类命名。大多数是以后缀形式存在的,也有不少可以组合使用,用来表达多重的意义。

这些单词很简单,但可以让你的类命名看起来更加清爽和专业。接下来,我将带大家游览一遍。为了方便理解,每种类型,我都配备了相应的 示例。

管理类命名

写代码,少不了对统一资源的管理,清晰的启动过程可以有效的组织代码。为了让程序运行起来,少不了各种资源的注册、调度,少不了公共集合资源的管理。

Bootstrap,Starter

一般作为程序启动器使用,或者作为启动器的基类。通俗来说,可以认为是 main 函数的入口。

```plain text AbstractBootstrap ServerBootstrap MacosXApplicationStarte rDNSTaskStarter

1
2
3
4
5
6
7
8
9
### Processor

某一类功能的处理器,用来表示某个处理过程,是一系列代码片段的集合。如果你不知道一些顺序类的代码怎么命名,就可以使用它,显得高大上一些

```plain text
CompoundProcessor
BinaryComparisonProcessor
DefaultDefaultValueProcessor

Manager

对生命状态的对象进行管理,通常作为某一类资源的管理入口

```plain text AccountManager DevicePolicyManager TransactionManager

1
2
3
4
5
6
7
8
9
### Holder

表示持有某个或某类对象的引用,并可以对其进行统一管理。多见于不好回收的内存统一处理,或者一些全局集合容器的缓存。

```plain text
QueryHolder
InstructionHolder
ViewHolder

Factory

工厂模式的命名,尤其是 Spring 中,数不胜数

```plain text SessionFactory ScriptEngineFactory LiveCaptureFactory

1
2
3
4
5
6
7
8
9
### Provider

Provider = Strategy + Factory Method 。它更高级一些,把策略模式和方法工厂揉在了一块,让人用起来很顺手。Provider 一般是接口或者抽象类,以便能够完成子实现。

```plain text
AccountFeatureProvider
ApplicationFeatureProviderImpl
CollatorProvider

Registrar

注册并管理一系列资源

```plain text ImportServiceRegistrar IKryoRegistrar PipelineOptionsRegistrar

1
2
3
4
5
6
7
8
9
### Engine

一般是核心模块,用来处理一类功能。引擎是一个非常高级的名词,一般的类是没有资格用它的。

```plain text
ScriptEngine
DataQLScriptEngine
C2DEngine

Service

Task

某个任务,通常是 runnable

```plain text WorkflowTask FutureTask ForkJoinTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 传播类命名

为了完成一些统计类或者全局类的功能,有些参数需要一传到底。传播类的对象就可以通过统一封装的方式进行传递,并在合适的地方进行拷贝或者更新。

### Context

如果你的程序执行,有一些变量,需要从函数执行的入口开始,一直传到大量子函数执行完毕之后。这些变量或者集合,如果以参数的形式传递,将会让代码变得冗长无比。这个时候,你就可以把变量统一塞到 Context 里面,以单个对象的形式进行传递。

在 Java 中,由于 ThreadLocal 的存在, Context 甚至可以不用在参数之间进行传递。

```plain text
AppContext
ServletContext
ApplicationContext

Propagator

传播,繁殖。用来将 context 中传递的值进行复制,添加,清除,重置,检索,恢复等动作。通常,他会提供一个叫做 propagate 的方法,实现真正的变量管理。

```plain text TextMapPropagator FilePropagator TransactionPropagator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## 回调类命名

使用多核可以增加程序运行的效率,不可避免的引入异步化。我们需要有一定的手段,获取异步任务执行的结果,对任务执行过程中的关键点进行检查。回调类API可以通过监听、通知等形式,获取这些事件

### Handler,Callback,Trigger,Listener

- Callback通常是一个接口,用于响应某类消息,进行后续处理:
- Handler通常表示持有真正消息处理逻辑的对象,它是有状态的
- Trigger触发器代表某类事件的处理,属于Handler,通常不会出现在类的命名中
- Listener的应用更加局限,通常在观察者模式中用来表示特定的含义。

```plain text
ChannelHandler
SuccessCallback
CronTrigger
EventListener

Aware

Aware就是感知的意思,一般以该单词结尾的类,都实现了 Aware 接口,拿 Spring 来说, Aware 的目的是为了让 bean 获取 Spring 容器的服务。具体回调方法由子类实现,比如 ApplicationContextAware。它有回调的意思。

```plain text ApplicationContextAware ApplicationStartupAware ApplicationEventPublisherAware

1
2
3
4
5
6
7
8
9
10
11
12
13
## 监控类命名

现在的程序都比较复杂,运行状态监控已经成为居家必备之良品。监控数据的收集往往需要侵入到程序的边边角角,如何有效的与正常业务进行区分,是非常有必要的。

### Metric

表示监控数据。不要用 Monitor 了,比较丑

```plain text
TimelineMetric
HistogramMetric
Metric

Estimator

估计,统计。用于计算某一类统计数值的计算器。

```plain text ConditionalDensityEstimator FixedFrameRateEstimator NestableLoadProfileEstimator

1
2
3
4
5
6
7
8
9
### Accumulator

累加器的意思,用来缓存累加的中间计算结果,并提供读取通道。

```plain text
AbstractAccumulator
StatsAccumulator
TopFrequencyAccumulator

Tracker

一般用来记录日志或者监控值,通常用于 apm 中。

```plain text VelocityTracker RocketTracker MediaTracker

1
2
3
4
5
6
7
8
9
10
11
12
13
## 内存管理类命名

如果你的应用用到了自定义的内存管理,那么下面这些名词是绕不开的。比如 Netty,就实现了自己的内存管理机制。

### Allocator

与存储相关,通常表示内存分配器或者管理器。如果你的程序需要申请有规律的大块内存, allocator 是你的不二选择。

```plain text
AbstractByteBufAllocator
ArrayAllocator
RecyclingIntBlockAllocator

Chunk

表示一块内存。如果你想要对一类存储资源进行抽象,并统一管理。可以采用它。

```plain text EncryptedChunk ChunkFactory MultiChunk

1
2
3
4
5
6
7
8
9
10
11
### Arena

英文是舞台、竞技场的意思。由于 Linux 把他用在内存管理器上并发扬光大,它普遍用于各种存储资源的申请、释放与管理。为不同存储规格的 chunk 提供舞台。

关键是这个词很美,作为后缀让类名显得很漂亮。

```plain text
BookingArena
StandaloneArena
PoolArena

Pool

内存池,线程池,连接池。

```plain text ConnectionPool ObjectPool MemoryPool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## 过滤检测类命名

程序收到的事件信息是非常多的,有些是合法的,有些需要过滤扔掉。根据不同的使用范围和功能性差别,过滤操作也有很多种形式。你会在框架类代码中发现大量这样的名词。

### Pipeline,Chain

一般用在责任链模式中。Netty,Spring MVC,Tomcat 等都有大量应用。通过将某个处理过程加入到责任链的某个位置中,就可以接收前面处理过程的结果,强制添加或者改变某些功能。就像 Linux 的管道操作一样,最终构造出想要的结果。

```plain text
Pipeline
ChildPipeline
DefaultResourceTransformerChain
FilterChain

Filter

过滤器,用来筛选某些满足条件的数据集,或者在满足某些条件的时候执行一部分逻辑。如果和责任链连接起来,则通常能够实现多级过滤。

```plain text FilenameFilter AfterFirstEventTimeFilter ScanFilter

1
2
3
4
5
6
7
### Interceptor

拦截器,其实和 Filter 差不多。不过在 Tomcat 中,Interceptor 可以拿到 Controller 对象,但 filter 不行。拦截器是被包裹在过滤器中。

```plain text
HttpRequestInterceptor

Evaluator

英文里其实是评估器的意思。可用于判断某些条件是否成立,一般内部方法 evaluate 会返回 Boolean 类型。比如你传递进去一个非常复杂的对象,或者字符串,进行正确与否的判断。

```plain text ScriptEvaluator SubtractionExpressionEvaluator StreamEvaluator

1
2
3
4
5
6
7
8
9
### Detector

探测器。用来管理一些探测性事件,并在发生的时候能够进行。比如:Android 的手势检测、温度检测等。

```plain text
FileHandlerReloadingDetector
TransformGestureDetector
ScaleGestureDetector

结构类命名

除了基本的数据结构,如数组、链表、队列、栈等,其他更高一层的常见的抽象类,能够大量减少大家的交流,并能封装常见的变化。

Cache

缓存,大块的缓存。常见的缓存算法有LRU、LFU、FIFO等。

```plain text LoadingCache EhCacheCache

1
2
3
4
5
6
7
8
9
### Buffer

缓冲,不同于缓存,它一般在数据写入阶段。

```plain text
ByteBuffer
RingBuffer
DirectByteBuffer

Composite

将相似的组件进行组合,并以相同的接口或功能暴露,使用者不知道这到底是一个组合体还是其他个体。

```plain text CompositeData CompositeMap ScrolledComposite

1
2
3
4
5
6
7
8
9
### Wrapper

用来包装某个对象,做一些额外的处理,以便增加或者去除某些功能。

```plain text
IsoBufferWrapper
ResponseWrapper
MavenWrapperDownloader

Option,Param,Attribute

用来表示配置信息。说实话,它和Properties 的区别不大,但由于 Option 通常是一个类,所以功能可以扩展的更强大一些。它通常比Config的级别更小,关注的也是单个属性的值。Param 一般作为参数存在,对象生成的速度要快一些。

```plain text SpecificationOption SelectOption AlarmParam ModelParam

1
2
3
4
5
6
7
8
### Tuple

元组的概念。由于 Java 中缺乏元组结构,我们通常会自定义这样的类。

```plain text
tuple2
tuple3

Aggregator

聚合器,可以做一些聚合计算。比如分库分表中的 sum , max , min 等聚合函数的汇集。

```plain text BigDecimalMaxAggregator PipelineAggregator TotalAggregator

1
2
3
4
5
6
7
8
### Iterator

迭代器,可以实现 Java 的迭代器接口,也可以有自己的迭代方法。在数据集很大的时候,需要进行深度遍历,迭代器可以说是必备的。使用迭代器还可以在迭代过程中安全的删掉某些元素。

```plain text
BreakIterator
StringCharacterIterator

Batch

某些可以批量执行的请求或者对象。

```plain text SavedObjectBatch BatchRequest

1
2
3
4
5
6
7
8
9
### limiter

限流器,使用漏桶算法或者令牌桶来完成平滑的限流。

```plain text
DefaultTimepointLimiter
RateLimiter
TimeBasedLimiter

常见设计模式命名

设计模式是名词的重灾区

Strategy

将抽象部分与它的实现部分分离,使它们都可以独立地变化。策略模式。相同的接口,不同的实现,同一方法结果不同,实现策略不同。比如一个配置文件,是放在xml里还是放在 json 文件里,都可以使用不同的 provider 去命名。

```plain text RemoteAddressStrategy StrategyRegistration AppStrategy

1
2
3
4
5
6
7
8
9
10
11
### Adapter

将一个类的接口转换为客户希望的另一个接口, Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类一起工作

不过,相对于传统的适配器进行 api 转接,如果你的某个 handler 里面的方法特别多,可以使用 Adapter 实现一些默认的方法进行 0 适配。那么其他类使用的时候,只需要集成 Adapter ,然后重写他想要重写的方法就可以了,这也是 Adapter 常见的用式。

```plain text
ExtendedPropertiesAdapter
ArrayObjectAdapter
CardGridCursorAdapter

Action,Command

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销操作。

用来表示一系列动作指令,用来实现命令模式,封装一系列动作或功能。Action 一般用在 UI 操作上,后端框架可以无差别的使用。

在DDD的概念中,CQRS的Command的C,既为Command。

```plain text DeleteAction BoardCommand

1
2
3
4
5
6
7
8
### Event

表示一系列事件。一般的,在语义上,Action,Command等,来自于主动触发;Event来自于被动触发。

```plain text
ObservesProtectedEvent
KeyEvent

Delegate

代理或者委托模式。委托模式是将一件属于委托者做的事情,交给另外一个被委托者来处理。

```plain text LayoutlibDelegate FragmentDelegate

1
2
3
4
5
6
7
8
### Builder

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。构建者模式的标准命名。比如StringBuilder。当然StringBuffer是个另类。这也说明了,规则是人定的,人也可以破坏。

```plain text
JsonBuilder
RequestBuilder

Template

模板方法类的命名。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

```plain text JDBCTemplate

1
2
3
4
5
6
7
8
### Proxy

代理模式。为其他对象提供一种代理以控制对这个对象的访问。

```plain text
ProxyFactory
SlowQueryProxy

解析类命名

写代码要涉及到大量的字符串解析、日期解析、对象转换等。根据语义和使用场合的区别,它们也分为多种。

Convert,Resolver

转换和解析。一般用于不同对象之间的格式转换,把一类对象转换成另一类。注意它们语义上的区别,一般特别复杂的转换或者有加载过程的需求,可以使用Resolver。

```plain text DataSetToListConverter LayoutCommandLineConverter InitRefResolver MustacheViewResolver

1
2
3
4
5
6
7
### Parse

用来表示非常复杂的解析器,比如解析DSL。

```plain text
SQLParserJSONParser

Customizer

用来表示对某个对象进行特别的配置。由于这些配置过程特别的复杂,值得单独提取出来进行自定义设置。

```plain text ContextCustomizer DeviceFieldCustomizer

1
2
3
4
5
6
7
8
### Formatter

格式化类。主要用于字符串、数字或者日期的格式化处理工作。

```plain text
DateFormatter
StringFormatter

网络类命名

网络编程的同学,永远绕不过去的几个名词。

Packet

通常用于网络编程中的数据包。

```plain text DhcpPacket PacketBuffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
### Protocol

同样用户网络编程中,用来表示某个协议。

RedisProtocolHttpProtocol

### der、Decoder、Codec

编码解码器

```plain text
RedisEncoder
RedisDecoder
RedisCodec

Request,Response

一般用于网络请求的进和出。如果你用在非网络请求的方法上,会显得很怪异。

CRUD类命名

这个就有意思多了,统一的Controller,Service,Repository,没什么好说的。但你一旦用了DDD,那就得按照DDD那一套的命名来。由于DDD不属于通用编程范畴,它的名词就不多做介绍了。

其他

Util,Helper

都表示工具类,Util一般是无状态的,Helper以便需要创建实例才能使用。但是一般没有使用Tool作为后缀的。

```plain text HttpUtil TestKeyFieldHelper CreationHelper

1
2
3
4
5
6
7
8
9
### Mode,Type

看到mode这个后缀,就能猜到这个类大概率是枚举。它通常把常见的可能性都列到枚举类里面,其他地方就可以引用这个Mode。

```plain text
OperationMode
BridgeMode
ActionType

Invoker,Invocation

invoker是一类接口,通常会以反射或者触发的方式,执行一些具体的业务逻辑。通过抽象出invoke方法,可以在invoke执行之前对入参进行记录或者处理;在invoke执行之后对结果和异常进行处理,是AOP中常见的操作方式。

```plain text MethodInvoker Invoker ConstructorInvocation

1
2
3
4
5
6
7
8
### Initializer

如果你的应用程序,需要经过大量的初始化操作才能启动,那就需要把它独立出来,专门处理初始化动作。

```plain text
MultiBackgroundInitialize
ApplicationContextInitializer

Feture,Promise

它们都是用在多线程之间的,进行数据传递。

Feture相当于一个占位符,代表一个操作将来的结果。一般通过get可以直接阻塞得到结果,或者让它异步执行然后通过callback回调结果。

但如果回调中嵌入了回调呢?如果层次很深,就是回调地狱。Java中的CompletableFuture其实就是Promise,用来解决回调地狱问题。Promise是为了让代码变得优美而存在的。

Selector

根据一系列条件,获得相应的同类资源。它比较像Factory,但只处理单项资源。

```plain text X509CertSelector NodeSelector

1
2
3
4
5
6
7
8
### Reporter

用来汇报某些执行结果。

```plain text
ExtentHtmlReporter
MetricReporter

Constants

一般用于常量列表。

Accessor

封装了一系列get和set方法的类。像lombok就有Accessors注解,生成这些方法。但Accessor类一般是要通过计算来完成get和set,而不是直接操作变量。这适合比较复杂的对象存取服务。

```plain text ComponentAccessor StompHeaderAccessor

1
2
3
4
5
6
7
8
### Generator

生成器,一般用于生成代码,生成id等。

```plain text
CodeGenerator
CipherKeyGenerator

End

写代码,看源码,怎么少得了意会和神通?代码要带感,命名也风骚。命名起的好,代码会看起来很爽,大家也都喜欢。

说不清楚的事情,给一段代码,咱就能懂!就是这么神奇!

其实,写专业牛b的代码,并不需要了解太多的英文单词,大多数时候用不着英文4级这么了不起的水平。只需要有限的单词,就能玩出代码界好莱坞的感觉。

看完本文之后,翻一翻开源软件的代码们,看看是不是这个理?

上面这些命名,高频率存在于各种框架中。你要是搞懂了这些名词,阅读大部分源代码可以说是一点障碍都没有了。在同一个场景下,优先使用这些名词,已经是大家心照不宣的规范。

有很多名词来自于设计模式,但又在特定场合使用了比较特殊的单词,比如Provider,大家仔细感受下其中的区别就可以了。

本文由作者按照 CC BY 4.0 进行授权