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.

...全文
44 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

170

社区成员

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

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