Identificatore vs oggetto dominio come parametro del metodo


10

Esistono argomenti oggettivi a favore o contro l'utilizzo di oggetti vs ID univoco come parametri metodo / funzione? (e membri di altri oggetti?). Specialmente nel contesto di linguaggi tipicamente statici (C # / Java / Scala)

Pro dell'oggetto stesso:

  • Altre chiamate typesafe. Con gli ID esiste il rischio di un ordinamento errato degli argomenti. Ciò può essere mitigato mantenendo una classe "mini" per ogni classe che memorizza solo l'ID di quella classe.
  • Ottieni una volta dalla persistenza, non c'è bisogno di riaverla
  • Con ID, se il tipo di ID cambia, dì int -> long, quindi richiederebbe modifiche su tutta la linea con possibilità di errori .. (courtey: https://softwareengineering.stackexchange.com/a/284734/145808 )

Pro dell'utilizzo dell'ID:

  • La maggior parte delle volte non è necessario l'oggetto reale, lo farebbe solo uniqueid, quindi avere un ID consente di risparmiare tempo dall'ottenerlo dalla persistenza.

Una combinazione di queste tecniche, per quanto posso vedere, avrebbe solo svantaggi di entrambi e pro di nessuno dei due.

Dato che questo è un problema concretamente definito, spero che ci siano risposte obiettive e tipi non "penso" o "mi piacciono" ... :-).

EDIT: contesto sul suggerimento di un commentatore. L'unica limitazione è un linguaggio tipicamente statico. L'applicazione è un'applicazione generale, sebbene felice di ottenere risposte basate anche su specifici scenari di utilizzo.

EDIT: qualche altro contesto. Supponiamo che io abbia un sistema di gestione dei libri. Il mio modello è:

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

Perché dovrei voler mantenere solo l'id e non l'intero membro? Di 'quando ricevo informazioni sul libro, raramente ho bisogno di sapere chi lo ha donato o preso in prestito. Ottenere le informazioni complete per popolare i campi donati e presi in prestito dai campi è eccessivo.

Naturalmente, questi sono solo i miei punti. Sono sicuro che mi mancano le cose, quindi volevo sapere quali sono i punti a favore / contro.


Potresti modificare la tua domanda con un po 'più di contesto? Non è chiaro quale sia lo scenario. Io vado a indovinare che si sta parlando di oggetti che sono gestiti da un sistema di ORM (come Hibernate) e che da "mini-class" si intende un proxy-oggetto lazy-carico.
Darien,


Aggiunta come commento qui (fino a quando non avrò abbastanza contesto per espandermi in una risposta completa): a meno che non si stiano codificando i valori ID nel codice (un grande no-no), sarà comunque necessario caricare i valori ID da qualche parte giusto? "Il più delle volte" è anche piuttosto vago IMHO ...
hjk,

@hjk Aggiunto qualche altro contesto, grazie. Hai un punto: devi ancora caricare i valori ID da qualche parte. Tuttavia, non si tratta di non "toccare" il DB, ma di ridurre al minimo l'utilizzo e la larghezza di banda al DB. Posso ottenere id di tutti coloro che vogliono prendere in prestito un libro, ma in realtà ottenere i loro dettagli completi sarebbe inutile.
0

Sembra che dipenderebbe da diverse cose: (1) se i casi d'uso richiedono gli attributi effettivi (colonne) o solo l'ID, che dipende dai casi d'uso stessi; (2) se si utilizzano tecniche di memorizzazione nella cache o di miglioramento delle prestazioni che renderebbero la query da ID a attributi senza sforzo e se i casi d'uso sarebbero abbastanza pesanti da interrompere tali schemi di memorizzazione nella cache.
rwong,

Risposte:


8

A seconda dell'ambiente e del contesto del problema, la necessità di accedere al database può essere mitigata e, di conseguenza (IMO), si perde l'argomento per utilizzare solo l'id.

Ad esempio, Doctrine2 ORM di PHP ha EntityManager::getReferenceun proxy che carica pigramente su un'entità usando l'id fornito; Non so quanti altri ORM lo facciano, ma corrisponde all'incirca alla nozione di "mini-classe" di cui parli. Per la maggior parte degli scopi, questa è un'entità completamente idratata, quindi puoi passarla in giro e usarla come qualsiasi altra.

