CodeGym /Adesua ahorow /Docker SELF /應用程式架構設計

應用程式架構設計

Docker SELF
等級 23 , 課堂 1
開放

2.1 整體架構

在這個階段,我們將設計一個任務管理應用的架構。我們會確定 frontend、backend 和資料庫如何互動,以及每個部分會包含哪些元件。

應用程式將由三個主要組成部分構成:

  • Frontend (ReactJS): 負責用戶與系統互動的客戶端部分。
  • Backend (Flask): 處理來自 frontend 的請求並與資料庫互動的伺服器端部分。
  • Database (PostgreSQL): 用於儲存用戶和任務數據的資料存儲。

架構將如下所示:

Terminal

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

組件間的互動

  • Frontend: 發送 HTTP 請求給 backend 執行 CRUD 操作(創建、讀取、更新、刪除任務)。
  • Backend: 處理來自 frontend 的 HTTP 請求,執行業務邏輯並與資料庫互動。
  • Database: 根據 backend 的請求儲存和提供數據。

2.2 每個元件的描述

1. Frontend (ReactJS):

  • 介面元件: 用於用戶註冊和登錄、創建和編輯任務、查看任務列表的元件。
  • 與 API 的互動: 使用 Axios 庫來向後端發送 HTTP 請求。

2. Backend (Flask):

  • REST API: 實現管理用戶和任務的端點。
  • 數據模型: 使用 SQLAlchemy 定義用戶和任務的數據模型。
  • 業務邏輯: 處理應用程式邏輯,包括數據驗證和用戶會話管理。

3. Database (PostgreSQL):

  • 表格: 用於存儲用戶和任務資訊的表格。
  • 表格之間的關係: 定義用戶和任務表格之間的關係(例如,一個用戶可以有多個任務)。

4. 網絡互動

所有元件之間的通信都將通過 HTTP 協議進行。Frontend 將通過 REST API 與 Backend 互動,而 Backend 則通過 SQL 查詢與 Database 互動。

  • Frontend: 用於開發和測試的埠號 3000。
  • Backend: 用於與 Frontend 互動的埠號 5000。
  • Database: 用於與 Backend 互動的埠號 5432。

2.3 每個組件的詳細説明

1. 基本數據結構

為了在PostgreSQL數據庫中儲存用戶和任務的資料,我們會創建兩個表:userstasks

表格 users

  • id (int, primary key): 用戶的唯一識別碼。
  • username (varchar, unique): 用戶名。
  • password (varchar): 用戶密碼的哈希值。

表格 tasks

  • id (int, primary key): 任務的唯一識別碼。
  • title (varchar): 任務標題。
  • description (text): 任務描述。
  • owner_id (int, foreign key): 分配該任務的用戶ID。
  • status (varchar): 任務狀態(例如,已完成/未完成)。

2. API 設計

後端將提供RESTful API以與前端進行交互。以下是API端點的範例列表:

  • 用戶:
    • POST /users: 創建一個新用戶。
    • GET /users: 獲取所有用戶的清單。
    • GET /users/:id: 獲取特定用戶的信息。
    • PUT /users/:id: 更新用戶信息。
    • DELETE /users/:id: 刪除用戶。
  • 任務:
    • POST /tasks: 創建一個新任務。
    • GET /tasks: 獲取所有任務的清單。
    • GET /tasks/:id: 獲取特定任務的信息。
    • PUT /tasks/:id: 更新任務信息。
    • DELETE /tasks/:id: 刪除任務。

2.4 數據模型

以下是 Python 用於與資料庫表交互的程式碼示例:

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

2.5 路由和控制器

伺服器端 API 實現範例:

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', "未完成")
    )
    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 從前端向伺服器請求的範例

用於顯示任務清單的 React 元件範例:

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('獲取任務時出現錯誤!', error);
      });
  }, []);

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

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