하나의 메소드 서명을 변경했으며 이제 25,000 개 이상의 오류가 있습니다. 지금 무엇?


166

나는 최근에 매우 큰 응용 프로그램 (15M 위치)에서 작업하는 새 직장을 시작했습니다. 이전 작업에서 우리는 비슷하게 큰 응용 프로그램을 사용했지만 OSGi를 사용했습니다. 이는 응용 프로그램이 독립적으로 변경, 컴파일 및 배포 될 수있는 많은 마이크로 서비스로 분류되었음을 의미합니다. 새 응용 프로그램은 몇 개의 .dll이있는 하나의 큰 코드 기반 일뿐입니다.

그래서이 클래스의 인터페이스를 바꿔야합니다. 왜냐하면 상사가 요청한 것이기 때문입니다. 그들은 처음에는 너무 잘 일반화하지 않은 몇 가지 가정으로 그것을 작성했으며, 한동안 너무 밀접하게 결합되어 있기 때문에 리팩토링 문제를 피하고있었습니다. 인터페이스를 변경했으며 이제 25000 개가 넘는 오류가 있습니다. 오류 중 일부는 "XYZPriceCalculator"같은 중요한 들리는 이름을 가진 클래스에 reaaally깨지 말아야합니다. 그러나 모든 오류가 해결 될 때까지 응용 프로그램이 작동하는지 확인하기 위해 응용 프로그램을 시작할 수 없습니다. 그리고 많은 단위 테스트는 해당 인터페이스를 직접 참조하거나 해당 인터페이스를 참조하는 기본 클래스에 연결되어 있으므로이를 수정하는 것은 그 자체로 매우 큰 작업입니다. 또한, 나는이 모든 조각들이 어떻게 조화를 이루는 지 알지 못하므로 시작할 수 있다고해도 물건이 부서지면 어떻게 보일지 모릅니다.

마지막 직장에서 이런 문제에 직면 한 적이 없습니다. 어떻게해야합니까?


7
우리는 오류의 종류와 "이 클래스"에 대해 더 많은 정보를 제공해야합니다.
whatsisname

137
VS에 표시된 "25000 이상의 오류"는 종종 잘못된 것입니다. 몇 가지 오류가 있지만 자주 사용되는 dll의 빌드가 손상되면 다른 빌드도 실패하여 천문학적 오류 수가 발생합니다. 나는 항상 오류 목록이 아닌 빌드 출력에서 ​​발견 된 첫 번째 오류 메시지로 수정을 시작합니다.
Bernhard Hiller

13
변경 한 방법에 대한 전후 서명을보고 싶습니다. BTW-25k 오류는 실제로 처리하기에 너무 많은 것처럼 들리지 않습니다. 지루하고 예, 어려우며, 예, 관리 할 수 ​​없습니다.
jmoreno

46
공용 인터페이스는 계약입니다. 그러한 계약을 어 기지 말고 새로운 계약을 만드십시오.
Matthew 읽기

6
25000 오류!? 휴스턴, 문제가 생겼어 변경 사항을 확실히 되돌리고 관리자에게 문의하여 새 인터페이스를 만들어야 할 수도 있다고 설명하십시오.
코드 위스퍼러

답변:


349

25000 오류는 기본적으로 "그것을 만지지 마십시오"를 의미합니다. 다시 변경하십시오. 원하는 인터페이스가있는 새 클래스를 만들고 클래스 소비자를 새 클래스로 천천히 이동하십시오. 언어에 따라 이전 클래스를 더 이상 사용하지 않는 것으로 표시하면 모든 종류의 컴파일러 경고가 발생할 수 있지만 실제로 빌드를 중단하지는 않습니다.

불행히도 이러한 일은 오래된 코드 기반에서 발생합니다. 천천히 일을 개선하는 것 외에는 할 수있는 일이 많지 않습니다. 새 클래스를 작성할 때는 올바르게 테스트하고 SOLID 원칙을 사용하여 작성하여 향후 변경하기가 더 쉬워야합니다.


79
반드시 새로운 클래스 일 필요는 없습니다 . 언어와 환경에 따라 기능, 인터페이스, 특성 등이 될 수 있습니다.
Jan Hudec

