it-swarm-ko.tech

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

나는 이런 예를 보았다.

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

상수를 감싸기 위해 Constants 클래스를 가질 수 있다고 가정하고 static final로 선언합니다. 나는 자바를 전혀 안다. 이것이 상수를 만드는 가장 좋은 방법인지 궁금하다.

373
mk.

그것은 완벽하게 받아 들일 수 있습니다. 아마도 표준이 될 수도 있습니다.

(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)을 가리킨다.

403
jjnguy

나는 하나의 상수 클래스를 갖는 것에 반대 할 것을 강력히 권고한다. 당시에는 좋은 생각 인 것 같지만 개발자가 상수를 문서화하기를 거절하고 클래스가 서로 관련이없는 500 개의 상수를 포함하도록 성장하면 (응용 프로그램의 완전히 다른 측면과 관련됨)이 일반적으로 완전히 읽을 수없는 상수 파일이됩니다. 대신 :

  • Java 5+에 액세스 할 수있는 경우 enum을 사용하여 응용 프로그램 영역에 대한 특정 상수를 정의하십시오. 응용 프로그램 영역의 모든 부분은 이러한 상수에 대해 상수 값이 아닌 열거 형을 참조해야합니다. 클래스를 선언하는 것과 비슷한 enum을 선언 할 수 있습니다. 열거 형은 아마 Java 5+의 가장 유용한 (그리고, 틀림없이, 유일한) 유용한 기능입니다.
  • 특정 클래스 또는 해당 하위 클래스 중 하나에서만 유효하는 상수가있는 경우 해당 클래스를 protected 또는 public으로 선언하고 계층 구조의 최상위 클래스에 배치합니다. 이 방법으로 하위 클래스는 이러한 상수 값에 액세스 할 수 있습니다. 다른 클래스가 public을 통해 액세스하면 상수는 특정 클래스에만 유효하지 않습니다. 즉이 상수를 사용하는 외부 클래스가 정수를 포함한 클래스)
  • 비헤이비어가 정의 된 인터페이스가 있지만 반환 값이나 인수 값이 특수해야하는 경우 해당 인터페이스에서 상수를 정의하여 다른 구현자가 해당 인터페이스에 액세스 할 수 있도록 완벽하게 수용 할 수 있습니다. 그러나 상수를 보유하기위한 인터페이스를 만들지 마십시오. 단지 상수를 보유하기 위해 만든 클래스만큼 나빠질 수 있습니다.
235
MetroidFan2002

상수를 유지하기 위해 인터페이스를 사용하는 것은 BAD PRACTICE입니다 (Josh Bloch의 이름이 일정한 인터페이스 패턴 ). Josh가 조언하는 내용은 다음과 같습니다.

상수가 기존 클래스 또는 인터페이스에 강력하게 연결되어 있으면 클래스 또는 인터페이스에 추가해야합니다. 예를 들어 Integer 및 Double과 같은 모든 박스형 숫자 기본 클래스는 MIN_VALUE 및 MAX_VALUE 상수를 내 보냅니다. 상수가 열거 유형의 멤버로 가장 잘 보이는 경우 enum 유형으로 내 보내야합니다. 그렇지 않으면 상수가 아닌 유틸리티 클래스를 사용하여 상수를 내 보내야합니다.

예:

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

명명 규칙 정보 :

일반적으로 이러한 필드의 이름은 대문자로 구성되며 단어는 밑줄로 구분됩니다. 이러한 필드에는 기본 값 또는 변경 불가능한 객체에 대한 참조가 포함되어야합니다.

120
Marcio Aguiar

Effective Java (2nd Edition)에서는 상수에 정적 int 대신 enum을 사용하는 것이 좋습니다.

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

그 기사의 끝 부분에 제기 된 질문은 다음과 같다.

언제 열거 형을 사용해야합니까?

대답은 다음과 같습니다.

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

36
shelfoo

인터페이스 사용을 피하십시오.

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

public class NeddsConstant implements MyConstants {

}

