go 写业务,也可以很简单 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
zhengchengdong
V2EX    Go 编程语言

go 写业务,也可以很简单

  •  
  •   zhengchengdong 2022-11-04 18:10:30 +08:00 3274 次点击
    这是一个创建于 1077 天前的主题,其中的信息可能已经有所发展或是发生改变。

    通常认为 go 更适合写中间件,复杂业务开发还是交给 java 吧。

    我们一直以来对处理软件开发的业务复杂性感兴趣,思考下来发现要处理好业务复杂性其实和用什么语言没什么关系,更为重要的是以下几点:

    • 要做到业务代码和技术代码分离,业务代码可以完全剥离技术代码单独测试
    • 以实体(对应不同的语言可能为对象,结构体等)为最小操作单位,一个业务,要么整个实体的各个属性都参与进来,要么都不参与
    • 编写业务代码不能有技术心智负担,比如写一个库存扣减,不能让人担心并发操作会不会扣成负数

    早期我们认为 DDD (领域驱动设计)是能比较好的解决问题的方法论,经过长期实践后我们发现 DDD 成功落地需要做很多减法,最后我们开始重新思考,抽象了Aggregate (聚合)、Repository (仓库)、Process (过程)的方法论。也用 go 实现了一套框架:https://github.com/framework-arp/ARP4G,之前 ARP 框架也用于生产了几个项目。

    现在就是想看看大家的想法和疑问,帮助我们探索解决软件业务复杂性之道,也欢迎试着用用看和你们的 issues

    8 条回复    2022-12-04 15:19:44 +08:00
    wencan
        1
    wencan  
       2022-11-06 17:58:30 +08:00
    怎么把复杂业务逻辑写好,似乎完全不被重视。还是第一次遇到同样在关注这个的朋友。
    我设计和实现复杂的业务,
    一部分是基于自己对 solid 的理解,具体还有待整理;
    另一部分见: https://blog.wencan.org/2022/10/21/programming-thinking/
    最近,我也在开发一套开源组件库。不过依据我的编程思想,它必须是组件库,没有重复的轮子,地址为: https://github.com/wencan/fastrest
    如果有兴趣进一步沟通:ZW1haWw6IHdlbmNhbkBmb3htYWlsLmNvbQ==
    BeijingBaby
        2
    BeijingBaby  
       2022-11-13 19:19:32 +08:00 via iPhone
    看了一下就是典型的 service ,repo 模式,感觉比较常见吧,目前我们 dev.com.cn 后端是这个模式。
    再扩展一下就是洋葱架构了。
    securityCoding
        3
    securityCoding  
       2022-11-14 03:15:46 +08:00 via Android
    我转 go 正好,其实没啥大的区别,比 spring 有意思一点,鹅厂内部新业务好多都是 go 了,框架工具集成都做得挺好
    tikazyq
        4
    tikazyq  
       2022-11-14 09:45:27 +08:00
    有意思,看起来跟 Sprint JPA 优点像了。不过好像还不完全,如果能有一个能高度抽象各种业务类的方式就更好了。目前来看,Go 跟其他框架来比写业务逻辑的问题,主要在于泛型的缺失,现在虽然有了,但还不清楚是否已经足够强大了
    zhengchengdong
        5
    zhengchengdong  
    OP
       2022-11-14 13:58:16 +08:00
    @BeijingBaby 是的,现在看来就只有 service 和 repo 了,这样最简单最好理解。实际上我们是从多层结构退回来的,比如之前我们一直写两层 service ,差不多就是 DDD 的 domain service 和 app service 。实际操作下来 DDD 过多的概念导致只有极少数人能恰当运用,运用不当的情形比运用得当的多了太多。所以我们重新思考后认为 ARP 三个概念就够了,就一层 service ,service 就是一些 process 的集合,另外 repo 就是存放聚合的一个地方,所以从分层来看差不多就只有 service 和 repo ,且不会再扩展了
    zhengchengdong
        6
    zhengchengdong  
    OP
       2022-11-14 14:53:06 +08:00
    @tikazyq 你提到的高度抽象各种业务类的方式,我估计你说的是 "业务复用",这是另外一个主题,不过和 ARP 确实也有关系。我们尝试过抽象出可复用的业务类,到了具体不同业务不可避免的会有个性需求,通常我们用 "插件" 的策略来处理个性需求,这种做法也很常见,就是在抽象的业务类里面组合了各个 "变化点" 的策略对象,这些个策略对象就是 "插件" 。比如我们游戏匹配的 Matcher 对象,不管什么游戏,他总是从匹配池捞上来所有匹配请求,然后按一定的规则,比如积分相近,进行分组,分组结果作为匹配结果,那么这个匹配规则就做成一个 "插件",其他部分都是不变的。实际实践当中我们发现,随着面对越来越多的游戏,总是有之前没有想到的变化点,比如有的游戏希望匹配不上的人要重回匹配池,那么我们就要加一个 "落选处理" 的插件。诸如此类,最终我们发现插件总是越加越多,更糟糕的是一个具有 10 个插件的业务类对某个具体业务来说可能只需要 4 、5 个插件,其他插件根本不关心,于是我们对于具体业务要写好多个他不关心的业务插件的 "哑" 实现。后来,我们重新思考了 "业务组合的方式",从 "抽象业务类组合插件" 变成了 "过程 append 过程",这个 "过程" 就是 ARP 的 P ,然后基于 P 我们提了一个新的概念叫 AP (抽象过程),后来我们都是通过抽象过程来做业务抽象。那么我们发的这个 ARP 框架对于业务抽象是起到关键支撑作用的,具体欢迎关注后续的开源工程。
    YuuuuuuH
        7
    YuuuuuuH  
       2022-11-23 20:11:27 +08:00
    @zhengchengdong #5 把两个 service 合成一个 service 大概率导致领域逻辑外溢,领域模型逐渐贫血,最后又变成事务脚本。
    zhengchengdong
        8
    zhengchengdong  
    OP
       2022-12-04 15:19:44 +08:00
    @YuuuuuuH #7 估计外溢说的是领域逻辑从 domain object 溢到了 service ?这一点是这样的,实践下来发现很难把所有的业务逻辑都封装在 domain object ,很多业务是几个对象之间协作完成的,硬要把他们塞进 domain object 有人就会生生造出 XXXManager 这样的伪 domain object ,其实 XXXManager 就是个 domain service 了,所以我们和 DDD 在 “service 也属于领域逻辑” 这一点上看法是相同的,所以 service 里面有领域业务算不上外溢。后来我们改进的只是把两层 service 合并成了一层,原因是发现有很多人写 service 出现了心智负担: “两个 service 都要写吗?外面那个就是代理了一下啥也没有啊?那如果只写一个的话到底是只写 domain service 还是只写 app service ?什么时候要写两个?什么时候只写一个?”,所以就一个 service ,类似于后来 clean architecture 的设计,同时我们当时并不知道 clean architecture ,说明我们同时认识到了只写一层 service 更合适些。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1221 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 23:50 PVG 07:50 LAX 16:50 JFK 19:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86