Ідентифікатор і об’єкт домену як параметр методу


10

Чи існують об'єктивні аргументи за або проти використання об'єктів проти унікального ідентифікатора як параметрів методу / функції? (а члени інших об’єктів?). Спеціально в контексті мов, що мають статичний тип (C # / Java / Scala)

Плюси самого об’єкта:

  • Більше типів безпечних дзвінків. Ідентифікатори мають ризик неправильного впорядкування аргументів. Це можна зменшити, зберігаючи міні-клас для кожного класу, який зберігає лише ідентифікатор цього класу.
  • Отримайте один раз від наполегливості, не потрібно отримувати знову
  • Ідентифікатор, якщо тип id зміниться, скажімо, int -> long, то вимагатиме змін у всій смузі з можливістю помилок .. (Courtsey: https://softwareengineering.stackexchange.com/a/284734/145808 )

Плюси використання ID:

  • Більшість часу не потребує фактичного об’єкту, а просто унікальний, тому наявність ID дозволяє економити час від отримання його від постійності.

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

Враховуючи, що це конкретно визначена проблема, я сподіваюся, що є об’єктивні відповіді, а не типи "я думаю" чи "мені подобається" ... :-).

EDIT: Контекст щодо пропозиції коментатора. Єдине обмеження - це статично набрані мови. Додаток - це програма загального призначення, хоча рада отримати відповіді і на конкретних сценаріях використання.

EDIT: Ще трохи контексту. Скажіть, у мене є система управління книгами. Моя модель:

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. 
}

Чому я хотів би зберегти тільки ідентифікатор, а не повний член? Скажіть, коли я отримую інформацію про книгу, мені рідко потрібно знати про те, хто її пожертвував чи позичив. Отримати їх повну інформацію для заповнення подарованихBy та позиченихBy полів - це надлишок.

Звичайно, це лише мої моменти. Я впевнений, що мені не вистачає речей, тому хотілося знати, які є бали на користь / проти.


Чи можете ви відредагувати своє запитання трохи більше контексту? Незрозуміло, що таке сценарій. Я здогадуюсь, що ви говорите про об'єкти, якими керує система ORM (як Hibernate), а під "міні-класом" ви маєте на увазі лінивий проксі-об'єкт.
Даріен

2
Можливо, пов'язані? programmers.stackexchange.com/questions/284634/…
hjk

Додавання тут як коментаря (поки я не можу отримати достатньо контексту, щоб розширитись до повнофункціональної відповіді): Якщо ви не кодуєте значення коду в своєму коді (великий ні-ні), вам все одно доведеться завантажувати свої ідентифікаційні значення звідкись правильно? "Більшу частину часу" теж досить розпливчасте IMHO ...
hjk

@hjk Додав ще трохи контексту, дякую. У вас є точка - вам все одно доведеться звідкись завантажувати значення ID. Однак справа не в тому, щоб не "торкатися" БД, а про мінімізацію використання та пропускної здатності до БД. Я можу отримати ідентифікацію всіх, хто хоче позичити книгу, але насправді отримання їхніх деталей було б зайвим.
0fnt

Здається, це залежатиме від кількох речей: (1), чи потребують випадки використання фактичні атрибути (стовпці) або просто ідентифікатор, що залежить від самих випадків використання; (2) чи використовуєте ви які-небудь методи кешування чи підвищення продуктивності, які б спрощували запит ідентифікаторів до атрибутів і чи ваші випадки використання були б досить важкими, щоб порушити такі схеми кешування.
rwong

Відповіді:


8

Залежно від вашого оточення та проблемного контексту, необхідність переходити до бази даних може бути пом’якшена, і в результаті (ІМО) аргумент для використання лише ідентифікатора втрачається.

Наприклад, PHP Doctrine2 ORM має, EntityManager::getReferenceякий виробляє ліниво завантажений проксі для сутності, використовуючи наданий ідентифікатор; Я не знаю, скільки інших ОРМ роблять це, але це приблизно відповідає поняттю "міні-класу", яке ви згадуєте. Для більшості намірів і цілей це повністю гідратований об'єкт, тому ви можете передавати його навколо і використовувати, як і будь-який інший.

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

Після того, як ми зменшимо потребу та витрати на перехід до бази даних, ми здебільшого залишаємося професіоналами використання сутності як параметра:

  1. Тип безпеки.
  2. Менше знань, необхідних для абонента. Розробник через 6 місяців вниз не може помилково передати ідентифікатор неправильної сутності.
  3. Зниження вартості рефакторингу. Якщо метод повинен був змінити, щоб вимагати від сутності 2 частини інформації, немає потреби в зміні абонента для надання його, припускаючи, що абонент повинен почати повністю гідратовану сутність.
  4. Для методу потрібно менше перевірки. Багато методів можуть припустити, що сутність, яку їм надано, існує в базі даних (тому що вона надходила з ORM), і тому більше не потрібно перевіряти ідентифікатор.
  5. (Потенційно) менше викликів до бази даних. Якщо ви передаєте ідентифікатори до 3-х методів, і кожен повинен підтвердити його або отримати більше даних про сутність, це в 3 рази більше викликів бази даних, ніж 1 метод отримання сутності та 2, що працюють над ним.

Звичайно, бувають випадки, коли можна просто передати ідентифікатор: наприклад, при перетині обмеженої межі контексту (у дизайні, керованому доменом, говорять). Якщо ми розглянемо два обмежені контексти з різними уявленнями про те, що складається з облікового запису (наприклад, фінанси та відносини з клієнтами), ми не можемо передати обліковий запис контексту А контексту В. Натомість ідентифікатор облікового запису (мовою домену) може бути переданим поперек.


Кешування не буде добре масштабуватись у кількох випадках запуску програми. У мене є власне кешування на місці. Бали все-таки відмінні.
0fnt

Думаю, ще один момент проти ідентифікаторів полягає в тому, що використання ідентифікатора означає виклик стійкості, крім валідації, і для того, щоб отримати об'єкт також.
0fnt

3

Для такого роду питань я делегую те рішення, яке найкраще повідомляє про мої наміри як програміста і полегшує роботу "Майбутніх Грега".

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

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

Подивіться на рішення, яке найпростіше зрозуміти новому програмісту або вашому майбутньому «Я», яке полягає в тому, щоб передати об'єкти Bookта Memberоб'єкти. Тільки після знаходження актуальної проблеми продуктивності ви повинні по-справжньому заклопотати себе просто передачею ідентифікаторів.

Або ми можемо пам’ятати, що статично набрані мови, такі як Java, пропонують метод перевантаження, тож ви можете випити торт і з'їсти його також:

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

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

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

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