كل مدخل عبر المجلدات الأربعة — تقنيات إعادة هيكلة الكود، وأنماط التصميم، وروائح الكود، والأنماط المعمارية — مجمعة حسب عائلتها.
إعادة هيكلة منظمة للكود الحالي — للحفاظ على السلوك وتحسين التصميم.
المشكلة: لا تمتلك الدالة البيانات الكافية لتنفيذ إجراءات معينة. الحل: قم بإنشاء معامل جديد لتمرير البيانات اللازمة.
المشكلة: لا يتم استخدام الدالة بواسطة فئات أخرى أو تُستخدم فقط داخل التسلسل الهرمي لفئتها الخاصة. الحل: اجعل الدالة خاصة (private) أو محمية (protected).
المشكلة: تحتوي توابعك على مجموعة متكررة من المعاملات. الحل: استبدل هذه المعاملات بكائن.
المشكلة: تقوم توابع متعددة بإجراءات متشابهة تختلف فقط في قيمها الداخلية أو أرقامها أو عملياتها. الحل: اجمع هذه التوابع معاً باستخدام معامل يمرر القيمة الخاصة المطلوبة.
المشكلة: تحصل على قيم متعددة من كائن ثم تمررها كمعاملات إلى تابع. الحل: بدلاً من ذلك، جرب تمرير الكائن بأكمله.
المشكلة: لا يُستخدم المعامل داخل متن التابع. الحل: أزل المعامل غير المستخدم.
المشكلة: يجب تعيين قيمة الحقل فقط عند إنشائه، ولا تتغير في أي وقت بعد ذلك. الحل: لذا احذف التوابع التي تقوم بتعيين قيمة هذا الحقل.
المشكلة: لا يوضح اسم التابع ما يفعله التابع. الحل: أعد تسمية التابع.
المشكلة: لديك باني (Constructor) معقد يقوم بشيء أكثر من مجرد تعيين قيم المعاملات في حقول الكائن. الحل: أنشئ تابعاً مصنعاً (Factory Method) واستخدمه لاستبدال استدعاءات الباني.
المشكلة: دالة تعيد قيمة خاصة تشير إلى وجود خطأ؟ الحل: قم برمي استثناء (exception) بدلاً من ذلك.
المشكلة: تقوم برمي استثناء في مكان يمكن لاختبار بسيط فيه القيام بالمهمة؟ الحل: استبدل الاستثناء باختبار شرطي.
المشكلة: تنقسم الدالة إلى أجزاء، يتم تشغيل كل منها اعتمادًا على قيمة معامل (parameter). الحل: استخلص الأجزاء الفردية من الدالة إلى دوال خاصة بها واستدعها بدلاً من الدالة الأصلية.
المشكلة: استدعاء دالة استعلام (query method) وتمرير نتائجها كمعاملات لدالة أخرى، في حين أن هذه الدالة يمكنها استدعاء الاستعلام مباشرة. الحل: بدلاً من تمرير القيمة عبر معامل، حاول وضع استدعاء الاستعلام داخل جسم الدالة.
المشكلة: هل لديك دالة تعيد قيمة ولكنها تغير أيضًا شيئًا ما داخل الكائن؟ الحل: قسّم الدالة إلى دالتين منفصلتين. كما تتوقع، يجب أن تعيد إحداهما القيمة والأخرى تعدل الكائن.
المشكلة: لديك ارتباط ثنائي الاتجاه بين فئات، ولكن إحدى الفئات لا تستخدم ميزات الفئة الأخرى. الحل: قم بإزالة الارتباط غير المستخدم.
المشكلة: لديك كائن مرجعي (reference object) صغير جداً ونادراً ما يتغير، مما لا يبرر إدارة دورة حياته. الحل: قم بتحويله إلى كائن قيمة (value object).
المشكلة: لديك فئتان تحتاج كل منهما إلى استخدام ميزات الفئة الأخرى، ولكن الارتباط بينهما أحادي الاتجاه فقط. الحل: قم بإضافة الارتباط المفقود إلى الفئة التي تحتاجه.
المشكلة: لديك العديد من النسخ المتطابقة لفئة واحدة تحتاج إلى استبدالها بكائن واحد. الحل: قم بتحويل الكائنات المتطابقة إلى كائن مرجعي واحد.
المشكلة: هل يتم تخزين بيانات النطاق (domain data) في فئات مسؤولة عن واجهة المستخدم الرسومية (GUI)؟ الحل: إذن فمن الجيد فصل البيانات في فئات منفصلة، مع ضمان الاتصال والمزامنة بين فئة النطاق وواجهة المستخدم الرسومية.
المشكلة: تحتوي فئة على حقل مجموعة (collection field) ودوال الحصول والتعيين (getter and setter) بسيطة للعمل مع المجموعة. الحل: اجعل القيمة التي تعيدها دالة الحصول للقراءة فقط، وأنشئ دوال لإضافة/حذف عناصر المجموعة.
المشكلة: لديك حقل عام (public field). الحل: اجعل الحقل خاصاً (private) وأنشئ دوال وصول (access methods) له.
المشكلة: لديك مصفوفة تحتوي على أنواع مختلفة من البيانات. الحل: استبدل المصفوفة بكائن يحتوي على حقول منفصلة لكل عنصر.
المشكلة: فئة (أو مجموعة فئات) تحتوي على حقل بيانات. هذا الحقل له سلوكه الخاص وبياناته المرتبطة به. الحل: إنشاء فئة جديدة، ووضع الحقل القديم وسلوكه في هذه الفئة، ثم تخزين كائن الفئة في الفئة الأصلية.
المشكلة: يستخدم الكود الخاص بك رقمًا له معنى معين. الحل: استبدل هذا الرقم بثابت له اسم مقروء ومفهوم يوضح معنى الرقم.
المشكلة: لديك فئات فرعية تختلف فقط في دوالها (التي تعيد قيمًا ثابتة). الحل: استبدل الدوال بحقول في الفئة الأب واحذف الفئات الفرعية.
المشكلة: تحتوي فئة ما على حقل يحتوي على كود نوع (type code). قيم هذا النوع لا تُستخدم في شروط العوامل ولا تؤثر على سلوك البرنامج. الحل: قم بإنشاء فئة جديدة واستخدم كائناتها بدلاً من قيم كود النوع.
المشكلة: لديك نوع مرمز يؤثر على السلوك ولكن لا يمكنك استخدام فئات فرعية للتخلص منه. الحل: استبدل كود النوع بكائن حالة (state object). إذا كان من الضروري استبدال قيمة حقل بكود نوع، يتم "توصيل" كائن حالة آخر.
المشكلة: لديك نوع مرمز يؤثر بشكل مباشر على سلوك البرنامج (تؤدي قيم هذا الحقل إلى تشغيل أكواد برمجية مختلفة في الجمل الشرطية). الحل: أنشئ فئات فرعية (subclasses) لكل قيمة من قيم النوع المرمز. ثم استخلص السلوكيات ذات الصلة من الفئة الأصلية إلى هذه الفئات الفرعية. واستبدل كود تدفق التحكم بتعدد الأشكال (polymorphism).
المشكلة: تستخدم الوصول المباشر إلى الحقول الخاصة داخل الفئة. الحل: أنشئ دالة جلب (getter) ودالة تعيين (setter) للحقل، واستخدمهما فقط للوصول إلى الحقل.
المشكلة: لديك تسلسل هرمي للفئات (class hierarchy) تكون فيه الفئة الفرعية (subclass) مطابقة تقريباً للفئة العليا (superclass). الحل: ادمج الفئة الفرعية والفئة العليا.
المشكلة: يستخدم عملاء متعددون نفس الجزء من واجهة الفئة. حالة أخرى: جزء من الواجهة في فئتين متطابق. الحل: انقل هذا الجزء المتطابق إلى واجهة مستقلة خاصة به.
المشكلة: تحتوي فئة على ميزات تُستخدم فقط في حالات معينة. الحل: أنشئ فئة فرعية واستخدمها في هذه الحالات.
المشكلة: لديك فئتان تحتويان على حقول ودوال مشتركة. الحل: أنشئ فئة عليا (superclass) مشتركة لهما وانقل إليها جميع الحقول والدوال المتطابقة.
المشكلة: تنفذ فئاتك الفرعية خوارزميات تحتوي على خطوات متشابهة بنفس الترتيب. الحل: انقل هيكل الخوارزمية والخطوات المتطابقة إلى فئة عليا، واترك تنفيذ الخطوات المختلفة في الفئات الفرعية.
المشكلة: تحتوي فئاتك الفرعية (Subclasses) على بانيات (Constructors) بها كود متطابق غالباً. الحل: أنشئ بانيًا للفئة الفائقة (Superclass) وانقل الكود المشترك في الفئات الفرعية إليه. واستدعِ باني الفئة الفائقة في بانيات الفئات الفرعية.
المشكلة: فئتان تحتويان على نفس الحقل. الحل: أزل الحقل من الفئات الفرعية وانقله إلى الفئة الفائقة.
المشكلة: تحتوي فئاتك الفرعية على توابع تؤدي عملاً متشابهاً. الحل: اجعل التوابع متطابقة ثم انقلها إلى الفئة الفائقة المناسبة.
المشكلة: هل يُستخدم الحقل في عدد قليل فقط من الفئات الفرعية؟ الحل: انقل الحقل إلى هذه الفئات الفرعية.
المشكلة: هل السلوك المطبق في الفئة الفائقة يُسخدم من قِبل فئة فرعية واحدة فقط (أو عدد قليل منها)؟ الحل: انقل هذا السلوك إلى الفئات الفرعية.
المشكلة: تحتوي فئة ما على العديد من الدوال البسيطة التي تفوض العمل إلى جميع دوال فئة أخرى. الحل: جعل الفئة وارثة للفئة المفوضة، مما يجعل دوال التفويض غير ضرورية.
المشكلة: لديك فئة فرعية تستخدم جزءًا فقط من دوال فئتها الفائقة (أو لا يمكنها وراثة بيانات الفئة الفائقة). الحل: قم بإنشاء حقل وضع فيه كائن الفئة الفائقة، وفوّض الدوال إلى كائن الفئة الفائقة، وتخلص من الوراثة.
المشكلة: لديك شروط متعددة تؤدي إلى نفس النتيجة أو الإجراء. الحل: ادمج كل هذه الشروط في تعبير شرطي واحد.
المشكلة: يمكن العثور على كود متطابق في جميع فروع الشرط. الحل: انقل الكود خارج الشرط.
المشكلة: لديك تعبير شرطي معقد (if-then/else أو switch). الحل: قم بتفكيك الأجزاء المعقدة من التعبير الشرطي إلى دوال منفصلة: الشرط (condition)، وثم (then)، وإلا (else).
المشكلة: لكي يعمل جزء معين من الكود بشكل صحيح، يجب أن تكون شروط أو قيم معينة صحيحة. الحل: استبدل هذه الافتراضات بفحوصات توكيد (assertions) محددة.
المشكلة: نظراً لأن بعض التوابع تعيد قيمة null بدلاً من كائنات حقيقية، فإن لديك العديد من فحوصات التحقق من null في الكود. الحل: بدلاً من null، أعد كائناً فارغاً (Null Object) يقدم السلوك الافتراضي.
المشكلة: لديك متغير منطقي (Boolean) يعمل كراية تحكم لتعبيرات منطقية متعددة. الحل: بدلاً من هذا المتغير، استخدم break و continue و return.
المشكلة: لديك جملة شرطية تؤدي إجراءات مختلفة اعتماداً على نوع الكائن أو خصائصه. الحل: أنشئ فئات فرعية (Subclasses) تطابق فروع الجملة الشرطية. وفيها، أنشئ تابعاً مشتركاً وانقل الكود من الفرع المقابل للجملة الشرطية إليه. ثم استبدل الجملة الشرطية باستدعاء التابع المعني. وتكون النتيجة هي الوصول للتطبيق الصحيح عبر تعدد الأشكال (Polymorphism) اعتماداً على فئة الكائن.
المشكلة: لديك مجموعة من الجمل الشرطية المتداخلة ويصعب تحديد التدفق الطبيعي لتنفيذ الكود. الحل: اعزل جميع الفحوصات الخاصة والحالات الاستثنائية في عبارات منفصلة وضعها قبل الفحوصات الرئيسية. من الناحية المثالية، يجب أن تحصل على قائمة مسطحة من الشروط، واحدًا تلو الآخر.
المشكلة: عندما تقوم فئة واحدة بعمل فئتين، ينتج عن ذلك ارتباك وتعقيد. الحل: بدلاً من ذلك، أنشئ فئة جديدة وضع فيها الحقول والدوال المسؤولة عن الوظائف ذات الصلة.
المشكلة: يحصل العميل على الكائن B من حقل أو دالة في الكائن A. ثم يقوم العميل باستدعاء دالة في الكائن B. الحل: أنشئ دالة جديدة في الفئة A تفوض الاستدعاء إلى الكائن B. الآن لا يعرف العميل الفئة B ولا يعتمد عليها.
المشكلة: الفئة لا تفعل شيئاً تقريباً وليست مسؤولة عن أي شيء، ولا توجد مسؤوليات إضافية مخططة لها. الحل: انقل جميع الميزات من الفئة إلى فئة أخرى.
المشكلة: لا تحتوي فئة أدوات (Utility Class) على التابع الذي تحتاجه ولا يمكنك إضافة التابع إلى الفئة. الحل: أضف التابع إلى فئة عميلة (Client Class) ومرر كائناً من فئة الأدوات إليها كمعامل.
المشكلة: لا تحتوي فئة أدوات (Utility Class) على بعض التوابع التي تحتاجها. ولكن لا يمكنك إضافة هذه التوابع إليها. الحل: أنشئ فئة جديدة تحتوي على التوابع المطلوبة واجعلها إما فئة فرعية (Subclass) أو فئة مغلفة (Wrapper) لفئة الأدوات.
المشكلة: يتم استخدام حقل في فئة أخرى أكثر من استخدامه في الفئة الخاصة به. الحل: أنشئ حقلاً في فئة جديدة ووجّه جميع مستخدمي الحقل القديم إليه.
المشكلة: يتم استخدام تابع في فئة أخرى أكثر من استخدامه في الفئة الخاصة به. الحل: أنشئ تابعاً جديداً في الفئة التي تستخدم التابع بشكل أكبر، ثم انقل الكود من التابع القديم إلى هناك. حوّل كود التابع الأصلي إلى إشارة مرجعية للتابع الجديد في الفئة الأخرى أو احذفه تماماً.
المشكلة: تحتوي الفئة على عدد كبير جداً من التوابع التي تقوم ببساطة بالتفويض لكائنات أخرى. الحل: احذف هذه التوابع واجبر العميل على استدعاء التوابع النهائية مباشرة.
المشكلة: لديك جزء من الكود يمكن تجميعه معاً. الحل: انقل هذا الكود إلى دالة جديدة منفصلة واستبدل الكود القديم باستدعاء لهذه الدالة.
المشكلة: لديك تعبير برمجى يصعب فهمه. الحل: ضع نتيجة التعبير أو أجزائه في متغيرات منفصلة توضح نفسها بنفسها.
المشكلة: عندما يكون متن التابع أكثر وضوحاً من التابع نفسه، استخدم هذه التقنية. الحل: استبدل استدعاءات التابع بمحتوى التابع واحذف التابع نفسه.
المشكلة: لديك متغير مؤقت يتم تعيين نتيجة تعبير بسيط له فقط ولا شيء غير ذلك. الحل: استبدل الإشارات إلى المتغير بالتعبير نفسه.
المشكلة: يتم تعيين قيمة معينة لمعامل داخل متن التابع. الحل: استخدم متغيراً محلياً بدلاً من المعامل.
المشكلة: لديك دالة طويلة تتشابك فيها المتغيرات المحلية لدرجة أنه لا يمكنك تطبيق تقنية استخلاص الدالة (Extract Method). الحل: قم بتحويل الدالة إلى فئة منفصلة بحيث تصبح المتغيرات المحلية حقولاً في هذه الفئة. بعد ذلك، يمكنك تقسيم الدالة إلى عدة دوال فرعية داخل نفس الفئة.
المشكلة: تضع نتيجة تعبير في متغير محلي لاستخدامه لاحقًا في الكود الخاص بك. الحل: انقل التعبير بالكامل إلى دالة منفصلة وأعد النتيجة منها. استعلم من الدالة بدلاً من استخدام المتغير. وادمج الدالة الجديدة في دوال أخرى، إذا لزم الأمر.
المشكلة: لديك متغير محلي يُستخدم لتخزين قيم وسيطة مختلفة داخل دالة (باستثناء متغيرات حلقات التكرار). الحل: استخدم متغيرات مختلفة للقيم المختلفة. يجب أن يكون كل متغير مسؤولاً عن شيء معين واحد فقط.
المشكلة: إذن تريد استبدال خوارزمية موجودة بأخرى جديدة؟ الحل: استبدل جسم الدالة التي تنفذ الخوارزمية بالخوارزمية الجديدة.
حلول نموذجية للمشاكل الشائعة في تصميم البرمجيات، مرتبة حسب الغرض.
المصنع المجرد (Abstract Factory) هو نمط تصميم إنشائي يتيح لك إنتاج عائلات من الكائنات ذات الصلة دون تحديد فئاتها الملموسة.
البنّاء هو نمط تصميم إنشائي يُتيح لك إنشاء كائنات معقدة خطوةً بخطوة. يُتيح النمط إنتاج أنواع وتمثيلات مختلفة لكائن ما باستخدام نفس شيفرة البناء.
طريقة المصنع هي نمط تصميم إنشائي يوفّر واجهة لإنشاء الكائنات في الصنف الأعلى (superclass)، لكنه يسمح للأصناف الفرعية بتغيير نوع الكائنات التي سيتم إنشاؤها.
النموذج الأولي (Prototype) هو نمط تصميم إبداعي يتيح لك نسخ الكائنات الموجودة دون جعل كودك يعتمد على فئاتها.
Singleton (النمط الفردي) هو نمط تصميم إنشائي يتيح لك ضمان أن الصنف لديه نسخة واحدة فقط، مع توفير نقطة وصول عالمية لهذه النسخة.
المهايئ (Adapter) هو نمط تصميم هيكلي يسمح للكائنات ذات الواجهات غير المتوافقة بالتعاون معاً.
الجسر هو نمط تصميم هيكلي يتيح لك تقسيم كلاس ضخم أو مجموعة من الكلاسات المترابطة إلى تسلسلين هرميين منفصلين — التجريد والتنفيذ — يمكن تطويرهما بشكل مستقل عن بعضهما.
المركَّب هو نمط تصميم هيكلي يتيح لك تكوين الكائنات في هياكل شجرية ثم العمل مع هذه الهياكل كما لو كانت كائنات فردية.
المُزَخرِف هو نمط تصميم هيكلي يتيح لك إرفاق سلوكيات جديدة بالكائنات عن طريق وضع هذه الكائنات داخل كائنات غلاف خاصة تحتوي على هذه السلوكيات.
الواجهة (Facade) هي نمط تصميم هيكلي يوفر واجهة مبسطة لمكتبة أو إطار عمل أو أي مجموعة معقدة أخرى من الفئات.
وزن الذبابة نمط تصميم هيكلي يتيح لك احتواء عدد أكبر من الكائنات في حجم ذاكرة الوصول العشوائي المتاحة، من خلال مشاركة الأجزاء المشتركة من الحالة بين كائنات متعددة بدلاً من الاحتفاظ بجميع البيانات في كل كائن على حدة.
الوكيل (Proxy) هو نمط تصميم هيكلي يتيح لك توفير بديل أو عنصر نائب لكائن آخر. يتحكم الوكيل في الوصول إلى الكائن الأصلي، مما يسمح لك بتنفيذ شيء ما إما قبل وصول الطلب إلى الكائن الأصلي أو بعده.
سلسلة المسؤوليات هي نمط تصميم سلوكي يتيح لك تمرير الطلبات عبر سلسلة من المعالجات. عند استقبال طلب، يقرر كل معالج إما معالجة الطلب أو تمريره إلى المعالج التالي في السلسلة.
الأمر (Command) هو نمط تصميم سلوكي يحوّل الطلب إلى كائن مستقل يحتوي على جميع المعلومات المتعلقة بالطلب. يتيح لك هذا التحويل تمرير الطلبات كوسائط للطرائق، وتأجيل تنفيذ الطلب أو وضعه في طابور، ودعم العمليات القابلة للتراجع.
المُكرِّر هو نمط تصميم سلوكي يتيح لك التنقل عبر عناصر المجموعة دون الكشف عن تمثيلها الداخلي (قائمة، مكدس، شجرة، إلخ).
الوسيط هو نمط تصميم سلوكي يُتيح لك تقليل الاعتماديات الفوضوية بين الكائنات. يقيّد النمط الاتصالات المباشرة بين الكائنات ويُجبرها على التعاون فقط عبر كائن وسيط.
التذكار هو نمط تصميم سلوكي يتيح لك حفظ الحالة السابقة لكائن واستعادتها دون الكشف عن تفاصيل تنفيذه.
المراقب هو نمط تصميم سلوكي يتيح لك تحديد آلية اشتراك لإخطار كائنات متعددة بأي أحداث تحدث للكائن الذي يراقبونه.
الحالة (State) هو نمط تصميم سلوكي يتيح لكائنٍ تغيير سلوكه عند تغيّر حالته الداخلية. ويبدو الأمر كما لو أنّ الكائن قد غيّر فئته.
الاستراتيجية هو نمط تصميم سلوكي يتيح لك تعريف عائلة من الخوارزميات، ووضع كل منها في فئة منفصلة، وجعل كائناتها قابلة للتبادل.
أسلوب القالب هو نمط تصميم سلوكي يُعرّف الهيكل العام لخوارزمية في الصنف الأساسي، لكنه يتيح للأصناف الفرعية إعادة تعريف خطوات محددة من الخوارزمية دون تغيير بنيتها.
الزائر هو نمط تصميم سلوكي يتيح لك فصل الخوارزميات عن الكائنات التي تعمل عليها.
مؤشرات على مشاكل أعمق — وعمليات إعادة صياغة الكود التي تعالجها.
كلاسان يؤديان وظائف متطابقة لكنهما يمتلكان أسماء أساليب مختلفة.
إذا كانت الفئة الفرعية (subclass) تستخدم فقط بعض الدوال والخصائص الموروثة من فئاتها الأبوية، فإن التدرج الهرمي يكون غير متوازن. قد تظل الدوال غير المطلوبة ببساطة غير مستخدمة أو يتم إعادة تعريفها لإطلاق استثناءات (exceptions).
لديك عامل switch معقد أو سلسلة من عبارات if.
تحصل الحقول المؤقتة على قيمها (وبالتالي تكون الكائنات بحاجة إليها) في ظل ظروف معينة فقط. وخارج هذه الظروف، تظل فارغة.
أسلوب مليء بتعليقات توضيحية.
كلاس البيانات هو كلاس يحتوي فقط على حقول وأساليب بسيطة للوصول إليها (getters وsetters). هذه الكلاسات مجرد حاويات للبيانات تستخدمها كلاسات أخرى، ولا تحتوي على أي وظائف إضافية ولا تستطيع التعامل باستقلالية مع البيانات التي تملكها.
متغير أو معامل أو حقل أو أسلوب أو كلاس لم يعد مستخدماً (عادةً لأنه أصبح قديماً).
يبدو مقطعا الكود متطابقَين تقريباً.
فهم الفئات وصيانتها يكلفان دائماً وقتاً ومالاً. لذا إذا كانت الفئة لا تفعل ما يكفي لتستحق اهتمامك، فيجب حذفها.
هناك فئة أو دالة أو حقل أو معامل (parameter) غير مستخدم.
في بعض الأحيان تحتوي أجزاء مختلفة من الكود على مجموعات متطابقة من المتغيرات (مثل معاملات الاتصال بقاعدة البيانات). ينبغي تحويل هذه التجمعات إلى كلاسات مستقلة.
تحتوي الكلاس على حقول/دوال/أسطر كود كثيرة.
تحتوي الدالة على عدد كبير جداً من أسطر الكود. بشكل عام، أي دالة يزيد طولها عن عشرة أسطر يجب أن تدفعك إلى التساؤل.
أكثر من ثلاثة أو أربعة معاملات في الدالة.
استخدام الأنواع الأساسية (primitives) بدلاً من الكائنات الصغيرة للمهام البسيطة (مثل العملة، النطاقات، سلاسل النصوص الخاصة بأرقام الهواتف، إلخ.) استخدام الثوابت لترميز المعلومات (مثل الثابت USER_ADMIN_ROLE = 1 للإشارة إلى المستخدمين الذين لديهم صلاحيات المسؤول.) استخدام الثوابت النصية كأسماء حقول للاستخدام في مصفوفات البيانات.
تجد نفسك مضطراً لتغيير كثير من الوظائف غير المترابطة عند إجراء تغييرات على فئة. على سبيل المثال، عند إضافة نوع منتج جديد يتعين عليك تغيير وظائف البحث والعرض وطلب المنتجات.
كلما قمت بإنشاء فئة فرعية (subclass) لفئة ما، تجد نفسك بحاجة إلى إنشاء فئة فرعية لفئة أخرى.
يتطلب إجراء أي تعديلات إجراء العديد من التغييرات الصغيرة على العديد من الفئات المختلفة.
تصل إحدى الوظائف إلى بيانات كائن آخر أكثر من بياناتها الخاصة.
تستخدم إحدى الفئات الحقول والوظائف الداخلية لفئة أخرى.
في الكود، ترى سلسلة من الاستدعاءات تشبه $a->b()->c()->d()
إذا كانت الفئة تؤدي عملاً واحداً فقط، وهو تفويض العمل إلى فئة أخرى، فلماذا توجد على الإطلاق؟
أنماط ومنهجيات على مستوى النظام — DDD وCQRS وTDD والتطوير القائم على المواصفات (Spec-Driven Development).
نهج في تطوير البرمجيات يضع نموذجًا غنيًا لمجال الأعمال في صميم التصميم، معبَّرًا عنه بلغة مشتركة بين المهندسين وخبراء المجال.
فصل النموذج الذي يُغيّر الحالة (الأوامر) عن النموذج الذي يقرأ الحالة (الاستعلامات)، بحيث يمكن نمذجة كل جانب وتوسيعه وتحسينه بشكل مستقل.
منهجية تطوير تكتب فيها اختباراً فاشلاً قبل الكود الذي يجتازه، ثم تُعيد الهيكلة — مدعاً الاختباراتِ تقود التصميم في دورات قصيرة ومتسارعة.
اكتب مواصفة صريحة وموثوقة أولاً، ثم انطلق منها في التنفيذ والاختبارات والكود المُولَّد — محافظاً على المواصفة بوصفها المصدر الوحيد للحقيقة.