Возможно ли, чтобы бизнес-логика не попадала в поле зрения?

31

За последние 3 года я разработал несколько проектов веб-приложений, как личных, так и рабочих, и я не могу понять, возможно ли, по крайней мере, некоторая бизнес-логика не оказаться в слое представления приложения.

В большинстве случаев возникают проблемы, такие как «Если пользователь выбрал опцию x, то приложение должно позволить ему предоставить информацию для y, если нет, то он / она должен предоставить информацию z». Или выполните некоторую AJAX-операцию, которая должна применить некоторые изменения к модели, но НЕ зафиксировать их, пока пользователь явно не запросит об этом. Вот некоторые из самых простых проблем, с которыми я столкнулся, и я не могу понять, как можно избежать сложной логики в представлении.

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

Можно ли достичь представления без какой-либо бизнес-логики?

vdaras
источник
2
Посмотрите на производные MVC MVP и MVVM (см. En.wikipedia.org/wiki/Model_View_Presenter и en.wikipedia.org/wiki/Model_View_ViewModel ), они могут быть тем, что вы ищете.
Док Браун
связанные (возможно, дубликаты): отделение классов от пользовательского интерфейса
gnat
2
Представление - это внешнее, видимое проявление ваших данных и логики. Представление НЕ может представить бизнес-логику. Или вы говорите, что в представлении не должно быть кода? Вы, конечно, можете создавать только HTML-представления.
BobDalgleish
Вы можете посмотреть на шаблон анимации ; хотя это, вероятно, не удалит всю логику со слоя представления , похоже, что это должно привести к немного лучшему разделению вещей.
Павел
Я думаю, что лучший вопрос - лучше ли данные представления загрязнять модель или лучше, чтобы представление содержало логику представления, которая связана с бизнес-логикой? Это более реальный сценарий. Ваш вопрос, по сути, выступает за загрязнение модели, чтобы поддержать взгляды, поскольку это был бы единственный способ выполнить то, что вы просите.
Данк

Ответы:

22

Можно ли достичь представления без какой-либо бизнес-логики?

Я считаю, что это обманчиво сложный вопрос. (Задумчивый вопрос!)

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

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

Но, как и во всем, есть компромиссы. Лучшее концептуальное местоположение не может быть лучшим местом по другим причинам. Возможно, нагрузка на ваш веб-сервер слишком велика, поэтому вы добавляете некоторый JavaScript на свои веб-страницы, чтобы отследить простые ошибки ввода, прежде чем они попадут на ваш сервер; Теперь у вас есть бизнес-логика на ваш взгляд.

Само представление само по себе не имеет ценности без бизнес-логики. И чтобы быть эффективным в использовании и отображении, неявно или явно, представление будет иметь некоторое представление о бизнес-процессах, происходящих за ним. Мы можем ограничить это количество знаний, и мы можем оцепить его части, но практические соображения часто вынуждают нас «нарушать» разделение интересов.

JVR
источник
2
The best conceptual location may not be the best location for other reasons: Браво !!
Магно C
8

Я обычно делаю это: если пользователь выбрал опцию x, представление вызывает

controller->OptionXChanged()

Затем контроллер активирует y на виде:

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

Представление уведомляет контроллер о том, что происходит, ничего не решая.

Fil
источник
+1. Тривиальные проблемы ОП обычно обрабатываются таким образом в нетривиальном приложении
dev_feed
Внедрение этой логики в контроллер имеет две проблемы: 1) это усложняет модульное тестирование, и невозможно поддерживать несколько представлений одних и тех же данных.
Кевин Клайн
4

Я подвергаю сомнению, являются ли приведенные вами примеры действительно бизнес-логикой. Примеры, которые вы описываете, представляют собой операции, которые можно выполнять в системе. То, как вы решили представить выбор пользователю, может показаться, что вы выполняете бизнес-логику в представлении.

С точки зрения «Просмотр» это только предоставление InfoY или InfoZ в систему. Тот факт, что ваша реализация пользовательского интерфейса выполняет некоторые динамические обновления, основанные на выборе оператора (например, включение InfoY или InfoZ), не делает бизнес-логику функциональности функциональной. Это действительно вид логики реализации. Вы вполне могли бы просто дать оператору возможность ввести InfoY или InfoZ без всякой возможности включения. В этом контексте, вы все еще считаете это бизнес-логикой? Если нет, то это же относится и к динамическому включению / отключению информационных полей.

