RPC 返回贫血模型情况下, 如何避免业务逻辑的分散? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
asanelder

RPC 返回贫血模型情况下, 如何避免业务逻辑的分散?

  •  
  •   asanelder 2021 年 1 月 9 日 3216 次点击
    这是一个创建于 1932 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果是本地调用

    interface UserService { User getUser(int userId); } 

    返回的 user 可以有行为, 调用方不必取出 user 字段来进行逻辑判断.

    但如果是 RPC 调用, 返回的 User 一般都没有行为. 调用方会取出数据字段来进行业务处理, 这样, 业务逻辑代码会分散到各个地方.

    如果 RPC 调用返回的对象也是充血多好.

    铁子们, 你们是如何处理 RPC 返回贫血模型呢? 如果返回贫血模型, 如何避免业务逻辑分散在各个地方?

    18 条回复    2021-01-11 22:44:03 +08:00
    xuanbg
        1
    xuanbg  
       2021 年 1 月 9 日
    你完全可以反序列化成充血模型
    gjkv86
        2
    gjkv86  
       2021 年 1 月 9 日
    RPC 为何要返回充血模型?这种主要是传输对象的状态吧。 其结果需要有基于可以传输的 user 再有一到两层的包装再使用。你传输的只是对象的状态,这个可传输的对象确实没必要很复杂。 但上层使用时,需要有再次的封装,而不是直接拿来用。这样也避免了传输的模型发生了变化,把变化波及的上层。
    wangyanrui
        3
    wangyanrui  
       2021 年 1 月 9 日 via Android
    rpc 传输的是 dto,业务方使用时自行定义 bo 包裹一下呀
    chendy
        4
    chendy  
       2021 年 1 月 9 日
    把业务封装进模型到处传播,不还是把业务分散掉了么
    daimazha
        5
    daimazha  
       2021 年 1 月 9 日
    看一下六边形架构
    YouLMAO
        6
    YouLMAO  
       2021 年 1 月 10 日 via Android
    你们说的中文真的是脑壳疼了,微服务啊,user 服务当然是跟 user 相关的读写都在 user 微服务,怎么可能你取出 user rpc 的字段写自己逻辑呢,万一逻辑变了,你不就造成事故了吗,当然是 user 微服务做逻辑而不是上层做逻辑
    yzbythesea
        7
    yzbythesea  
       2021 年 1 月 10 日
    充血和贫血给我头都看晕了。
    yzbythesea
        8
    yzbythesea  
       2021 年 1 月 10 日
    你的意思是想执行 User.SayHi( ) 这种?这个正确做法是在 User Service 执行,然后提供 API,sayHiFromUser( )
    taowen
        9
    taowen  
       2021 年 1 月 10 日 via Android
    user service 封装 user 可以做的一切事情,那啥事 user service 是不管的?
    Kirsk
        10
    Kirsk  
       2021 年 1 月 10 日 via Android
    写一个公共项目 只放 service 接口 通过接口调用
    Kirsk
        11
    Kirsk  
       2021 年 1 月 10 日 via Android
    @Kirsk 实现与调用分离 也就是长见的一个接口一个实现 不过如果实现写的垃圾比较容易出问题 至少保证每个业务实现的独立性
    asanelder
        12
    asanelder  
    OP
       2021 年 1 月 10 日
    @xuanbg #1 铁子意思是在 User 中添加相关业务方法? User 一般不都是生成的么?比如 thrift 使用 idl 定义, 然后生成 user 类。然后在生成的 User 类中再添加自定义方法?


    @gjkv86 #2
    @wangyanrui #3

    也就是使用方有个 UserWrapper 之类的, 然后这个类有业务逻辑?

    @daimazha #5 这个看过, 但不知道使用六边形架构怎么解决俺的问题, 铁子请明示

    @YouLMAO #6 如果说微服务做业务逻辑,然后通过接口给 client 使用, 会出现这样一个问题。

    可能 client 的业务要基于 user 的多个字段做操作, 比如 age 和 sex, 然后有四种结果, 然后把这个业务逻辑放到微服务中, 通过接口提供可能无法方便返回四种结果。


    @yzbythesea #8 简单的业务逻辑可以放到微服务,但感觉有些复杂的, 通过一个接口不好满足。


    @Kirsk #10 铁子的意思还是把业务放到接口后面?
    yzbythesea
        13
    yzbythesea  
       2021 年 1 月 10 日
    @asanelder 你举一个比较困惑的例子呢?有可能业务复杂是因为你们各服务过于耦合。
    daimazha
        14
    daimazha  
       2021 年 1 月 10 日
    @asanelder #12 很简单,六边形架构里面,你 rpc 查询的数据会有个 adapter 来转换成系统的领域对象
    Kirsk
        15
    Kirsk  
       2021 年 1 月 10 日 via Android
    @asanelder 对的
    ychost
        16
    ychost  
       2021 年 1 月 11 日
    提供二方包的时候打包一个 userValidator 公用等静态工具类就行了,直接返回充血模型不太友好,而且大多时候模型都是 idl 直接生成的,万一改漏了就麻烦了
    asanelder
        17
    asanelder  
    OP
       2021 年 1 月 11 日
    @daimazha #14 可以, 这个建议有启示感
    @yzbythesea #13 嗯俺遇到真实的例子再补充
    @ychost #16 就怕改漏
    gjkv86
        18
    gjkv86  
       2021 年 1 月 11 日 via iPhone
    你叫 wrapper 也可以,或其他什么都行。但是从职责上,正如有朋友指出的,传输的确实是 dto 一类的东西。而你说的对象包括业务行为的这种类,应该是属于你自己建模的一部分,他应该不依赖于 user 数据是 rpc 来的还是 db 来的。我理解的不一定符合这理论那理论,但代码之所以这样那样的封装,很重要的一个目的就是为了适应变化,封装变化。最大限度的自己掌控适应变化。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     868 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 47ms UTC 22:07 PVG 06:07 LAX 15:07 JFK 18:07
    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