단일 문자 상수가 리터럴보다 낫습니까?


127

나는 최근에 거의 모든 단일 문자를 상수로 제공하는 클래스를 만났다. 에 이르기 COMMA까지 BRACKET_OPEN. 이것이 필요한지 궁금합니다. 단일 문자 리터럴을 상수로 가져 오는 것이 도움이 될 수 있음을 나타내는 "기사" 를 읽었습니다 . 그래서 저는 회의적입니다.

상수 사용의 주요 장점은 변경이 필요할 때 유지 관리를 최소화한다는 것입니다. 그러나 ','과 다른 기호를 사용하여 쉼표를 나타내려면 언제 시작해야합니까?

리터럴 대신 상수를 사용하는 유일한 이유는 코드를 더 읽기 쉽게하기 위해서입니다. 그러나 city + CharacterClass.COMMA + state(예를 들어)는 실제로보다 읽기 쉽습니다 city + ',' + state.

나를 위해 단점은 장점보다 중요합니다. 주로 다른 클래스와 다른 수입품을 소개합니다. 그리고 가능한 한 적은 코드를 믿습니다. 그래서 나는 일반적인 합의가 무엇인지 궁금합니다.



33
흠 ... 그것은 다른 로케일에 유용 할 수 있습니다. 예를 들어, 일부 언어는 guillements (각도 시세, 사용 «»인용 부호 대신 영어의 표준) "(또는 더 좋은 - 찾고 ). 그 외에도, 그것은 마치 마술 같은 캐릭터처럼 들립니다. 두 인스턴스 가정 CharacterClass전화를 englishChars하고 frenchChars, 그 가능성이 englishChars.LEFT_QUOTE있을 때, frenchChars.LEFT_QUOTE수 있습니다 «.
Justin Time

4
쉼표에는 다양한 변형이 있습니다. en.wikipedia.org/wiki/Comma#Comma_variants- 아마도 소스 코드를 utf-8로 인코딩 할 수있는 경우에는 어리석은 아이디어가 아닙니다.
Aaron Hall

21
귀하의 경우에는 변수 "숫자"를 호출하는 것과 같습니다. 상수는 DELIMITER라고합니다. 또는 CITY_STATE = "{0}, {1}"
이어야합니다.

13
당신이 연결 한 기사는 매우 끔찍합니다. 상수는 그런 버킷에 버리지 않아야합니다. 컨텍스트가있는 클래스에 배치하십시오. 본질적으로 상수가있는 클래스는 상수가 사용되는 컨텍스트를 제공합니다. 예를 들어, Java 's File.separator입니다. 클래스는 구분자 유형을 알려줍니다. 명명 된 클래스가 Consts있거나 Constants컨텍스트를 제공하지 않고 상수를 올바르게 사용하기가 어렵습니다.

답변:


184

타우 톨 로지 :

이 질문이 마법의 숫자를 제거 하는 것과 같은 적절한 용도에 관한 것이 아니라는 것이 끔찍한 어리석은 어리석은 일관성에 관한 것입니다 . 이 답변은 무엇을 다루고 있습니까?

상식은 시스템에 유지 관리 및 복잡성 외에 아무것도 추가 const char UPPER_CASE_A = 'A';하거나 알려주지 const char A = 'A'않습니다. const char STATUS_CODE.ARRIVED = 'A'다른 경우입니다.

상수 는 런타임에 변경할 수없는 것을 나타내지 만 나중에 컴파일 타임에 수정해야 할 수도 있습니다. 언제가 const char A =아닌 다른 것이 올바르게 A됩니까?

당신이 보는 경우 public static final char COLON = ':'자바 코드에서, 그것을 쓴 사람 누구에게나 찾아 자신의 키보드를 휴식. 당신의 표현이 COLON계속 바뀌면 :유지 보수의 악몽이 생길 것입니다.

난처:

누군가가 그것을 COLON = '-'사용하는 -곳 이 대신 어디에나 필요 하기 때문에 그것을 바꾸면 어떻게됩니까 ? 기본적으로 assertThat(':' == COLON)모든 단일 const참조에 대해 변경되지 않는지 확인 하는 단위 테스트를 작성 하시겠습니까? 시험을 변경할 때 누군가 가 시험을 고치 도록 하기 위해서만 ?

누군가가 실제로 public static final String EMPTY_STRING = "";유용하고 유익 하다고 주장한다면 , 당신은 그들의 지식을 인정하고 다른 모든 것에서 안전하게 무시합니다.

이름이 지정된 버전으로 모든 인쇄 가능한 문자를 사용할 수 있다는 것은 누가 그것을했는지에 상관없이 감독되지 않은 코드를 작성할 자격이 없음을 보여줍니다.

응집력:

또한 인공적으로 응집력을 떨어 뜨립니다. 왜냐하면 그것들은 그것을 사용하고 관련있는 것들로부터 멀어지기 때문입니다.

컴퓨터 프로그래밍에서, 응집력은 모듈의 요소들이 서로 속하는 정도를 의미합니다. 따라서 응집성은 주어진 모듈 내의 기능들 간의 관계 강도를 측정합니다. 예를 들어, 응집력이 높은 시스템에서 기능은 밀접한 관련이 있습니다.

커플 링:

또한 많은 관련없는 클래스를 결합합니다. 모두 실제로 수행하는 것과 관련이없는 파일을 참조하기 때문입니다.

긴밀한 결합은 클래스 그룹이 서로에 크게 의존하는 경우입니다. 이 시나리오는 수업이 너무 많은 책임을 맡거나 하나의 관심사가 자체 수업이 아닌 많은 수업에 퍼져있을 때 발생합니다.

