Domanda

mi viene da pensare se ho davvero bisogno di un livello di servizio.

sto usando primavera + hibernate per un'applicazione desktop swing e in questo momento ho gui / oscillare Layer-> servizio Layer-> dao strato. Io uso la primavera solo per il supporto @Transactional e per IOC-iniezione

Best diciamo pratica che devo scrivere un servizio di usare le mie Tao, e mettere tutte le operazioni di gestione nel servizio.

Ma mi rendo conto che molto spesso, livello di servizio solo metodi Dao replicati, così per esempio:

// a DAO example
@Repository
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO {

 public List<Customer> findAllCustomerILikeName(String name){
  return getSession()
   .createCriteria(Customer.class)
   .add(Restriction.ilike("name", name))
   .list();
 }
}

// Customer service to use this dao...
@Service
@Transactional
public class CustomerService {

 @Autowired
 CustomerDAO customerDAO;

 // Why i can't call DAO instead the service?
 public List<Customer> getAllCustomersByName(String name){
      return customerDAO.findAllCustomerILikeName(name);
 }

}

Questa è una miniera utilizzo tipico del livello di servizio ... Hibernate è db-agnostico, la primavera sono tecnologia-agnostic:? Così, ho davvero bisogno

Che dire di una classe di servizio unico per gestire tutte DAO ?? Penso che questo possa essere un buon compromesso, o, è una cattiva pratica?

So messo @Transactional su DAO è un brutto modo, ma in questo momento devo servizi di scrittura solo per mettere @Transactional su di esso ...

Modifica

Ulteriori informazioni su mia app.

La mia domanda è un software di gestione e gestire la registrazione degli utenti, i prodotti, l'ordine e altre cose come quelle. In pratica contiene un sacco di lettura entity> Modifica-> Salva entità o Create-> Modifica-> le operazioni di salvataggio, e, grazie per il letargo, queste operazioni sono gestiti da uno dao maggior parte del tempo, siccome Hibernate con @manyto. .. raccolta e cascade.save_update permette di risparmiare due o più entità nella stessa persistono operazione.

Così, per esempio, nei miei articoli JFrame dove posso inserire, modificare o creare un elemento (un prodotto da vendere) ci sono:

public ItemFrame(){
 // the constructor
 itemService=springAppContext.getBeans(ItemService.class);
}

public boolean validateForm(){
 // test if the gui is correctly filled by user
}

public boolean save(){
 // create an Item entity taking value from swing gui(JTextField etc)
 Item item=new Item();
 item.setName(nameTextField.getText());
 item.setEtc...
 // ItemService ' save method is a wrap around itemDao.save(item)...
 itemService.save(item);
}

private void saveItemActionPerformed(ActionEvent evt){
 // When i press SAVE button
 if(validateForm()){
  save();
 }
}

Questo è quello che ho nella maggior parte dei casi, dunque io mi sono anemico-domain-antipattern ...

Grazie.

È stato utile?

Soluzione

Se il servizio duplicati strato DAO, non si utilizza livello di servizio a tutti. Ho fatto lo stesso errore in alcune delle mie applicazioni, mi chiedevo "perché gli sguardi livello di servizio così brutto, ed è DAO duplicationg" ...

Il livello di servizio dovrebbe essere l'interfaccia per il vostro appliacation, questo Doest media, che alcuni metodi non sono gli stessi in dao e nel servizio, ma la parte principale è significativamente differente. Non posso dire questo senza visualizzare il resto del codice, ma per la tua domanda (che è quasi lo stesso come lo erano le mie domande pochi mesi fa), mi sembra, che si sta utilizzando modello di dominio anemico antipattern . Nel modello di dominio anemico, il vostro modello contiene solo campi e getter, esistono metodi reali (di comportamento), che viola i principi oggetto fondamentale orientati (oggetto == dati + comportamento) ... il tuo comportamento è probabilmente in qualcosa che assomiglia di script di transazione in servizio strato, ma dovrebbe essere nel modello (strato di dominio).

