코드를 볼 때 어떤 것이 즉시 알람 벨을 울립니 까? [닫은]


98

몇 주 전에 저는 소프트웨어 장인 행사에 참석했으며 한 의견은 "우리가 볼 때 나쁜 코드를 모두 알아볼 것"이라고 말했으며 모두가 더 이상의 논의없이 현혹하게 고개를 끄덕였습니다.

모든 사람들이 자신이 평균 이상의 드라이버라고 생각하는 진실이 있기 때문에 이런 종류의 일은 항상 나를 걱정합니다. 나는 나쁜 코드를 인식 할 수 있다고 생각하지만 다른 사람들이 코드 냄새로 간주하는 것에 대해 사람들의 블로그와 소수의 책에서만 자세히 설명하지 않기 때문에 더 배우고 싶습니다. 특히 한 언어에서는 냄새가 나지만 다른 언어에서는 냄새가 나는 것을 듣는 것이 흥미로울 것 같습니다.

쉬운 것부터 시작하겠습니다.

주석 처리 된 코드의 비율이 높은 소스 제어의 코드 -왜 존재합니까? 삭제 되었습니까? 반 완성 된 작품인가요? 아마도 주석 처리되어서는 안되며 누군가가 무언가를 테스트 할 때만 수행 되었습니까? 개인적으로 나는 이런 종류의 것이 여기저기서 이상한 라인 일지라도 실제로 성가신 것을 알지만, 큰 코드가 나머지 코드와 산재되어 있으면 완전히 받아 들일 수 없습니다. 또한 일반적으로 나머지 코드의 품질이 모호 할 수 있음을 나타냅니다.


61
코드를 주석 처리하고 체크인 한 다음 "이제 코드를 제거하면 나중에 다시 필요할 수 있습니다."라고 말하는 사람들이있는 경우가 있습니다. "Er, ... 그것이 소스 제어의 목적"입니다.
talonx

6
때로는 최적화 할 때 이전 코드를 주석으로 남겨 두는 것이 편리하므로 모호한 최적화 된 코드가 무엇을 대체하는지 알 수 있습니다. 1 라인 비트 트위들 링 스왑으로 교체 할 때 임시로 3 라인 스왑을 남겨 두는 것을 고려하십시오. (프로그램 크기가 중요하지 않은 한, 한 줄 스왑을 사용할 필요는 없습니다.)
Chris Cudmore

4
유용한 엔지니어를 코딩했지만 프로그래머가 아니라는 것을 인정하는 엔지니어 중 한 명이 작성한 코드를 유지 / 정리하고 있습니다. 내가 자료를 통합함에 따라 그의 이전 코드를 주석 처리 한 다음 나중에 변경 사항을 검토하고 이해하기 쉽도록 더 작고 효율적이며 더 쉬운 것으로 대체하는 방법을 보여줍니다. 그 후 나는 그 블록을 제거하고 그것을 체크인합니다. 오래된 코드를 가지고 있으면 작업이 더 간단하게 수행 될 수있는 방법을보고 대화 할 때 왜 변경했는지를 기억할 수 있기 때문에 이점이 있습니다.
틴 남자

8
1 커밋에 대해 "사용할 수있는"항목을 남겨둔 다음, 문제가 발생하지 않거나 필요를 찾지 못하면 다음 커밋에서 제거됩니다.
Paul Nathan

24
흠. printf("%c", 7)일반적으로 나를 위해 알람 벨을 울립니다. ;)

답변:


128
/* Fuck this error */

일반적으로 넌센스 try..catch블록 내부에서 발견되며 내 관심을 끌기 쉽습니다. 뿐만 아니라 /* Not sure what this does, but removing it breaks the build */.

몇 가지 더 :

  • 여러 개의 중첩 된 복잡한 if명령문
  • 정기적으로 논리 흐름을 결정하는 데 사용되는 try-catch 블록
  • 일반적인 이름과 기능 process, data, change, rework,modify
  • 100 줄의 6 가지 또는 7 가지 다른 브레이스 스타일

방금 찾은 것 :

/* Stupid database */
$conn = null;
while(!$conn) {
    $conn = mysql_connect("localhost", "root", "[pass removed]");
}
/* Finally! */
echo("Connected successfully.");

MySQL 연결을 무차별하게 수행하는 것이 올바른 방법입니다. 데이터베이스에 연결 수에 문제가있어 시간이 초과되지 않았습니다. 이를 디버깅하는 대신 작동 할 때까지 반복해서 시도했습니다.


19
6 번만 공표 할 수 있다면! 모든 좋은 예. 또한 오만한 / 재미있는 의견 (특히 욕설을 포함하는 경우)을 싫어합니다. 처음 읽을 때는 약간 재미 있지만 아주 오래되어 산만하게됩니다.
FinnNk

5
나는 당신의 예를 좋아하지만, 특정 상황에서는 여러 개의 중첩 된 if 문을 피할 수 없다고 말할 것입니다. 많은 비즈니스 로직을 사용하면 코드가 약간 혼란 스러울 수 있지만, 비즈니스 자체가 처음부터 혼란 스러우면 코드를 단순화하는 것이 프로세스를 덜 정확하게 모델링하는 것입니다. 아인슈타인이 말한 것처럼 : "사물은 가능한 한 단순해야하며 조금 단순하지 않아야합니다."
Morgan Herlocker

2
@Prof Plum-어떤 예를 들어 줄 수 있습니까? 일반적으로 여러 개의 중첩 된 if의 대안은 여러 메소드로 나누는 것입니다. 주니어 개발자는 if보다 덜 바람직하지 않은 것처럼 이것을 피하는 경향이 있습니다. 그러나 보통 누르면 "줄이 더 적을 경우"라고 말합니다. OOP에 확신이있는 사람이 들어와 줄 수를 줄이려면! OP가 더 좋습니다.
STW

