软件工程结对作业(第二次之程序实现)

这个作业属于哪个课程 软件工程
这个作业要求在哪里 作业要求
这个作业的目标 通过与队友的协作交流完成一个软件的设计,并进行测试与运用
学号 102202107&&102202140

2024秋软件工程第二次结对作业报告

项目信息

GitHub仓库地址: 102202107-102202140仓库

项目名称: ProjectPartner

结对成员与分工:

本次结对编程作业中,我们根据个人的技能和兴趣进行了明确的分工,以确保项目的高效和顺利进行。

郭心怡 (102202140)

  • 使用Flutter框架进行应用的界面设计和开发。
  • 实现用户认证和授权机制。
  • 进行前端单元测试,确保代码质量和功能正确性。

王勤琛 (102202107)

  • 使用Flutter框架进行应用的界面设计和开发。
  • 实现项目发布模块,包括表单输入和数据展示。

共同责任

  • 项目管理:使用GitHub进行代码版本控制,并通过Pull Request进行代码审查。
  • 文档编写:共同维护项目文档,包括README和PSP表格的更新。
  • 测试和部署:协作进行系统集成测试,确保项目按时发布。

PSP2.1 表格

个人软件开发流程阶段 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60
Estimate 估计 40
Development 开发 640
Analysis 需求分析 120
Design Spec 生成设计文档 40
Design Review 设计复审 30
Coding Standard 代码规范 20
Design 具体设计 80
Coding 具体编码 500
Code Review 代码复审 60
Test 测试 160
Reporting 报告 60
Test Report 测试报告 20
Size Measurement 计算工作量 20
Postmortem & Process Improvement Plan 事后总结与过程改进计划 40
合计 总计 2000

代码实现思路

本次项目“ProjectPartner”使用Flutter框架进行移动端应用开发,实现了用户界面和用户体验。以下是具体的实现思路:

  1. 需求分析:通过用户访谈,我们确定了应用需要实现的核心功能,包括项目发布、项目浏览和实时交流等。

  2. 系统设计:基于需求分析,我们设计了应用的用户界面和用户交互流程。

  3. 前端开发:使用Flutter框架构建应用的用户界面和用户体验。

  4. 数据存储:使用本地存储(如shared_preferences)或Flutter推荐的数据库(如sqflite)来保存项目数据。

  5. 测试:编写单元测试和集成测试,确保代码质量和系统稳定性。

  6. 部署:将应用打包并发布到相应的平台。

关键实现的流程图

以下是使用Mermaid格式绘制的项目发布流程图:

sequenceDiagram participant U as 用户 participant FE as 前端应用 participant S as 本地存储 U->>FE: 选择发布项目 FE->>U: 显示发布表单 U->>FE: 提交项目信息 FE->>S: 保存项目信息 S->>FE: 确认保存 FE->>U: 显示发布结果

重要的/有价值的代码片段

首页底部导航栏实现

return Scaffold(
  appBar: AppBar(
    title: Text('欢迎, ${widget.userName}'),
  ),
  body: pages[_selectedIndex],
  bottomNavigationBar: BottomNavigationBar(
    items: const [
      BottomNavigationBarItem(
        icon: Icon(Icons.home),
        label: '主页',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.message),
        label: '消息',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.person),
        label: '个人',
      ),
    ],
    currentIndex: _selectedIndex,
    selectedItemColor: Colors.blue,
    unselectedItemColor: Colors.grey,
    onTap: onItemTapped,
  ),
);

解释:此代码段实现了一个底部导航栏,允许用户在不同的页面(主页、消息、个人)之间切换。BottomNavigationBar控件使用onTap回调来处理用户的点击事件,更新当前选中的页面。

消息列表和点击事件处理

class MessageList extends StatelessWidget {
  final List<Message> messages;
  final ValueChanged<String> onMessageTap;

  const MessageList({
    Key? key,
    required this.messages,
    required this.onMessageTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: messages.length,
      itemBuilder: (context, index) {
        final message = messages[index];
        return ListTile(
          leading: CircleAvatar(
            backgroundImage: NetworkImage(message.avatarUrl),
          ),
          title: Text(message.sender),
          subtitle: Text(message.content),
          onTap: () => onMessageTap(message.userId),
        );
      },
    );
  }
}
}

解释:MessageList是一个无状态组件,用于展示一个消息列表。每个消息项是一个ListTile,包含发送者的头像、名称和消息内容。当用户点击某个消息时,会触发onMessageTap回调,传递被点击消息的用户ID。

附加特点设计与展示

设计的创意独到之处

意义:在本次项目中,我们特别注重提升用户体验和应用的实用性。一个独特的设计是我们实现了一个离线浏览功能,它允许用户在没有网络连接的情况下,依然可以浏览本地保存的项目信息。这个设计的意义在于提高了应用的可用性和用户体验,尤其是在网络不稳定或无法连接到服务器的情况下,用户仍然能够访问和查看项目信息。

