숙련 된 소프트웨어 개발자로서 나는 마법의 끈을 피하는 법을 배웠습니다.
내 문제는 내가 사용한 이후로 오랜 시간이 걸린다는 것인데, 그 이유를 대부분 잊어 버렸습니다. 결과적으로 저 경험이 적은 동료들에게 왜 문제인지 설명하는 데 어려움을 겪고 있습니다.
피해야 할 객관적인 이유는 무엇입니까? 어떤 문제가 발생합니까?
숙련 된 소프트웨어 개발자로서 나는 마법의 끈을 피하는 법을 배웠습니다.
내 문제는 내가 사용한 이후로 오랜 시간이 걸린다는 것인데, 그 이유를 대부분 잊어 버렸습니다. 결과적으로 저 경험이 적은 동료들에게 왜 문제인지 설명하는 데 어려움을 겪고 있습니다.
피해야 할 객관적인 이유는 무엇입니까? 어떤 문제가 발생합니까?
답변:
컴파일하는 언어에서는 컴파일 타임에 매직 문자열 값이 확인되지 않습니다 . 문자열이 특정 패턴과 일치해야하는 경우 해당 패턴에 맞는지 확인하기 위해 프로그램을 실행해야합니다. 열거 형과 같은 것을 사용하면 값이 잘못되어도 적어도 컴파일 타임에 값이 유효합니다.
매직 스트링이 여러 곳에서 쓰여지는 경우, 컴파일 타임 오류와 같은 안전없이 모든 스트링 을 변경해야합니다 . 그러나 한 곳에서만 선언하고 변수를 재사용하여 대응할 수 있습니다.
오타는 심각한 버그가 될 수 있습니다. 기능이있는 경우 :
func(string foo) {
if (foo == "bar") {
// do something
}
}
누군가 실수로 다음을 입력합니다.
func("barr");
특히 프로젝트의 모국어에 익숙하지 않은 프로그래머가있는 경우 문자열이 더 드물거나 복잡해집니다.
마술 줄은 거의 자기 문서화가 아닙니다. 하나의 문자열이 보이면 문자열이 무엇을 할 수 있는지 / 아무것도 말하지 않아도됩니다. 올바른 문자열을 선택했는지 확인하려면 구현을 조사해야 할 것입니다.
이러한 종류의 구현은 누출 되어서, 특히 문서화해야 할 점을 이해하기 위해 외부 문서 나 코드에 액세스해야합니다.
IDE에서 "find string"함수가 부족하면 패턴을 지원하는 도구가 거의 없습니다.
우연히 두 곳에서 동일한 마술 줄을 사용할 수 있습니다. 실제로 다른 것들 일 때 찾기 및 바꾸기를 수행하고 둘을 변경하면 다른 곳이 작동하는 동안 둘 중 하나가 깨질 수 있습니다.
다른 답변이 파악한 것에 대한 정상 회담은 "마법의 가치"가 나쁘다는 것이 아니라 다음과 같아야한다는 것입니다.
일반적으로 허용되는 "상수"와 "마법의 가치"를 구별하는 것은 이러한 규칙 중 하나 이상을 위반하는 것입니다.
잘 사용하면 상수를 사용하면 코드의 특정 공리를 표현할 수 있습니다.
위의 기준을 준수하더라도 (특히 그 값에서 벗어난 경우) 과도한 상수 사용 (따라서 값으로 표현 된 과도한 수의 가정 또는 제약 조건)을 마지막으로 알려줍니다. 고안 된 솔루션이 충분히 일반적이거나 잘 구조화되어 있지 않다는 것을 암시 할 수 있습니다 (따라서 우리는 더 이상 상수의 장단점에 대해 이야기하는 것이 아니라 잘 구성된 코드의 장단점에 대해 이야기하고 있습니다).
고급 언어에는 상수를 사용해야하는 하위 언어의 패턴에 대한 구성이 있습니다. 같은 언어를 더 높은 수준의 언어로 사용할 수도 있지만 그렇게해서는 안됩니다.
그러나 그것은 모든 상황에 대한 인상과 해결책이 어떤 모습이어야하는지에 기초한 전문가 판단 일 수 있으며, 그 판단이 어떻게 정당화 될 것인지는 상황에 따라 크게 좌우 될 것입니다. 실제로 그것은 "나에게 익숙하고 더 잘한 이런 종류의 일을 이미 보았을만큼 나이가 든다"고 주장하는 것을 제외하고는 일반적인 원칙의 관점에서 정당화 될 수 없다!
편집 : 하나의 편집을 수락하고 다른 편집을 거부했으며 이제 내 자신의 편집을 수행 한 후 이제 규칙 목록의 형식 및 문장 스타일을 한 번에 설정하는 것이 좋습니다.
value / 2
값을 value / VALUE_DIVISOR
사용하는 것보다 간단히 작성하는 것이 더 명확하고 간단 할 수 있습니다 2
. CSV를 처리하는 메서드를 일반화하려는 경우 구분 기호를 매개 변수로 전달하고 상수로 정의하지 않는 것이 좋습니다. 그러나 그것은 맥락에서 판단의 문제입니다. @WGroleau의 예제는 SPEED_OF_LIGHT
명시 적으로 이름을 지정하고자하는 것이지만 모든 리터럴이 이것이 필요한 것은 아닙니다.
실제 예 : "엔터티"가 "필드"와 함께 저장되는 타사 시스템을 사용하고 있습니다. 기본적으로 EAV 시스템. 다른 필드를 추가하는 것은 상당히 쉬우므로 필드 이름을 문자열로 사용하여 필드에 액세스 할 수 있습니다.
Field nameField = myEntity.GetField("ProductName");
(매직 문자열 "ProductName"참고)
이로 인해 몇 가지 문제가 발생할 수 있습니다.
그래서 이것에 대한 해결책은 엔티티 유형별로 구성된 이러한 이름에 대한 상수를 생성하는 것이 었습니다. 이제 사용할 수 있습니다 :
Field nameField = myEntity.GetField(Model.Product.ProductName);
여전히 문자열 상수이며 정확히 동일한 이진으로 컴파일되지만 몇 가지 장점이 있습니다.
다음으로 내 목록에서 : 생성 된 강력한 형식의 클래스 뒤에 이러한 상수를 숨기면 데이터 형식도 보호됩니다.
nameField = myEntity.ProductName;
.
마법의 끈 이 항상 나쁘지 는 않기 때문에 이것이 피할 수있는 담요 이유를 생각해 낼 수없는 이유 일 수 있습니다. ( "마법 문자열"은 표현식의 일부로서 상수로 정의되지 않은 문자열 리터럴을 의미한다고 가정합니다.)
특정한 경우에, 매직 스트링은 피해야합니다 :
그러나 어떤 경우에는 "매직 스트링"이 좋습니다. 간단한 파서가 있다고 가정 해보십시오.
switch (token.Text) {
case "+":
return a + b;
case "-":
return a - b;
//etc.
}
여기에는 실제로 마술이 없으며 위에서 설명한 문제 중 어느 것도 적용되지 않습니다. IMHO string Plus="+"
등 을 정의하면 이점이 없습니다 . 단순하게 유지하십시오.
if (dx != 0) { grad = dy/dx; }
. 에서 0을 magic이라고 합니다.
"+"
과 "-"
함께 TOKEN_PLUS
와 TOKEN_MINUS
. 내가 읽을 때마다 나는 그것 때문에 읽고 디버깅하기가 더 어렵다고 생각했습니다! 분명히 간단한 문자열을 사용하는 것이 더 낫다는 데 동의하는 곳입니다.
기존 답변에 추가하려면
화면에 표시 할 텍스트가 하드 코딩되어 기능 계층 내에 묻혀 있으면 해당 텍스트의 번역을 다른 언어로 제공하기가 매우 어려울 것입니다.
일부 개발 환경 (예 : Qt)은 기본 언어 텍스트 문자열에서 번역 된 언어로 조회하여 번역을 처리합니다. 매직 스트링은 일반적으로 다른 곳에서 동일한 텍스트를 사용하고 오타를 원할 때까지 일반적으로이 상태를 유지합니다. 그럼에도 불구하고 다른 언어에 대한 지원을 추가하려고 할 때 어떤 마술 문자열을 번역해야하는지 찾기가 매우 어렵습니다.
일부 개발 환경 (예 : MS Visual Studio)은 다른 접근 방식을 취하며 변환 된 모든 문자열을 리소스 데이터베이스 내에 보유하고 해당 문자열의 고유 ID로 현재 로캘을 다시 읽어야합니다. 이 경우 마술 줄을 사용하는 응용 프로그램은 주요 재 작업 없이는 다른 언어로 번역 할 수 없습니다. 효율적인 개발을 위해서는 모든 텍스트 문자열을 리소스 데이터베이스에 입력하고 코드를 처음 작성할 때 고유 한 ID를 부여해야하며, 이후 i18n은 비교적 쉽습니다. 사실 이후에 백업을 시도하려면 일반적으로 매우 많은 노력이 필요하며 (그렇습니다. 나는 그곳에있었습니다!) 처음부터 올바르게하는 것이 훨씬 좋습니다.
이것이 모든 사람에게 우선 순위는 아니지만 자동화 된 방식으로 코드에서 커플 링 / 결합 메트릭을 계산하려면 마술 문자열이 거의 불가능합니다. 한 곳에서 문자열은 다른 곳에서 클래스, 메서드 또는 함수를 참조하며 코드를 구문 분석하는 것만으로 문자열이 클래스 / 방법 / 함수에 연결되어 있는지 쉽게 확인할 수있는 방법은 없습니다. 기본 프레임 워크 (예 : Angular) 만 링크가 있는지 결정할 수 있으며 런타임에만 할 수 있습니다. 커플 링 정보를 직접 얻으려면 파서는 코딩하는 기본 언어 이상으로 그리고 사용중인 프레임 워크에 대한 모든 것을 알아야합니다.
그러나 이것은 많은 개발자들이 관심을 갖는 것이 아닙니다.