문제

그래서 저는 최근 다른 소프트웨어 공급 업체가 제품에 대해 제공 한 여러 API를 다루고 있습니다. 때로는 상황이 부족하고 때로는 코드를 더 읽기 쉽게 만들고 싶고 API에서 "필요한 것을 얻지 못하는"정적 방법을 피하려고 노력하고 있습니다. 따라서 나는 나 자신이 상당히 몇 가지 확장 방법을 쓰고 있음을 발견했습니다.

그러나 많은 방법이 있고 코드 가독성 측면에서 "나의"방법을 API 객체와 분리하는 "내"방법을 유지하는 데 관심이 있기 때문에, 나는이 작은 무두질을 생각해 냈습니다.

public class MyThirdPartyApiExtensionClass {

    public static MyThirdPartyApiExtensionClass MTPAEC(this ThirdPartyApiClass value) {
        return new MyThirdPartyApiExtensionClass(value);
    }

    private ThirdPartyApiClass value;

    public MyThirdPartyApiExtensionClass(ThirdPartyApiClass extendee) {
        value = extendee;
    }

    public string SomeMethod() {
        string foo = value.SomeCrappyMethodTheProviderGaveUs();
        //do some stuff that the third party api can't do that we need
        return foo;
    }

    public int SomeOtherMethod() {
        int bar = value.WowThisAPISucks(null);
        //more stuff
        return bar;
    }

}

그런 다음 다음과 같은 작업을 수행 할 수 있습니다.

string awesome = instanceOfApiObject.MTPAEC.SomeMethod();

그리고 나는 그들의 물건을 그들의 물건과 깨끗하게 분리하고 있습니다.

이제 내 질문은 .. 이것은 좋은 관행처럼 보이고 코드 가독성을 향상시키는 것 같습니까? 아니면 나쁜 생각입니까? 이 작업에 해로운 결과가 있습니까?

부인 성명:위의 코드는 개념을 보여주는 것입니다. 분명히 실제에는 더 나은 정신 점검과 유용성이 있습니다.

나는 같은 수준의 분리가 단순히 다음과 같이 할 수 있다고 생각합니다.

public static class MyThirdPartyApiExtensionClass {

    public ThirdPartyApiClass MTPAEC(this ThirdPartyApiClass value) {
        return value;
    }

    public string SomeMethod(this ThirdPartyApiClass value) {
        string foo = value.SomeCrappyMethodTheProviderGaveUs();
        //do some stuff that the third party api can't do that we need
        return foo;
    }

    public int SomeOtherMethod(this ThirdPartyApiClass value) {
        int bar = value.WowThisAPISucks(null);
        //more stuff
        return bar;
    }

}
도움이 되었습니까?

해결책

직접적인 질문에 답하기 위해 기능성을 기본 기능과 분리하기 위해 추가 문제를 겪는 것은 나쁜 코드 냄새라고 생각합니다. 코드를 사용법 관점에서 코드와 분리하는 것에 대해 걱정하지 마십시오. 먼저 동일한 기능을 찾아야 할 두 개의 장소가있는 이후로 원하는 것을 찾기가 훨씬 어려워지고 두 번째로 구문은 핵심 개체 (핵심 개체가 아닌 MTPAEC 속성에서 확장자가 작동하는 것처럼 보이게합니다. 이다).

내 제안은 추가 생성자가 없지만이를 가질 수있는 실제 확장 방법을 사용하는 것입니다.

public static class ApiExtension
{
    public static string SomeMethod(this ThirdPartyApiClass value)
    {
        string foo = value.SomeCrappyMethodTheProviderGaveUs();
        //do some stuff that the third party api can't do that we need
        return foo;
    }
}

사용

var mine = new ThirdPartyApiClass();
mine.SomeMethod();

C#은 나머지를 할 것입니다.

위의 제안을 살펴보면 두 수업을 나누어야합니다. 하나는 확장 메커니즘을 사용하여 확장 그룹을 제공하고 다른 하나는 각 논리 그룹을 제공하기위한 것입니다.

당신이 한 눈에 당신의 것을 분리해야한다면, 이름 지정 컨벤션을 사용하여 모양을 독특하게 만듭니다. 호버링과 Intellisense를 통해 확장 방법이라고 말할 것입니다.

당신이 가진 것과 같은 콘텐츠 분리를 원한다면 두 개의 수업이 필요합니다.

public static class ApiExtensionder
{
    public static MTPAEC(this ThirdPartyApiClass value)
    {
        return new MtpaecExtensionWrapper(value);
    }
}

public class MtpaecExtensionWrapper
{
    private ThirdPartyApiClass wrapped;

    public MtpaecExtensionWrapper(ThirdPartyApiClass wrapped)
    {
        this.wrapped = wrapped;
    }

    public string SomeMethod()
    {
        string foo = this.wrapped.SomeCrappyMethodTheProviderGaveUs();
        //do some stuff that the third party api can't do that we need
        return foo;
    }
}

다른 팁

수정할 수없는 API를 처리 할 때 확장 방법은 상대적으로 분리 된 IMHO를 유지하면서 API의 표현력을 확장하는 합리적인 방법입니다.

확장 방법의 가장 큰 문제는 네임 스페이스 포함 (파일 상단의 사용 명령문)을 기반으로 암시 적으로 추론된다는 사실과 관련이 있습니다. 결과적으로, 단순히 네임 스페이스를 포함하는 것을 잊어 버린 경우, 왜 이용할 수 없는지 궁금해하는 머리를 긁을 수 있습니다.

또한 확장 방법은 명백한 구조가 아니며 결과적으로 개발자는 일반적으로 기대하거나 예상하지 않습니다. 그러나 LINQ의 사용이 증가함에 따라 점점 더 많은 개발자들이 사용에 익숙해 질 것이라고 생각합니다.

내 의견은 당신이 불필요하게 추가 간접 수준을 추가하고 있다는 것입니다. 원래 오브젝트에서 확장 방법을 사용할 수 있기를 원합니다. 그렇다면 왜 거기에 넣지 않겠습니까? Intellisense는 실제로 걱정하는 드문 경우에 대한 객체가 확장임을 알려줄 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top