Extreme Programming Project

2401_83692523 2024-11-24 23:58:58
Course for This Assignment2401_MU_SE_EE308
Group StudentsHuang Xingcheng Guo Yongzhen
First Student IDFZU:832201123 MU:22125469
Second Student IDFZU:832202122 MU:22124594
Assignment RequirementsExtreme Programming: Improve a front-end and back-end separated contact
Objectives of This AssignmentExercise extreme programming ability and learn the basic knowledge of software development
Other Referenceshttps://developer.aliyun.com/article/850913

 

1. Assignment Introduction

1.1 Task Description

The Extreme Programming assignment for Software Engineering involves enhancing the functionality of a front-end and back-end separated address book system. We were required to complete a series of programming tasks within a strict two-day timeline. This assignment emphasizes teamwork, the application of theoretical knowledge, and the development of a reliable system with efficient front-end and back-end integration. The primary functionalities to be implemented include:

  1. Bookmark Contacts: Enable marking contacts as "important" or "frequently used" for quick access.
  2. Multiple Contact Methods: Support adding multiple contact details, such as phone numbers, email addresses, and physical addresses for each contact.
  3. Excel Import and Export: Allow importing contacts from an Excel file and exporting contact data to an Excel file.
  4. Web Deployment: Deploy the address book system to a cloud server for public access.

1.2 Git Repository Link and Coding Standards Link

This blog post provides an in-depth overview of our project, including the final product, system architecture, and the development process. The complete source code can be found in our repository. Sensitive information, such as database credentials, has been excluded from the public repository.

1.3 PSP Table

We recorded the estimated and actual time to develop each module of the program in the PSP sheet.

1.3.1 Development Time Record Sheet

Xingcheng Huang

ModulesTask DescriptionEstimated TimeActual Time
Group Discussion and Demand AnalysisDetermine the requirements of the web page and the functions that can be achieved1 hour1 hour
Knowledge LearningLearning about Excel Import and Export1 hours2 hours
Backend DevelopmentCreate a Spring Boot application and write an interface3 hours5 hours
Backend TestTest whether the web page meets expectations2 hour2 hours
DeployDeploy the application to the server (Alibaba Cloud)2 hours1 hours
Total 9 hours11 hours

Yongzhen Guo

ModulesTask DescriptionEstimated TimeActual Time
Group Discussion and Demand AnalysisDetermine the requirements of the web page and the functions that can be achieved1 hour1 hour
Knowledge LearningLearning about Excel Import and Export1 hours2 hours
Front-end DevelopmentPage design, front-end development using JS2 hours3 hours
Front-end TestTest whether the web page meets expectations1 hour1.5 hours
Front-end and Back-end Integration TestingTest whether the front-end and back-end integration works as expected2 hours3 hours
Total 7 hours10.5 hours

 

1.4 Team Contribution Evaluation

Member NameContribution (%)
Xingcheng Huang85
Yongzhen Guo15

2. Finished Product Display

 

3. Design and Implementation Process

3.1 Project Background

The Address Book Management System aims to provide users with a convenient platform to manage contact information using a modern front-end and back-end separation architecture. The system allows users to display contact information on a webpage and perform intuitive operations such as adding, editing, deleting, and querying contact details.

3.2 Project Significance

This project simplifies the process of managing contact information through a user-friendly web interface. By implementing a front-end and back-end separated architecture, the system enhances responsiveness and user experience while improving maintainability and scalability for future development.

3.3 Design Concept and Technology Selection

When designing the address book application, the following functional modules and technologies were considered:

  1. Front-end and Back-end Separation:

    • The front end uses HTML, CSS, and JavaScript for rendering pages and interacting with the back end.
    • The back end is implemented using Python Flask framework, providing RESTful API interfaces for data exchange.
  2. Contact Management with In-Memory and Persistent Data:

    • Contact information is managed in the back end using Python data models (classes) with support for CRUD operations.
    • Persistent data is achieved through Excel file import and export, ensuring data security and accessibility.
  3. Data Interaction:

    • The Fetch API is used for asynchronous communication between the front end and back end.
    • Data is transmitted in JSON format for lightweight and flexible handling.
  4. Responsive Design:

    • A custom CSS stylesheet ensures a user-friendly interface across different devices.

3.4 Implementation Process

1. Environment Setup

  1. Development Environment Configuration:

    • Install Python and Flask framework:
      
       

      bash

      复制代码

      pip install flask pandas

    • Ensure front-end development tools (e.g., VSCode) are ready.
  2. Data Storage:

    • Define the contact data model in contacts.py.
    • Use Excel files for import and export functionality, simulating persistent storage.