당신이 사용하는 경우 더 좋은 이름을 같은 DELIMITER = ','이름이 일반적이며, 어떤 의미를 전달하지 않기 때문에 당신은 여전히 같은 문제가있다. 값을 다시 할당해도 리터럴을 검색하고 바꾸는 것보다 영향 분석을 수행하는 데 도움이되지 않습니다 ','. 어떤 코드가 그것을 사용하고 ,다른 코드가 필요하지만 ;지금 필요 하기 때문에? 여전히 모든 사용을 수동으로보고 변경해야합니다.

야생에서:

최근 1,000,000+ LOC에 18 세였던 애플리케이션을 리팩터링했습니다 . 그것은 같은 것들을 가졌습니다 public static final COMMA = SPACE + "," + SPACE;. " , "필요한 곳을 단순히 인라인 하는 것 보다 낫지 는 않습니다.

가독성 을 주장 하려면 whitespace문자를 볼 수있는 곳에 문자 를 표시하도록 IDE를 구성하는 방법을 배워야합니다 . 이는 시스템에 엔트로피를 도입하는 매우 게으른 이유입니다.

또한 여러 패키지와 클래스에서 ,단어의 철자가 틀리면서 여러 번 정의 COMMA되었습니다. 코드에서 모든 변형에 대한 참조가 혼합되어 있습니다. 완전히 무관 한 것을 깨뜨리지 않고 무언가 를 시도하고 고치는 것은 악몽 일뿐입니다.

알파벳과 같은 여러가 있었다 UPPER_CASE_A, A, UPPER_A, A_UPPER대부분의 시간에 동일한 있다고 A 하지만, 어떤 경우에는하지 않았다 . 거의 모든 캐릭터에 해당하지만 모든 캐릭터에 적용되는 것은 아닙니다.

그리고 편집 기록에서 18 년 동안이 중 하나가 편집되거나 변경된 것으로 보이지 않았습니다. 이제 분명한 이유는 추적 할 수없는 너무 많은 것들을 깨뜨릴 수 있기 때문에 새로운 변수가 있습니다. 같은 이유로 변경 될 수없는 같은 것을 가리키는 이름.

이 관행이 아무 것도하지 않고 최대 엔트로피에서 시작한다고 주장 할 수는 없습니다.

나는이 모든 혼란을 리팩토링하고 모든 긴장을 인라인했으며 새로운 대학 채용은이 const참조가 실제로 지적한 여러 수준의 간접적 인 길을 찾아 낼 필요가 없었기 때문에 훨씬 생산적 이었습니다. 그들이 무엇을 포함했는지.


112
어쩌면 반례를 추가해야 const char DELIMITER = ':'할 수도 있습니다. 실제로 유용 할 것입니다.
Bergi

115
나는 EMPTY_STRING유익한 몇 가지 주장을 할 것이다 . (1)의 모든 용도를 EMPTY_STRING찾을 수있는 것보다 파일에서 모든 용도를 훨씬 쉽게 찾을 수 있습니다 "". (2) 내가 볼 때 EMPTY_STRING개발자가 문자열을 비우려고 의도했으며 나중에 제공 할 문자열이 잘못 편집되거나 자리 표시자가 아니라는 것을 알고 있습니다. 이제, 당신은 내가 당신이 내 지식을 인정받을 수 있다고 주장하면서 영원히 나를 무시해도된다고 주장합니다. 내 지식을 어떻게 인정합니까? 그리고 내 조언을 영원히 무시할 계획입니까? 어느 쪽도 문제가 없습니다.
Eric Lippert

39
@immibis : 변화 관리의 맥락에서 유용한 것들에 대해 생각하지 않아도됩니다. 그들은 상수입니다. 그들은 변하지 않습니다. 인간이 코드의 의미를 검색하고 이해하는 맥락에서 그것들을 유용하다고 생각하십시오 . 키-값 쌍 구분 기호가 무엇 인지 아는 것이 콜론임을 아는 것보다 훨씬 유용합니다. 그것은 구문이 아니라 프로그램의 관심 의 의미 론적 도메인 에 관한 사실 이다.
Eric Lippert

15
@EricLippert : 나는 여기에 다른 사람들의 요점을보고 있습니다. const제공하는 것이 보장한다는 것은 런타임에 (컴파일 후) 변경되지 않는다는 것입니다.하지만 의미의 의미 const는 변경 관리 도구로 사용하는 것보다 훨씬 중요합니다. 즉, const EARLIEST_OS_SUPPORTED의미 론적으로 일관성이있을뿐만 아니라 프로그램이 발전하고 오래된 균열이 제거됨에 따라 시간이 지남에 따라 변경 될 것이라고 확신 할 수 있습니다.
Robert Harvey

16
@DanielJour : 그럼 이것은 세번째 주장입니다 EMPTY_STRING; 잘 설계된 IDE는이 엔티티를 구문 적으로보다는 상징적으로 취급 할 수있는 도구를 제공 할 것입니다. IDE 아래에있는 코드 분석 도구 라이브러리 를 사용하면 기호 수준에서 코드 정확성 대한 고급 프로그래밍 분석을 수행 할 수 있습니다 . 문자 그대로 40 년 전에 작성된 도구보다 더 진보 된 도구를 활용하려는 개발자는 고급 도구의 보상을 얻기 위해 습관을 조금만 변경하면됩니다.
Eric Lippert

145

상수 사용의 주요 장점은 변경이 필요할 때 유지 관리를 최소화한다는 것입니다.

절대적으로하지. 이다 전혀없는 때문에 상수를 사용하는 이유 상수가 정의에 의해 변경되지 않습니다 . 상수가 변하면 상수 가 아니 었습니까?

상수를 사용한다는 호소는 변경 관리와 관련이 없으며 사람들이 프로그램을 작성, 이해 및 유지 관리 할 수 ​​있도록하는 것과 관련이 있습니다. 콜론이 URL 구분 기호로 사용되는 프로그램의 모든 곳을 알고 싶다면 상수 URLSeparator를 정의하는 규칙이 있으면 쉽게 알 수 있으며 grep 해야하는 경우 쉽게 알 수 없습니다. 기본 클래스, 연산자 또는 기타 를 나타내는 데 사용되는 :코드의 모든 단일 위치를 가져옵니다 .:?:

