软件工程第二次结对作业

这个作业属于哪个课程 软件工程
这个作业要求在哪里 2024秋软件工程结对作业(第二次之程序实现)
这个作业的目标 程序实现上一次作业设计的的原型
结对同学的博客链接 结对同学博客
我们队创建的仓库的GitHub项目地址 GitHub项目地址
我的学号 102202121
队友学号 102202118

🎉 欢迎来到我的博客!🎉

📚结对编程作业博客

🪄🪄我们的FCC在此!! 我们app的apk文件链接!

🎧链接

📝分工

  • 102202118
    负责完成登录和注册页面、首页以及消息和聊天页面、以及软件首页的设计和代码实现;
    博客的编写;
    GitHub仓库管理;
    PSP表格填写;
    目录结构和README文档编写
  • 102202121
    负责完成项目详情以及项目发起、个人主页的设计和代码实现;
    整体代码的修缮和补充;
    单元测试;

🖌️PSP表格

PSP 2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 50
Estimate 估计这个任务需要多少时间 20 20
Development 开发 360 400
Analysis 需求分析 (包括学习新技术) 250 260
Design Spec 生成设计文档 30 30
Design Review 设计复审 30 45
Coding Standard 代码规范 (制定合适规范) 30 45
Design 具体设计 60 30
Coding 具体编码 100 120
Code Review 代码复审 60 40
Test 测试(自我测试,修改代码,提交修改) 200 120
Reporting 报告 100 120
Test Repor 测试报告 30 20
Size Measurement 计算工作量 15 10
Postmortem & Process Improvement Plan 事后总结与改进计划 30 50
Total 合计 1375 1360

💡解题思路描述与设计实现说明

🗺️解题思路

  1. 需求分析:明确项目的需求,包括功能需求(如用户管理、数据展示等)和非功能需求(如性能、安全性等)。
  2. 系统设计:设计系统的整体架构,包括前端和后端的交互方式(如AJAX请求)、数据库设计(如数据表结构、索引等)。
  3. 技术选型
    • 前端:选择JavaScript作为开发语言,使用特定框架(如React,但原描述中未提及,故保持原描述中的JavaScript)。
    • 后端:使用Node.js和Express框架搭建服务器。
    • 数据库:选择MySQL作为存储数据库。
  4. 模块划分:将系统划分为前端模块、后端模块和数据库模块,每个模块由专人负责。
  5. 接口设计:设计前后端交互的RESTful风格接口,确保数据传递的正确性和安全性。

💻设计实现

  1. 前端实现

    • 使用JavaScript和特定前端框架(如原描述中未具体提及React,但可根据实际情况调整)构建用户界面。
    • 通过状态管理和组件化开发实现页面的动态渲染。
    • 使用Axios等HTTP库发送请求,与后端进行数据交互。
  2. 后端实现

    • 使用Node.js和Express框架搭建服务器,处理前端请求并返回相应的数据。
    • 定义路由和控制器,实现业务逻辑的处理。
    • 使用适当的中间件(如body-parser)解析请求数据。
  3. 数据库设计

    • 使用MySQL数据库存储数据,设计合理的表结构和索引以提高查询效率。
    • 编写SQL语句实现数据的增删改查操作。
  4. 接口实现

    • 使用RESTful风格设计API接口,确保数据传递的规范性和安全性。
    • 实现数据的序列化和反序列化,确保前后端数据格式的一致性。
  5. 安全性设计

    • 采用HTTPS协议保障数据传输的安全性。
    • 实现输入验证和参数校验,防止SQL注入等安全问题。
    • 使用JWT等认证机制实现用户登录和权限控制。

🎧代码实现思路,文字描述

  1. 前端实现

    • 使用JavaScript和特定前端框架(如React)的组件化开发,将页面划分为多个组件,每个组件负责特定的功能。
    • 使用Redux或MobX等状态管理工具管理全局状态,确保组件间的数据共享和同步。
    • 使用Axios等HTTP库发送请求到后端API,获取数据并渲染到页面上。
  2. 后端实现

    • 使用Express框架搭建服务器,定义路由和控制器处理前端请求。
    • 使用Node.js的原生模块或第三方库(如mysql或sequelize)操作MySQL数据库,实现数据的增删改查操作。
    • 使用JWT等认证机制实现用户登录和权限控制,确保只有授权用户才能访问特定接口。

