CodeGym /Cursos /Docker SELF /Diseño de la arquitectura de la aplicación

Diseño de la arquitectura de la aplicación

Docker SELF
Nivel 23 , Lección 1
Disponible

2.1 Arquitectura general

En esta etapa vamos a diseñar la arquitectura de una aplicación para la gestión de tareas. Vamos a definir cómo interactuarán el frontend, el backend y la base de datos, así como qué componentes estarán incluidos en cada uno de ellos.

La aplicación se compondrá de tres componentes principales:

  • Frontend (ReactJS): la parte del cliente, que garantiza la interacción del usuario con el sistema.
  • Backend (Flask): la parte del servidor, que procesa las solicitudes del frontend e interactúa con la base de datos.
  • Database (PostgreSQL): el almacenamiento de datos para los usuarios y las tareas.

La arquitectura se verá de la siguiente manera:

Terminal

+-------------+       +-------------+       +--------------+
|             |       |             |       |              |
|  Frontend   +------->+   Backend   +------->+   Database   |
|  (ReactJS)  |       |   (Flask)   |       | (PostgreSQL) |
|             |       |             |       |              |
+-------------+       +-------------+       +--------------+

Interacción entre los componentes

  • Frontend: envía solicitudes HTTP al backend para realizar operaciones CRUD (crear, leer, actualizar, eliminar tareas).
  • Backend: procesa las solicitudes HTTP del frontend, realiza la lógica de negocio e interactúa con la base de datos.
  • Database: guarda y proporciona datos según las solicitudes del backend.

2.2 Descripción de cada componente

1. Frontend (ReactJS):

  • Componentes de la interfaz: componentes para registro y autorización de usuarios, creación y edición de tareas, visualización de la lista de tareas.
  • Interacción con API: uso de la biblioteca Axios para enviar solicitudes HTTP al backend.

2. Backend (Flask):

  • REST API: implementación de endpoints para la gestión de usuarios y tareas.
  • Modelos de datos: definición de modelos de datos para usuarios y tareas usando SQLAlchemy.
  • Lógica de negocio: procesamiento de la lógica de la aplicación, incluyendo validación de datos y gestión de sesiones de usuario.

3. Database (PostgreSQL):

  • Tablas: tablas para almacenar información sobre usuarios y tareas.
  • Relaciones entre tablas: definición de relaciones entre las tablas de usuarios y tareas (por ejemplo, un usuario puede tener muchas tareas).

4. Interacción en red

Toda la comunicación entre los componentes se realizará a través del protocolo HTTP. El frontend interactuará con el backend a través de REST API, y el backend interactuará con la base de datos mediante consultas SQL.

  • Frontend: puerto 3000 para desarrollo y pruebas.
  • Backend: puerto 5000 para interactuar con el frontend.
  • Database: puerto 5432 para interactuar con el backend.

2.3 Descripción detallada de cada componente

1. Estructura básica de datos

Para almacenar datos sobre usuarios y tareas en la base de datos PostgreSQL, crearemos dos tablas: users y tasks.

Tabla users:

  • id (int, primary key): identificador único del usuario.
  • username (varchar, unique): nombre del usuario.
  • password (varchar): hash de la contraseña del usuario.

Tabla tasks:

  • id (int, primary key): identificador único de la tarea.
  • title (varchar): título de la tarea.
  • description (text): descripción de la tarea.
  • owner_id (int, foreign key): identificador del usuario asignado a la tarea.
  • status (varchar): estado de la tarea (por ejemplo, completada/no completada).

2. Diseño del API

El backend proporcionará un RESTful API para interactuar con el frontend. Lista aproximada de endpoints:

  • Usuarios:
    • POST /users: creación de un nuevo usuario.
    • GET /users: obtención de la lista de todos los usuarios.
    • GET /users/:id: obtención de información sobre un usuario específico.
    • PUT /users/:id: actualización de la información de un usuario.
    • DELETE /users/:id: eliminación de un usuario.
  • Tareas:
    • POST /tasks: creación de una nueva tarea.
    • GET /tasks: obtención de la lista de todas las tareas.
    • GET /tasks/:id: obtención de información sobre una tarea específica.
    • PUT /tasks/:id: actualización de la información de una tarea.
    • DELETE /tasks/:id: eliminación de una tarea.

2.4 Modelos de datos

Así se verá el código en Python para trabajar con tablas de una base de datos:

Modelo User:

Python

from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)
    tasks = db.relationship('Task', backref='owner', lazy=True)
    def to_dict(self):
        return {
            "id": self.id,
            "username": self.username
        }

Modelo Task:

Python

from app import db

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(120), nullable=False)
    description = db.Column(db.Text, nullable=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    status = db.Column(db.String(20), nullable=False, default="no completada")
    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "description": self.description,
            "owner_id": self.owner_id,
            "status": self.status
        }

2.5 Rutas y controladores

Ejemplo de implementación de API en el lado del servidor:

Python

from app import app, db
from app.models import Task, User
from flask import request, jsonify

@app.route('/tasks', methods=['GET'])
def get_tasks():
    tasks = Task.query.all()
    return jsonify([task.to_dict() for task in tasks])

@app.route('/tasks', methods=['POST'])
def create_task():
    data = request.get_json()
    new_task = Task(
        title=data['title'],
        description=data.get('description'),
        owner_id=data['owner_id'],
        status=data.get('status', "no completada")
    )
    db.session.add(new_task)
    db.session.commit()
    return jsonify(new_task.to_dict()), 201

@app.route('/tasks/<int:id>', methods=['GET'])
def get_task(id):
    task = Task.query.get_or_404(id)
    return jsonify(task.to_dict())

@app.route('/tasks/<int:id>', methods=['PUT'])
def update_task(id):
    data = request.get_json()
    task = Task.query.get_or_404(id)
    task.title = data['title']
    task.description = data.get('description')
    task.status = data.get('status', task.status)
    task.owner_id = data['owner_id']
    db.session.commit()
    return jsonify(task.to_dict())

@app.route('/tasks/<int:id>', methods=['DELETE'])
def delete_task(id):
    task = Task.query.get_or_404(id)
    db.session.delete(task)
    db.session.commit()
    return '', 204

2.6 Ejemplo de solicitud al servidor desde el frontend

Ejemplo de un componente React para mostrar una lista de tareas:

Javascript

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const TaskList = () => {
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    axios.get('http://localhost:5000/tasks')
      .then(response => {
        setTasks(response.data);
      })
      .catch(error => {
        console.error('¡Hubo un error al obtener las tareas!', error);
      });
  }, []);

  return (
    <div>
      <h1>Lista de Tareas</h1>
      <ul>
        {tasks.map(task => (
          <li key={task.id}>{task.title} - {task.status}</li>
        ))}
      </ul>
    </div>
  );
};

export default TaskList;
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION