Чи можливо, щоб бізнес-логіка не забилася на думку?


31

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

У більшості випадків виникнуть проблеми типу "Якщо користувач обрав варіант x, програма повинна дозволити йому подавати інформацію для y, якщо ні, то s / він повинен надати інформацію z". Або виконайте деяку операцію AJAX, яка повинна застосувати деякі зміни до моделі, але НЕ виконувати їх, поки користувач явно не вимагає цього. Це кілька найпростіших проблем, з якими я зіткнувся, і я не можу зрозуміти, як можливо уникнути складної логіки в погляді.

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

Чи можна домогтися того, щоб взагалі не бачити бізнес-логіки?


2
Погляньте на MVC-похідні MVP та MVVM (див. En.wikipedia.org/wiki/Model_View_Presenter та en.wikipedia.org/wiki/Model_View_ViewModel ), вони можуть бути тим, що ви шукаєте.
Док Браун


2
Вид - це зовнішній, видимий прояв ваших даних та логіки. Неможливо для представлення НЕ представити бізнес-логіку. Або ви хочете сказати, що представлення не повинно містити в ньому жодного коду? Ви, звичайно, можете створювати представлення лише для HTML.
BobDalgleish

Ви можете заглянути в анімацію шаблонів ; хоча це, ймовірно, не викорінить всю логіку з шару перегляду , схоже, це повинно призвести до трохи кращого розділення речей.
Павло

Я думаю, що краще питання - чи краще для перегляду даних забруднювати модель, чи краще для представлення містити логіку перегляду, пов'язану з бізнес-логікою? Це більш реальний сценарій. Ваше питання по суті полягає в тому, щоб забруднити модель, щоб підтримати погляди, оскільки це був би єдиний спосіб здійснити те, що ви запитуєте.
Данк

Відповіді:


22

Чи можна домогтися того, щоб взагалі не бачити бізнес-логіки?

Мені здається, що це питання, що є обманливо важким для відповіді. (Питання, що викликає думки!)

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

Розділення проблем - це чудовий спосіб подумати про створення програмного забезпечення: він пропонує вам ідеї про те, куди розмістити код, і дає керівникам гарне уявлення про те, де шукати код. Я заперечу, що люди в основному неможливо створити робоче програмне забезпечення без відокремлення проблем. Нам це потрібно.

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

Сам погляд, сам по собі, не має значення без логіки бізнесу. І щоб бути ефективним у використанні та відображенні, неявно або явно, представлення матиме певні знання про бізнес-процеси, що відбуваються за ним. Ми можемо обмежити цей об'єм знань і можемо обмежити його частини, але практичні міркування часто змушують нас "зламати" розділення проблем.


2
The best conceptual location may not be the best location for other reasons: Браво !!
Magno C

8

Зазвичай я це роблю: якщо користувач обрав варіант x, перегляд дзвонить

controller->OptionXChanged()

Потім увімкніть контролер y на перегляді:

view->SetEnableInfoY(True) // suppose False=SetDisable

Перегляд повідомляє контролера про те, що відбувається, нічого не вирішуючи.


+1. Тривіальні проблеми ОП зазвичай вирішуються таким чином у нетривіальному додатку
dev_feed

Поміщення цієї логіки в контролер має дві проблеми: 1) це ускладнює тестування одиниць, і неможливо підтримувати кілька переглядів одних і тих же даних.
Кевін Клайн

4

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

З точки зору "Перегляд", це лише надання InfoY або InfoZ в систему. Тільки тому, що ваша реалізація інтерфейсу користується деякими динамічними оновленнями на основі вибору оператора (тобто включення InfoY або InfoZ) не робить логікою бізнес функціональність. Це дійсно перегляд логіки реалізації. Ви цілком могли б просто дати оператору можливість ввести InfoY або InfoZ без усієї активної дії. Чи вважаєте ви, що в такому контексті це ділова логіка? Якщо ні, то те саме стосується динамічного включення / відключення інформаційних полів.

