كتاب طهي المطور: وصفات التصميم المستندة إلى المجال (الجزء 2 ، الهيكل والتفاعل)

رأس ددد


مقدمة


في المقالة الأولى ، سلطنا الضوء على نطاق الممارسات المشار إليها ، والتي يمكن تطبيق المشاريع عليها ، والتي لا ينبغي لها.


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


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


DDD


أذكر التعريف السابق:


التصميم المستند إلى المجال (DDD) هو نهج لتطوير البرامج من أجل تلبية الاحتياجات بشكل شامل ، من خلال ربط التنفيذ مع نماذج الأعمال الرئيسية التي يتم تطويرها باستمرار بإحكام.

الكتاب المرجعي الذي يصف ممارسة بناء الأنظمة المعقدة هو Dedign ( المجال الأزرق الكبير) لـ Eric Evans. إذا قرأت أي مقال مراجعة حول هذا الموضوع ، فأنت تعرفه بالفعل. في الوقت الذي تستخدم فيه DDD في الممارسة العملية ، سيكون عليك قراءته. ليس هذا أسهل كتاب للقراءة:


المصدر الأساسي لـ DDD هو كتاب إريك إيفانز. إنها ليست أسهل قراءة في أدبيات البرمجيات ، لكنها واحدة من تلك الكتب التي تسدد بشكل كبير استثمارًا كبيرًا.

مارتن فاولر: 15 يناير 2014

بالتمرير خلال محتويات الكتاب ، يبدو أنك غير منظم تمامًا. لكن الخريطة ستساعدنا.
خريطة DDD


على الخريطة هي تلك الممارسات التي سننظر فيها اليوم.


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


  • زيادة الإنتاجية.
  • كتابة رمز مفهومة.
  • التوسع على مستوى تطوير البرمجيات.

لغة واحدة


نادرًا ما يؤدي تطوير البرامج إلى إنشاء شيء جديد ، كقاعدة عامة ، هذه محاكاة لشيء موجود.


النموذج هو تمثيل لكائن حقيقي ، يتضمن فقط الخصائص والوظائف الضرورية.

لا يمكننا إنشاء منتج برمجي يغطي مجال الموضوع بالكامل. من الممكن إعادة إنتاج هذا الجزء فقط الذي سيعيد إنتاج الوظائف الضرورية.


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


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


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


كيفية الاحتفاظ بوثائق المشروع


  1. أي اتصال بين الأعمال والتطوير يجب أن يحسن نموذجك.
  2. بعد الاجتماع ، سجل النتيجة في شكل توثيق (Scrum artifact) ، وأظهر هذه الوثائق لجميع المشاركين في عملية التطوير.
  3. استخدم لغة واحدة في الوثائق.
  4. الأهم: لا تضيعوا الوقت في التوثيق. لا يزال عليك كتابة الرمز ، وستتم إعادة كتابة الوثائق عدة مرات ، وإنفاق الموارد باهظ الثمن. بدلاً من العبث مع تطبيق مخطط UML لفترة طويلة ، استخدم منديل وقلم وكاميرا على هاتفك.
  5. يتطلب التوثيق الانضباط ، ولا يمكنك كتابته من وقت لآخر.
  6. افصل الوثائق:
    • التعليقات في الكود - وصف اللحظات غير المفهومة مباشرة في الكود ، اترك #ODO: (قم بإزالته عند دمج الكود في الكود). عبر عن رأيك في التعليقات ، على سبيل المثال ، يجب عليك استخدام عكاز واحد أو آخر عند العمل مع رمز legacy.
    • يجب أن تحتوي التعليقات على مشروع README.md في الدليل الجذر لمشروعك على معلومات فنية: كيفية بدء المشروع ، وكيفية تشغيل الاختبارات ، وما إلى ذلك. من الجيد أيضًا الحصول على خريطة حيث لديك جميع المشاريع والخوادم التي تعمل عليها. سجل بشكل منفصل جميع الاتفاقات المقبولة.
    • والأهم من ذلك قاعدة المعرفة. مجموعة من المستندات التي تصف العمليات التجارية ، وهذا هو جزء من المستندات المتاحة لك وللعمل.
  7. الخطأ الرئيسي لمن يكتبون الوثائق هو التكرار. لا تحاول تغطية كل شيء وكل شيء ، فقط نقل المعنى العام. يجب أن تكون الوثائق مكملة لمشروعك ، ولكن لا تحل محلها بأي شكل من الأشكال. لا تكتب جميع المصطلحات الغامضة فقط. إذا أخذ التعريف أكثر من جملتين ، فهو تعريف ضعيف.

