Questa domanda è, nella sua essenza, una domanda di progettazione. Userò un esempio EE Java/Java per illustrare la domanda.Design: quando la linea tra oggetti dominio e oggetti servizio non è chiara
Si consideri un'applicazione di posta elettronica creata utilizzando JPA per la persistenza e EJB per il livello di servizi. Diciamo che abbiamo un metodo di servizio nel nostro EJB come questo:
public void incomingMail(String destination, Message message) {
Mailbox mb = findMailBox(destination); // who cares how this works
mb.addMessage(message);
}
Questo è apparentemente un metodo di business ragionevole. Presumibilmente, l'oggetto Mailbox verrà comunque collegato e ripristinerà senza problemi le modifiche sul database. Dopotutto, questa è la promessa di una persistenza trasparente.
l'oggetto cassetta postale avrebbe questo metodo:
public void addMessage(Message message) {
messages.add(message);
}
Ecco dove diventa complicato - supponiamo che vogliamo avere altri tipi di cassette postali. Supponiamo di avere una casella di risposta automatica che risponda automaticamente al mittente e un HelpDeskMailbox che apra automaticamente un ticket helpdesk con ogni email ricevuta.
La cosa più naturale da fare sarebbe quella di estendere la Posta elettronica, in cui AutoRespondingMailbox ha questo metodo:
public void addMessage(Message message) {
String response = getAutoResponse();
// do something magic here to send the response automatically
}
Il problema è che il nostro oggetto maibox ed è sottoclassi sono "oggetti di dominio" (e in questo esempio, anche Entità JPA). I ragazzi di Hibernate (e molti altri) predicano un modello di dominio non dipendente, ovvero un modello di dominio che non dipende dai servizi forniti dal contenitore/runtime. Il problema con questo modello è che il metodo AutoRespndingMailbox.addMessage() non può inviare un messaggio di posta elettronica perché non può accedere, ad esempio, a JavaMail.
Lo stesso problema si verificava con HelpDeskMailbox, poiché non poteva accedere ai servizi Web o all'iniezione JNDI per comunicare con il sistema HelpDesk.
Così si è costretti a mettere questa funzionalità nel livello di servizio, come questo:
public void incomingMail(String destination, Message message) {
Mailbox mb = findMailBox(destination); // who cares how this works
if (mb instanceof AutoRespondingMailbox) {
String response = ((AutoRespondingMailbox)mb).getAutoResponse();
// now we can access the container services to send the mail
} else if (mb instanceof HelpDeskMailbox) {
// ...
} else {
mb.addMessage(message);
}
}
dover utilizzare instanceof in questo modo è il primo segno di un problema. La modifica di questa classe di servizio ogni volta che si desidera creare una sottoclasse di cassette postali è un altro segno di un problema.
Qualcuno ha le migliori pratiche su come vengono gestite queste situazioni? Alcuni direbbero che l'oggetto Mailbox dovrebbe avere accesso ai servizi del contenitore, e questo può essere fatto con qualche confusione, ma sta sicuramente combattendo l'uso previsto di JPA per farlo, poiché il contenitore fornisce l'iniezione delle dipendenze ovunque tranne che nelle Entità, indicando chiaramente che questo non è un caso d'uso previsto.
Quindi, cosa dovremmo fare invece? Litigare i nostri metodi di servizio e il polimorfismo di rinuncia? I nostri oggetti vengono automaticamente relegati a strutture in stile C e perdiamo la maggior parte del vantaggio di OO.
Il team di Hibernate direbbe che dovremmo dividere la nostra logica di business tra il livello di dominio e il livello di servizio, mettendo tutta la logica che non dipende dal contenitore nelle entità di dominio e mettendo tutta la logica che dipende da il contenitore nel livello di servizi. Posso accettarlo, se qualcuno può darmi un esempio di come farlo senza dover rinunciare completamente al polimorfismo e ricorrere a instanceof e ad altri tali cattiveria
Penso che tu abbia perso l'intento della mia domanda. Dimentica le specifiche dell'esempio e presume che alcune sottoclassi di un determinato comportamento di Entity si basino su alcuni servizi forniti dal contenitore. – TTar
Sono d'accordo con questo. Il problema è che il tuo oggetto dominio non è più un semplice titolare di dati, ma ora hai un comportamento collegato (con impatti sulla persistenza) ad esso. Personalmente questo sembra qualcosa che dovrebbe essere gestito a livello di servizio. –
Quindi, se un oggetto dominio è un semplice titolare di dati, il mio oggetto dominio non è solo una struttura? Non è la definizione di progettazione orientata agli oggetti che i dati e il comportamento sono combinati in oggetti? – TTar