Java에서 상수를 구현하는 가장 좋은 방법은 무엇입니까?[닫은]

StackOverflow https://stackoverflow.com/questions/66066

  •  09-06-2019
  •  | 
  •  

문제

나는 다음과 같은 예를 본 적이 있습니다.

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

그리고 상수를 감싸서 static final로 선언하는 Constants 클래스를 가질 수 있다고 가정했습니다.저는 Java를 전혀 알지 못하며 이것이 상수를 생성하는 가장 좋은 방법인지 궁금합니다.

도움이 되었습니까?

해결책

이는 완벽하게 수용 가능한 수준이며 아마도 표준일 수도 있습니다.

(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)의 점이 됩니다.

다른 팁

단일 상수 클래스를 사용하지 않는 것이 좋습니다.당시에는 좋은 아이디어처럼 보일 수 있지만 개발자가 상수 문서화를 거부하고 클래스가 서로 전혀 관련되지 않은(애플리케이션의 완전히 다른 측면과 관련되어 있는) 500개 이상의 상수를 포함하도록 성장하면 이는 일반적으로 상수 파일을 완전히 읽을 수 없게 됩니다.대신에:

  • Java 5+에 액세스할 수 있는 경우 열거형을 사용하여 애플리케이션 영역에 대한 특정 상수를 정의하세요.응용 프로그램 영역의 모든 부분은 이러한 상수에 대해 상수 값이 아닌 열거형을 참조해야 합니다.클래스를 선언하는 방법과 유사하게 열거형을 선언할 수 있습니다.열거형은 아마도 Java 5+의 가장 유용한 기능일 것입니다.
  • 특정 클래스나 그 하위 클래스 중 하나에만 유효한 상수가 있는 경우 이를 protected 또는 public으로 선언하고 계층 구조의 최상위 클래스에 배치하세요.이런 방식으로 하위 클래스는 이러한 상수 값에 액세스할 수 있습니다. (그리고 다른 클래스가 공개를 통해 상수에 액세스하는 경우 상수는 특정 클래스에만 유효한 것이 아닙니다. 즉, 이 상수를 사용하는 외부 클래스가 클래스에 너무 밀접하게 결합될 수 있습니다. 상수를 포함하는 클래스)
  • 동작이 정의된 인터페이스가 있지만 반환된 값이나 인수 값이 특별해야 하는 경우 다른 구현자가 이에 액세스할 수 있도록 해당 인터페이스에 상수를 정의하는 것이 완벽하게 허용됩니다.그러나 단지 상수를 유지하기 위해 인터페이스를 만드는 것은 피하세요.단지 상수를 유지하기 위해 만들어진 클래스만큼 나빠질 수 있습니다.

이것은 나쁜 관행 상수를 유지하기 위해 인터페이스를 사용하려면(이름이 지정됨) 일정한 인터페이스 패턴 조쉬 블로흐 지음).Josh가 조언하는 내용은 다음과 같습니다.

상수가 에 강하게 연결된 경우 기존 클래스 또는 인터페이스, 클래스에 추가해야 합니다. 인터페이스.예를 들어, 모든 박스형 숫자 프리미티브 클래스, 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;
}

명명 규칙 정보:

규칙에 따라 이러한 필드에는 이름이 있습니다 대문자로 구성, 밑줄로 구분된 단어입니다.그것이 이러한 필드에 포함되는 것이 중요합니다. 기본 값 또는 참조 불변 객체에.

Effective Java(2판)에서는 상수에 정적 정수 대신 열거형을 사용하는 것이 좋습니다.

여기에 Java의 열거형에 대한 좋은 글이 있습니다.http://java.sun.com/j2se/1.5.0/docs/guide/언어/enums.html

해당 기사의 마지막 부분에 제시된 질문은 다음과 같습니다.

그렇다면 언제 열거형을 사용해야 할까요?

다음과 같은 답변으로:

고정된 상수 세트가 필요할 때마다

인터페이스 사용을 피하세요.

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

public class NeddsConstant implements MyConstants {

}

유혹적이지만 캡슐화를 위반하고 클래스 정의의 구분을 모호하게 만듭니다.

나는 다음 접근 방식을 사용합니다.

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 일정해지도록.나에게는 더 "객체 지향적"으로 보입니다.