La via d'uscita è di utilizzare ricco modello di dominio (fagioli iniettati per via del modello @Configurable). Si può dire, che questo viola il modello livelli e si sarà probabilmente corretto. Ma io sono convinto, che dovremmo pensare la nostra applicazione (dominio + dao + servizi) come un singolo componente (vedere Alistair Cockburn esagonali architettura / Porte e adattatori ).

Il suo cliente altalena app / web sarà quindi un client per il componente di base, è quindi possibile passare senza alcuna limitazione (beacause tutto ciò che i dati modiefies è in core).

Ma v'è una limitazione / svantaggio di questo approccio. Se si intende utilizzare un qualche tipo di sicurezza (sicurezza primavera) o record attivi tramite Hibernate, di quanto deve comunicare con tutti i clienti tramite DTO (non i si entità), perché quando un'entità contatto, si può chiamare il servizio, che sarà attiva stessa via transazionale e in grado di modificare il database (by-pass la sicurezza).

Mi auguro, che ho indovinato la propria architettura, se non, mi dispiace per aver inventato la ruota qui, ma questo post può aiutare qualcuno che non sa questo (come ero pochi falene fa).

Modifica

per la modifica: Anche nella semplice applicazione CRUD, un qualche tipo di azioni dovrebbe essere in livello di servizio - ad esempio la convalida (non la convalida "questo è un numero", ma alcuni di convalida specifica attività). Questo shouldn essere nella vostra vista, perché se si cambia, si avrà copia & incolla di nuovo. Quando si guarda il codice, si dovrebbe chiedere un qeusting "se decido di scrivere thin client (vista nel browser web)", c'è qualche codice, che avrò da copiare? Se la risposta è SI, che si dovrebbe creare un metodo di servizio per questa chiamata possibilmente a distanza.

L'altra cosa che si dovrebbe / può fare su livello di servizio è Autorization (è l'utente in questo ruolo permited per eliminare questa voce). Che si dovrà avere un livello di servizio per quasi tutte le entità, perché semplice utente dovrebbe essere in grado di modificare (eliminare) le sue voci, ma probabilmente non dovrebbe cancellare altri utenti. Ma l'utente nel ruolo di amministratore può fare questo.

Esempio di codice (parte dell'interfaccia articolo servizio nella mia app (sicurezza primavera)):

@Secured("ROLE_EDITOR")
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails);

Nel commentare il servizio tutti possono salvare i loro commenti agli articoli ....

E un'ultima nota: probabilmente si dovrebbe prendere in considerazione, se si necessità servizio di livello a tutti. Quando il suo scritto in un bel modo, la vostra applicazione guadagnerà molte qualità nella sua flessibilità, la riusabilità e manutenibilità. Ma è piuttosto difficile e richiede tempo per scriverlo. Se non volete fare questo tutta questa roba (sicurezza, ricco modello di dominio, chiamando da più interfacce (cambiando vista implementazione)), si può vivere senza di essa: -)

Altri suggerimenti

A un certo punto, l'applicazione vorrà un po 'di logica di business. Inoltre, si potrebbe desiderare di convalidare l'input per assicurarsi che non ci sia qualcosa di male o di non performing dalla richiesta. Questa logica appartiene nel vostro livello di servizio.

Inoltre, può essere possibile per rendere il vostro DAO piuttosto generica, in modo da avere solo uno o due metodi che non cambiano molto. Questo riduce il rischio di fare qualcosa di terribilmente sbagliato per le vostre classi DAO ogni volta che si desidera aggiungere / modificare la funzionalità della app.

Il DAO è per i dati di accesso. Il servizio è per la logica di business. Tenerli separati e sarete più felici nel lungo periodo.

Alla fine, è necessario coordinare il comportamento tra più di DAO. Si può anche introdurre una certa complessità delle regole aziendali (es: non si aggiorna [questo], se [che] è in un particolare stato). Questo è dove il livello di servizio è molto utile.

Detto questo, non v'è "tecnicamente" sbagliato nulla con l'eliminazione il livello di servizio del tutto. Sarà solo un po 'più doloroso quando alla fine si decide che è necessario uno.

Invece di far rispettare

ui -> service -> DAO

per ogni operazione, in considerazione consentendo sia

ui -> DAO
ui -> service -> DAO

quest'ultima essendo usata per operazioni più complesse

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top