当前位置: 首页 > news >正文

bestofrs.org! DDD? Rust? WebAssembly?—— 纯血Rust最佳实践齐打交!

开门见山,这是我开源的绣化版本bestofjs——Best of RS!

Github: https://github.com/zhiyanzhaijie/bestofrs
官网: https://bestofrs.org

已上线稳定运行一个多月,目前文档、CI齐全,所以各平台做下宣传。

Preview预览



架构介绍

一个基于 Rust 的Clean & Hexagonal Doamin Driven Design架构, 结合dioxus全栈。

Notice: 本文档所用图表均由Excalidraw绘制, 在此鸣谢。

Clean 架构

先看项目分层:

crates/ - adapters/# Clean Core- app/# Clean Core- domain/# Clean Core- infra/# Clean Core- ui/# User Interface- worker/# User Interface

本项目架构参考 axum-clean-architecture by @Thodin,并结合了 Dioxus fullstack 的工程实践。

核心依赖方向:

domain <- app(application) <- adapter <- infra(infrastructure) <- user interface


Clean Core(DDD核心)

1. Domain Layer(crates/domain/src

Tree图
crates/domain/src ├── auth ├── error.rs ├── lib.rs ├── project ├── repo └── snapshot
Layer 构成与职责
  • auth / project / repo / snapshot:按业务子域划分的领域模型
  • error.rs:领域级错误语义
  • lib.rs:领域模块导出边界

Domain层承载领域语义与业务不变式,只关心领域建模,不关心业务编排与技术实现。

典型单元:以project为例
crates/domain/src/project ├── entity.rs(实体)├── event.rs(领域事件)├── mod.rs └── value_object.rs(值对象)

2. Application Layer(crates/app/src

Tree图
crates/app/src ├── app_error.rs ├── auth ├── backup ├── common ├── lib.rs ├── prelude.rs ├── project ├── repo └── snapshot
Layer 构成与职责
  • commonapp_error.rs:跨 use case 的通用业务逻辑与统一错误语义
  • auth / backup / project / repo / snapshot:不同领域用例(use cases)模块
  • prelude.rs:应用层常用导出

Application层负责业务编排(Use Cases),通过端口抽象依赖外部能力,不直接依赖具体基础设施实现。

典型单元:以project为例
crates/app/src/project ├── command.rs(CQRS - read用例)├── event_handler.rs(领域事件驱动编排)├── impls(充血模型实现,Rich Domain Model)├── mod.rs ├── port.rs(Hexagonal Port)└── query.rs(查询用例)

3. Adapter Layer(crates/adapters/src+crates/ui/src/IO

Tree图
crates/adapters/src ├── auth ├── clock.rs ├── github.rs ├── lib.rs ├── persistence └── prelude.rs
Layer 构成与职责
  • persistence:存储适配实现
  • auth:鉴权/授权相关适配
  • github.rs:外部 API 适配
  • clock.rs:时间能力适配

Adapter层负责技术编排与边界转换,把Application ports落地为具体实现。

补充:HTTP endpoint 的实现代码位于crates/ui/src/IO。这是“物理位置在ui,逻辑归属在Adapter”的工程布局。

典型单元:以persistence/psql为例
crates/adapters/src/persistence/psql ├── backup.rs(数据备份实现)├── db.rs(数据库连接实现)├── mod.rs ├── project_repo.rs(Project 仓储实现)├── repo_repo.rs(Repo 仓储实现)├── repo_tag_repo.rs(Tag 仓储实现)├── runtime.rs(运行时装配)└── snapshot_repo.rs(Snapshot 仓储实现)

4. Infrastructure Layer(crates/infra/src

Tree图
crates/infra/src ├── config ├── lib.rs └── setup.rs
Layer 构成与职责
  • config:配置模型与配置来源
  • setup.rs:装配入口,负责初始化与依赖注入
  • lib.rs:基础设施模块导出

Infrastructure层只做系统装配与启动准备,不承载业务规则。

典型单元:以config为例
crates/infra/src/config ├── mod.rs(配置模块导出)├── settings.rs(配置结构定义)└── toml(环境配置文件目录)

User Interface(表现层)

WorkerUI同属User Interface,但交互对象不同:

  • UI面向用户交互界面
  • Worker面向任务调度与后台执行

1. UI crate(crates/ui/src

Tree图
crates/ui/src ├── IO ├── components ├── impls ├── js ├── lib.rs ├── main.rs ├── root └── types
内容
-`main.rs`:UI/Web 入口与服务启动入口(fullstack) -`root`:页面布局与Router -`components`:可复用 UI 组件(目前,出于KISS原则考虑,我将页面组件也放入其中,受影响于Next.js的App Router组织风格) -`types`前端viewmodel数据结构 -`impls / js`:前端侧实现细节

Notice:IO目录虽物理上位于ui,但本质逻辑为HTTP endpoint adapter的axum实现,在架构归属上属于Adapter
参考下图:

SSR Fullstack的核心

Dioxus v0.7.0+ 版本提供了非常便捷的#[post], #[get]等宏,这些宏在提供无缝的fullstack体验的前提下,又保证了代码整洁。
具体的Fullstack原理请参考Dioxus官方文档。

为了更优雅的SSR实现,我根据以往的前端工程经验,创建了

面向复杂ui组件的mod-like样板:

crates/ui/src/components/**/exampleComp/ ├── mod.rs#组件├── skeleton.rs#loading fallback├── error.rs#错误fallback├── hook.rs#私有hook├── context.rs#私有context├── style.css#若tailwind样式不便├──(optional)sub-Comp/#若有子组件,则样板递归

并封装IOCell组件收敛ssr处理逻辑。

还有最简单的纯组件样板,compName.rs, 这个没有特别点,不做展开。


2. Worker crate(crates/worker/src

Tree图
crates/worker/src └── main.rs
内容

依赖core层功能的快捷应用,当前仅使用到snapshot领域下一个小的快照功能。略。

为什么做 Best Of RS?

  1. 作者本身于bestofjs.org受益良多,在写rust的时候一直想,想着想着就有个这么个点子
  2. 离职期间,想挖掘下Dioxus的潜力,落地一下DDD, 一拍即合,所以Best Of RS出来了(PS:求个💼,请github邮箱联系~♥️)

为什么宣传?

  1. 求Stars要饭
  2. 普及DDD & cleanDDD
  3. 普及Rust & Dioxus & WASM

欢迎使用Best Of RS, 如果有所帮助, Star秋梨膏!Orz!!!

http://www.jsqmd.com/news/587696/

相关文章:

  • 利用快马平台快速搭建yolov5目标检测web应用原型
  • LINQ数据访问技术
  • 告别编译噩梦:用VSCode + CMake Tools 在Windows上优雅地构建和调试ncnn项目
  • 新手福音:在快马平台用OpenClaw轻松学习机械爪控制
  • 让ai替你思考复杂逻辑:基于快马智能生成kafka多消费者组流处理应用
  • 虚拟滚动如何实现高度自适应?解决 Item 动态撑开导致的滚动条跳动
  • 宇宙知识管线 R1—R9 全周期消融
  • Project AirSim避障实战:深度图分割与动态航向规划详解
  • PaddleOCR实战:教你处理扫描版PDF里那些‘拦腰截断’的表格
  • 成都兴诚艺门窗有限公司
  • ffmpeg精确极速剪辑方案
  • 如何应对SQL注入威胁_使用存储过程封装查询降低风险
  • 生产环境Certbot泛域名证书全自动续期完整配置指南(Cloudflare DNS验证)
  • 效率提升秘籍:借助快马平台让winner1300代码生成速度提升300%
  • 深入探讨Laravel Eloquent的Distinct查询
  • HJ喜欢切数组的红
  • 效率翻倍:用快马打造专属阿里悟空AI绘画批量生成工具
  • 实战演练:基于快马平台与方锐理念构建短视频智能配乐应用
  • Qualcomm SA8775P深度解析 ——一颗芯片搞定座舱+智能驾驶?工程师告诉你真相
  • CSS如何实现响应式导航在小屏下的隐藏_利用-checked实现开关交互
  • 新手友好:用快马AI生成第一个Skill-Vetter式自测应用
  • REX-UniNLU实战:无需代码,用Web界面快速分析文本情感与实体关系
  • YimMenu:GTA V 增强与防护工具全攻略
  • Godot 4 2D 物理引擎位置初始化踩坑:add_child() 和 position 到底谁先? (错误位置触发物理事件)
  • seo关键词挖掘工具哪个好_seo数据分析工具哪个最强
  • STM32CubeIDE实战:手把手教你为stm32f767手动添加DSP库(附FPU配置技巧)
  • c语言完美演绎6-20
  • League-Toolkit:英雄联盟客户端全功能智能助手,颠覆传统游戏体验的本地化解决方案
  • 探索Azure REST API与Power BI的无缝集成
  • Golang怎么用sqlc从SQL生成类型安全代码_Golang如何根据SQL语句自动生成Go查询函数【教程】