별도의 클래스에 정적 최종 상수를 생성하면 문제가 발생할 수 있습니다.Java 컴파일러는 실제로 이를 최적화하고 이를 참조하는 모든 클래스에 상수의 실제 값을 배치합니다.

나중에 '상수' 클래스를 변경하고 해당 클래스를 참조하는 다른 클래스에서 하드 재컴파일을 수행하지 않으면 이전 값과 새 값의 조합이 사용되게 됩니다.

이를 상수로 생각하는 대신 구성 매개변수로 생각하고 이를 관리할 클래스를 만듭니다.값이 최종이 아니도록 하고 getter 사용을 고려해보세요.앞으로는 이러한 매개변수 중 일부를 실제로 사용자나 관리자가 구성할 수 있어야 한다고 판단하면 작업이 훨씬 쉬워질 것입니다.

당신이 할 수 있는 가장 큰 실수는 상수와 같은 일반 이름으로 호출되는 전역적으로 액세스 가능한 클래스를 만드는 것입니다.이는 단순히 쓰레기로 가득 차게 되며 시스템의 어느 부분이 이러한 상수를 사용하는지 파악하는 모든 능력을 잃게 됩니다.

대신, 상수는 이를 "소유"하는 클래스에 들어가야 합니다.TIMEOUT이라는 상수가 있나요?아마도 Communications() 또는 Connection() 클래스로 들어가야 할 것입니다.MAX_BAD_LOGINS_PER_HOUR?User()로 들어갑니다.등등.

다른 가능한 용도는 런타임에 "상수"를 정의할 수 있지만 사용자가 쉽게 변경할 수 없는 경우 Java .properties 파일입니다.이를 .jars로 패키징하고 Class ResourceLoader를 사용하여 참조할 수 있습니다.

그게 옳은 길이에요.

일반적으로 상수는 ~ 아니다 검색할 수 없기 때문에 별도의 "상수" 클래스에 보관됩니다.상수가 현재 클래스와 관련된 경우 이를 그대로 유지하면 다음 개발자에게 도움이 됩니다.

열거형은 어떻습니까?

나는 상수보다는 getter를 사용하는 것을 선호합니다.이러한 게터는 상수 값을 반환할 수 있습니다. public int getMaxConnections() {return 10;}, 그러나 상수가 필요한 모든 것은 getter를 통과합니다.

한 가지 이점은 프로그램이 상수를 초과하는 경우(구성 가능해야 함을 알게 되면) getter가 상수를 반환하는 방법을 변경할 수 있다는 것입니다.

또 다른 이점은 상수를 수정하기 위해 이를 사용하는 모든 항목을 다시 컴파일할 필요가 없다는 것입니다.정적 최종 필드를 참조하면 해당 상수의 값이 이를 참조하는 바이트코드로 컴파일됩니다.

인터페이스를 사용하는 것이 좋은 방법이 아니라는 데 동의합니다.이 패턴을 피하면 Bloch의 자체 아이템(#18)도 있습니다. 효과적인 자바.

Bloch가 상수 인터페이스 패턴에 대해 주장하는 바는 상수 사용은 구현 세부 사항이지만 이를 사용하기 위해 인터페이스를 구현하면 내보낸 API에 해당 구현 세부 사항이 노출된다는 것입니다.

그만큼 public|private static final TYPE NAME = VALUE; 패턴은 상수를 선언하는 좋은 방법입니다.개인적으로 모든 상수를 수용하기 위해 별도의 클래스를 만들지 않는 것이 낫다고 생각하지만 개인적인 취향과 스타일 외에는 이렇게 하지 않을 이유를 본 적이 없습니다.

상수를 열거형으로 잘 모델링할 수 있는 경우 다음을 고려하세요. 열거형 1.5 이상에서 사용 가능한 구조입니다.

1.5 이전 버전을 사용하는 경우에도 일반 Java 클래스를 사용하여 유형이 안전한 열거형을 가져올 수 있습니다.(보다 이 장소 이에 대한 자세한 내용은)

위의 의견을 바탕으로 나는 이것이 구식 전역 상수 클래스(공용 정적 최종 변수를 가짐)를 다음과 같은 방식으로 열거형과 동등한 클래스로 변경하는 좋은 접근 방식이라고 생각합니다.

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

좋은 객체 지향 디자인에는 공개적으로 사용 가능한 상수가 많이 필요하지 않습니다.대부분의 상수는 해당 작업을 수행하는 데 필요한 클래스에 캡슐화되어야 합니다.

이에 대한 답변에는 어느 정도 의견이 있습니다.우선, Java의 상수는 일반적으로 공개, 정적 및 최종으로 선언됩니다.이유는 다음과 같습니다.

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

Java에서 상수를 구현하는 가장 좋은 방법은 무엇입니까?

우리가 정말 피해야 할 접근 방식 중 하나 :인터페이스를 사용하여 상수를 정의합니다.

상수를 선언하기 위해 특별히 인터페이스를 만드는 것은 실제로 최악의 일입니다.인터페이스가 설계된 이유를 무효화합니다.메소드 계약을 정의합니다.

특정 요구 사항을 해결하기 위해 인터페이스가 이미 존재하더라도 상수를 선언하는 것은 실제로 의미가 없습니다. 상수는 클라이언트 클래스에 제공되는 API 및 계약의 일부가 되어서는 안 되기 때문입니다.


단순화하기 위해 광범위하게 4가지 유효한 접근 방식이 있습니다..

와 함께 static final String/Integer 필드 :

  • 1) 내부에 상수를 선언하는 클래스를 사용하는 것뿐만 아니라.
  • 1 변형) 상수 선언 전용 클래스를 생성합니다.

