领域驱动设计模式是当今的热门话题。
领域驱动设计 (DDD) 是一种软件开发方法,通过将实现连接到不断发展的模型来简化开发人员面临的复杂性。
注
**这不是一篇解释在 Golang 中实现 DDD 的“理想”方式的文章,因为作者绝不是这方面的专家。本文是作者根据自己的研究对 DDD 的理解。作者
将非常感谢有关如何改进本文的贡献。**
检查 github 存储库以获取更新的代码:
https://github.com/victorsteven/food-app-server
为什么是 DDD?
以下是考虑使用 DDD 的原因:
-
提供解决疑难问题的原则和模式
-
基于域模型的复杂设计
-
发起技术专家和领域专家之间的创造性合作,以迭代改进解决领域问题的概念模型。
领域驱动设计的思想被Eric Evans颠覆了。他在一本书中写到了它,你可以在这里找到一些亮点
DDD 包括 4 层:
-
域:这是定义应用程序的域和业务逻辑的地方。
-
基础设施:这一层由独立于我们的应用程序存在的一切组成:外部库、数据库引擎等。
-
应用:这一层作为域和界面层之间的通道。将请求从接口层发送到域层,域层对其进行处理并返回响应。
-
接口:这一层包含与其他系统交互的所有内容,例如 Web 服务、RMI 接口或 Web 应用程序以及批处理前端。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--mhcXpSHR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/zxy4sge2vsk0pv53ik9v.jpg)
要对每一层的术语有一个彻底的定义,请参考这个
让我们开始吧。
我们将构建一个食物推荐 API。
如果您没有时间阅读,您可以获取代码。
在此处获取 API 代码。
在此处获取前端代码。
首先要做的是初始化依赖管理。我们将使用 go.mod。从根目录(路径:food-app/)初始化 go.mod:
go mod init food-app
这就是项目的组织方式:
[](https://res.cloudinary.com/practicaldev/image/fetch/s---SDOlNFy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to -uploads.s3.amazonaws.com/i/603kx3hs78n8s7aopood.png)
在这个应用程序中,我们将使用 postgres 和 redis 数据库来持久化数据。我们将定义一个包含连接信息的 .env 文件。
.env 文件如下所示:
该文件应位于根目录(路径:food-app/)
域层
我们将首先考虑域。
该域有几种模式。其中一些是:
实体、值、存储库、服务等。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--v8Z8dxLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/l8ux2zry0gpcf3moy16o.png)
由于我们在这里构建的应用程序很简单,因此我们只考虑两个 domain 模式:entity 和 repository。
实体
这是我们定义事物的“模式”的地方。
例如,我们可以定义一个用户的结构。将 entity 视为域的蓝图。
从上面的文件中,定义了包含用户信息的用户结构,我们还添加了帮助函数来验证和清理输入。调用哈希方法来帮助哈希密码。这是在 infrastructure 层中定义的。
Gorm用作选择的 ORM。
定义食品实体时采用相同的方法。您可以查找回购。
存储库
存储库定义了基础设施实现的方法的集合。这生动地描绘了与给定数据库或第三方 API 交互的方法的数量。
用户的存储库将如下所示:
这些方法在接口中定义。这些方法稍后将在基础设施层中实现。
几乎同样适用于食物存储库这里。
基础设施层
该层实现了存储库中定义的方法。这些方法与数据库或第三方 API 交互。本文将只考虑数据库交互。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--Sq2VGlgp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/as8nb3zr2oq46tjsrgjq.png)
我们可以看到用户的存储库实现是这样的:
好吧,您可以看到我们实现了在 repository 中定义的方法。这可以使用实现 UserRepository 接口的 UserRepo 结构来实现,如下行所示:
//UserRepo implements the repository.UserRepository interface
var _ repository.UserRepository = &UserRepo{}
进入全屏模式 退出全屏模式
您可以在此处查看有关食物存储库如何实施的存储库。
因此,让我们通过创建包含以下内容的 db.go 文件来配置我们的数据库:
从上面的文件中,我们定义了 Repositories 结构,它保存了应用程序中的所有存储库。我们有用户和食物储存库。 Repositories 也有一个 db 实例,它被传递给 user 和 food 的“构造函数”(即 NewUserRepository 和 NewFoodRepository)。
应用层
我们已经在我们的 domain 中成功定义了 API 业务逻辑。 应用程序连接域和接口层。
我们只会考虑用户的应用程序。您可以在repo中查看食物的内容。
这是用户的应用程序:
以上有保存和检索用户数据的方法。 UserApp 结构具有 UserRepository 接口,这使得调用 user repository 方法成为可能。
接口层
interfaces 是处理 HTTP 请求和响应的层。这是我们收到身份验证、用户相关内容和食物相关内容的传入请求的地方。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--pNX0gVst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/o6uj342ppcc7wu232xge.png)
用户处理程序
我们定义了保存用户、获取所有用户和获取特定用户的方法。这些可以在 user_handler.go 文件中找到。
我想让你注意,在返回用户时,我们只返回一个公共用户(在实体中定义)。公共用户没有敏感的用户详细信息,例如电子邮件和密码。
身份验证处理程序
login_handler 负责处理 login、logout 和 refresh 令牌方法。在其各自文件中定义的一些方法在此文件中被调用。最好按照文件路径在存储库中签出它们。
食品加工人员
在 food_handler.go 文件中,我们有基本的 food crud 方法:创建、读取、更新和删除食物。该文件解释了代码的工作原理。
请注意,在使用 postman 通过 API 测试创建或更新食物方法时,请使用 form-data 而不是 JSON。这是因为请求类型是 multipart/form-data。
运行应用程序
所以,让我们测试一下我们所拥有的。我们将连接路由,连接到数据库并启动应用程序。
这些将在根目录中定义的 main.go 文件中完成。
router(r) 是我们使用的gin包中的 Engine 类型。
中间件
从上面的文件可以看出,有些路由是有限制的。 AuthMiddleware 限制对未经身份验证的用户的访问。 CORSMiddleware 支持从不同域传输数据。这很有用,因为 VueJS 用于此应用程序的前端,并且它指向不同的域。
MaxSizeAllowed 中间件会停止任何大小超过中间件指定的文件。由于 food 实现需要文件上传,中间件会停止将大于指定值的文件读入内存。这有助于防止黑客上传不合理的大文件并降低应用程序的速度。 中间件包在interfaces层中定义。
我们现在可以使用以下命令运行应用程序:
go run main.go
进入全屏模式 退出全屏模式
奖金
-
Vue 和 VueX 用于消费 API。在此处获取存储库,您也可以访问url并使用它。
-
为大多数功能编写了测试用例。如果你有时间,你可以添加它。为了实现处理程序中每个方法的单元测试,我们创建了一个模拟包(在 utils 目录中),它模拟处理程序方法中使用的所有依赖项。
-
Circle CI 用于持续集成。
-
Heroku 用于部署 API
-
Netlify 用于部署前端。
结论
我希望您在构建 golang 应用程序时不会很难遵循这个关于如何使用 DDD 的指南。如果您有任何问题或任何意见,请不要犹豫,使用评论部分。如前所述,作者不是这方面的专家。他只是根据他的用例写了这篇文章。
在此处获取 API 代码。
在此处获取前端代码。
您还可以访问应用程序url并使用它。
在此处](https://medium.com/@victorsteven)查看有关介质[的其他文章。
您也可以关注推特
快乐 DDD。