2010-01-20 9 views
7

Dans un projet de serveur Web avec un modèle de domaine riche (la logique d'application est dans le modèle, pas dans les services), comment gérez-vous l'injection des dépendances dans les objets du modèle? Quelles sont vos expériences?Comment gérer l'injection de dépendances dans les modèles de domaine riche?

Utilisez-vous un certain type d'AOP? Comme Springs @ Annotation configurable? Temps de chargement ou temps de construction? Problèmes que vous avez rencontrés?

Utilisez-vous l'injection manuelle? Alors comment gérez-vous différents scénarios d'instanciation (création des objets à travers une bibliothèque [comme Hibernate], création d'objets avec "nouveau" ...)? Ou utilisez-vous une autre manière d'injecter les dépendances?

+0

http://stackoverflow.com/questions/2091749/domain-driven-design-and-transactions-in-spring-environment – Bozho

Répondre

2

Pour garder les objets de mon domaine propres, j'évite d'utiliser l'injection sur les objets entities/aggregats/Value et je préfère les placer dans les services ou les dépôts si nécessaire. Pour cela, nous avons utilisé l'injection du constructeur de Spring pour faciliter les tests.

Si vous avez besoin d'injecter quelque chose dans vos entités, une suggestion pourrait être d'écrire un constructeur ou une usine et d'y injecter ce dont vous avez besoin.

4

Nous utilisons Spring @Configurable (avec un nouvel opérateur régulier) qui fonctionne comme un charme. Plus de anemic domain models. Enfin, c'est beaucoup plus la conception orientée objet, n'est-ce pas:

Person person = new Person(firstname, lastname); 
// weird 
peopleService.save(person); 
// good (save is @Transactional) 
person.save(); 

Mail mail = new Mail(to, subject, body); 
// weird 
mailService.send(mail); 
// good (send is @Transactional) 
mail.send(); 

Cependant, nous n'avons fait aucune comparaison de performance. Jusqu'à présent, nous n'avons tout simplement pas ressenti le besoin de le faire.

EDIT: voilà comment la classe personne ressemblerait à ceci:

@Configurable("person") 
public class Person { 
    private IPersonDAO _personDAO; 
    private String _firstname; 
    private String _lastname; 

    // SNIP: some constructors, getters and setters 

    @Transactional(rollbackFor = DataAccessException.class) 
    public void save() { 
     _personDAO.save(this); 
    } 

    @Transactional(readOnly = true) 
    public List<Role> searchRoles(Company company) void{ 
     return _personDAO.searchRoles(this, company); 
    } 

    // it's getting more interesting for more complex methods 
    @Transactional(rollbackFor = DataAccessException.class) 
    public void resignAllRoles(Company company) { 
     for (Role role : searchRoles(company)) { 
      role.resign(); 
     } 
    } 
} 

// the implementation now looks like this 
personService.getPerson(id).resignAllRoles(company); 

// instead of this 
roleService.resignAll(personService.searchRoles(personService.getPerson(id), company)); 

Et c'est la configuration Spring:

<context:spring-configured /> 
<bean id="person" class="org.example.model.Person" lazy-init="true"> 
    <property name="personDAO" ref="personDAO" /> 
</bean> 

Note: comme vous le voyez, il y a des services toujours là, par exemple pour rechercher des objets (personService.getPerson (id)) mais toutes les méthodes qui opèrent sur un objet passé (par exemple une personne) sont déplacées vers cette classe elle-même (c'est-à-dire person.save() au lieu de personService.save (personne)). La méthode reste la même et fonctionne avec n'importe quelle couche d'accès aux données sous-jacente (JDBC pur, Hibernate, JPA, ...). Il a simplement déménagé là où il appartient.

+0

Comment vous persistez vos entités? JDBC ordinaire? Parce que cette stratégie ne fonctionnerait pas si vous utilisez Hibernate !? – Arne

+0

@Arne bien sûr que ce serait. voir mon edit pour un exemple. l'idée est que vous injectez simplement le DAO dans les objets du domaine. Les méthodes sont ensuite déplacées des services vers la classe (généralement toutes les méthodes qui prennent un objet de cette classe en argument). Tout le reste demeure inchangé. – sfussenegger

+0

Mais que se passe-t-il si vous avez déjà personId (par exemple si vous modifiez une personne)? Ensuite, vous pouvez faire quelque chose comme 'personService.getPerson (personId) .resignAllRoles (société);' ou 'roleService.resignAll (personService.searchRoles (personId, société));' Le premier fera probablement une requête supplémentaire inutile pour obtenir le objet personne. –

0

Vous pouvez également consulter le lien ci-dessous, qui peut aider beaucoup. Une vue pragmatique sur l'architecture logicielle et le modèle de domaine enrichi décrit où le modèle de domaine enrichi et l'architecture logicielle se rencontrent.

En outre, il décrit comment configurer, mettre en œuvre et JUnit ce point de vue des techniques suivantes, des cadres et des API:

  1. printemps; pour faciliter la vie d'un développeur
  2. JPA; pour le mappage relationnel d'objet
  3. AspectJ; pour expérimenter pleinement le modèle de domaine riche
  4. JUnit; pour les tests d'intégration de votre modèle de domaine riche

http://www.ruimtefotografie.org/forum/viewtopic.php?f=32&t=193