33
또한 이전 인터페이스를 새 인터페이스 주변의 호환성 래퍼로 교체 할 수있는 경우 도움이됩니다.
Jan Hudec

79
때때로 25000 오류는 실제로 우리가 감히 감히 만지지 않는다는
mouviciel

13
@ theDmi : 나는 1 변화와 25k 오류가 최대 2.5k 변화를 의미한다는 것을 동의하며, 그것이 약 250 가지라는 사실에 놀라지 않을 것입니다. 어느 쪽이든 많은 작업이 가능하지만 가능합니다.
jmoreno

33
이러한 25000 오류는 한 번의 변경으로 해결 될 수 있습니다. 거대한 계층의 기본 클래스를 중단하면 파생 클래스 중 하나가 잘못된 기본에 대한 오류를 발생시키고 해당 클래스를 사용할 때마다 존재하지 않는 클래스에 대한 오류가 발생합니다. "getName"이라고 가정하고 추가했습니다. 논쟁. "HasAName"구현 클래스의 오버라이드는 이제 작동하지 않으며 (오류),이 클래스 에서 상속 된 모든 것은 이제 오류 (1000 개의 클래스 모두)를 생성 할뿐만 아니라 이들 중 하나의 인스턴스를 작성할 때마다 (클래스 당 24x 평균). 수정은 ... 한 줄입니다.
Yakk

80

리팩토링으로 나누고 정복

작은 단계로 수행해야하는 변경 사항을 세분화하면 소프트웨어를 전혀 손상시키지 않는 방식으로 작은 단계를 대부분 수행 할 수 있기 때문에 도움이 될 수 있습니다. 리팩토링 도구는 이러한 작업에 많은 도움이됩니다.

분할

먼저 달성하려는 변경에 해당하는 가장 작은 변경 사항 (변경된 LoC가 아닌 논리적 변경 측면)을 식별하십시오. 특히 순수한 리팩토링 이며 도구로 수행 할 수있는 단계를 분리하십시오 .

억누르다

귀하와 같은 복잡한 경우에는 한 번에 하나의 작은 리팩토링을 수행 한 다음 문제를 해결하여 모든 지속적인 통합 시스템이 변경 사항을 확인할 수 있으며 테스트 팀도 살펴볼 수 있습니다. 이렇게하면 단계가 확인됩니다.

특정 리팩토링을 수행하려면 변경하려는 메소드의 25,000 개의 콜 사이트가있는 경우 툴 지원이 절대적으로 필요합니다. 아마 검색 및 바꾸기, 너무 일을하지만, 이러한 중요한 경우에, 그 무서워 할 것입니다.

예를 들어 C #에서는 Resharper 를 사용 하여 메서드 의 서명변경할있습니다 . 변경이 충분히 간단한 경우 (예 : 새 매개 변수 추가) 콜 오류에서 컴파일 오류가 발생하는 값을 지정할 수 있습니다.

그러면 오류가없는 코드베이스에 즉시 도달하고 리팩토링 일 뿐이므로 모든 단위 테스트를 실행할 수 있습니다.

메소드의 서명이 양호 해지면 Resharper가 새로 도입 된 매개 변수에 인수로 추가 한 값을 대체 할 수 있습니다. 이것은 더 이상 리팩토링아니지만 오류가없는 코드베이스가 있으며 변경 한 각 라인 후에 테스트를 실행할 수 있습니다.

때때로 그것은 작동하지 않습니다

이 방법은 통화 사이트가 많은 사용자와 같은 경우에 매우 유용한 접근 방식입니다. 그리고 현재 작동하는 소프트웨어가 있으므로 서명을 약간 변경하기 위해 작은 리팩토링 단계를 수행 한 다음 다른 것을 수행하는 것이 가능할 수 있습니다.

불행히도 서명 변경이 너무 복잡하고 더 작은 변경으로 나눌 수 없으면 작동하지 않습니다. 그러나 이것은 드물다. 작은 문제로 문제를 분할하는 것은 대개는 것을 알 수 있다 가능합니다.