2
@STW 좋은 지적이지만 중첩의 깊이에 달려 있다고 말할 것입니다. 나는 세 개 이상의 깊숙한 곳이 털이 많기 때문에 리팩토링이 필요한 경우가 많다는 것에 분명히 동의한다. 그러나 보험 견적은 다중 중첩이 실제로 실제 세계를 잘 모델링 할 수있는 좋은 예입니다. 특정 요율 / 프리미엄을 제외하고, 매뉴얼은 문자 그대로 "이것이 부동산이고 최저 요금이 5.6 미만이고 NC에 있고 구내에 보트가있는 경우 다음과 같이 수행합니다. 이러한." 다른 많은 옵션으로.
Morgan Herlocker

4
@josh, "그들"이 동료라면 "우리"라고 말하지 않은 이유에 대해 숙고 할 것입니다.

104

저에게있어 주요 위험 신호는 중복 된 코드 블록입니다. 이는 프로그래밍 기초를 이해하지 못했거나 기존 코드베이스를 적절히 변경하기에는 너무 무서웠 ​​음을 보여주기 때문입니다.

나는 또한 의견이 부족한 적을 붉은 깃발로 생각했지만 최근에는 의견이없는 아주 좋은 코드를 많이 사용하여 다시 완화했습니다.


1
+1 : Linux 전문가로 자신을 선전 한 동료의 코드를 보았습니다. 그는 리눅스 전문가로서 하나의 긴 함수로 간단한 반복 응용 프로그램을 작성했습니다. Yikes.
KFro

4
@KFro, 루프 언 롤링입니다. 그것이 컴파일러가 항상하는 일입니다. :) 매우 효율적입니다!

3
@Thorbjorn : 때로는 컴파일러를 조금 도와 줘야합니다. 결국, 당신은 똑똑한 인간이며 그는 멍청한 컴퓨터 일뿐입니다.
yatima2975

3
내가 본 또 다른 이유 : 컨설턴트가 가능한 빨리 기능을 구현하도록 비용을 지불했습니다 (물론 테스트와 문서도 누락 된 것입니다). 복사 / 붙여 넣기는 올바른 방법을 생각하는 것보다 빠릅니다.
LennyProgrammers

4
코드 중복을 피하는 것은 강박 관념 일 수 있습니다. C ++과 같은 언어에서는 다양한 부분을 제외하고 여전히 강력하고 효율적인 코드를 유지하는 것만 큼 쉽지만은 않습니다. 때로는 약간의 잘라 내기 및 붙여 넣기가 더 실용적인 옵션입니다. 또한 최적화 원칙을 적용 할 수 있습니다. 잘라 내기 및 붙여 넣기를 사용 하면 필요한 경우 나중에 리팩토링 할 수있는 빠르고 쉬운 솔루션을 얻을 수 있습니다 . 나중에 유지 관리 문제를 해결할 수도 있지만 지금 당장 지연을 피하고 있다는 것을 알고 있습니다.
Steve314

74

실제 가치가 없다는 사실에도 불구하고 프로그래머가 얼마나 영리한지 보여 주려고 시도하는 코드 :

x ^= y ^= x ^= y;

12
와우, 그것은 훨씬 더 읽기 쉽다swap(x, y);
JBRWilkinson

8
x와 y가 포인터이고이 할당이 합당한 시간 동안 수행되면 Boehm GC와 같은 보수 가비지 수집기 제대로 중단 됩니다.
SingleNegationElimination

12
그건 그렇고,이 코드는 개입 시퀀스 포인트없이 여러 변경 때문에 C 및 C ++에서 정의되지 않았습니다.
fredoverflow

9
그것을 보면서, 마음에 떠오른 유일한 것은 이모티콘이었습니다.^_^
Darien

62
  • 20,000 (과장) 라인 기능. 두 개 이상의 화면을 차지하는 모든 기능에는 리팩토링이 필요합니다.

  • 같은 줄을 따라 계속 진행되는 클래스 파일. 원래 클래스의 목적과 기능을 명확하게하는 클래스로 추상화 할 수있는 몇 가지 개념이있을 수 있습니다.

  • 비 설명 적, 사소하지 않은 변수 또는 너무 많은 사소한 비 설명 적 변수 이것들은 실제로 일어나는 수수께끼를 추론합니다.


9
가능할 때마다 기능을 1 화면으로 제한하는 경향이 있습니다.
Matt DiTrolio

20
1 화면은 스트레치입니다. 10 줄 정도 지나면 더러워지기 시작합니다.
Bryan Rowe

54
좋아, 나는 인기가없는 의견이 무엇인지 말하려고한다. 필자는 개발자가 일부 "기능은 짧아야한다"는화물 문화에 집착하기 때문에 별도의 기능으로 분리 된 원 자형의 상단에서 하단 프로세스 인 기능을 작성하는 것이 코드 냄새라고 말한다. 함수는 신화적인 "올바른 크기"여야하기 때문에 기능 행을 따라 끊어야합니다. 이것이 바로 FUNCTIONS라고하는 이유입니다.
Dan Ray

7
@ Dan, 함수는 짧아지기 위해 짧아서는 안되지만 한 번에 머리에 넣을 수있는 정보는 너무 많습니다. 어쩌면 나는 한계가 몇 화면이라는 작은 뇌를 가지고있을 것입니다 :). 실수를 피하기 위해 경계를 테스트해야 할 때 함수를 여러 함수로 나눕니다. 한편으로는 캡슐화를 제공하므로 더 높은 수준에서 생각할 수 있고 다른 한편으로는 발생하는 것을 숨기므로 함수 작동 방식을 해결하기가 더 어려워집니다. 나는 '완벽한 길이'에 맞지 않기 위해 가독성을 돕기 위해 함수를 분해해야한다고 생각합니다.
도미니크 맥도넬

