Использование методов расширения для повышения читабельности кода - PullRequest
0 голосов
/ 27 октября 2009

Итак, я недавно имел дело с несколькими 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;
    }

}

Ответы [ 3 ]

2 голосов
/ 27 октября 2009

Чтобы ответить на ваш прямой вопрос, я думаю, что преодоление дополнительных трудностей, связанных с выделением вашей функциональности из базовой функциональности, является неприятным запахом кода. Не беспокойтесь о том, чтобы ваш код был отделен от кода с точки зрения использования. Во-первых, это значительно усложняет поиск того, что вы ищете, поскольку теперь есть два места для поиска одинаковых функций, и, во-вторых, синтаксис делает вид, что ваши расширения работают со свойством MTPAEC, а не с основным объектом ( есть).

Мое предложение состоит в том, чтобы использовать реальные методы Extension, которые позволяют вам иметь это, но без дополнительного конструктора.

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;
    }
}
2 голосов
/ 27 октября 2009

При работе с API, который вы не можете изменить, методы расширения являются разумным способом расширить выразительность API, оставаясь относительно отделенным, ИМХО.

Самая большая проблема с методами расширения связана с тем фактом, что они неявно предполагаются доступными на основе включения пространства имен (операторы using в верхней части файла). В результате, если вы просто забудете включить пространство имен, вы можете почесать голову, задаваясь вопросом, почему его нет в наличии.

Я бы также добавил, что методы расширения не являются очевидной конструкцией, и в результате разработчики обычно не ожидают или не ожидают их. Тем не менее, с расширением использования LINQ, я думаю, все больше и больше разработчиков будут чувствовать себя комфортно с их использованием.

0 голосов
/ 27 октября 2009

Мое мнение, что вы добавляете дополнительный уровень косвенности без необходимости. Вы хотите, чтобы методы расширения были доступны для исходных объектов ... так почему бы не поместить их туда? Intellisense сообщит вам, что объекты являются расширениями, для того редкого случая, который вас действительно волнует.

...