12
이. 가능하면 리팩토링 (안전하게), 그렇지 않으면 적절한 마이그레이션이 필요합니다.
sleske

3
그리고 무엇이든 사랑하기 위해서는 (예를 들어) 메소드 서명을 로컬로 변경 한 다음 결과 오류를 수정하지 않고 IDE의 내장 리팩토링 도구를 사용하십시오.
KlaymenDK

36

상사와 업무를 명확하게하여 문제와 전문 소프트웨어 개발자로서의 요구를 이해하도록 도와줍니다.

팀의 일원 인 경우 수석 개발자를 찾아 조언을 구하십시오.

행운을 빕니다.


15
이것은 내가 취해야 할 첫 번째 단계입니다. "저는 주니어이고 상사는 나에게 일을하라고했는데 지금은 정말 큰 오류 메시지를 받고 있지만 상사는 나에 대해 말하지 않았습니다." 1 단계 : "상사 님, 제가 그 일을했지만 지금 25k 오류가 발생합니다.
그럴까요

28

만지지 마십시오. 커밋하지 마십시오.

대신, 의자에 앉아서 "Heeeeelp !!!!!" 당신이 할 수있는 한 큰 소리로.

글쎄요, 정확히 그런 것은 아니지만 상급 동료에게 조언을 구하십시오. 25,000 개의 오류가있는 경우 오류를 수정하지 않고 오류의 원인을 수정합니다. 또한 선임 동료는 25,000 개의 오류없이 상사가 원하는 변경 방법 을 알려줄 수 있어야합니다 . 이를 수행하는 다양한 방법이 있지만 좋은 방법은 특정 상황에 따라 다릅니다.

그리고 상사는 동료들에게도 같은 변화를 시키라고 말했을 수 있으며 그들은“아니요”라고 말했습니다. 그들은 무슨 일이 일어날 지 알았 기 때문입니다. 그렇기 때문에 당신은 그 일을 받았습니다.


2
이것은 명심해야 할 중요한 것입니다. 신입 사원이 진정으로 야심 찬 경우, 5 바이트 메모리 이점을 얻거나 나중에 다시 코딩하고 유지 관리하는 데 더 논리적 일 수있는 정말 큰 작업을 수행하기에 부지런한 (익숙한) 사람 일 수 있습니다.
그레이트 덕

@TheGreatDuck : 당신은 어디서나 사용되는 인터페이스 본 적이 말해 잘못 사방을. 확실 해요
Joshua

@Joshua는 방금 말한 것과 관련이 없습니다. 경미한 버그를 수정하는 것이 항상 현명한 것은 아닙니다. 10,000 줄 이상의 코드를 다시 작성한다는 의미입니다. 불행히도, 신입 사원은 직장 밖에서 밤새도록 10 명의 사람들을 끌어내어 상사에게 깊은 인상을 심어 줄 수있을 정도로 익살 스러울 수 있습니다. 물론, 그것은 좋은 일이지만 때로는 충분합니다. 버그의 존재 만 받아 들여야합니다.
그레이트 덕

1
@Joshua btw,이 질문은 인기있는 질문 피드에 들어 왔기 때문에이 커뮤니티에만 가입했습니다. 나는 이와 같은 대규모 디자인에 대한 경험이 없다. 나는이 사람의 견해에 동의했다.
그레이트 덕

22

Entrenched API는 단순히 변경할 수 없습니다. 실제로 변경 해야하는 경우 사용하지 않는 것으로 언어를 허용하거나 문서화하고 대신 사용할 API를 문서화하십시오. 그러면 리팩토링을위한 시간 예산에 따라 이전 API를 천천히 단계적으로 제거 할 수 있습니다.


10

평가

이 변경이 필요한지 또는 새 메소드를 추가 하고 다른 메소드를 더 이상 사용할 수 없는지 평가 하십시오.

앞으로

변경이 필요한 경우 마이그레이션 계획이 필요합니다.

첫 번째 단계는 새로운 방법을 소개하고 기존 방법으로 인수를 마사지하여 새로운 것을 호출하는 것입니다. 이를 위해서는 몇 가지 하드 코딩이 필요할 수 있습니다. 괜찮아.