مثال التوثيق:


 #         . # :  : -    - email -  ## : ###        ,     email  ,    1  (      email  ). ###           .          email . ###  email  email     .    ,    email.   . ###       ,     ,    .   . ###      email,    ,       .   2 . ###                  .    ,     ,             . 

لاحظ أننا في هذا المثال لم نحدد قاموسًا صريحًا ، ومع ذلك فقد أصلحنا مفهوم المستخدم والتفويض والتسجيل . لن تستغرق كتابة هذه الوثائق الخبير أكثر من 20 دقيقة.


بالنسبة لشخص غير خبير في مجال الموضوع ، يُنظر إلى عملية كتابة الوثائق على أنها أمر معقد. من الضروري فصل جمع المعرفة وسجل المعرفة المجمعة. != + .


قال الرابع: "ما تسمونه الكون ، هو في الواقع ، تراكم عوالم ، مثل جلد القوس ، فوق بعضها البعض ويتم فصلها تدريجياً عن بعضها البعض".

- ذكر بوضوح غير عادي! - معجب بالبدريين. - واضح بشكل مثير للدهشة! "اعتقدوا أنهم فهموا الفيلسوف ، لأنهم يعرفون جيدًا ما هو البصل."

قصة أبردين ، كريستوف مارتن ويلاند

سياقات ومجالات محدودة


تخيل أننا تصرفنا كمصمم للشركات الناشئة التقدمية. كلنا نحب البيتزا المبردة ، ونشتمها بالسعاة ونملأ الاستمارات على الموقع لساعات. لذلك ، توصلنا إلى شركة ناشئة رائعة "أربع سلحفاة وفأر واحد":


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

دعونا نتذكر الوثائق التي وصفناها في الفصل السابق. هناك ، في قاموسنا المفرد ، تم استخدام مصطلح التسجيل . لكن في هذا المشروع لدينا العديد منهم:


  • تسجيل العملاء
  • تسجيل بيتزا
  • تسجيل البريد السريع
  • تسجيل الطلب

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


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


المجال (المجال) - تمثيل هيكل الأعمال الحقيقي الذي يحل مشكلة معينة.

على سبيل المثال: النظام اللوجستي ، نظام الدفع ، نظام التفويض ، نظام إدارة الطلبات.


ينقسم المجال إلى نطاقات فرعية ، والتي تصف الهياكل الأصغر ، على سبيل المثال: سلة أوامر ، ونظام لبناء المسارات.


كل مجال له مساحة محدودة من المسؤولية - وظائف محدودة.


السياق المحدود - مجموعة من قيود المجال التي تساعد المجال على التركيز على مهمة واحدة فقط للحصول على أفضل حل لها.

أحب أن أعرض هذا المصطلح على أنه تجريد. المجال هو دائرة. السياق المقيد هو دائرة.


سياق المجال


يتم تخصيص النواة حتى في مصطلحات DDD.


المجال (المجال الأساسي) - المجال الأكثر أهمية الذي يميز عملك.

لذا فإن مجالات مشروع "أربع سلحفاة وفأر واحد":


العمل مع مطعم بيتزا (Pizzarias)


السياق : b2b كل ما يتعلق بمطاعم البيتزا


المجالات الفرعية :


  • تسجيل بيتزا جديدة
  • مضيفا تشكيلة
  • تحديث حالة توفر المنتج

العمل مع العميل (عملاء)


السياق : b2c ، كل ما يتعلق بالعمل مع عملاء البيتزا


المجالات الفرعية :


  • عرض تشكيلة
  • مواد إعلامية

العمل مع شركات النقل (نظام التوصيل)


السياق : b2e ، كل ما يتعلق بالعمل مع شركات النقل


المجالات الفرعية :


  • تسجيل البريد السريع
  • تعيين المهام
  • تسجيل طلبات سحب الأموال التي حصل عليها الساعي.

نظام الطلب


السياق : Kernel. يتيح لك تنسيق جميع المجالات الفردية ، مما يوفر دورة كاملة من استلام الطلب إلى توصيل البيتزا إلى المستخدم. إنها ليست مؤدية ، لكنها تلعب دور الموصل.


المجالات الفرعية :


  • قبول الطلب
  • تنفيذ الأمر
  • تتبع حالة الطلب

نظام التسوية (الفواتير)


