Programing

열거 형 사용 및 유지를위한 모범 사례

crosscheck 2020. 10. 20. 07:20
반응형

열거 형 사용 및 유지를위한 모범 사례


내가 처리 할 수있는 가장 좋은 방법은 여기에 대해 몇 가지 질문 / 토론을 보이고 열거 같은 값을 유지 한 (예를 들어 열거 형에 적합한 지속 데이터를 , 어떻게 NHibernate에를 사용하여 열거를 유지하기 위해 ), 그리고 일반 consenus이 무엇인지 물어보고 싶습니다 .

특히:

  • 코드에서 이러한 값을 어떻게 처리해야합니까?
  • 데이터베이스에 어떻게 유지되어야합니까 (텍스트 / 숫자)?
  • 다른 솔루션의 장단점은 무엇입니까?

참고 :이 질문에 원래 포함 된 설명을 답변으로 옮겼습니다.


나는 당신이 말하는 많은 것에 동의합니다. 그러나 열거 형의 지속성에 대해 추가하고 싶은 한 가지는 : DB 값에서 빌드 할 때 열거 형을 생성하는 것이 허용되지 않는다고 생각하지만 런타임 검사가 좋은 솔루션이 아니라고 생각합니다. . 세 번째 방법을 정의하겠습니다. 데이터베이스에 대해 열거 형의 값을 확인하는 단위 테스트가 있습니다. 이것은 "인과적인"발산을 방지하고 코드가 실행될 때마다 데이터베이스에 대해 열거 형을 검사하는 오버 헤드를 방지합니다.


초기 기사는 괜찮아 보입니다. 그럼에도 불구하고 주석에 따르면 Java 열거 형에 대한 일부 주석은 몇 가지 사항을 명확히 할 수 있습니다.

Java의 Enum 유형은 정의에 따라 클래스이지만 다른 언어에서와 같이 "허용 된 값 목록"과 관련이 있기 때문에 많은 프로그래머가 이것을 잊어 버리는 경향이 있습니다. 그 이상입니다.

따라서 이러한 switch 문을 피하려면 enum 클래스에 일부 코드와 추가 메서드를 넣는 것이 합리적 일 수 있습니다. 별도의 "열거 형 실제 클래스"를 만들 필요가 거의 없습니다.

문서화의 요점도 고려하십시오-데이터베이스에서 열거 형의 실제 의미를 문서화 하시겠습니까? 값 (열거 형 유형)을 반영하는 소스 코드 또는 일부 외부 문서에서? 개인적으로 소스 코드를 선호합니다.

속도 나 어떤 이유로 든 데이터베이스에서 열거 형 값을 정수로 표시하려면 해당 매핑도 Java 열거 형에 있어야합니다. 당신은 기본적으로 문자열 이름 매핑을 얻게 될 것이고 나는 그것에 만족해 왔습니다. 각 열거 형 값과 관련된 서 수가 있지만이를 코드와 데이터베이스 간의 매핑으로 직접 사용하는 것은 그리 밝지 않습니다. 누군가 소스 코드의 값을 재정렬하면 서 수가 변경되기 때문입니다. 또는 기존 값 사이에 추가 열거 형 값을 추가합니다. 또는 일부 값을 제거합니다.

(물론 누군가가 소스 코드에서 열거 형의 이름을 변경하면 기본 문자열 매핑도 시시해 지지만 실수로 발생할 가능성은 적습니다. 필요한 경우 런타임 검사를 추가하여 더 쉽게 보호 할 수 있습니다. 여기에 이미 제안 된대로 데이터베이스의 제약 조건을 확인하십시오.)


나는 나의 이해를 요약하려고 노력했다. 수정 사항이 있으면 자유롭게 편집하십시오. 그래서 여기에 간다 :

코드에서

