سؤال

لدي نموذج مجال يحتوي على مفهوم المحرر والمشروع.

يمتلك المحرر عددًا من المشاريع، ولا يحتوي المشروع على مالك محرر فحسب، بل يحتوي أيضًا على عدد من أعضاء المحرر.لذلك، لدى المحرر أيضًا عدد من المشاريع "المنضمة".

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

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

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

وبدلاً من ذلك، إذا قمت بتقسيم المجموعة وكان لدي مستودع محرر ومستودع مشروع، فكيف يمكنني التعامل مع المعاملة عبر الاثنين، كما هو الحال عند إضافة مشروع جديد إلى محرر؟على سبيل المثال:

Editor e = new Editor("Editor Name");
editorRepository.Add(e);

Project p = e.CreateProject("Project Name");
projectRepository.Add(p);    // These two lines
editorRepository.Save(e);    // should be atomic

هل أسيء تفسير القصد من نمط المستودع؟

هل كانت مفيدة؟

المحلول

هل أسيء تفسير القصد من نمط المستودع؟

سأقول "نعم"، لكن اعلم أنني وكل شخص عملت معه طلب نفس الشيء لنفس السبب... "أنت لا تفكر في البعد الرابع يا مارتي".

دعونا نبسط الأمر قليلًا ونلتزم بالمنشئات بدلاً من إنشاء الأساليب أولاً:

Editor e = new Editor("Editor Name");
e = editorRepository.Add(e);

Project p = new Project("Project Name", e);
p = projectRepository.Add(p);

أدناه، يقوم مستودع مشروعك دائمًا بتخزين مالك صالح (p.EditorId) في بيانات المشروع بمجرد إنشائه، وبغض النظر عن كيفية إعادة تعبئة مشاريع المحرر، فستكون هناك.هذا هو السبب في أنه من الممارسات الجيدة وضع جميع الخصائص المطلوبة في المُنشئين.إذا كنت لا ترغب في تمرير الكائن بأكمله، فقط e.Id سوف تفعل.

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

الآن، فيما يتعلق بكيفية إعادة نشر مشاريع المحرر حسب الطلب، لديك خياران اعتمادًا على ما تسعى إليه.يقول المستودع المستقيم أنك تريد:

IEnumerable<Project> list = projectRepository.GetAllProjects()
                                .Where(x => x.editorId == e.Id);

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

التالي هو طبقة المحول لتطبيقك، مع مصدر مشترك للمستودعات (StaticServiceWrapper) وإما نوع من كائن EditorAdapter (أو Aggregate أو أي شيء تسميه) أو يمكنك الآن المزج بين طرق الامتداد التي يمكنها التحدث إلى أي وجميع المستودعات الضرورية بطلاقة.لم أفعل ذلك بالضبط بهذه الطريقة في نظام الإنتاج، ولكن لأعرض لك مثالا موجزا:

public static class Aggregators
{
    // one to one, easy
    public static Editor GetOwner(this Project p)
    {
        return StaticServiceWrapper.editorRep.GetEditorById(p.editorId);
    }

    // one to many, medium
    public static IEnumerable<Project> GetProjects(this Editor e) 
    { 
        return StaticServiceWrapper.projectRep.GetAllProjects()
                .Where(x => x.editorId == e.Id);
    }

    // many to many, harder
    public static IEnumerable<Editor> GetMembers(this Project p)
    {
        var list = StaticServiceWrapper.projectMemberMap.GetAllMemberMaps()
                        .Where(x => x.projectId == p.projectId);

        foreach ( var item in list )
            yield return StaticServiceWrapper.editorRep.GetEditorById(item.editorId);
    }
}

بشكل أساسي، بمجرد الانتهاء من GetAll وGetById وAdd وUpdate وRemove Object Repository، يجب عليك ترك الارتباطات بمفردها والانتقال إلى أعلى التسلسل الهرمي للكائن/الطبقة إلى الأجزاء الممتعة مثل المحولات وذاكرة التخزين المؤقت ومنطق الأعمال ("يا بلدي!").

نصائح أخرى

وماذا عن مسؤوليات تقسيم إلى EditorOwner وEditorMember؟

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

وهذه الكائنات المجال قد تتعلق أيضا للمستخدمين، ولكن ذلك سيكون في سياق آخر.

هل ان الامور المساعدة، أو مجرد جعلها أكثر تعقيدا؟

وهذا يعتمد على احتياجات التطبيق الخاص بك. إذا كان هذا هو مشكلة كبيرة لتحميل جميع مشاريع لمحرر معين، ثم حاول نمط تحميل كسول مثل <وأ href = "http://en.wikipedia.org/wiki/Lazy_loading#Virtual_proxy" يختلط = "نوفولو noreferrer "> وكيل الظاهري .

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

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

وهنا لديك 2 علاقات مختلفة، واحدة للملكية واحدة للحصول على العضوية.

والعلاقة ملكية بسيطة واحدة إلى العديد (مالك واحد لكل مشروع). العلاقة العضوية عديدة لكثير من (كثير من المحررين من المشروع، العديد من المشاريع من قبل المحرر).

وأنت يمكن أن توفر خاصية المالك على الطبقة مشروع، وتوفير وسيلة على ProjectRepository للحصول على كل المشاريع المملوكة من قبل محرر معين.

لالعلاقة عديدة، توفر خاصية الأعضاء على الطبقة مشروع، وأسلوب على ProjectRepository للحصول على كل المشاريع التي تحتوي على محرر محدد عضوا.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top