实现思路

为了实现离线浏览功能,我们采用了Flutter的shared_preferences插件来保存用户浏览过的项目信息。这样,即使在离线状态下,用户也可以访问这些信息。我们首先将项目数据保存到本地存储中,然后在应用启动或用户请求时,从本地存储中读取数据并显示给用户。

重要的代码片段

Future<void> _saveProjectToLocalStorage(String projectName) async {
    final storage = await SharedPreferences.getInstance();
    storage.setString('project_name', projectName);
}

// 在应用启动时读取本地存储的项目信息
Future<void> _loadProjectsFromLocalStorage() async {
    final storage = await SharedPreferences.getInstance();
    String? projectName = storage.getString('project_name');
    if (projectName != null) {
        // 加载项目信息到UI
    }
}

解释:上述代码片段展示了如何使用shared_preferences来保存和读取项目名称到本地存储。_saveProjectToLocalStorage函数用于保存项目名称,而_loadProjectsFromLocalStorage函数用于在应用启动或需要时从本地存储中读取项目信息。这样,即使在没有网络的情况下,用户也能够查看之前保存的项目信息。

实现成果展示

具体代码组成:

  • 项目结构:首先,定义整个项目的结构,包括主页面(HomeScreen)、登录页面(LoginPage)、注册页面(RegisterPage)、聊天页面(ChatPage)、课程页面(CoursePage)以及项目详情页面(ProjectDetailPage 和 TeamInfoPage)。

  • 状态管理:使用Flutter的状态管理功能,如StatefulWidgetsetState,来更新页面中的UI元素。对于登录和注册页面,使用TextEditingControllerFocusNode来管理输入框的文本和焦点。

  • 数据传递:通过构造函数或全局变量(如SharedPreferences)来传递数据,如在登录页面验证成功后,将用户名和密码保存到SharedPreferences中,并在后续页面中使用。

  • 网络通信:与服务器进行通信,使用Flutter的HTTP客户端库来发送请求和接收响应。

  • 页面导航:使用Navigator来在不同页面之间进行导航,如从主页面跳转到聊天页面或项目详情页面。

  • UI设计:使用Flutter的Material Design组件来构建UI,如AppBarListViewTextFieldElevatedButton等。

ProjectPartner 项目目录结构

以下是 ProjectPartner 项目的目录组织结构,描述了项目中每个主要文件夹和文件的用途:
ProjectPartner/
├── .vscode/ # Visual Studio Code 配置文件
├── android/ # Android 项目配置和资源文件
├── ios/ # iOS 项目配置和资源文件
├── lib/ # Dart 源代码,包含应用的逻辑
│ ├── models/ # 数据模型
│ ├── pages/ # 应用的主要页面
│ │ ├── academic_page.dart
│ │ ├── chat_page.dart
│ │ ├── competition_page.dart
│ │ ├── course.dart
│ │ ├── create_team_page.dart
│ │ ├── home_page.dart
│ │ ├── login_page.dart
│ │ ├── notification_page.dart
│ │ ├── personal_information.dart
│ │ ├── profile.dart
│ │ ├── register_page.dart
│ │ ├── team_info_page.dart
│ │ └── testlogin.dart
│ ├── widget/ # 应用的自定义组件和部件
│ ├── message_list.dart
├── main.dart # 应用的入口文件
├── linux/ # Linux平台的配置文件
├── macos/ # macOS平台的配置文件
├── test/ # 测试目录
└── README.md # 项目说明文档

使用说明

下载apk文件,在Android手机上安装程序(注意:本应用仅在Android手机上可安装);注册账号,进入应用,开始使用。

单元测试

由于篇幅限制,这里仅展示我们为Message类创建的一个单元测试示例。

选用的测试工具

本项目使用Flutter自带的测试框架进行单元测试,即package:test

如何学习单元测试

  • 阅读官方文档:阅读package:test的官方文档,了解其基本用法和API。
  • 观看教程:在线有许多关于Flutter单元测试的教程,例如在Bilibili上搜索Flutter单元测试教程。
  • 实践:通过实际编写测试代码来加深理解。

简易教程

  1. 添加依赖

    pubspec.yaml文件中添加test依赖:

    dev_dependencies:
      flutter_test:
        sdk: flutter
      test: ^1.16.8
    

2.创建测试文件

test 目录下创建测试文件,例如 message_test.dart

3.编写测试代码

import 'package:flutter_test/flutter_test.dart';
import 'package:your_project/models/message.dart';