Те саме стосується і прикладу фіксації. Це дві окремі операції, які система потребує для належної роботи. Ваш Перегляд повинен бути в змозі ініціювати належні дії для виконання потрібного функціоналу. Чи знає, як використовувати вашу систему, означає, що бізнес-логіка просочується? Я бачу, як хтось може сказати «так», але якщо ви вірите в це так, то реальність полягає в тому, що не існує такого поняття, як відокремлення ділової логіки від нічого. Ви повинні знати, що система працює / працює, щоб досягти нічого значимого. Інакше було б легко створити єдиний загальний вигляд і контролер, який працює з усіма можливими програмами MVC. Що ми знаємо, неможливо.

Підсумок, я думаю, що ваше визначення бізнес-логіки не те саме, що визначення інших.


1

Я працюю так (Struts2 + Hibernate):

Мої дії Struts відповідають лише за інформацію про показ у веб-переглядачі. Не думаючи.

Користувач -> Дія -> Сервіс -> Репозиторій -> Доступ до даних

Або:

Я хочу бачити -> Як бачити -> Що робити -> Як дістатися -> Де дістатися

Отже, у першому шарі (вид) у мене є щось на кшталт:

public String execute ()   {
    try {
        CourseService cs = new CourseService();
        Course course = cs.getCourse(idCourse);
    } catch (NotFoundException e) {
        setMessageText("Course not found.");
    } catch (Exception e) {

    }
    return "ok";
}

Як бачите, мій «погляд» не думаю. Це запит про надання послуги (для управління курсами) конкретного курсу. Цей сервіс може зробити багато іншого, як, наприклад, звіти, серачі тощо. Результати - це завжди список або конкретний об'єкт (як приклад). Служби - це справжня машина, застосовують правила та отримують доступ до сховища (для управління даними).

Отже, якщо я розміщую свої сервіси, сховища та DAOS в різних бібліотеках, я можу використовувати їх навіть у текстовій програмі або на настільній системі на основі Windows, нічого не змінюючи.

Сервіс знає, що робити, але не знає, як показати. Погляд знає, як показати, але не знає, що робити. Те саме з Сервісом / Репозиторієм: служба надсилає та запитує дані, але не знає, де дані і як їх взяти. Репозиторій "складає" необроблені дані для об'єктів, з якими Сервіс може працювати.

Але Репозиторій нічого не знає про базу даних. Вид бази даних (MySQL, PostgreSQL, ...) стосується DAO.

Ви можете змінити DAO, якщо хочете змінити базу даних, і вона не повинна впливати на верхні шари. Ви можете змінити сховище, якщо ви хочете оновити управління даними, але це не повинно впливати на DAO та верхні шари. Ви можете змінити Служби, якщо хочете змінити свою логіку, але це не повинно псуватись із шарами вище чи нижче.

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

Логіка бізнесу - Сервіс. Але як взаємодіяти з цим - це переглянути. Яку кнопку показати зараз? Чи може користувач бачити це посилання? Подумайте, що ваша система - це консольна програма: ви повинні заборонити, якщо неправильний користувач вибере #> myprogram -CourseService -option=getCourse -idCourse=234або зупинити його, щоб натиснути клавіші, щоб написати цю команду?

Якщо говорити у веб-системах (Struts + JavaEE), у мене є окремий пакет контролерів GUI. З огляду Дія, я надаю користувачеві, який зареєструвався, і клас дає мені кнопки (або будь-який елемент інтерфейсу, який я хочу).

                <div id="userDetailSubBox">
                    <c:forEach var="actionButton" items="${actionButtons}" varStatus="id">
                        ${actionButton.buttonCode}
                    </c:forEach>
                </div>

І

private List<ActionButton> actionButtons;

Пам’ятайте, щоб це не було від служб. Це речі VIEW. Зберігайте це в дії Struts. Будь-які взаємодії з інтерфейсом повинні бути повністю відокремлені від реального ділового коду, тому, якщо ви портуєте свою систему, буде легко вирізати те, що вам більше не потрібно.


1

У більшості випадків виникнуть проблеми на кшталт "Якщо користувач обрав варіант x, програма повинна дозволити йому подавати інформацію для y, якщо ні, то s / він повинен надати інформацію z"

