Идентификатор против объекта домена в качестве параметра метода

10

Есть ли объективные аргументы за или против использования объектов против уникального идентификатора в качестве параметров метода / функции? (а члены других объектов?). Особенно в контексте статически типизированных языков (C # / Java / Scala)

Плюсы самого объекта:

  • Более безопасные звонки. С идентификаторами существует риск неправильного упорядочения аргументов. Этого можно избежать, сохранив мини-класс для каждого класса, в котором хранится только идентификатор этого класса.
  • Получить один раз от настойчивости, нет необходимости получать снова
  • С идентификатором ID, если тип идентификатора изменится, скажем, int -> long, потребуется изменение по всем направлениям с возможными ошибками .. (суд: https://softwareengineering.stackexchange.com/a/284734/145808 )

Плюсы использования ID:

  • Большую часть времени нет необходимости в реальном объекте, просто будет uniqueid, поэтому наличие идентификатора экономит время на его получение от постоянства.

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

Учитывая, что это конкретно определенная проблема, я надеюсь, что есть объективные ответы, а не - «я думаю» или «мне нравятся» типы ... :-).

РЕДАКТИРОВАТЬ: Контекст по предложению комментатора-Единственное ограничение является статически типизированных языков. Приложение является приложением общего назначения, хотя с удовольствием получит ответы и на основе конкретных сценариев использования.

РЕДАКТИРОВАТЬ: немного больше контекста. Скажем, у меня есть система управления книгами. Моя модель:

Book: { id: Int, isbn: String, donatedBy: Member, borrowedBy: Member }
Member: {id: Int, name: String}

Table- wishlist: { isbn: String, memberId: Int}
Table- borrows:  { id: Int, memberId: Int}  

Method: 
isInWishList( book: Book, member: Member ) vs isInWishList( bookId: Int,  memberId: Int)

handleBorrowRequest( memberId: Int, book: Book ){ 
   //the login system doesn't actually get the entire member structure, only the member id. I don't need the full member yet. can run a query to verify that the memberId has less than max allowed books for borrowing. 
}

Почему я хочу оставить только идентификатор, а не полноправного члена? Скажем, когда я получаю информацию о книге, мне редко нужно знать, кто ее пожертвовал или одолжил. Получение их полной информации для заполнения полей donatedBy и loanedBy является излишним.

Конечно, это только мои очки. Я уверен, что я скучаю по вещам, поэтому хотел знать, какие моменты в пользу / против.

0fnt
источник
Не могли бы вы отредактировать свой вопрос с немного большим контекстом? Непонятно, что это за сценарий. Я собираюсь догадаться, что вы говорите об объектах, которые управляются системой ORM (например, Hibernate), и что под «мини-классом» вы подразумеваете лениво загружаемый прокси-объект.
Дариен
2
Возможно связано? programmers.stackexchange.com/questions/284634/…
hjk
Добавление в качестве комментария здесь (пока я не получу достаточно контекста, чтобы перейти к полнофункциональному ответу): Если вы не жестко кодируете значения идентификаторов в своем коде (большое нет-нет), вам все равно придется загружать значения идентификаторов откуда-то верно? «Большую часть времени» тоже довольно расплывчато ИМХО ...
hjk
@hjk Добавил еще немного контекста, спасибо. У вас есть точка - вам все равно нужно загрузить значения идентификатора откуда-то. Однако речь идет не о том, чтобы «не касаться» БД, а о том, чтобы минимизировать использование и пропускную способность для БД. Я могу получить идентификаторы всех тех, кто хочет одолжить книгу, но на самом деле получить их полную информацию было бы ненужным.
0
Кажется, что это будет зависеть от нескольких вещей: (1) требуют ли варианты использования фактических атрибутов (столбцов) или только идентификатора, который зависит от самих вариантов использования; (2) используете ли вы какие-либо методы кэширования или повышения производительности, которые сделают запрос идентификаторов атрибутов легким, и будут ли ваши варианты использования достаточно тяжелыми, чтобы нарушить такие схемы кэширования.
Руонг

Ответы:

8

В зависимости от вашей среды и проблемного контекста необходимость использования базы данных может быть уменьшена, и в результате (IMO) аргумент для использования только идентификаторов теряется.

Например, PHP Doctrine2 ORM имеет EntityManager::getReferenceлениво загруженный прокси для сущности, используя предоставленный идентификатор; Я не знаю, сколько других ORM делают это, но это примерно соответствует понятию «мини-класс», которое вы упоминаете. Для большинства целей и задач это полностью гидратированный объект, поэтому вы можете передать его и использовать как любой другой.

Единственный случай, когда это не так, это когда ему дают недопустимый идентификатор, и в этом случае вы все равно захотите пойти в базу данных для проверки; Кроме того, чтобы снизить стоимость получения сущностей, большинство ORM имеют (в первом и втором уровнях) функции кэширования, доступные в той или иной форме.

Как только мы сократим необходимость и стоимость обращения к базе данных, у нас останется много преимуществ использования объекта в качестве параметра:

  1. Тип безопасности.
  2. Меньше знаний требуется звонящему. Разработчик через 6 месяцев не может ошибочно передать идентификатор неправильной сущности.
  3. Снижение стоимости рефакторинга. Если метод должен был измениться, чтобы потребовать от субъекта 2 части информации, то нет необходимости менять вызывающего абонента для его предоставления, при условии, что вызывающий получил для начала полностью гидратированный объект.
  4. Требуется меньше проверки для каждого метода. Многие методы могут предполагать, что заданная ими сущность существует в базе данных (потому что она пришла из ORM), и поэтому больше не нужно проверять идентификатор.
  5. (Потенциально) меньше вызовов базы данных. Если вы передаете идентификаторы 3 методам, и каждый из них должен проверить их или получить больше данных об объекте, это в 3 раза больше вызовов базы данных, чем 1 метод, извлекающий объект, и 2 работающих с ним.

Конечно, есть случаи, когда кто-то может захотеть передать только идентификатор: например, при пересечении ограниченной границы контекста (говорят в дизайне, управляемом доменом). Если мы рассмотрим два ограниченных контекста с различными представлениями о том, что составляет учетную запись (например, финансы против отношений с клиентами), то мы не можем передать учетную запись контекста A в контекст B. Вместо этого идентификатор учетной записи (на языке домена) может пройти через

Энди Хант
источник
Кэширование не будет хорошо масштабироваться при нескольких запущенных приложениях. У меня есть собственное кэширование. Очки отличные, хотя.
0
Я предполагаю, что еще одно замечание против идентификаторов состоит в том, что использование идентификатора подразумевает сохранение персистенции, помимо проверки, для фактического получения объекта.
0
3

Для такого рода вопросов я делегирую любое решение, наилучшим образом сообщающее о моих намерениях как программиста, и облегчающее работу «Будущего Грега».

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

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

Выберите решение, которое проще всего понять новому программисту или вашему Future Self, а именно передать объекты Bookи Member. Только после обнаружения реальной проблемы с производительностью вы должны действительно позаботиться о простой передаче идентификаторов.

Или мы могли бы вспомнить, что статически типизированные языки, такие как Java, предлагают перегрузку методов, так что вы можете получить свой торт и съесть его тоже:

public boolean isInWishList(int bookId, int memberId) {
    // ...
}

public boolean isInWishList(Book book, Member member) {
    return isInWishList(book.getId(), member.getId());
}

Реальный ответ на этот вопрос - написать оба метода, вызвать целочисленную версию из строго типизированной версии, а Боб - твой дядя.

Грег Бургхардт
источник