CodeGym /Corsi /Docker SELF /Progettazione dell'architettura dell'applicazione

Progettazione dell'architettura dell'applicazione

Docker SELF
Livello 23 , Lezione 1
Disponibile

2.1 Architettura generale

In questa fase progetteremo l'architettura di un'applicazione per la gestione delle attività. Definiremo come interagiranno il frontend, il backend e il database, oltre a quali componenti saranno inclusi in ciascuno di essi.

L'app sarà composta da tre componenti principali:

  • Frontend (ReactJS): la parte client che assicura l'interazione dell'utente con il sistema.
  • Backend (Flask): la parte server che gestisce le richieste dal frontend e interagisce con il database.
  • Database (PostgreSQL): il sistema di archiviazione dei dati per utenti e attività.

L'architettura sarà così strutturata:

Terminale

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

Interazione tra i componenti

  • Frontend: invia richieste HTTP al backend per eseguire operazioni CRUD (creazione, lettura, aggiornamento, eliminazione delle attività).
  • Backend: gestisce le richieste HTTP dal frontend, esegue la logica di business e interagisce con il database.
  • Database: memorizza e fornisce dati su richiesta dal backend.

2.2 Descrizione di ogni componente

1. Frontend (ReactJS):

  • Componenti dell'interfaccia: componenti per la registrazione e l'autenticazione degli utenti, la creazione e la modifica delle attività, la visualizzazione dell'elenco delle attività.
  • Interazione con API: utilizzo della libreria Axios per inviare richieste HTTP al backend.

2. Backend (Flask):

  • REST API: implementazione degli endpoint per la gestione degli utenti e delle attività.
  • Modelli di dati: definizione dei modelli di dati per utenti e attività utilizzando SQLAlchemy.
  • Logica di business: gestione della logica dell'applicazione, inclusa la validazione dei dati e la gestione delle sessioni utenti.

3. Database (PostgreSQL):

  • Tabelle: tabelle per memorizzare informazioni su utenti e attività.
  • Relazioni tra tabelle: definizione delle relazioni tra le tabelle degli utenti e delle attività (ad esempio, un utente può avere molte attività).

4. Interazione di rete

Tutta la comunicazione tra i componenti avverrà tramite il protocollo HTTP. Il frontend interagirà con il backend tramite REST API, mentre il backend interagirà con il database tramite query SQL.

  • Frontend: porta 3000 per sviluppo e test.
  • Backend: porta 5000 per interazione col frontend.
  • Database: porta 5432 per interazione col backend.

2.3 Descrizione dettagliata di ogni componente

1. Struttura base dei dati

Per memorizzare i dati degli utenti e dei task nel database PostgreSQL, creeremo due tabelle: users e tasks.

Tabella users:

  • id (int, primary key): identificatore univoco dell'utente.
  • username (varchar, unique): nome dell'utente.
  • password (varchar): hash della password dell'utente.

Tabella tasks:

  • id (int, primary key): identificatore univoco del task.
  • title (varchar): titolo del task.
  • description (text): descrizione del task.
  • owner_id (int, foreign key): identificatore dell'utente al quale è assegnato il task.
  • status (varchar): stato del task (ad esempio, completato/non completato).

2. Design dell'API

Il backend fornirà un'API RESTful per interagire con il frontend. Elenco approssimativo degli endpoint:

  • Utenti:
    • POST /users: creazione di un nuovo utente.
    • GET /users: ottenimento della lista di tutti gli utenti.
    • GET /users/:id: ottenimento delle informazioni su un utente specifico.
    • PUT /users/:id: aggiornamento delle informazioni di un utente.
    • DELETE /users/:id: eliminazione di un utente.
  • Task:
    • POST /tasks: creazione di un nuovo task.
    • GET /tasks: ottenimento della lista di tutti i task.
    • GET /tasks/:id: ottenimento delle informazioni su un task specifico.
    • PUT /tasks/:id: aggiornamento delle informazioni di un task.
    • DELETE /tasks/:id: eliminazione di un task.

2.4 Modelli di dati

Questo è come apparirà il codice in Python per lavorare con le tabelle del database:

Modello 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
        }

Modello 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="non completata")
    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "description": self.description,
            "owner_id": self.owner_id,
            "status": self.status
        }

2.5 Rotte e controller

Esempio di implementazione dell'API lato server:

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', "non completata")
    )
    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 Esempio di richiesta al server dal frontend

Esempio di componente React per visualizzare una lista di task:

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('C'è stato un errore mentre si recuperavano i task!', error);
      });
  }, []);

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

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