와 함께 Java 5 enum :

  • 2) 관련 목적 클래스(중첩 클래스)에서 열거형을 선언합니다.
  • 2 변형) 열거형을 독립형 클래스로 생성합니다(자체 클래스 파일에 정의됨).

TLDR:가장 좋은 방법은 무엇이며 상수는 어디에 있습니까?

대부분의 경우 열거형 방식은 아마도 열거형 방식보다 더 정밀할 것입니다. static final String/Integer 방법 그리고 개인적으로 내 생각에는 static final String/Integer way는 열거형을 사용하지 말아야 할 타당한 이유가 있는 경우에만 사용해야 합니다.
그리고 상수 값을 어디에 선언해야 하는지에 대해, 아이디어는 상수 값과 구체적이고 강력한 기능적 응집력을 소유한 단일 기존 클래스가 있는지 검색하는 것입니다.그러한 클래스를 찾으면 이를 상수 홀더로 사용해야 합니다..그렇지 않으면 상수는 특정 클래스와 연관되어서는 안 됩니다.


static final String/ static final Integer ~ 대 enum

열거형 사용은 실제로 강력히 고려되는 방법입니다.
Enum은 Enum에 비해 큰 이점을 가지고 있습니다. String 또는 Integer 상수 필드.
그들은 더 강력한 컴파일 제약 조건을 설정했습니다.열거형을 매개 변수로 사용하는 메서드를 정의하는 경우 열거형 클래스(또는 null)에 정의된 열거형 값만 전달할 수 있습니다.
문자열 및 정수를 사용하면 호환 가능한 유형의 값으로 대체할 수 있으며 값이 정의된 상수가 아니더라도 컴파일은 문제가 없습니다. static final String/ static final Integer 필드.

예를 들어, 클래스에 다음과 같이 정의된 두 개의 상수가 있습니다. static final String 필드 :

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");

런타임에만 오류가 발생하며 전송된 값을 한 번에 확인하는 경우에만 발생합니다.

enum을 사용하면 클라이언트가 enum 매개변수의 enum 값만 전달할 수 있으므로 검사가 필요하지 않습니다.

예를 들어, 열거형 클래스에 정의된 두 개의 값은 다음과 같습니다(즉, 기본적으로 상수임).

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 라이브러리에서 지수 및 파이 상수 값은 상수 선언(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 enum을 보유하는 데 가장 직관적인 것으로 보이는 JDK 특정 클래스는 실제로 하나도 없기 때문에 특정 클래스에서 선언되지 않습니다.

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

많은 클래스가 선언되었습니다. java.util.concurrent 그것을 써 :BlockingQueue, ArrayBlockingQueue<E>, CompletableFuture, ExecutorService , ...실제로 그들 중 어느 누구도 열거형을 보유하는 데 더 적합한 것 같지 않습니다.

모든 유형의 상수는 클래스 내에서 불변 속성(즉, final 수정자).일반적으로 static 그리고 public 수정자도 제공됩니다.

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

상수 값이 n-튜플에서의 선택을 나타내는 수많은 응용 프로그램이 있습니다(예: 열거) 선택 사항입니다.이 예에서는 할당 가능한 값을 제한하는 열거 유형을 정의하도록 선택할 수 있습니다(예:향상 유형 안전성):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}

