2008-10-18 7 views
24

저는 실제 로켓 의사가 제작 한 시스템의 유지 보수 작업을 주기적으로 요구받습니다. 시작할 때부터 알기가 너무 어렵다.유지 관리해야 할 가장 불만스러운 프로그램은 무엇입니까?

아니요, 처음부터 시작하겠습니다. 프로젝트 초기에 설계자는 시스템을 확장해야한다고 말했고 확장 성 문제의 원인은 응용 프로그램 및 데이터베이스 서버를 관리하므로이 트래픽을 최소화해야했습니다. 방법? 모든 응용 프로그램 논리를 SQL Server 저장 프로 시저에 저장합니다.

진지하게. XML 메시지를 공식화하는 HTML 프론트 엔드가 응용 프로그램의 상당 부분을 담당합니다. 중간 계층은 XML 메시지를 받으면 문서 요소의 태그 이름을 호출해야하는 저장 프로 시저의 이름으로 사용하고 SP를 호출하여 XML 메시지 전체를 매개 변수로 전달합니다. SP가 반환하는 XML 메시지를 받아 프론트 엔드로 직접 반환합니다. 응용 프로그램 계층에 다른 논리가 없습니다.

은 (은 중간 계층의 일부 코드는 스키마의 라이브러리에 들어오는 XML 메시지의 유효성을 검사이 있었다. 그러나 나는 한 것을 확인하는 후에, 그것을 제거) 메시지의 작은 소수 스키마를 해당했다 2) 메시지는 실제로 이러한 스키마에 부합하지 않았다. 3) 메시지의 유효성을 검증 한 후에 오류가 발생하면 메소드는이를 무시했다. "이 퓨즈 박스는 실시간 세이버입니다. 동전이 미리 설치되어있는 공장에서 나옵니다!")

전에는 잘못한 소프트웨어를 보았습니다. 그것의 제비. 나는 꽤 많이 썼다. 그러나 나는 결코 과 같은 눈으로 볼 수는 없지만, 번에 번으로이 시스템의 디자인과 프로그래밍에 구현되었습니다.

글쎄, 그는 적어도 그가 알고있는 것과 같이 갔다. 그렇지? 음. 분명히 그가 아는 ​​것은 접근이었다. 그리고 그는 실제로 을 이해하지 못했습니다. 액세스. 또는 데이터베이스.

다음은이 코드의 일반적인 패턴의 미세한 좋아

 
SELECT @TestCodeID FROM TestCode WHERE TestCode = @TestCode 

SELECT @CountryID FROM Country WHERE CountryAbbr = @CountryAbbr 

SELECT Invoice.*, TestCode.*, Country.* 
    FROM Invoice 
    JOIN TestCode ON Invoice.TestCodeID = TestCode.ID 
    JOIN Country ON Invoice.CountryID = Country.ID 
    WHERE Invoice.TestCodeID = @TestCodeID AND Invoice.CountryID = @CountryID 