السياق : يحتوي على جميع المعاملات المالية. يوفر التفاعل مع مركز المعالجة.


المجالات الفرعية :


  • قبول المال للطلبات
  • إعطاء المال للسعاة للعمل المنجز

نظام الإحصاء


السياق : جمع ومعالجة (عدم إصدار) المعلومات التحليلية.


المجالات الفرعية :


  • إحصاءات عن الأموال
  • إحصاءات التطبيق

نظام الإدارة (لوحة الإدارة)


السياق : إصدار المعلومات التحليلية. مجموعة أدوات قرارات الإدارة.


  • تحليلات على أساس الإحصاءات التي تم جمعها
  • الاعتدال المسبق للمدفوعات للسعاة

استنادًا إلى المجالات ، فلنرسمها.


خريطة المجال (خريطة السياق) هي أداة رسومية تسمح لك بوصف العلاقات بين المجالات الفردية.

خريطة السياق


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


أهم شيء على الخريطة هو أننا نرى روابط بين المجالات. يتناسب هذا الهيكل بشكل جيد للغاية مع بنية الخدمات الصغيرة:


المبدأ الرئيسي لبنية الخدمات الصغيرة: ضعف الاتصال والالتصاق القوي.

تم إعطاء هذا المبدأ في كتاب Sam Newman - إنشاء Microservices ، هذا هو الكتاب الثاني الذي يجب عليك قراءته لبدء الاستخدام العملي للمناهج الموضحة في هذه المقالة. المعنى: يجب أن تقترن المجالات بشكل فضفاض ، ولكن ترتبط ارتباطًا وثيقًا داخليًا.


تؤخذ ترجمة هذه المصطلحات من الترجمة الروسية الرسمية ، وربما تعكس بشكل سيئ المعنى المرسل. في المصطلحات الأصلية هي: اقتران منخفض (الاتصال ، المشاركة ، القبضة ، الاقتران) ، التماسك العالي (الاتصال ، القوة).


ممارسة تنفيذ مشاركة المجال


أود مشاركة تجربتي الشخصية - مجموعة من القرارات المستنيرة. لا أحثك ​​على استخدام هذه الحلول. لكنها قد تكون خيارًا جيدًا إذا كنت لا تعرف من أين تبدأ. مع الخبرة الشخصية ، سيتم تخصيص الأدوات بشكل أكبر لاحتياجاتك.


المبادئ الرئيسية التي وجهتنا:


  • بساطة الحل. اجعل الأشياء المعقدة بسيطة وليست معقدة.
  • البراغماتية تحتاج دائمًا إلى النظر إلى الموقف ، وفي حالة عدم وجود حل موجود ، قم بتطوير حل جديد. حاول أن تصف كل شيء ، لكن تجنب العقيدة.
  • الرمز! = التوثيق. الرمز هو تعليمات للجهاز ، والتوثيق هو تعليمات للناس. لا حاجة إلى إرباكهم وإعطاء واحد تلو الآخر.
  • صلب

كيفية تنفيذ المجالات؟


من الملائم للغاية تحديد المجالات كخدمات مايكرو منفصلة.


Microservices هو تطبيق منفصل يطبق منطق مجال واحد.

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


كيفية تسليط الضوء على العلاقة بين المجالات؟


العلاقات بين المجالات هي دائما API. يمكن أن يكون RESTful json api ، gRPC ، AMPQ. في إطار هذه المقالة ، لن نقارن بروتوكولًا ببروتوكول آخر ونسلط الضوء على مزاياه وعيوبه ؛ لكل منها مجال التطبيق الخاص به. ولكن مع ذلك ، دعنا نتناول التوصيات العامة:


كن مرناً في اختيار بروتوكول جامد في توحيد تطبيقه.


اختر بروتوكولًا لكل زوج من المجالات بشكل فردي ، ولا تحاول استخدام http في كل مكان ، فقد تحتاج إلى قوائم انتظار غير متزامنة في مكان ما وستصبح مزايا AMPQ واضحة لك. لا تتجاهل هذه الفرصة لأن لديك RESTful في كل مكان.


من ناحية أخرى ، إذا كنت تقوم بتنفيذ RESTful json ، فاستخدم معيارًا واحدًا لهيكلة البيانات. يمكنك أن تستعد على سبيل المثال jsonapi أو openapi. إذا كانت الحلول الجاهزة لسبب ما لا تناسبك وتشعر أنه يمكنك تطوير المعيار الخاص بك ووصفه واستخدامه. ولكن استخدامها في كل مكان ، لا تولد معايير "حديقة الحيوان". إذا كنت بحاجة إلى التواصل مع نظام خارجي حيث لا يعرفون شيئًا عن معاييرك ، فاكتب محول خدمة صغيرة.


