2010-01-20 4 views
7

In einem Web-Server-Projekt mit einem Rich-Domain-Modell (Anwendungslogik ist im Modell, nicht in den Services) Wie behandeln Sie die Abhängigkeiten in die Modellobjekte? Was sind deine Erfahrungen?Wie wird das Injizieren von Abhängigkeiten in Rich Domain-Modelle gehandhabt?

Verwenden Sie irgendeine Form von AOP? Wie Springs @Konfigurierbare Annotation? Ladezeit oder Bauzeit wowing? Probleme, denen Sie begegnet sind?

Verwenden Sie manuelle Injektion? Wie gehen Sie dann mit verschiedenen Instanziierungsszenarien um (Erstellen der Objekte über eine Bibliothek [wie Hibernate], Erstellen von Objekten mit "new" ...)?

Oder verwenden Sie eine andere Möglichkeit, die Abhängigkeiten zu injizieren?

+0

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

Antwort

2

Um meine Domain-Objekte sauber zu halten, vermeide ich es, die Entitäten/Aggregate/Wert-Objekte zu injektionieren und diese bei Bedarf in die Services oder Repositories zu legen.

Dafür verwendeten wir normale Spring Constructor-Injektion, um die Prüfung zu erleichtern.

Wenn Sie etwas in Ihre Entitäten injizieren müssen, könnte ein Vorschlag sein, einen Builder oder eine Fabrik zu schreiben und stattdessen das zu injizieren, was Sie dort benötigen.

4

Wir verwenden Spring @Configurable (zusammen mit regulären neuen Operator), die wie ein Charme funktioniert. Nicht mehr anemic domain models. Schließlich ist dies viel mehr objektorientierten Design, nicht wahr:

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(); 

Wir haben keinen Performance-Vergleich obwohl getan. Bislang haben wir das einfach nicht für nötig gehalten. Und das ist der Frühling Config

@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)); 

:

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

Hinweis:

EDIT: das ist, wie die Person Klasse aussehen würde, wie Sie sehen, gibt es Dienste noch um, zum Beispiel um nach Objekten zu suchen (personService.getPerson (id)), aber alle Methoden, die an einem übergebenen Objekt (z. B. einer Person) arbeiten, werden selbst in diese Klasse verschoben (d. h. person.save() anstelle von personService.save (person)). Die Methode selbst bleibt die gleiche und arbeitet mit jeder zugrunde liegenden Datenzugriffsebene (reine JDBC, Hibernate, JPA, ...). Es hat sich einfach dorthin bewegt, wo es hingehört.

+0

Wie beharren Sie Deine Entitäten? Einfaches JDBC? Weil diese Strategie nicht funktionieren würde, wenn Sie den Ruhezustand verwenden !? – Arne

+0

@Arne würde es natürlich. Sehen Sie meine Bearbeitung für ein Beispiel. Die Idee ist, dass Sie das DAO einfach in die Domänenobjekte injizieren. Methoden werden dann von Services in die Klasse verschoben (normalerweise alle Methoden, die ein Objekt dieser Klasse als Argument verwenden). Alles andere bleibt gleich. – sfussenegger

+0

Aber was ist, wenn Sie bereits personId haben (z. B. Sie bearbeiten eine Person)? Dann könnten Sie etwas wie 'personService.getPerson (personId) .resignAllRoles (Firma);' oder 'roleService.resignAll (personService.searchRoles (personId, Firma));' Der erste wird wahrscheinlich eine zusätzliche unnötige Abfrage, um die zu tun Personenobjekt. –

0

Sie können auch den unten stehenden Link überprüfen, der sehr hilfreich sein kann.

Eine pragmatische Sicht auf die Softwarearchitektur und das Rich-Domain-Modell beschreibt, wo sich das Rich-Domain-Modell und die Softwarearchitektur treffen.

Außerdem beschreibt es die Konfiguration, Implementierung und junit diese Ansicht mit folgenden Techniken, Frameworks und api:

  1. Frühling; einem Entwickler das Leben zu erleichtern
  2. JPA; für objektrelationales Mapping
  3. AspectJ; das Rich-Domain-Modell vollständig zu erleben
  4. JUnit; für Integrationstests von Rich Domain Model

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