[language-agnostic] 매직 넘버는 무엇이며 왜 나쁜가요? [닫은]

매직 넘버는 무엇입니까?

왜 피해야합니까?

적절한 경우가 있습니까?



답변

매직 넘버는 코드에서 숫자를 직접 사용하는 것입니다.

예를 들어, Java로 된 경우 :

public class Foo {
    public void setPassword(String password) {
         // don't do this
         if (password.length() > 7) {
              throw new InvalidArgumentException("password");
         }
    }
}

이것은 다음과 같이 리팩토링되어야합니다.

public class Foo {
    public static final int MAX_PASSWORD_SIZE = 7;

    public void setPassword(String password) {
         if (password.length() > MAX_PASSWORD_SIZE) {
              throw new InvalidArgumentException("password");
         }
    }
}

코드의 가독성을 향상시키고 유지 관리가 더 쉽습니다. GUI에서 암호 필드의 크기를 설정 한 경우를 상상해보십시오. 마법의 숫자를 사용하면 최대 크기가 변경 될 때마다 두 개의 코드 위치에서 변경해야합니다. 하나를 잊어 버리면 불일치가 발생합니다.

JDK에는이처럼 예 가득 Integer, CharacterMath클래스.

추신 : FindBugs 및 PMD와 같은 정적 분석 도구는 코드에서 마술 숫자의 사용을 감지하고 리팩토링을 제안합니다.


답변

매직 넘버는 하드 코딩 된 값으로 나중에 변경 될 수 있지만 업데이트하기가 어려울 수 있습니다.

예를 들어 “주문”개요 페이지에 마지막 50 개의 주문을 표시하는 페이지가 있다고 가정합니다. 50은 매직 넘버입니다. 표준 또는 컨벤션을 통해 설정되지 않았기 때문에 스펙에 설명 된 이유로 만든 숫자입니다.

이제 SQL 스크립트 ( SELECT TOP 50 * FROM orders), 웹 사이트 (최근 50 주문), 주문 로그인 ( for (i = 0; i < 50; i++)) 및 다른 많은 장소와 같은 다른 장소에 50 개가 있습니다.

이제 누군가가 50에서 25로 변경하기로 결정하면 어떻게됩니까? 또는 75? 또는 153? 이제 모든 장소에서 50을 교체해야하며 놓칠 가능성이 큽니다. 50은 다른 용도로 사용될 수 있기 때문에 찾기 / 바꾸기가 작동하지 않을 수 있으며, 맹목적으로 50을 25로 바꾸면 부작용이 발생할 수 있습니다 (예 : Session.Timeout = 50통화도 25로 설정되고 사용자가 너무 자주 시간 초과보고를 시작 함).

또한 코드가 이해하기 어려울 수 있습니다. 즉, ” if a < 50 then bla“-복잡한 함수 도중에이 코드를 발견하면 코드에 익숙하지 않은 다른 개발자가 “WTF는 50 ???”

그렇기 const int NumOrdersToDisplay = 50때문에 코드를 더 읽기 쉽도록 ( ” if a < NumOrdersToDisplay“) 명확하게 정의 된 1 개 위치에서만 변경 하면되기 때문에 “1”- ” ” 와 같이 모호하고 임의의 숫자를 갖는 것이 가장 좋습니다 .

마법의 숫자는 적절한 장소가 표준을 통해 정의 된 모든 것, 즉 SmtpClient.DefaultPort = 25TCPPacketSize = whatever(즉,이 표준화하지 않도록 경우). 또한 1 함수 내에서만 정의 된 모든 것이 허용 될 수는 있지만 상황에 따라 다릅니다.


답변

마법 번호 에 대한 Wikipedia 항목을 살펴 보셨습니까 ?

매직 넘버 레퍼런스가 만들어지는 모든 방법에 대해 조금 자세하게 설명합니다. 나쁜 프로그래밍 연습으로 마술 번호에 대한 인용문은 다음과 같습니다.

매직 넘버라는 용어는 또한 설명없이 소스 코드에서 직접 숫자를 사용하는 나쁜 프로그래밍 방식을 말합니다. 대부분의 경우 이로 인해 프로그램을 읽고 이해하고 유지하기가 더 어려워집니다. 대부분의 안내서는 숫자 0과 1을 제외하지만 코드의 다른 모든 숫자를 명명 된 상수로 정의하는 것이 좋습니다.


답변

매직 넘버 대 기호 상수 : 교체시기

마법 : 알 수없는 의미

Symbolic Constant-> 올바른 의미 및 올바른 컨텍스트를 제공합니다

시맨틱 : 사물의 의미 또는 목적.

