상수를 어디에 두어야하고 왜합니까?


34

대부분의 대규모 응용 프로그램에서는 일반적으로 "상수"위치가 몇 군데 있습니다.

  • GUI 및 내부 상수에 대한 하나의 클래스 (탭 페이지 제목, 그룹 상자 제목, 계산 요소, 열거)
  • 데이터베이스 테이블 및 열에 대한 하나의 클래스 (이 부분은 코드가 생성됨)와 읽을 수있는 이름 (수동으로 할당 됨)
  • 응용 프로그램 메시지 (로깅, 메시지 상자 등)를위한 하나의 클래스

상수는 일반적으로 해당 클래스에서 다른 구조체로 분리됩니다. C ++ 애플리케이션에서 상수는 .h 파일에만 정의되며 값은 .cpp 파일에 지정됩니다.

장점 중 하나는 모든 줄 등이 하나의 중앙 위치에 있으며 모든 것이 무언가를 변경해야 할 때 찾을 위치를 알고 있다는 것입니다.

이것은 특히 사람들이 들어오고 갈 때 프로젝트 관리자가 좋아하는 것이므로 모든 사람이 응용 프로그램의 구조를 파지 않고도 사소한 것을 바꿀 수 있습니다.

또한 유사한 그룹 박스 / 탭 페이지 등의 제목을 한 번에 쉽게 변경할 수 있습니다. 또 다른 측면은 해당 클래스를 인쇄하여 프로그래머가 아닌 사람에게 제공하여 캡션이 직관적인지 여부와 사용자에게 보내는 메시지가 너무 상세하거나 혼동되는지 등을 확인할 수 있다는 것입니다.

그러나 특정 단점이 있습니다.

  • 모든 단일 클래스는 상수 클래스와 밀접하게 연결되어 있습니다.
  • 상수를 추가 / 제거 / 이름 바꾸기 / 이동하려면 응용 프로그램의 최소 90 %를 다시 컴파일해야합니다 (참고 : 값을 변경해도 C ++에서는 그렇지 않습니다). 1500 개의 클래스가있는 C ++ 프로젝트 중 하나에서 이는 약 7 분의 컴파일 시간 (사전 컴파일 된 헤더 사용, 약 50 분)과 특정 정적 라이브러리에 대한 약 10 분의 링크를 의미합니다.
  • Visual Studio Compiler를 통해 속도 최적화 릴리스를 빌드하는 데 최대 3 시간이 걸립니다. 엄청난 양의 계급 관계가 소스인지는 모르겠지만 그럴 수도 있습니다.
  • 무언가를 매우 빠르게 테스트하고 해당 테스트를 위해 15 분을 기다리지 않기 때문에 일시적으로 하드 코드를 코드로 직접 코드화해야합니다. 모든 사람은 "나중에 고칠 것"이라는 생각을 알고 있습니다.
  • 다른 프로젝트에서 클래스를 재사용하는 것이 항상 쉬운 것은 아닙니다 (주로 다른 단단한 커플 링으로 인해 상수 상수를 사용하는 것이 쉽지 않습니다).

그런 상수를 어디에 저장 하시겠습니까? 또한 위에 나열된 이점을 준수하는 더 나은 개념이 있음을 프로젝트 관리자에게 확신시키기 위해 어떤 주장을 제기 하시겠습니까?

C ++ 전용 또는 독립적 인 답변을 자유롭게 제공하십시오.

추신 : 나는이 질문이 주관적이라는 것을 알고 있지만 솔직히이 종류의 질문에 대해이 사이트보다 더 좋은 곳을 모릅니다.

이 프로젝트에서 업데이트

컴파일 시간에 대한 소식이 있습니다
.Caleb와 gbjbaanb의 게시물에 따라 시간이있을 때 상수 파일을 다른 여러 파일로 나눕니다. 또한 결국 내 프로젝트를 여러 라이브러리로 분할하여 훨씬 쉽게 할 수있었습니다. 이것을 릴리스 모드에서 컴파일하면 데이터베이스 정의 (테이블, 열 이름 및 8000 개 이상의 기호)를 포함하고 특정 해시를 빌드하는 자동 생성 파일이 릴리스 모드에서 컴파일 시간이 엄청나게 증가하는 것으로 나타났습니다.