6
@Dominic, @ Péter, 저는 우리 셋이 실제로 같은 말을하고 있다고 생각합니다. 더 작은 함수로 코드를 팩토링해야 할 이유가 있다면 그럴 것입니다. 내가 거부하는 것은 기능 설계 가 부족 하기 때문에 부족하다는 것 입니다. 알다시피, 호출 스택은 필요한 것보다 3 배 더 길지만 적어도 그러한 기능은 짧습니다. 차라리 이전에 호출 된 수십 개의 체인 함수를 통해 실행 경로를 추적하는 것보다 한 가지 일을 명확하고 명확하게 수행하는 키 큰 함수를 디버깅하고 싶습니다.
Dan Ray

61
{ Let it Leak, people have good enough computers to cope these days }

더 나쁜 것은 상용 라이브러리에서 나온 것입니다!


32
알람 벨이 울리지 않습니다. 그것은 실제로 다리 사이에서 당신을 차 버립니다.
Steven Evers

15
딸은 마약 중독자입니다. 누가 신경 쓰는지, 적어도 그녀는 비만이되지 않을 것입니다. :: sigh ::
Evan Plaice

17
곤경에 처했을 때, 어머니 분투가 온다. 지혜로운 말을하면 새어 나옵니다. 하자 ..하자. 누출하자 오 누출. 한 번만 누출되면 누출이 아닙니다. (먼저 읽으면 +1). 나는 정말로 디카 프를 고려해야합니다.
Tim Post

13
"마감일이 다가 오면서 LEAKS는 누군가가 'Write in C ...... eeeeee !!!'을 속삭이는 곳을 모두 볼 수있다"
chiurox

9
옛날 옛적에 두 개의 OS가있었습니다. 하나는 49 일 이상 달렸 으면 새고 추락했고 다른 하나는 완벽했고 영원히 도망 쳤습니다. 하나는 1995 년 거대한 팬 페어로 시작되었고 수백만 명의 사람들이 사용했습니다. 다른 하나는 버그가 없는지 여전히 확인하기 때문에 배송되지 않았습니다. 철학과 공학에는 차이가 있습니다.
Martin Beckett

53

너무 자세한 주석은 영어 컴파일러가 있으면 컴파일하고 완벽하게 실행하지만 코드에서 설명하지 않는 것은 설명하지 않습니다.

//Copy the value of y to temp.
temp = y;
//Copy the value of x to y.
y = x;
//Copy the value of temp to x.
x = temp;

또한 제거 할 수있는 코드에 대한 주석에는 코드가 몇 가지 기본 지침을 준수했습니다.

//Set the age of the user to 13.
a = 13;

15
그것은 COBOL이라고합니다 :-)
Gaius

26
두 번째 경우는 최악이 아닙니다. 최악은 : / * 사용자의 연령을 13으로 설정 * / a = 18;
PhiLho

4
@PhiLho-아니, 더 나쁜 것은 /from에서 */누락 된 것이므로 다음 코드 끝까지의 모든 코드 */는 무시됩니다. 운 좋게도 구문 강조는 요즘 그런 종류의 일을 드물게 만듭니다.
Steve314

3
auser_age 에 대해 다시 걱정하십니까? 정말?
glasnt

2
이전 고용주에서 코드 표준 문서를 유지 관리했으며 그 중 한 섹션은 적절한 주석 처리였습니다. 내가 가장 좋아하는 예는 MSDN의 예입니다.i = i + 1; //increment i
Michael Itzoe

42

컴파일 할 때 경고를 생성하는 코드.


1
'모든 경고를 오류로'컴파일러 옵션을 makefile / 프로젝트에 추가 할 수 있습니다.
JBR 윌킨슨

3
나는 당신이 단순히 신뢰할 수없는 여러 사람들과 함께 프로젝트에 있다면 유용 할 수 있다고 생각합니다.하지만 그 옵션이 설정된 곳에서 프로젝트에 참여한다면 그 자체로는 다른 사람이 얼마나 유능한 지 걱정할 것입니다. 프로그래머들이 있습니다.
Rei Miyasaka

1
나는 이것에 동의하지 않습니다. 불필요한 캐스트가있는 코드를 버리는 것보다 일부 컴파일러 경고 (서명 이 다르더라도 부호없는 값과 두 값을 모두 알고있는 경우 부호있는 것과 부호없는 것 비교 )가 바람직합니다. 정수에 부호없는 값이있는 경우 에만 함수가 수정하는 이식 가능한 부호있는 정수를 사용하여 코드를 줄이면 그렇게 할 것입니다.
Tim Post

13
오히려 (unsigned int)경고 / 오류 목록을 양성 경고로 어지럽히는 것보다 거의 불필요한 코드로 혼란스럽게하고 싶습니다 . 경고 목록이 사각 지대가되기를 싫어합니다. 그것은 또한 당신이 자연의 캐스트하고있는 이유를 설명하는 것보다 당신이 경고를 무시하는 이유 피타가 다른 사람에게 설명하는 훨씬 더 ints로를 unsigned ints.
Rei Miyasaka

때때로, 당신은 무엇을 하든지 오류를 분출하는 API로 작업해야합니다. 고전적인 예제는 API가 디자인에 의해 깨지는 것 (구식 ioctl () 상수와 같았으며 때로는 OS 개발자가 헤더에 잘못된 유형을 사용한다고 주장하는 경우) 또는 좋은 대체품을 남겨 두십시오 (Apple에게 감사드립니다).
Donal Fellows

