이것이 상징적 인 상수 오버 킬을 사용합니까? 대신해야한다고 주장하면서 for (int

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

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. 체스 프로그램의 소스 코드를 사용하는 사람이라면 누구나 체스에 대해 충분히 알고 있어야합니다.

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

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



답변

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

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

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

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


답변

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

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

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

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

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


답변

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

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

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

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

당신은 결코 Gonna (TM)를 9×9 체스 프로그램으로 바꾸지 않으며, 그렇게한다면, 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”이 없으면 잊어 버리십시오.