في هذه المقالة ، سأحاول التحدث عن مبدأ التصميم المسمى Inversion of Control / IoC ، والذي يسمى أيضًا مبدأ هوليوود.
سأوضح كيف يرتبط هذا
بمبدأ استبدال Barbara Liskovo (LSP) ، وكذلك المساهمة في الحرب المقدسة الخاصة مقابل المحمية.

كتقديم ، أود أن أقول بضع كلمات عن نفسي. أنا مهندس برمجيات عن طريق التدريب ، لقد عملت في صناعة تكنولوجيا المعلومات منذ أكثر من 10 سنوات ، ومؤخراً كنت مولعا بكتابة مقالات مهنية موضوعية. البعض منهم كانوا ناجحين. في وقت سابق ، نشرت على مورد آخر ، لسوء الحظ ، يتعذر الوصول إليها في روسيا (تحيات إلى Roskomnadzor). إذا أراد شخص ما التعرف عليه ، فأنت تعرف ما يجب القيام به.
يتم تقديم جميع أمثلة الكود ، كالمعتاد ، في المقالة برمز زائف منمق كـ "php مكروه".
المهمة الأولية
لجعله أسرع وأكثر قابلية للفهم ، ننتقل إلى المثال على الفور. من قسم المبيعات أردت أن أرى المقاييس: كم من المال نربحه شهريًا ، يوميًا ، كل ساعة.
نحل هذه المشكلة بمساعدة ثلاثة فرق يتم تشغيلها بشكل دوري وفق جدول زمني:
- MonthlyReportCommand
- DailyReportCommand
- HourlyRerortCommand
سنحتاج إلى واجهات:
interface ReportCommandInterface { public function createReport(): Money; } interface MoneyRepositoryInterface { public function getMoney(Period $period): array; } interface MetricRepositoryInterface { public function saveMoneyMetric(Period $period, Money $amount, string $metricType); }
نكتب فرق التقارير (تم حذف الأخير ، كتمرين عملي لأولئك الذين يرغبون في الفهم والممارسة بشكل جيد ، اكتبه بنفسك):
class MonthlyReportCommand implements ReportCommandInterface {
ونرى أن رمز طريقة calculateTotals () سيكون هو نفسه تمامًا في جميع الحالات. أول ما يتبادر إلى الذهن هو وضع رمز مكرر في فئة مجردة مشتركة. مثل هذا:

abstract class AbstractReportCommand { protected function calculateTotals(array $moneyRecords): Money {
طريقة calculateTotals () هي جزء من الآليات الداخلية لفصلنا. نحن نغلقه بحكمة ، لأنه لا ينبغي أن يطلق عليه عملاء خارجيون - نحن لا نقوم بتصميمه لهذا الغرض. نعلن هذه الطريقة محمية ، لأن نحن نخطط للاتصال به في الورثة - هذا هو هدفنا. من الواضح أن مثل هذا الفصل التجريدي يشبه إلى حد كبير ما يشبه المكتبة - فهو يوفر بعض الطرق فقط (لخبراء php: أي أنها تعمل مثل Trait).
سر الطبقات التجريدية
لقد حان الوقت لأخذ استراحة من المثال واستعادة الغرض من الطبقات المجردة:
تتضمن الطبقة التجريدية آليات عامة ، مع السماح للورثة في نفس الوقت بتنفيذ سلوكهم الخاص.التجريد (اللات. Abstract - الهاء) هو الهاء عن التفاصيل والتعميم. في هذه اللحظة ، يعمم الفصل AbstractReportCommand فقط الأموال التي يتم حسابها لجميع التقارير. ولكن يمكننا أن نجعل تجريدنا أكثر كفاءة باستخدام مبدأ هوليوود ، والذي يبدو كالتالي:
"لا تتصل بنا ، سنتصل بك"لنرى كيف يعمل هذا ، دعونا نضع في AbstractReportCommand آلية إبلاغ عامة:

abstract class AbstractReportCommand implements ReportCommandInterface { private $moneyRepository; private $metricRepository;
ماذا فعلنا؟ لا ينطبق أي من أحفاد الصف التجريدي على الآليات الشائعة (لا تتصل بنا). بدلاً من ذلك ، يمنح التجريد ورثته مخططًا عامًا للوظائف ويتطلب منهم تنفيذ ميزات سلوكية معينة ، وذلك باستخدام النتائج فقط (سوف ندعوك لأنفسنا).
ولكن ماذا عن IoC الموعودة ، LSP ، الخاص مقابل المحمي؟
فما علاقة انقلاب السيطرة به؟ من أين يأتي هذا الاسم؟ بسيط للغاية: أولاً ، قمنا بتعيين تسلسل المكالمات مباشرة في التطبيقات النهائية ، والتحكم في ما سيتم القيام به ومتى. وبعد ذلك ، نقلنا هذا المنطق إلى تجريد عام. الآن ، يتحكم التجريد في ما سيتم تحديده ومتى سيتم ذلك ، والتطبيقات ببساطة تطيع هذا. وهذا هو ، ونحن مقلوب السيطرة.
لإصلاح هذا السلوك وتجنب المشكلات المتعلقة
بمبدأ استبدال Barbara Liskov (LSP) ، يمكنك إغلاق الأسلوب createReport () من خلال تضمين final في تعريف الطريقة. بعد كل شيء ، يعلم الجميع أن LSP يرتبط مباشرة بالميراث.
abstract class AbstractReportCommand implements ReportCommandInterface { final public function createReport(): Money {
ثم تصبح جميع أحفاد الفئة AbstractReportCommand تابعة بشكل صارم لمنطق واحد لا يمكن إعادة تعريفه. الانضباط الحديد ، النظام ، مستقبل مشرق.
لنفس السبب ، تصبح ميزة الحماية الخاصة المحمية ظاهرة. يجب توصيل كل ما يتعلق بآليات التشغيل العامة في فصل تجريدي ولا يمكن إعادة تعريفه - خاص. كل ما يحتاج إلى إعادة تعريف / تنفيذها في حالات خاصة هو حماية مجردة. تم تصميم أي طرق لأغراض محددة. وإذا كنت لا تعرف نوع النطاق الذي يجب تعيينه لطريقة ما ، فهذا يعني أنك لا تعرف سبب إنشائها. هذا التصميم يستحق المراجعة.
النتائج
يفضل بناء الطبقات المجردة دائمًا باستخدام Inversion of control ، منذ ذلك الحين يسمح لك باستخدام فكرة التجريد على أكمل وجه. لكن استخدام الفصول المجردة كمكتبات في بعض الحالات يمكن تبريره أيضًا.
إذا نظرت على نطاق أوسع ، فإن مواجهتنا للمدينة الصغيرة بين مبدأ هوليوود وفئة المكتبة المجردة تتحول إلى نزاع: إطار (IoC للبالغين) مقابل مكتبة. لا يوجد أي فائدة في إثبات أيهما أفضل - يتم إنشاء كل منهما لغرض محدد. الشيء الوحيد المهم هو خلق واعية لمثل هذه الهياكل.
شكرا لجميع الذين قرأوا بعناية من البداية إلى النهاية - أنت القراء المفضلين لدي.