小编mar*_*zar的帖子

如何根据Clean Architecture在Golang中实现演示者?

适当的软件架构是创建可维护项目的关键.什么正确的方法是100%主观,但最近我喜欢并尝试遵循罗伯特C.马丁(又名叔叔鲍勃)的清洁建筑.

虽然我非常喜欢这个理论,但它缺乏开发人员可能面临的常见技术挑战的实用实施指南.例如,我一直在努力解决的问题之一就是正确实现了presenter层.

演示者负责接受我的用例中的"响应",并以可以"呈现"到我的输出设备的方式对其进行格式化(无论它是Web应用程序还是CLI应用程序).

这个问题有多种方法,但它们通常属于以下类别之一:

  1. 演示者由用例本身通过某种输出接口调用
  2. 用例返回响应模型,控制器(最初称为用例)将此模型传递给演示者

选项1与Clean Architecture/Uncle Bob所说的大致相同(在书中和各种帖子中,见后文),选项2是另一种有效的方法.

听起来很酷,但让我们看看我们如何在Go中实现它们.

这是我的第一个版本.为简单起见,我们的输出现在转到网上.

另外,请原谅我的简洁.

package my_domain

import "http"

type useCase struct {
    presenter presenter
}

func (uc *useCase) doSomething(arg string) {
    uc.presenter("success")
}

type presenter interface {
    present(respone interface{})
}

type controller struct {
    useCase useCase
}

func (c *controller) Action(rw http.ResponseWriter, req *http.Request) {
    c.useCase("argument")
}
Run Code Online (Sandbox Code Playgroud)

基本上它完全如上所述并且在Clean Architecture中:有一个控制器调用一个用例(通过边界,这里不存在).用例做了一些事情并调用了演示者(没有实现,但这正是问题).

我们的下一步可能是实现演示者....但是考虑到输出如何在Go HTTP处理程序中工作,有一个很好的问题需要解决.即:请求范围.

每个请求都有自己的响应编写器(传递给http处理程序),其中应该写入响应.演示者无法访问全局请求范围,它需要响应编写器.因此,如果我想要遵循选项1(用例调用演示者),我必须以某种方式将它传递给演示者,这种方式变为请求作用域,而应用程序的其余部分完全无状态且不请求作用域,它们被实例化一次.

这也意味着我要么将响应编写器本身传递给用例和演示者(我宁愿不这样做),也不要为每个请求创建一个新的演示者.

我在哪里可以做到:

  1. 在控制器通过工厂
  2. 在通过工厂的用例中(但话又说明:用例必须接收响应编写器作为参数)

这带来了另一个问题:如果演示者是请求作用域,那么用例也是如此吗?

如果我想将演示者注入用例结构,那么它是,并且必须在控制器中创建用例.

或者,我可以使演示者成为用例的参数(没有人说必须在"构建时"注入依赖项).但这仍然会将演示者与控制器联系起来.

还有其他未解决的问题(比如我应该在哪里发送HTTP标头),但这些不是特定于Go的.

这是一个理论问题,因为我还不确定我是否想要使用这种模式,但到目前为止,我已经花了很多时间思考这个问题而没有找到完美的问题.

基于我读过的有关该主题的文章和问题:其他人也没有.

architecture go clean-architecture

7
推荐指数
1
解决办法
708
查看次数

在 select 子句中重用学说别名

我在 Doctrine 中有以下 SELECT 子句(查询本身是使用查询构建器创建的):

u.username,
MAX(p.score) as highscore,
SUM(pc.badgeCount) as badgeCount,
(SUM(pc.badgeCount) / :badgeSum) AS probability,
(-LOG(RAND()) * probability) as weight
Run Code Online (Sandbox Code Playgroud)

p是主实体的别名,pc是连接实体)

这给了我来自 MySQL 的错误消息:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'probability' in 'field list'
Run Code Online (Sandbox Code Playgroud)

如何在同一个 SELECT 子句中重用创建的别名?

php mysql doctrine doctrine-orm

6
推荐指数
1
解决办法
518
查看次数

Protocol Buffers 3 部分更新

我正在尝试使用 Protocol Buffers 3 (使用 Go)实现部分更新。问题是,在某些情况下,无法区分默认(空)值和故意设置的相同值(例如将描述设置为空字符串以清除它)。

经过一番挖掘,我发现本期中对 FieldMasks 的引用解释无法区分这些值,但可以使用 FieldMasks 进行增量更新。

我试图找到一些解释如何使用 FieldMasks 的文档或指南,但我找不到。

所以问题是:如何使用 proto3 实现部分更新(使用 FieldMasks)?

任何帮助表示赞赏。

go protocol-buffers

5
推荐指数
0
解决办法
907
查看次数