단일의 일반 상수 클래스는 좋지 않습니다.상수는 가장 논리적으로 관련된 클래스와 함께 그룹화되어야 합니다.

어떤 종류의 변수(특히 열거형)를 사용하는 대신 메서드를 사용하는 것이 좋습니다.변수와 동일한 이름을 가진 메서드를 만들고 변수에 할당한 값을 반환하도록 합니다.이제 변수를 삭제하고 해당 변수에 대한 모든 참조를 방금 만든 메서드에 대한 호출로 바꿉니다.상수가 단지 사용하기 위해 클래스의 인스턴스를 생성할 필요가 없을 만큼 충분히 일반적이라고 생각되면 상수 메소드를 클래스 메소드로 만드십시오.

FWIW, 초 단위의 시간 초과 값은 아마도 상수가 아니라 구성 설정(속성 파일에서 읽거나 Spring에서 주입을 통해 읽음)이어야 합니다.

차이점은 무엇입니까

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 이 상수가 필요한 곳이면 어디든지요.나는 둘 다 같다고 생각한다.

나는 클래스를 상수와 동일하게 (대소문자 제외) 호출하지 않을 것입니다 ...모든 상수가 존재하는 "설정", "값" 또는 "상수" 클래스가 하나 이상 있어야 합니다.그 수가 많으면 논리 상수 클래스(UserSettings, AppSettings 등)로 그룹화합니다.

한 단계 더 나아가, 전역적으로 사용되는 상수를 인터페이스에 배치하여 시스템 전체에서 사용할 수 있습니다.예:

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

그러나 그것을 구현하지 마십시오.정규화된 클래스 이름을 통해 코드에서 직접 참조하면 됩니다.

상수의 경우 Enum이 더 나은 선택입니다. IMHO.여기에 예가 있습니다.

공개 클래스 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 }


}

내가 수행하는 방법 중 하나는 상수 값을 사용하여 '전역' 클래스를 만들고 상수에 액세스해야 하는 클래스에서 정적 가져오기를 수행하는 것입니다.

static final 제가 선호하는 것은 다음과 같습니다. enum 항목이 실제로 열거 가능한 경우.

나는 사용한다 static final 상수를 선언하고 ALL_CAPS 명명 표기법을 사용합니다.나는 모든 상수가 하나의 인터페이스에 함께 묶인 실제 사례를 꽤 많이 보았습니다.몇몇 게시물에서는 인터페이스의 용도가 아니기 때문에 이를 나쁜 습관이라고 올바르게 표현했습니다.인터페이스는 계약을 시행해야 하며 관련 없는 상수를 입력하는 장소가 되어서는 안 됩니다.상수 의미 체계가 특정 클래스에 속하지 않는 경우 (개인 생성자를 통해) 인스턴스화할 수 없는 클래스에 함께 넣는 것도 괜찮습니다.나는 항상 가장 관련이 있는 클래스에 상수를 넣습니다. 왜냐하면 그것이 의미가 있고 쉽게 유지 관리할 수 있기 때문입니다.

열거형은 값 범위를 나타내는 좋은 선택이지만 절대값에 중점을 두고 독립형 상수를 저장하는 경우(예:TIMEOUT = 100ms) 그냥 갈 수 있습니다 static final 접근하다.

나는 대부분의 말에 동의합니다. 상수 컬렉션을 다룰 때 열거형을 사용하는 것이 가장 좋습니다.그러나 Android에서 프로그래밍하는 경우 더 나은 솔루션이 있습니다. IntDef 주석.

@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 주석은 한 가지 간단한 방식으로 열거형보다 우수하며, 단순한 컴파일 타임 마커이므로 훨씬 적은 공간을 차지합니다.클래스도 아니고 자동 문자열 변환 속성도 없습니다.

그것은 나쁜 습관과 끔찍하게 성가신 연습 기본적인 그라운드 제로 근본주의를 이해하지 못한 채 조슈아 블로흐(Joshua Bloch)의 말을 인용하는 것입니다.