36

설명적인 이름 대신 이름에 숫자가있는 함수는 다음과 같습니다.

void doSomething()
{
}

void doSomething2()
{
}

기능 이름을 의미로 만드십시오! doSomething 및 doSomething2가 유사한 작업을 수행하는 경우 차이점을 구별하는 함수 이름을 사용하십시오. doSomething2가 doSomething의 기능을 분리 한 경우 해당 기능의 이름을 지정하십시오.


마찬가지로 @Parm for SQL
Dave

2
+1- mshtml
Enter-

3
이에 대한 예외는 GUI 코드입니다. 예를 들어 달팽이 메일 양식에 두 개의 주소가있는 경우 address1과 address2는 address와 alternateAddress보다 합리적입니다. 정적 전용 인 스퓨리어스 레이블도 합리적인 예외입니다.
Evan Plaice

@Evan-기능면에서 더 차별화되었지만 충분합니다.
Sane Wonko

1
+1-나는 이것이 의사 버전 제어 방법으로 사용되는 것을 보았습니다.
EZ Hart

36

매직 넘버 또는 매직 스트링.

   if (accountBalance>200) { sendInvoice(...); }

   salesPrice *= 0.9;   //apply discount    

   if (invoiceStatus=="Overdue") { reportToCreditAgency(); }

4
두 번째 두 가지로 나쁘지는 않지만 적어도 할인에 대해 설명하고 "지연"은 직관적입니다. 200, 반면에 ...
Tarka

9
@Slokun-직관적은 유지 관리 및 취약성만큼 중요한 것은 아닙니다. 예를 들어, 할인 금액이 변경되고 0.9가 6 개의 다른 장소에 하드 코딩 된 경우 어떻게되는지 고려하십시오. 또한 상수 / 열거 대신 문자열을 사용하면 대소 문자를 구분하는 언어의 언어에서 문제가 발생합니다.
JohnFx

+1 방금 'timeout = 15;'줄로 인해 발생한 문제를 디버깅하는 데 너무 많은 시간을 보냈습니다. 프로그램에 묻혔다.
aubreyrhodes

나는 마지막이라고 생각 때때로 , 좋아 invoiceStatus에 대한 데이터가 어디에서 왔는지에 따라 달라집니다. 방금 디코딩 된 JSON을 반환하는 공용 API에서 가져온 경우 하드 코딩 된 String 상수를 확인하는 것이 좋습니다. "200"과 "0.9"는 마법 상수 일 뿐이므로 이런 식으로 하드 코딩해서는 안된다는 데 동의하십시오. 이 위치에서만 사용하더라도 논리 코드에 산재하지 않고 구성 섹션에서 별도로 정의하면 유지 보수가 더 쉽습니다. 그리고 여러 곳에서 사용하면 유지 관리가 훨씬 쉬워집니다.
Ben Lee

36
  • 아마도 최악이 아니지만 구현 수준을 분명히 보여줍니다.

    if(something == true) 
  • 언어에 for 루프 또는 반복자 구성이있는 경우 while 루프를 사용하면 구현 자의 언어 이해 수준을 보여줍니다.

    count = 0; 
    while(count < items.size()){
       do stuff
       count ++; 
    }
    
    for(i = 0; i < items.size(); i++){
      do stuff 
    }
    //Sure this is not terrible but use the language the way it was meant to be used.
  • 문서 / 주석의 철자 / 문법이 코드 자체만큼이나 많이 사용됩니다. 그 이유는 코드는 사람이 읽고 기계를 실행하기위한 것이기 때문입니다. 이것이 우리가 고급 언어를 사용하는 이유입니다. 문서가 잘 나오지 않으면 코드베이스를 보지 않고 선입관 적으로 부정적인 의견을 만들 수 있습니다.


29

내가 즉시 눈에 띄는 것은 깊게 중첩 된 코드 블록 의 빈도입니다 (if, while 등). 코드가 자주 2 ~ 3 레벨 이상 깊어지면 디자인 / 논리 문제의 징조입니다. 그리고 8 개의 둥지처럼 깊어지면 부서지지 않는 좋은 이유가 더 낫습니다.


6
일부 사람들은 모든 방법에 하나의 return진술 만 있어야 함을 알고 있지만 6 단계 이상의 if / the 중첩이 발생하면 좋은 것보다 훨씬 해로운 것으로 생각합니다.
Darien

28

학생의 프로그램을 채점 할 때 때때로 "깜박임"스타일로 말할 수 있습니다. 이것들은 즉각적인 단서입니다.

  • 열악하거나 일관성이없는 형식
  • 행에 두 개 이상의 빈 줄
  • 비표준 또는 불일치 명명 규칙
  • 반복되는 코드 일수록 반복되는 단어가 많을수록 경고가 강해집니다.
  • 간단한 코드 조각은 지나치게 복잡합니다 (예 : main에 전달 된 인수를 복잡한 방식으로 확인)

내 첫인상이 드물지 않으며,이 경고음 이 시간의95 %에 해당합니다 . 한 가지 예외로, 언어를 처음 접하는 학생은 다른 프로그래밍 언어의 스타일을 사용하고있었습니다. 다른 언어의 관용구에서 자신의 스타일을 파고 다시 읽으면 알람 벨이 제거되어 학생은 완전히 학점을 얻었습니다. 그러나 그러한 예외는 드 rare니다.