L'unico caso in cui non lo è è quando viene fornito un ID non valido, e in quel caso dovresti comunque andare al database per convalidare; inoltre, per ridurre i costi di acquisizione di entità, la maggior parte degli ORM ha funzionalità di memorizzazione nella cache (di primo e secondo livello) disponibili in qualche forma.

Una volta che abbiamo ridotto la necessità e il costo di andare al database, siamo rimasti in gran parte con i professionisti dell'utilizzo dell'entità come parametro:

  1. Digitare sicurezza.
  2. Meno conoscenza richiesta dal chiamante. Uno sviluppatore di 6 mesi lungo la linea non può passare erroneamente nell'ID dell'entità sbagliata.
  3. Riduzione dei costi di refactoring. Se un metodo dovesse cambiare per richiedere 2 informazioni dall'entità, non vi è alcun costo nel cambiare il chiamante per fornirlo, presumendo che il chiamante abbia l'entità completamente idratata per cominciare.
  4. Meno convalida richiesta per metodo. Molti metodi possono presumere che l'entità che viene loro data esiste nel database (perché proviene dall'ORM) e quindi non è più necessario convalidare l'id.
  5. (Potenzialmente) meno chiamate al database. Se stai passando gli ID a 3 metodi e ognuno deve convalidarlo o recuperare più dati sull'entità, questo è 3 volte il numero di chiamate al database di 1 metodo che recupera l'entità e 2 che vi operano.

Certo, ci sono casi in cui si potrebbe desiderare di passare solo un ID: ad esempio quando si attraversa un confine di contesto limitato (nella progettazione guidata dal dominio si parla). Se consideriamo due contesti limitati con nozioni diverse di ciò che costituisce un account (ad es. Relazioni finanziarie e relazioni con i clienti), allora non possiamo passare l'account del contesto A al contesto B. Al contrario, un ID account (nella lingua del dominio) può essere attraversato.


La memorizzazione nella cache non si ridimensionerebbe bene con più istanze di applicazione in esecuzione. Ho la mia cache in atto. I punti sono eccellenti comunque.
0

Suppongo che un altro punto contro gli ID sia che l'uso dell'ID implica la chiamata persistenza oltre alla convalida, per ottenere effettivamente anche l'oggetto.
0

3

Per questo tipo di domanda, delego a qualunque soluzione comunichi meglio il mio intento di programmatore e faciliti il ​​lavoro di "Future Greg".

L'uso dell'oggetto come argomento rende più semplice ottenere la chiamata del metodo tra 6 mesi e ho dimenticato i dettagli grintosi di questa applicazione. Per costruire il tuo "è questo libro nell'esempio della lista dei desideri di questa persona", diciamo che il isInWishListmetodo deve solo confrontare gli ID interi di libri e membri. In realtà, questo metodo richiede solo due parti di dati per fare il suo lavoro. Ora facciamo un passo indietro rispetto a questo metodo e osserviamo l'intero sistema software. Dubito che per funzionare sia necessario solo un ID libro e un ID membro. Tirerai comunque l'intero libro e il membro dal database prima ancora di chiamare il isInWishListperché è probabile che dovrai fare qualcosa di più che chiamare questo metodo. Forse lo fai, ma la maggior parte delle volte dovrai fare di più.

Detto questo, non realisticamente incorrerai in una penalità prestazionale recuperando e mappando entrambi gli oggetti per intero dal database. Teoricamente avrai bisogno di meno chiamate al database, ma troverai in pratica che questo non è vero. Se passi questi ID come parametri nella stringa di query al server, allora sì, dovrai solo recuperare la lista dei desideri dal database. Ma questa è una visione molto ristretta dell'intera applicazione. Ci saranno scenari quando si eseguono altre operazioni oltre a controllare una lista dei desideri, ad esempio aggiungendo un libro a una lista dei desideri. Non vuoi aggiungere elementi duplicati.

Scegli la soluzione più semplice da comprendere per un nuovo programmatore, o per il tuo Sé futuro, che consiste nel far passare gli oggetti Booke Member. Solo dopo aver trovato un vero problema di prestazioni dovresti davvero preoccuparti solo di passare gli ID.

Oppure, potremmo ricordare che linguaggi tipicamente statici come Java offrono un sovraccarico del metodo, quindi puoi avere la tua torta e mangiarla anche:

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

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

La vera risposta a questa domanda è scrivere entrambi i metodi, chiamare la versione a numero intero dalla versione fortemente tipizzata e Bob è tuo zio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.