2. Functional Modules

Function 1: User Interface

  • When users visit the system, they will see a clean and intuitive interface.

  • The page design includes a list of contacts and buttons for adding, deleting, and editing contact details.

  • Example interface screenshot:

     


    (Replace with actual interface screenshot)

Function 2: Bookmark Contacts

  • Users can mark contacts as important or frequently used by clicking the "Bookmark" button next to the contact.
  • Implementation:
    • Add an is_bookmarked attribute to the contact model in the back end.
    • Update bookmark status through a POST request from the front end.

Function 3: Multiple Contact Methods

  • Users can associate multiple contact details (e.g., phone numbers, emails, addresses) with each contact.
  • Implementation:
    • Enable dynamic updates to contact properties using class methods in the back end.
    • Handle new information submissions via front-end forms and inputs.

Function 4: Import and Export

  • Export Contacts: Clicking the "Export" button allows users to download the contact list as an Excel file.
  • Import Contacts: Uploading an Excel file with contact information automatically adds new contacts to the system.
  • Implementation:
    • Use the pandas library in the back end to process Excel files.
    • Handle file submission through a front-end upload component.

Function 5: Deployment

  • The system is functional locally via Flask's built-in server and is ready for deployment on a cloud platform for broader access.

When you visit http://127.0.0.1:5000, you will see this interface:

4. Code Description