나는 이것이 무의미한 시간 낭비라는 다른 답변에 완전히 동의하지 않습니다. 명명 된 상수 는 프로그램 에 의미 를 부여하며, 이러한 의미는 프로그램을보다 깊이 이해하고보다 효과적으로 유지하기 위해 인간과 기계 모두에서 사용될 수 있습니다.

여기서 트릭은 상수를 피하는 것이 아니라 구문 속성이 아닌 시맨틱 속성 으로 이름을 지정하는 것입니다 . 상수는 무엇에 사용됩니까? 프로그램의 비즈니스 영역이 타이포그래피, 영어 구문 분석 등이 아니면 호출하지 마십시오 . 그 의미를 명확하게하기 위해 그것을 또는 그와 같은 것으로 부릅니다 .CommaListSeparator


42
여기서 말하는 내용의 정신에 동의하지만 두 번째 / 세 번째 문장은 실제로 정확하지 않습니다. 상수는 파일 버전간에 변경 될 수 있습니다. 실제로, 내가 작성하는 대부분의 프로그램 MY_VER은와 같은 이름의 상수를 가지고 있으며 , 여기에는 프로그램의 현재 버전 번호가 포함되어 있으며, "5.03.427.0038"과 같은 마술 문자열이 아닌 나머지 프로그램 전체에서 사용될 수 있습니다. 추가 혜택은 의미 정보가 제공되었다는 것입니다.
Monty Harder

50
공평하게 말하면 상수의 요점은 초기화 후에 런타임 동안 변경되지 않고 컴파일 사이에서 변경되지 않는다는 것입니다. 컴파일러의 관점에서 볼 때 컴파일러가 프로그램을 수정할 수 없다고 가정 할 수 있다는 것이 핵심입니다. 프로그래머가 재 컴파일 할 때이를 수정할 수 있는지 여부는 상수를 변경하지 않습니다. 소프트웨어가 하드웨어에서 읽기 전용 값을 가져 오는 경우도있을 수 있습니다 const volatile T*. 프로그램은 변경할 수 없지만 하드웨어는 변경할 수 있습니다.
Justin Time

6
@MontyHarder : 좋은 지적입니다. 필자는 평상시 변하지 않는 상수와 한 번만 할당 할 수있는 변수를 구분하는 언어를 사용한다는 사실을 알고 있으며, 버전마다, 실행마다 또는 기타로 변경 될 수 있습니다. 상수와 변수는 다릅니다. 하나는 동일하게 유지되고 하나는 시간이 지남에 따라 변합니다.
Eric Lippert

7
@SteveCox : 동의합니다. C / C ++가 "const"를 특징 짓는 방식은 이상하고 제한적으로 사용됩니다. 상수를 원하는 속성은 값이 변경되지 않고 일부 함수에서는 변경되지 않지만 다른 함수에서는 변경되지 않는다는 것입니다.
Eric Lippert

15
상수가 정의에 따라 변하지 않기 때문에 상수를 사용해야하는 이유는 전혀 없다. 상수가 변하면 상수가 아니 었는가?” 컴파일 타임에 상수를 변경하는 것은 (런타임이 아닌) 완전히 정상입니다. 그렇기 때문에 처음에 "사물"이라고 명확하게 표시 한 것입니다. 물론, 영업 이익의 정수는 정크하지만, 같은 생각 const VERSION='3.1.2'하거나 const KEYSIZE=1024또는 무엇 이건.
AnoE

61

아니, 그건 바보 야

현지화를 위해 반드시 바보 같은 것은 아닙니다 . 예를 들어, 천 단위 구분 기호 미국에서는 쉼표 (1,000,000)이지만 다른 로케일에서는 쉼표가 아닙니다 . 쉼표가 아닌 적절한 이름을 사용하여 이름이 지정된 레이블로 가져 오면 프로그래머가 해당 세부 사항을 무시 / 추출 할 수 있습니다.

그러나 "매직 스트링이 나쁘기 때문에"일정하게하는 것은화물을 경작하는 것입니다.


8
지역화는 일반적으로 문자열 상수보다 더 복잡합니다. 예를 들어, 일부 언어는 모든 목록 항목간에 목록 구분 기호를 원하지만 다른 언어는 마지막 항목 앞의 구분자를 제외합니다. 따라서 일반적으로 지역화 된 상수가 아니라 지역화 된 규칙이 필요 합니다.
Vlad

19
실제로 수천 구분 기호는 다른 로케일 (중국 / 일본)에서 반드시 수천 구분 기호 일 필요는 없습니다. 일정한 자릿수 (인도) 후에도 설정되지 않습니다. 아, 1000 구분 기호인지 또는 1000000 구분 기호 (멕시코)인지에 따라 다른 구분 기호가있을 수 있습니다. 그러나 일부 로케일 (Farsi)에서 ASCII 숫자 0-9를 사용하지 않는 것보다 문제가 적습니다. ux.stackexchange.com/questions/23667/…
Peter

1
@Vlad Localization은 그보다 훨씬 복잡하지만 천 단위 구분 기호는 사람들이 잘 알고있는 잘 알려진 예입니다.

현지화 전략에 따라 다릅니다 ... 번역하기 위해 프로그램의 모든 상수를 변경합니까? 아니면 파일 (또는 다른 데이터 저장소)에서 값을 읽어서 런타임 변수를 효과적으로 만들어야합니까?
Paŭlo Ebermann

그것은 상수로 전혀 유용하지 않을 것입니다. 로케일을 위해 프로그램을 다시 컴파일해야하는데 이는 끔찍한 관행입니다. 정의 파일에서로드 된 변수 여야하며 필요에 따라 조회해야합니다. 나는 그 요점에 동의하지 않지만 (답을 투표했다), 그 문제에 대해 더 어려운 입장을 취할 것이다.