🎨 关键实现的流程图或数据流图

流程图

🔍 重要代码片段及解释

// 当文档加载完成后,添加事件监听器以处理表单提交事件
document.addEventListener('DOMContentLoaded', function() {
     // 获取项目表单元素
     var projectForm = document.getElementById('projectForm');

     // 为表单添加提交事件监听器
     projectForm.addEventListener('submit', function(event) {
         // 阻止表单默认提交行为,以便进行前端验证
         event.preventDefault();

         // 获取表单输入值,并进行清理(去除空白)
         var title = projectForm.title.value.trim();
         var description = projectForm.description.value.trim();
         var startTime = new Date(projectForm.startTime.value);
         var deadline = new Date(projectForm.deadline.value);
         var personCount = parseInt(projectForm.personCount.value, 10);

         // 验证项目名称、简介和人员数量是否已填写
         if (!title || !description || isNaN(personCount)) {
             // 如果有必填项为空,通知用户并阻止表单提交
             alert('项目名称、简介和人员数量不能为空!');
             return;
         }

         // 验证开始时间和截止时间是否为有效日期
         if (isNaN(startTime.getTime()) || isNaN(deadline.getTime())) {
             // 如果日期无效,通知用户并阻止表单提交
             alert('请选择有效的开始时间和截止时间!');
             return;
         }

         // 检查截止时间是否在开始时间之后
         if (deadline <= startTime) {
             // 如果截止时间不在开始时间之后,通知用户并阻止表单提交
             alert('项目截止时间必须在项目开始时间之后!');
             return;
         }

         // 验证人员数量是否至少为1
         if (personCount < 1) {
             // 如果人员数量小于1,通知用户并阻止表单提交
             alert('请选择至少1位人员!');
             return;
         }

         // 如果所有验证都通过,则可以提交表单或执行其他操作
         // 例如:projectForm.submit();
         // 输出日志,确认验证流程通过
         console.log('所有验证通过,可以提交表单!');
     });
});
  • 解释:这段代码通过全面的验证、清晰的逻辑、用户友好的错误提示和良好的可维护性,确保了用户在发起项目时能够提供正确和有效的信息。它使用了注释来解释每个主要步骤的目的和逻辑,这有助于其他开发者理解代码的功能和设计决策。此外,代码结构允许轻松添加更多的验证规则或调整现有规则,适应未来可能的需求变更。
  • 下面这段代码将解释融入在注释中以便更好理解
/* 使用媒体查询来适应屏幕宽度小于或等于600px的设备,通常是手机 */
@media (max-width: 600px) {
     /* 为手机屏幕设计的样式类,添加圆角边框和内边距以提升视觉效果和可点击性 */
     .phone-border {
         border-radius: 15px; /* 圆角边框,使元素看起来更现代友好 */
         padding: 10px; /* 添加内边距,确保内容不贴边,提升可点击性 */
     }

     /* 导航栏的样式,使用flex布局实现简洁的水平分布 */
     .navbar {
         display: flex; /* 使用flex布局,使子元素水平排列 */
         justify-content: space-around; /* 子元素间平均分布空间 */
         background-color: #007bff; /* 设置背景颜色,符合品牌或设计风格 */
     }

     /* 导航按钮的基本样式 */
     .nav-button {
         color: #fff; /* 文字颜色设置为白色,确保在深色背景上的可读性 */
         padding: 10px; /* 添加内边距,提升点击区域大小和美观度 */
         text-decoration: none; /* 移除下划线,保持简洁的视觉效果 */
     }

     /* 当导航按钮处于激活状态时的样式 */
     .nav-button.active {
         background-color: #004a97; /* 深色背景,突出显示当前活动的导航项 */
         font-weight: bold; /* 加粗文字,进一步强调当前活动项 */
     }
}

✨ 附加特点设计与展示