DB 상수를 포함하는 라이브러리에 대한 MSVC의 옵티 마이저를 비활성화하면 릴리스 모드 에서 프로젝트 (여러 응용 프로그램)의 총 컴파일 시간을 최대 8 시간에서 1 시간 미만 으로 줄일 수있었습니다 !

아직 MSVC가 이러한 파일을 최적화하는 데 어려움을 겪는 이유를 아직 알지 못했지만, 이제는 더 이상 야간 빌드에만 의존 할 필요가 없기 때문에 이러한 변경으로 인해 많은 압박이 완화됩니다.

그 사실-그리고 덜 단단한 커플 링, 더 나은 재사용 성 등과 같은 다른 이점은 또한 "상수"를 나누는 데 시간을 보내는 것이 그렇게 나쁜 생각이 아니라는 것을 보여주었습니다. ;-)

업데이트 2

이 질문은 여전히 ​​주목을 받고 있기 때문에
지난 몇 년 동안 내가 한 일이 있습니다.

모든 상수, 변수 등을 관련 범위에 정확하게 넣으십시오. 단일 메소드에서만 상수를 사용하는 경우 해당 메소드에서 정의하는 것이 좋습니다. 단일 클래스에 관심이있는 경우 해당 클래스의 개인용 구현 세부 사항으로 두십시오. 네임 스페이스, 모듈, 프로젝트, 회사 범위에도 동일하게 적용됩니다. 또한 도우미 기능 등에 동일한 패턴을 사용합니다. (공개 프레임 워크를 개발하는 경우 100 % 적용되지 않을 수 있습니다.)

이렇게하면 재사용 성, 테스트 가능성 및 유지 관리 성이 향상되어 컴파일 시간 (적어도 C ++에서)이 줄어들뿐만 아니라 버그 수정에 더 적은 시간이 소요되므로 실제로 새로운 기능을 개발하는 데 더 많은 시간을 할애 할 수 있습니다. 동시에 더 많은 코드를 더 쉽게 재사용 할 수 있기 때문에 이러한 기능의 개발이 더 빨라집니다. 이것은 중앙 상수 파일이 가질 수있는 모든 이점보다 중요합니다.

더 자세히 알고 싶다면 특히 인터페이스 분리 원칙단일 책임 원칙을 살펴보십시오 .

동의한다면,이 업데이트는 기본적으로 그가 말한 것을 더 일반적으로 받아들이 기 때문에 Caleb의 대답을 찬성하십시오.


2
개인적으로 UI 제목이나 메시지 문자열을 상수로 사용하지 않았습니다. app.config
jk에 있습니다.

1
나는 당신이 지금하고있는 방식과 비슷합니다-당신의 단점을 이해하지만 우리는 그것을 처리해야 할 수도 있습니다.
bigtang

1
나는 큰 Java 프로젝트에서 정확히 같은 문제를 보았습니다 ... 하나의 거대한 "상수"인터페이스, 그 안에있는 것을 변경하고 일식이 다시 컴파일 될 때까지 15 분 동안 기다리십시오. 나는 Caleb과 함께 있습니다 : 상수를 사용하는 코드에 가깝게 자연적으로 속한 상수를 그룹화하십시오. 상수이기 때문에 별도로 유지하는 것은 쓸모없는 OCD 연습입니다.
Michael Borgwardt

타이트한 커플 링은 문제가되지 않습니다. 왜냐하면 실제로 원하는 것이기 때문입니다. 당신이 원하는 당신의 상수 파일에 하나의 변화는 소스 파일의 가능성이 많은 영향을 미칩니다. (물론 다른 문제도 있습니다).
gnasher729

@ gnasher729 많은 클래스가 동일한 상수를 사용하는 경우에만 해당됩니다. 클래스가 관련이없는 상수에 단단히 결합되기를 원하지 않습니다. 복사하거나 고립 된 테스트를 실행하지 않고 다른 프로젝트에서 재사용하려고 시도 할 때까지 처음에는 문제가되지 않을 수 있습니다.
Tim Meyer

답변:


29

클래스에 특정한 상수는 해당 클래스의 인터페이스에 있어야합니다.