4.1 Part of Front End

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Address Book</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <h1>Address Book</h1>

    <!-- 输入表单 -->
    <div class="form-container">
        <form id="addContactForm">
            <label>姓名:</label>
            <input type="text" id="contact_name" placeholder="姓名" required>
            <label>学号:</label>
            <input type="text" id="contact_id" placeholder="学号">
            <label>地址:</label>
            <input type="text" id="contact_address" placeholder="地址">
            <label>邮箱:</label>
            <input type="email" id="contact_email" placeholder="邮箱">
            <label>电话:</label>
            <input type="text" id="contact_phone" placeholder="电话">
            <label>备注:</label>
            <input type="text" id="contact_notes" placeholder="备注">
            <button type="submit" class="btn btn-primary">添加联系人</button>
        </form>
    </div>

    <!-- 联系人表格 -->
    <table class="contact-table">
        <thead>
            <tr>
                <th>姓名</th>
                <th>电话</th>
                <th>学号</th>
                <th>邮箱</th>
                <th>地址</th>
                <th>备注</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for contact in contacts %}
                <tr>
                    <td>{{ contact.name }}</td>
                    <td>{{ contact.phone }}</td>
                    <td>{{ contact.id }}</td>
                    <td>{{ contact.email }}</td>
                    <td>{{ contact.address }}</td>
                    <td>{{ contact.notes }}</td>
                    <td>
                        <button onclick="editContact({{ loop.index0 }})" class="btn btn-edit">编辑</button>
                        <button onclick="deleteContact({{ loop.index0 }})" class="btn btn-delete">删除</button>
                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

    <script>
        // 添加联系人
        document.getElementById('addContactForm').addEventListener('submit', function(event) {
            event.preventDefault();
            const name = document.getElementById('contact_name').value;
            const phone = document.getElementById('contact_phone').value;
            const id = document.getElementById('contact_id').value;
            const email = document.getElementById('contact_email').value;
            const address = document.getElementById('contact_address').value;
            const notes = document.getElementById('contact_notes').value;

            fetch('/add_contact', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    name: name,
                    phone: phone,
                    id: id,
                    email: email,
                    address: address,
                    notes: notes
                }),
            }).then(response => response.json())
              .then(data => {
                  if (data.status === "success") {
                      alert("Contact added!");
                      location.reload(); // 刷新页面
                  } else {
                      alert(data.message);
                  }
              });
        });

        // 删除联系人
        function deleteContact(contactId) {
            if (confirm("确定要删除这个联系人吗?")) {
                fetch(`/delete_contact/${contactId}`, {
                    method: 'DELETE',
                }).then(response => response.json())
                  .then(data => {
                      if (data.status === "success") {
                          alert("Contact deleted!");
                          location.reload();
                      } else {
                          alert(data.message);
                      }
                  });
            }
        }

        // 编辑联系人
        function editContact(contactId) {
            const newName = prompt("请输入新的姓名:");
            const newPhone = prompt("请输入新的电话:");
            const newId = prompt("请输入新的学号:");
            const newEmail = prompt("请输入新的邮箱:");
            const newAddress = prompt("请输入新的地址:");
            const newNotes = prompt("请输入新的备注:");

            fetch(`/edit_contact/${contactId}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    name: newName,
                    phone: newPhone,
                    id: newId,
                    email: newEmail,
                    address: newAddress,
                    notes: newNotes
                }),
            }).then(response => response.json())
              .then(data => {
                  if (data.status === "success") {
                      alert("Contact updated!");
                      location.reload();
                  } else {
                      alert(data.message);
                  }
              });
        }
    </script>
</body>
</html>
<body>
    <h1>Address Book</h1>

    <!-- 上传文件表单 -->
    <div class="form-container">
        <form id="importForm" enctype="multipart/form-data">
            <label for="fileInput">导入联系人:</label>
            <input type="file" id="fileInput" name="file" accept=".xlsx">
            <button type="submit" class="btn btn-primary">导入</button>
        </form>
        <button onclick="exportContacts()" class="btn btn-secondary">导出联系人</button>
    </div>

    <script>
        // 导入联系人
        document.getElementById('importForm').addEventListener('submit', function (event) {
            event.preventDefault();
            const fileInput = document.getElementById('fileInput');
            const formData = new FormData();
            formData.append('file', fileInput.files[0]);

            fetch('/import', {
                method: 'POST',
                body: formData
            }).then(response => response.json())
              .then(data => {
                  if (data.status === "success") {
                      alert("Contacts imported successfully!");
                      location.reload();
                  } else {
                      alert("Error: " + data.message);
                  }
              }).catch(error => console.error('Error:', error));
        });

        // 导出联系人
        function exportContacts() {
            window.location.href = '/export';
        }
    </script>
</body>

4.2 Part of Back End

from flask import Flask, render_template, request, jsonify
import pandas as pd
from contacts import Contact

app = Flask(__name__)

# 初始化联系人列表
contacts = []

@app.route('/')
def index():
    return render_template('index.html', contacts=contacts)

@app.route('/add_contact', methods=['POST'])
def add_contact():
    data = request.get_json()
    name = data.get('name')
    phone = data.get('phone')
    student_id = data.get('id')
    email = data.get('email')
    address = data.get('address')
    notes = data.get('notes')

    if not name:
        return jsonify({"status": "error", "message": "Name is required"}), 400

    new_contact = Contact(name=name, phone=phone, id=student_id, email=email, address=address, notes=notes)
    contacts.append(new_contact)
    return jsonify({"status": "success", "contact": new_contact.__dict__})

@app.route('/delete_contact/<int:contact_id>', methods=['DELETE'])
def delete_contact(contact_id):
    if 0 <= contact_id < len(contacts):
        removed_contact = contacts.pop(contact_id)
        return jsonify({"status": "success", "removed_contact": removed_contact.__dict__})
    else:
        return jsonify({"status": "error", "message": "Contact not found"})

@app.route('/edit_contact/<int:contact_id>', methods=['PUT'])
def edit_contact(contact_id):
    if 0 <= contact_id < len(contacts):
        data = request.get_json()
        contact = contacts[contact_id]
        contact.name = data.get('name', contact.name)
        contact.phone = data.get('phone', contact.phone)
        contact.id = data.get('id', contact.id)
        contact.email = data.get('email', contact.email)
        contact.address = data.get('address', contact.address)
        contact.notes = data.get('notes', contact.notes)
        return jsonify({"status": "success", "updated_contact": contact.__dict__})
    else:
        return jsonify({"status": "error", "message": "Contact not found"})

if __name__ == '__main__':
    app.run(debug=True)
import os
from flask import Flask, render_template, request, jsonify, send_file
import pandas as pd
from contacts import Contact

app = Flask(__name__)

# 初始化联系人列表
contacts = []

@app.route('/')
def index():
    return render_template('index.html', contacts=contacts)

@app.route('/add_contact', methods=['POST'])
def add_contact():
    data = request.get_json()
    name = data.get('name')
    phone = data.get('phone')
    student_id = data.get('id')
    email = data.get('email')
    address = data.get('address')
    notes = data.get('notes')

    if not name:
        return jsonify({"status": "error", "message": "Name is required"}), 400

    new_contact = Contact(name=name, phone=phone, id=student_id, email=email, address=address, notes=notes)
    contacts.append(new_contact)
    return jsonify({"status": "success", "contact": new_contact.__dict__})

@app.route('/export', methods=['GET'])
def export_contacts():
    # 将联系人列表导出为 Excel 文件
    data = [{
        "Name": contact.name,
        "Phone": contact.phone,
        "ID": contact.id,
        "Email": contact.email,
        "Address": contact.address,
        "Notes": contact.notes
    } for contact in contacts]
    df = pd.DataFrame(data)
    file_path = "contacts_export.xlsx"
    df.to_excel(file_path, index=False)
    return send_file(file_path, as_attachment=True)

@app.route('/import', methods=['POST'])
def import_contacts():
    # 从 Excel 文件导入联系人
    if 'file' not in request.files:
        return jsonify({"status": "error", "message": "No file provided"}), 400

    file = request.files['file']
    try:
        df = pd.read_excel(file)
        for _, row in df.iterrows():
            contact = Contact(
                name=row.get('Name'),
                phone=row.get('Phone'),
                id=row.get('ID'),
                email=row.get('Email'),
                address=row.get('Address'),
                notes=row.get('Notes')
            )
            contacts.append(contact)
        return jsonify({"status": "success", "message": "Contacts imported successfully"})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

5. Challenges Encountered and Solutions

While working on the project, we encountered several technical challenges. Here’s a breakdown of the key issues and how we addressed them:


5.1 Challenges for Team Member 1 (Backend Development)

Problem:
While implementing the Excel Import and Export functionalities, there were frequent errors during the file reading process. Specifically, the system failed to correctly parse and store the data from the uploaded Excel file.

Solution:
To debug, I added a try-except block in the relevant part of the code to trace the root cause of the issue. It turned out the problem was due to inconsistent column headers in the imported Excel file. After aligning the headers in the file with the system’s expected format, the import functionality worked perfectly. The export functionality was also optimized using the pandas library to ensure proper formatting.


5.2 Challenges for Team Member 2 (Frontend Development)

Problem:
While implementing the “Bookmark Contacts” feature, I faced challenges in ensuring seamless integration between the front-end button and back-end API. Additionally, there were errors in updating the bookmark status on the webpage after interacting with the server.

Solution:
The issue was resolved by thoroughly debugging the Fetch API calls and correcting the endpoint URLs. Furthermore, I worked closely with the backend developer to ensure the API responses were in the correct format. Testing was carried out using Postman to verify the data exchange between the front end and back end. This collaborative effort led to the successful implementation of the Favorites feature.


5.3 Conclusion

This project demonstrated the value of teamwork and collaborative problem-solving. Each team member brought unique skills and perspectives to the table, contributing to the completion of a well-functioning system. Through effective task division and persistence in overcoming challenges, we were able to achieve our project goals.

Looking ahead, we aim to further improve our workflow by incorporating lessons learned from this project, such as conducting more thorough initial testing and improving communication between team members during development.


6. Group Learning Journey

Through this assignment, we gained valuable insights and practical experience. Here are the key takeaways:


6.1 Collaborative Development

We enhanced our teamwork skills by effectively coordinating tasks, sharing progress, and resolving conflicts together.


6.2 Knowledge Application

This project bridged the gap between theoretical knowledge and practical implementation, allowing us to apply concepts from software engineering to real-world coding challenges.


6.3 Technical Proficiency

  • Backend Development:
    We gained hands-on experience with Python Flask, learning to design RESTful APIs and handle data operations such as Excel import/export.

  • Frontend Development:
    By working with HTML, CSS, and JavaScript, we developed skills in creating user-friendly interfaces and implementing interactive features. Debugging tools like Postman and browser developer tools proved invaluable during this process.


6.4 Time Management

Working under tight deadlines required us to carefully plan and prioritize our tasks. This helped improve our ability to deliver quality results within a limited timeframe.

 

Acknowledgments

We are sincerely grateful to our professor and teaching assistants for their guidance and support throughout this project. Their feedback and encouragement have been invaluable to our learning journey.

Thank you for reading about our experience! Please feel free to share any suggestions or feedback to help us improve.

...全文
114 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
打开链接下载源码: https://pan.quark.cn/s/589796089f72 C++课程设计任务列表,涵盖以下内容:1、识别并显示10至99范围内,各位数乘积超过各位数和的数值,例如数字12不满足条件,因为1乘以2小于1加2,故不输出;而数字27满足条件,因为2乘以7大于2加7,因此需要输出该数。2、开发一个功能,用于从用户输入的任意数量实数中找出最大值与最小值:首先要求用户输入一个正整数n,代表数值的个数,随后用户可输入任意n个实数,程序需找出这n个数中的最大值和最小值并将它们展示出来。3、实现两个已排序数组的合并操作:设有数组A和B,且假设这两个数组的元素均已按照降序排列。编写程序将A和B合并成一个新的数组C,并确保C中的元素同样保持降序排列。int A[10]={123, 86,80, 49,33,15,7,0,-1,-3};int B[10]={100,64,51,50,27,19,15,12,5,2};4、设计一个函数,用于计算特定分数序列前n项的总和,该序列为1/2,1/3,1/4,1/5,1/6,1/7,...。要求在主程序中提示用户输入一个整数n,并验证输入的合法性(n需大于1方为有效),若输入合法,则调用求和函数并显示计算结果。5、编写一个程序,计算两个用户输入日期之间的天数差:用户需以year1,month1,day1和year2,month2,day2的格式输入两个日期,程序随后计算这两个日期之间的天数间隔,并将结果输出到屏幕上。要求编制具有如下原型的函数difs2Date:long GetDayDifference(int y1,int m1,int d1,int y2,int m2,int d2);并在主函数中调用此函数,将计...
代码下载地址: https://pan.quark.cn/s/ee8627e4e6d7 ABAP调试器是一种功能强大的工具,可用于在执行期间对ABAP代码进行检验。除了常规的核心功能(例如逐行运行代码以及检验变量、字段符号和引用的值)之外,它还提供了一些辅助性的特性,能够简化并压缩调试会话的时长。并非所有使用者都熟悉这些辅助特性。SAP ABAP调试器是处理和优化ABAP代码开发与维护工作的核心资源,它配备了多样的功能来协助开发人员在运行状态下进行检验和排除故障。此资源着重阐述了ABAP调试器的一些高级特性,涵盖了深入分析调用堆栈、系统级调试、更新会话调试以及提升调试效率的方法。 1. **深入分析调用堆栈**:除了常规的应用程序调试,开发人员有时需要对调用堆栈的内部层级进行深入调试,特别是在错误出现在异步执行的更新处理或系统级程序时。通过启用**系统级调试**,可以访问通常不公开的系统代码,但这也会导致调用堆栈的显著增加,因此需要审慎操作。 2. **系统级调试**:对于不含业务逻辑的系统级程序,开发人员通常无需进行调试。然而,在特定情形下,例如进行错误追踪时,可能需要进入系统代码。借助调试器的“系统调试启用/禁用”选项,可以赋予对系统程序的调试权限。 3. **更新会话调试**:在处理异步更新任务,例如持久化业务数据时,错误可能发生在更新任务内部。激活**更新会话调试**,在更新任务完成后,调试器将自动启动,展示执行路径。比如,在变更成本中心后,通过输入调试指令 "/h" 启动调试,保存后能够看到更新过程中的错误。 4. **分析调用堆栈**:在进行深入调试时,调用堆栈是至关重要的。通过分析调用堆栈,能够定位到引发问题的具体位置,如在VB_V2_NORMAL...
源码链接: https://pan.quark.cn/s/a4b39357ea24 小程序雷达 AI 驱动的小程序生态选型与风险评估工具,把微信小程序开发资源转化为可筛选、可评估、可对比的技术雷达。 线上地址 主站: Vercel: 适合谁 正在做微信小程序技术选型的产品、研发和架构团队。 需要判断 Taro、uni-app、原生小程序、组件库、云开发和 SDK 风险的团队。 需要把历史 awesome 列表转成可筛选、可对比、可验证技术雷达的维护者。 可以做什么 Radar:按推荐状态、风险等级、资源类型、分类和适用场景浏览小程序生态资源。 Quick Search:快速搜索资源并跳转常用页面。 Compare:对比 Taro、uni-app、原生小程序等核心方案。 Advisor:输入选型问题,获得推荐结论、适用/不适用条件、迁移成本、下一步和证据来源。 Doctor:粘贴小程序项目配置,识别框架依赖、过时方案和迁移风险。 Weekly:查看小程序生态周报和近期风险信号。 数据概览 当前数据集中包含 236 个小程序生态资源。 完整资源可在 Radar 页面和导出能力中查看。 核心样例 Taro ★30.6k+ - 使用 React 的方式开发小程序的框架,同时支持生成多端应用 uni-app ★36.1k+ - 使用 Vue 语法开发小程序、H5、App的统一框架 MPX ★2.1k+ - 增强型小程序框架,深度性能优化,支持跨小程序平台开发,完全兼容原生小程序组件 WePY ★21.7k+ - 支持组件化的小程序开发框架 vant-weapp ★12.3k+ - 高颜值、好用、易扩展的微信小程序 UI 库 tdesign-miniprogram ★1.3...

173

社区成员

发帖
与我相关
我的任务
社区描述
2401_MU_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 助教-吴可仪
  • 助教-孔志豪
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