370

我见过这样的例子:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

并假设我可以有一个常量类来包装常量,将它们声明为静态最终的。我几乎不知道 Java,我想知道这是否是创建常量的最佳方式。

4

28 回答 28

402

这是完全可以接受的,甚至可能是标准。

(public/private) static final TYPE NAME = VALUE;

其中TYPE是类型,NAME是全大写的名称,下划线表示空格,并且VALUE是常量值;

我强烈建议不要将常量放在它们自己的类或接口中。

附带说明:声明为 final 且可变的变量仍然可以更改;但是,变量永远不能指向不同的对象。

例如:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

这是合法的,ORIGIN然后将是 (3, 0) 处的一个点。

于 2008-09-15T19:39:48.023 回答
234

我强烈建议不要使用单个常量类。这在当时似乎是个好主意,但是当开发人员拒绝记录常量并且类增长到包含超过 500 个彼此根本不相关的常量(与应用程序的完全不同方面相关)时,这通常会变成完全不可读的常量文件。反而:

  • 如果您可以访问 Java 5+,请使用枚举来定义应用程序区域的特定常量。对于这些常量,应用程序领域的所有部分都应该引用枚举,而不是常量值。您可以声明一个类似于声明类的枚举。枚举可能是 Java 5+ 中最有用的(并且可以说是唯一的)有用的特性。
  • 如果您有仅对特定类或其子类之一有效的常量,请将它们声明为受保护或公共,并将它们放在层次结构的顶级类中。这样,子类可以访问这些常量值(如果其他类通过公共访问它们,则常量不仅对特定类有效……这意味着使用该常量的外部类可能与包含常量的类)
  • 如果您有一个定义了行为的接口,但返回的值或参数值应该是特定的,那么在该接口上定义常量以便其他实现者可以访问它们是完全可以接受的。然而,避免仅仅为了保存常量而创建一个接口:它可能变得和仅仅为了保存常量而创建一个类一样糟糕。
于 2008-09-15T19:51:44.597 回答
120

仅使用接口来保存常量是一种不好的做法(Josh Bloch 将其命名为常量接口模式)。以下是乔希的建议:

如果常量与现有的类或接口紧密相关,则应将它们添加到类或接口中。例如,所有装箱的数值基元类(如 Integer 和 Double)都导出 MIN_VALUE 和 MAX_VALUE 常量。如果最好将常量视为枚举类型的成员,则应使用枚举 类型导出它们。否则,您应该使用不可实例化的实用程序类导出常量。

例子:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

关于命名约定:

按照惯例,此类字段的名称由大写字母组成,单词之间用下划线分隔。这些字段包含原始值或对不可变对象的引用至关重要。

于 2008-09-15T19:58:22.223 回答
36

在 Effective Java(第 2 版)中,建议您使用枚举而不是静态整数作为常量。

这里有一篇关于 Java 枚举的好文章:http: //java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

请注意,在那篇文章的末尾提出的问题是:

那么什么时候应该使用枚举呢?

答案是:

任何时候你需要一组固定的常数

于 2008-09-15T20:00:12.267 回答
21

只是避免使用接口:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

这很诱人,但违反了封装并模糊了类定义的区别。

于 2008-09-15T19:45:33.800 回答
18

我使用以下方法:

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

比,例如,我Constants.DB.Connection.URL用来保持不变。对我来说,它看起来更“面向对象”。

于 2012-01-10T19:47:29.160 回答
17

在单独的类中创建静态最终常量可能会给您带来麻烦。Java 编译器实际上会对此进行优化,并将常量的实际值放入引用它的任何类中。

如果您稍后更改“常量”类并且不对引用该类的其他类进行硬重新编译,那么您最终会使用新旧值的组合。

与其将这些视为常量,不如将它们视为配置参数并创建一个类来管理它们。让这些值不是最终的,甚至考虑使用 getter。将来,当您确定其中一些参数实际上应该由用户或管理员配置时,它会更容易做到。

于 2008-09-16T03:36:05.180 回答
13

您可能犯的第一个错误是创建一个全局可访问的类,该类使用通用名称调用,例如常量。这只是被垃圾堆满了,你失去了弄清楚系统的哪个部分使用这些常量的能力。

