이것이 상징적 인 상수 오버 킬을 사용합니까?


34

저는 소프트웨어 공학에 익숙하지 않아서 학습 연습으로 체스 게임을 썼습니다. 내 친구가 그것을 보았고 내 코드가 다음과 같이 지적되었습니다.

for (int i = 0; i < 8; i++){
    for (int j = 0; j < 8; j++){

그가 대신해야한다고 주장하면서

for (int i = 0; i < CHESS_CONST; i++){
    for (int j = 0; j < CHESS_CONST; j++){

더 좋은 심볼 이름으로 지금 당장 생각할 필요가 없습니다.

물론 나는 일반적으로 마법의 숫자를 사용하지 않는 것을 알고 있지만

  1. 이 숫자는 절대 바뀌지 않습니다.
  2. 코드 전체의 많은 장소에서 숫자가 사용되기 때문에 이름은 어쨌든 설명 적이 지 못했습니다. 과
  3. 체스 프로그램의 소스 코드를 사용하는 사람이라면 누구나 체스에 대해 충분히 알고 있어야합니다.

실제로 기호 상수가 필요하지 않습니다.

그래서 어떻게 생각하세요? 이것은 과잉입니까, 아니면 그냥 관례를 가지고 기호를 사용해야합니까?


46
CHESS_CONST는 숫자 8을 사용하는 것보다 훨씬 나쁘지만 설명적인 이름을 가진 상수가 향상됩니다. 코드에서 8의 의미를 알아야한다고 말하지만 이것은 사실이 아닙니다. 문맥이없는 정수 리터럴은 많은 움직임, 보드의 조각 수 등과 같은 여러 가지를 의미 할 수 있습니다. 상수에 대한 설명적인 이름은 의도를 명확하게하여 코드를 이해하기 쉽게 만듭니다.
JacquesB

43
개인적으로, 마법의 숫자보다 훨씬 더 엉망인 것은 이름 ij루프 변수입니다. 나는 내 삶에서 어느 쪽이 계급을 대표하고 어떤 것이 파일을 대표해야 하는지를 알아낼 수 없다. 계급은 1..8 범위 및 파일 a..h에 이르기까지 다양하지만, 귀하의 경우, 모두 ij범위 0..7에서, 그래서 나를 이는 확인할 도움이되지 않습니다. 내가 모르는 어떤 국제 편지 부족 위기가 있는가, 또는 무엇에 이름을 변경에 이상이 rankfile?
Jörg W Mittag

4
악마의 옹호자를 잠시 플레이하십시오. 누군가가 마법의 숫자 8을 사용한 곳에서 체스 코드를 읽는다고 상상해보십시오. 자신이 무엇을 사용하는지 알 수 있습니까? 어떻게 100 % 확신 할 수 있습니까? 다른 의미가있을 가능성이 있습니까? 당신이 가정을하지 않아도 조금 더 좋았을까요? 가정이 올바른지 알아 내기 위해 코드를 추적하는 데 얼마나 많은 시간을 할애 할 수 있습니까? 의미 있고 통찰력있는 이름을 사용하여 코드 자체 문서화 작업을 수행 한 경우 시간을 줄이겠습니까?
벤 Cottrell

16
@JacquesB : 참으로. 8 등급, 8 파일, 8 폰이 있습니다. 일부 체스 엔진은 특정 조각, 특정 필드 및 특정 동작에 점이 첨부되어 있고 점수가 가장 높은 동작을 선택하는 포인트 시스템을 사용합니다. 8은 그런 점수 일 수 있습니다. 8이 기본 검색 깊이 일 수 있습니다. 거의 모든 것이 될 수 있습니다.
Jörg W Mittag

9
예를 들어 foreach 루프를 사용하는 것이 foreach(var rank in Ranks)좋습니다. 또한 두 루프를 각 요소가 (순위, 파일) 튜플 인 하나로 병합하는 것을 고려할 것입니다.
코드 InChaos

답변:


101

IMHO 당신의 친구는 상징적 인 이름을 사용하는 것이 옳습니다.하지만 그 이름은 분명히 더 설명 적이어야한다고 생각합니다 (예 : BOARD_WIDTH대신 CHESS_CONST).

프로그램 수명 기간 동안 숫자가 변경되지 않더라도 다른 의미로 숫자 8이 발생하는 다른 위치가 프로그램에있을 수 있습니다. BOARD_WIDTH보드 너비가 의미 하는 곳마다 "8"을 바꾸고, 다른 의미가있을 때 다른 기호 이름을 사용하면 이러한 다른 의미가 명확하고 명백하며 전체 프로그램을 더 읽기 쉽고 유지 관리 할 수 ​​있습니다. 또한 보드 너비에 따라 코드의 모든 위치를 신속하게 식별해야하는 경우 프로그램을 통해 전역 검색 (또는 환경이 제공하는 경우 역방향 기호 검색)을 수행 할 수도 있습니다.

숫자의 이름을 선택하는 방법에 대한 설명 은이 전 SE.SE 게시물 을 참조하십시오 .

참고로 여기에서 주석에서 논의되었으므로 실제 프로그램 코드에서 변수 가 보드의 i행과 j열을 참조 하는지 또는 그 반대 인지 여부가 중요하다면 변수 이름을 선택하는 것이 좋습니다. 같은 구분을 명확하게 row하고 col. 이러한 이름의 장점은 잘못된 코드잘못 보이게 한다는 것입니다.


22
OP가 정말 훌륭한 체스 엔진을 작성한 경우 3D 체스 또는 다른 변형을 포함하도록 확장하고 싶었다면 8 대를 바꿔야 할 과제가 될 것입니다.
Steve Barnes

32
@SteveBarnes : "이 프로그램을 다른 종류의 게임으로 만드는 것과는 매우 다른 것 같아서 마법의 숫자 8을 그대로 둘 수 있습니다. "
Doc Brown

4
@IllusiveBrian 그것은 두 가지 이유에서 고전적인 "짚맨"주장입니다 : (1) 상수를 정의한다고해서 프로그래머가 여전히 "8"을 입력 할 수 없다는 것을 의미하지는 않습니다. BOARD_WIDTH = 8 상수가 있다고해서 BOARD_WIDTH 가 프로그램의 특정 위치에서 사용할 올바른 상수 가되지는 않습니다 .
alephzero

3
@Blrfl ... 또는 코드를 과도하게 엔지니어링하게됩니다. 미래의 변화를 인식하고 그에 따라 코드를 작성하는 것은 개발자의 책임입니다. 요구 사항과 같은 코딩은 변경되지 않지만 문제는 발생하지 않습니다.
Malcolm

4
@corsiKa 루프 변수가 물리적 축에 해당하는 경우 x, y 또는 row, col 또는 체스, 파일, 순위로 이름을 지정해야합니다.
user949300

11

좋아, 여기 몇 가지 의견이 있습니다.

마법의 숫자를 제거하는 것이 좋습니다. DRY라는 개념이 있는데, 종종 잘못 표현되지만 아이디어는 프로젝트의 개념에 대한 지식을 복제하지 않는다는 것입니다. 따라서 ChessBoard라는 클래스가 있으면 BOARD_SIZE 또는 ChessBoard.SIZE라는 상수를 유지할 수 있습니다. 이런 식으로이 정보를 얻을 수있는 유일한 소스가 있습니다. 또한 이것은 나중에 가독성에 도움이됩니다.

for (int i = 0; i < ChessBoard.SIZE; i++){
  for (int j = 0; j < ChessBoard.SIZE; j++){

숫자가 변하지 않더라도 프로그램이 더 좋습니다. 코드를 읽는 사람은 코드가 수행하는 작업에 대한 자세한 정보를 알고 있습니다.

나쁜 이름은 이름이없는 것보다 나쁘지만 이름을 지어서는 안된다는 의미는 아닙니다. 이름 만 바꾸면됩니다. 목욕물로 아기를 버리지 마십시오. : p 설명하는 내용을 잘 이해하면 이름을 설명 할 수 있습니다. 그런 다음이 개념을 여러 가지 다른 용도로 사용할 수 있습니다.


8
이것은 단지 이미 정답으로 설명한 점을 반복하는 것으로 보인다
gnat

-7

실제로 원하는 것은 상수에 대한 광고 구역 참조가 이름 이건 아니건 상관없이 제거 하는 것입니다.

for_each_chess_square (row, col) {
  /*...*/
}

이러한 루프를 반복하여 상수를 실제로 늘리려면를 사용하는 것이 가장 좋습니다 8.

8자기 서술 적이다. 그것은 다른 것을 나타내는 매크로가 아닙니다.

당신은 결코 Gonna (TM)를 9x9 체스 프로그램으로 바꾸지 않으며, 그렇게한다면, 8의 확산은 큰 어려움이되지 않을 것입니다.

토큰 8에 대한 150,000 라인 코드 기반을 검색하고 어떤 발생이 초 단위를 의미하는지 분류 할 수 있습니다.

체스 지식이 가능한 한 적은 곳에 집중되도록 코드를 모듈화하는 것이 훨씬 더 중요합니다. 기호 이름을 통해 8을 참조하는 체스 고유의 책임으로 묶인 36 개의 모듈보다 리터럴 8이 발생하는 1, 2, 3 개의 체스 특정 모듈을 갖는 것이 좋습니다.

이 8 상수가 프로그램에서 긴장의 원천이 될 때 또는 그 때 쉽게 고칠 수 있습니다. 지금 일어나고있는 실제 문제를 해결하십시오. 당신이 그 특정 8에 의해 방해를 느끼지 않는다면, 그 본능에 따라 가십시오.

앞으로 대체 보드 크기를 지원하려고한다고 가정하십시오. 이 경우 이러한 루프는 명명 된 상수를 사용할지 또는를 사용할지 여부를 변경해야 8합니다. 치수는 board.widthand와 같은 일부 표현식으로 검색되기 때문 board.height입니다. 당신이있는 경우 BOARD_SIZE대신 8,이 장소는 쉽게 찾을 수있을 것입니다. 따라서 노력이 줄어 듭니다. 그러나, 우선 교체 8로 인한 노력을 잊지 말아야합니다 BOARD_SIZE. 전반적인 노력은 낮지 않습니다. 코드를 변경 8하여 로 변경 BOARD_SIZE한 다음 다른 8차원을 지원하도록하는 것은 대체 차원 지원으로 가는 것보다 저렴하지 않습니다 .

또한 순전히 차갑고 객관적인 위험 / 혜택 분석에서이를 확인할 수 있습니다. 이 프로그램에는 현재 상수가 있습니다. 이것들이 상수로 대체되면 아무런 이점이 없습니다. 프로그램은 동일합니다. 변경하면 0이 아닌 위험이 있습니다. 이 경우에는 작습니다. 그럼에도 불구하고 이익 없이는 위험을 감수해서는 안됩니다. 이러한 추론에 맞서 변화를 "판매"하기 위해서는, 다른 프로그램에 도움이 될 미래의 이점, 현재 존재하지 않는 프로그램의 미래 버전이라는 이점을 가정해야합니다. 그러한 프로그램이 계획되고 있다면,이 가설과 그와 관련된 추론은 선의의 것이며 진지하게 받아 들여 져야합니다.

예를 들어, 이러한 상수를 더욱 확산시킬 수있는 코드를 더 추가 할 필요가 없다면이를 제거 할 수 있습니다. 상수의 인스턴스가 대략 존재할 모든 인스턴스라면 왜 귀찮게합니까?

상용 소프트웨어를 사용하는 경우 ROI 인수도 적용됩니다. 프로그램이 판매되지 않고 일부 하드 코딩 된 숫자를 상수로 변경해도 판매가 개선되지 않으면 노력에 대한 보상이 이루어지지 않습니다. 시간 투자에 대한 변경은 0으로 돌아갑니다. ROI 논쟁은 돈을 넘어 일반화합니다. 당신은 프로그램을 작성하고 시간과 노력을 투자하고 무언가를 얻었습니다. 그것은 당신의 귀환, "R"입니다. 만약 그 변화를 혼자서한다면, "R"을 더 많이 얻게됩니다. 추가 개발 계획이 있고 그 변경으로 인해 "R"이 향상된다면, 위험합니다. 변경 사항에 즉각적이거나 예측 가능한 "R"이 없으면 잊어 버리십시오.


13
8그 자체 설명이 아니라, 그것은 무엇이든 의미 할 수있는 숫자입니다. 그리고 그들은 9x9 체스 게임을하고 싶을 수도 있습니다. 150,000 줄의 코드가 있다면 코드에서 각각의 8의미 를 기억할 수있는 방법이 없으며 , 가능하다면 왜 그럴까요? 그것은 많은 번거 로움입니다. 지금까지 교체 모듈화 등 8처럼 무언가 NUM_RANKS가 어설프게에 코드 쉽게 만들기 때문에, 사실, 그렇지 않은 상처 모듈화를 할 수 없습니다.
Jerfov2

4
@ Kaz 나도 그렇게합니다. 그런 다음 소수의 사용법이 내가 생각했던 것과 다르기 때문에 심각한 이상한 버그가 발생합니다. 대량의 교체에 많은 관심을 기울이고 매번 수정하기가 어렵 기 때문입니다. 이런 이유로 나는 처음에이 시나리오에 들어가는 것을 피하기 때문에, 묵과하는 조언을 뒷받침 할 수 없습니다.
doppelgreener

1
"그러나, 당신은 대체의 노력에 대해 잊지 말아야 8BOARD_SIZE처음에" 각이 무엇을 내려고 코드를 통해 자세히 조사 소요했던 시간 - 8대부분의 시간을 대체 소요 초과 지금부터 프로그램 달에서와 8함께 의미있는 모듈 수준 상수.
Christian Dean

1
@doppelganger 그 시나리오는 이미 여기 있습니다. 나는 상수를 사용하는 체스 프로그램을 가져 와서 8로 대체하지 않는다. "아직 작성되지 않은 체스 프로그램에서 상수를 사용하지 않을 계획"
Kaz

1
@Kaz 왜 당신이 8 주위의 모든 코드를 읽도록하고 싶을 수도 있고, 의미있는 이름으로 3 초를 더 쓸 수있을 때 때때로 문맥이 잘못 될 수 있습니까? 상수의 실제 값을 아는 경우 코드의 마법 정수가 무엇을 의미하는지 역 엔지니어링하는 것보다 변수의 정확한 값을 찾는 것이 훨씬 쉽습니다.
Jerfov2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.