No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Arquitectura Cebolla

7/24
Recursos

Aportes 9

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Importante: el modelo de dominio solo depende de sí mismo, en ningún momento tiene dependencia hacia las capas.

  • Servicios de dominio: una capa más arriba. Aquí encontramos las interfaces de esos repositorios (base de datos) para acceder a los datos. Están definidas pero no implementadas.

  • Servicios de aplicación: una capa más arriba, donde se encuentran las operaciones específicas. Aquí no hay interfaces.

  • La capa externa: incluye las diferentes pruebas que queremos usar en nuestra aplicación, así como la interfaz gráfica y la infraestructura.

Se utiliza principalmente en el ecosistema .NET.

Onion Architecture 🧅 Fuente: dev.to

En Python, la arquitectura de software cebolla se puede implementar siguiendo estos elementos clave:

  1. Núcleo (Core): Es el centro de la aplicación y contiene las reglas de negocio y la lógica principal. En el núcleo, se definen las entidades, modelos de datos y la lógica que representa el comportamiento central de la aplicación. Esta capa no debe depender de ninguna otra capa y, por lo tanto, puede ser reutilizable e independiente.

  2. Capa de Aplicación (Application Layer): Esta capa actúa como intermediaria entre el núcleo y las capas externas, como la interfaz de usuario o servicios externos. Contiene los casos de uso de la aplicación y coordina las interacciones entre el núcleo y las capas externas. Aquí se implementan los servicios que serán expuestos a través de API o interfaz de línea de comandos.

  3. Capa de Infraestructura (Infrastructure Layer): Es la capa más externa y se encarga de interactuar con elementos externos, como bases de datos, servicios web, sistemas de archivos, etc. La capa de infraestructura proporciona implementaciones concretas de las interfaces definidas en las capas internas. Además, maneja detalles técnicos como el almacenamiento de datos y la comunicación con recursos externos.

En una implementación típica de Onion Architecture en Python, la estructura del proyecto se organizaría en directorios, donde cada capa tiene su propio espacio y las dependencias fluyen hacia adentro, siguiendo la lógica de la cebolla:

- app/
  - core/
    - entities/
    - use_cases/
  - application/
    - services/
  - infrastructure/
    - repositories/
    - external_services/
  - interfaces/
    - web/
    - cli/

Aquí, una breve descripción de cada directorio:

  • core: Contiene las entidades y los casos de uso principales de la aplicación.
  • application: Implementa los servicios de aplicación que orquestan la lógica de negocio.
  • infrastructure: Proporciona implementaciones concretas para interactuar con bases de datos, servicios externos, etc.
  • interfaces: Aquí se encuentran las interfaces de usuario o cualquier otra interfaz para interactuar con la aplicación. Puede haber subdirectorios específicos para las interfaces web o de línea de comandos, entre otros.

Es importante destacar que la estructura exacta puede variar según los requisitos y el tamaño del proyecto. La clave está en mantener una separación clara de responsabilidades y dependencias, permitiendo así una mayor flexibilidad y mantenibilidad del software.

Arquitectura Cebolla

Se compone de:

  1. Modelo de dominio: Es la capa que se encuentra más al interior de la cebolla. Se tienen las entidades que modela el problema y éstas no están relacionadas con la persistencia. Sólo tiene dependencia de sí mismo, nunca de las capas que lo están rodeando. Se denomina “modelo de objetos”, “capa de dominio” o “entidades de dominio”.
  2. Servicios de dominio: Contiene reglas del negocio, pero un elemento fundamental es que habrán interfaces que van a representar repositorios para acceder a los datos. Se van a definir las interfaces pero no se van a implementar. Se denomina “servicio de objetos” o “capa de repositorio”.
  3. Servicios de aplicación: Lógica de la aplicación puede estar repartida entre los servicios de aplicación y servicios de dominio. Se denomina “capa de servicios”.

Esto se denomina el núcleo del sistema.

  1. Capa externa: Rodea al núcleo del sistema y esa pueden estar:
  2. Pruebas: Unitarias, de integración y ayudar a testear que todo esté funcionando correctamente.
  3. Interfaz gráfica: Es algo que puede cambiar con el tiempo.
  4. Infraestructura: Se tienen elementos como acceder a un sistema de archivos, aplicaciones de terceros e integraciones varias.

Esta capa externa rodea al dominio.

Datos adicionales:

  • Propuesta por Jeffrey Palermo en 2008.
  • Arquitectura conocida principalmente en el ecosistema .NET.