📚设计的创意独到之处

  1. 模块化设计:将系统划分为多个模块,每个模块独立开发,提高了代码的可维护性和可扩展性。
  2. 前后端分离:采用前后端分离的开发模式,前端使用JavaScript作为开发语言,后端使用Node.js和Express框架,提高了开发效率和系统的灵活性。
  3. 安全性设计:采用HTTPS协议、输入验证、权限控制等措施保障系统的安全性,提高了系统的可靠性和用户信任度。

🗺️实现思路

  1. 模块化开发:按照功能划分模块,每个模块独立开发并测试,最后集成到系统中。
  2. 前后端交互:通过定义RESTful风格的API接口实现前后端的交互,确保数据传递的正确性和安全性。
  3. 安全性实现:使用JWT等认证机制实现用户登录和权限控制,采用HTTPS协议保障数据传输的安全性。

🎶 重要代码片段及解释

// Node.js和Express框架构建的简单后端服务
const bodyParser = require('body-parser');
const cors = require('cors');
const mysql = require('mysql2');

const app = express();
const port = 5500;

// 数据库连接配置
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'qianqianjie.6', // 替换为你的数据库密码
  database: 'userDB'
});

// 连接数据库
connection.connect(err => {
    if (err) {
        console.error('Error connecting to the database:', err);
        throw err;
    }
    console.log('Connected to the database!');
});