Це логіка для моделі, а не погляд. Це може бути "view-model", створений спеціально для підтримки інтерфейсу користувача, але це все ж логіка моделі. Контрольна послідовність така:

  • Контролер приєднує обробник для перегляду подій
  • Перегляд додає обробник подій моделі
  • Користувач вибирає варіант X.
  • Перегляд викликає подію "Варіант X вибраний"
  • Контролер отримує подію та викликає model.selectOptionX ()
  • Модель піднімає подію "Стан моделі змінено"
  • Перегляд отримує подію, змінену моделлю, і оновлює подання на новий стан: inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed());

UI View Controller Model |.checkbox X checked.> | | | | | .. X selected ...>| | | | |-----> set X ------->| | | | | | |< .............state changed ............| | | | | | |-------------- Get state --------------->| | | | | | |<----------- new state ------------------| | <-- UI updates ------| Це класичний шаблон MVC. Можна повністю перевірити логіку моделі окремо від інтерфейсу користувача. Контролер і вигляд дуже тонкі і легко перевіряються.

=== У відповідь на Данк ===

Модель в шаблоні MVC інтерфейсу користувача (як правило) не є моделлю бізнес-об'єкта. Це просто модель для стану інтерфейсу користувача. У настільному додатку він може містити посилання на кілька бізнес-моделей. У додатку Web 2.0 це клас Javascript, який зберігає стан інтерфейсу, і спілкується через AJAX з сервером. Дуже важливо вміти писати тести одиничних моделей стану користувальницького інтерфейсу, оскільки саме там знайдено більшість помилок інтерфейсу. Перегляд і контролер повинні бути дуже тонкими роз'ємами.


1
Я думаю, це все зводиться до того, що ви вважаєте, визначенням MVC є. Ця версія, безумовно, дотримується дуже, дуже суворої інтерпретації MVC. Проблема полягає в тому, що ця сувора інтерпретація рідко забезпечує корисну або реконструйовану систему в реальному житті. Причиною цього є те, що майже кожного разу, коли ви придумаєте новий елемент / спосіб інтерфейсу користувача, щоб зробити щось, вам доведеться змінити модель. Потім модель забивається непотрібними властивостями, що стосуються лише інтерфейсу користувача. Вони не мають нічого спільного з додатком, який ви намагаєтеся створити, а лише з тим, як ви хочете представити дані оператору. БАД!
Данк

Кевін, будь ласка, помістіть свої відповіді тут у поле для коментарів, тому нам легко відповісти. Я погоджуюсь з тобою. Неможливо підтримувати інформацію інтерфейсу (UI) без будь-якої структури, але номенклатура "МОДЕЛЬ" може бути заплутаною. Я вважаю за краще керувати інтерфейсом інтерфейсу в іншому взаємозамінному пакеті, щоб легко зробити те, про що говорить @Dunk. Дивіться мою відповідь.
Magno C

@MagnoC: Я відредагував він відповідь у відповідь на Dunk, тому що думав, що доданий текст покращив відповідь. Ось про що йдеться на сайті: питання та відповіді. Модель є досить загальним терміном, і в шаблоні MVC вона означає "модель стану інтерфейсу".
Кевін Клайн

0

Логіка бізнесу більше схожа If X then return InfoType.Y, тоді інтерфейс відображатиме поля на основі результату, поверненого доменом.

// Controller method pseudocode
option changed routine

    get selected option

    get required info type from domain routine based on selected option

    display fields based on required info type

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


0

Якщо користувач обрав варіант x, програма повинна дозволити йому подавати інформацію для y, якщо ні, то s / він повинен надати інформацію z ".

Є входи, які мають умовно засновані необхідні значення. У більшості середовищ графічного інтерфейсу існує багато варіантів, як обробляти входи, особливо терміни. Вибраний варіант (у цьому випадку х) потрібно обробити, тому надішліть його контролеру. Відправте його, коли користувачі залишають поле введення. Зачекайте, поки вони натиснуть на інший об’єкт або натисніть зберегти. Не має значення для бізнес-логіки. Так чи інакше, контролер прийме рішення і йому потрібно сказати думку, "y потрібно".

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

І подумайте, все це могло статися тому, що контролер намагався зберегти і не вводив значення для необхідного поля в базі даних і суто відповідав на помилку бази даних. Не має значення, наскільки це стосується погляду.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.