나는 Joshua Bloch의 글을 읽은 적이 없습니다.

  • 그 사람은 끔찍한 프로그래머야
  • 또는 지금까지 내가 그를 인용한 사람들(Joshua는 내 생각에 소년의 이름인 것으로 추정됩니다)은 단순히 그의 자료를 그들의 소프트웨어 종교적 면죄부를 정당화하기 위한 종교적 대본으로 사용하고 있습니다.

성경 근본주의에서처럼 성경의 모든 법칙은 다음과 같이 요약될 수 있습니다.

  • 마음을 다하고 뜻을 다하여 근본 정체성을 사랑하라
  • 네 이웃을 네 자신처럼 사랑하라

마찬가지로 소프트웨어 공학 근본주의는 다음과 같이 요약될 수 있습니다.

  • 모든 프로그래밍 능력과 정신을 다해 그라운드 제로 기본 사항에 전념하십시오.
  • 그리고 동료 프로그래머의 우수성을 위해 헌신하십시오.

또한 성경 근본주의 집단 사이에서는 강력하고 합리적인 추론이 도출됩니다.

  • 먼저 자신을 사랑하십시오.왜냐하면 당신이 자신을 많이 사랑하지 않는다면, "네 이웃을 너 자신처럼 사랑하라"는 개념은 그다지 중요하지 않기 때문입니다. 왜냐하면 "당신이 자신을 얼마나 사랑하는지"가 당신이 다른 사람을 사랑할 기준선이기 때문입니다.

마찬가지로, 당신이 프로그래머로서 자신을 존중하지 않고 기본에 의문을 제기하지 않고 일부 프로그래밍 전문가의 선언과 예언을 받아들이면 Joshua Bloch 등에 대한 인용과 의존은 의미가 없습니다.따라서 실제로 동료 프로그래머에 대한 존경심이 없을 것입니다.

소프트웨어 프로그래밍의 기본 법칙

  • 게으름은 좋은 프로그래머의 미덕이다
  • 프로그래밍 생활을 최대한 쉽고, 게으르게, 따라서 최대한 효과적으로 만들어야 합니다.
  • 당신은 프로그래밍의 결과와 과정을 가능한 한 쉽고, 게으르게, 따라서 당신과 함께 일하고 프로그래밍 과정을 이어가는 이웃 프로그래머들에게 최대한 효과적으로 만들어야 합니다.

인터페이스 패턴 상수는 나쁜 습관입니다 ???

이 종교적 칙령은 근본적으로 효과적이고 책임감 있는 프로그램의 어떤 법률에 속합니까?

