关于code:编程实战如何管理代码里的常量

49次阅读

共计 3925 个字符,预计需要花费 10 分钟才能阅读完成。

摘要:置信不少同学在见过千奇百怪的常量类之后都有这样的疑难——怎么治理这些常量类?

本文分享自华为云社区《编程实战:如何治理代码里的常量》,原文作者:技术火炬手。

置信不少同学在见过千奇百怪的常量类之后都有这样的疑难——怎么治理这些常量类,但同时又感觉这个如同不是很重要,怎么治理都能用的样子,不就是个常量嘛,明天咱们就把这个问题关上来看看。

先看看前辈们是怎么做的

从事 Web 开发,有个绕不开的常量就是 HTTP 的状态码,不如以此为终点

org.springframework.http.HttpStatus

①应用枚举

public enum HttpStatus {CONTINUE(100, "Continue"),
    SWITCHING_PROTOCOLS(101, "Switching Protocols"),
    PROCESSING(102, "Processing"),
    CHECKPOINT(103, "Checkpoint"),
    OK(200, "OK"),
    CREATED(201, "Created"),
    ACCEPTED(202, "Accepted"),
    NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
    NO_CONTENT(204, "No Content"),
    ...

org.eclipse.jetty.http.HttpStatus

②类中定义常量

public class HttpStatus {
    public static final int CONTINUE_100 = 100;
    public static final int SWITCHING_PROTOCOLS_101 = 101;
    public static final int PROCESSING_102 = 102;
    public static final int OK_200 = 200;
    public static final int CREATED_201 = 201;
    public static final int ACCEPTED_202 = 202;
    public static final int NON_AUTHORITATIVE_INFORMATION_203 = 203;
    public static final int NO_CONTENT_204 = 204;
    ...

org.apache.hc.core5.http.HttpStatus

③final 类中定义常量

public final class HttpStatus {
    public static final int SC_INFORMATIONAL = 100;
    public static final int SC_CONTINUE = 100;
    public static final int SC_SWITCHING_PROTOCOLS = 101;
    public static final int SC_PROCESSING = 102;
    public static final int SC_EARLY_HINTS = 103;
    public static final int SC_SUCCESS = 200;
    public static final int SC_OK = 200;
    public static final int SC_CREATED = 201;
    public static final int SC_ACCEPTED = 202;
    public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    public static final int SC_NO_CONTENT = 204;
    ...

以上都是在罕用开源框架中的定义,在业务中还曾见过一种用法,是

④在接口中定义常量

public interface HttpStatus {
    public static final int CONTINUE_100 = 100;
    public static final int SWITCHING_PROTOCOLS_101 = 101;
    public static final int PROCESSING_102 = 102;
    public static final int OK_200 = 200;
    public static final int CREATED_201 = 201;
    public static final int ACCEPTED_202 = 202;
    public static final int NON_AUTHORITATIVE_INFORMATION_203 = 203;
    public static final int NO_CONTENT_204 = 204;
    ...

这种接口被称为常量接口,不过在《Effective Java》中的“接口只用于定义类型”这条倡议中,特地批评了这种常量接口,认为“常量接口模式是对接口的不良应用”。原文叙述如下:

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class’s exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.
常量接口模式是应用接口的蹩脚形式。类外部会应用一些常量,这是实现细节。然而,实现常量接口会导致这个实现细节透露到类的导出 API 中。对于类的用户来说,类实现一个常量接口没有什么价值。事实上,这甚至会让他们感到困惑。更蹩脚的是,它代表了一种承诺:如果在未来的版本中批改了类,使其不再须要应用常量,那么它依然必须实现接口以确保二进制兼容性。如果一个非 final 类实现了一个常量接口,那么它的所有子类的命名空间都会被接口中的常量所净化。
思考到常量类不应该被继承,应用 final 要比没有适合。

此外思考到常量类应该不须要被实例化,将构造函数设置为 private 也是种额定的爱护。

综上,应用 枚举 final 常量 类就是首选了,那么这两者之间又如何抉择呢?咱们还是能从《Effective Java》失去无效的倡议,第 34 条中就是在倡议咱们用枚举代替 int 常量。

如何治理常量类

尽管枚举是首选,然而常量类不会隐没,常量不只是 int 常量,字符串常量也是日常开发中避不开的,而且有些时候咱们还是会感觉常量更为便捷。那该如何治理这些常量呢?

常量的坏滋味

1. 巨幅常量类

把程序中所有用到的常量,都集中放到一个 Constants 类中。这样做会有一些毛病,

  1. 为了减少常量会导致这个类的批改会很频繁
  2. 依赖这个常量类的代码会很多
  3. 为了应用某一个常量,会导致引入很多无关的常量

2. 反复的常量定义

作为职场新人的时候,我常干的一件事件就是反复定义常量,因为我不晓得他人是否定义过,在哪里定义过,与其要翻遍整个代码库去找这个常量,本人定义一个显得不便的多。

直到有一天我须要去批改一个常量的定义,后面欠下的债就须要还了。反复代码最大的问题就是,当你须要去批改或者保护那段反复的代码的时候,你须要去批改每一处,如果有脱漏,那就是 bug 了。反复常量也是如此。

治理思路

1. 定义多个性能繁多的常量类

一个思路是按性能维度,去定义常量,一个常量类只跟某一性能相干。

如 MySQLConstants、RedisConstants。

但这个有个很虚的概念,就是性能,一个性能可大可小,领域能够是某一个类,也能够是一整个模块,这里没有定论,依赖的就是程序员聪慧的头脑和丰盛的教训了。

2. 不独自定义常量类

另外一种思路就是不独自设计常量类,常量在哪个类外面应用,就把常量定义到这个类中。

比方在 RedisClient 和 RedisConfig 中都用到了之前 RedisConstants 中的常量,能够将其别离定义在 RedisClient 和 RedisConfig 中。

但这样做有个显著的问题就是,如果多个类用到了同一个常量,如果各自定义就造成了反复,如果定义一份申明为 public,就会造成两个类之间的依赖。这样来看,在没有复用诉求的状况下,就地定义才比拟可取。

3. 按档次复用

上述两种形式都没有残缺的解决咱们的纳闷,思考将上述两种形式联合起来,能够失去一种按档次定义复用的形式。

  1. 跨利用复用常量:搁置在二方库中,通常是 client.jar 中的 constant 目录下。
  2. 利用内复用常量:搁置在一方库中,通常是 common 中的 constant 目录下。
  3. 模块外部复用常量:即在以后子工程的 constant 目录下。
  4. 包内复用常量:即在以后包下独自的 constant 目录下。
  5. 类内复用常量:间接在类外部 private static final 定义。

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0