2012-01-19 16 views
25

Ho lavorato/visto alcuni progetti di applicazioni Web con sospensione letargica con tante interfacce quante sono le effettive classi di servizio e dao.Perché sempre le singole interfacce di implementazione sono disponibili nei livelli service e dao?

ho sempre pensato che questi due come le principali ragioni di queste singole interfacce di attuazione:

  1. molla può cablare attuazione effettiva come dipendenze in una determinata classe (accoppiamento lasco)

    public class Person { 
        @Autowired 
        private Address address; 
    
        @Autowired 
        private AccountDetail accountDetail; 
    
        public Person(Address address, AccountDetail accountDetail) 
        { // constructor 
    
  2. Durante il test delle unità, posso creare classi di simulazione e testare una classe in isolamento.

    Address mockedAddress = mock(Address); 
    AccountDetail mockedAccountDetail = mock(AccountDetail); 
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows 
    

Ma, negli ultimi tempi, mi sono reso conto che:

molla può collegare le classi di implementazione concreti come dipendenze:

public class Person { 

@Autowired 
private AddressImpl address; 

@Autowired 
private AccountDetailImpl accountDetail; 

public Person(AddressImpl address, AccountDetailImpl accountDetail) { 
// constructor 

quadri Mock come EasyMock possono deridere classi concrete, nonché

AddressImpl mockedAddress = mock(AddressImpl); 
AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl); 
Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
// unit test follows 

Inoltre, come nel caso della discussione this, penso che il riassunto sia che all'interno di una singola app, le interfacce sono per lo più sovrautilizzate probabilmente per convenzione o abitudine. In genere hanno senso nei casi in cui ci interfacciamo con un'altra applicazione, ad esempio slf4j utilizzata da molte app in tutto il mondo. All'interno di una singola app, una classe è quasi un'astrazione quanto un'interfaccia.

Quindi, la mia domanda è perché abbiamo ancora bisogno di interfacce e quindi abbiamo implementazioni singole come le classi * ServiceImpl e * DaoImpl e aumentano inutilmente le dimensioni della base del codice. C'è qualche problema nel prendere in giro lezioni concrete di cui non sono a conoscenza.

Ogni volta che ho discusso di questo con i miei compagni di squadra, la sola risposta che ottengo è che il servizio di implementazione e le lezioni dao basate su interfacce è IL PROGETTO che seguono tutti - citano le migliori pratiche di primavera, OOP, DDD ecc. ancora non si ottiene una ragione pragmatica per avere così tante interfacce all'interno di un'applicazione isolata.

+2

Per quanto riguarda le risposte ottenute, non riesco a vedere come si possa invocare il DDD come motivo per lanciare un'interfaccia davanti a ciascun oggetto. DDD non ha nulla a che fare con questo. Anche l'OOP è una scarsa giustificazione. Se prendi cose come la L, I e D di SOLID, specificano solo come dovresti progettare astrazioni come interfacce e cosa dovresti usarle, non che * dovresti usarle tutto il tempo *. Quindi, come hai detto tu, suppongo che tutto si riduca alla "best practice di primavera" o solo a persone che lo fanno per abitudine. – guillaume31

risposta

14

Ci sono altri vantaggi per le interfacce, come nel proxy. Se la tua classe implementa un'interfaccia, i proxy dinamici JDK verranno utilizzati di default per AOP. Se si utilizzano direttamente le implementazioni, si sarà costretti a utilizzare i proxy CGLIB rendendo proxy-target-class = true. Questi richiedono la manipolazione del codice byte a differenza dei proxy JDK.

leggi here per ulteriori informazioni.

Leggi un'altra discussione allo what reasons are there to use interfaces (Java EE or Spring and JPA) per ulteriori informazioni.

14

È un argomento molto controverso. In breve, non c'è nessuno, almeno per te, lo sviluppatore.

Nel mondo EJB2, le interfacce Home e Remote erano un must ed erano esattamente per un motivo @AravindA menziona: proxy. Sicurezza, servizi remoti, pooling, ecc. Tutti possono essere inclusi in un proxy e fornire i servizi richiesti rigorosamente all'interno della libreria standard (come in DynamicProxy).

Ora che abbiamo javaassist e cglib, Spring (Hibernate, EJB3 se si preferisce) sono perfettamente in grado di strumentare le classi come i mi piace degli sviluppatori di framework. Il problema è che quello che fanno è una cosa molto fastidiosa: di solito chiedono di aggiungere un costruttore senza parametri. -Attendere, avevo i parametri qui? -Normalmente, basta aggiungere il costruttore.

Quindi le interfacce sono qui per mantenere la vostra sanità mentale. Eppure, è strano, un costruttore senza argomenti per una classe con un costruttore appropriato non è qualcosa che ha senso per me, giusto? Risulta (avrei dovuto leggere le specifiche, lo so) che Spring crea un equivalente funzionale di un'interfaccia fuori dalla classe: un'istanza senza stato (o ignorata) e tutti i metodi sovrascritti. Quindi hai un'istanza "reale" e una "interfaccia falsa", e quale interfaccia fake fa, serve tutta la magia di sicurezza/transazionale/remoting per te. Bello, ma difficile da capire, e sembra un insetto se non lo hai smontato.

Inoltre, se ti capita di implementare un'interfaccia nella tua classe, (almeno alcune versioni di) Spring decide all'improvviso di voler utilizzare solo questa interfaccia, e l'applicazione non funziona per nessun motivo apparente.

Quindi, finora il motivo è, sicurezza e sanità mentale. Ci sono dei motivi per cui è una buona pratica, ma dal tuo post, vedo che hai già letto tutti questi. La ragione più importante che posso vedere oggi è la metrica WTH/minuto, specialmente se stiamo parlando di nuovi arrivati ​​al tuo progetto.

Problemi correlati