2011-02-17 3 views
4

거대한 코드베이스에서 불쾌한 점을 리팩터링하고 특정 구현 방법을 사용하여 특정 인터페이스를 구현하는 특정 메소드를 호출해야하는 경우를 찾아야합니다. 그 인터페이스.특정 하위 유형으로 호출 될 때 특정 메소드의 사용법 찾기

예를 들어, NastyStaticDoBadThings(IBusinessObject)입니다. 저의 비즈니스 라이브러리에 IBusinessObject을 구현하는 약 50 개의 클래스가 있습니다 (예 : DontHurtMe : IBusinessObject).

NastyStatic.DoBadThings(foo)에 대한 모든 전화는 어떻게 찾을 수 있습니까? fooDontHurtMe의 인스턴스입니까?

편집 : 나는 일종의 정적 분석 도구를 사용하고 있습니다. DoBadThings (또는 이와 유사한)에서 동적 감시를 설정하고 응용 프로그램을 실행하는 것은 실제로 옵션이 아닙니다. DontHurtMe에 대한 변경 사항으로 인해 예외가 이미 throw되며 모든 사용법을 찾기에는 너무 많은 코드 경로가 있습니다 (최소한 라이브가 시작되고 사용자가 불평하기 시작할 때까지).

+0

DoBadThings 메서드에 어떤 종류의 추적을 추가하고 응용 프로그램을 실행하는 것을 포함하지 않는 앤서가 존재한다면 놀라실 것입니다 (매우 흥미 롭습니다). –

+0

@xorcrud 그건 내가 너무 피하고 싶습니다 .--)도 있습니다. 많은 코드 경로, 그리고 이미 예외를 throw합니다. –

+0

어쨌든 리팩토링하는 데 어떻게 도움이 될까요? – Dyppl

답변

5

쉬운. DontHurtMe를 매개 변수로 사용하는 DoBadThings의 오버로드를 작성하십시오. 이제 그것이 어디에서 불려지는지보십시오. 이것은 이 DontHurtMe 인이 발생하는 선언 된 IBusinessObject로 메소드가 호출 된 경우를 감지하지 못합니다. 그러나 정적 분석이이를 감지 할 수 있다고 생각하지 않습니다. 이 메소드는 DontHurtMe로 선언 된 모든 호출을 가져옵니다.

+0

그 _could_는 작동하지만'NastyStatic'은 다른 어셈블리에 있으며'DontHurtMe' 그 자체에 대해 알지 못합니다. 'DontHurtMe' 어셈블리에 오버로드를 추가하기 위해 부분 클래스로 놀아 볼 것입니다. –

+1

+1 우아한 솔루션에 대한 것이고 사실 정적 분석이 객체가 단지 'DontHurtMe'인 경우를 다루기에 충분히 똑똑 할 수 있다고 (또는 가능하다면) 의심 스럽습니다. 만약 당신이 어떤 공장을 가지고 있거나 인터페이스가 어떻게 든 연결된다면 당신은 운이 없다. – Dyppl

+0

동의, @ 칼 좋은 계획. 부분적인 클래스 아이디어가 제대로 작동하지 않았다. (정적 메소드 만 사용하는'NastyStatic '때문이라고 생각한다.)하지만, 나는 그것을 전부 stubbed하고, 오버로드를 추가하고, 재 컴파일하고, Find All References를 완벽하게 작업했다. –

0

정적 분석을위한 솔루션을 찾을 수 없습니다. ReSharper의 "Find usages advanced ..."옵션을 재검토하고 아무 것도 찾지 못했습니다. foo is DontHurtMe과 같은 조건으로이 메서드에 조건 중단 점을 지정할 수 있지만 이미 알고 있다고 가정하고 리팩터링 목적보다 버그를 찾으려는 경우에 더 적합합니다.

+0

그것은 수치 스럽습니다. ReSharper가 답이 될지도 모릅니다. 그것을 확인해 주셔서 감사합니다. –

+0

@Ben Scott : 또는 NDepend (http://www.ndepend.com/Features.aspx)를 참조하십시오. 나는 그것에 대한 경험이 없지만 유사한 작업을 위해 그것을 사용하는 것에 관한 이야기를 들었습니다. – Dyppl

2

ReSharper 5 's 구조 검색이 작업을 수행 할 수 있습니다. 언급 한 바와 같이

class Program 
{ 
    static void Main(string[] args) 
    { 

     var hm = new HurtMe(); 
     var dhm = new DontHurtMe(); 

     DoBadThings(hm); 

     DoBadThings(dhm); 

    } 

    static void DoBadThings(IBusinessObject ibo) { } 
} 

interface IBusinessObject { } 

class DontHurtMe : IBusinessObject { } 

class HurtMe : IBusinessObject { } 

지금, 아무리 우리가 지정하는 어떤 옵션 A부터 R 번호 DoBadThingsFind Usages이, 찾을 모두 Main에서 호출 : 다음 코드를 치죠.

그러나 우리

  1. ReSharper | Find | Search with Pattern....
  2. Add Placeholder로 이동하는 경우 | Expression, DoBadThings($dbm$)
  3. 클릭 우리의 결과에서 우리가 얻을

을 찾아 그것을 dhm의 이름을 지정하고 유형 Search pattern에서

  • , 유형으로 DontHurtMe을 지정 와 같이 정적으로 식별 유형의 개체에 대한 DoBadThings의 호출 a DontHurtMe이 아닌HurtMe에 대한 호출입니다.


    나는 @Carl Manaster에서 제공하는 절차의 깔끔함과 같이 할 수 있지만,이 방법은 문제의 방법을 오버로드 할 수없는 경우에 대한 옵션을 제공합니다.

  • +0

    아, 좋습니다. 내가 R #을 시도하는 것을 잊지 않는다면 나는 기억할 것이다. 감사. –

    +0

    이것은 텍스트 검색입니다 (사용할 수있는'type' 패턴 제외). 그래서 같은 이름을 가진 다른 메소드가 있으면 오도 된 결과를 줄 수 있습니다. 개인적으로 X 유형의 인수로 메소드 호출을 찾으려고 할 때 예상대로 작동하도록 관리하지 못했습니다. – Polymorphix