إشعارات البريد الإلكتروني - في كائن المجال أو خدمة؟

StackOverflow https://stackoverflow.com/questions/928533

سؤال

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

سيناريو:

لنفترض أنه يتم تطوير ميزة جديدة ل Stackoverflow التي ترسل إشعارا بالبريد الإلكتروني إلى مالك السؤال كلما تلقي سؤاله 10 upvotes.

نموذج كائن المجال هو شيء مثل هذا:

public class Question
{
    string Question { get; set; }
    IList<Votes> Upvotes { get; set; }
    User Owner { get; set; }

    public void AddUpvote(Vote upvote)
    {
        Upvotes.Add(upvote);
    }
}

التطبيقات المحتملة:

  1. يتغيرون AddUpvote() لاتخاذ IEmailerService المعلمة وأداء المنطق داخل AddUpvote() طريقة.

    public void AddUpvote(Vote upvote, IEmailerService emailer)
    {
        Upvotes.Add(upvote);
        if ( Upvotes.Count == 10 )
        {
            emailer.Send(Owner.EmailAddr);
        }
    }
    
  2. كشف هذه الحالة في الداخل AddUpvote() و لدي AddUpvote() حل IEMAILSERVICE من حاوية IOC (بدلا من تمرير IEMailerservice كمعلمة).

  3. كشف هذه الحالة في كائن الخدمة الخارجية الذي يستدعي question.AddUpvote().

    public void UpvoteClickHandler(Question question)
    {
        question.AddUpvote(new Upvote());
        if ( question.Upvotes.Count == 10 )
        {
            _emailer.Send(question.Owner.EmailAddr);
        }
    }
    
  4. حل أفضل هنا!

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

المحلول

أنت حقا لا ترغب في مزج هذين معا لأنهم لديهم مخاوف منفصلة. دع السؤال يهتم بالأسئلة ورعاية خدمة الرسائل حول ما يجب القيام به عندما يضرب التصويت 10 أو 20 أو 100 أو ...

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

public class Question
{
    public string Description { get; set; }
    public Int32 Votes { get; set; }
    public User Owner { get; set; }

    public event EventHandler<QuestionEventArgs> OnUpvote;

    private void RaiseUpvoteEvent(QuestionEventArgs e)
    {
        var handler = OnUpvote;
        if (handler != null) handler(this, e);
    }

    public void Upvote()
    {
        Votes += 1;

        RaiseUpvoteEvent(new QuestionEventArgs(this));
    }
}

public class MessageService
{
    private Question _question;

    public MessageService(Question q)
    {
        _question = q;

        q.OnUpvote += (OnUpvote);
    }

    private void OnUpvote(object sender, QuestionEventArgs e)
    {
        if(e.Question.Votes > 10)
            SendMessage(e.Question.Owner);
    }
}

public class QuestionEventArgs: EventArgs
{
    public Question Question { get; set; }

    public QuestionEventArgs(Question q)
    {
        Question = q;
    }
}

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

نصائح أخرى

كلا الخيارين 1) و 2) القفز باعتباره المكان الخطأ لإرسال بريد إلكتروني. يجب ألا يعرف مثيل سؤال هذين الأمرين:

  1. لا ينبغي أن يعرف عن السياسة، أي متى يتم إرسال بريد إلكتروني.
  2. لا ينبغي أن يعرف عن ميكانيكا الإخطار بسياسة، أي خدمة البريد الإلكتروني.

أعلم أن هذه مسألة ذوق، لكنك تربط في السؤال عن كثب مع كل من السياسة وكذلك الآلية لإرسال بريد إلكتروني. سيكون من الصعب حقا نقل فئة الأسئلة إلى مشروع آخر (مثل ServerFault، وهو موقع أخت StackoverFlow على سبيل المثال)

أنا مهتم بهذا السؤال، لأنني أخلق نظام إعلام لمكتب مساعدة أقوم بتشغيله. هذا ما فعلته في نظامي:

قم بإنشاء إخفاع (أساسا، نقل تماما قلق الإخطارات إلى فئة منفصلة).

public Class NotificationManager
{
    public void NotificationManager(NotificationPolicy policy, IEmailService emailer)
    {
    }
}

ثم لقد فعلت شيئا على غرار هذا (يحتوي Upvoteclickhandler على اعتماد على مثيل إعلام):

public void UpvoteClickHandler(Question question)
{
    question.AddUpvote(new Upvote());
    _notificationManager.Notify(Trigger.UpvoteAdded, question);
}

يتم إخبار كل ما upvoteclickhandler بإخطار الرفاه الذي تمت إضافته في التصويت على السؤال والسماح بإخطار المحدد تحديد ما إذا كان ينبغي إرسال بريد إلكتروني وكيف ينبغي إرسال بريد إلكتروني.

تعتمد الجواب على النهج الأساسي الخاص بك في تصميم التطبيق والكائن. (تحرير هنا) ما تنظر إليه كسماتك الأكثر أهمية للنظام. يبدو أن لديك بيانات وأسئلة وقواعد أعمالها، وأصوات الأصوات. عدم السؤال كائنات على الإطلاق. لذلك يجب عليك التعامل مع بياناتك كبيانات وتسمح لأدوات البيانات بالعمل عليها، من خلال عدم خلط السلوك فيها. سيكون تصميم الكائن التقليدي جميع السلوكيات والبيانات في الكائن، لذلك سوف ينتمي إرسال البريد الإلكتروني إلى الكائن. (الخيار 1 و 2) أعتقد أن هذا هو الصندوق الأسود، أو نهج الكائن الموجود في الذات. الممارسات الحديثة، كما جئت للتعلم، لديها كائنات كحاملات بيانات بسيطة. والذي المقصود أن يتم نقله حولها، استمرت، وتحولت ولديها الأشياء بها. ربما تعيش أكثر قليلا من الهياكل في C. السلوك يأتي من الخدمات والتحولات التي يتم تطبيقها على الكائنات البسيطة.

أهلا بكم،

في رأيي "يرسل إشعارا بالبريد الإلكتروني إلى مالك السؤال كلما تلقي سؤاله / الخاص به 10 upvotes" هو منطق المجال، لذلك يجب أن يكون في كائن المجال، من أجل تجنب مجال الفقراء.

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

لذلك أعتقد أن الخيار 1 ليس خطأ تماما. ضع في اعتبارك أنه يمكنك دائما اختبار كائنك عن طريق تمرير تطبيق وهمية ل IEMailerservice.

أنا في حاجة إليها،

ستيفانو

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