Как избежать повторения бизнес-логики между клиентом и сервером?

По мере роста потребностей в веб-приложениях я все больше и больше пишу веб-приложения на основе API. Я использую фреймворки, такие как AngularJS, для создания многофункциональных веб-клиентов, которые взаимодействуют с этими API В настоящее время я использую PHP (Lumen или Laravel) для серверной части / API.

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

Когда я говорю бизнес-логику, я имею в виду правила, подобные следующим для формы заказа:

  • Вы можете купить X, если вы покупаете Y.
  • Вы не можете купить Y, если у вас есть Z.
  • Если вы купите 10 из них, вы получите 10% скидку.
  • Высота х Ширина х Глубина х Стоимость = Конечная стоимость.
  • Высота должна быть от 10 до 20, если ваша ширина больше 5.
  • И т. Д.

Чтобы сделать это приложение быстрым и отзывчивым, логика для вычислений (наряду с другой бизнес-логикой) выполняется на стороне клиента. Поскольку мы не должны доверять клиенту, я проверил эти цифры на стороне сервера. Эта логика может быть довольно сложной, и написание этой сложной логики в обоих местах кажется опасным.

Я имею в виду три решения:

  1. Сделайте все, что требует бизнес-логики, сделайте ajax-вызов API. Вся бизнес-логика будет жить в одном месте и может быть проверена один раз. Это может быть медленным, поскольку клиенту придется ждать каждого изменения, вносимого в форму заказа, чтобы получить обновленные значения и результаты. Очень быстрый API поможет в этом. Основным недостатком является то, что это может не сработать, если у пользователей плохое соединение (мобильные устройства).

  2. Напишите бизнес-логику на стороне клиента И на стороне сервера. Клиент получает мгновенную обратную связь, когда вносит изменения в форму, и мы проверяем все данные после их отправки на сервер. Недостатком является то, что мы должны продублировать всю бизнес-логику и протестировать обе стороны. Это, безусловно, больше работы и сделает будущую работу хрупкой.

  3. Доверься клиенту!?! Напишите всю бизнес-логику на стороне клиента и предположите, что они не вмешивались в данные. В моем текущем сценарии я работаю над создателем цитат, который всегда будет проверяться человеком, так что, возможно, это действительно нормально.

Честно говоря, я не рад ни одному из решений, поэтому я обращаюсь к сообществу за советом. Я хотел бы услышать ваше мнение или подходы к этой проблеме!

17

Решение

Вы можете сделать еще одну вещь.

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

Затем настройте сервер nodejs рядом с PHP-сервером для обслуживания этой логики на стороне клиента. Так что на стороне клиента его можно использовать без вызова AJAX.

Затем со стороны сервера (PHP), когда вам нужно проверить и запустить все эти бизнес-логики, вызовите cURL для nodejs для проверки этих данных. Это означает, что это HTTP-вызов с PHP-сервера на сервер nodejs. Сервер Nodejs будет иметь другой код, который будет принимать эти данные и проверять их с тем же кодом и возвращать результат.

Таким образом, вы можете сделать

  1. Ускоренное развитие (Одно место для модульного тестирования вашей логики)
  2. Более быстрое выполнение клиентского кода (Нет необходимости в ajax, так как одинаковые файлы javascript проверки обслуживаются nodejs на стороне клиента)
  3. Вся бизнес-логика будет идти на сервер nodejs. (Когда меняется бизнес-логика, вам нужно коснуться только этой части, так что в ближайшем будущем, если вам понадобится также создать некоторые другие интерфейсы, вы сможете использовать этот сервер для проверки ваших данных. Он будет работать так же, как ваш сервер бизнес-правил)

Единственное, что вам нужно сделать, это настроить nodejs рядом с PHP-сервером. Но вам не нужно менять весь ваш код на сервере nodejs.

8

Другие решения

У меня возникла та же проблема, когда я решил создать приложение, используя Laravel для внутреннего интерфейса и Angular 2 для внешнего интерфейса. И мне кажется, что пока нет решения избежать дублирования бизнес-логики, потому что:

В настоящее время PHP и JavaScript не могут быть преобразованы из одного в другой. Было бы неплохо, если бы мы могли использовать один и тот же язык для написания бизнес-логики, а затем встраивать их как во внутренний, так и во внешний интерфейс. С этого момента это приводит меня к другому вопросу:

Чтобы достичь цели, мы должны писать бизнес-логику только на одном языке, и пока JavaScript является лучшим решением. Как вы знаете, TypeScript / EMCA Script помогают нам писать код в ООП. метеор Инфраструктура инфраструктуры NodeJS помогает нам писать код на JavaScript для запуска в обе стороны Back-end и Front-End.