相反,常量应该进入“拥有”它们的类。你有一个叫做 TIMEOUT 的常量吗?它可能应该进入您的 Communications() 或 Connection() 类。MAX_BAD_LOGINS_PER_HOUR?进入用户()。等等等等。

另一个可能的用途是 Java .properties 文件,当“常量”可以在运行时定义,但用户不容易更改时。您可以将它们打包到您的 .jar 中,并使用 Class resourceLoader 引用它们。

于 2008-09-15T20:26:15.183 回答
6

这是正确的方法。

通常常量不会保存在单独的“常量”类中,因为它们是不可发现的。如果常量与当前类相关,将它们保留在那里有助于下一个开发人员。

于 2008-09-15T19:44:16.487 回答
5

枚举呢?

于 2008-09-15T19:50:34.690 回答
5

我同意使用界面不是要走的路。避免这种模式甚至在 Bloch 的Effective Java中有自己的项目(#18)。

Bloch 反对常量接口模式的一个论点是常量的使用是一个实现细节,但是实现一个接口来使用它们会在导出的 API 中公开该实现细节。

public|private static final TYPE NAME = VALUE;模式是声明常量的好方法。就个人而言,我认为最好避免创建一个单独的类来容纳所有常量,但除了个人喜好和风格之外,我从未见过不这样做的理由。

如果您的常量可以很好地建模为枚举,请考虑1.5 或更高版本中可用的枚举结构。

如果您使用的是 1.5 之前的版本,您仍然可以通过使用普通的 Java 类来实现类型安全的枚举。(有关更多信息,请参阅此站点)。

于 2008-09-15T20:00:43.543 回答
5

我更喜欢使用 getter 而不是常量。那些 getter 可能会返回常量值,例如public int getMaxConnections() {return 10;},但任何需要常量的东西都将通过 getter。

一个好处是,如果你的程序超出了常量——你发现它需要是可配置的——你可以改变 getter 如何返回常量。

另一个好处是,为了修改常量,您不必重新编译使用它的所有内容。当您引用静态最终字段时,该常量的值将编译为引用它的任何字节码。

于 2008-09-16T01:30:29.540 回答
4

根据上面的评论,我认为这是一种将老式全局常量类(具有公共静态最终变量)更改为类似枚举的等价物的好方法,如下所示:

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public interface ConstantType {}

    public enum StringConstant implements ConstantType {
        DB_HOST("localhost");
        // other String constants come here

        private String value;
        private StringConstant(String value) {
            this.value = value;
        }
        public String value() {
            return value;
        }
    }

    public enum IntConstant implements ConstantType {
        DB_PORT(3128), 
        MAX_PAGE_SIZE(100);
        // other int constants come here

        private int value;
        private IntConstant(int value) {
            this.value = value;
        }
        public int value() {
            return value;
        }
    }

    public enum SimpleConstant implements ConstantType {
        STATE_INIT,
        STATE_START,
        STATE_END;
    }

}

那么我可以推荐他们喜欢:

Constants.StringConstant.DB_HOST
于 2011-06-26T21:16:48.933 回答
3

一个好的面向对象设计不应该需要很多公开可用的常量。大多数常量应该封装在需要它们完成工作的类中。

于 2008-09-15T23:58:26.797 回答
2

有一定的意见可以回答这个问题。首先,Java 中的常量通常被声明为 public、static 和 final。以下是原因:

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

我永远不会仅仅因为通常期望实现接口而将接口用于 CONSTANTS 访问器/对象。这看起来是不是很有趣:

String myConstant = IMyInterface.CONSTANTX;

相反,我会在一些不同的方式之间进行选择,基于一些小的权衡,所以这取决于你需要什么:

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe
于 2017-01-07T20:24:48.977 回答
2

在 Java 中实现常量的最佳方法是什么?

我们应该真正避免的一种方法:使用接口来定义常量。

专门创建一个接口来声明常量确实是最糟糕的事情:它违背了设计接口的原因:定义方法契约。

即使已经存在满足特定需求的接口,在其中声明常量也没有任何意义,因为常量不应成为 API 和提供给客户端类的合同的一部分。


为简化起见,我们大致有 4 种有效方法

static final String/Integer字段:

  • 1)使用一个在内部但不仅仅是声明常量的类。
  • 1 个变体)创建一个专用于仅声明常量的类。