. 쿼리 최적화 프로그램을 신뢰하지 않습니다. 하지만 이건 어때? (원래이 글을 What's the best comment in source code you have ever encountered?에 올리려고했지만,이 한 문장의 주석보다 더 많은 내용을 써야한다는 것을 깨달았습니다. 많은 유틸리티 저장 프로 시저가 끝나면

 
-- Fix NULLs 
SET @TargetValue = ISNULL(@TargetValue, -9999) 

예, 그 코드가 정확히하고있는 당신 자신이 당신이 화를 구동 할 않도록이 일을 믿을 수 없습니다 수있는 '에는 다음과 같은 코드를 볼 것이다. 변수에 NULL이 포함되어 있으면 호출자에게 값을 -9999로 변경하여 경고합니다. 이 번호는 일반적으로 다음과 같이 사용됩니다.

 
-- Get target value 
EXEC ap_GetTargetValue @Param1, @Param2, OUTPUT @TargetValue 
-- Check target value for NULL value 
IF @TargetValue = -9999 
    ... 

정말.

이 시스템의 다른 차원에 대해서는 thedailywtf.com의 문서 I Think I'll Call Them "Transactions"을 참조하십시오. 나는 이걸 만들지 않을거야. 맹세코.

나는이 시스템을 사용할 때 볼프강 파울리 (Wolfgang Pauli)의 유명한 학생 반응에 대해 종종 상기시켜줍니다. "그건 잘못이 아니야."

이것은 정말 최악의 프로그램이 될 수는 없지만 30 년 전의 나의 경력에서 내가 가장 열심히 일한 것은 분명하지만 모든 것을 보지 못했습니다. ?

+2

그래서를 ON .... 이것은 정말 통풍구만큼이나 큰 질문이 아닙니다! 당신이 수사학 적으로 묻고있는 것 같아요. ... 흠 ... –

+0

이것은 블로그 또는 [토론 전용 사이트] (http://meta.stackexchange.com/questions/13198/)에 더 적합합니다. –

+0

나는 그것에 대한 대답이 유용 할 수 있다고 생각했기 때문에 질문을했다. 소프트웨어의 오류 분석은 일반적으로 소프트웨어가 완전히 실패한 후에 만 ​​수행됩니다 (해당되는 경우). 수고를 통해서만 살아남은 끔찍한 헛간은 종종 한 두 사람이 정말로 이해합니다. 소프트웨어가 얼마나 유용 할 수 있습니까? 그런 것들은 어떻게 생겨 났으며 그들을 지원하기 위해 어떤 노력이 필요합니까?이러한 질문을 체계적으로 탐구하기는 어렵지만 탐구 할 가치가 있습니다. –

답변

40

내가 한 번 MP3 디코더를 작성했습니다. 그것은 작동하지 않았다.

+1

말장난이 의도되었다고 가정하면, 내 upvote 선생님, 좋은 사람, 그리고 그 주관적인 질문 어쨌든 어떤 심각한 대답을받을 자격이 아니에요. – Seldaek

+0

나는 그 말장난을 보지 않는다 ... –

+13

"불건전 한", 나는 생각한다. 내가 들어 본 최고의 말장난이 아니야. P – Blorgbeard

6

난 그냥에 시작 하나.

  1. 없음 소스 제어 할 수 있습니다.
  2. 모든 소스는 라이브 편집 실수를 막기 위해 db-access.php.070821과 같은 백업 파일은 소스 트리를 흩어지게합니다.
  3. 코드가 매우 부서지기 때문에 오류 검사 방식이 거의없고 오류가있는 경우 오류가 전혀 발생하지 않습니다.
+2

그들이 실수를 되 돌리는 것에 대해 허둥 거리는 동안 며칠을 기다려야합니다. 그 결과 얼굴 표정이 훨씬 더 재미있게 만듭니다. –

+1

분산 된 인터넷 프로젝트이지만 실제 현금이 있습니다. 나는 svn에 대해 망치질을 해왔고 지금까지 아무 일도 일어나지 않았다. –

+0

그냥 빌드를 깰. 그런 다음 일주일 동안 깨지도록하십시오. 그렇다면 아마도 버전 관리 = D –

19

나는 ExtUtils::MakeMaker을 유지했다. MakeMaker는 확실히 내가 유지해야만하는 최악의 코드는 아닙니다. 그것은 실제로 엔지니어링 경이로운 일입니다. 그러나 가장 중요한 미션 크리티컬 코드도 가장 무서운 코딩 끔찍한 클래스에 속합니다.

MakeMaker는 대부분의 Perl 모듈 용 설치 프로그램입니다. "Makefile.PL"을 실행하면 MakeMaker를 호출하게됩니다. MakeMaker가 깨진다면 Perl은 깨집니다. Perl은 모든 것을 실행하므로 MakeMaker는 모든 것을 실행해야합니다. 내가 모든 것을 말할 때 나는 모든 것을 의미한다. 모든 기괴한 유닉스 변종. Windows 95를 켭니다. 그리고 VMS. 예, VMS.

MakeMaker의 기능은 무엇입니까? Makefile.PL은 Perl 모듈을 만들고 설치하기 위해 종종 Perl을 실행하는 쉘 명령을 포함하는 Makefile을 작성하는 Perl 프로그램입니다. 다시 해봅시다. Perl을 실행하기위한 쉘 명령어를 작성합니다. Perl은 쉘 스크립트를 대체하는 언어입니다.

아, 또한 C 코드를 컴파일하고 연결할 수 있습니다. 또한 정적으로 Perl 모듈을 perl에 연결할 수도 있습니다. 아, RCS 체크 아웃을 관리 할 수 ​​있습니다. 아, 그리고 배포판의 타볼을 굴려 라. 그리고 zip 파일. 그리고 모듈을 설치하는 것과 관련된 모든 다른 작업을 수행하십시오.

그리고이 모든 것을 이전 버전과 호환되는 휴대용으로 수행해야합니다. 그것은

  • 에서 ...

    • 메이크업의 변형 및 버그 (GNU는 NMAKE, dmake는, MMS는, MMK는 몇 가지 이름을, 확인 BSD 만들기)
    • 쉘 처리해야 파일 시스템 (당신이이 큰 문제라고 생각하지 않는 경우, VMS를 시도)
    • C 컴파일러 & 링커 그것은 절대적으로, 긍정적으로 실패 할 수없고 100 % backw 남아 있어야

  • ards 호환.

    아, 진짜 확장 API의 길은 거의 없으므로 사람들이 확장해야하는 임시 Makefile hackery와 호환되어야합니다.

    왜이 모든 작업을 수행합니까? 15 년 전 Perl이 Unix에서만 실행되었을 때 이것은 훌륭한 아이디어처럼 보였습니다. make를 사용할 수있을 때 전체 빌드 시스템을 작성하는 이유는 무엇입니까? Perl은 텍스트 처리 언어입니다. 우리는 Makefile을 작성하기 위해 그것을 사용할 것이다!

    다행히도 교체 번호 Module::Build이 있으며, MakeMaker를 신속하게 삭제할 수 있기를 희망합니다. 그러나 그것의 이해는 느리고 커뮤니티는 변화에 매우 저항했습니다. 그래서 저는 MakeMaker를 유지하는 데 막혀 있습니다.

    1

    인트라넷에서 사용하는 일정 웹 응용 프로그램을 유지 관리하고 있습니다. 스케줄러에서 에이전트를 제거 할 수 있는지 묻는 질문을 받았을 때, 왜 그렇게 생각하지 않았습니까? 소스 코드를 살펴보면이 상담원의 1 시간마다 한 시간 씩 별도로 코딩된다는 것을 알았습니다. 일주일의 매일 같이. 그리고 매주이 지역의 모든 요원들도 마찬가지였습니다. 5 개 지역의 모든 지역도 그렇습니다. html 코드는 장소 전체에 asp 코드를 저장합니다.

    언젠가 나는이 다양한 파일에 몇 줄의 코드가 있는지 추측하기 위해 언젠가 시간이 걸렸습니다. 약 300000 줄의 코드를 작성했습니다. 한 번에 수십만 줄의 코드를 한 번 손으로 쓴 다음 코드를 복사하여 붙여 넣었습니다.

    그러나이 번호는 내 관리자에게 새로운 스케줄링 앱이 매우 빨리 필요할 것이라고 확신했습니다.

    12

    유지 관리해야 할 가장 불만스러운 프로그램은 무엇입니까?

    내가 작성한 모든 것!

    진지하게. 블로그를 더 많이 읽거나 팟 캐스트를 듣고 이와 같이 사이트를 팔로우하면할수록 매일 더 많이 배웁니다. 그리고 매일 내가 기본적으로 어제 쓴 모든 것이 어떤 식 으로든 잘못되었다는 것을 깨닫습니다. 나는 내가 일찍 쓴 것들을 유지하고있는 빈약 한 수액에 대해 느끼고있다.

    +3

    오, 나도. 그러나 근본적으로, 끔찍하게도 잘못된 코드와 코드 사이에는 카테고리 차이가 있습니다. 그런 종류의 코드를 작성하는 것은 경험이없는 것 이상을 필요로합니다. 그것은 엄청난 양의 부당한 자신감을 필요로합니다. –

    2

    나는 COBOL 프로그래머 (떨림꾼)이었습니다. 우리 코드는 모두 "불건전 한"범주에 속합니다. COBOL에는 네임 스페이스가 없으며 모든 변수는 전역 변수이며 파일 이름 및 기타 자원의 필수 복제가 많이 있습니다. 프로 시저를 호출하려면 전역 변수를 설정하고 프로 시저를 호출 한 다음 전역 변수 (또는 설정 될 수있는 다른 변수)의 내용을 검사합니다.

    최악의 경우, 나는 태어나 기 전에 작성된 COBOL 프로그램을 유지하고 있었으며 (1967 년에 태어 났음) 흐름 제어의 독점적 인 방법은 GOTO였습니다. 절대 혼란 스러웠고 따르기가 불가능했습니다. 변수 유형을 약간 변경하면 해결하는데 며칠이 걸릴 수 있습니다. 자동화 된 테스트가 없었으며 수동 테스트 계획이 저장되지 않았기 때문에 모든 변경 작업을 수행하기 위해 새로운 수동 테스트 계획을 작성하고 철저히 조사한 후 코드로 전환해야했습니다.

    역설적이게도 COBOL이 그렇게 성공한 이유입니다. COBOL은 종종 JCL (Job Control Language)로 실행됩니다. COBOL은 매우 약하기 때문에 프로그램이 많이 수행하지 않으므로 JCL은 디스크 공간 (종종 실린더 레벨까지)을 할당하고 작은 COBOL 프로그램을 실행하여 데이터를 읽은 다음 필요한 데이터 만 출력합니다. 그런 다음 JCL은 정렬 프로그램을 호출하여 결과 파일을 정렬 할 수 있습니다. 그런 다음 다른 COBOL 프로그램을 호출하여 정렬 된 파일을 읽고 데이터를 요약하고 필요한 결과를 다시 추출 할 수 있습니다. 그리고 아마도 JCL이 다른 곳으로 파일을 옮기는 데 다시 사용될 것이고, 또 다른 COBOL 프로그램이 호출되어 결과를 읽고이를 데이터베이스에 저장하는 등의 작업을 수행 할 것입니다. 각 COBOL 프로그램은 유닉스 파이프 라인 모델의 원시 버전이 만들어 졌을뿐입니다. 왜냐하면 COBOL이 유지 보수하기가 너무 어렵거나 복잡한 작업을하기가 너무 어렵 기 때문입니다. COBOL을 다른 방법으로 쓰는 것은 거의 불가능했기 때문에 우리는 느슨한 결합과 긴밀한 결합 (프로그램 사이에서, 그렇지 않은 프로그램 사이)을 가졌습니다.

    0

    이전 고용자를 유지하기 위해 개발자를 고용 한 특정 회사의 ASP 응용 프로그램 유지 관리 ... 이러한 모든 응용 프로그램은 문서화되지 않았으며 주석도 없습니다.

    모든 기능이 모든 ASP 페이지에 복사되고 붙여 넣어집니다. 그래서 함수가 정의되거나 전혀 없습니다 ... 매일 서버를 사용하지 않기 때문에 매일 환경이 좋지 않아서 DMZ을 우회합니다. 그 후에 변경해야하는 프로덕션 서버에 원격으로 접속해야합니다.

    5

    이전에 프로그램하고 (아마도 살 수있는) 의사를 잃어 버린 일부 프로그래머가 이전에 작성하고 유지 관리했던 레거시 C 응용 프로그램을 유지해야했습니다. 그것은 언급 할 WTF가 너무 많았지 만, 여러 특수한 경우에 TRUE + 1, TRUE + 2 등을 반환하는 부울 함수를 기억합니다.

    그런 다음 나는 Roedy Green's essay을 읽고 많이 웃었습니다. 내가 재미 있다고 느꼈던 이유는 내가 유지하고 있던 코드에서 대부분의 예제를 인식했기 때문입니다. (그 에세이는 수년간의 추가 작업으로 약간 비대 해졌지 만 여전히 가치가 있습니다.)

    0

    EDIF 리더의 주기적 충돌을 추적하기 위해 한 번 전화를 받았습니다. 거의 즉시 두통이 생기기 시작했습니다. 원저자는 Yacc이 공백을 위해 그를 벌하려하고 있다고 생각하는 듯했으며, 그의 Yacc 문법은 밀도가 높고 읽을 수없는 엉망이었다. 나는 두 시간짜리 서식을 지정하고 누락 된 터미널에 대한 규칙을 추가하여 스택 증가를 피하기 위해 선언문을 구조화하고 보일라는 충돌을 없앴습니다.

    Yacc이 문법을 처리하는 동안 기다릴 때마다 생성 된 파서가 수천 회 실행됩니다. 공백으로 싸지 마십시오!

    0

    필자가 작성한 모든 내용은 원래 빠른 프로토 타입 인 것으로 간주되어 잠시 머물러 있습니다. 내 문제 영역은 본질 상 많은 원형 프로토 타입을 필요로합니다. 이 프로토 타입의 경우, 최상의 스타일과 규칙을 위반하는 것이 합리적입니다. 프로토 타입의 가치가 유지되면 나중에 완료하고 정리하십시오. 그러나 때로는 이러한 프로토 타입이 제대로 작동하지 못하게되지만 결국 파수꾼이됩니다. 이 경우, 나는 보통 리팩토링/퍼팅을 무기한으로 끝내지 만, 나는 결코 다시 작동하지 않을까 걱정된다. 내 동기 부여를 더욱 줄이는 것은 내 상사가 전혀 프로그래밍하지 않는 도메인 전문가라는 것입니다.

    1

    연락처 테이블에 자연 키가없는 PHP/MySQL 기반 온라인 연락처 관리 시스템입니다. 나중에 응용 프로그램 코드로 구문 분석해야하는 구분 된 문자열 형태의 복합 데이터를 포함하는 수많은 데이터베이스 필드 인스턴스가있었습니다.

    HTML과 로직이 서로 얽혀 거의 기능이 사용되지 않았지만 코드가 수십 개의 소스 코드 파일로 잘라 붙여 넣어졌습니다. 데이터가 삭제되지 않았고 (예 :) 수직 탭이 포함 된 필드는 Ajax가 오작동을 호출하여 반환 된 XML을 발생 시켰으며 수백 개의 공백 진술이 아니라면 수십 개의 파일을 포함하여 닫는 중괄호와 그 뒤에 세미콜론 : "};"

    0

    Microsoft 기본 전문 개발 시스템 (PDS)로 작성된 CAD/CAM 지오메트리 처리 언어 (P1 = 10,10; P2 = 20,20; L1 = P1, P2) , 최소 길이의 변수 이름 (단 하나의 글자가 빠져 나오기 때문에 PP, PQ, PR, 누구든지?)를 두 글자로 옮겼습니다. 그리고 공평하게, 일부 댓글. 이탈리아어로.

    는 충분히 재미있게, 실제로 일을하고, 나는 몇 가지 기능을 추가 할 수 있었다, 그러나 아마추어 치과 같았다 - 권장하지 확실히 고통, 그리고 ...

    2

    오른쪽 루슨트 I에서 대학원 중 PL/I로 작성된 컴파일러와 인터프리터에게 유지 보수를 의뢰했다.컴파일되는 언어는 복잡한 무결성 제약 조건 집합을 설명하고 인터프리터는 나중에 4ESS 스위치를 제어하는 ​​초기 데이터베이스로 구성된 대규모 데이터 집합에 대해 이러한 제약 조건을 실행했습니다. 4ESS는 장거리 음성 트래픽을위한 회선 교환기 였지만 여전히 사용되었습니다.

    코드가 혼란 스럽습니다. "NORTH40"이라고하는 지점에 레이블이있었습니다. 나는 원 개발자에게 그것이 의미하는 바를 물었다.

    "범위 검사가 수행되는 곳입니다. 알다시피, 각 필드에 올바른 값이 있는지 확인하는 것입니다."

    "왜 'NORTH40'입니까?"

    는 "당신은, '홈, 범위에 가정을."알고있다 "

    "응? "

    "NORTH40"은 농장의 북쪽 40 에이커를 의미하며 도시에서 자란 마음에는 가축 목장과의 연결이 애매했다.

    다른 모듈에는 병렬로 업데이트 된 TORY 및 DIREC이라는 두 개의 병렬 배열이 있었으므로 데이터 쌍을 포함하는 단일 배열을 모델링하려는 명백하게 잘못된 시도였습니다. 나는 이름을 알아 내지 못하고 개발자에게 물었다. 그들이 함께 읽히는 것을 의미하는 것으로 밝혀졌습니다 : "방향". 큰.

    무결성 제약 조건을 작성해야했던 가난한 사람들은 가이드를 직접 작성하는 사용자 설명서가 없으며 구두 전통과 손으로 쓴 메모가있었습니다. 더욱이 컴파일러는 신택스 검사를하지 않았으며 종종 매우 잘못된 결과를 낳고 잘못된 로직에 조용히 매핑 된 제약 조건을 지정하는 것을 끝내었다.

    나빠질 것입니다. 통역사의 대변을 들여다 보니 나는 그것이 거대한 정렬 과정을 중심으로 만들어 졌음을 발견했습니다. 정렬은 원시 데이터 및 + 결성 제한 조건에서 정렬 입력 데이터를 생성하는 입력 프로세스였습니다. 따라서 5,000 개의 트렁크 정의가있는 테이블이 있고 각 트렁크 레코드가 전체 입력 데이터 세트에서 고유해야하는 세 개의 필드 값을 가지고 있다면 입력 프로세스는 3 * 5,000 = 15,000 개의 정렬 입력 레코드를 생성합니다. 무결성 제약 번호 앞에 접두사가 붙은 데이터 레코드와 정렬 할 필드 값의 사본. 3,000 건의 레코드 정렬을하는 대신 15,000 건의 레코드 정렬을 수행했습니다. 수백 개의 내부 및 테이블 간 무결성 제약 조건과 매우 큰 테이블을 고려할 때 조합 적 악몽이있었습니다.

    조금 리팩터링하고 언어를 문서화하고 구문 검사에 이해할 수있는 오류 메시지를 추가 할 수 있었지만 몇 개월 후에 새 그룹으로 이전했습니다.

    1

    나는 한 번 회사의 정책은 모든 프로그램이 문으로 시작해야 함을 어디에 Basic으로 작성된 CAD 응용 프로그램에 근무 :

    에러 다시 시작

    JMM

    +0

    무슨 요점 ??? :피 –

    관련 문제