MindArch Project Team Code Standards

Abstract: This document provides comprehensive coding standards and best practices for the Heart Island (MindCarer) mental health management system development team. It covers architecture, naming conventions, code style, Qt development, server-side programming, database design, and security considerations.

1. Project Overview

This document summarizes the code standards and best practices followed by our team during the development of the Heart Island (MindCarer)​ mental health management system. The project adopts a C/S architecture​ with the following technical stack:

  • Client: Qt Creator 4.8.2 (C++)

  • Server: Visual Studio 2019

  • Database: SQLite

2. Architecture Standards

2.1 Three-Tier Architecture Design

The system employs a three-tier architecture​ with clear separation of concerns:

Client (Qt/C++)
    ↓
Front Server (Gateway Layer)
    ↓
Back Server (Business Logic Layer)
    ↓
Database (SQLite)

Architecture Characteristics:

  • Clear separation between frontend and backend responsibilities

  • Front server manages connections and request forwarding

  • Back server handles business logic and database operations

  • Dual Socket architecture: Main Socket for synchronous requests, Push Socket for server-initiated notifications

2.2 Directory Structure Specification

MindCarer_Code/
├── client/                    # Client-side code
│   ├── *.h                   # Header files
│   ├── *.cpp                 # Implementation files
│   ├── *.ui                  # Qt UI files
│   └── resources/            # Resource files
├── Server_Code/
│   ├── Front_Server/         # Front server
│   └── Back_Server/          # Back server
└── Database_Backup/          # Database scripts

3. Naming Conventions

3.1 File Naming

  • Use PascalCase​ for class files

  • Header files: .hextension

  • Implementation files: .cppextension

Examples:

// Correct
MainWindow.h / MainWindow.cpp
FrontClient.h / FrontClient.cpp

// Avoid
mainwindow.h
front_client.cpp

3.2 Class Naming

  • Use PascalCase

  • Names should clearly express class responsibilities

  • Task classes end with Task

  • Page/Window classes end with Pageor Window

Examples:

class MainWindow;
class LoginTask;
class HomePage;
class BaseModel;

3.3 Variable Naming

Member Variables: m_prefix + camelCase

class MainWindow {
private:
    HomePage* m_homePage;
    bool m_dragging;
    QPoint m_dragStartPos;
};

Local Variables: camelCase

void LoginTask::do_service() {
    LOGIN_REQ recv_body = {0};
    std::string phone = std::string(recv_body.user_phone);
}

Constants: UPPER_CASE with underscores

#define PACKAGESIZE 8192
const int MAX_RETRIES = 5;

3.4 Function Naming

Qt Slots: on_prefix + widget name + action

void on_btnHome_clicked();
void on_btnSendCodeLogin_clicked();

Member Functions: camelCase

void setUserInfo(const QString& userId, const QString& userName);
bool ensureConnected();

Virtual Functions: snake_case

virtual void do_service() = 0;

3.5 Enum and Structure Naming

Enums: snake_case for type, UPPER_CASE for values

enum service_type {
    SMS_CODE = 0,
    LOGIN = 1,
    REGISTER = 2
};

Structs: UPPER_CASE with underscores

struct HEAD {
    int service_type;
    int data_len;
};

struct LOGIN_REQ {
    char user_phone[12];
    char user_pwd[33];
};

4. Code Style Guidelines

4.1 Indentation and Spacing

  • 4 spaces​ for indentation (no tabs)

  • Spaces around operators

  • Space after commas

// Correct
int result = a + b;
function(param1, param2, param3);

4.2 Brace Style

Classes and Functions: Braces on new lines

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
};

Control Statements: Braces on same line

if (condition) {
    // code
} else {
    // code
}

for (int i = 0; i < count; i++) {
    // code
}

4.3 Comment Standards

File Header Comments:

// ========================================
// File: LoginTask.cpp
// Purpose: Handle user login business logic
// Author: Team Name
// Date: 2024-XX-XX
// ========================================

Class Documentation:

/**
 * @brief Front server client class
 * 
 * Responsible for establishing connections with front server,
 * sending requests and receiving responses
 */
class FrontClient : public QObject {
    // ...
};

Inline Comments:

// Password login mode: only send password, leave code field empty
if (isPasswordMode) {
    QString password = ui->editPwdLogin->text();
    // ...
}

5. Qt Development Standards

5.1 Signals and Slots

Preferred Syntax: New-style syntax (function pointers)

connect(m_settingsPage, &SettingsPage::showChangePasswordPage,
        this, &MainWindow::onShowChangePasswordPage);

5.2 Memory Management

Parent-Child Relationships:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::MainWindow)
{
    m_homePage = new HomePage(this);  // Specify parent object
    m_contactsPage = new ContactsPage(this);
}

Safe Deletion: Use deleteLater()instead of delete

void MainWindow::onLogout() {
    this->close();
    this->deleteLater();  // Safe deletion
}