محول


كيفية تنفيذ المجالات الفرعية؟


كوحدات منفصلة داخل خدمة متناهية الصغر.


الوحدة النمطية هي تنفيذ نطاق فرعي ، عن طريق وضع المنطق في مساحة اسم منفصلة (مساحة الاسم) داخل خدمة مايكرو واحدة.

كيف يبدو كل هذا؟ دعونا نلقي نظرة على مثال. كما نتذكر ، لدينا نطاق نظام التسليم - يحتوي هذا النطاق على ثلاثة نطاقات فرعية:


  • تسجيل البريد السريع
  • قضية المهام (المهام)
  • تسجيل طلبات سحب الأموال التي حصل عليها الساعي (السحب)
  • التحقق من أن الخدمة الصغيرة الخاصة بك تعمل ، أداة مساعدة ، تقنية (healt_checker)

تخيل هذا كله في شكل هيكل مجلد:


 $ tree --dirsfirst delivery_system delivery_system ├── app/ │ ├── health_checker/ │ │ └── endpoints.rb │ ├── registrations/ │ │ ├── entities/ │ │ ├── forms/ │ │ ├── repositories/ │ │ ├── interactor/ │ │ ├── services/ │ │ ├── validations/ │ │ ├── endpoints.rb │ │ └── helpers.rb │ ├── tasks │ │ ├── entities/ │ │ ├── queries/ │ │ ├── repositories/ │ │ ├── endpoints.rb │ │ └── helpers.rb │ └── withdrawals │ ├── entities/ │ ├── forms/ │ ├── repositories/ │ ├── interactor/ │ ├── services/ │ ├── validations/ │ ├── endpoints.rb │ └── helpers.rb ├── config/ ├── db/ ├── docs/ ├── lib/ │ ├── schemas/ │ └── values/ ├── public ├── specs ├── config.ru ├── Gemfile ├── Gemfile.lock ├── Rakefile └── README.md 

يطبق كل مجلد في apps/ الدليل نطاقًا فرعيًا واحدًا أو آخر ، داخل كل مجال هناك أنماط مختلفة: entities forms services ، وما إلى ذلك. سننظر في كل من الأنماط المطبقة بالتفصيل في إحدى المقالات المستقبلية.


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


 module Withdrawal #   module Forms #  class Create end end end 

كيفية تنفيذ الاتصال بين المجالات الفرعية؟


دعونا نلقي نظرة على مثال محدد. لدينا حساب ساعي: Registrations::Entities::Account . يشير إلى النطاق الفرعي Registrations - نظرًا لأننا نعتبر هذا النطاق ليس كعملية تسجيل ، بل كجدول حساب ودفتر تسجيل ، كما هو موضح في وثائق أعمالنا.


لدينا عمليتان يتم من خلالهما الوصول إلى هذا الحساب.


  • انشاء حساب (تسجيل)
  • إنشاء طلب لسحب الأموال المكتسبة بواسطة ناقل (Wihtdrawal)

كما نرى هاتين العمليتين تنتمي إلى نطاقات فرعية مختلفة - التسجيل و Wihtdrawal.


 module Registrations module Serivices class CreateAccount def call account = Entities::Account.new end end end end module Withdrwals module Serivices class CreateOrder def call account = Registrations::Entities::Account.new end end end end 

في الحالة الأولى ، سيتم تنفيذ استدعاء للفصل من خلال استدعاء Entities::Account . وفي الحالة الثانية ، من خلال استدعاء صريح Registrations::Entities::Account . على سبيل المثال إذا حددنا نطاقًا فرعيًا بشكل صريح ، فإن الفئة تنتمي إلى نطاق فرعي آخر ، ولذا فإننا نشير بوضوح إلى الاتصال.


إذا لم يطبق الفصل بشكل صريح على أي من النطاقات الفرعية ، فمن المنطقي نقله إلى المجلد lib/ . كقاعدة ، هذه هي الفئات التي تطبق نمط 'ValueObject'. سندرس هذا النمط بمزيد من التفصيل في إحدى المقالات التالية.


التنفيذ من خلال النموذج.


على حد تعبير إيريك إيفانز:


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

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


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




مصادر الإلهام

Source: https://habr.com/ru/post/ar428209/


All Articles