void main() {
  group('Message class', () {
    test('should create a message with correct properties', () {
      final message = Message(
        sender: 'Alice',
        content: 'Hello, Bob!',
        time: '10:00',
        avatarUrl: 'https://example.com/avatar.png',
        userId: '12345',
      );

      expect(message.sender, 'Alice');
      expect(message.content, 'Hello, Bob!');
      expect(message.time, '10:00');
      expect(message.avatarUrl, 'https://example.com/avatar.png');
      expect(message.userId, '12345');
    });

    test('should throw if sender is null', () {
      expect(
        () => Message(sender: null, content: 'Hello, Bob!', time: '10:00', avatarUrl: 'https://example.com/avatar.png', userId: '12345'),
        throwsAssertionError,
      );
    });
  });
}

4.运行测试
在终端中执行以下命令来运行测试:

flutter test

5.说明测试的函数
第一个测试

  • 目的:验证 Message 类是否可以正确地创建一个消息对象,并验证其属性是否符合预期。
  • 操作:创建一个 Message 对象,并检查其 sendercontenttimeavatarUrluserId 属性是否与创建时传入的值一致。

第二个测试

  • 目的:验证当 sender 参数为 null 时,构造函数是否抛出 AssertionError
  • 操作:尝试创建一个 Message 对象,其中 sender 参数为 null,并捕获预期的异常。

构造测试数据的思路

正常情况

  • 操作:构造符合预期的正常数据,确保对象可以正确创建。例如,使用有效的字符串、数字等作为属性值。

边界情况

  • 操作:考虑边界值,例如字符串为空、数字为0或负数等,以确保对象在极端情况下的行为。

异常情况

  • 操作:构造会导致错误或异常的数据,例如传递非法格式的数据,确保代码能正确处理这些异常情况。

如何考虑将来测试人员的***难

覆盖所有分支

  • 策略:确保测试覆盖所有的代码分支,包括正常路径和异常路径,以确保代码在各种情况下都能正常工作。

使用Mock

  • 策略:对于依赖外部资源或服务的部分,使用Mock对象来模拟行为,确保测试的独立性和稳定性。

随机数据

  • 策略:使用随机数据生成测试数据,以覆盖更多未预见的情况,增强测试的全面性。

通过这些方法,我们可以确保单元测试的全面性和健壮性,应对未来可能的挑战。

Github的代码签入记录

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

问题描述

在实现项目伙伴招募功能时,我们遇到了一个难题:如何确保用户在离线状态下仍然可以访问和查看项目信息。此外,在结对编程过程中,我们发现代码风格不一致和沟通不畅也严重影响了开发效率。

做过哪些尝试

  1. 离线数据访问问题

    • 初步尝试使用本地数据库存储项目信息,但在应用重启后发现数据丢失的问题。
    • 尝试使用 shared_preferences 插件来持久化存储项目信息。
  2. 代码风格不一致

    • 分别按照个人习惯编写代码,导致代码难以阅读和维护。
    • 尝试统一代码风格,但缺乏明确的编码规范。
  3. 沟通不畅

    • 开发过程中缺乏有效沟通,导致开发进度不同步。
    • 尝试使用即时通讯工具加强沟通,但效果有限。

是否解决

  1. 离线数据访问问题

    • 通过使用 shared_preferences 成功解决了数据持久化问题,现在用户即使在离线状态下也能访问项目信息。
  2. 代码风格不一致

    • 制定了一套明确的编码规范,并使用代码格式化工具如 Dartfmt 来统一代码风格。
  3. 沟通不畅

    • 开始定期举行简短的站立会议,讨论进展和问题,大大提升了团队协作效率。

有何收获

通过解决这些问题,我们学会了以下几点:

  • 使用 shared_preferences 进行数据持久化:对于离线数据访问的处理有了更深的理解。
  • 制定编码规范:明白了统一代码风格对于项目维护的重要性。
  • 团队协作:加强沟通对于提升团队合作效率的重要性,学会了更有效的沟通方法。

这些经验不仅帮助我们完成了项目,也为未来的开发工作提供了宝贵的经验。

队友评价 - 王勤琛

值得学习的地方

  • 技术能力:王勤琛在Flutter框架的使用上非常熟练,能够快速实现复杂的UI和交云逻辑。
  • 问题解决:面对开发中的难题,她总能冷静分析并找到有效的解决方案。
  • 责任心:王勤琛对自己的工作非常负责,总是确保代码的质量和功能的正确性。

需要改进的地方

  • 时间管理:在项目截止日期临近时,王勤琛有时会因为时间管理不当而感到压力。

队友评价 - 郭心怡

值得学习的地方

  • 创新思维:郭心怡在设计应用功能时总能提出创新的想法,为项目增添亮点。
  • 团队合作:她非常注重团队合作,总是愿意协助队友解决问题,是团队中不可或缺的一员。
  • 学习态度:郭心怡对新技术充满好奇心,总是积极学习并将其应用到项目中。

需要改进的地方

  • 细节关注:在编码过程中,有时会忽略一些细节问题。
posted on 2024-10-10 17:38  102202107  阅读(8)  评论(0编辑  收藏  举报