더 고급 코드를 고려할 때 다음은 다른 경고입니다.

  • 의 존재는 많은 데이터 만 보유 할 "구조체"있는 자바 클래스. 필드가 공개 또는 개인인지 여부와 상관없이 게터 / 세터를 사용하더라도 여전히 잘 설계된 디자인의 일부는 아닙니다.
  • 네임 스페이스와 같이 이름이 좋지 않고 코드에 실제로 응집력이없는 클래스
  • 코드에서 사용되지 않는 디자인 패턴에 대한 참조
  • 설명없이 빈 예외 처리기
  • Eclipse에서 코드를 가져 오면 수백 개의 노란색 "경고"가 코드에 표시됩니다. 대부분 사용되지 않은 가져 오기 또는 변수로 인해

스타일면에서 나는 일반적으로보고 싶지 않습니다.

  • 코드 만 에코하는 Javadoc 주석

이것들은 나쁜 코드의 단서 일뿐 입니다. 프로그래머의 의도를 모르기 때문에 잘못된 코드처럼 보일 수도있는 것은 아닐 수도 있습니다. 예를 들어, 무언가가 지나치게 복잡해 보이는 좋은 이유가있을 수 있습니다. 다른 고려 사항이있을 수 있습니다.


한 언어에서 다른 언어로 스타일을 사용하는 것이 얼마나 심각한 오류인지 (인 덴트 당 2, 4, 8 공백 ...) 알 수 없습니다. 학생이 따라야 할 다른 스타일이 거의 없다면, 자기 일관성을 유지하는 데 아무런 문제가 없습니다. 채점자로서 10 억 개의 프로그램을 볼 수 있으므로 스펙트럼의 반대편에 있지만 다른 (일관된) 스타일을 완전히 무시할 필요는 없습니다.
Nick T

18
나는 단순히 데이터를 집계하는 클래스, 즉 구조체에 아무런 문제가 없다고 생각합니다. 그것이 바로 데이터 전송 객체 (DTO)가 말한 것보다 코드를 훨씬 더 읽기 쉽게 만들 수있는 방법입니다.
Nemi

1
구조체에 대한 귀하의 의견은 현재 자리에 있습니다. 데이터가 가장 원시적 인 형태이면 아무 문제가 없습니다. 그러나 시간의 95 %는 데이터를 형식화 / 작동하기 위해 클래스에 일부 기능이 있어야합니다. 필자는 본질적으로 해당 패턴을 사용하고 개선 해야하는 코드 중 일부를 기억했습니다.
DisgruntledGoat

2
일치하지 않는 스타일과 여분의 줄 바꿈 +1 (임의의 들여 쓰기, 들여 쓰기 없음 , 무작위 및 변경 명명 규칙 등-및 프로덕션 코드에서 이것을 보았습니다 !). 당신이 그 권리를 얻는 것을 귀찮게 할 수 없다면, 당신은 무엇을 방해하지 않을 수 있습니까?
Dean Harding

1
본문에 비해 너무 들여 쓰기 된 메소드의 선언 줄을 찾습니다. 이것은 다른 사람의 파일에서 복사하여 붙여 넣은 표시입니다.
베리 브라운

25

개인적으로 좋아하는 / 애완 동물 친구 : IDE 생성 이름이 커밋됩니다. TextBox1이 시스템에서 중요하고 중요한 변수라면 코드 검토에 또 다른 문제가 있습니다.



21

많은 사람들이 언급했습니다 :

//TODO: [something not implemented]

나는 물건이 구현되기를 원하지만 적어도 그들은 메모를했다. 내가 더 나쁜 생각은 :

//TODO: [something that is already implemented]

Todo는 귀찮게 제거하지 않으면 무가치하고 혼란 스럽습니다!


1
방금 릴리스 제품의 모든 TODO에 대한 보고서를 작성하고 폐기 계획에 대한 연습을 진행했습니다. 거의 절반이 쓸모없는 것으로 판명되었습니다.
AShelly

1
-1 TODO 주석은 MS Visual Studio에서 여전히 작업이 필요한 프로젝트 부분을 추적하는 데 사용됩니다. IE의 IDE는 TODO를 추적하는 목록을 유지하므로 TODO를 쉽게 클릭하여 TODO가있는 행으로 직접 가져올 수 있습니다. 차라리 TODO가 명시 적으로 배치되어 여전히 수행해야 할 작업을 확인합니다. dotnetperls.com/todo를 참조하십시오 .
Evan Plaice

3
@Evan Plaice : 와우, VS IDE가 무언가를 구현했을 때 인식하고 //TODO주석을 제거한다는 것을 의미 합니까? 대박!
JBR 윌킨슨

4
@Prof Plum TODO를 담당하는 사람이 의견에 이름을 넣는 정책을 만드는 것이 어떻습니까? 그런 식으로 남은 음식이 있다면
Evan Plaice

3
보다 더 나은 계획을 세우 // TODO 려면 버그 추적기를 사용하십시오.
SingleNegationElimination

20

모든 것을 읽으려면 아래로 스크롤 해야하는 방법입니다.


14
흠 .. 구현되는 내용에 따라 다릅니다. 복잡한 알고리즘을 구현할 때 이것이 정의되는 방식이므로 이런 일이 발생하는 것은 부당하지 않습니다. 물론, 대부분의 방법이 그런식이라면 그것은 붉은 깃발입니다.
Billy ONeal

9
총괄 성명서로서 나는 동의하지 않고 시간을 계속 리팩토링하여 모든 종류의 자체 부과 규칙에 부합하여 실제로 전체 프로젝트 비용을 증가시킵니다.
익명 타입