“상수를 작성하고 의미 뒤에 이름을 지정한 다음 숫자로 바꾸십시오.” -마틴 파울러

첫째, 매직 넘버는 단순한 숫자가 아닙니다. 모든 기본 값은 “마법”이 될 수 있습니다. 기본 값은 정수, 실수, double, float, 날짜, 문자열, 부울, 문자 등과 같은 매니페스트 엔터티입니다. 문제는 데이터 유형이 아니라 코드 텍스트에 나타나는 값의 “마법”측면입니다.

“마술”은 무엇을 의미합니까? 정확하게하기 위해 : “마법”에 의해, 우리는 코드의 맥락에서 가치의 의미 (의미 또는 목적)를 가리 키려고합니다. 알 수 없거나, 알 수 없거나, 불분명하거나 혼동된다. 이것이 “마술”의 개념입니다. 특별한 의미의 단어 (예 : 기호 상수)없이 서라운드 컨텍스트에서 의미 론적 의미 또는 목적이 빠르고 쉽게 알려지고 명확하고 이해 (혼동되지 않음) 할 때 기본 값은 마술이 아닙니다.

따라서, 우리는 주변 환경으로부터 기본 가치의 의미와 목적을 알고, 명확하게 이해하는 코드 리더의 능력을 측정하여 마법의 숫자를 식별합니다. 독자가 덜 알려지고 덜 명확하고 더 혼란 스러울수록 기본 값이 “매직”입니다.

유용한 정의

  • 혼동 : (누군가) 당황하거나 당황하게 만듭니다.
  • 당황 : (누군가) 당황하고 혼란하게합니다.
  • 당황 : 완전히 당황; 매우 당황했다.
  • 당황 : 완전히 어리둥절하거나 당황합니다.
  • 의아해 : 이해할 수없는; 황당한가요.
  • 이해 : 의도 된 의미 (단어, 언어 또는 화자)를 인식합니다.
  • 의미 : 단어, 텍스트, 개념 또는 행동의 의미
  • 의미 : (특정한 것 또는 개념)을 전달, 표시 또는 언급하려는 의도; 의미합니다.
  • 서명하다 : 표시한다.
  • 표시 : 무언가를 나타내는 표시 또는 정보.
  • 표시 : 지적; 보여 주다.
  • 부호 : 존재 또는 발생이 다른 존재의 존재 또는 발생을 나타내는 객체, 품질 또는 이벤트.

기초

마법의 기본 가치에 대한 두 가지 시나리오가 있습니다. 프로그래머와 코드에서 두 번째 만이 가장 중요합니다.

  1. 그 의미를 알 수 없거나 알 수 없거나 불분명하거나 혼동되는 고독한 기본 값 (예 : 숫자)
  2. 문맥 상 기본 값 (예 : 숫자)이지만 그 의미는 알 수 없거나 알 수 없거나 불분명하거나 혼동됩니다.

“매직”에 대한 가장 중요한 의존성은 고독한 기본 값 (예 : 숫자)이 일반적으로 알려진 의미론 (예 : Pi)을 갖지 않지만, 로컬에서 알려진 의미론 (예 : 프로그램)을 가지므로 문맥에서 완전히 명확하지 않거나 악용 될 수 있습니다. 좋은 또는 나쁜 맥락에서.

대부분의 프로그래밍 언어의 의미는 (아마도) 데이터 (예 : 데이터 테이블)를 제외하고 고독한 기본 값을 사용할 수 없습니다. 우리가 “마법의 숫자”를 만날 때 우리는 일반적으로 맥락에서 그렇게합니다. 따라서

“이 마법 번호를 기호 상수로 대체합니까?”

입니다 :

“컨텍스트에서 숫자의 의미 적 의미 (거기에 대한 목적)를 얼마나 빨리 평가하고 이해할 수 있습니까?”

마술의 종류, 그러나 꽤

이러한 생각을 염두에두고 적절한 맥락에 배치 할 때 Pi (3.14159)와 같은 숫자가 어떻게 “마법의 숫자”가 아닌지 빠르게 알 수 있습니다 (예 : 2 x 3.14159 x 반경 또는 2 * Pi * r). 여기서 숫자 3.14159는 기호 상수 식별자없이 정신적으로 Pi로 인식됩니다.

여전히, 우리는 일반적으로 3.14159를 숫자의 길이와 복잡성 때문에 Pi와 같은 기호 상수 식별자로 대체합니다. Pi의 길이와 복잡성의 측면 (정확도의 필요성과 결합)은 일반적으로 기호 식별자 또는 상수가 오류가 덜 발생한다는 것을 의미합니다. “Pi”를 이름으로 인식하는 것은 단순히 편리한 보너스이지만 상수를 갖는 주된 이유는 아닙니다.