То же самое касается примера фиксации. Это две отдельные операции, которые требуются системе для правильной работы. Ваш View должен иметь возможность инициировать правильные действия для выполнения желаемой функциональности. Означает ли знание того, как использовать вашу систему, что бизнес-логика просачивается? Я понимаю, как кто-то может сказать «да», но если вы верите в это, то реальность такова, что нет такой вещи, как отделение бизнес-логики от чего-либо. Вы должны знать, что система делает / работает, чтобы достичь чего-то значимого. В противном случае было бы просто создать единый общий вид и контроллер, работающий с любым мыслимым приложением MVC. Что мы знаем невозможно.

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

Замочить
источник
1

Я работаю так (Struts2 + Hibernate):

My Struts Actions отвечает только за отображение информации в веб-браузере. Не думая

Пользователь -> Действие -> Служба -> Хранилище -> Доступ к данным

Или:

Хочу посмотреть -> Как увидеть -> Что делать -> Как добраться -> Где взять

Итак, в первом слое (вид) у меня есть что-то вроде:

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;

Не забудьте не допускать этого к услугам. Это ПРОСМОТР вещи. Держите это в Struts Actions. Любое взаимодействие с интерфейсом должно быть полностью отделено от реального бизнес-кода, поэтому, если вы перенесете свою систему, вам будет легко сократить то, что вам больше не нужно.

Магно С
источник
1

В большинстве случаев возникают проблемы, такие как «Если пользователь выбрал опцию x, то приложение должно позволить ему предоставить информацию для y, если нет, то он / она должен предоставить информацию z»

Это логика для модели, а не для представления. Это может быть «модель представления», созданная специально для поддержки пользовательского интерфейса, но это все еще логика модели. Последовательность управления:

  • Контроллер присоединяет обработчик для просмотра событий
  • View прикрепляет обработчик для событий модели
  • Пользователь выбирает опцию 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. Смотри мой ответ.
Магно C
@MagnoC: я отредактировал его ответ в ответ на Данка, потому что я думал, что добавленный текст улучшил ответ. Вот о чем сайт: вопросы и ответы. Модель - это довольно общий термин, и в паттерне 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

Если для пользовательского интерфейса требуется бизнес-логика, делегируйте выбор домену. Пользовательский интерфейс будет просто действовать в соответствии с решением.

Yorro
источник
0

Если пользователь выбрал опцию x, то приложение должно позволить ему предоставить информацию для y, если нет, то он / она должен предоставить информацию z ".

Есть входы, которые имеют условно-обязательные значения. В большинстве сред с графическим интерфейсом существует множество вариантов обработки входных данных, особенно времени. Выбранный параметр (в данном случае x) необходимо обработать, поэтому отправьте его контроллеру. Отправьте его, когда пользователь покинет поле ввода. Подождите, пока они не нажмут на другой объект или не нажмут кнопку «Сохранить». Не имеет значения для бизнес-логики. Так или иначе, контроллер примет решение и должен сказать представлению «y требуется».

То, как представление интерпретирует или реализует это, на самом деле не имеет значения с точки зрения бизнес-логики. Сделайте нужное поле. Сделайте всплывающее окно или выстрелите из пушки и скажите пользователю, что нужно ввести y, или просто будьте упрямы и не позволяйте бедному пользователю делать что-либо, пока он не поймет это.

И только подумайте, все это могло произойти, потому что контроллер попытался сохранить и не ввел значение для обязательного поля в базе данных и просто отвечал на ошибку базы данных. Это не имеет значения, что касается представления.

Нечто подобное обязательному или ограниченному значению для входа может быть обработано во многих местах. Если вы «только» обращаетесь к нему в представлении, многие разработчики увидят это как проблему, когда может быть несколько пользовательских интерфейсов. Вот почему бизнес-логика может быть создана и протестирована без особого пользовательского интерфейса или даже базы данных. Вам даже не нужно иметь сайт.

JeffO
источник