인터페이스 패턴 상수에 대한 Wikipedia 기사를 읽어보세요(https://en.wikipedia.org/wiki/Constant_interface) 그리고 인터페이스 패턴 상수에 대해 언급하는 어리석은 변명입니다.

  • 만약에 IDE가 없나요?소프트웨어 프로그래머로서 도대체 누가 IDE를 사용하지 않겠습니까?우리 대부분은 IDE 사용을 피하면서 마초적 금욕주의적 생존주의를 갖고 있음을 증명할 필요가 없는 것을 선호하는 프로그래머입니다.

    • 또한 - IDE가 필요하지 않은 수단으로 마이크로 기능 프로그래밍의 두 번째 지지자를 기다리십시오.데이터 모델 정규화에 대한 내 설명을 읽을 때까지 기다리십시오.
  • 현재 범위 내에서 사용되지 않는 변수로 네임스페이스를 오염시키나요?이 의견을 지지하는 사람일 수도 있습니다.

    • 데이터 모델 정규화에 대한 필요성을 인식하지 못함
  • 상수를 적용하기 위해 인터페이스를 사용하는 것은 인터페이스를 남용하는 것입니다.그런 주장을 하는 사람들은 나쁜 습관을 가지고 있습니다.

    • "상수"가 계약으로 처리되어야 한다는 것을 알지 못합니다.그리고 인터페이스는 계약 준수를 시행하거나 예측하는 데 사용됩니다.
  • 미래에 인터페이스를 구현된 클래스로 변환하는 것은 불가능하지는 않더라도 어렵습니다.하....흠 ...???

    • 왜 당신의 지속적인 생계와 같은 프로그래밍 패턴에 참여하고 싶습니까?IOW, 왜 이렇게 양향적이고 나쁜 프로그래밍 습관에 전념합니까?

변명이 무엇이든, 인터페이스 상수의 사용을 불법화하거나 일반적으로 방해하는 근본적으로 효과적인 소프트웨어 엔지니어링에 관해서는 유효한 변명이 없습니다.

미국 헌법을 만든 건국의 아버지들의 원래 의도와 정신 상태가 어떠했는지는 중요하지 않습니다.우리는 건국의 아버지들의 원래 의도에 대해 토론할 수 있지만 내가 관심 있는 것은 미국 헌법의 서면 진술뿐입니다.그리고 미국 헌법의 기록되지 않은 건국 의도가 아닌 기록된 문학적 근본주의를 활용하는 것은 모든 미국 시민의 책임입니다.

마찬가지로, 나는 Java 플랫폼과 프로그래밍 언어 창시자의 "원래" 의도가 인터페이스에 대해 무엇을 가졌는지에 대해 관심이 없습니다.내가 관심을 갖는 것은 Java 사양이 제공하는 효과적인 기능이며, 책임감 있는 소프트웨어 프로그래밍의 기본 법칙을 충족하는 데 도움이 되도록 이러한 기능을 최대한 활용하려고 합니다."인터페이스에 대한 의도를 위반한다"고 인식되더라도 상관하지 않습니다.나는 Gosling이나 누군가 Bloch가 "Java를 사용하는 올바른 방법"에 대해 말하는 것에 관심이 없습니다. 그들이 말하는 것이 기본 사항을 효과적으로 충족하려는 나의 요구를 위반하지 않는 한입니다.

기본은 데이터 모델 정규화입니다

데이터 모델이 호스팅되거나 전송되는 방식은 중요하지 않습니다.데이터 모델 정규화의 필요성과 프로세스를 이해하지 못하는 경우 인터페이스, 열거형 또는 관계형 또는 비SQL 등 무엇을 사용하든 상관없습니다.

먼저 일련의 프로세스의 데이터 모델을 정의하고 정규화해야 합니다.그리고 일관성 있는 데이터 모델이 있을 때만 해당 구성 요소의 프로세스 흐름을 사용하여 기능적 동작을 정의하고 프로세스가 응용 프로그램 분야 또는 영역을 차단할 수 있습니다.그래야만 각 기능 프로세스의 API를 정의할 수 있습니다.

EF Codd가 제안한 데이터 정규화의 측면조차도 이제 심각한 어려움을 겪고 있습니다.예를 들어1NF에 대한 그의 진술은 특히 현대 데이터 서비스, 저장소 기술 및 전송의 출현에 대한 그의 나머지 진술과 마찬가지로 모호하고, 잘못 정렬되었으며, 지나치게 단순화되었다는 비판을 받았습니다.IMO에서는 EF Codd 진술을 완전히 폐기하고 수학적으로 더 그럴듯한 새로운 진술 세트를 설계해야 합니다.

EF Codd의 눈에 띄는 결함과 효과적인 인간 이해에 대한 잘못된 정렬의 원인은 인간이 인식할 수 있는 다차원, 가변 차원 데이터가 일련의 단편적인 2차원 매핑을 통해 효율적으로 인식될 수 있다는 그의 믿음입니다.

데이터 정규화의 기초

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;
  }
}

고려해야 할 인터페이스 상수와 관련된 유일한 문제는 인터페이스가 구현될 때입니다.

이것이 인터페이스의 "원래 의도"가 아닌가요?대법원이 미국 헌법의 서면 편지를 어떻게 해석할지보다는 미국 헌법을 제정할 때 건국의 아버지들의 "원래 의도"에 관심을 두는 것처럼 ???

결국 나는 자유의 땅, 야생의 땅, 용감한 자의 고향에 살고 있습니다.용감하고, 자유롭고, 열정적으로 인터페이스를 사용하세요.동료 프로그래머가 효율적이고 게으른 프로그래밍 수단을 사용하기를 거부하는 경우, 나는 그들의 프로그래밍 효율성에 맞춰 프로그래밍 효율성을 줄여야 한다는 황금률을 지켜야 합니까?아마도 그렇게 해야 할 것입니다. 그러나 그것은 이상적인 상황이 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top