Java 5 enum

  • 2)在相关目的类(如嵌套类)中声明枚举。
  • 2 变体)将枚举创建为独立类(在其自己的类文件中定义)。

TLDR:哪个是最好的方法,在哪里定位常量?

在大多数情况下,枚举方式可能比static final String/Integer方式更好,我个人认为static final String/Integer只有当我们有充分的理由不使用枚举时才应该使用这种方式。
关于我们应该在哪里声明常量值,我们的想法是搜索是否存在一个现有的类,该类具有与常量值的特定且强大的功能内聚。如果我们找到这样一个类,我们应该将它用作常量持有者。否则,该常量不应与任何特定类相关联。


static final String/static final Integerenum

枚举的使用确实是一种强烈考虑的方式。枚举比常量字段
有很大的优势。 他们设置了更强的编译约束。如果定义一个以枚举为参数的方法,则只能传递枚举类中定义的枚举值(或 null)。 使用 String 和 Integer,您可以将它们替换为兼容类型的任何值,并且即使该值不是/字段中定义的常量,编译也会很好。StringInteger

static final Stringstatic final Integer

例如,在一个类中定义为static final Stringfields 的以下两个常量:

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

这是一个期望将这些常量之一作为参数的方法:

public void process(String constantExpected){
    ...    
}

您可以通过这种方式调用它:

process(MyClass.ONE_CONSTANT);

或者

process(MyClass.ANOTHER_CONSTANT);

但是没有编译约束阻止您以这种方式调用它:

process("a not defined constant value");

只有在运行时并且仅当您一次检查传输的值时才会出现错误。

使用枚举,不需要检查,因为客户端只能在枚举参数中传递枚举值。

例如,这里在枚举类中定义了两个值(开箱即用的常量):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

这是一个期望将这些枚举值之一作为参数的方法:

public void process(MyEnum myEnum){
    ...    
}

您可以通过这种方式调用它:

process(MyEnum.ONE_CONSTANT);

或者

process(MyEnum.ANOTHER_CONSTANT);

但是编译永远不会允许您以这种方式调用它:

process("a not defined constant value");

我们应该在哪里声明常量?

如果您的应用程序包含一个现有类,该类与常量值具有特定且强大的功能内聚,则 1) 和 2) 看起来更直观。
一般来说,如果在操作它们的主类中声明了这些常量,或者有一个很自然的名字可以猜测我们会在里面找到它,那么它会简化常量的使用。

例如,在 JDK 库中,指数和 pi 常量值在一个不仅声明常量声明 ( java.lang.Math) 的类中声明。

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

使用数学函数的客户通常依赖于Math类。因此,他们可以很容易地找到常量,并且还可以以非常自然的方式记住在哪里定义E和定义。PI

如果您的应用程序不包含与常量值具有非常具体和强大功能内聚的现有类,则 1 变体)和 2 变体)方式显得更直观。
通常,如果在一个操纵它们的类中声明这些常量,而我们还有 3 或 4 个其他类来操纵它们,并且这些类中没有一个似乎比其他类更自然主机常量值。
在这里,定义一个只保存常量值的自定义类是有意义的。
例如,在 JDK 库中,java.util.concurrent.TimeUnit枚举没有在特定类中声明,因为实际上并没有一个而且只有一个 JDK 特定类看起来最直观地保存它:

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

许多在java.util.concurrent使用它们时声明的类 : BlockingQueue, ArrayBlockingQueue<E>, CompletableFuture, ExecutorService, ... 实际上没有一个类似乎更适合保存枚举。

于 2017-06-09T08:18:31.663 回答
1

可以通过在类中创建不可变属性(即带有final修饰符的成员变量)来声明任何类型的常量。通常还提供staticand 修饰符。public

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

在许多应用中,常量的值表示从 n 元组(例如enumeration)中进行的选择。在我们的示例中,我们可以选择定义一个 Enumerated Type 来限制可能的分配值(即改进的类型安全):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}
于 2008-09-15T21:17:31.130 回答
1

一个单一的、通用的常量类是个坏主意。常量应该与它们在逻辑上最相关的类组合在一起。

