2015-10-12 11 views
6

Ho iniziato ad imparare scala per un po 'ora e ora guardando il modello di torta. Ho avuto l'esempio dalla hereimportanza del modello di torta in scala

trait UserRepositoryComponent { 
    def userLocator: UserLocator 

    trait UserLocator { 
    def findAll: List[User] 
    } 
} 

trait UserRepositoryJPAComponent extends UserRepositoryComponent { 
    val em: EntityManager 

    def userLocator = new UserLocatorJPA(em) 

    class UserLocatorJPA(val em: EntityManager) extends UserLocator { 
    def findAll = { 
     println("Executing a JPA query") 
     List(new User, new User) 
    } 
    } 
} 

trait UserServiceComponent { 
    def userService: UserService 

    trait UserService { 
    def findAll: List[User] 
    } 
} 

trait DefaultUserServiceComponent extends UserServiceComponent { 
    this: UserRepositoryComponent => 

    def userService = new DefaultUserService 

    class DefaultUserService extends UserService { 
    def findAll = userLocator.findAll 
    } 
} 

A me sembra che troppi codice standard per ottenere il repository APP iniettato al servizio.

Tuttavia questo codice farebbe lo stesso con molto minore numero di linee

trait UserRepository { 
    def findAll 
} 

trait JPAUserRepository extends UserRepository { 
    val em: EntityManager 
    def findAll = { 
    em.createQuery 
    println("find using JPA") 
    } 
} 

trait MyService { 
    def findAll 
} 

trait MyDefaultService extends MyService { 
    this: UserRepository=> 
} 

Istanziare entrambi gli scenari.

val t1 = new DefaultUserServiceComponent with UserRepositoryJPAComponent { 
    val em = new EntityManager() 
} 
t1.userService.findAll 


val t2 = new MyDefaultService with JPAUserRepository { 
    val em = new EntityManager 
} 

t2.findAll 

Secondo scenario utilizza molto meno codice e utilizza DI. Puoi aiutarmi a capire quali sono i vantaggi extra del modello di torta.

+0

Come dice @Archeg, il tuo secondo esempio è anche una variante del modello di torta. –

risposta

2

A quanto mi risulta, non c'è molta differenza. In realtà il motivo della torta è IoC. È solo l'idea di implementare IoC e DI, senza il framework DI separato, ma solo con il codice scala. Probabilmente dovresti preferirlo a un contenitore separato DI a meno che tu non abbia bisogno di più funzionalità.

Inoltre, mi sembra che entrambi i vostri esempi siano modelli di torta. Almeno è così che lo capisco. Ma Martin non l'ha chiamato "schema di torta" nel suo libro, e baso la mia conoscenza di scala mosly su un singolo libro, quindi potrei perdere qualcosa. La mia comprensione è che modello torta è un'idea che unisce tratti differenti per raggiungere DI

Penso Martin espressamente menzionato nel suo libro, che è bene utilizzare DI -containers come la primavera in scala, ma purtroppo non riesce a trovare questo posto

Aggiornamento

trovato: http://www.artima.com/pins1ed/modular-programming-using-objects.html Vedi ultimo comma 27.1 The problem. Ma come ho detto, che non sta parlando di "torte" qui, anche se l'idea sembra la stessa dall'articolo hai dato

Update 2

Ho appena riletto la mia risposta e capito che ho bisogno per migliorarlo, in quanto non risponde completamente alla domanda.

Si dovrebbe preferire "modello di torta", perché è più semplice.Se usi Spring, devi mantenere la configurazione, che si tratti di XML o annotazioni, potresti anche avere dei requisiti sulle tue classi (non ho usato Spring, quindi non sono sicuro se ce ne sono), e tu hai per portare tutta la primavera con te Con lo schema a torta basta scrivere codice tanto semplice (il tuo secondo esempio è semplice, dovresti essere d'accordo). La cosa bella di scala è che puoi fare un sacco di cose con esso, e usare solo pochi framework - se lo paragoni a java, - di solito usi molte più librerie esterne

Se hai bisogno di più funzionalità avanzate, come proxy - puoi passare a Spring, o continuare a usare Scala e risolvere i tuoi problemi con la lingua stessa, speriamo che scala sia estremamente potente e che copra anche casi complicati.

La differenza tra due pezzi di codice forniti è solo un'astrazione: la prima ha un'astrazione in più rispetto alle operazioni definite nel repository e nel servizio e queste non fanno parte del modello. Non credo che sia necessario, ma l'autore ha deciso di mostrarlo in questo modo.

2

Ciò che il modello di torta offre rispetto a un tipo di sistema di iniezione di codice IoC è che al momento della compilazione si ha una dipendenza esplicita dall'implementazione che si utilizzerà rispetto a un set che prevede controlli di runtime contro un gruppo di file XML o annotazioni. Vale a dire, la distinzione è tempo di compilazione vs runtime.

In fase di test, è possibile inserire in mock impls e semplicemente mescolarli. In produzione, è possibile utilizzare i "reali" impli e semplicemente mescolare quelli in. Il compilatore ti dirà quando hai fatto qualcosa di sbagliato.

(La realtà è molto più complessa, come si può ottenere problemi di puntatore nullo e vari tipi di non-determinismo se miscelazione e la congruenza oggetti statici.)

+0

L'IoC non riguarda l'XML in alcun modo. Di solito è possibile impostare dipendenze nel codice in fase di compilazione, e personalmente lo preferisco in questo modo. È ancora IoC – Archeg

+0

@Archeg La mia risposta è colorata dalle mie esperienze con Spring e altre soluzioni IoC simili che coinvolgono grandi quantità di file di configurazione XML. – wheaties

+0

Il secondo metodo consente anche di combinare entrambe le implementazioni di simulazione/reale. Il compilatore contrassegna gli errori se provi a mescolare tipi sbagliati. Ancora non vedo il vantaggio che Cake offre per tutto quel codice extra. –

1

Nel secondo esempio si utilizza solo l'implementazione findAll di . Ma, in fondo, il problema del secondo approccio, a mio parere è che si espone api tramite interfaccia business che non deve essere esposto (aka UserRepositor api should't essere esposto quando si utilizza oggetto di Service tipo t2)

Infatti modello torta introduce un po 'più di codice di quello che puoi scrivere usando un framework IoC. Ma puoi anche strutturare il tuo codice in modo leggermente diverso. Ad esempio, scrivendo componente componente non per alcuni servizi, ma per gruppo di servizi logicamente correlati. Ad esempio, tutti i tipi di servizi di deposito possono risiedere in RespositoryComponent e tutti i tipi di servizi aziendali possono risiedere in BusinessLogicComponent). Per fare un confronto con la primavera, l'idea è che il tratto di implementazione di quel componente è la stessa decalrazione XML dei fagioli.

Per utilizzare primavera come DI nella scala vi consiglio di guardare MacWire

+0

Grazie Sono d'accordo. Credo che i moduli siano la chiave. Non è solo DI. Cake consente di creare moduli e moduli possono ereditarsi a vicenda. Le annotazioni self-type consentono ai moduli di associarsi. Sto leggendo i moduli e ci sono discussioni molto interessanti su questo. –

Problemi correlati