حول الكيانات و DTO و ORM والحمل الكسول

نموذج وجوه المنحى هو المعيار لبرامج التطبيق. قواعد البيانات العلائقية - معيار لتخزين البيانات في برنامج التطبيق. نعم ، يمكنك الكتابة في Haskell وتخزين البيانات حصريًا في ClickHouse. ولكن عن التيار الرئيسي.

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

  1. قم بتنزيل كل شيء وسقط من ذاكرة / مهلة
  2. حدد صراحة التبعيات التي نريد تنزيلها وتلك التي لا تنتهك وتخالف مبدأ عدم السؤال
  3. قم بتحميل التبعيات ضمنيًا عند الطلب باستخدام Lazy Load واحصل على مشاكل في الأداء في مكان ما من الكود المدعو

أي نوع من الساق يجب أن تقطعه: اليسار أو اليمين؟

TLDR Lazy Load ليس سيئًا جدًا إذا تم استخدامه للكتابة فقط ولم يتم استخدامه عند القراءة. ولكن كل شيء ليس بهذه البساطة ، وهناك الكثير من الفروق الدقيقة.

مع مرور الوقت ، توصلت إلى استنتاج مفاده أن Lazy Load و / أو اعتماد الكيانات على تنفيذ ORM هو الشر الأقل تحت ظروف معينة.

في النظام الفرعي للقراءة ، قم دائمًا بقراءة DTO فقط


في 90٪ من الحالات ، تنشأ مشاكل Lazy Load بدقة عند القراءة. نحصل على قائمة الكيانات ، ونستعرضها ونفحصها ونبدأ في تحديد جميع البيانات اللازمة. نحصل على مجموعة من الاستعلامات إلى قاعدة البيانات. في هذه الحالة ، غالبًا ما يكون الشيء الوحيد الذي يجب القيام به هو الحصول على البيانات وتسلسلها وإرسالها مرة أخرى في شكل JSON. لماذا ، إذن ، تحميل الكيانات على الإطلاق؟ ليست هناك حاجة لإضافة هذه البيانات إلى متتبع التغيير UOW ، لقراءة الكيان بالكامل إلى جانب الحقول "الإضافية". بدلاً من ذلك ، يمكنك دائمًا كتابة إما Select أو ProjectTo . كسول الحمل غير مطلوب لأنه سيتم ترجمة رمز C # من Select إلى SQL وتنفيذها على جانب قاعدة البيانات.

ماذا لو لم يترجم منطقي إلى SQL؟


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

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

قد يكون التنفيذ على النحو التالي:

 public interface IHasProductPrice { decimal BasePrice { get; } decimal? SalePrice { get; } } public class Product: IHasProductPrice { // ... a lot of code public decimal BasePrice { get; protected set;} public decimal? SalePrice { get; protected set;} } public class ProductDto: IHasProductPrice { public decimal BasePrice { get; set;} public decimal? SalePrice { get; set;} } public static class ProductCalculator { public static void decimal Calculate(IEnumerable<IHasProductPrice> prices) } 

في النظام الفرعي للكتابة ، Lazy Load ليس مخيفًا جدًا


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

المجموعات المرتبطة في المجاميع


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

ماذا لو كان لا يزال هناك الآلاف من السجلات في المجموع؟


قم بتمرير DbContext إلى المُنشئ وقراءة البيانات الضرورية منه فقط في سياق العملية. نعم ، انتهك DIP. إما ذلك ، أو لا تستخدم الوحدة على الإطلاق في هذه الحالة.

عمليات جماعية


يعد استيراد ملف خط 10،000 هدفًا رائعًا لـ Lazy Load. هنا ، لجميع مشاكل النظام الفرعي للقراءة ، يتم إضافة الفرامل ChangeTracker أيضا. للتسجيل الشامل ، تحتاج إلى استخدام أدوات منفصلة. أفضل امتدادات الدُفعات ، لأنه مرة أخرى يمكنك الاستغناء عن إنشاء كيانات للحالات الشديدة بشكل خاص ، هناك إجراءات قديمة مخزنة جيدة وحتى أدوات DBMS خاصة .

اختراق الحياة


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

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


All Articles