29

모호하거나 여러 다른 목적으로 사용되는 문자가 몇 가지 있습니다. 예를 들어, '-'하이픈, 빼기 기호 또는 대시로 사용합니다. 다음과 같이 별도의 이름을 만들 수 있습니다.

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '-';
static const wchar_t EM_DASH = '-';

나중에 다음과 같이 코드를 다시 정의하여 명확하게 코드를 수정하도록 선택할 수 있습니다.

static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '\u2122';
static const wchar_t EM_DASH = '\u2014';

이것이 특정 단일 문자에 대한 상수 정의를 고려 하는 이유 일 수 있습니다 . 그러나 이러한 방식으로 모호한 문자 수는 적습니다. 기껏해야, 당신은 그것들을 위해서만 할 것 같습니다. 또한 코드를 이러한 방식으로 고려하기 전에 모호한 문자를 실제로 구별해야 할 때까지 기다릴 수 있다고 주장합니다.

활자체 규약은 언어 및 지역에 따라 다를 수 있으므로 번역 표에서 이러한 모호한 문장 부호를로드하는 것이 좋습니다.


나에게 이것이 문자 상수를 생성 할 수있는 유일한 이유이다
FP

2
-em 대시로 사용 하는 것은 오해의 소지가 있습니다 ... 대부분의 글꼴에서 그 길이가 짧습니다. (그것은 대시보다 짧습니다.)
Paŭlo Ebermann

가장 좋은 예는 아닙니다. 나는 string오히려 s로 시작 하여 대시 wchar_t"--"대한 표준 원고 규칙을 사용했습니다 . 그러나 원래 예제는 단일 문자를 사용했기 때문에 질문에 충실하도록 전환했습니다. -특히 고정 피치 글꼴로 작업 할 때 대시 를 입력하는 사람들이 있습니다 .
Adrian McCarthy

1
@ PaŭloEbermann 아니요, 전통적으로 em 대시는 글자체의 'm'문자의 너비이고 en 대시는 'n'문자의 너비입니다.
Dizzley

@Dizzley yes 및 하이픈 너비 <n 너비 <m 너비입니다.
Paŭlo Ebermann

22

상수는 의미를 추가해야합니다.

쉼표를 쉼표로 정의하면 쉼표가 쉼표라는 것을 알기 때문에 의미가 없습니다. 대신 COMMA는 더 이상 쉼표가 아니기 때문에 의미를 파괴합니다.

목적으로 쉼표를 사용하고 명명 된 상수를 사용하려면 목적 뒤에 이름을 지정하십시오. 예:

  • city + CharacterClass.COMMA + state = 나쁨
  • city + CITY_STATE_DELIMITER + state = 좋다

포맷 기능 사용

나는 개인적 FormatCityState(city, state)으로 그 기능의 본문이 짧고 테스트 케이스를 통과하는 한 어떻게 보이는지 신경 쓰지 않습니다.


1
아, 그러나 쉼표가 항상 같은 쉼표는 아닙니다. COMMA = '\ u0559'또는 '\ u060C'등을 정의하거나 (유니 코드 참조) 나중에 변수로 바꾸어 구성 파일에서 읽을 수도 있습니다. 그렇게하면 여전히 같은 의미 를 가지지 만 다른 값을 갖습니다. 어떻게에 대한.
Mr Lister

2
@MrLister : 야 그니. 당신이 필요로하는 경우 : 좋은! 좋은 해결책이 있습니다. 그러나 그렇지 않으면 언젠가는 어쩌면 코드를 어지럽히 지 마십시오. 또한 내 경험상 코드베이스에 기능이없는 추상화를 도입하려고하면 사람들이 일관성을 유지하지 못합니다. 따라서 다른 코드 포인트를 사용하려는 의도로 충분한 크기와 연령의 프로그램에서 COMMA를 정의한 경우에도 선택이 중요한 모든 위치에서 상수가 사용되지 않았 음을 알 수 있습니다 (그리고 반대로, 부적절하게 사용되었을 수도 있습니다).
Eamon Nerbonne

17

일정한 쉼표가 더 좋 ','거나 더 ","쉽다는 생각. 물론이 예 결정이 것이 의미가있다 경우입니다 final String QUOTE = "\"";모든 슬래시없이 일기 좋게에 크게 절약 할 수는 있지만, 같은 언어 제어 문자를 금지 \ '하고 "나는 그들이 매우 유용하다는 것을 발견하지 않았습니다.

사용하는 final String COMMA = ","것은 나쁜 형태 일뿐만 아니라 위험합니다! 사람에서 분리를 변경하고자하는 경우 ","";"그들은 상수가 파일을 변경 갈 수도 COMMA = ";"그들을 그렇게하기가 빠르다 때문에 그냥 작동합니다. COMMA를 사용한 다른 모든 것들은 외부 소비자에게 보낸 것을 포함하여 세미콜론이기도합니다. 따라서 모든 마샬링 및 마샬링 해제 코드가 COMMA를 사용했기 때문에 모든 테스트를 통과하지만 외부 테스트는 실패합니다.

유용한 것은 그들에게 유용한 이름을 부여하는 것입니다. 그리고 네, 때로는 여러 상수가 같은 내용이지만 이름이 다릅니다. 예를 들면 final String LIST_SEPARATOR = ",".

따라서 귀하의 질문은 "단일 문자 상수보다 리터럴보다 낫습니다"라는 대답은 확실하지 않습니다. 그러나 두 가지보다 더 나은 것은 목적이 무엇인지 명시 적으로 나타내는 좁은 범위의 변수 이름입니다. 물론, 추가 참조에 약간의 추가 바이트를 소비 할 것입니다 (아마도 그들이 당신에게 컴파일되지 않는다고 가정 할 것입니다). 그러나 장기적인 유지 보수는 응용 프로그램의 비용이 가장 많이 드는 곳입니다. 시간을 할 가치가 있습니다.