그것은 유혹이지만, 캡슐화에 위배되며 클래스 정의의 구별을 모호하게합니다.

21
stimpy

나는 다음 접근법을 사용한다.

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를 사용하면 상수가됩니다. 그것은 나를 위해 "객체 지향적으로"더 보입니다.

19
albus.ua

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

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

이들을 상수로 생각하는 대신 구성 매개 변수로 생각하고 매개 변수를 관리하는 클래스를 만듭니다. 값을 비 최종적인 것으로하고 getter 사용을 고려해보십시오. 앞으로 이러한 매개 변수 중 일부는 실제로 사용자 또는 관리자가 구성 할 수 있어야한다고 결정할 때 훨씬 쉽게 수행 할 수 있습니다.

17
Kevin Day

당신이 할 수있는 가장 큰 실수는 Constants와 같은 일반적인 이름으로 불리는 전역 적으로 접근 가능한 클래스를 만드는 것입니다. 이것은 단순히 쓰레기로 흩어지며 시스템의 어느 부분이 이러한 상수를 사용하는지 알 수있는 모든 능력을 잃습니다.

대신, 상수는 그것들을 "소유"하는 클래스에 들어가야한다. TIMEOUT이라는 상수가 있습니까? 그것은 아마도 귀하의 Communications () 또는 Connection () 클래스로 이동해야합니다. MAX_BAD_LOGINS_PER_HOUR? 사용자 ()로 이동하십시오. 등등.

런타임시 "상수"를 정의 할 수 있지만 사용자가 쉽게 변경할 수없는 경우 Java .properties 파일을 사용할 수 있습니다. 이것들을 .jars에 패키지화하고 Class resourceLoader로 참조 할 수 있습니다.

13
Yann Ramin

그것이 올바른 길입니다.

일반적으로 상수는 발견되지 않기 때문에 별도의 "상수"클래스에 not 보관됩니다. 상수가 현재 클래스와 관련이 있으면 해당 클래스를 유지하면 다음 개발자에게 도움이됩니다.

6
Jason Cohen