한편 : 목장에서

Pi와 같은 일반적인 상수를 제외하고는 주로 특별한 의미를 가진 숫자에 중점을 두지 만 그 의미는 소프트웨어 시스템의 세계에 제약을받습니다. 이러한 숫자는 “2”(기본 정수 값) 일 수 있습니다.

숫자 2를 단독으로 사용하는 경우 첫 번째 질문은 “2”는 무엇을 의미합니까? “2”자체의 의미는 문맥 없이는 알 수없고 알 수 없으므로 사용이 불분명하고 혼동됩니다. 언어 의미 때문에 소프트웨어에 “2”만있는 것은 아니지만 “2”자체에는 특별한 의미가 없거나 명백한 목적 만 가지고 있지 않습니다.

우리의 고독한 “2”를 다음과 같은 맥락에 두자. padding := 2문맥이 “GUI 컨테이너”인 . 이와 관련하여 2의 의미 (픽셀 또는 기타 그래픽 단위)는 의미 (의미 및 목적)를 빠르게 추측 할 수있게합니다. 우리는 여기서 멈추고이 맥락에서 2가 괜찮다고 말할 수 있으며 우리가 알아야 할 것이 없습니다. 그러나 아마도 우리의 소프트웨어 세계에서 이것은 전체 이야기가 아닙니다. 그것에 더 많은 것이 있지만, 문맥으로 “padding = 2″는 그것을 드러 낼 수 없습니다.

우리 프로그램에서 2 개의 픽셀 패딩이 시스템 전체에서 “default_padding”다양성을 가지고 있다고 가정 해 봅시다. 따라서 지시를 작성하는 padding = 2것만으로는 충분하지 않습니다. “기본”의 개념은 공개되지 않습니다. 내가 쓸 때 : padding = default_padding문맥으로 그리고 다른 곳에서 : default_padding = 2나는 우리 시스템에서 2의 더 나은 의미 (의미 적 및 목적)를 완전히 실현합니까?

위의 예는 “2”자체만으로도 가능하기 때문에 꽤 좋습니다. “내 프로그램” default_padding의 GUI UX 부분에 2가있는 “내 프로그램”으로 이해의 범위와 영역을 제한 할 때만 , 적절한 문맥에서 “2”를 이해해야합니다. 여기서 “2”는 “마법의”숫자이며, default_padding“내 프로그램”의 GUI UX 컨텍스트 내에서 기호 상수를 고려 default_padding하여 묶는 코드의 더 큰 컨텍스트에서 빠르게 이해할 수 있도록 사용 합니다.

따라서 의미 (의미 및 목적)를 충분하고 신속하게 이해할 수없는 모든 기본 값은 기본 값 (예 : 마법 수) 대신 기호 상수에 적합한 후보입니다.

더 나아 가기

스케일의 숫자에도 의미가있을 수 있습니다. 예를 들어, 우리가 괴물이라는 개념을 가지고있는 D & D 게임을하는 것처럼 가장하십시오. 우리의 괴물 객체는 life_force정수 라는라는 기능을 가지고 있습니다. 숫자에는 의미를 제공 할 단어가 없으면 알 수 없거나 명확한 의미가 있습니다. 따라서 우리는 임의로 다음과 같이 말합니다.

  • full_life_force : INTEGER = 10-매우 살아 있음 (그리고 아프지 않음)
  • minimum_life_force : INTEGER = 1-간신히 살아 남음 (매우 손상됨)
  • 사망 : INTEGER = 0-사망
  • 언데드 : INTEGER = -1-최소 언데드 (거의 사망)
  • 좀비 : 정수 = -10-최대 언데드 (매우 언데드)

위의 상징적 인 상수로부터, 우리는 D & D 게임에서 우리의 몬스터에 대한 생존, 사망 및 “언데드”(그리고 가능한 결과 또는 결과)에 대한 정신적 인 그림을 얻기 시작합니다. 이 단어들 (기호 상수)이 없으면, 우리는 ~에 이르는 숫자들만 남게됩니다 -10 .. 10. 게임의 다른 부분이 무엇인지와 같은 다양한 작업의 숫자 수단의 범위에 대한 종속성이있는 경우 가능성이 큰 혼란의 장소에있는 단어 잎 우리없이 잠재적으로 우리의 게임에 오류가 그냥 범위 attack_elvesseek_magic_healing_potion.

따라서 “매직 숫자”의 대체를 검색하고 고려할 때 우리는 소프트웨어의 맥락에서 숫자와 숫자가 의미 적으로 상호 작용하는 방식에 대해 매우 의도적으로 채워진 질문을하고 싶습니다.