app.use(cors({
    origin: '*',
    credentials: true
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// 注册API
app.post('/register', (req, res) => {
    const { username, password } = req.body;
    
    // 检查用户名是否已存在
    connection.query('SELECT * FROM users WHERE username = ?', [username], (err, result) => {
        if (err) {
            console.error('Error checking user:', err);
            res.status(500).send('Server error');
            return;
        }
        if (result.length > 0) {
            // 用户名已存在
            res.status(409).send('Username already exists');
        } else {
            // 插入新用户
            connection.query('INSERT INTO users (username, password) VALUES (?, ?)', [username, password], (err, result) => {
                if (err) {
                    if (err.code === 'ER_DUP_ENTRY') {
                        // 处理“重复条目”错误
                        res.status(409).send('Username already exists');
                    } else {
                        console.error('Error registering user:', err);
                        res.status(500).send('Server error');
                    }
                    return;
                }
                res.send('User registered successfully!');
            });
        }
    });
});
  • 解释:这段代码是一个使用Node.js和Express框架构建的简单后端服务,它提供了用户注册和登录的功能
  • 使用Node.js和Express框架构建的后端服务,提供用户注册和登录功能。主要依赖包括express用于创建HTTP服务器,body-parser解析请求体,cors处理跨源资源共享,以及mysql2与MySQL数据库交互。通过mysql.createConnection配置数据库连接,并在连接成功后定义了两个主要API:/register和/login。在注册过程中,系统检查用户名是否已存在,若不存在则将用户信息存储在数据库中;在登录过程中,系统验证用户名和密码的匹配性。错误处理机制确保了对数据库查询错误和重复用户名的适当响应。为了增强安全性,建议对密码进行加密存储,并使用HTTPS协议保护数据传输。此外,数据验证和日志记录是提升系统可靠性和可维护性的关键技术。整体设计应具备扩展性,以便未来添加更多功能,如密码重置和用户信息更新。

🍴 实现成果展示

实现成果

🔍目录说明和使用说明

🌍目录组织

项目文件目录结构

/

  • .gitkeep
  • home/
    • css文件
    • html文件
    • js文件
  • login/
    • css文件
    • html文件
    • js文件
  • message/
    • css文件
    • html文件
    • js文件
  • previous version-login-register/
    • css文件
    • html文件
    • js文件
  • project/
    • css文件
    • html文件
    • js文件
  • register/
    • css文件
    • html文件
    • js文件

🎧 使用说明

  1. 安装依赖:在项目根目录下运行npm install安装项目依赖。
  2. 启动后端:在server目录下运行node server.js启动后端服务器。
  3. 启动前端:在client目录下运行npm start启动前端开发服务器。
  4. 访问项目:在浏览器中访问http://localhost:5500即可查看项目。

📖 界面预览




🖌️ 单元测试

🍲 测试工具及学习

我们选用了unittest作为测试工具,通过查阅官方文档和在线教程学习单元测试的基本概念和实现方法。
unittest单元测试简易教程

  • 什么是单元测试?
    单元测试是针对程序中最小可测试部分(通常是函数或方法)进行的测试。

  • 为什么需要单元测试?
    确保代码在修改后仍能按预期工作。
    帮助开发者及早发现错误。
    提高代码质量,便于维护和重构。
    节省手动测试的时间。

  • 环境准备
    由于unittest是Python的标准库,你不需要安装任何额外的包。只需确保你的环境中有Python即可。

  • 编写第一个单元测试

    1.创建一个函数
    首先,创建一个简单的函数用于测试。例如,创建一个math_operations.py文件:
    2.编写测试用例
    创建一个测试文件test_math_operations.py:
    3.运行测试
    在命令行中运行以下命令来执行测试:
    bash
    python -m unittest test_math_operations.py
    如果一切正常,你将看到测试通过的消息。

  • 进阶测试技巧

  • 测试异常
    使用assertRaises来测试代码是否抛出预期的异常。

🚀 单元测试代码及说明

// 后端单元测试示例
const request = require('supertest');
const app = require('../server/app');

describe('GET /api/data', () => {
  it('should return a list of data', async () => {
    const response = await request(app).get('/api/data');
    expect(response.statusCode).toBe(200);
    expect(Array.isArray(response.body)).toBe(true);
  });
});
  • 解释:这是一个使用Jest和Supertest编写的后端单元测试,测试了GET请求/api/data是否返回了一个数据列表。

🔧 构造测试数据的思路

编写测试代码,我们主要考虑几个关键功能:账号注册、登录、项目发布和聊天功能。

  1. 账号注册功能测试
    测试用例 1: 输入有效的用户名和密码,期望结果是注册成功。
    测试用例 2: 输入已存在的用户名,期望结果是注册失败,提示用户名已存在。
    测试用例 3: 输入空的用户名或密码,期望结果是注册失败,提示信息不完整。
    测试用例 4: 输入非法格式的用户名(如特殊字符过多)或密码(如太短),期望结果是注册失败,提示格式错误。
  2. 账号登录功能测试
    测试用例 5: 输入正确的用户名和密码,期望结果是登录成功。
    测试用例 6: 输入错误的密码,期望结果是登录失败,提示密码错误。
    测试用例 7: 输入不存在的用户名,期望结果是登录失败,提示用户不存在。
    测试用例 8: 输入空的用户名或密码,期望结果是登录失败,提示信息不完整。
  3. 项目发布功能测试
    测试用例 9: 登录后,输入有效的项目信息并发布,期望结果是项目发布成功。
    测试用例 10: 尝试发布一个空项目或信息不完整的项目,期望结果是发布失败,提示信息不完整。
    4.聊天功能测试
    测试用例 11: 两个用户都登录后,A用户向B用户发送消息,期望结果是B用户能收到消息。
    测试用例 12: 用户尝试发送空消息,期望结果是发送失败,提示消息不能为空。

密码过于复杂时:

未输入正确的大学名称:

输入项为空时:

🧾 Github代码签入记录截图

Github代码签入记录
Github代码签入记录
Github代码签入记录

🖋️ 遇到的代码模块异常或结对困难及解决方法

🧩 问题描述

在开发过程中,我们遇到了前后端数据交互异常的问题,导致前端无法正确获取后端数据。

🪄 做过哪些尝试

  1. 检查接口:检查前后端接口是否一致,确保请求的参数和返回的数据格式正确。
  2. 调试代码:使用调试工具逐步排查代码,查找问题所在。
  3. 查看日志:查看后端日志和前端控制台输出,分析错误信息。

⚙️ 是否解决

通过逐步排查和调试,最终找到了问题所在并解决了该问题。

🪄 有何收获

通过解决该问题,我们加深了对前后端交互的理解,提高了调试和排查问题的能力。

🙂 评价队友

📖 值得学习的地方

办事认真,做事效率高。

🔧 需要改进的地方

代码利用率低,会稍微出错。

posted @ 2024-10-10 23:57  FungusTanion  阅读(18)  评论(0编辑  收藏  举报