目录
最近家里有一些物品不能正常用了,本着能修就不换的态度,从互联网的维修平台预约了师傅进行上门维修。师傅在维修的过程中,我观察到不同工种的师傅都有自己趁手的工具包。比如维修热水器的是热水器的工具包,维修洗漱池是洗漱池的工具包,维修洗衣机是洗衣机的工具包。
通过生活场景,让我联想到,如果我们也希望通过互联网平台接单帮别人开发软件,那是不是也需要构造一套自己合适的工具包呢?
1 技术选型
如果把开发软件比喻为修热水器,那么我们要从工具包中选择合适的工具,包括拆卸、更换配件、重新安装、加水加电测试。那这一系列的过程可以统称为软件架构。软件架构就是考虑不同的阶段使用不同的工具。
要进行软件架构首先面临技术选项的问题,需要确定自己比较擅长的技术栈。通常流行的技术栈有如下搭配:
1.1 编程语言
- Python: Django (功能全面), Flask/FastAPI (轻量灵活)
- Node.js: Express (经典灵活), NestJS (类 Spring Boot, 强类型), Koa
- Java: Spring Boot (生态强大, 企业级)
- Go: Gin (高性能, 简洁)
- PHP: Laravel (开发效率高, 生态成熟)
- Ruby: Ruby on Rails (约定优于配置, 快速开发)
1.2 数据库 (Database)
- 关系型 (SQL): PostgreSQL, MySQL/MariaDB. 适用于结构化数据,事务性要求高的场景。
- 文档型: MongoDB (灵活的数据结构)
- 键值型: Redis (高性能缓存, 简单数据存储)
- 列式: Cassandra (大数据)
1.3 ORM/ODM
(Object-Relational/Document Mapper)主要是用于简化数据库操作,常见的工具有:
- SQLAlchemy (Python), TypeORM/Prisma (Node.js), GORM (Go), Hibernate/MyBatis (Java)
2 架构模式
选择好了工具包之后,就需要思考我们是接小活还是接比较大的活。通常刚起步,也接不了太大的订单,可以考虑方便自己快速交付。在架构模式上我们可以有三种选择:
- 单体架构 (Monolithic): 初期开发快,部署简单。但随着功能增加,可能变得臃肿、难以维护和扩展。对于小型项目或 MVP (Minimum Viable Product) 可能是合适的起点。
- 微服务架构 (Microservices): 将系统拆分成多个独立的服务,每个服务负责特定业务功能。优点是独立开发、部署、扩展,技术栈灵活。缺点是架构复杂,运维成本高,需要处理分布式事务、服务发现、服务间通信等问题。
- 模块化单体 (Modular Monolith): 在单体应用内部划分清晰的模块边界,模块间通过定义的接口交互。是介于单体和微服务之间的一种折衷,既保持了单体开发的简便性,又具备一定的模块化和可维护性。对于接单脚手架,这通常是一个很好的起点。
一般的单子预算都是在大几千,其实选择单体架构是比较合适的。
3 核心功能模块设计
除了考虑架构模式,那开发自己的脚手架都需要考虑哪些部分的内容呢?一般的项目通常要求有后台,有小程序,有的还要求有APP。可以先从搭建后台开始考虑,一个完善的后台通常包括这些部分的内容:
1.用户认证与授权
- 登录注册 (账号密码、手机号、邮箱、第三方登录如微信)
- Token 管理 (JWT, OAuth2, Session)
- 权限控制 (RBAC - Role-Based Access Control 是常用模型)
2.API 接口设计
- 遵循 RESTful 风格或选择 GraphQL
- 统一的 API 响应格式 (包含状态码、消息、数据)
- API 版本管理
- 使用 OpenAPI (Swagger) 等工具生成和维护 API 文档
3.配置管理
- 区分不同环境 (开发、测试、生产) 的配置
- 使用环境变量、配置文件 (YAML, JSON, .env) 等方式管理
- 敏感配置 (如数据库密码、API 密钥) 的安全处理
4.日志系统
- 结构化日志 (JSON 格式方便机器解析)
- 日志分级 (Debug, Info, Warning, Error, Critical)
- 日志轮转 (Log Rotation) 和归档
- 接入统一的日志收集系统 (如 ELK Stack: Elasticsearch, Logstash, Kibana; 或 Loki+Promtail+Grafana)
5.错误处理与异常捕获
- 全局异常处理器,捕获未处理的异常
- 定义清晰的业务错误码
- 统一错误响应格式
6.数据库迁移
- 使用工具管理数据库结构变更 (如 Alembic for SQLAlchemy, TypeORM Migrations, Flyway/Liquibase for Java)
- 保证不同环境数据库结构的一致性
4 可扩展性与可维护性
在编写软件的时候一开始就要设计良好的结构,方便后期扩展和运维。为什么要这样考虑,因为你面对的甲方,即使预算再低,要求都是很高的。
我们经常会遇见自行车的预算,劳斯莱斯的需求。良好的设计保证,即使和客户后续拉扯,只是拉扯价格和预算,但是交付保证一直是稳定的。
可以考虑以下几个方面:
- 模块化设计: 业务逻辑按模块划分,高内聚、低耦合
- 代码规范与风格: 使用 Linter (如 ESLint, Flake8, Checkstyle) 和 Formatter (如 Prettier, Black) 强制执行统一的代码风格
- 面向接口编程: 依赖抽象而非具体实现,方便替换和扩展
- 文档: 清晰的 README 文件,必要的代码注释,API 文档
- 版本控制: 使用 Git 进行版本管理,遵循合理的分支策略 (如 Gitflow)
5 部署与运维
有的项目是一锤子买卖,交付了后续就不怎么修改了。有的客户要靠他营业,要保障每时每刻都可用,所以免不了持续的迭代,可以使用比较现代的部署方式:
- 容器化: 使用 Docker 将应用及其依赖打包,保证环境一致性,简化部署。编写 Dockerfile 和 docker-compose.yml
- 持续集成/持续部署 (CI/CD),比如GitHub Actions, GitLab CI/CD, Jenkins
- 监控与告警,包括系统资源监控 (CPU, 内存, 磁盘, 网络)、应用性能监控、业务指标监控
6 安全性
系统上线之后,安全是重中之重,在开发阶段就要有良好的设计来避免一些常见的安全漏洞
- 输入验证: 永远不要相信用户的输入,对所有输入进行严格校验。
- 防止常见 Web 攻击: SQL 注入, XSS, CSRF, 文件上传漏洞等。使用框架提供的安全特性或引入安全库 (如 Helmet.js for Node.js)。
- HTTPS: 强制使用 HTTPS。
- 密码安全: 使用强哈希算法 (如 bcrypt, Argon2) 存储密码,加盐。
- 依赖安全: 定期扫描项目依赖,更新有漏洞的库 (如 npm audit, pip check, Snyk)。
- API 速率限制 (Rate Limiting): 防止暴力破解和 DoS 攻击。
7 其他通用功能
除了上述需要考虑的功能外,还有一些通用的功能在架构的时候也需要考虑:
- 缓存 (Caching): 使用 Redis 或 Memcached 提升性能。考虑缓存策略(缓存穿透、雪崩、击穿)
- 后台任务/消息队列 (Background Tasks/Message Queue): 处理耗时任务、异步任务 (如发送邮件/短信、数据处理)
- 文件存储: 对接对象存储服务
- 国际化 (i18n) / 本地化 (l10n)
- 测试
总结
自己搭建一个趁手的脚手架是一件不容易的事情,但是总是要从做中学嘛,有了一个确定的目标,然后一步步的把问题拆解开,在搭建的过程中就会收获不少经验。下一篇我们介绍确定技术栈,利用AI编程工具来一步步的搭建属于我们自己的脚手架。