1
이 규칙이 프로젝트의 전체 비용을 증가시킬 수 있다는 데 동의하지 않지만 이는 개발자 (들)에 의존하기 때문에 주관적인 것 같습니다. 개발 과정에서 "문제의 분리"에 대한 일반적인 원칙을 유지한다면 리팩토링은 선택을한다면 그다지 쉽지 않습니다. 고려해야 할 점은 원래 프로젝트를 코딩하지 않은 개발자가 300 줄 이상의 코드로 많은 메소드를 버그 수정하려고 할 때 3 년이 걸리면 얼마입니까? 그 비용은 얼마입니까?
BradB

18
아래로 스크롤하는 것보다 오른쪽으로 스크롤하는 것이 더 짜증납니다. 공백은 "무료"입니다.
Sane Wonko

4
코드가 수행하는 작업을 파악하기 위해 파일 (또는 여러 파일) ​​전체를 건너 뛰어야하는 것보다 스크롤하고 싶습니다.
TMN

20

메소드 이름의 연결 :

public void addEmployeeAndUpdatePayrate(...) 


public int getSalaryOrHourlyPay(int Employee) ....

설명 :이 경고음이 울리는 이유는이 방법이 단일 책임 원칙을 위반할 가능성이 있음을 나타냅니다 .


흠 ... 함수 이름이 함수의 기능을 정확하게 정의하면 동의하지 않습니다. 방법이 분리하는 것이 더 나은 두 가지 별도의 작업을 수행 하는 경우 상황에 따라 동의 할 수 있습니다 .
Sane Wonko

2
그게 요점입니다. 이 연결은 하나 이상의 작업을 수행 할 가능성이 높다는 것을 의미합니다. 질문에 따르면 그것은 무언가 잘못되었을 수도 있다는 내 인식을 높이는 것입니다.
JohnFx

3
이제 여러 곳에서 직원을 추가하고 급여를 업데이트해야하는 경우 어떻게해야합니까? 해당 메소드에 두 개의 메소드 호출 ( addEmployee(); updatePayrate();)이 포함되어 있으면 문제가되지 않습니다.
Matt Grande

13

분명히 GPL의 소스 코드를 상업용 비공개 소스 프로그램에 연결합니다.

즉각적인 법적 문제를 야기 할뿐만 아니라 제 경험상 일반적으로 코드의 다른 부분에도 반영된 부주의 또는 무관심을 나타냅니다.


6
요점은 훌륭하지만 톤은 불필요합니다.
JBR 윌킨슨

@JBRWilkinson : 감사합니다. 맞습니다. 모두에게 사과드립니다.
밥 머피

제목을 다시 작성해야한다고 생각합니다. GPL 소스 코드에 정적으로 동적으로 링크하는 것은 GPL을 위반하는 것입니다.
Gavin Coates

좋은 지적입니다. 전체 게시물을 다시 작성했습니다. 모두 감사합니다.
밥 머피

9

언어에 구애받지 않음 :

  • TODO: not implemented
  • int function(...) { return -1; } ( "구현되지 않음"과 동일)
  • 예외가 아닌 이유로 예외가 발생합니다.
  • 오용 또는 일치하지 않는 사용 0, -1또는 null같은 뛰어난 반환 값.
  • 왜 실패해서는 안되는지 설득력있는 설명이없는 주장.

언어 별 (C ++) :

  • 소문자로 된 C ++ 매크로.
  • 정적 또는 글로벌 C ++ 변수
  • 초기화되지 않거나 사용되지 않은 변수.
  • 모든 array new분명히 RAII 안전하지입니다.
  • 분명히 경계 안전하지 않은 배열이나 포인터 사용. 이 포함됩니다 printf.
  • 초기화되지 않은 배열 부분 사용

Microsoft C ++ 전용 :

  • Microsoft SDK 헤더 파일에서 이미 정의한 매크로와 충돌하는 식별자 이름
  • 일반적으로 Win32 API를 사용하면 큰 알람 벨이 발생합니다. MSDN을 항상 열어 두어야하며, 의심이있을 때마다 인수 / 반환 값 정의를 찾아보십시오. (편집)

C ++ / OOP 특정 :

  • 가상 클래스와 가상이 아닌 메소드를 모두 갖는 가상 클래스와 비가 상 메소드를 갖는 구현 (콘크리트 클래스) 상속.

18
// TODO :이 답변에 대한 의견
johnc

8
"언어 불가지론"이 "C / C ++ / Java"를 의미한다고 생각합니까?
Inaimathi

+1 "예외가 아닌 이유로 예외를 던짐"은 더 이상 동의 할 수 없습니다!
billy.bob

2
@Inaimathi-TODO 주석, 함수 스텁, 예외 남용, 0 / 널 / 빈 의미의 혼동 및 무의미한 상태 확인은 모든 명령 / OOP 언어 및 모든 프로그래밍 언어에 일반적으로 적용됩니다.
Rei Miyasaka

소문자의 C 전 처리기 매크로 괜찮지 만 인수가 한 번만 평가되고 단일 문만 생성되는 경우에만 가능합니다.
Joe D

8

기괴한 들여 쓰기 스타일.

매우 인기있는 스타일이 몇 가지 있으며 사람들은 그 토론을 무덤으로 가져갈 것입니다. 그러나 때때로 나는 누군가가 정말로 드물거나 심지어 집에서 자란 들여 쓰기 스타일을 사용하는 것을 본다. 이것은 아마도 자신 이외의 다른 사람과 코딩하지 않았 음을 나타냅니다.


2
또는 "최고의 실천"과 관련이없는 균질화 된 코딩 관행의 웹에 얽매이지 않은 매우 가치있는 개인 주의적 재능이라는 표시 일뿐입니다.
익명 유형

