CodeGym /Kurse /Docker SELF /Entwurf der Anwendungsarchitektur

Entwurf der Anwendungsarchitektur

Docker SELF
Level 23 , Lektion 1
Verfügbar

2.1 Allgemeine Architektur

In diesem Schritt entwerfen wir die Architektur der Aufgabenverwaltungsanwendung. Wir legen fest, wie Frontend, Backend und Datenbank miteinander interagieren und welche Komponenten in jedem von ihnen enthalten sein werden.

Die Anwendung wird aus drei Hauptkomponenten bestehen:

  • Frontend (ReactJS): der Client-Teil, der die Interaktion des Benutzers mit dem System ermöglicht.
  • Backend (Flask): der Server-Teil, der Anfragen vom Frontend verarbeitet und mit der Datenbank interagiert.
  • Database (PostgreSQL): der Datenspeicher für Benutzer und Aufgaben.

Die Architektur wird wie folgt aussehen:

Terminal

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

Interaktion zwischen den Komponenten

  • Frontend: sendet HTTP-Anfragen an das Backend, um CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen von Aufgaben) auszuführen.
  • Backend: verarbeitet HTTP-Anfragen vom Frontend, führt die Geschäftslogik aus und interagiert mit der Datenbank.
  • Database: speichert und stellt Daten auf Anfrage des Backends bereit.

2.2 Beschreibung jedes Komponente

1. Frontend (ReactJS):

  • Benutzeroberflächenkomponenten: Komponenten für die Registrierung und Authorisierung von Benutzern, Erstellung und Bearbeitung von Aufgaben, Ansicht der Aufgabenliste.
  • Interaktion mit API: Verwendung der Axios-Bibliothek zum Senden von HTTP-Anfragen an das Backend.

2. Backend (Flask):

  • REST API: Implementierung von Endpoints zur Verwaltung von Benutzern und Aufgaben.
  • Datenmodelle: Definition von Datenmodellen für Benutzer und Aufgaben mit SQLAlchemy.
  • Geschäftslogik: Verarbeitung der Anwendungslogik, einschließlich Datenvalidierung und Verwaltung der Benutzersitzungen.

3. Datenbank (PostgreSQL):

  • Tabellen: Tabellen für die Speicherung von Informationen über Benutzer und Aufgaben.
  • Beziehungen zwischen Tabellen: Definition von Beziehungen zwischen Benutzertabellen und Aufgabentabellen (zum Beispiel, ein Benutzer kann viele Aufgaben haben).

4. Netzwerkkommunikation

Die gesamte Kommunikation zwischen den Komponenten erfolgt über das HTTP-Protokoll. Das Frontend kommuniziert mit dem Backend über die REST API, und das Backend kommuniziert mit der Datenbank über SQL-Abfragen.

  • Frontend: Port 3000 für Entwicklung und Tests.
  • Backend: Port 5000 für die Interaktion mit dem Frontend.
  • Datenbank: Port 5432 für die Interaktion mit dem Backend.

2.3 Detaillierte Beschreibung jeder Komponente

1. Grundstruktur der Daten

Um Daten über Benutzer und Aufgaben in der PostgreSQL-Datenbank zu speichern, erstellen wir zwei Tabellen: users und tasks.

Tabelle users:

  • id (int, primary key): eindeutige Benutzer-ID.
  • username (varchar, unique): Benutzername.
  • password (varchar): Hash des Benutzerpassworts.

Tabelle tasks:

  • id (int, primary key): eindeutige Aufgaben-ID.
  • title (varchar): Titel der Aufgabe.
  • description (text): Beschreibung der Aufgabe.
  • owner_id (int, foreign key): Benutzer-ID, dem die Aufgabe zugewiesen wurde.
  • status (varchar): Status der Aufgabe (z. B. erledigt/nicht erledigt).

2. API-Design

Das Backend stellt ein RESTful API zur Verfügung, um mit dem Frontend zu interagieren. Eine ungefähre Liste der Endpoints:

  • Benutzer:
    • POST /users: Erstellung eines neuen Benutzers.
    • GET /users: Abrufen der Liste aller Benutzer.
    • GET /users/:id: Abrufen von Informationen über einen bestimmten Benutzer.
    • PUT /users/:id: Aktualisierung der Benutzerinformationen.
    • DELETE /users/:id: Löschen eines Benutzers.
  • Aufgaben:
    • POST /tasks: Erstellung einer neuen Aufgabe.
    • GET /tasks: Abrufen der Liste aller Aufgaben.
    • GET /tasks/:id: Abrufen von Informationen über eine bestimmte Aufgabe.
    • PUT /tasks/:id: Aktualisierung der Aufgabeninformationen.
    • DELETE /tasks/:id: Löschen einer Aufgabe.

2.4 Datenmodelle

So sieht der Python-Code für die Arbeit mit Tabellen in einer Datenbank aus:

User Model:

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
        }

Task Model:

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

2.5 Routen und Controller

Beispiel der Implementierung eines APIs auf der Serverseite:

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', "nicht abgeschlossen")
    )
    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 Beispiel eines Serveraufrufs vom Frontend

Ein Beispiel für eine React-Komponente zur Darstellung einer Aufgabenliste:

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('Es gab einen Fehler beim Abrufen der Aufgaben!', error);
      });
  }, []);

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

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