استخدام طرق التمديد لزيادة إمكانية قراءة التعليمات البرمجية

StackOverflow https://stackoverflow.com/questions/1632363

  •  06-07-2019
  •  | 
  •  

سؤال

لذلك كنت أتعامل مع العديد من واجهات برمجة التطبيقات التي قدمها مؤخرًا بائعو البرامج المختلفون لمنتجاتهم.في بعض الأحيان تكون هناك أشياء مفقودة، وأحيانًا أريد فقط أن أجعل الكود أكثر قابلية للقراءة، وأحاول تجنب الكثير من الأساليب الثابتة التي لا تنتمي إلى "الحصول على ما أحتاج إليه" من واجهات برمجة التطبيقات.وهكذا، وجدت نفسي أكتب عددًا لا بأس به من طرق الإرشاد.

ومع ذلك، نظرًا لوجود العديد من الأساليب، ومن أجل إبقاء الأساليب "الخاصة بي" منفصلة عن تلك الخاصة بكائنات واجهة برمجة التطبيقات (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 # سوف تفعل بقية.

وعند النظر إلى الاقتراح المذكور أعلاه الخاص بك سيكون لديك لتقسيم الطبقات اثنين من اعتقد. واحدة لتقديم مجموعة تمديد باستخدام آلية ملحقات وآخر لتوفير كل مجموعة من المنطق.

إذا كنت بحاجة إلى فصل لك من لمحة ثم استخدام اصطلاح التسمية لجعل نظرة فريدة من نوعها. على الرغم من بناء تحوم ومن خلال التحسس وسوف اقول لكم انه هو وسيلة التمديد.

إذا كنت ترغب فقط في فصل المحتوى مثل لديك، ثم عليك فئتين.

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) التي لا يمكنك تعديلها، تعد طرق الامتداد طريقة معقولة لتوسيع تعبير واجهة برمجة التطبيقات (API) مع البقاء منفصلة نسبيًا، IMHO.

تتعلق أكبر مشكلة تتعلق بطرق الامتداد بحقيقة أنه يتم الاستدلال ضمنيًا على أنها متاحة بناءً على تضمين مساحة الاسم (عبارات الاستخدام في الجزء العلوي من الملف).ونتيجة لذلك، إذا نسيت ببساطة تضمين مساحة اسم، فقد ينتهي بك الأمر إلى التساؤل عن سبب عدم توفرها.

أود أيضًا أن أضيف أن طرق الامتداد ليست بناءًا واضحًا، ونتيجة لذلك لا يتوقعها المطورون أو يتوقعونها عادةً.ومع ذلك، مع زيادة استخدام LINQ، أتخيل أن المزيد والمزيد من المطورين سوف يشعرون بالارتياح تجاه استخدامها.

ورأيي هو أنك تقوم بإضافة مستوى إضافي من indirection داع. كنت ترغب في طرق الإرشاد لتكون متوفرة على الكائنات الأصلية ... فلماذا لا وضعها هناك؟ والتحسس تتيح لك معرفة أن الكائنات ملحقات، لحالة نادرة أن يهمك فعلا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top