1
나는 당신이 냉소적이기를 바랍니다. 누군가가 비정상적인 방식으로 코딩하는 경우 알람 벨이 울려 야합니다. 그들은 원하는만큼 예술적 일 수 있지만 여전히 ... 종소리입니다.
Ken

2
Haskell / ML / F # 외부에서는 극히 드문 일이기는하지만 상당히 드문 스타일이 있습니다 (유트 레흐트 스타일이라고합니다). "모듈 모양"아래로 스크롤 learnyouahaskell.com/making-our-own-types-and-typeclasses . 이 스타일에 대한 좋은 점은 이전 행에서 구분 기호를 수정하지 않아도 새 행을 추가 할 필요가 없다는 것입니다.
Rei Miyasaka

@ReiMiyasaka 7 년 늦었지만 위트레흐트 스타일이 정말로 저를 자극합니다. 나는 수직으로 구성된 목록에 또 다른 "레이아웃 규칙"을 부과하지 않는 것이 Haskell 사양의 오류라고 생각합니다. 이런 식으로 파서는 들여 쓰기를 확인하는 것만으로도 새로운 목록 항목을 감지 할 수 있습니다.
Ryan Reich

@RyanReich Weird (7 년 후), 나는 여전히 그것을 좋아합니다. 하지만 동의합니다. 구문상의 어색함과 실패로 인해 F #을 사용하면 줄 바꿈과 들여 쓰기 (대부분의 경우)로 항목을 구분하여 깔끔한 코드를 만들 수 있습니다.
Rei Miyasaka

8

열거 형이나 전역 적으로 정의 된 변수 대신 많은 텍스트 블록을 사용합니다.

안좋다:

if (itemType == "Student") { ... }

보다 나은:

private enum itemTypeEnum {
  Student,
  Teacher
}
if (itemType == itemTypeEnum.Student.ToString()) { ... }

베스트:

private itemTypeEnum itemType;
...
if (itemType == itemTypeEnum.Student) { ... }

또는 최선 : 다형성을 사용하십시오.
Lstor

8

약한 유형의 매개 변수 또는 메소드의 값을 리턴합니다.

public DataTable GetEmployees() {...}

public DateTime getHireDate(DataTable EmployeeInfo) {...}

public void FireEmployee(Object EmployeeObjectOrEmployeeID) {...}

2
+1 : 명확한 구문 오류가있는 것을 전달하더라도 의사 HTML 테이블로 모든 것을 반환하는 일부 "REST"웹 서비스를 사용해야합니다. 권한이 없습니까? 완전한 정크를 입력 하시겠습니까? 서버 초과 용량? 200 (한 열, 한 행 테이블의 끔찍한 형식의 메시지) AAaaaaaaaargh!
Donal Fellows

7
  • 여러 삼항 연산자는 함께 중독, 그래서 대신 닮은의 if...else블록을, 그것은된다 if...else if...[...]...else블록
  • 밑줄이나 camelCasing이없는 긴 변수 이름. 내가 뽑은 일부 코드의 예 :$lesseeloginaccountservice
  • 주석이 거의 없거나 전혀없는 파일에 수백 줄의 코드가 있고 코드가 명확하지 않은 경우
  • 지나치게 복잡한 if진술. 코드의 예 : if (!($lessee_obj instanceof Lessee && $lessee_obj != NULL))나는 아래로 뛰어 들었다 .if ($lessee_obj == null)

7

코드 냄새 : 모범 사례를 따르지 않음

모든 사람들이 자신이 평균 이상의 드라이버라고 생각하는 진실이 있기 때문에 이런 종류의 일은 항상 나를 걱정합니다.

전 세계 인구의 50 %가 평균 지능보다 낮습니다. 좋아, 그래서 어떤 사람들은 정확히 평균적인 지능을 가지 겠지만 까다 롭지 않게합시다. 또한, 어리 석음의 부작용 중 하나는 자신의 어리 석음을 인식 할 수 없다는 것입니다! 이 문장들을 결합하면 상황이 좋지 않습니다.

코드를 볼 때 어떤 것이 즉시 알람 벨을 울립니 까?

많은 좋은 것들이 언급되어 왔으며, 일반적으로 모범 사례따르지 않는 것이 코드 냄새 인 것 같습니다 .

모범 사례는 일반적으로 무작위로 발명되지 않으며 종종 이유가 있습니다. 여러 번 주관적 일 수 있지만, 내 경험상 그들은 대부분 정당화됩니다. 모범 사례를 따르는 것이 문제가되지 않아야하며, 왜 그런지 궁금해하는 경우 무시하거나 불만을 제기하지 말고 조사하십시오. 아마도 정당화 될 수도 있고 아닐 수도 있습니다.

모범 사례의 한 예는 한 줄만 포함하더라도 모든 if-block에 curly를 사용하는 것입니다.

if (something) {
    // whatever
}

당신은 그것이 필요하다고 생각하지 않을 수도 있지만, 최근 에 그것이 버그의 주요 원인이라는 것을 읽었습니다 . 항상 대괄호 사용에 대해서도 Stack Overflow 에서 논의되었으며 if 문에 대괄호가 있는지 확인하는 것도 Java의 정적 코드 분석기 인 PMD규칙 입니다 .

"최상의 방법이므로" "이러한 이유는 무엇입니까?"라는 질문에 대한 대답은 결코 아닙니다. 왜 모범 사례가 무엇인지 설명 할 수 없다면, 모범 사례가 아니라 미신입니다.


2
이것은 pedantic 일 수 있지만, 당신이 선택한 평균이 중요하다고 생각합니다. 내가 이해하는 것처럼, 세계 인구의 50 %는 (지식에 따라) 중앙 지능보다 낮습니다. 그러나 다른 평균은 같은 방식으로 작동하지 않습니다. 예를 들어 산술 평균이 2 인 모집단 (1, 1, 1, 5)을
생각해보십시오