실제로 구성 옵션 인 상수는 구성 클래스의 일부 여야합니다. 해당 클래스의 구성 옵션에 대한 접근자를 제공하고 다른 곳의 상수 대신 사용하는 경우 몇 가지 옵션을 변경할 때 전 세계를 다시 컴파일 할 필요가 없습니다.

클래스간에 공유되지만 구성 할 수없는 상수는 합리적으로 범위를 지정해야합니다. 개별 클래스가 실제로 필요한 것만 포함하도록 특정 용도의 파일로 분류하십시오. 이것은 다시 일부 상수를 변경할 때 컴파일 시간을 줄이는 데 도움이됩니다.


1
혹시 관심이 : 내가 달성 한 것과 내 질문을 업데이트, 당신의 대답 등 다음
팀 마이어

6

간단히 말하면 거대한 상수 클래스를 예를 들어 양식 당 하나씩 작은 파일로 나눕니다. 이렇게하면 상수 파일에 큰 의존성이 없어 지므로 문자열을 추가하거나 업데이트해도 전체 재 컴파일이 필요하지 않습니다. 이 파일들을 여전히 중앙 위치에 저장할 수는 있지만 (예를 들어) 각 대화 상자마다 상수가있는 파일이 하나 있습니다. 그런 다음 해당 대화 상자 파일에만 해당 파일을 포함시킬 수 있으므로 재 컴파일이 크게 줄어 듭니다.

또한 문자열을 처리하기 위해 GNU GetText 유틸리티와 같은 것을 사용하는 것이 좋습니다. 번역을 위해 설계되었지만 단순히 텍스트를 다른 것으로 변경하는 데에도 효과적입니다. 문자열 리소스에 넣을 수는 있지만 ID로 키를 입력하면 작업하기가 더 어려워지고 GetText 유틸리티는 원래 문자열로 키를 지정하므로 개발이 매우 쉽습니다.


나는 그 기회를 줄 수 있습니다. 제목 등이있는 상수 클래스가 여러 구조체로 나뉘어지면 구조체 당 하나의 클래스를 시작으로 할 수 있습니다. GNU에 대해서는 잘 모르지만 개발 시간 동안 런타임에 문자열을 변경하고 싶지 않습니다. 그러나 앞으로 다른 언어로 번역해야 할 경우를 대비하여 Qt의 번역 메커니즘을 사용하고 있습니다.
Tim Meyer

혹시 관심이 : 내가 달성 한 것과 내 질문을 업데이트, 당신의 대답 등 다음
팀 마이어

2

참고 : 나는 C ++ 개발자가 아니지만 여기에 내 생각이 있습니다. 구성 파일 사용의 차이점에 대한 @jk의 의견을 고려해야합니다. DotNet에는 이러한 정보를 저장하는 데 사용되는 리소스 파일이 있습니다. Windows Forms에서 리소스 파일은 각 양식에 대해 VS에서 유지 관리됩니다.

공유 해야하는 전역 상수가 아닌 한 상수 값이 사용 범위를 벗어나는 값을 볼 수 없습니다. 언급했듯이 최소한 개발 중에는 유지하기가 어렵습니다. 또한 이름 충돌이 발생할 수 있습니다. 또 다른 것은 주어진 상수를 사용하는 사람을 아는 것이 어려울 수 있다는 것입니다.

이제 프로그래머가 아닌 사용자가 정보를 검토하도록하려면 GUI의 경우 화면을 캡처하십시오. 데이터 테이블 항목을 검토하기 위해 데이터를 Excel 또는 이와 유사한 것으로 내보낼 수 있습니다.

중앙 집중식 위치 접근 방식을 계속 사용하고 모든 상수를 하나의 큰 파일에 배치하려는 경우 각 개발자는 각 간격의 끝에 업데이트 된 공유 파일을 중앙 파일로 사용할 수 있습니다. 데이터는 개발에 사용 된 개별 파일에서 가져옵니다. 이것은 쉽게 자동화하거나 수동으로 수행 할 수 있습니다. 그러나 내가 말했듯이 그것은 아마도 당신이 취할 필요가없는 위험 일 것입니다.


2