Так что, с моей точки зрения, мы можем использовать TypeScript / EMCA для написания пакетов для бизнес-логики, например, класс для проверки, написанный на JavaScript, может быть реализован с обеих сторон, так что вы пишете только один раз, но он будет вызываться дважды из передний и задний конец также.

Это моя точка зрения. Надеюсь увидеть другие решения по этой очень интересной теме.

8

Одно из возможных решений — объявить ваши правила проверки на декларативном абстрактном языке, таком как XML или JSON Schema.

Затем на стороне клиента, скажем, AngularJS — вы можете преобразовать эти правила в готовый рендерер формы. Так что теперь на стороне клиента вы получаете формы, которые проверяют заявленные правила.

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

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

5

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

Я думаю, что вариант 1 — это лучший вариант, он наиболее понятен и, кажется, наиболее логичен. Если в будущем вы захотите расширить свое веб-приложение до нативных мобильных приложений, вы сможете повторно использовать всю бизнес-логику, вызывая эти API-интерфейсы. Для меня это огромная победа.

Если вы беспокоитесь, если делаете слишком много запросов API, и это может повлиять на производительность мобильных устройств, то, возможно, попробуйте сгруппировать некоторые запросы и выполнить одну проверку в конце? Таким образом, вместо того, чтобы выполнять проверку каждого поля в форме, выполняйте проверку, когда пользователь отправляет всю форму. Кроме того, большинство подключений к Интернету будет достаточно, если вы продолжите запрашивать и отвечать на данные до минимума, поэтому я не буду беспокоиться об этом.

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

Вот некоторые из общих проблем, с которыми мне приходилось сталкиваться:

  • Отображает ли интерфейсная ошибка, если API ее возвращает?
  • Если пользователь допустил ошибку и отправил форму, он должен увидеть ошибку. Но как только пользователь исправит ошибку и отправит снова, ошибка должна скрыться, и теперь должно появиться сообщение об успехе.
  • Что делать, если API глючит или интернет-соединение нестабильно, поэтому ничего не возвращается. Будет ли зависать интерфейс?
  • Что, если есть несколько сообщений об ошибках, может ли / отображает ли их интерфейс?

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

3

Прежде всего: никогда не доверяй клиенту.

При этом, я имею дело с этим все время, и, к сожалению, я не нашел легкого решения. Вы должны выполнить проверку с обеих сторон, НО, вам не нужно делать полную проверку с обеих сторон.

Что я делаю, так это пытаюсь сбалансировать это. На стороне клиента вы выполняете большую часть простой (но ценной) проверки, обычные вещи, числа должны быть числами, даты должны быть датами, данные в пределах диапазона и т. Д., Поэтому, когда вы отправляете его, он отправляется на сервер, чтобы получить полностью проверено, но на стороне клиента вы удостоверяетесь, что большая часть информации по меньшей мере в правильном формате, а часть (или большая часть) уже проверена, однако настоящая бизнес-логика выполняется на стороне сервера , но поскольку большая часть данных уже верна, проверка на стороне сервера, скорее всего, утвердит запрос, поэтому вы избежите много повторных отправок.

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

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

Я надеюсь, что вы найдете это полезным.

1

Сегодня решение явно принадлежит @ParthaSarathiGhosh, но ближайшее будущее, безусловно, даст нам другое решение …

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

Сегодня эта технология уже поддерживается в большинстве современных браузеров, но доступна только с c / c ++. Таким образом, вы уже можете использовать его, если у вас есть эти навыки.

Конечно, планируется расширить его и на другой язык (так как уже есть некоторые исследования для C # — например: blazor — и другие языки). Но уровень зрелости кажется недостаточно стабильным для производства (даже команда разработчиков Blazor пока не рекомендует его для производства).

Это только мое собственное мнение, но => Логика в NodeJS — это решение для повторного использования кода javascript, но я все еще чувствую необходимость в строго типизированном языке, когда речь идет о большом поддерживаемом логическом коде. (Да, я знаю TypeScript, и это действительно хорошо, но я что-то упускаю). WebAssembly еще немного молода, но наверняка принесет большое улучшение в отношении принципа СУХОЙ.

1

Я чувствую, что 1-й вариант — лучший шаг вперед в будущем. Первоначальная разработка API позволяет тестировать и правильно работать всю бизнес-логику и обеспечивает доступ к интерфейсам. Вы никогда не должны доверять пользователю!

Первая разработка Power API не имеет ограничений по сравнению с кодированием одной и той же логики снова и снова для каждого необходимого интерфейса.

0

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

Сторона клиента против стороны сервера

0