后端组件设计/封装的思路是什么?( Java /Spring 相关) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
dumbbell5kg
V2EX    程序员

后端组件设计/封装的思路是什么?( Java /Spring 相关)

 
  •   dumbbell5kg 2024-05-08 17:14:37 +08:00 2537 次点击
    这是一个创建于 605 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近了解到 SpringCache 这个组件,是用了 AOP 来消灭这样的重复代码

     public V queryList(){ if(Redis 缓存里有值){ return 值; }else{ 查数据库; 查询结果写入缓存; } } 

    使用 SpringCache 后,写法变成下面这样,与缓存打交道的代码就被放到运行时生成的代理类里去了:

     @Cacheable public V queryList(){ 查数据库 } } 

    看到这个组件的用法,我觉得很方便、灵活,我想请教的是,当工作中遇到类似需要写/封装组件的情况,应该怎么去思考,或者说解题框架是什么。

    求大佬赐教!! orz

    PS:没看到 SpringCache 前我也想过去消灭这种重复代码,但是我只知道一个很单一的目标:要把缓存相关操作提出来。关于怎么提、提完之后开发人员的使用方式(上面的使用方式就是注解 @Cacheable)完全没有思路。

    第 1 条附言    2024-05-08 17:55:54 +08:00
    感觉问题问的太宽泛了,不明确,简要来说就是想请教大家在工作中写组件的思路是什么
    比如:
    1.确定现有痛点 与 组件可以提供的能力
    2.确定方便的使用方式
    3.分析组件里有些哪些角色(Cache 、CacheManager) 可以用哪些合适的设计模式
    20 条回复    2024-05-09 17:16:19 +08:00
    jatesun
        1
    jatesun  
       2024-05-08 17:30:33 +08:00
    其他的也可以用类似的方式,比如这种注解的形式,可以把日志也用这种方法写一下
    Leviathann
        2
    Leviathann  
       2024-05-08 17:31:34 +08:00   1
    就是 decorator
    azhong123
        3
    azhong123  
       2024-05-08 18:05:14 +08:00
    @Leviathann 赞,非核心逻辑,装饰掉
    murmur
        4
    murmur  
       2024-05-08 18:08:04 +08:00
    建议去找个开源的那种大而全的企业框架看一下,你能看到各种各样奇奇怪怪的注解
    BiChengfei
        5
    BiChengfei  
       2024-05-08 18:10:40 +08:00   1
    多看、多写、多想,工作久了,学会举一反三后,你就悟了
    例如一个调用链:A --> B --> C --> D --> E ,那么我们绝对能在 A 调用 B 之间,做一些操作,日志?缓存?限流?编码?动态修改?参数篡改?参数防串改?熔断?......。每一个流程都是上一个流程的”网关“
    人类社会也是如此,A --> B --> C --> D --> E ,你把这些字母,想象成不同的人,在消息传达的过程中,你是否有机会做一些动作?保留消息?缓存消息?篡改消息,制造谣言?判断消息是否被篡改?
    BiChengfei
        6
    BiChengfei  
       2024-05-08 18:11:09 +08:00
    人类社会,是最复杂的代码
    huigeer
        7
    huigeer  
       2024-05-08 18:22:01 +08:00
    先设计组件接口 interface ,然后再实现接口
    lingalonely
        8
    lingalonely  
       2024-05-08 18:56:18 +08:00
    说白了,第一步是要提取共性,比如你说的加缓存,又比如你要加日志,这些都存在某种共性,再思考如何细分粒度,不同粒度设计会存在不同,既然是要提纯成组件,就要有合适的粒度,不能用一次改一次,能做到这些,一个基本的组件结构就出来,后面就是 bug 和性能的问题。
    Hurriance
        9
    Hurriance  
       2024-05-08 18:59:31 +08:00
    可能有些偏题
    仅是我个人的看法,我认为在工作中的代码应该需要保持统一的风格,框架、日志收集,开源框架带给我们的一大好处之一就是给大家做同样一件事达成了共识,对于每个人的阅读代码成本不会太高,除非是与业务深度绑定或者未有适用的开源框架,不然我不认为自己写一个组件是最优的选择,对于团队来讲,否则这样的做法在我看来只是为了满足工程师个人的成就感
    iOCZS
        10
    iOCZS  
       2024-05-08 19:15:01 +08:00
    说白了就是让每个人可以少写代码
    hitsmaxft
        11
    hitsmaxft  
       2024-05-08 19:24:01 +08:00
    aop 和注解/装饰器两者达到目的差别不大.无非差别就是通过扫描还是手动标注. 背后都是实现对应的 process, 加入对应的代码

    如果你还不清楚怎么选择. 首先还是多写写框架. 通过包装的方式进行代码复用和增强, 从插件到 interpreter 再到 decorator, 最后就是字节码增强/代码生成这种黑魔法了

    上来就 aop 和修饰器.很容易涉及不完善, 花了大力气, 后患无穷.
    hitsmaxft
        12
    hitsmaxft  
       2024-05-08 19:46:50 +08:00
    @hitsmaxft 勘误, process -> processor; interpreter -> interceptor
    k9990009
        13
    k9990009  
       2024-05-08 20:52:11 +08:00
    为了偷懒,少写代码或者二次开发少改动。首先你要抽取业务需求的共性,区分出两部分,一部分是不变的,另一部分是变化的。不变的抽取出公共代码,变化的留出拓展口(允许自由实现或配置),与业务解耦。然后就是根据你已掌握的知识,设计不同的方案,考虑不同方案的优缺点,最终设计出一个最佳实践,想多了自然就会了。设计模式是让你更好的去维护你的代码。
    cp19890714
        14
    cp19890714  
       2024-05-08 21:06:39 +08:00
    * 看现有的各种框架, 包含了什么思想, 利用了什么能力 来实现.
    * 总结各种 思想 和 能力, 熟于心
    * 下次遇到问题时, 套用.
    * 套用的多了, 形成思维惯性.
    wolfie
        15
    wolfie  
       2024-05-08 21:07:47 +08:00
    试想为使用者,大胆的设计 API 使用方式 再考虑实现。
    代码实现都是小事,外观设计好,内部实现代码垃圾点也无所谓,后面重构就行。
    fkdtz
        16
    fkdtz  
       2024-05-09 04:08:36 +08:00   1
    个人有一个观点是不要过度设计,架构是演进出来的不是设计出来的。做一些可预见的设计优化是对的,但不要想的太多做的太早,否则你会发现要么设计的东西根本用不到、要么就是不符合业务发展需要不断重构。

    回到问题,我认为封装的根本是分层思想。最基本的封装就是调用一个函数了,稍微进一步调用另一个文件中的函数,再如调用另一个包中的函数,再如调用另一个服务给你提供的函数,这些我认为都是分层,函数调用可以认为是陷入另一个层再回来,操作系统调用就是 trap 到内核层再回到用户层。
    分层可以让你专注你自己的业务,其他的东西由别的层负责,例如限流、风控、鉴权、日志等都是与具体业务无关的通用的功能,就可以考虑封装为独立的一层。

    到了具体实现环节我认为应该首先确定好接口,接口意味着协议,至少应该是一个在未来可以扩展的协议,这对分层来说是十分重要的,也意味着未来的修改没有历史包袱。另外应该尽量做到对业务无侵入性或尽量小,否则如果与业务有很强的耦合性就应该再思考一下是不是哪里不合理了。
    Ashe007
        17
    Ashe007  
       2024-05-09 08:49:33 +08:00 via iPhone
    需要指出,SpringCache 并不能完全替换 Redis 缓存,因其是 jvm 的缓存,只是单机缓存,在多实例情况下会引发 bug 。你的问题也不太明确,或许你希望的是了解设计模式来指导组件的设计,常用的设计模式就那几种装饰器,代理,观察者……经常被提及的通常就是应用比较广泛的
    Ashe007
        18
    Ashe007  
       2024-05-09 08:52:16 +08:00 via iPhone
    而且需要注意的是不能因设计模式强行提升项目复杂度,比如很多项目中过度抽象,毫无意义的 interface ,多余的策略模式
    lizy0329
        19
    lizy0329  
       2024-05-09 15:33:46 +08:00   1
    终极的设计/封装的思路就是 sidecar 的概念,让业务人员始终关注业务:),其他都是透明层
    dumbbell5kg
        20
    dumbbell5kg  
    OP
       2024-05-09 17:16:19 +08:00
    感谢各位的回复!挺有收获的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2590 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 09:27 PVG 17:27 LAX 01:27 JFK 04:27
    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