대상 플랫폼에 따라 DISP_APOSTROPHE를 조건에 따라 ASCII 0x27 또는 유니 코드 작은 따옴표 (아포스트로피에 더 적합한 어포 스트로피 표현)로 정의하는 것은 어떻습니까?
supercat

3
실제로 QUOTE예는 당신이 일반적으로 / 대중적으로 알려진에 할당되기 때문에뿐만 아니라 나쁜 생각 증명 DOUBLE QUOTE하고 QUOTE의미 SINGLE_QUOTE보다 정확하게라고한다 APOSTROPHE.

3
@JarrodRoberson 개인적으로 따옴표는 작은 따옴표를 의미한다고 생각하지 않습니다. 그러나 이것이 가능한 모호성을 제거하는 또 다른 좋은 이유입니다!
corsiKa

2
QUOTE추가 이유로 인해 예제 가 마음에 들지 않습니다. 문자열로 구성된 문자열을 읽기 "Hello, my name is " + QUOTE + "My Name" + QUOTE가 더 어려워 지지만 사소한 예제이지만 여전히 나빠 보입니다. 물론, 대신 연결 토큰을 사용할 수 있습니다 "Hello, my name is %sMy Name%s".format(QUOTE, QUOTE). 나빠질 수도 있습니다. 그러나 인덱스 토큰을 사용해 보도록하겠습니다 "Hello, my name is {0}My Name{0}".format(QUOTE). 따옴표로 생성 된 사소하지 않은 문자열은 더 나빠질 것입니다.
VLAZ

2
@corsiKa-나는 이스케이프 된 실제 따옴표와 함께 살 것입니다. 탈출하는 것을 놓치면 사용하는 IDE가 즉시 불평합니다. 코드도 컴파일되지 않을 것입니다. 꽤 쉽게 발견 할 수 있습니다. 실수를 저지르는 것이 얼마나 쉬운 지 "My name is" + QUOTE + "My Name" + QUOTE실제로 위의 의견을 쓰면서 같은 실수를 세 번 했어요 . 당신은 그것을 발견 할 수 있습니까? 조금 시간이 걸리면 is 다음에 누락 된 공간 입니다 . 문자열을 포맷합니까? 이 경우 대체 할 토큰이 여러 개인 문자열이 더 나빠질 수 있습니다. 더 읽기 쉽게 사용하려면 어떻게해야합니까?
VLAZ

3

나는 어휘 분석기와 파서를 작성하는 작업을 수행했으며 정수 상수를 사용하여 터미널을 나타냅니다. 단일 문자 터미널은 단순성을 위해 ASCII 코드를 숫자 값으로 사용했지만 코드는 완전히 다른 것일 수 있습니다. 그래서 나는 ','에 대한 ASCII 코드가 상수 값으로 지정된 T_COMMA를 가질 것입니다. 그러나 ASCII 집합 이상의 정수가 할당 된 비 터미널에 대한 상수도있었습니다. yacc 또는 bison과 같은 파서 생성기 또는 이러한 도구를 사용하여 작성된 파서를 보면 기본적으로 모든 사람이 그렇게 한 인상을 받았습니다.

따라서 다른 모든 사람들과 마찬가지로 코드 전체에서 리터럴 대신 상수를 사용하는 표현 목적으로 상수를 정의하는 것은 의미가 없다고 생각합니다. 설명하는 것과 같은 상수. 파서의 경우 상수는 문자 리터럴을 나타내는 것이 아닙니다. 문자 리터럴 수도있는 엔티티를 나타냅니다 .

해당 리터럴 대신 상수를 사용하는 것이 더 합리적인 몇 가지 더 고립 된 경우를 생각할 수 있습니다. 예를 들어, UNILINE 상자에서는 NEWLINE을 리터럴 '\ n'으로 정의하고 Windows 또는 Mac 상자에서는 '\ r \ n'또는 '\ n \ r'로 정의 할 수 있습니다. 테이블 형식 데이터를 나타내는 파일 구문 분석도 마찬가지입니다. FIELDSEPARATOR 및 RECORDSEPARATOR 상수를 정의 할 수 있습니다. 이 경우 실제로 특정 함수를 제공하는 문자를 나타내는 상수를 정의하고 있습니다. 그래도 초보자 프로그래머라면 필드 구분 기호를 상수 COMMA로 지정하고 FIELDSEPARATOR라고 불렀다는 사실을 깨닫지 못했을 것입니다. 실제로 코드가 생산 중이며 다음에있을 것입니다. 계획,

마지막으로, 당신이 설명하는 연습을 수있는 특정 문자 인코딩으로 인코딩 된 데이터를 처리하는 코드를 작성하는 몇 가지 경우에 이해는 ISO-8859-1을 말하지만, 인코딩이 나중에 변경 될 전망이다. 물론 이러한 경우 현지화 또는 인코딩 및 디코딩 라이브러리를 사용하여 처리하는 것이 훨씬 더 합리적이지만 어떤 이유로 든 라이브러리를 사용하여 인코딩 문제를 처리 할 수없는 경우 상수를 사용하면됩니다. 소스 코드 전체에 흩어져있는 하드 코딩 된 리터럴 대신 단일 파일로 재정의해야 할 수도 있습니다.

당신이 링크 한 기사에 관해서는 : 문자 리터럴을 상수로 대체하려는 경우를 생각하지 않습니다. 인터페이스를 사용하여 상수를 코드베이스의 다른 부분으로 가져 오는 방법을 설명하려고한다고 생각합니다. 이것을 설명하는 데 사용되는 상수 예제는 매우 잘못 선택되었지만 어떤 식 으로든 중요하다고 생각하지 않습니다.


