You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

2 Días
14 Hrs
26 Min
17 Seg

Reestructuración de un proyecto en Python

13/27
Resources

Design patterns are a powerful tool in software development that allow you to solve common problems in an efficient and reusable way. In this introduction, we will explore what they are, why they exist, and what are the main types of patterns, such as creative, structural and behavioral, along with practical examples that will allow you to understand their usefulness in the creation of quality software.

What are design patterns?

Design patterns are reusable solutions to recurring problems in software development. They can be compared to recipes in the culinary world: each pattern is a guide applicable to certain scenarios or problems. Just as recipes fit certain ingredients, design patterns apply to specific situations within programming.

Why do design patterns exist?

These patterns arise from the accumulated experience of the authors of the book Design Patterns, known as "The Gang of Four". Through their work, they compiled solutions that help create maintainable and reusable code, which is crucial in collaborative development. By adopting these patterns, developers can communicate more effectively, using a common language that simplifies the exchange of ideas and collaboration on code reviews.

What are the categories of design patterns?

There are three main categories:

  1. Creational patterns: these focus on the creation of object instances. They are useful when the creation of an object is complex or has many dependencies. Examples include:

    • Singleton
    • Factory Method
    • Abstract Factory
    • Builder
    • Prototype
  2. Structural patterns: They focus on the composition of classes and objects to create efficient structures. They allow to organize classes in an optimal way. Some examples are:

    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  3. Behavioral patterns: They help to improve communication and assignment of responsibilities between objects, solving complex interactions between classes. Examples include:

    • Observer
    • Strategy
    • Command
    • Iterator
    • Mediator
    • State
    • Visitor

How are design patterns applied in industry?

In real projects, it is not necessary to use all design patterns. The key is to select those that best fit the specific context of the project. In this course, we will see some of the most used patterns in the industry, applicable to the type of software we will develop, and will be key to solve common problems efficiently.

Contributions 7

Questions 0

Sort by:

Want to see more contributions, questions and answers from the community?

