前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >小型项目架构设计:提升可维护性与扩展性的实用原则

小型项目架构设计:提升可维护性与扩展性的实用原则

原创
作者头像
不惑
发布2024-12-02 08:51:34
发布2024-12-02 08:51:34
3760
举报
文章被收录于专栏:GoboyGoboy

Hey小伙伴们,今天要给大家安利一篇优秀的文章,相信大家通过仔细阅读,一定会有所收货!

🔗【文章链接】:程序员启示录

💖 推荐理由:这篇文章是由 江拥羡橙 撰写的,笔者深刻地记录了多年工作的心得与领悟,借由本文,愿为同仁们献上点滴启示。特别欣赏笔者结尾之言:大丈夫行于乱世,当光明磊落。即使处于逆境,也当屈身守分,以待天时,不可与命抗争也

我们也要学习刘皇叔的这句话啊,在等待时机的同时,不断积累自己的力量,完善自我,以便在机会来临时能够抓住。


引言

软件开发过程中,架构设计是至关重要的环节,尤其对于小型项目来说,合理的架构不仅能帮助团队避免后期的重构麻烦,还能大大提升代码的可维护性和可扩展性。尽管小型项目看似不需要复杂的架构设计,但实际应用中,如果架构设计得当,能有效提高开发效率,并为未来可能的扩展打下坚实的基础。在这篇文章中,我们将探讨一些简单易懂的架构设计原则,并结合小型项目的特点,说明如何将这些原则有效应用到实际开发中。

模块化设计

下面我会结合实际的 Java 代码来演示如何在小型项目中实现高效的模块化设计,并应用一些常见的架构设计原则,如单一职责原则、接口与实现分离、依赖倒转原则等。

假设我们正在开发一个简单的待办事项应用,功能包括:

  1. 添加待办事项
  2. 查看待办事项
  3. 标记待办事项为完成
  4. 使用 Thymeleaf 渲染 HTML 页面

我们将使用 Java 编写代码,并应用前面提到的架构设计原则。

1. 单一职责原则 (SRP)

首先,我们将待办事项功能拆分成不同的类,每个类负责一个单一的职责。

代码语言:java
复制
package com.example.todo.model;

// TodoItem.java - 代表待办事项实体
public class TodoItem {
    private String title;
    private boolean isCompleted;

    public TodoItem(String title) {
        this.title = title;
        this.isCompleted = false;
    }

    public String getTitle() {
        return title;
    }

    public boolean isCompleted() {
        return isCompleted;
    }

    public void markAsCompleted() {
        this.isCompleted = true;
    }
}
代码语言:java
复制
package com.example.todo.service;// TodoService.java - 业务逻辑层
import com.example.todo.model.TodoItem;
import com.example.todo.repository.TodoRepository;

import java.util.List;

public class TodoService {

    private TodoRepository todoRepository;

    public TodoService(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    public void addTodoItem(String title) {
        TodoItem item = new TodoItem(title);
        todoRepository.save(item);
    }

    public List<TodoItem> getAllTodoItems() {
        return todoRepository.findAll();
    }

    public void markItemAsCompleted(int index) {
        TodoItem item = todoRepository.findByIndex(index);
        if (item != null) {
            item.markAsCompleted();
            todoRepository.save(item);  // 保存更新后的状态
        }
    }
}

2. 接口与实现分离

在代码中,我们通过接口将数据访问层抽象出来,并提供不同的实现,这样可以保持模块的解耦。

代码语言:java
复制
package com.example.todo.repository;
// TodoRepository.java - 数据访问接口
import com.example.todo.model.TodoItem;

import java.util.List;

public interface TodoRepository {
    void save(TodoItem item);
    List<TodoItem> findAll();
    TodoItem findByIndex(int index);
}
代码语言:java
复制
package com.example.todo.repository;

// InMemoryTodoRepository.java - 内存存储的实现
import com.example.todo.model.TodoItem;

import java.util.ArrayList;
import java.util.List;

public class InMemoryTodoRepository implements TodoRepository {
    private List<TodoItem> todoItems = new ArrayList<>();

    @Override
    public void save(TodoItem item) {
        todoItems.add(item);
    }

    @Override
    public List<TodoItem> findAll() {
        return todoItems;
    }

    @Override
    public TodoItem findByIndex(int index) {
        if (index >= 0 && index < todoItems.size()) {
            return todoItems.get(index);
        }
        return null;
    }
}

3. 依赖倒转原则 (DIP)

通过接口依赖而不是具体实现,使得高层模块 (TodoService) 不依赖低层模块 (InMemoryTodoRepository) 的具体实现,而是依赖于抽象接口 (TodoRepository)。

在上面的代码中,TodoService 类依赖 TodoRepository 接口,而不是 InMemoryTodoRepository 类的具体实现。这样,我们可以很方便地将数据存储方式从内存切换到数据库、文件等,而不需要修改 TodoService 的代码。

4. 分层架构

在实际开发中,我们通常将系统分为不同的层次,如控制层、服务层、数据访问层。

  • 控制层 (Controller):负责接收用户输入,并调用服务层处理业务逻辑。
  • 服务层 (Service):封装具体的业务逻辑。
  • 数据访问层 (Repository):负责与数据库交互,获取或存储数据。
代码语言:java
复制
package com.example.todo.controller;
// TodoController.java - 控制器层
import com.example.todo.repository.InMemoryTodoRepository;
import com.example.todo.service.TodoService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class TodoController {

    private final TodoService todoService;

    public TodoController() {
        this.todoService = new TodoService(new InMemoryTodoRepository()); // 使用内存存储
    }

    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("todos", todoService.getAllTodoItems());
        return "index";  // 视图名称应该是 "index" 而不是 "index.html"
    }