2
인터페이스를 사용하여 상수를 코드베이스의 다른 부분으로 가져 오는 방법을 설명하려고한다고 생각합니다. 더 나쁜 안티 패턴 이며 단단히 결합하고 응집력이 낮기 때문에 그럴만 한 이유가 없습니다.

3

여기에있는 모든 훌륭한 답변 외에도, 좋은 프로그래밍은 동일한 코드를 반복해서 반복하지 않고도 자신과 다른 사람들이 만들 수있는 적절한 추상화 를 제공하는 것입니다.

좋은 추상화는 코드를 사용하기 편하고 다른 한편으로는 유지하기 쉽다.

나는 DELIMITER=':'그 자체가 그 자체로는 열악한 추상화이며, COLON=':'(후자가 완전히 빈곤하기 때문에) 단지 나아진 것에 완전히 동의한다 .

문자열과 구분 기호를 포함하는 추상화에는 하나 이상의 개별 컨텐트 항목을 문자열로 압축하고 압축 된 문자열에서 가장 먼저 분리 기호를 알려주는 방법이 포함됩니다. 이러한 추상화는 대부분의 언어에서 하나의 개념으로 하나의 개념으로 묶일 수 있습니다. 예를 들어,이 클래스가 사용되는 모든 장소를 검색하고 일부 추상화가 사용되는 각 경우에 묶음 문자열의 형식에 관한 프로그래머의 의도를 확신 할 수 있다는 점에서 사용 자체가 실질적으로 자체 문서화됩니다.

이러한 추상화가 제공되면 DELIMITER또는 의 가치를 상담 할 필요없이 쉽게 사용할 수 있으며 COLON구현 세부 사항 변경은 일반적으로 구현으로 제한됩니다. 요컨대, 이러한 상수는 실제로 적절한 추상화 내에 숨겨진 구현 세부 사항이어야합니다.

상수 사용의 주요 장점은 변경이 필요할 때 유지 관리를 최소화한다는 것입니다.

일반적으로 여러 관련 기능으로 구성된 좋은 추상화는 유지 관리를 최소화하는 데 더 좋습니다. 첫째, 공급자와 소비자를 명확하게 구분합니다. 둘째, 구현 세부 사항을 숨기고 대신 직접 유용한 기능을 제공합니다. 셋째, 사용시기와 장소에 대해 높은 수준으로 문서화합니다.


2

효과적으로 사용되는 상수를 본 것은 기존 API 또는 문서와 일치하는 것입니다. COMMA특정 소프트웨어가 COMMA추상 구문 트리에서 태그로 사용되는 파서에 직접 연결되어 있기 때문에 사용되는 기호를 보았습니다 . 또한 공식 사양과 일치하는 데 사용되는 것을 보았습니다. 공식적인 사양에서, 당신은 때때로 최대한 명확하게하기를 원하기 COMMA보다는 오히려 기호를 보게 될 것 ','입니다.

두 경우 모두와 같이 명명 된 기호를 사용 COMMA하면 분리 된 제품에 응집력을 제공 할 수 있습니다. 그 가치는 종종 지나치게 자세한 표기법의 비용을 능가 할 수 있습니다.


2

목록을 작성하려고 함을 관찰하십시오 .

따라서 다음과 같이 리 팩터하십시오. String makeList(String[] items)

즉, data 대신 논리 를 인수 분해하십시오 . 언어는 목록을 나타내는 방식이 다를 수 있지만 쉼표는 항상 쉼표입니다 (관념). 따라서 언어가 변경되면 쉼표 문자를 변경해도 도움이되지 않지만 도움이됩니다.


0

이 클래스가 동료 개발자가 응용 프로그램의 일부로 작성한 클래스 인 경우 이는 거의 잘못된 생각입니다. 다른 사람들이 이미 지적했듯이 SEPARATOR = ','값을 변경할 수있는 위치 와 같은 상수를 정의하는 것이 합리적 이며 상수는 여전히 의미가 있지만 그 이름이 단지 값을 설명하는 상수는 훨씬 적습니다.

그러나 이름이 내용을 정확하게 설명하고 상수 이름을 적절하게 변경하지 않고 값을 변경할 수없는 상수를 선언하는 것이 의미가있는 경우가 적어도 두 가지 있습니다.

  • 수학적 또는 물리적 상수, 예 PI = 3.14159. 여기서 상수의 역할은 기호 이름 PI이 나타내는 값보다 훨씬 짧고 읽기 쉽기 때문에 니모닉으로 작동하는 것입니다.
  • 파서의 전체 기호 목록 또는 키보드의 키. 대부분의 또는 모든 유니 코드 문자가 포함 된 상수 목록을 갖는 것이 합리적 일 수 있으며이 경우 문제가 발생할 수 있습니다. 와 같은 일부 문자 A는 명확하고 명확하게 인식 가능합니다. 그러나 당신은 쉽게 말할 수 АA떨어져? 첫 번째는 키릴 문자 A 이고 후자는 라틴 문자 A 입니다. 그래픽 적으로 거의 동일하더라도 다른 문자이며 다른 유니 코드 코드 포인트로 표시됩니다. 오히려 상수가 CYRILLIC_CAPITAL_A있고LATIN_CAPITAL_A내 코드에서 거의 동일하게 보이는 두 문자보다. 물론 키릴 문자가 포함되지 않은 ASCII 문자로만 작업한다는 것을 알고 있다면 이것은 의미가 없습니다. 마찬가지로 : 나는 매일 라틴 알파벳을 사용하므로 한자를 필요로하는 프로그램을 작성하는 경우 이해할 수없는 문자를 삽입하는 대신 상수를 사용하는 것이 좋습니다. 매일 한자를 사용하는 사람에게는 한자가 분명하지만 라틴어는 명명 된 상수로 표현하기가 더 쉽습니다. 보시다시피 상황에 따라 다릅니다. 그럼에도 불구하고 라이브러리는 모든 문자에 대한 기호 상수를 포함 할 수 있습니다. 저자는 라이브러리가 어떻게 사용되는지, 특정 응용 프로그램에서 가독성을 향상시키기 위해 상수가 필요한 문자를 미리 알 수 없기 때문입니다.

