Використання бізнес-об’єктів у перегляді моделей


11

Використовуючи бізнес-об'єкти для багаторазового використання, що вважається найкращою практикою при побудові моделей перегляду?

Ми використовуємо об'єкт, який ми називаємо Builderдля створення наших моделей перегляду. Один конструктор для кожної логічної одиниці переглядів (замовлення, користувачі тощо), де кожен блок може містити декілька різних моделей перегляду (замовлення містить підсумки, рядки замовлення тощо).

Будівельник може перетягувати дані через один або декілька стандартних бізнес-об'єктів, щоб створити модель перегляду.

Що вважається кращою практикою, коли мова йде про використання бізнес-об'єктів / моделей для перегляду моделей?

Підхід 1

Дозволити використання бізнес-об’єктів у моделі перегляду?

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary();
        obModel.Order = obOrder;

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public Some.Business.Logic.Order Order;
    //Other methods for additional logic based on the order
    //and other properties
}

Підхід 2

Візьміть лише необхідні дані з об’єктів бізнесу

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary()
        {
            OrderNum = obOrder.OrderNum,
            NumOrderLnes = obOrder.NumOrderLines,
        }

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public int OrderNum;
    public int NumOrderLines
    //Other methods for additional logic based on the order
    //and other properties
}

Я бачу переваги та недоліки обох, але мені цікаво, чи є прийнятий підхід? У підході 1 немає дублювання коду навколо моделей, але це створює залежність від логіки бізнесу. У підході 2 ви берете лише дані, необхідні для перегляду, але дублюєте код навколо моделей.

Відповіді:


12

Варіант 1 створює тісний зв'язок між доменною моделлю та поданням. Це суперечить дуже проблемним моделям перегляду, розробленим для вирішення.

Моделі представлення "причина зміни" - це якщо сам погляд змінюється. Вставляючи об’єкт доменної моделі в модель перегляду, ви вводите ще одну причину для зміни (наприклад, домен змінено). Це є чіткою ознакою порушення принципу єдиної відповідальності. Наявність двох або більше причин для зміни призводить до перегляду моделей, які потребують великого обслуговування - можливо, більше, ніж передбачені витрати на технічне обслуговування з копіювання в моделях домену / перегляду.

Я завжди виступаю за підхід 2. Часто буває так, що моделі перегляду можуть виглядати дуже схоже, навіть ідентично об’єктам доменної моделі, але різницею, як я вже згадував, є їх різні причини змін.


Чи правильно я вважаю, що під "причиною зміни" ви маєте на увазі зміну в сенсі обслуговування, а не зміну оновлення (наприклад, події ui)?
Енді Хант

@AndyBursh так, це правильно - див. Цю статтю , зокрема рядок "Роберт К. Мартін визначає відповідальність як причину зміни, і робить висновок, що клас або модуль повинен мати одну, і лише одну, причину для зміни".
MattDavey

Мені подобається ваша відповідь, але деякі думки ... Модель перегляду необов'язково змінюється лише тому, що модель змінюється. Тільки якщо ви прив'язували або використовували певну властивість, яка змінилася, це буде проблемою, оскільки ваша посилання стосується всього об’єкта. Наявність посилання на об’єкт домену полегшує внесення змін та збереження їх знову. Ваші способи збереження також залежать від об’єкта домену, тому вам доведеться перетворити модель перегляду назад або налаштувати свій бізнес-метод, щоб прийняти моделі перегляду, що теж не добре. Я все ще думаю, що №2 має найбільш сенс, але всього на два центи.
KingOfHypocrites

Якщо ви не можете мати об’єкти домену у вітчизняній машині, то як би ви представляли щось складніше, як масив замовлень?
Джефф

Це означає, що такі речі, як, скажімо, форматування часової позначки для відображення користувачем, повинні належати шару перегляду, а не доменному шару, а об’єкти рівня домену повинні повертати лише необроблені, неформатовані часові позначки об’єктам перегляду, і останні - те, що повинно містять логіку форматування?
The_Sympathizer

2

Варіант 1 є кращим, оскільки він дозволяє уникнути дублювання коду. Це воно.

Якщо модель домену істотно зміниться, майже впевнено, що погляд доведеться все-таки змінити. З варіантом 2 вам доведеться змінити модель перегляду І конструктор, а також сам вид. Така річ є абсолютною отрутою для подрібнення. ЯГНІ.