    @PostMapping("/add")
    public String addTodo(@RequestParam("title") String title) {
        todoService.addTodoItem(title);
        return "redirect:/";  // 添加后重定向到首页
    }

    @PostMapping("/complete")
    public String completeTodo(@RequestParam("index") int index) {
        todoService.markItemAsCompleted(index);
        return "redirect:/";  // 完成后重定向到首页
    }
}

5. 模块化设计与扩展性

假设将来我们要添加更多的功能,比如按照优先级排序待办事项,或者支持用户登录。由于我们采用了接口与实现分离的设计,扩展功能时我们不需要修改已有的代码,只需要增加新的模块或类。

例如,假如我们要添加一个 待办事项优先级功能,我们可以这样做:

代码语言:java
复制
// PriorityTodoItem.java - 扩展 TodoItem 类,加入优先级功能
public class PriorityTodoItem extends TodoItem {
    private int priority;

    public PriorityTodoItem(String title, int priority) {
        super(title);
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }
}

TodoService 中,我们可以使用新的 PriorityTodoItem 类来代替 TodoItem 类,从而实现待办事项的优先级功能,而不影响已有的 TodoItem 使用者。

前端展示

接下来我将结合 ThymeleafSpring Boot 来实现一个完整的待办事项应用。我们将使用之前提到的架构设计原则,并通过 Thymeleaf 来实现前端展示。

项目结构

代码语言:properties
复制
├── src/main/java/com/example/todo/
│   ├── controller/           # 控制器层
│   │   └── TodoController.java
│   ├── model/                # 模型层
│   │   └── TodoItem.java
│   ├── repository/           # 数据访问层
│   │   └── TodoRepository.java
│   │   └── InMemoryTodoRepository.java
│   ├── service/              # 服务层
│   │   └── TodoService.java
│   └── TodoAppApplication.java  # Spring Boot 启动类
│
├── src/main/resources/
│   ├── templates/            # Thymeleaf 模板文件
│   │   └── index.html
│   ├── application.properties
│
└── pom.xml                   # Maven 配置文件

Maven 配置

pom.xml 中添加 Spring BootThymeleaf 的依赖:

代码语言:properties
复制
<dependencies>
    <!-- Spring Boot Web Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Boot Thymeleaf Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <!-- Spring Boot DevTools for hot reload (optional) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

配置文件

src/main/resources/application.properties 中,设置端口和模板路径等配置:

代码语言:properties
复制
# 设置应用运行端口
server.port=8080

# Thymeleaf 配置(默认配置可以省略)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

HTML

代码语言:html
复制
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>待办事项</title>

    <!-- 引入 Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- 可选:引入 Google 字体 -->
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">

    <!-- 可选:引入 FontAwesome 图标库 -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
    
    <style>
        /* 自定义样式 */
        body {
            font-family: 'Roboto', sans-serif;
        }
    </style>
</head>
<body class="container mt-5">

<h1 class="text-center">待办事项</h1>

<!-- 添加待办事项表单 -->
<form action="/add" method="post" class="mb-4">
    <div class="mb-3">
        <label for="title" class="form-label">添加待办事项:</label>
        <input type="text" id="title" name="title" class="form-control" required>
    </div>
    <button type="submit" class="btn btn-primary">添加</button>
</form>

<h2>待办事项列表</h2>
<ul class="list-group">
    <th:block th:each="todo, iterStat : ${todos}">
        <li class="list-group-item d-flex justify-content-between align-items-center">
            <span th:text="${todo.title}"></span>
            <span th:if="${todo.isCompleted}" class="badge bg-success">[完成]</span>
            
            <!-- 完成操作按钮 -->
            <form action="/complete" method="post" th:object="${todo}" class="d-inline">
                <input type="hidden" th:value="${iterStat.index}" name="index">
                <button type="submit" class="btn btn-success btn-sm" th:if="${not todo.isCompleted}">
                    <i class="fas fa-check"></i> 标记为完成
                </button>
            </form>
        </li>
    </th:block>
</ul>

<!-- 引入 Bootstrap JS 和 Popper.js -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js"></script>

</body>
</html>
  1. Bootstrap 5 样式:引入了 Bootstrap 5 的 CDN(通过 link 标签)。它为表单、按钮、列表等提供了响应式设计和现代化样式。
  2. Google 字体:添加了 Google Fonts 的 Roboto 字体,使页面字体更美观。
  3. FontAwesome 图标库:通过引入 FontAwesome 的 CDN,为按钮添加了图标。
  4. 自定义样式:在 <style> 标签中增加了简单的自定义样式,以便覆盖默认样式或进行微调。
  5. 表单和按钮样式:使用 Bootstrap 类如 form-control, btn, btn-primary, list-group 等来美化表单、按钮和列表。

效果展示

结尾

总之,架构设计在小型项目中的作用远超我们的预期。通过遵循一些基本的设计原则,比如模块化、分层结构、松耦合和高内聚等,可以为项目的长期发展提供极大的支持。良好的架构设计不仅能够帮助我们快速应对项目需求的变化,还能让代码在未来的维护与扩展中变得更加轻松。希望本文的架构设计原则能够帮助你在小型项目的开发中,打造一个高效、可维护、易扩展的系统架构,为项目的成功奠定基础。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 模块化设计
    • 1. 单一职责原则 (SRP)
    • 2. 接口与实现分离
    • 3. 依赖倒转原则 (DIP)
    • 4. 分层架构
    • 5. 模块化设计与扩展性
  • 前端展示
    • 项目结构
    • Maven 配置
    • 配置文件
    • HTML
    • 效果展示
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档