Настройки на ниво приложение в DDD?

Просто исках да разбера мислите на групите за това как да се справят с подробностите за конфигурацията на обектите.

Това, за което имам предвид конкретно, са настройките на високо ниво, които може да се променят от администратора. нещо, което може да съхранявате в приложението или web.config в крайна сметка, но от гледна точка на DDD трябва да се зададе изрично някъде в обектите.

В името на спора, нека вземем за пример уеб базирана CMS или приложение за блог.

Даден обект на запис в блог има произволен брой настройки на екземпляри като автор, съдържание и т.н.

Но също така може да искате да зададете (например) описание или ключови думи по подразбиране, с които да започват всички записи в сайта, ако не са променени от автора. Разбира се, можете просто да направите тези константи в класа, но тогава собственикът на сайта не може да промени настройките по подразбиране.

Така че мислите ми са следните:

1) използвайте (статични) свойства на ниво клас, за да представите тези настройки и след това ги задайте, когато приложението се стартира, като ги зададете от DB или от web.config.

or

2) използвайте отделен обект за съхраняване на настройките, евентуално речник, или го използвайте директно, или го накарайте да бъде член на класа Entry

Какво ви се струва най-лесно/гъвкаво? Притесненията ми относно първото са, че не ми се струва много свързано (ако в крайна сметка искам да добавя още функции), тъй като промяната на методите на класа на обекта ще ме накара да променя и самото приложение (което се чувства като нарушение на OCP ). Вторият се усеща като по-тежък, особено ако след това трябва да изхвърля или анализирам стойности от речник.


person Paul    schedule 23.11.2009    source източник


Отговори (1)


Бих казал, че дали дадена стойност може да се конфигурира или не е без значение от гледна точка на модела на домейн - важното е, че е дефинирана външно.

Да кажем, че имате клас, който трябва да има име. Ако името винаги се изисква, то трябва да бъде капсулирано като инвариант, независимо от източника на стойността. Ето пример за C#:

public class MyClass
{
    private string name;

    public MyClass(string name)
    {
        if(name == null)
        {
            throw new ArgumentNullException("name");
        }

        this.name = name;
    }

    public string Name
    {
        get { return this.name; }
        set
        {
            if(value == null)
            {
                throw new ArgumentNullException("name");
            }
            this.name = value;
        }
    }
}

Клас като този ефективно защитава инварианта: Името не трябва да е нула. Моделите на домейни трябва да капсулират инварианти като този, без да имат предвид кой потребител ще ги използва - в противен случай те няма да постигнат целта на Supple Design.

Но вие попитахте за стойностите по подразбиране. Ако имате добра стойност по подразбиране за Име, тогава как да съобщите тази стойност по подразбиране на MyClass.

Това е мястото, където фабриките идват на помощ. Вие просто отделяте изграждането на вашите обекти от тяхното изпълнение. Това често е добра идея във всеки случай. Дали ще изберете изпълнение на Abstract Factory или Builder е по-малко важно, но Abstract Factory е добър избор по подразбиране.

В случая с MyClass можем да дефинираме интерфейса IMyClassFactory:

public interface IMyClassFactory
{
    MyClass Create();
}

Сега можете да дефинирате реализация, която изтегля името от конфигурационен файл:

public ConfigurationBasedMyClassFactory : IMyClassFactory
{
    public MyClass Create()
    {
        var name = ConfigurationManager.AppSettings["MyName"];
        return new MyClass(name);
    }
}

Уверете се, че кодът, който се нуждае от екземпляри на MyClass, използва IMyClassFactory, за да го създаде, вместо да го създава ръчно.

person Mark Seemann    schedule 24.11.2009
comment
Стойностите по подразбиране бяха пример, може би лош; Запознат съм с Factory модела. Друг пример би бил нещо, което трябва да се прилага за всички екземпляри на клас, но което може да се промени на ниво приложение. Може би нещо като броя на екземплярите за зареждане в списък (винаги) или правило за това дали да се показват или не коментари. Това наистина не ми се струват стойности на ниво екземпляр или нещо не разбирам правилно? - person Paul; 24.11.2009
comment
Винаги можете да капсулирате една или повече свързани стойности в тип и след това да инжектирате екземпляр от този тип във всички потребители. От съображения за ефективност (или други причини) можете да изберете да инжектирате единичен, споделен екземпляр, докато потребителите нямат представа за живота на инжектирания обект. Това ще остави възможностите ви отворени. - person Mark Seemann; 24.11.2009
comment
@MarkSeemann Какво ще стане, ако искам да имам конфигурируема логика в моя богат модел на домейн? Като проста настройка bool например за определяне на метода на изчисление. Трябва ли да предам този bool и в конструктора? - person Konrad; 13.09.2018
comment
@Konrad Може би. Както обяснява Clean Code, булевите флагове рядко са индикации за добър дизайн. Често полиморфизмът може да е за предпочитане, но в крайна сметка дизайнът на софтуера е свързан с претегляне на множество проблеми, така че не може да има окончателни отговори без задълбочени познания за конкретни контексти. - person Mark Seemann; 13.09.2018
comment
@MarkSeemann няма особено значение дали е булево или нещо друго, но да кажем, че е някаква настройка, която диктува как се изчисляват цените. Мисля, че трябва да има някакъв общ отговор на това. - person Konrad; 13.09.2018
comment
@Konrad Ако обект на домейн зависи от нещо друго, било то булева стойност или нещо по-сложно, не е ли част от инвариантите на обекта на домейн? По-конкретно, не е ли предварително условие? Ако е така, ако не го подадете през конструктора, тогава как ще гарантирате този инвариант? - person Mark Seemann; 13.09.2018
comment
@MarkSeemann Статична конфигурационна променлива? Но трябва по някакъв начин да гарантирам безопасността на нишката. В моята система искам глобална настройка, която диктува как да се третират конкретни изчисления. Тези изчисления се извършват вътре в модели на домейн. И тази настройка не е специфична за този 1 модел на домейн, а за цялото приложение или всички модели на домейн, които се нуждаят от тези изчисления. - person Konrad; 13.09.2018
comment
Не мога просто да инжектирам конфигурация в моите модели на домейн, защото не ми се струва правилно. Но имам нужда от достъп до него. Мисля, че едно решение би било да добавя параметър за моя метод, който извършва тези изчисления, за да избера типа изчисление. Така че би било като CalculateSomething(CalculationMethod calculationMethod), но тогава ще трябва да го прочета и да го подавам всеки път ръчно. - person Konrad; 13.09.2018
comment
Така че това, което исках да направя, е да настроя този CalculationMethod само 1 път, без да предавам нищо на моя метод или модел на домейн. - person Konrad; 13.09.2018
comment
@Konrad AFAICT, тук има повече от едно притеснение. Това е твърде сложен въпрос, за да го разгледаме в тези коментари, но ако зададете нов въпрос, ще се радвам да погледна, ако ми изпратите ping с връзката. - person Mark Seemann; 14.09.2018
comment
@MarkSeemann stackoverflow. com/questions/52327508/ - person Konrad; 14.09.2018