Сенс створення окремої моделі перегляду полягає в тому, щоб стан, який має значення лише для представлення даних (наприклад, яку вкладку зараз вибрано), зберігав окремо від бізнес-моделі. Але самі бізнес-дані слід використовувати повторно, а не дублювати.


YAGNI - секретний вбивця вирішення більшості проблем дизайну програмного забезпечення.
Мартін Блер

6
Вибачте, але це жахлива порада для всіх, крім самих тривіальних програм. Перегляд моделей не має стану. Вони є об'єктами передачі даних. Вибрана вкладка є частиною СТРУКТУРИ подання і НІЧОГО стосунку не має ДАНИХ в моделі перегляду, як ніколи. Технічне обслуговування не є кошмаром, якщо ви правильно структуруєте програму і використовуєте щось на зразок Automapper для гідратації моделей перегляду.
Люцифер Сем

"Якщо модель домену істотно зміниться, майже впевнено, що погляд доведеться все-таки змінити." - Домовились. Але що робити, коли у вас невелика зміна домену? Опція перша: кожна невелика зміна домену (навіть просто перейменування ресурсу) вимагає відповідної зміни у представленні. Це також абсолютна отрута для ремонту.
MattDavey

@MattDavey: якщо ви перейменовуєте властивість, то за допомогою окремої моделі перегляду ви також повинні змінити представлення (або будь-які карти між доменом та моделлю перегляду), і тепер у вас є два різних імені для однієї і тієї ж речі, що, безумовно, спричинить плутанину.
Майкл Боргвардт

@Lucifer Sam: очевидно, що у нас дуже різні поняття, що таке модель перегляду. Ваше звучить для мене дуже, дуже дивно, як ви описуєте додатки для мейнфреймів для тупих терміналів, але, звичайно, не сучасні веб-програми або товсті клієнтські програми.
Майкл Боргвардт

2

Принципи та мантри іноді цінні для керівного дизайну ... але ось моя практична відповідь:

Уявіть, що ваші моделі перегляду серіалізуються в JSON або XML. Якщо ви спробуєте і серіалізуєте свої доменні моделі, ви зіткнетеся з огидним безладом тексту і, швидше за все, зіткнетеся з проблемами з циркулярними посиланнями та іншими проблемами.

Мета моделі перегляду - не групувати доменні моделі разом, щоб представлення могло їх споживати. Натомість модель перегляду повинна бути повністю плоскою моделлю зору ... фактична річ, яку ви дивитесь на екрані. Ваша логіка перегляду повинна стосуватися лише структуризації даних, що є у моделі перегляду.

В ідеалі модель перегляду повинна майже повністю складатися з попередньо відформатованих рядків. Подумайте про це ... ви навіть не хочете дати або часу чи десятиці у своїй моделі перегляду, тому що тоді ви застрягли, роблячи логіку форматування у C #, Javascript, Objective-C тощо.


2
У мене ніколи не було проблем із серіалізацією моделей доменів. І перетворити все на рядки в моделі? Серйозно?
Майкл Боргвардт

3
@MichaelBorgwardt Так, саме такою має бути модель перегляду. Ви не хочете серіалізувати свої доменні моделі та надсилати їх всюди. Вся бізнес-логіка повинна безпечно залишатися вдома в одному місці. Однак огляди повинні бути гнучкими та мати можливість їх відображення на будь-якому пристрої, тому ви хочете повністю розділити СТРУКТУРУ, ДАНІ та СТІЛ.
Люцифер Сем

Вибачте, але це жахлива порада для будь-якої програми, періоду. Це призводить до перенапружених додатків, повних дублікатів коду, які є абсолютно протилежною гнучкості.
Майкл Боргвардт

1
@MichaelBorgwardt, це здається, що ви звикли працювати з анемічними моделями домену, де сутності трохи більше, ніж пакети з властивостями, які мало поведінки. У такому випадку так, модель DTO / View в основному буде дублікатом. Однак якщо у вас є багата модель домену зі складними взаємозв'язками, шар DTO / View-моделей стає необхідним, і вони будуть не настільки схожими на доменні сутності.
MattDavey

@MattDavey: Здається, що доменні моделі, з якими ви звикли працювати, - це не просто багаті, а справжні клептократи. Мені також не подобаються анемічні моделі, але вони все ще є моделями, і їх поведінку слід обмежувати лише представленням домену. Принцип єдиної відповідальності і все таке ...
Майкл Боргвардт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.