Hola, no entendí nada :/
Cuando se habla de servicios de dominio en esta arq., se trata de lógica con código ejecutable o son interfaces, abstractos y tipos unicamente?
La \*\*arquitectura de cebolla\*\* (Onion Architecture) es un estilo de diseño de software que tiene como objetivo construir aplicaciones mantenibles y flexibles mediante la organización del código en capas concéntricas. En esta arquitectura, la \*\*lógica de negocio\*\* es el centro del diseño, y las dependencias fluyen hacia adentro, lo que significa que las capas más externas pueden depender de las capas más internas, pero no al revés. \### Componentes de la Arquitectura de Cebolla: 1\. \*\*Dominio\*\* (Core): \- \*\*Descripción\*\*: Es el núcleo de la aplicación y contiene la lógica de negocio más pura. Esta capa no tiene dependencias externas. Aquí se encuentran las entidades y los objetos de valor. \- \*\*Ejemplo en Python\*\*: ```python class Usuario: def \_\_init\_\_(self, id, nombre, email): self.id = id self.nombre = nombre self.email = email def cambiar\_email(self, nuevo\_email): \# Lógica de negocio para cambiar el email if "@" in nuevo\_email: self.email = nuevo\_email else: raise ValueError("Email inválido") ``` 2\. \*\*Servicios de Dominio\*\*: \- \*\*Descripción\*\*: Contiene la lógica de negocio que no encaja naturalmente dentro de una sola entidad. Es útil para operaciones que involucran múltiples entidades o reglas complejas. \- \*\*Ejemplo en Python\*\*: ```python class ServicioTransferenciaDinero: def transferir(self, cuenta\_origen, cuenta\_destino, monto): if cuenta\_origen.balance >= monto: cuenta\_origen.debit(monto) cuenta\_destino.credit(monto) else: raise ValueError("Fondos insuficientes") ``` 3\. \*\*Interfaces de Repositorio\*\*: \- \*\*Descripción\*\*: Define los contratos que deben cumplir las implementaciones de los repositorios. Los repositorios son responsables de abstraer el acceso a datos (por ejemplo, bases de datos) de la lógica de negocio. \- \*\*Ejemplo en Python\*\*: ```python from abc import ABC, abstractmethod class UsuarioRepositorio(ABC): @abstractmethod def obtener\_por\_id(self, id): pass @abstractmethod def guardar(self, usuario): pass ``` 4\. \*\*Aplicación (Application Layer)\*\*: \- \*\*Descripción\*\*: Contiene los casos de uso y las reglas de aplicación. Esta capa orquesta las interacciones entre el dominio y el mundo exterior (por ejemplo, UI, bases de datos). \- \*\*Ejemplo en Python\*\*: ```python class ServicioUsuario: def \_\_init\_\_(self, usuario\_repositorio): self.usuario\_repositorio = usuario\_repositorio def registrar\_usuario(self, nombre, email): usuario = Usuario(id=None, nombre=nombre, email=email) self.usuario\_repositorio.guardar(usuario) def cambiar\_email(self, id, nuevo\_email): usuario = self.usuario\_repositorio.obtener\_por\_id(id) usuario.cambiar\_email(nuevo\_email) self.usuario\_repositorio.guardar(usuario) ``` 5\. \*\*Interfaces de Entrada\*\*: \- \*\*Descripción\*\*: Define cómo los casos de uso son invocados desde el exterior. Puede incluir controladores de API, interfaces de usuario, etc. Esta capa depende de la capa de Aplicación. \- \*\*Ejemplo en Python\*\*: ```python from flask import Flask, request, jsonify app = Flask(\_\_name\_\_) servicio\_usuario = ServicioUsuario(usuario\_repositorio=...) @app.route("/usuarios", methods=\["POST"]) def registrar\_usuario(): datos = request.json servicio\_usuario.registrar\_usuario(nombre=datos\["nombre"], email=datos\["email"]) return jsonify({"mensaje": "Usuario registrado con éxito"}), 201 @app.route("/usuarios/\<int:id>/email", methods=\["PUT"]) def cambiar\_email(id): datos = request.json servicio\_usuario.cambiar\_email(id=id, nuevo\_email=datos\["email"]) return jsonify({"mensaje": "Email actualizado con éxito"}), 200 ``` 6\. \*\*Infraestructura\*\*: \- \*\*Descripción\*\*: Contiene las implementaciones de los repositorios, adaptadores para acceso a bases de datos, sistemas de mensajería, etc. Esta capa interactúa con la infraestructura y puede depender de bibliotecas externas. \- \*\*Ejemplo en Python\*\*: ```python class UsuarioRepositorioSQL(UsuarioRepositorio): def \_\_init\_\_(self, conexion): self.conexion = conexion def obtener\_por\_id(self, id): cursor = self.conexion.cursor() cursor.execute("SELECT id, nombre, email FROM usuarios WHERE id = %s", (id,)) row = cursor.fetchone() if row: return Usuario(id=row\[0], nombre=row\[1], email=row\[2]) else: return None def guardar(self, usuario): cursor = self.conexion.cursor() if usuario.id is None: cursor.execute("INSERT INTO usuarios (nombre, email) VALUES (%s, %s) RETURNING id", (usuario.nombre, usuario.email)) usuario.id = cursor.fetchone()\[0] else: cursor.execute("UPDATE usuarios SET nombre = %s, email = %s WHERE id = %s", (usuario.nombre, usuario.email, usuario.id)) self.conexion.commit() ``` \### Resumen de la Arquitectura de Cebolla en Python: \- \*\*Dominio (Core)\*\*: Contiene las entidades, objetos de valor, y servicios de dominio. Es la capa más interna y no depende de nada externo. \- \*\*Aplicación\*\*: Contiene los casos de uso y las reglas de aplicación. Orquesta las interacciones entre el dominio y las capas externas. \- \*\*Interfaces de Entrada\*\*: Define cómo los casos de uso son invocados desde el exterior (por ejemplo, controladores de API). \- \*\*Infraestructura\*\*: Implementa los detalles de acceso a datos, integraciones con otros sistemas, etc. La arquitectura de cebolla promueve la \*\*desacoplamiento\*\*, lo que permite que la lógica de negocio permanezca independiente de la infraestructura y las interfaces externas, facilitando así la \*\*mantenibilidad\*\*, \*\*pruebas\*\* y \*\*flexibilidad\*\* del software.

Termino de ver este vídeo y estoy en shock.

Me estoy dando cuenta que luego de haber combinado varias patrones de arquitectura, creyendo que aplicaba una arquitectura principalmente hexagonal, puede que haya terminado implementado la arquitectura de Cebolla sin saber que esta existía.