5.3 UI Design Standards

Widget Naming:

// Buttons
QPushButton* btnHome;
QPushButton* btnSendCode;

// Input fields
QLineEdit* editPhoneLogin;
QLineEdit* editPwdLogin;

// Labels
QLabel* lbHome;
QLabel* lbUserName;

6. Server-Side Development Standards

6.1 Task Class Design

Base Class Design:

class BaseTask {
protected:
    char* recv_msg_package;
    int client_fd;
    int package_len;
    
public:
    BaseTask(char* recv_msg_package, int len, int client_fd);
    virtual ~BaseTask();
    virtual void do_service() = 0;  // Pure virtual function
};

Derived Class Implementation:

class LoginTask : public BaseTask {
public:
    LoginTask(char* recv_msg_package, int len, int client_fd);
    void do_service() override;
};

void LoginTask::do_service() {
    // 1. Parse request
    LOGIN_REQ recv_body = {0};
    memcpy(&recv_body, this->recv_msg_package + sizeof(HEAD), sizeof(LOGIN_REQ));
    
    // 2. Business processing
    BaseModel* model = ModelControl::getInstance()->getModel();
    LOGIN_RESP resp_body = model->LoginCheck(phone, pwd);
    
    // 3. Send response
    HEAD resp_head = {0};
    resp_head.service_type = LOGIN;
    resp_head.data_len = sizeof(LOGIN_RESP);
    // ...
}

6.2 Database Operation Standards

RAII Wrapper:

class SQLiteDB {
public:
    SQLiteDB() : db_(nullptr) {}
    ~SQLiteDB() { close(); }
    
    bool open(const std::string& db_path);
    void close();
    bool execute(const std::string& sql);
    
private:
    sqlite3* db_;
    SQLiteDB(const SQLiteDB&) = delete;
    SQLiteDB& operator=(const SQLiteDB&) = delete;
};

Prepared Statements:

class SQLiteStmt {
public:
    bool prepare(sqlite3* db, const std::string& sql);
    bool bindInt(int index, int value);
    bool bindText(int index, const std::string& value);
    bool execute();
    
private:
    sqlite3_stmt* stmt_;
};

7. Database Design Standards

7.1 Table Naming

  • Use lowercase with underscores

  • Use plural form for collections

CREATE TABLE users (...);
CREATE TABLE daily_assessments (...);

7.2 Field Naming

  • Use lowercase with underscores

  • Primary key: id

  • Foreign key: table_name_id

  • Timestamp: _atsuffix

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    phone CHAR(12) NOT NULL UNIQUE,
    pwd_hash CHAR(64) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_login_at DATETIME
);

7.3 Index Standards

CREATE INDEX idx_users_phone ON users(phone);
CREATE INDEX idx_users_last_login ON users(last_login_at);

8. Security Standards

8.1 Password Security

Password Hashing:

QString password = ui->editPwdLogin->text();
QByteArray pwd = QCryptographicHash::hash(password.toUtf8(), 
                                        QCryptographicHash::Md5).toHex();

8.2 SQL Injection Protection

Use Prepared Statements:

// Correct: Parameter binding
SQLiteStmt stmt;
stmt.prepare(db->get(), "SELECT * FROM users WHERE phone=?");
stmt.bindText(1, phone);

// Avoid: String concatenation
std::string sql = "SELECT * FROM users WHERE phone='" + phone + "'";

8.3 Input Validation

Client-Side Validation:

QRegularExpression phoneRegex("^1[3-9]\\d{9}$");
if (!phoneRegex.match(phone).hasMatch()) {
    QMessageBox::warning(this, "Error", "Invalid phone number format");
    return;
}

9. Performance Optimization

9.1 Database Optimization

WAL Mode:

sqlite3_exec(db_, "PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL;", 
             nullptr, nullptr, &err_msg);

Batch Operations with Transactions:

db->beginTransaction();
for (const auto& item : items) {
    // Insert operations
}
db->commit();

9.2 UI Optimization

Asynchronous Data Loading:

QTimer::singleShot(100, this, [this, userId, userName]() {
    m_homePage->setUserInfo(userId, userName);
});

10. Version Control Standards

10.1 Commit Message Format

[Type] Brief description

Detailed description (optional)

Related Issue: #123

Type Labels:

  • [Feature]New feature

  • [Fix]Bug fix

  • [Refactor]Code refactoring

  • [Docs]Documentation updates

Conclusion

These coding standards represent our team's collective experience in developing the Heart Island project. By following these guidelines, we ensure code consistency, maintainability, and quality across our codebase. Remember that standards evolve with technology and experience, so we regularly review and update these guidelines.

Key Takeaways:

  • Consistency is more important than perfect syntax

  • Document any deviations from standards

  • Regular code reviews help maintain quality

  • Continuous improvement is essential

更多推荐