我建议您使用方法,而不是使用任何类型的变量(尤其是枚举)。创建一个与变量同名的方法,并让它返回您分配给变量的值。现在删除该变量并将所有对它的引用替换为对您刚刚创建的方法的调用。如果你觉得这个常量足够通用以至于你不应该仅仅为了使用它而创建一个类的实例,那么让这个常量方法成为一个类方法。

于 2008-09-15T22:17:12.950 回答
1

FWIW,以秒为单位的超时值可能应该是配置设置(从属性文件中读取或像在 Spring 中一样通过注入),而不是常量。

于 2008-09-16T01:33:07.753 回答
1

有什么不同

1.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2.

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

MyGlobalConstants.TIMEOUT_IN_SECS在我们需要这个常量的地方使用。我认为两者都是一样的。

于 2010-12-09T21:11:54.430 回答
0

我不会将类称为与常量相同的类(除了大小写)......我至少会拥有一类“设置”、“值”或“常量”,所有常量都将在其中存在。如果我有大量它们,我会将它们分组到逻辑常量类(UserSettings、AppSettings 等)中

于 2008-09-15T19:41:23.963 回答
0

更进一步,您可以将全局使用的常量放在接口中,以便它们可以在系统范围内使用。例如

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

但不要实施它。只需通过完全限定的类名在代码中直接引用它们。

于 2008-09-15T19:45:34.407 回答
0

对于常量,枚举是一个更好的选择恕我直言。这是一个例子