Perdon, no entendi, en donde esta el proyecto open source para implementar la reestructuracion que dice Eduardo al final del video? gracias
Difinitvamente es una lucha constante seguir al profesor, pero ya teniendo el codigo mas avanzado en los recursos, deberian poner como recurso un github inicial con el codigo base para que se pueda seguir la clase.
La organización de tu código es crucial y debe adaptarse al contexto y necesidades del proyecto. Tu propuesta de crear un paquete por cada responsabilidad y un paquete para las implementaciones es válida y favorece la claridad y mantenibilidad. 1. **Protocolo y paquetes**: Crear un paquete raíz con protocolos y otro para las implementaciones es una buena práctica. Así, se facilita el entendimiento y se separan las preocupaciones. 2. **Estructuras como `pydantic.BaseModel`**: Pueden considerarse modelos, pero también pueden formar parte de un paquete de validadores. Si decides crear un paquete específico, un nombre apropiado podría ser `schemas` o `models`, dependiendo de su uso. Recuerda que la consistencia en la nomenclatura y la organización facilitará el trabajo en equipo y la escalabilidad del proyecto.
Me queda la duda de cómo decide si un payment debe usar sms o email para notificar cuando tiene dos Notifier (clases email o sms) y solo crea uno de esos objetos ¿En qué parte de la lógica está que se crea uno o el otro objeto dependiendo del tipo de dato que recibió? En anteriores clases, vi que creaba dos servicios distintos, pero era el programador quien decidía eso y no se lo hacía dinámicamente. Al final de la reestructuración no ejecutó nuevamente el código. Me deja mucho que desear el curso hasta este punto.
Las clases de bajo nivel son aquellas que tienen una responsabilidad específica y se encargan de realizar tareas concretas dentro de un sistema. En el contexto de la reestructuración del proyecto de pagos, las clases de bajo nivel incluyen validadores, procesadores de pago y loggers. Estas clases son utilizadas por la clase de alto nivel (PaymentService), permitiendo una mayor modularidad y facilidad de mantenimiento en el código. Esto se alinea con los principios SOLID, donde cada clase tiene una única responsabilidad y se puede modificar sin afectar al sistema completo.
Reestructurar un proyecto en Python implica organizar su estructura de archivos y carpetas para que sea modular, mantenible y escalable, especialmente en proyectos complejos. Una estructura bien organizada facilita el desarrollo, las pruebas, la colaboración en equipo y la integración de herramientas de CI/CD. Aquí tienes una guía para estructurar un proyecto en Python, especialmente útil para aplicaciones de tamaño medio a grande. \--- \### Estructura Común para un Proyecto en Python Imaginemos que tienes un proyecto llamado `my\_project`. La estructura típica podría verse así: ``` my\_project/ │ ├── my\_project/ # Paquete principal de la aplicación │ ├── \_\_init\_\_.py # Marca este directorio como un paquete Python │ ├── main.py # Archivo principal para ejecutar la aplicación │ ├── config.py # Configuración de la aplicación │ ├── controllers/ # Lógica de controladores o lógica de negocio │ │ ├── \_\_init\_\_.py │ │ └── user\_controller.py │ ├── models/ # Modelos y clases de datos │ │ ├── \_\_init\_\_.py │ │ └── user.py │ ├── services/ # Servicios o lógica de negocio │ │ ├── \_\_init\_\_.py │ │ └── user\_service.py │ ├── repositories/ # Capa de acceso a datos │ │ ├── \_\_init\_\_.py │ │ └── user\_repository.py │ ├── utils/ # Utilidades y funciones auxiliares │ │ ├── \_\_init\_\_.py │ │ └── helpers.py │ └── schemas/ # Definición de esquemas o validaciones │ ├── \_\_init\_\_.py │ └── user\_schema.py │ ├── tests/ # Pruebas unitarias y funcionales │ ├── \_\_init\_\_.py │ ├── test\_main.py # Pruebas de integración para main.py │ ├── controllers/ # Pruebas de controladores │ ├── models/ # Pruebas de modelos │ ├── services/ # Pruebas de servicios │ └── repositories/ # Pruebas de acceso a datos │ ├── scripts/ # Scripts de gestión (deploy, migraciones) │ └── run\_migration.py │ ├── .env # Variables de entorno (NO subir a control de versiones) ├── requirements.txt # Dependencias del proyecto ├── README.md # Documentación general del proyecto ├── .gitignore # Archivos y carpetas ignoradas por git └── setup.py # Script de instalación para pip ``` \### Explicación de Cada Directorio y Archivo \- \*\*my\_project/\*\*: Este es el paquete principal de tu aplicación, que incluye la mayor parte de la lógica y componentes del proyecto. \- \*\*`\_\_init\_\_.py`\*\*: Marca el directorio como un paquete. Si usas namespaces, puedes añadir configuraciones básicas. \- \*\*`main.py`\*\*: Punto de entrada de la aplicación. En una aplicación web, aquí podría residir el servidor principal, mientras que en una CLI se definiría el comando principal. \- \*\*`config.py`\*\*: Define configuraciones globales (puedes cargar variables de `.env` o definir configuraciones específicas para cada entorno). \- \*\*controladores (controllers/)\*\*: Aquí reside la lógica de los controladores, que gestionan la lógica de flujo de la aplicación. Para una API, por ejemplo, este directorio puede incluir controladores para diferentes endpoints. \- \*\*modelos (models/)\*\*: Define la estructura de datos (o modelos ORM, si usas una base de datos). Cada modelo representa una entidad o clase de datos. \- \*\*servicios (services/)\*\*: Contiene la lógica de negocio. Aquí colocas las operaciones específicas y servicios que actúan sobre los datos y no necesariamente dependen del flujo del usuario. \- \*\*repositorios (repositories/)\*\*: Capa de acceso a datos que interactúa con la base de datos o con APIs externas. Permite la separación del almacenamiento de datos y la lógica de negocio. \- \*\*utilidades (utils/)\*\*: Funciones auxiliares que pueden ser usadas en distintas partes del proyecto (validaciones, formateo de datos, etc.). \- \*\*esquemas (schemas/)\*\*: Definiciones de esquemas o validaciones de datos (por ejemplo, usando librerías como `pydantic` o `marshmallow`). Sirve para definir y validar los datos que entran o salen del sistema. \- \*\*tests/\*\*: Directorio para pruebas unitarias, funcionales e integradas. Organizado de forma similar al proyecto principal para encontrar y estructurar mejor las pruebas de cada módulo. \- \*\*scripts/\*\*: Contiene scripts auxiliares, como scripts de migraciones, herramientas de despliegue, o utilidades de mantenimiento del sistema. \- \*\*`.env`\*\*: Archivo para variables de entorno, como claves API o configuraciones específicas del entorno, que no deben subirse al repositorio. \- \*\*`requirements.txt`\*\*: Lista de dependencias del proyecto, necesaria para instalar las librerías con `pip`. \- \*\*`README.md`\*\*: Documentación general del proyecto. Aquí puedes describir el propósito del proyecto, instrucciones de instalación y guías de uso. \- \*\*`.gitignore`\*\*: Archivo de configuración para ignorar archivos específicos en el control de versiones (por ejemplo, `.env`, archivos de caché, etc.). \- \*\*`setup.py`\*\*: Script de configuración para la instalación del paquete si estás planeando distribuir el proyecto como una biblioteca o una herramienta instalable. \### Consejos Adicionales 1\. \*\*Usa herramientas de linting y formateo\*\*: Utiliza `flake8` o `pylint` para asegurar la calidad del código, y `black` o `autopep8` para mantener el formato del código. 2\. \*\*Pruebas automatizadas\*\*: Configura tus pruebas con `pytest` o `unittest` para que corran automáticamente en un servidor de CI/CD (por ejemplo, usando GitHub Actions o GitLab CI). 3\. \*\*Documentación\*\*: Es recomendable documentar tanto el código como el README.md, e incluso usar docstrings y herramientas como Sphinx si el proyecto es grande. 4\. \*\*Configuración flexible\*\*: En `config.py`, carga variables de entorno usando una librería como `dotenv` para facilitar el cambio de entornos (producción, desarrollo, etc.). \### Ejemplo de Código para `config.py` ```python import os from dotenv import load\_dotenv \# Cargar variables de entorno del archivo .env load\_dotenv() class Config: DEBUG = os.getenv("DEBUG", "False") == "True" DATABASE\_URL = os.getenv("DATABASE\_URL") SECRET\_KEY = os.getenv("SECRET\_KEY", "default\_secret\_key") ``` \### Ejemplo de `main.py` con Configuración de Entrada ```python from my\_project.config import Config from my\_project.controllers.user\_controller import UserController def main(): print("Starting application...") user\_controller = UserController() user\_controller.run() if \_\_name\_\_ == "\_\_main\_\_": main() ``` \### Beneficios de una Buena Estructura de Proyecto \- \*\*Mantenibilidad\*\*: La separación de responsabilidades hace que el código sea más fácil de modificar y mantener. \- \*\*Escalabilidad\*\*: Una estructura bien organizada permite agregar nuevas funcionalidades de manera ordenada. \- \*\*Colaboración\*\*: Facilita el trabajo en equipo, ya que cada miembro puede trabajar en un módulo sin interferir en otros. \- \*\*Pruebas\*\*: Las pruebas se integran de forma natural en la estructura, permitiendo que cada módulo tenga sus pruebas específicas. Organizar y estructurar bien un proyecto en Python es esencial para el éxito a largo plazo. Mantener estas buenas prácticas hará que el desarrollo sea más eficiente y sostenible.
La carpeta `payment_service` se organiza en módulos que representan distintos contextos, como: 1. **Commons**: Información de contacto, datos de cliente y datos de pago. 2. **Notificadores**: Protocolo y clases para notificaciones (email y SMS). 3. **Loggers**: Clase para el registro de transacciones. 4. **Validadores**: Clases para validar datos de cliente y pago. 5. **Procesadores**: Protocolos y clases que implementan la lógica de pagos, como Stripe. Cada contexto tiene su propia carpeta y las clases se importan en el archivo `service.py` para mantener la estructura limpia y escalable.