이것은 커밋 포인트입니다. 모든 테스트가 통과, 커밋, 푸시되는지 확인하십시오.

이주

바쁜 작업은 이전 방법의 모든 호출자를 새로운 방법으로 마이그레이션합니다. 고맙게도 전달자 덕분에 점진적으로 수행 할 수 있습니다.

계속 진행하십시오. 주저하지 말고 도움을주는 도구를 사용 sed하십시오 (가장 기본적인 것은 다른 것들이 있습니다).

이전 메소드를 더 이상 사용하지 않는 것으로 표시하십시오 (새 메소드로 전환하는 힌트와 함께). 그것은 당신이 무언가를 잊었는지 여부를 알아내는 데 도움이되며 동료 가이 작업을 수행하는 동안 이전 방법에 전화를 걸면 도움이 될 것입니다.

이것은 커밋 포인트 (또는 여러 커밋 포인트)입니다. 모든 테스트가 통과, 커밋, 푸시되는지 확인하십시오.

없애다

일정 시간이 지난 후 (하루 정도는 되었음) 단순히 이전 방법을 제거하십시오.


4
sed아마도 나쁜 생각 일 것입니다 ... 실제로 언어를 "알고"의도하지 않은 과감한 변화를 일으키지 않는 것이 더 좋습니다.
wizzwizz4

1
@ wizzwizz4 : 불행히도, 실제로 C ++에 충분한 언어를 이해 하는 도구는 거의 없었습니다 . 대부분의 도구는 이름을 바꾸는 것으로 보입니다. 이름을 변경, 부여 정확한 메소드 호출 (그리고 어떤 과부하 또는 관련이없는 있지만, 비슷한 이름의 메소드 호출은) 이미 인상적이지만, 더 복잡 아무것도 부족합니다. 최소한 (1) 인수를 섞고, (2) 주어진 인수에 변환을 적용하고 ( .c_str()예를 들어 호출 ) 새로운 인수를 도입 할 수있는 능력이 필요합니다 . sed다소 작동하면 컴파일러가 나중에 문제를 포착합니다.
Matthieu M.

1
sed(또는 ed) 커밋하기 전에 diff를 제대로 검토하는 한 이러한 종류의 작업에 적합 할 수 있습니다.
Toby Speight

이것은 HTML의 TCRR입니다. :)
Daniel Springer 2016

8

메소드 서명 변경이 단순히 이름 변경 인 경우 간단한 솔루션은 도구를 사용하여 해당 메소드를 참조하는 25,000 클래스의 변경을 자동화하는 것입니다.

코드를 수동으로 편집했기 때문에 모든 오류가 발생했다고 가정합니다. 또한 Java에 익숙하다고 가정합니다 (OSGi에 대한 참조 참조). 예를 들어 Eclipse (사용하는 프로그래밍 환경을 모르지만 다른 환경에는 비슷한 리팩토링 도구가 있음) "리팩터링-> 이름 바꾸기"를 사용할 수 있습니다 메소드에 대한 모든 참조를 업데이트하면 오류가 발생하지 않습니다.

단순히 이름을 바꾸는 것 (매개 변수의 수 또는 유형 변경) 이외의 방법으로 서명을 변경하는 경우 "리팩토링-> 방법 서명 변경"을 사용할 수 있습니다. 그러나 다른 답변에서 제안하는 것처럼 더 조심해야 할 수도 있습니다. 또한 변경 유형에 관계없이 바쁜 코드베이스에서 이러한 모든 변경 사항을 커밋하는 것은 여전히 ​​큰 작업 일 수 있습니다.


2
OP는 OSGi가 이전 직장에 있다고 말했기 때문에 실제로는 관련이 없습니다.
CVn

3
@ MichaelKjörling OP가 이전 작업에서 Java 프로그래머 였다면이 작업에서도 Java 프로그래머 일 가능성이 더 높습니다.
Rich

@ MichaelKjörling OP가 Java에 익숙하기 때문에 Eclipse를 리팩토링에 사용하는 구체적인 권장 사항을 제시하고 싶었습니다. OP가 현재 프로젝트에 실제로 Java를 사용하는지 여부는 덜 중요하지만 내 대답을 명확히해야합니다. 감사.
MikkelRJ

