oop - patterns - object oriented design شرح




متى يكون الفصل كبيرًا جدًا؟ (9)

أميل إلى إنشاء فئات كبيرة جدًا تحتوي على 30-40 (أو أكثر) من الأساليب. كم عدد الطرق كثيرة جدا؟ هل هناك أي "رائحة" أو استخدام قواعد إرشادية؟


أنا لدغة. دون القيام بأكثر من الخوض في الحواف الضحلة للمياه العميقة لتصميم OO ، سأقوم من خلال اثنين من القواعد الأساسية:

  1. الخصائص الثابتة هي موضع شك كبير. اسأل نفسك بقوة عما إذا كانت هناك حاجة فعلاً إليها أم لا.

  2. يجب أن تكون معظم خصائص / سمات فئة خاصة (يمكن الوصول إليها فقط بواسطة مثيل الكائن) أو محمية ، يمكن الوصول إليها فقط بواسطة مثيل للفئة أو فئة مشتقة (فئة فرعية).

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

  4. تكون أساليب أو خصائص Getter / Setter العامة مشكوك فيها حيث أنها تعرض حالة الكائن في المقام الأول (التي ترى البند رقم 2 أعلاه).

  5. يجب أن تعرض الطرق العامة في المقام الأول العمليات المنطقية (الرسائل) التي يستجيب لها مثيل الكائن. يجب أن تكون هذه العمليات ذرية (على سبيل المثال ، لكي يكون الكائن في حالة داخلية متناسقة منطقيًا ، يجب ألا يعتمد على جهات خارجية يرسلها تسلسلًا معينًا من الرسائل). يجب أن تتغير حالة الكائن كنتيجة للاستجابة لهذه الرسائل ويجب أن يتم عرضها كأثر جانبي للرسالة (على سبيل المثال ، نافذة تبلغ عن موقعها كأثر جانبي للسؤال عنها للتحرك مقبول).

ما ورد أعلاه يجب أن يقلل من الواجهة العامة لأشياءك إلى حد كبير.

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

أتمنى أن يساعدك هذا.

هناك الكثير من الكتب هناك على تصميم OO ، تحليل ونمذجة.


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


بشكل عام ، يجب تصميم الصف لفعل شيء واحد والقيام به بشكل جيد. الآن ، مع مثالك في فصل الرياضيات ، يمكن أن يكون بمثابة واجهة لفصل التطبيقات. أو يمكن تقسيمها إلى تسلسل هرمي:

public abstract class Math 
{

       abstract Solve(IMathPayload);
       abstract CanSolve(IMathPayload);
}

public class LinearMath : Math {}

public class DifferentialEquasionMath: Math {}

عدد الطرق في حد ذاته ليس مؤشرا يمكن الاعتماد عليه. ماذا لو كان 20 من هؤلاء مجرد ملاك عقارات؟

جرّب المقاييس الأكثر واقعية ، على الرغم من أن هذا دائمًا عبارة عن حكم. هناك قائمة من "رموز الروائح" here .


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

لكن:

عندما يتعلق الأمر بالبرمجة ، لن تحتاج أبداً إلى أكثر من 40 طريقة في فصل واحد ، ويجب أن تنقسم إلى هناك.

مثال

class HTTP
{
    /*
        * Base functions for HTTP Fetching / transferring / Sending
        * so when it comes to single responsibility this would be the the fetch / set in HTTP
    */
}

عندها ستكون أكثر تحديدًا مع الفئات الفرعية الخاصة بك مثل

class YoutubeUploader extends HTTP
{
    /*
        * This class is responsible for uploading to youtube only
     */
}

class YoutubeDownload extends HTTP
{
    /*
        * This class is responsible for downloading to youtube only
     */
}

class CronRunner extends HTTP
{
    /*
        * This class is responsible for Running your HTTP Cron Tasks
     */
}

لا إذا لم يكن لديك BASE HTTP Class ، فسيتعين عليك تحديد الطرق في جميع الفئات الفرعية الثلاثة لنقل البيانات عبر بروتوكول HTTP.

إن تقسيم حصصك الدراسية إلى مسؤوليات فردية يعطي إطارًا أكثر تنظيماً يؤدي إلى رمز أقل والمزيد من النتائج.

الجميع سبق ذكره: مسؤول مسؤولية واحدة ولكن شيء يجب أن نفهمه حقا.

هناك أيضًا طرق لتقليل التعليمة البرمجية في الفصول الدراسية ، وتأخذ هذا المثال

class User
{
    public function getUsername()
    {
        return $data['username']; 
    }

    public function getPermissions()
    {
        return $data['permissions'];
    }

    public function getFirstname()
    {
        return $data['firstname']; 
    }
}

لا تكون هناك حاجة لذلك فعلاً عندما يمكنك القيام بذلك:

class User
{
    public function __call($method,$params = array())
    {
        if(substr(0,3,$method) == "get")
        {
            $var_name = substr(3,strlen($method),$method);
            return $data[$var_name];
        }
    }
}

هذا من شأنه أن يأخذ السيارة من أي طريقة تسمى التي تبدأ بـ "get" ويستغرق الجزء الأخير من السلسلة ويبحث في الصفيف.


مبادئ توجيهية عامة للتصميم: إذا كان رد فعل الشخص المعقول الأول على <مجموعة من الأشياء> يمكن أن يكون معقولاً "هذا كثير جدًا من <الشيء> s!" ، فهذا كثير جدًا من <الشيء> s.


هذا يعتمد.
إذا كنت في جافا مع الحصول على أزواج / تعيين لكل حقل ، لست مندهشا. ولكن إذا كانت كل واحدة من هذه الطرق أكثر من 100 حيوان خط ، فستكون هذه رائحة.


وكما قال الآخرون ، فالفئة كبيرة للغاية عندما تحاول أن تفعل أكثر من شيء وتنتهك مبدأ المسؤولية الواحدة .

كتاب رائع عن هذا الموضوع ومواضيع أخرى (وأوصي بشدة لأي مطور) هو Clean Code من Bob Martin.



يتم أخذ نقطة حولها في الإصدار الثالث من "فعّال C ++":
"تفضيل الوظائف غير الأعضاء وغير الصديقة إلى وظائف الأعضاء". ما يعنيه هذا هو أنه يجب عليك الحفاظ على صغر حجم صفك نظرًا لأن الصفوف الكبيرة تكون صعبة التوسيع (لا تحسب بشكل جيد)

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

تحياتي الحارة،
مارسين







design