결론

어떤 질문을해야하는지 검토해 보겠습니다.

다음과 같은 경우 마법 번호가있을 수 있습니다 …

  1. 기본 가치가 소프트웨어 세계에서 특별한 의미 나 목적을 가질 수 있습니까?
  2. 특수한 의미 나 목적이 적절한 상황에서도 알려지지 않거나 알 수 없거나 불분명하거나 혼동 될 수 있습니까?
  3. 올바른 기본 가치를 잘못된 맥락에서 나쁜 결과로 부적절하게 사용할 수 있습니까?
  4. 부적절한 기본 가치가 올바른 맥락에서 나쁜 결과를 초래할 수 있습니까?
  5. 기본 값이 특정 상황에서 다른 기본 값과 의미 또는 목적 관계가 있습니까?
  6. 각각의 의미가 다른 코드에서 둘 이상의 위치에 기본 값이 존재할 수있어 독자에게 혼란을 줄 수 있습니까?

코드 텍스트에서 독립형 매니페스트 상수 기본 값을 검사하십시오. 그러한 가치의 각 사례에 대해 천천히 그리고 신중하게 질문하십시오. 답의 힘을 고려하십시오. 여러 번 대답은 흑백이 아니지만 의미와 목적, 학습 속도 및 이해 속도를 잘못 이해하는 음영이 있습니다. 또한 소프트웨어 소프트웨어가 주변의 소프트웨어 시스템에 어떻게 연결되어 있는지 확인해야합니다.

결국, 대체에 대한 대답은 독자의 강점 또는 약점의 측정치 (당신의 마음에)에 답하여 연결을 만드는 것입니다 (예 : “얻습니다”). 의미와 목적을 더 빨리 이해할수록 “마법”이 적습니다.

결론 : 마법이 혼동으로 인해 발생하는 버그를 감지하기 어려울 정도로 큰 경우에만 기본 값을 기호 상수로 대체하십시오.


답변

매직 넘버는 파일 형식 또는 프로토콜 교환을 시작할 때 일련의 문자입니다. 이 번호는 상태 점검 기능을합니다.

예 : GIF 파일을 열면 시작 부분에 GIF89가 표시됩니다. “GIF89″는 매직 넘버입니다.

다른 프로그램은 파일의 처음 몇 문자를 읽고 GIF를 올바르게 식별 할 수 있습니다.

임의의 이진 데이터는 동일한 문자를 포함 할 수 있습니다. 그러나 매우 가능성이 낮습니다.

프로토콜 교환과 관련하여 전달 된 현재 ‘메시지’가 손상되었거나 유효하지 않음을 신속하게 식별 할 수 있습니다.

매직 넘버는 여전히 유용합니다.


답변

프로그래밍에서 “마법의 숫자”는 상징적 인 이름을 부여해야하는 값이지만, 대신 일반적으로 여러 곳에서 리터럴로 코드에 삽입되었습니다.

SPOT (Single Point of Truth)이 좋은 것과 같은 이유로 나쁩니다. 나중에이 상수를 변경하려면 모든 인스턴스를 찾기 위해 코드를 찾아야합니다. 이 숫자가 무엇을 나타내는 지 다른 프로그래머에게 명확하지 않을 수 있기 때문에 “나쁜”마법이기도합니다.

사람들은 때때로 이러한 상수를 별도의 파일로 이동하여 구성으로 작동함으로써 마법 번호를 더 이상 제거하지 않습니다. 이것은 때때로 도움이되지만 가치보다 더 복잡해질 수도 있습니다.


답변

매직 넘버는 또한 특수한 하드 코딩 된 시맨틱을 가진 숫자 일 수도 있습니다. 예를 들어, 레코드 ID> 0이 정상적으로 처리되고 0 자체가 “새 레코드”이고 -1이 “이것이 루트”이고 -99가 “이것이 루트에 작성 됨”인 시스템을 본 적이 있습니다. 0과 -99는 WebService가 새 ID를 제공하게합니다.

나쁜 점은 특별한 능력을 위해 공백 (레코드 ID의 부호있는 정수)을 재사용한다는 것입니다. ID 0 또는 음수 ID를 사용하여 레코드를 만들지 않을 수도 있지만, 그렇지 않더라도 코드 나 데이터베이스를 보는 모든 사람이이 문제를 발견하고 처음에는 혼란 스러울 수 있습니다. 그 특별한 가치가 잘 문서화되지 않았다는 것은 말할 나위도 없습니다.

틀림없이, 22, 7, -12 ~ 620 도 매직 넘버로 계산. 😉