Brevemente sobre dónde colocar el repositorio en Onion Architeckture y DDD


Hola Habr Quiero hablar sobre dónde, en la figura de arriba, poner el repositorio. Un poco más sobre DIP, IoC y la estructura del proyecto. Existe un enfoque estándar según el cual las interfaces IRepository deben interferirse en la capa de dominio para DomainServices y la implementación en Infraestructura. Aquí estamos hablando de repositorios estándar, que son solo una colección abstracta de objetos que no conoce las transacciones y UnitOfWork, etc. (por ejemplo, IList y su versión genérica son la interfaz típica de un repositorio abstracto). Personalmente, no estoy de acuerdo con él porque generalmente los repositorios están cubiertos de un comportamiento específico para una aplicación en particular, por lo que pongo sus interfaces en ApplicationServices. La implementación, por supuesto, permanece en la capa Infraestructura. Si estás interesado, entonces bienvenido a cat.

A menudo, muchos se confunden con la vieja foto de Robert Martin:

él tiene las palabras en el artículo
Las entidades encapsulan las reglas comerciales de toda la empresa. Una entidad puede ser un objeto con métodos, o puede ser un conjunto de estructuras y funciones de datos. No importa mientras las entidades puedan ser utilizadas por muchas aplicaciones diferentes en la empresa.

Por lo tanto, resulta que simplemente asigna DomainServices a la capa Entities. Bueno, UseCases == ApplicationServices. Gateways == UserPepository, EmailService, Logger. Lee más aquí .

  1. Serivice es cualquier clase sin estado. InfrastructureService es un laer anticorrupción que lo aísla del sistema de archivos, la biblioteca para trabajar con SMTP y, por supuesto, de ORM o la biblioteca para trabajar con la base de datos, etc.
  2. Repository . . List Repository T[] ValueObject Entities. Repository InfrastructureService InfrastructureService Repository. : Logger, EmailSender.
  3. Repository InfrastructureService - EmailSender EmailService, FileService ( File.Open(… ) . .) .


Para comprender dónde ubicar las abstracciones, debemos pensar en la Inversión de dependencia y la Inversión de control. Según ellos, nuestro ApplicationService puede usar Infraestructura, no sé cuál es su implementación de la siguiente manera:
  1. Defina la interfaz que implementará la Infraestructura e interactuará con ella.
  2. Solo acepte delegados como Action y Func.


A través de interfaces:

    interface IRepository
    {
        int Get();
    }

    class ApplicationService
    {
        private readonly IRepository _repository;

        public ApplicationService(IRepository repository)
        {
            _repository = repository;
        }

        public int GetInt() => _repository.Get();
    }

A través de delegados:

    class ApplicationService
    {
        private readonly Func<int> _getIntFromDb;

        public ApplicationService(Func<int> getIntFromDb)
        {
            _getIntFromDb = getIntFromDb;
        }

        public int GetInt() => _getIntFromDb();
    }

Ahora sobre cómo estructurar el código. Hay dos casos a considerar:
  1. Todo está dividido en carpetas.
  2. Todo está dividido en bibliotecas.

Los detalles de la terminología se pueden encontrar aquí .

Carpetas dentro de la misma aplicación


Ejemplo de código de SnakeGame


Por bibliotecas


Ponemos las interfaces InfrastructureServices (IRepository) en la biblioteca ApplicationServices y la implementación (Repository) en la biblioteca Infrastructure.



La imagen final del artículo es una persona con mucha más experiencia en desarrollo que la mía y que también piensa que IRepository debe colocarse en Application Layer to ApplicationServices (las implementaciones del repositorio también tienen infraestructura).


recomendaciones


La interfaz de servicios de infraestructura (IRepository, IEmailSender) se puede colocar en la biblioteca ApplicationServices.dll, y su implementación específica (Repository, EMailSender) en la biblioteca Infrastructure.dll.

All Articles