سؤال

كنت أنظر إلى الاختلافات بين poco و dto (يبدو أن Poco's هي DTO مع السلوك (الأساليب؟)) واتصل هذه المقالة بواسطة مارتن فاولر على نموذج النطاق الفقراء.

من خلال عدم الفهم، أعتقد أنني قد أنشأت واحدة من نماذج النماذج هذه الفقراء.

في أحد التطبيقات الخاصة بي، لدي كيانات مجال الأعمال التجارية المحددة في DLL "DTO". لديهم الكثير من العقارات مع Getter's و Studter وغيرها الكثير. رمز منطق عملي (ملء وحساب) في "BLL" DLL "آخر ورمز الوصول إلى البيانات في DLL" DAL ". "أفضل الممارسات" اعتقدت.

لذلك عادة ما أقوم بإنشاء DTO مثل:

dto.BusinessObject bo = new dto.BusinessObject(...)

وتمريرها إلى طبقة Bll مثل ذلك:

bll.BusinessObject.Populate(bo);

الذي بدوره، يؤدي بعض المنطق ويمره إلى طبقة DAL مثل ذلك:

dal.BusinessObject.Populate(bo);

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

poco.BusinessObject bo = new poco.BusinessObject(...)
bo.Populate();

بمعنى آخر. أنا أدعو الطريقة الموجودة على الكائن بدلا من اجتياز الكائن إلى الطريقة.

سؤالي - كيف يمكنني القيام بذلك ولا يزال يحتفظ بطبقات "أفضل الممارسات" للمخاوف (DLL المنفصلة وغيرها ...). لا يدعو الطريقة الموجودة على الكائن يعني أنه يجب تعريف الطريقة في الكائن؟

الرجاء مساعدة ارتباكي.

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

المحلول

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

حيث يأتي نموذج مجال الفقر الدم في اللعب هو عندما تفعل أشياء مثل هذا:

IAirplaneService service = ...;
Airplane plane = ...;
service.FlyAirplaneToAirport(plane, "IAD");

في هذه الحالة، إدارة دولة الطائرة (سواء كانت تسافر، حيث يكون ذلك، ما هو وقت المغادرة / المطار، ما هو وقت الوصول / المطار، ما هي خطة الطيران، إلخ) تفويض إلى شيء خارج الطائرة .. . مثيل Airplaneservice.

طريقة بوكو لتنفيذ هذا سيكون لتصميم واجهةك بهذه الطريقة:

Airplane plane = ...;
plane.FlyToAirport("IAD");

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

نصائح أخرى

أعتقد أن أفضل طريقة لتوضيح هذا بحكم التعريف:

DTO: كائنات نقل البيانات:

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

public class ClientDTO
{
    public long Id {get;set;}
    public string Name {get;set;}
}

بو: كائنات الأعمال:

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

public class Client
{
    private long _id;
    public long Id 
    { 
        get { return _id; }
        protected set { _id = value; } 
    }
    protected Client() { }
    public Client(string name)
    {
        this.Name = name;    
    }
    private string _name;
    public string Name
    {
        get { return _name; }
        set 
        {   // Notice that there is business logic inside (name existence checking)
            // Persistence is isolated through the IClientDAO interface and a factory
            IClientDAO clientDAO = DAOFactory.Instance.Get<IClientDAO>();
            if (clientDAO.ExistsClientByName(value))
            {
                throw new ApplicationException("Another client with same name exists.");
            }
            _name = value;
        }
    }
    public void CheckIfCanBeRemoved()
    {
        // Check if there are sales associated to client
        if ( DAOFactory.Instance.GetDAO<ISaleDAO>().ExistsSalesFor(this) )
        {
            string msg = "Client can not be removed, there are sales associated to him/her.";
            throw new ApplicationException(msg);
        }
    }
}

خدمة أو فئة التطبيقتمثل هذه الفصول التفاعل بين المستخدم والنظام وسوف تستخدم كلا من العملاء والعميل.

public class ClientRegistration
{
    public void Insert(ClientDTO dto)
    {
        Client client = new Client(dto.Id,dto.Name); /// <-- Business logic inside the constructor
        DAOFactory.Instance.Save(client);        
    }
    public void Modify(ClientDTO dto)
    {
        Client client = DAOFactory.Instance.Get<Client>(dto.Id);
        client.Name = dto.Name;  // <--- Business logic inside the Name property
        DAOFactory.Instance.Save(client);
    }
    public void Remove(ClientDTO dto)
    {
        Client client = DAOFactory.Instance.Get<Client>(dto.Id);
        client.CheckIfCanBeRemoved() // <--- Business logic here
        DAOFactory.Instance.Remove(client);
    }
    public ClientDTO Retrieve(string name)
    {
        Client client = DAOFactory.Instance.Get<IClientDAO>().FindByName(name);
        if (client == null) { throw new ApplicationException("Client not found."); }
        ClientDTO dto = new ClientDTO()
        {
            Id = client.Id,
            Name = client.Name
        }
    }
}

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

interface ISomeDomainObjectBehaviour
{
    SomeDomainObject Get(int Id);
    void Save(SomeDomainObject data);
    void Delete(int Id);
}

class SomeDomainObjectSqlBehaviour : ISomeDomainObjectBehaviour
{
    SomeDomainObject ISomeDomainObjectBehaviour.Get(int Id)
    {
        // code to get object from database
    }

    void ISomeDomainObjectBehaviour.Save(SomeDomainObject data)
    {
        // code to store object in database
    }

    void ISomeDomainObjectBehaviour.Delete(int Id)
    {
        // code to remove object from database
    }
}
class SomeDomainObject
{
    private ISomeDomainObjectBehaviour _behaviour = null;
    public SomeDomainObject(ISomeDomainObjectBehaviour behaviour)
    {

    }

    public int Id { get; set; }
    public string Name { get; set; }
    public int Size { get; set; }


    public void Save()
    {
        if (_behaviour != null)
        {
            _behaviour.Save(this);
        }
    }

    // add methods for getting, deleting, ...

}

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

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