그러나 이러한 경우는 일반적으로 시스템 클래스 또는 특수 목적 라이브러리에 의해 처리되며 응용 프로그램 개발자가 작성한 코드에서 발생하는 경우는 매우 특별한 프로젝트를 수행하지 않는 한 매우 드 rare니다.


-1

아마도.

단일 문자 상수는 비교적 구별하기 어렵습니다. 따라서 쉼표 대신 마침표를 추가한다는 사실을 놓치기가 쉽습니다.

city + '.' + state

반면에 상대적으로 어려운 실수입니다.

city + Const.PERIOD + state

국제화 및 세계화 환경에 따라 ASCII 아포스트로피와 Windows-1252 열기 및 닫기 아포스트로피 (또는 ASCII 이중 인용 부호 및 Windows-1252 열기 및 닫기 큰 따옴표)의 차이가 중요 할 수 있으며보기에 시각적으로 어렵습니다. 코드에서.

아마도 실수로 쉼표가 아닌 마침표를 두는 것이 중요한 기능적 문제라면 오타를 찾을 수있는 자동화 된 테스트가있을 것입니다. 소프트웨어가 CSV 파일을 생성하는 경우 테스트 스위트가 도시와 주 사이의 기간이 있음을 꽤 빨리 발견 할 것으로 기대합니다. 다양한 국제화 구성을 가진 클라이언트에 대해 소프트웨어를 실행해야하는 경우 아마도 테스트 스위트가 각 환경에서 실행되며 아포스트로피를 사용하려는 경우 Microsoft 공개 견적이있는 경우 선택됩니다.

나는 아마도 이런 식으로 코딩하지 않더라도 포괄적 인 테스트 스위트가없는 오래된 코드를 가질 때 이러한 문제를 해결할 수있는 더 자세한 코드를 선택하는 것이 더 합리적인 프로젝트를 상상할 수 있습니다. 그린 필드 개발 프로젝트. 또한 특정 응용 프로그램에서 문제가 될 수있는 문자가 아닌 모든 문장 부호 문자에 상수를 추가하는 것은 아마도 과도한 과잉 일 것입니다.


2
일부 moron Const.PERIOD이 동일하게 변경되면 어떻게됩니까 ~? 명명 된 문자에 대한 타우 톨 로지에 대한 타당성이 없으며, 현대의 프로그래밍 환경에서 원하지 않는 유지 관리 및 복잡성을 추가합니다. 기본적으로 말하는 단위 테스트 모음을 작성 assert(Const.PERIOD == '.')하시겠습니까?

3
@JarrodRoberson-당연하지. 그러나 누군가가 실제 쉼표가 아닌 쉼표와 거의 똑같이 보이는 유니 코드 상수를 추가하면 많은 어려움을 겪을 것입니다. 내가 말했듯이, 이것은 내가 그린 필드 개발 프로젝트에서 할 일이 아닙니다. 그러나 콤마 / 기간 또는 아포스트로피 / Microsoft abomination 아포스트로피 문제에 대해 몇 번 트립 된 드문 드문 테스트 스위트가있는 레거시 코드베이스가있는 경우 몇 가지 상수를 만들고 사람들에게 알리는 것이 합리적인 방법 일 수 있습니다. 테스트를 작성하는 데 1 년이 걸리지 않고 코드가 더 좋습니다.
저스틴 동굴

3
레거시 예제는 좋지 않은 것입니다. 방금 18 세인 1,000,000 + LOC 코드베이스 리팩토링을 마쳤습니다. 서로 다른 충돌하는 이름으로도 이렇게 인쇄 가능한 모든 문자를 여러 번 정의했습니다. 그리고 여러 번 명명 된 COMMA것들이 실제로 설정되었습니다 = SPACE + "," + SPACE. 예, 일부 바보는 SPACE일정했습니다. 나는 그것들을 모두 리팩토링했고 코드는 읽기 쉽도록 주문이 많았고 대학 채용은 실제로 무엇을 설정했는지 알기 위해 6 단계의 간접 지시없이 물건을 추적하고 수정할 수있었습니다.

-1

단일 문자 상수가 리터럴보다 낫습니까?

여기에 떠 다니는 많은 갈등이 있습니다. 내가 그들을 놀릴 수 있는지 보자.

상수는 다음을 제공합니다.

  • 의미론
  • 개발 중 변화
  • 우회

단일 문자 이름으로 내려 가면 의미에 영향을 미칩니다. 이름은 주석으로 유용하고 문맥에서 명확해야합니다. 가치가 아니라 의미를 표현해야합니다. 그것이 한 문자 벌금으로 모든 것을 할 수 있다면. 할 수 없다면,하지 마십시오.

리터럴과 상수는 개발 중에 변경 될 수 있습니다. 이것이 마법의 숫자 문제를 제기하는 것입니다. 문자열도 마법의 숫자가 될 수 있습니다.

의미 적 의미가 존재하고 둘 다 상수이므로 상수가 리터럴보다 더 많은 값을 갖는지 여부는 간접적입니다.

간접적 인 간접적 인 것 이외의 문제를 해결할 수 있습니다.

한 위치에서 아이디어의 가치를 결정할 수 있기 때문에, 간접적 인 숫자 문제를 해결할 수 있습니다. 의미 상, 그것이 가치가 있으려면, 그 이름은 그 아이디어가 분명한 것을 만들어야합니다. 이름은 가치가 아니라 아이디어에 관한 것이어야합니다.

간접 지정을 무시할 수 있습니다. 일부는 리터럴을 검색하고 바꾸어 변경을 선호합니다. 42가 분명히 생명의 의미이고 몰리브덴의 원자 수인 42와 혼합되지 않는 한 괜찮습니다.

