Comme son nom l'indique, le développement axé sur le domaine n'est pas seulement un modèle de mise en œuvre, mais une méthode de développement qui implique des membres autres que le personnel de développement.
Dans la conception du développement piloté par domaine, le logiciel est conçu dans les trois couches suivantes.
--Couche d'application --Couche de domaine
Pourquoi faites-vous une telle division? Soudainement, le développement de la version de l'application mobile peut démarrer, et soudainement la base de données peut ne plus être un RDB. Dans un tel cas, ce qui peut être réutilisé entre des logiciels du même domaine est la connaissance du domaine, et ce qui inclut cela, c'est la couche de domaine.
** Couche d'application **
--Fonction principale
** Couche de domaine **
--Service de domaine --Entité
** Couche infrastructure **
--Dépôt
Vous pouvez voir que la classe d'implémentation du référentiel est la couche d'infrastructure. Mais pourquoi l'interface est-elle une couche de domaine? En effet, si une interface est une couche d'infrastructure, l'implémentation de la couche de domaine qui l'appelle dépendra inévitablement de la couche d'infrastructure. En d'autres termes, vous ne pourrez pas sélectionner la bibliothèque d'infrastructure à utiliser.
Il a expliqué que l'interface du référentiel est placée dans la couche domaine afin que la couche domaine ne dépende pas de la couche infrastructure. Alors, où initialisez-vous une instance du référentiel contenant des connaissances d'implémentation? En pensant simplement, il semble qu'il n'y ait pas d'autre choix que de l'initialiser au niveau de la couche application et de le propager au service de domaine. Cependant, si vous utilisez Spring DI et déclarez une classe d'implémentation en tant que composant qui hérite de la classe et de l'interface du service de domaine, Spring DI résoudra ce problème. Il n'est pas nécessaire de préparer un modèle Factory ou ʻApplicationContextAware`.
@Repository
public class Repository extends IRepository {
...
}
Utilisez le constructeur @ Autowired
au lieu du champ @ Autowired
pour résoudre la dépendance. Cela facilite la rédaction de tests unitaires.
Il peut être écrit plus facilement avec @ RequiredArgsConstructor
de Lombok.
@Service
@RequiredArgsConstructor
public class Service {
private final IRepository repository;
}
IRepository mockRespository = new MockRepository();
var service = new Service(mockRespotory);
J'ai écrit que le logiciel a été conçu en trois couches, mais le module Maven doit-il également être divisé en trois couches? Si le logiciel est unique, il suffit de le diviser en packages.
Au contraire, lors de la division du module, préparez un module parent
/pom.xml
<modules>
<module>./web</module>
<module>./mobile</module>
<module>./domain</module>
<module>./infrastructure</module>
</modules>
Comme
/application/pom.xml
<parent>
<groupId>me.yong_ju.application</groupId>
<artifactId>parent</artifactId>
<version>...</version>
<relativePath>../</relativePath>
</parent>
...
<dependencies>
<dependency>
<groupId>me.yong_ju.application</groupId>
<artifactId>domain</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>me.yong_ju.application</groupId>
<artifactId>infrastructure</artifactId>
<version>...</version>
</dependency>
</dependencies>
Tu peux le faire. En définissant d'abord le module enfant dans le module parent, lorsque ce module est ajouté à la dépendance, il sera récupéré localement au lieu de dans le référentiel Maven. (Cependant, les versions doivent correspondre)
Si vous divisez le package en trois couches, vous rencontrerez immédiatement un problème.
C'est parce que nous mettons @ SpringBootApplication
dans le package d'application, de sorte que l'analyse des composants de Spring n'injecte que les composants de la couche application.
Que faire. Vous pouvez utiliser scanBasePackages
pour modifier les paquets que vous souhaitez numériser vers la couche supérieure, mais nous ne le recommandons pas.
Ici, nous avons décidé de préparer une classe de configuration avec l'analyse des composants activée dans la couche de domaine et la couche d'infrastructure, et explicitement @ Importer
la configuration utilisée par l'application.
@Configuration
@ComponentScan
public class DomainConfiguration {
...
}
@Configuration
@ComponentScan
public class InfrastructureConfiguration {
...
}
@SpringBootApplication
@Import({ DomainConfiguration.class, InfrastructureConfiguration.class })
public class Application {
...
}
Un modèle dans lequel un service que vous voyez souvent est devenu simplement un wrapper pour le référentiel. Il doit être entretenu dans des unités opérationnelles significatives, et s'il n'est pas encore connu, il est encore plus rapide de le transformer en service. (En relation avec cela, je vois souvent des modèles qui ont été «@ transactionnels» dans une unité d'opération complètement dénuée de sens.)
Je pense personnellement que les modèles de mise en œuvre sont généralement un outil pour arrêter la réflexion tout en évitant les erreurs de conception fatales dans le développement de logiciels avec de mauvaises perspectives de planification. Par conséquent, perdre du temps à errer à la recherche des meilleures pratiques pour quoi que ce soit est un gâchis. Et Java et ses frameworks périphériques sont en constante évolution. Dans certains cas, ils peuvent être utilisés pour une mise en œuvre moins redondante et plus sûre.
Si j'ai du temps libre, je me concentrerai sur ce que j'ai mis du temps à comprendre.
Recommended Posts