나는 인터페이스를 사용하는 것이 최선의 방법이 아니라는 것에 동의한다. 이 패턴을 피하는 것은 심지어 Bloch의 Effective Java 에서 자체 항목 (# 18)을 사용합니다.

Bloch가 상수 인터페이스 패턴에 대해하는 인수는 구현 세부 사항이지만 상수 사용은 인터페이스를 구현하여 내 보낸 API에서 해당 구현 세부 사항을 노출합니다.

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

상수를 열거 형으로 잘 모델링 할 수 있다면 1.5 이상에서 사용할 수있는 enum structure를 고려하십시오.

1.5 이전 버전을 사용하고 있다면 일반 Java 클래스를 사용하여 typesafe 열거 형을 계속 풀 수 있습니다. (자세한 내용은 이 사이트 를 참조하십시오).

5
Rob Dickerson

열거 형은 어떻습니까?

5
Sébastien D.

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

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

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

5
big_peanut_horse

위의 주석을 기반으로 이것은 구식 글로벌 상수 클래스 (public static final 변수를 가짐)를 다음과 같은 방식으로 열거 형으로 변경하는 좋은 방법이라고 생각합니다.

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
4
Lorand Bendig

좋은 객체 지향 설계는 많은 공개 상수가 필요하지 않아야합니다. 대부분의 상수는 작업을 수행하는 데 필요한 클래스에 캡슐화되어야합니다.

3
Bradley Harris

이에 대한 답변은 어느 정도의 의견이 있습니다. 우선, 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
2
djangofan

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 Integer_ 대 enum

열거 형 사용법은 실제로 강력하게 고려할 수있는 방법입니다.
Enums는 String 또는 Integer 상수 필드보다 큰 이점이 있습니다.
더 강력한 컴파일 제약 조건을 설정했습니다. 열거 형을 매개 변수로 사용하는 메서드를 정의하면 열거 형 클래스에 정의 된 열거 형 값 (또는 null) 만 전달할 수 있습니다.
String 및 Integer를 사용하면 호환되는 유형의 값으로 대체 할 수 있으며 값이 _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 매개 변수에 열거 형 값만 전달할 수 있으므로 검사가 필요하지 않습니다.

예를 들어, 여기 열거 형 클래스에 정의 된 두 개의 값 (따라서 상수) :

_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 클래스에 의존합니다. 따라서 상수를 쉽게 찾을 수 있으며 EPI이 매우 자연스럽게 정의 된 위치를 기억할 수도 있습니다.

응용 프로그램에 상수 값과 매우 구체적이고 강력한 기능적 응집력을 가진 기존 클래스가 포함되어 있지 않으면 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 등의 클래스를 사용하며 실제로 열거 형을 보유하는 데 적합한 클래스는 없습니다.

2
davidxxx

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

1
Tim Howland

차이점은 무엇입니까?

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를 사용합니다. 둘 다 같아요.

1
chandrayya

하나의 일반적인 상수 클래스는 나쁜 생각입니다. 상수는 가장 논리적으로 관련된 클래스와 함께 그룹화되어야합니다.

어떤 종류의 변수 (특히 enum)를 사용하는 대신 메서드를 사용하는 것이 좋습니다. 변수와 동일한 이름의 메소드를 작성하고 변수에 지정한 값을 리턴하게하십시오. 이제 변수를 삭제하고 모든 참조를 방금 작성한 메소드 호출로 바꿉니다. 상수가 충분히 일반적인 것 같아서 사용하기 위해 클래스의 인스턴스를 만들지 않아도된다면 상수 메서드를 클래스 메서드로 만듭니다.

1
ab

모든 유형의 상수는 클래스 내에서 (즉, final 수정자를 가진 멤버 변수 인) 불변의 속성을 생성하여 선언 할 수 있습니다. 일반적으로 staticpublic 수정 자도 제공됩니다.

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

상수의 값이 선택 항목의 n-Tuple (예 : 열거 )에서 선택을 나타내는 많은 응용 프로그램이 있습니다. 이 예에서는 가능한 할당 값 (예 : 향상된 type-safety )을 제한하는 열거 형을 정의하도록 선택할 수 있습니다.

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

저는 상수와 같은 클래스를 케케 묵과는 다른 것으로 부르지 않을 것입니다 ... 나는 최소한 하나의 클래스 인 "Settings"또는 "Values"또는 "Constants"를 가지게 될 것입니다. 모든 상수가 살 것입니다. 많은 수가있는 경우 논리 상수 클래스 (UserSettings, AppSettings 등)로 그룹화합니다.

0
Joel Martinez

static final 내 환경 설정, 항목을 실제로 열거 할 수있는 경우에만 enum 사용하고 싶습니다.

0
wulfgarpro

기본적인 그라운드 제로 근본주의를 이해하지 않고 조슈아 블로흐를 인용하는 것은 나쁜 습관과 끔찍한 괴롭힘 연습 입니다.

나는 Joshua Bloch도 읽지 않았다.

  • 그는 끔찍한 프로그래머입니다
  • 또는 내가 지금까지 인용 한 사람들 (여호수아는 내가 추정하는 소년의 이름이다)은 단순히 소프트웨어를 종교적 방종을 정당화하기 위해 종교적 대본으로 사용하고있다.

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

  • 당신의 모든 마음과 마음으로 기본 정체성을 사랑하십시오
  • 이웃을 자신처럼 사랑하십시오

소프트웨어 엔지니어링의 근본주의는 다음과 같이 요약 될 수 있습니다.

  • 모든 프로그래밍 능력과 마음으로 그라운드 제로 기본에 자신을 헌신
  • 동료 프로그래머의 우수성을 위해 최선을 다하십시오.

또한 성서적 근본 주의자들 사이에서 강력하고 합리적인 견해가 도출된다

  • 먼저 자신을 사랑하십시오. 당신이 자신을 많이 사랑하지 않는다면, "당신의 이웃을 당신 자신처럼 사랑한다"라는 개념은 "무엇을 당신 자신을 사랑 하느냐"가 다른 사람들을 사랑할 데이텀 라인이기 때문에 많은 무게를 갖지 않습니다.

마찬가지로, 자신을 프로그래머로 존중하지 않고 기본에 대해 의문을 제기하지 않고 프로그래밍 전문가의 선언과 예언을 받아들이면 Joshua Bloch (및 기타)에 대한 인용과 의존은 의미가 없습니다. 그러므로, 당신은 실제로 동료 프로그래머를 존중하지 않을 것입니다.

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

  • 게으름은 좋은 프로그래머의 미덕이다
  • 당신은 프로그래밍 생활을 쉽고, 게으 르며, 가능한 한 효율적으로 만들어야한다
  • 귀하는 귀하와 함께 일하고 귀하의 프로그래밍 창업자를 데리러가는 귀하의 프로그래머가 가능한 한 쉽고, 게으 르며, 귀하의 프로그램의 결과를 가능한 한 쉽고 게으르게해야합니다.

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

이 종교 칙령은 근본적으로 효과적이고 책임감있는 프로그래밍 법에 따라 어떻게됩니까?

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

  • Whatif-No IDE? 소프트웨어 프로그래머로서 누가 지구상에서 IDE를 사용하지 않겠습니까? 우리 대부분은 IDE 사용을 피하면서 마치 초자연적 생존주의를 증명할 필요가없는 프로그래머입니다.

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

    • 데이터 모델 정규화를 알지 못하고 필요
  • 상수를 적용하기 위해 인터페이스를 사용하는 것은 인터페이스를 남용합니다. 그러한 지지자들은 나쁜 습관을 가지고있다

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

    • 왜 지속적인 생계와 같은 프로그래밍 패턴에 참여하고 싶습니까? IOW, 왜 그런 주변 환경과 나쁜 프로그래밍 습관에 헌신합니까?

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

미국 헌법을 만들었던 건국의 아버지들의 원래 의도와 정신 상태는 중요하지 않습니다. 우리는 건국의 아버지들의 원래 의도에 대해 토론 할 수 있었지만 제가 관심을 갖는 것은 미국 헌법의 서면 진술입니다. 그리고 미국 헌법의 문서화 된 근본 의도가 아닌 문학적 문학적 근본주의를 착취하는 것은 모든 미국 시민의 책임입니다.

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

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

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

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

EF Codd가 제안한 데이터 정규화의 양상조차도 이제는 심각한 도전에 직면하고 있습니다. 예 : 1NF에 대한 그의 진술은 특히 현대 데이터 서비스, 저장소 기술 및 전송의 출현에 관한 그의 진술의 나머지 부분과 같이 모호하고 잘못 정렬되어 지나치게 단순화 된 것으로 비난 받았다. IMO, EF Codd 문은 완전히 빠져 나와야하며 수학적으로 그럴듯한 새 문을 디자인해야합니다.

EF 코드의 눈부신 결함과 효과적인 인간 이해에 대한 오정렬의 원인은 인간이인지 할 수있는 다차원의 가변 치수 데이터가 일련의 단편적인 2 차원 맵핑을 통해 효율적으로 인식 될 수 있다는 그의 신념이다.

데이터 정규화의 기초

EF Codd가 표현하지 못한 것.

각각의 코 히어 런트 데이터 모델 내에서, 이들은 순차적으로 단계적으로 데이터 모델 코 히어 런스를 달성하기 위해 순서대로 정렬된다.

  1. 데이터 인스턴스의 통일성과 정체성.
    • 각 데이터 구성 요소의 세분성을 설계하여 세분성을 구성 요소의 각 인스턴스를 고유하게 식별하고 검색 할 수있는 수준으로 설정합니다.
    • 인스턴스 별칭이 없습니다. 즉, 식별이 구성 요소의 둘 이상의 인스턴스를 생성하는 수단이 존재하지 않습니다.
  2. 인스턴스 누화가 없습니다. 구성 요소의 인스턴스를 식별하는데 기여하기 위해 구성 요소의 하나 이상의 다른 인스턴스를 사용할 필요가 없다.
  3. 데이터 구성 요소/차원의 통일성과 정체성.
    • 구성 요소 디 앨리어싱의 존재. 구성 요소/치수를 고유하게 식별 할 수있는 하나의 정의가 있어야합니다. 구성 요소의 기본 정의는 다음과 같습니다.
    • 여기서 1 차 정의는 의도 된 구성 요소의 일부가 아닌 부분 치수 또는 구성원 구성 요소를 노출시키지 않을 것;
  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 프로그래머는 항아리의 구조에 신경 쓰지 않습니다.

이것은 osgi-motivated 런타임 스와핑에 복잡성을 제공합니까? Osgi는 프로그래머가 나쁜 습관을 계속 유지할 수있는 매우 효율적인 수단입니다. osgi보다 더 나은 대안이 있습니다.

아니면 왜 안됩니까? 비공개 상수가 공개 된 계약으로 유출되지 않습니다. 상수를 검색 할 필요가없고 "private final String"을 반복적으로 입력하기에는 너무 게으 르기 때문에 모든 개인 상수는 "Constants"라는 개인 인터페이스로 그룹화해야합니다.

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

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

이것이 인터페이스의 "원래 의도"가 아닙니까? 내가 대법원이 미국 헌법의 서면 서한을 해석하는 방법보다는 미국 헌법을 만들 때 건국의 아버지들의 "원래 의도"에 관심이있는 것처럼 ???

결국, 나는 자유의 땅, 용감한 집과 야생의 집에서 산다. 용감하고, 자유롭고, 강렬하다-인터페이스를 사용하십시오. 동료 프로그래머가 효율적이고 게으른 프로그래밍 수단을 사용하지 않으면 프로그래밍 규칙을 따라야하는 프로그래밍 효율을 낮추는 황금률이 ​​적용됩니까? 아마도 내가해야하지만 이상적인 상황은 아닙니다.

0
Blessed Geek

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

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

그러나 그것을 구현하지 마십시오. 완전한 클래스 이름을 통해 코드에서 직접 참조하십시오.

0
Andrew Harmel-Law

저는 static final를 사용하여 상수를 선언하고 ALL_CAPS 명명 표기법을 사용합니다. 모든 상수가 인터페이스로 묶여있는 실제 인스턴스를 꽤 많이 보았습니다. 몇 가지 게시물은 올바르지 않게 나쁜 습관을 부른 바 있습니다. 그 이유는 인터페이스가 필요한 것이 아니기 때문입니다. 인터페이스는 계약을 강제해야하며 무관 한 상수를 넣을 장소가되어서는 안됩니다. 상수의 의미가 특정 클래스에 속하지 않으면 (개인 생성자를 통해) 인스턴스화 할 수없는 클래스에 함께 넣어도 좋습니다. es). 나는 그것이 가장 관련이있는 클래스에 항상 상수를 두었습니다. 왜냐하면 그것은 의미가 있으며 쉽게 유지할 수 있기 때문입니다.

열거 형은 값의 범위를 나타내는 좋은 선택이지만, 절대 값 (예 : TIMEOUT = 100 ms)을 강조하는 독립형 상수를 저장하는 경우 static final 접근 방식을 사용할 수 있습니다.

0
bincob

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

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


}
0
mmansoor

대부분의 내용에 동의합니다. 상수 컬렉션을 처리 할 때 enum을 사용하는 것이 가장 좋습니다. 그러나 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 주석은 단순한 방법으로 enum보다 우수합니다. 단순히 컴파일 타임 마커이므로 공간이 훨씬 적습니다. 클래스가 아니며 자동 문자열 변환 속성도 없습니다.

0
Quinn Turner

내가하는 일 중 하나는 상수 값으로 '전역'클래스를 만들고 상수에 대한 액세스가 필요한 클래스에서 정적 가져 오기를 수행하는 것입니다.

0
Javamann