한 글자로 된 것과 같은 유용한 구별은 문맥에 따라 크게 다릅니다. 그러나 나는 그것을 습관으로 만들지 않을 것입니다.


1
시맨틱이 핵심입니다. 만약 "A"가 단순히 "A"인 것보다 더 의미가 있다면, 동일한 의미를 동일한 "참조"에 묶는 것이 가치가 있습니다. 상수인지 여부는 중요하지 않습니다. 전적으로 동의합니다.
oopexpert

-1

대다수의 견해에 대한 철학적 결백으로, 나는 우리 중 일부가 19 세기 프랑스 농민 프로그래머와

그의 단조롭고 영원한 자애, 모든 것에 대한 완고한 현명한 견해, 진실에 의한 트루 미즘에 대한 그의 거만 만족을 기억했습니다. "모두 혼란스러워!" 턴불에게 자신이 비명을 지르면 외부에 아무도있을 수 없다고 외쳤다.

GK Chesterton, 공과 십자가

진실을 이해하는 데에는 잘못된 것이 없으며, 특히 컴퓨터와 대화 할 때 진실을 말하는 데에는 아무런 문제가 없습니다.

컴퓨터에 거짓말을하면

Perry Farrar-메릴랜드 저먼 타운 (기타 프로그래밍 펄)


그러나 대부분 나는 그것이 바보라고 말하는 사람들에 동의합니다. FORTRAN을 프로그래밍하는 법을 배우기에는 너무 어리지만, 여러분이 재정의 'A' = 'Q'하고 모든 종류의 멋진 암호 를 만들 수 있다고 들었 습니다. 당신은 이것을하지 않습니다.

이전에 제기 된 i18n 문제를 넘어서 (글리프 "COMMA"를 재정의하는 것이 아니라 DECIMAL_POINT의 글리프를 재정의하는 것). 인간에게 의미를 전달하기 위해 프랑스 당근 따옴표 나 영국의 작은 따옴표를 만드는 것은 중요하며 실제로 상수가 아닌 변수 여야합니다. 상수는 것 AMERICAN_COMMA := ','comma := AMERICAN_COMMA

그리고 빌더 패턴을 사용하여 SQL 쿼리를 구성한다면 훨씬 더 많이 볼 것입니다.

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(" ( ")
 .append(val_1)
 .append(",")
 .append(val_2)
 .append(" ); ")

다른 것보다, 그러나 상수를 추가하려고한다면

INSERT_VALUES_START = " ( "
INSERT_VALUES_END = " ) "
INSERT_VALUES_SEPARATOR = " , "
QUERY_TERMINATOR = ";"

sb.append("insert into ")
 .append(table_name)
 .append(" values ")
 .append(INSERT_VALUES_START)
 .append(val_1)
 .append(INSERT_VALUES_SEPARATOR)
 .append(val_2)
 .append(INSERT_VALUES_END)
 .append(QUERY_TERMINATOR)

그러나 다른 프로그램 (또는 유형)을 본 적이 있다면 흥미로운 점이 있습니다. 우리 모두가 훌륭한 타이피스트는 아닙니다. 우리 중 많은 사람들이 늦게 프로그래밍을 시작했거나 소비에트 키보드 (키가 당신에게 입력되는 곳)로 자랐고 키보드에서 개별 문자를 찾 거나 자동 완성에 의존하는 대신 개별 문자잘라 붙여 넣기를 좋아합니다 .

아무것도 자동으로 문자열을 완성하지 않으므로 'con', alt-space, down, down, down을 눌러 쉼표를 얻을 수 있다면 'con', alt-space, down, 아래로 입력하십시오. 그냥 할 수도 있습니다.


문자열 리터럴에 대해 기억해야 할 또 다른 사항은 컴파일되는 방식입니다. 델파이에서는 적어도 (이것은 내가 스택에 집착 한 유일한 언어입니다) 리터럴을 각 함수의 스택에 뿌립니다. 따라서 많은 리터럴 = 많은 함수 오버 헤드; function_A의 ","는 function_B "의", "와 동일한 메모리 비트가 아닙니다.이를 막기 위해 옆에 빌드하고 링크 할 수있는"리소스 문자열 "이 있습니다. 파이썬에서 모든 문자열 리터럴은 객체이며 실제로 사용하는 것이 좋을지 모르지만 utils.constants.COMMA.join(["some","happy","array","strings"])이 페이지에서 반복해서 반복되는 점에 대해서는 별다른 아이디어가 아닙니다.


-4

그러나 ','과 다른 기호를 사용하여 쉼표를 나타내려면 언제 시작해야합니까?

현지화 용.

영어권 국가에서 소수의 전체 및 소수 부분을 구분하는 기호는 "."이며,이를 "소수점"이라고합니다. 다른 많은 국가에서 기호는 ","이며 일반적으로 현지 언어에서는 "쉼표"와 동일합니다. 마찬가지로 영어를 사용하는 국가에서 ","를 사용하여 세 자리 그룹을 큰 숫자 (예 : 백만의 경우 1,000,000)로 구분하는 경우 쉼표를 소수점으로 사용하는 국가는 점 (1.000.000)을 사용합니다.

따라서 세계화를 수행하는 경우 DECIMAL_POINT 및 COMMA 상수를 만드는 경우가 있습니다.


2
그러나 COMMA 및 DECIMAL_POINT는 엔티티의 올바른 이름이 아닙니다 (아마도 다운 피트 된 이유 일 수 있습니다).
Kyle Strand

현지화 된 특정 버전을 컴파일해야합니다. 리터럴 상수는 적합하지 않습니다. 이 유스 케이스는 정의 파일과 조회를 요구합니다 (상수는 포함 할 수 있지만 상수 문자가 아닌 조회 상수가 포함될 수 있음).
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.