公共类 myClass {

public enum myEnum {
    Option1("String1", 2), 
    Option2("String2", 2) 
    ;
    String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}
于 2008-09-15T20:45:52.593 回答
0

我这样做的一种方法是使用常量值创建一个“全局”类,并在需要访问常量的类中进行静态导入。

于 2008-09-15T21:44:56.913 回答
0

static final是我的偏好,我只会enum在项目确实是可枚举的情况下使用。

于 2012-08-31T01:49:03.907 回答
0

static final用来声明常量并使用 ALL_CAPS 命名符号。我见过很多现实生活中的实例,其中所有常量都聚集在一个接口中。一些帖子正确地称这是一种不好的做法,主要是因为这不是接口的用途。接口应该强制执行契约,而不应该是放置不相关常量的地方。如果常量语义不属于特定类,则将其放在无法实例化的类中(通过私有构造函数)也可以(埃斯)。我总是在与其最相关的类中放置一个常量,因为这很有意义并且易于维护。

枚举是表示一系列值的好选择,但如果您要存储独立的常量并强调绝对值(例如 TIMEOUT = 100 ms),您可以采用这种static final方法。

于 2013-05-15T12:45:24.017 回答
0

我同意大多数人的说法,在处理常量集合时最好使用枚举。但是,如果您在 Android 中编程,则有一个更好的解决方案:IntDef Annotation

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST,NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();

IntDef 注释以一种简单的方式优于枚举,它占用的空间显着减少,因为它只是一个编译时标记。它不是一个类,也没有自动字符串转换属性。

于 2016-07-28T14:40:19.247 回答
0

在不了解基本零基础原教旨主义的情况下引用约书亚·布洛赫的话是一个坏习惯,也是非常令人讨厌的做法。

我没有读过任何东西 Joshua Bloch,所以要么

  • 他是个糟糕的程序员
  • 或者到目前为止,我发现引用他的人(我认为约书亚是一个男孩的名字)只是将他的材料用作宗教脚本来证明他们的软件宗教放纵是正当的。

就像在圣经原教旨主义中一样,所有的圣经律法都可以概括为

  • 全心全意地爱基本身份
  • 爱你的邻居如同爱自己

类似地,软件工程原教旨主义可以总结为

  • 用你所有的编程能力和头脑专注于零基础
  • 并像为自己一样致力于卓越的程序员伙伴。

此外,在圣经原教旨主义圈子中,得出了一个强有力且合理的推论

  • 先爱自己。因为如果你不太爱自己,那么“爱邻如己”的概念就没有多大分量,因为“你有多爱自己”是你爱他人的基准线。

同样,如果您不尊重自己作为程序员的身份,并且只是接受一些编程大师的声明和预言而不质疑基本原理,那么您对 ​​Joshua Bloch(等)的引用和依赖是毫无意义的。因此,您实际上不会尊重您的程序员同事。

软件编程的基本规律

  • 懒惰是优秀程序员的美德
  • 你要让你的编程生活尽可能简单、懒惰并尽可能有效
  • 你要让你的编程的后果和内脏变得简单、懒惰,因此对与你一起工作并收集你的编程内脏的邻居程序员尽可能有效。

接口模式常量是一个坏习惯???

这条宗教法令属于什么基本有效和负责任的编程法则?

只需阅读关于接口模式常量的维基百科文章(https://en.wikipedia.org/wiki/Constant_interface),以及它针对接口模式常量声明的愚蠢借口。

  • Whatif - 没有 IDE?作为软件程序员,谁不会使用 IDE?我们大多数人都是程序员,他们不希望通过避免使用 IDE 来证明自己有男子气概的求生主义。

    • 另外 - 等待微功能编程的第二个支持者作为不需要 IDE 的手段。等你读完我对数据模型规范化的解释。
  • 使用当前范围内未使用的变量污染命名空间?可能是这种观点的支持者

    • 不知道也不需要数据模型规范化
  • 使用接口强制常量是对接口的滥用。这样的支持者有一个坏习惯

    • 没有看到“常量”必须被视为合同。接口用于强制或预测合同的合规性。
  • 将来将接口转换为已实现的类是很困难的,如果不是不可能的话。哈……嗯……???

    • 你为什么要从事这样的编程模式作为你的持续生计?IOW,为什么要养成这种矛盾和不良的编程习惯?

无论借口是什么,当涉及从根本上有效的软件工程来取消合法性或通常不鼓励使用接口常量时,都没有任何有效的借口。

制定美国宪法的开国元勋的初衷和精神状态是什么并不重要。我们可以辩论开国元勋的初衷,但我只关心美国宪法的书面声明。每个美国公民都有责任利用美国宪法的书面文学原教旨主义,而不是不成文的建国意图。

同样,我不在乎 Java 平台和编程语言的创始人对接口的“原始”意图是什么。我关心的是 Java 规范提供的有效特性,我打算充分利用这些特性来帮助我实现负责任的软件编程的基本法则。我不在乎我是否被认为“违反了接口的意图”。我不在乎 Gosling 或 Bloch 对“使用 Java 的正确方法”说了什么,除非他们说的不违反我对有效实现基本原理的需要。

基础是数据模型规范化

您的数据模型如何托管或传输并不重要。如果您不了解数据模型规范化的需求和过程,无论您使用接口还是枚举或其他任何东西,关系或非 SQL。

我们必须首先定义和规范化一组流程的数据模型。当我们拥有一个连贯的数据模型时,只有这样我们才能使用其组件的流程来定义功能行为和流程块应用程序的领域或领域。只有这样我们才能定义每个功能流程的API。

即使是 EF Codd 提出的数据规范化方面现在也面临着严峻的挑战和严峻的挑战。例如,他关于 1NF 的陈述被批评为模棱两可、错位和过度简化,他的其他陈述也是如此,特别是在现代数据服务、回购技术和传输的出现方面。IMO,应该完全抛弃 EF Codd 语句,并设计一组新的数学上更合理的语句。

EF Codd 的一个明显缺陷及其与有效人类理解不一致的原因是他相信人类可感知的多维、可变维数据可以通过一组零碎的二维映射有效地感知。

数据规范化的基础

EF Codd 未能表达的内容。

在每个连贯的数据模型中,这些都是要实现的数据模型连贯性的顺序分级顺序。

  1. 数据实例的统一性和身份。
    • 设计每个数据组件的粒度,使其粒度处于可以唯一标识和检索组件的每个实例的级别。
    • 没有实例别名。即,不存在使标识产生多个组件实例的方法。
  2. 没有实例串扰。不存在使用组件的一个或多个其他实例来帮助识别组件实例的必要性。
  3. 数据组件/维度的统一性和同一性。
    • 存在组件去锯齿。必须存在一个定义,从而可以唯一地标识组件/维度。这是组件的主要定义;
    • 其中主要定义不会导致暴露不属于预期组件的子维度或成员组件;
  4. 独特的组件去锯齿方法。一个组件必须存在一个,并且只有一个,这样的组件去锯齿定义。
  5. 存在一个,并且只有一个定义接口或契约来标识组件的层次关系中的父组件。
  6. 没有组件串扰。没有必要使用另一个组件的成员来对组件的最终识别做出贡献。
    • 在这样的父子关系中,父子的标识定义不能依赖于子组件的部分成员组件。父母身份的成员组成部分必须是完整的孩子身份,而不诉诸于引用孩子的任何或所有孩子。
  7. 抢占数据模型的双模式或多模式外观。
    • 当一个组件存在两个候选定义时,这是一个明显的迹象,表明存在两个不同的数据模型混合为一个。这意味着在数据模型级别或字段级别存在不连贯性。
    • 一个应用领域必须一致地使用一个且只有一个数据模型。
  8. 检测和识别组件突变。除非您已经对大量数据进行了统计成分分析,否则您可能看不到或认为需要处理成分突变。
    • 数据模型的某些组件可能会周期性地或逐渐地发生变异。
    • 该模式可以是成员旋转或换位旋转。
    • 成员轮换突变可能是组件之间子组件的不同交换。或者必须定义全新的组件。
    • 换位突变将表现为维度成员突变为属性,反之亦然。
    • 每个突变周期都必须被识别为不同的数据模式。
  9. 版本化每个突变。这样您就可以在可能需要处理数据模型的 8 年前突变时提取数据模型的先前版本。

在服务间组件应用程序的领域或网格中,必须有一个且只有一个连贯的数据模型,或者存在一种数据模型/版本标识自身的方法。

我们还在问是否可以使用接口常量吗?真的吗 ?

存在比这个平凡问题更重要的数据规范化问题。如果您不解决这些问题,那么您认为接口常量引起的混乱相对来说没什么。齐尔奇。

从数据模型规范化中,您可以将组件确定为变量、属性、合同接口常量。

然后你确定哪些进入值注入、属性配置占位、接口、最终字符串等。

如果你不得不以需要找到一个更容易控制接口常量的组件为借口,这意味着你养成了不练习数据模型规范化的坏习惯。

也许您希望将数据模型编译成 vcs 版本。您可以提取数据模型的明显可识别版本。

接口中定义的值完全保证是不可变的。并且可以分享。当您只需要一组常量时,为什么要将一组最终字符串从另一个类加载到您的类中?

那么为什么不发布数据模型合约呢?我的意思是,如果你能连贯地管理和规范它,为什么不呢?...

public interface CustomerService {
  public interface Label{
    char AssignmentCharacter = ':';
    public interface Address{
      String Street = "Street";
      String Unit= "Unit/Suite";
      String Municipal = "City";
      String County = "County";
      String Provincial = "State";
      String PostalCode = "Zip"
    }

    public interface Person {
      public interface NameParts{
        String Given = "First/Given name"
        String Auxiliary = "Middle initial"
        String Family = "Last name"
      }
    }
  }
}

现在我可以通过以下方式引用我的应用程序的合同标签

CustomerService.Label.Address.Street
CustomerService.Label.Person.NameParts.Family

这混淆了jar文件的内容?作为一名 Java 程序员,我并不关心 jar 的结构。

这给 osgi 驱动的运行时交换带来了复杂性?Osgi 是一种非常有效的手段,可以让程序员继续他们的坏习惯。有比 osgi 更好的选择。

或者为什么不这样做?私有常量不会泄漏到已发布的合约中。所有私有常量都应该分组到一个名为“Constants”的私有接口中,因为我不想搜索常量,也懒得重复输入“private final String”。

public class PurchaseRequest {
  private interface Constants{
    String INTERESTINGName = "Interesting Name";
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

甚至可能是这样:

public interface PurchaseOrderConstants {
  public interface Properties{
    default String InterestingName(){
       return something();
    }
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

接口常量唯一值得考虑的问题是接口何时实现。

这不就是接口的“初衷”吗?就像我会关心开国元勋制定美国宪法的“初衷”,而不是最高法院将如何解释美国宪法的书面文字???

毕竟,我生活在自由、狂野和勇敢者的家园。勇敢、自由、狂野——使用界面。如果我的同事拒绝使用高效和懒惰的编程方式,我是否有义务降低我的编程效率以与他们保持一致?也许我应该,但这不是一个理想的情况。

于 2018-01-10T11:41:53.957 回答