6

여기 내 공헌.

나는 최근에 매우 큰 응용 프로그램 (15M 줄의 코드)에서 작업하고있는 새로운 일을 시작했습니다.

프로젝트와 "기능"에 익숙하지 않을 것입니다. 한 줄의 코드를 입력하기 전에 프로젝트에 익숙해지는 것이 중요합니다. 변경 사항을 롤백하고 코드를 분석하여 시작하십시오 . (적어도 영향을받은 사람)

기존 솔루션을 이해하면 어디로 가는지 더 잘 알 수 있습니다. 솔루션의 맥락과 그 중요성.

@Greg가 지적했듯이 기존 코드를 테스트하여 유효한 회귀 참조 (회귀 테스트)를 가질 수 있어야합니다. 솔루션은 기존 솔루션과 매우 동일한 결과를 생성 할 수 있어야합니다 . 이 단계에서는 결과가 올바른지 여부에 대해 걱정하지 마십시오 . 첫 번째 목표는 버그를 수정하지 않고 리팩토링하는 것입니다. 기존 솔루션에 "2 + 2 = 42"라고 표시되면 솔루션도 마찬가지입니다. 예외가 발생하지 않으면 당신도 예외가 아닙니다. null을 반환하면 null도 반환해야합니다. 등등. 그렇지 않으면 25k 줄의 코드가 손상됩니다.

이것은 레트로 호환성을위한 것입니다.

왜? 지금 당장은 성공적인 리 팩터를 보장합니다.

그리고 많은 단위 테스트는 해당 인터페이스를 직접 참조하거나 해당 인터페이스를 참조하는 기본 클래스에 연결됩니다.

레트로 호환성을 보장하는 방법이 시급히 필요합니다. 첫 번째 도전입니다. 단위 테스트를 위해 구성 요소를 분리하십시오.

이 25k 줄의 코드는 기존 코드의 가능한 결과를 가정하여 만들어졌습니다. 계약의이 부분을 어 기지 않으면 최종 솔루션의 절반이됩니다. 당신이 잘한다면 : 힘이 당신과 함께 할 수 있습니다

새로운 "계약"을 설계하고 구현했으면 이전 계약을 교체하십시오. 더 이상 사용하지 않거나 꺼내십시오.

리팩토링으로 버그를 내버려 두는 것이 좋습니다. 버그를 수정하는 것은 다른 작업입니다. 함께 가져 가려고하면 둘 다 실패 할 수 있습니다. 버그를 발견했다고 생각할 수도 있지만 "기능"일 수 있습니다. 따라서 잠시 두십시오.

25k 줄의 코드는 하나의 작업에만 집중할 수있는 충분한 문제로 보입니다.

첫 번째 작업이 완료되면 그 버그 / 기능을 상사에게 노출 시키십시오.

마지막으로 @Stephen이 말했듯이 :

천천히 일을 개선하는 것 외에는 할 수있는 일이 많지 않습니다. 새 클래스를 작성할 때 올바르게 테스트하고 SOLID 원칙을 사용하여 작성하여 향후 변경하기가 더 쉬워야합니다


5

그것을 테스트하십시오.

다른 모든 사람은 리팩토링 방법을 권장하므로 영향이 거의 없습니다. 그러나 많은 오류가 발생하면 10 줄의 코드로 리팩토링에 성공하더라도 (가능할 수도 있음) 다시 작성하지 않아도 25,000 코드 흐름에 영향을 미쳤 습니다.

따라서 다음으로해야 할 일은 회귀 테스트 스위트가 비행 색상으로 통과하는지 확인하는 것입니다. 그리고 당신이 없다면, 그 것을 만드십시오. 모 놀리 식 프로젝트에 포괄적 인 회귀 테스트 스위트를 추가하면 지루한 것처럼 들리지만 릴리스 후보에 대한 신뢰를 높이고 스위트가 자동화 된 경우 더 빠르게 릴리스 할 수있는 좋은 방법입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.