음, 당신은 사용자가 소스없이 중괄호에 대해 대담한 진술을 한 "What-superstitions-do-programmers-have"포스트를 인용했습니다. 모범 사례의 좋은 예라고 생각하지 않습니다.
Evan Plaice

@Evan : 그렇습니다. 나는 그것에 대해 조금 더 덧붙였다. 이것이 도움이되기를 바란다.
Vetle

4
이것의 단점은 왜 "우수 사례"가 무엇인지에 대한 비판적 사고없이 "우수 사례"를 노예로 따르는 사람들입니다. 이것이 바로 "모범 사례"라는 용어를 싫어하는 이유입니다. 일부 사람들에게는 생각을 멈추고 무리를 따르는 것이 핑계이기 때문입니다. "가장 좋은 방법이기 때문에" "왜 이런 짓을합니까?"라는 질문에 대한 대답은 결코 용납되지 않습니다. 왜 모범 사례가 무엇인지 설명 할 수 없다면, 모범 사례가 아니라 미신입니다.
Dan Dyer

아주 좋은 의견, 댄! 마지막 두 줄을 답에 추가했습니다.
Vetle

6

"Froz 하위 시스템의 설계가 완전히 중단 되었기 때문"이라고 설명합니다.

그것은 전체 단락에 걸쳐 진행됩니다.

다음과 같은 리 팩터가 발생해야한다고 설명합니다.

그러나 그것을하지 않았다.

그들은 시간이나 역량 문제로 인해 당시 상사에 의해 그것을 바꿀 수 없다고 들었을 수도 있지만, 아마도 사람들이 사소한 것일 수도 있습니다.

감독자가 j.random이라고 생각하면 프로그래머가 리팩토링을 수행 할 수 없으면 감독자가이를 수행해야합니다.

어쨌든 이런 일이 발생하면 코드가 전력 정책과 함께 분할 된 팀에 의해 작성되었으며 보크 서브 시스템 설계를 리팩터링하지 않았다는 것을 알고 있습니다.

실화. 당신에게 일어날 수 있습니다.


6

누구나 코드가 절대 경로로 파일을 합법적으로 참조 해야하는 예를 생각할 수 있습니까?


1
XML 스키마는 중요합니까?
Nick T

1
시스템 구성 파일. 일반적으로 ./configure로 설정해야하지만 어딘가에 기본값이 필요합니다.
eswald

4
/dev/null친구도 괜찮습니다. 그러나 같은 것조차 /bin/bash의심스러워합니다 /usr/bin/bash.
Tom Anderson

1
JAX-WS 도구 (최소한 JBossWS 및 Metro)에 의해 생성 된 웹 서비스 클라이언트 코드에는 WSDL 파일에 대한 고정 배선 된 절대 경로가 포함되어 있습니다 (두 번!). 어느 것이 아마도 매우 부적절한 것 같습니다 /home/tom/dev/randomhacking/thing.wsdl. 이것이 기본 행동이라는 것은 범죄에 미친 짓 입니다.
Tom Anderson

4
/dev/null: 나는 Windows에서 응용 프로그램과 라이브러리를 유지하기 위해 개발할 때 습관이 있습니다 c:\dev. 어떻게 든 폴더 null는 항상 해당 폴더 안에 자동으로 만들어집니다. 맹세 컨데 누가 그런 짓을했는지 몰라 (내가 가장 좋아하는 버그 / 기능 중 하나)
Sean Patrick Floyd

6

일반적인 예외 잡기 :

try {

 ...

} catch {
}

또는

try {

 ...

} catch (Exception ex) {
}

지역 남용

일반적으로 너무 많은 지역을 사용하면 수업이 너무 크다는 것을 알 수 있습니다. 이 코드를 자세히 조사해야한다는 경고 플래그입니다.


일반적인 예외를 잡는 것은 아무 것도하지 않고 다시 던질 경우에만 문제가됩니다. 실제로 하나의 예외 클래스로 충분할 것입니다. runtime_error를 사용하는 경향이 있습니다.
CashCow

'catch and throw exception'예제의 경우 +1 예외없이 아무것도하지 않으면 잡지 마십시오. 최소한 기록하십시오. 적어도 모든 예외를 잡아서 코드의 해당 지점에서 계속 진행하는 것이 좋은 이유를 설명하는 의견을 작성하십시오.
EZ Hart

5

생성하려는 추상화에 대한 이해가 부족한 클래스 명명 규칙. 또는 그것은 추상화를 전혀 정의하지 않습니다.

첫 번째 파일 Data에서 제목 이 30,000 줄 이상인 VB 클래스에서 극단적 인 예가 떠 오릅니다 . 적어도 6 개의 다른 파일로 분할 된 부분 클래스였습니다. 대부분의 메소드는 이름이 같은 저장된 proc를 래퍼로 사용했습니다 .FindXByYWithZ()

덜 극적인 예를 들더라도, 나는 우리가 논리를 완전히 구식이 아닌 클래스에 '덤핑'하여 완전히 일반적인 제목을 부여하고 나중에 후회했다고 확신합니다.


5

언어의 기본 기능을 다시 구현하는 기능. 예를 들어, 문자열의 ".length"속성을 호출하는 대신 JavaScript에서 "getStringLength ()"메서드가 표시되면 문제가있는 것입니다.


5
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...

물론 문서의 종류 및 가끔 중첩없이 #define


어제 정확히이 "패턴"을 보았습니다 ... 제작 코드에서 ... 그리고 더 악화되었습니다 ... C ++ 생산 코드에서 :-/
Oliver Weiler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.