шаблон для обмена объектами между API и приложением

9

У меня есть серьезные сомнения по поводу дизайна для моего веб-приложения.

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

Это ASP.NET Web API с платформой Entity, единицей работы и общим шаблоном хранилища. Пока все хорошо.

ПРОБЛЕМА

Там, где мне нужна помощь, я не могу найти эффективный способ обмена объектами между API и приложением.

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

Как это реализовано сейчас

Поскольку мой интерфейс - это веб-приложение ASP.NET в C #, а мой API - в C #, я создал общую библиотеку с определением всех моих классов, которыми я хочу поделиться между ними.

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

Проблема в том, что я чувствую, что я всегда конвертирую свои объекты.

ПРИМЕР

Вот пример моего рабочего процесса:

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

В контроллере я должен преобразовать эту модель в класс в моей общей библиотеке, а затем отправить этот объект в мой API.

Затем контроллер в моем API перехватывает вызов и преобразует этот объект в объект сущности для обновления базы данных.

Итак, у меня есть 3 класса

  1. Модель для представления со всей аннотацией данных для проверки (Клиент)
  2. Общие библиотеки классов для совместного использования объектов (DLL)
  3. Классы сущностей (API)

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

Марк
источник
Если мой вопрос не ясен, не стесняйтесь задавать вопросы.
Марк
Мне не ясно, какую архитектуру вы реализовали (возможно, меня озадачивает формулировка .net) - это трехуровневая архитектура: клиент, сервер, дБ?
Энди
Да, у меня есть веб-приложение, которое использует веб-API. Это API с бизнес-логикой и базой данных.
Марк

Ответы:

12

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

Каждый из этих объектов может представлять одну и ту же единицу информации, но у них разные обязанности. Объект базы данных является вашим интерфейсом связи с базой данных и должен храниться на уровне базы данных, поскольку он может иметь или не иметь разные аннотации метаданных базы данных и / или ненужные подробности о реализации базы данных в нем.

Ваш объект передачи данных является интерфейсом связи с вашими пользователями API. Они должны быть как можно более чистыми, чтобы облегчить их использование на разных языках / платформах. Это может наложить определенные ограничения на то, как они выглядят и ведут себя, в зависимости от того, каких потребителей API вы хотите поддерживать.

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

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

Я также ненавижу писать код преобразования между различными типами объектов, как это, но мое решение обычно одно из следующего:

  • Используйте библиотеку, которая выполняет большую часть тяжелой работы по преобразованию объектов - например, если вы используете C #, вы можете использовать фантастическую библиотеку AutoMapper ( http://automapper.org/ ). Я полагаю, что есть еще пара таких библиотек, но AutoMapper - самая мощная из тех, что я когда-либо видел.
  • Если вы не можете найти библиотеку, которая поможет вам в преобразовании ваших объектов, напишите набор служебных методов для преобразования между ними. Это может быть отстой, но в конечном итоге это того стоит, напишите метод преобразования в первый раз, когда вам нужно что-то преобразовать - не ждите.
wasatz
источник
Спасибо за ваши объяснения, но мне все еще трудно что-то понять. Я не понимаю, почему слой для передачи данных не имеет никакой проверки? Что если я забуду некоторые проверки для моего следующего мобильного приложения? По крайней мере, он не будет проверяться, когда я вызываю API вместо того, чтобы делать исключение в моей модели базы данных. Я не уверен, что понимаю.
Марк
1
Я не говорю, что вы не должны проверять на уровне API. Честно говоря, это самое важное место для проверки. Проверка в вашем приложении - это просто «приятная функция», которая помогает пользователям не совершать ошибок, проверка объектов передачи данных предназначена для защиты от вредоносных и ошибочных данных. Однако, поскольку это разные варианты использования, вам может потребоваться использовать разные среды проверки (вы будете использовать разные среды проверки, если ваше приложение и API не написаны на одном языке), и вы можете проверять немного разные вещи на каждом уровне (продолжение в следующем комментарии)
wasatz
1
Таким образом, вы должны проверить ваши объекты передачи данных. Но вы также должны убедиться, что способ их проверки не случайно вводит какие-либо зависимости от любой другой среды . И, конечно, как я уже говорил ранее, вы действительно не можете быть уверены, что ваши объекты передачи данных были проверены вообще или что они были проверены одной и той же структурой - поэтому вы должны «проверить дважды».
wasatz
2
В основном вы должны попытаться рассматривать ваше приложение и API как два совершенно разных и отдельных приложения. Возможно, вы разрабатываете их одновременно, и они могут быть в одном проекте Visual Studio Solution / Eclipse. Но на самом деле это две совершенно разные программы. Когда вы работаете в своем приложении, постарайтесь «забыть», что вы тот, кто создал API, и используйте его так же, как и с обычным сторонним API. Таким образом, у вас будет больше шансов увидеть, как другие будут чувствовать себя при использовании вашего API, и исправить наихудшие части на ранней стадии.
wasatz
1
И то же самое, конечно, верно при работе над вашим API-проектом, попробуйте представить, что вы пишете сервис, который собираются использовать сторонние разработчики. Постарайтесь не думать слишком много о вашем текущем приложении, а больше думать о том, «какие услуги я предоставляю», и предполагая, что все, кто использует ваш API (включая вас), являются злыми людьми, которые пытаются убить ваш сервер и заставить вас удалить всю вашу базу данных.
wasatz