코드에서 열거 형은 언어의 기본 열거 형 유형 (적어도 Java 및 C #에서)을 사용하거나 "유형 안전 열거 형 패턴" 과 같은 것을 사용하여 처리해야합니다 . 일반 상수 (Integer 또는 유사)를 사용하는 것은 권장되지 않습니다. 유형 안전성을 잃어 버리기 때문입니다.

이 둘 사이의 선택은 열거 형에 추가 할 추가 기능의 양에 따라 다릅니다.

  • 열거 형에 많은 기능을 넣으려면 (항상 switch ()를 사용하지 않기 때문에 좋습니다) 일반적으로 클래스가 더 적합합니다.
  • 반면에 단순한 열거 형 값의 경우 언어의 열거 형이 일반적으로 더 명확합니다.

특히, 적어도 Java에서는 열거 형이 다른 클래스에서 상속 될 수 없으므로 수퍼 클래스에 넣고 싶은 유사한 동작을 가진 여러 열거 형이있는 경우 Java의 열거 형을 사용할 수 없습니다.

지속 형 열거 형

열거 형을 유지하려면 각 열거 형 값에 고유 한 ID를 할당해야합니다. 정수 또는 짧은 문자열 일 수 있습니다. 니모닉이 될 수 있으므로 짧은 문자열이 선호됩니다 (DBA 등이 db의 원시 데이터를 더 쉽게 이해할 수 있음).

  • 소프트웨어에서 모든 열거 형에는 열거 형 (소프트웨어 내부에서 사용)과 ID 값 (영구 용)간에 변환 할 매핑 함수가 있어야합니다. 일부 프레임 워크 (예 : (N) Hibernate)는이를 자동으로 수행하기위한 제한적인 지원을 제공합니다. 그렇지 않으면 열거 형 / 클래스에 넣어야합니다.
  • 데이터베이스는 (이상적으로) 유효한 값을 나열하는 각 열거 형에 대한 테이블을 포함해야합니다. 하나의 열은 PK 인 ID (위 참조)입니다. 예를 들어 설명에 추가 열이 의미가있을 수 있습니다. 해당 열거 형의 값을 포함 할 모든 테이블 열은이 "열거 형 테이블"을 FK로 사용할 수 있습니다. 이것은 부정확 한 열거 형 값이 결코 지속될 수 없음을 보장하고 DB가 "자체적으로 작동"할 수 있도록합니다.

이 접근 방식의 한 가지 문제는 유효한 열거 형 값 목록이 두 위치 (코드 및 데이터베이스)에 존재한다는 것입니다. 이것은 피하기가 어려우므로 종종 허용되는 것으로 간주되지만 두 가지 대안이 있습니다.

  • DB의 값 목록 만 유지하고 빌드시 enum 유형을 생성하십시오. 우아하지만 빌드를 실행하려면 DB 연결이 필요하므로 문제가있는 것 같습니다.
  • 코드에서 신뢰할 수있는 값 목록을 정의하십시오. 런타임시 (일반적으로 시작시) DB의 값을 확인하고 불일치시 불평 / 중단합니다.

C #에 대한 코드 처리에서 0 값을 정의하는 것을 놓쳤습니다. 나는 거의 틀림없이 항상 내 첫 번째 가치를 다음과 같이 선언합니다.

public enum SomeEnum
{
    None = 0,
}

따라서 null 값으로 사용됩니다. 백업 유형은 정수이고 정수의 기본값은 0이기 때문에 열거 형이 실제로 프로그래밍 방식으로 설정되었는지 여부를 아는 것은 많은 곳에서 매우 유용합니다.


Java 또는 C #은 항상 코드에서 열거 형을 사용해야합니다. 면책 조항 : 내 배경은 C #입니다.

값이 데이터베이스에 유지되는 경우 나중에 코드를 변경해도 변환 된 열거 형 값 및 응용 프로그램 동작이 실수로 변경되지 않도록 각 열거 형 멤버의 정수 값을 명시 적으로 정의해야합니다.

열거 형 이름 리팩토링으로부터 보호하기 위해 값은 항상 정수 값으로 데이터베이스에 유지되어야합니다. 위키의 각 열거에 대한 문서를 유지하고 유형을 문서화하는 위키 페이지를 가리키는 데이터베이스 필드에 주석을 추가하십시오. 또한 Intellisense를 통해 사용할 수 있도록 위키 항목에 대한 링크를 포함하는 열거 형 유형에 XML 문서를 추가합니다.

도구를 사용하여 CRUD 코드를 생성하는 경우 생성 된 코드 개체가 항상 열거 형 멤버를 사용하도록 열에 사용할 열거 형을 정의 할 수 있어야합니다.

열거 형 멤버에 사용자 지정 논리를 적용해야하는 경우 몇 가지 옵션이 있습니다.

  • 열거 형 MyEnum이있는 경우 스위치 문 또는 필요한 모든 수단을 통해 열거 형 멤버에 대한 추가 정보를 검색하는 유틸리티 메서드를 제공하는 정적 클래스 MyEnumInfo를 만듭니다. 클래스 이름의 열거 형 이름 끝에 "Info"를 추가하면 IntelliSense에서 서로 옆에있게됩니다.
  • 추가 매개 변수를 지정하려면 속성으로 열거 형 멤버를 장식하십시오. 예를 들어 열거 형 값으로 채워진 ASP.NET 드롭 다운을 만드는 EnumDropDown 컨트롤을 개발했으며 EnumDisplayAttribute는 각 멤버에 사용할 멋진 형식의 표시 텍스트를 지정합니다.

나는 이것을 시도하지 않았지만 SQL Server 2005 이상에서는 이론적으로 열거 정보를 포함하는 데이터베이스에 C # 코드를 등록하고 뷰 또는 기타 구문에서 사용하기 위해 값을 열거 형으로 변환하는 기능을 사용할 수 있습니다. DBA가 사용하기 쉬운 방식으로 데이터를 제공합니다.


enum의 텍스트 값을 데이터베이스에 저장하는 것은 추가 공간이 필요하고 검색 속도가 느리기 때문에 정수를 저장하는 것보다 선호되지 않습니다. 숫자보다 더 많은 의미가 있다는 점에서 가치가 있지만 데이터베이스는 저장을위한 것이고 프레젠테이션 레이어는 사물을 멋지게 보이게하기위한 것입니다.


글쎄, 내 경험에 비추어 볼 때 옵션을 (플래그로) 즉시 메서드 호출에 전달하는 것 이외의 다른 항목에 대해 열거 형을 사용하면 switch어느 시점 에서 -ing이 발생합니다.

  • If you are going to use the enum all over your code, then you might end up with code that is not so easy to maintain (the infamous switch statement)
  • Extending enums is a pain. You add a new enum item and end up in going through all of your code to check for all conditions.
  • With .NET 3.5, you can add extension methods to enums to make them behave a bit more like classes. However, adding real functionality this way is not so easy since it's still not a class (you would end up using switch-es in your extension methods if not elsewhere.

So for an enum-like entity with a bit more of functionality you should take some time and create it as a class, with several things in mind:

  • To make your class behave like an enum, you can either force each derived class to instantiate as a Singleton, or override Equals to allow value comparison of different instances.
  • If your class is enum-like, it should mean that it should contain no serializable state - deserialization should be possible from its type alone (a sort of an "ID", as you said).
  • Persistence logic should be confined to the base class only, otherwise extending your "enum" would be a nightmare. In case that you went for the Singleton pattern, you would need to ensure proper deserialization into singleton instances.

Each time you find your self using "magic numbers" in code change to enums. Besides time savings ( since magic will disappear when the bugs come ...) it will save your eyes and memory (meaningful enums make code more readable and self-documenting), since guess what - you are most probably the person to maintain and develop your own code


Imho, as for the code part:

You should always use the 'enum' type for your enumerations, basically you get alot of freebies if you do: Type safety, encapsulation and switch avoidance, the support of some collections such as EnumSet and EnumMap and code clarity.

as for the persistence part you can always persist the string representation of the enum and load it back using the enum.valueOf(String) method.


I know this is an old forum, what if the database might have other things integrating directly to it? E.g. when the resulting DB is the SOLE purpose of the code. Then, you will be defining the enums at every integration. Better then to have them in the DB. Otherwise, I agree with the original post.

참고URL : https://stackoverflow.com/questions/746812/best-practices-for-using-and-persisting-enums

반응형