일반적인 해결책은 없습니다. 상수의 성능, 유용성, 보안 및 수명주기에 대해 스스로에게 물어보십시오.

범위에 가깝게 정의 될수록 성능이 높아집니다.

논리적으로 범위를 벗어나 그룹화할수록 재사용 성이 높아집니다.

비용이 많이 들수록 보안이 향상됩니다.

상수의 수명이 길수록 유용성에 대한 관심이 적습니다.

버전 번호와 같은 상수는 일종의 매니페스트에서 정의됩니다. 오류 함수의 오류 코드는 클래스 내에 정의됩니다. 오류 코드는 수명이 긴 것일 수 있습니다 (= 거의 변경되지 않음). 일정한 파일에 넣으면 불필요한 것들로 파일을 스팸으로 만듭니다.

상수는 상수의 문자가 적지 만 버전 번호와 같은 변수는 외부에 더 많이 넣을 수 있습니다. 상수가 적은 변수 일수록 상수가 클수록 범위 안에 더 많이 배치해야합니다. 디버깅하는 동안 컴파일 시간을 줄이기 위해 외부에 배치하는 것이 좋습니다.

그러나 초기 문제는 컴파일 시간입니다. 따라서 질문은 올바른 질문을하는지 여부입니다. 응용 프로그램의 컴파일 시간이 너무 긴 경우 부품이 서로 독립적으로 작동하도록 모듈화하는 방법을 더 잘 생각해야합니다. 부분적으로 컴파일하고 독립적으로 물건을 테스트하십시오. 단위 테스트가 제대로 수행되고 본격적으로 작동하면 (실제로 많은 작업), 걱정할 필요없이 쉽게 물건을 바꿀 수 있습니다. 그리고 질문은 완전히 다른 추진력을 얻습니다.


1

이 모든 상수를 일종의 구성 파일에 넣는 것이 좋습니다. Java 응용 프로그램의 경우 일반적으로 각 줄이 "(key) = (value)"형식의 간단한 텍스트 인 .properties 파일을 사용합니다. 예

MainPanel.Title = 응용 프로그램에 오신 것을 환영합니다
DB.table.users = TBL_USERS
logging.filename = 응용 프로그램 .log

그런 다음 런타임에이 파일을로드하고 키를 찾고 값을 다시 가져올 수있는 캐시를 채 웁니다. 상수가 필요할 때 캐시를 쿼리합니다. 여전히 어딘가에 키가 있어야하고 캐시에 전역 적으로 액세스 할 수 있어야하지만 상수 의 실제 을 변경하면 다시 컴파일 할 필요가 없으며 앱을 다시 시작하는 것이 가능해야합니다 (또는 당신은 정말 화려하고 .properties 파일과 캐시를 여러 개 가지고 있고 응용 프로그램이 런타임에 캐시를 다시로드 할 수있는 기능을 제공하려고합니다.

구현의 경우이 SO 질문을 발견했습니다 : https://stackoverflow.com/questions/874052/properties-file-library-for-c-or-c (Google 검색에서 처음으로 발견되었습니다. 실제로이 소프트웨어를 직접 사용했습니다).


C ++ 프로젝트의 경우 값을 변경하면 상수 파일 만 다시 컴파일하면됩니다. .cpp 파일에 값이 할당되어 있기 때문입니다. 그러나 여전히 필요로하는 전체 다시 / 이름 변경 상수를 이동 / 추가 / 제거
팀 마이어

@TimMeyer : 상수를 여러 파일로 분할하는 경우 상수를 추가 / 제거하면 해당 특정 파일에 종속 된 파일에만 영향을줍니다. 맞습니까?
FrustratedWithFormsDesigner

옳은. 가장 큰 문제는 내가 제안하면 사람들이 내가 "장점"으로 잃어버린 것들 중 하나를 잃어 버리는 경향이 있다는 것입니다.
Tim Meyer

그러나 실제로 여러 상수 파일을 같은 곳에 두는 것에 대해서는 생각하지 않았습니다.
Tim Meyer

+1. @Tim Meyer :이 목적을 위해 컴파일 타임 검사는 비용보다 훨씬 비쌉니다. 게다가 국제화가 필요한 경우 어떻게해야합니까?
케빈 클라인
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.