V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
asanelder
V2EX  ?  程序员

why javaer 什么都要搞一个 interface?

  •  
  •   asanelder · 2022-05-26 15:21:56 +08:00 · 7471 次点击
    这是一个创建于 708 天前的主题,其中的信息可能已经有所发展或是发生改变。

    腾讯云最新优惠活动来了:云产品限时1折,云服务器低至88元/年 ,点击这里立即抢购:9i0i.cn/qcloud,更有2860元代金券免费领取,付款直接抵现金用,点击这里立即领取:9i0i.cn/qcloudquan

    (福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

    最近看了几个 web 项目, 不明白的是, 为什么到处都是 interface? 而且很多 interface 只有一种实现?

    俺理解的是, 只有在抽象的情况下, 以及可能有多种实现的情况下, 才需要 interface, 比如一个

    IUserRepo 表示用户数据的存储, 而存储方式可能是有多种情况, 为了不在业务层耦合到具体的存储方式, 所以使用接口没问题.

    但像以下这种

    IUserService

    UserSeriveImpl

    对于这种业务层为什么还要抽象一种接口? 俺好像没见过 IUserService 这种接口有多种实现的情况?

    89 条回复  ?  2022-05-28 13:01:00 +08:00
    janus77
        1
    janus77  
       2022-05-26 15:23:32 +08:00
    面向接口编程是这样的
    dcalsky
        2
    dcalsky  
       2022-05-26 15:25:43 +08:00   ?? 3
    如果经常写测试你就会发现除了正常的实现,还有一种叫 mock 实现。

    结论:写 interface 是方便测试的时候 mock 以及今后多实现拓展;但是现实却是很多人压根不写测试,活生生把 interface 玩成样板模板。
    eote
        3
    eote  
       2022-05-26 15:26:01 +08:00
    使用 interface 进行 AOP 效率比较高,因为对外暴露的方法已经确定了。还有就是 web 领域外包遗毒,DDD 模式深入骨髓
    Oktfolio
        4
    Oktfolio  
       2022-05-26 15:30:43 +08:00
    Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib
    zzzkkk
        5
    zzzkkk  
       2022-05-26 15:31:14 +08:00
    那种设计已经成了业界标准
    更恶心的是
    有人竟然把这套东西搬到 php

    这套东西最没技术含量
    unco020511
        6
    unco020511  
       2022-05-26 15:39:39 +08:00
    因为这是毒瘤模板
    pavelpiero
        7
    pavelpiero  
       2022-05-26 15:40:15 +08:00 via Android
    ?
    pavelpiero
        8
    pavelpiero  
       2022-05-26 15:41:30 +08:00 via Android
    你好,其实你举例的 userservice 最贴近这种场景了,因为多样化的登录方式会涉及到不同的实现,比如密码登录,扫码登录,刷系统授权登录。
    banmuyutian
        9
    banmuyutian  
       2022-05-26 15:45:40 +08:00
    因为大部分是毒瘤模板+1
    crysislinux
        10
    crysislinux  
       2022-05-26 15:49:02 +08:00 via Android
    这就叫依赖反转
    asanelder
        11
    asanelder  
    OP
       2022-05-26 15:51:18 +08:00
    @dcalsky #2 应该是 mock 的 repo 吧, 比如, 测试的时候, 可能不依赖真实的数据库, 而是依赖内存存储之类的, 本来就是要测试业务逻辑的, 不应该 mock UserService 这咱吧...
    @Oktfolio #4 第二种不是效率更好么?
    @zzzkkk #5 一直没找到这种标准是从哪里来的... 找不到出处啊, 铁子
    @pavelpiero #8 俺理解的是, 如果登陆方式要抽象的话, 设计一个 ILogin 接口就好, UserService 依赖这个, 而不必把 UserService 也搞成接口
    JaguarJack
        12
    JaguarJack  
       2022-05-26 15:52:07 +08:00
    明明业务里面只有一种实现,为什么还需要定义 Interface ?我也有这样的疑问
    yohole
        13
    yohole  
       2022-05-26 15:55:33 +08:00
    对于大型项目或者可预见会持续迭代的中大型需求,面对接口编程没有错,成本也是基本客户忽略

    但是实际情况下正如你所说的,很多系统或者需求可能在第一次上线之后,基本很少改动或者不会有变化了,这种情况下完全可以直接写实现的,不需要任何接口的实现

    如果一定要扯远一点,这有可能是因为 JAVA 从诞生的那一刻的定位和宣传都是企业级,可维护性和可扩展性可能是要放首位的

    然后很多后来者不断受着各种设计模式和大量开源项目的影响,于是就慢慢变成现在的"标准"和事实了
    Oktfolio
        14
    Oktfolio  
       2022-05-26 15:56:42 +08:00
    @asanelder JDK 动态代理从 1.8 开始就比 cglib 高了吧。不过大多数人不会考虑这个问题,按照“传统”来就是了
    makelove
        15
    makelove  
       2022-05-26 15:58:08 +08:00
    @zzzkkk php 作者绝对是个脑残 java 粉,连语法都抄 java,甚至以前半官方的 Zend 框架都一股子恶臭 Java 味。
    LeegoYih
        16
    LeegoYih  
       2022-05-26 16:00:30 +08:00
    有没有一种可能,人家用 interface 是为了 RPC 准备的
    offswitch
        17
    offswitch  
       2022-05-26 16:04:19 +08:00
    你的理解是对的,很多人不懂,就喜欢这样呗,没办法。
    wolfie
        18
    wolfie  
       2022-05-26 16:06:14 +08:00
    面向 kpi 设计带来的习惯,只有一个实现不需要这么做。
    系统性搞过架构的毕竟少数。
    statumer
        19
    statumer  
       2022-05-26 16:06:36 +08:00 via iPhone   ?? 2
    这种做法对于项目管理是有好处的,不要觉得用接口就是为了替换实现。
    如果搞个 Interface ,开发者就只能暴露方法,不会乱暴露对象成员变量,减少 caller 做 hack 的可能性。
    elintwenty
        20
    elintwenty  
       2022-05-26 16:08:41 +08:00   ?? 2
    某些情况比如 rpc 需要 interface 、或低版本的一些实现方式,而且 interface 就算只有一个实现类的情况,可以起到 中高级开放人员编写 interface 交给其他人开发 的管理作用,或者更方便的看提供接口,直接看实现类代码量较大(虽然这个可以被插件或 ide 取代)
    BBCCBB
        21
    BBCCBB  
       2022-05-26 16:08:52 +08:00
    为什么我在只有一个实现的时候就不搞?
    mgcnrx11
        22
    mgcnrx11  
       2022-05-26 16:09:13 +08:00   ?? 2
    经历过麻木写 Interface ,然后变成觉得都是一种了就不写 Interface ,到最后维护的项目需求确实增长超出预期又退回去老老实实写 Interface 的阶段

    这种设计模式嘛,你不知道后面会不会有用得上的时候,当真的用得上多种实现,就会庆幸当年没有偷懒写一个 Interface 了
    MicroGalaxy
        23
    MicroGalaxy  
       2022-05-26 16:13:14 +08:00
    模板吧,我见过项目绝大部分都是只有一个实现。况且我写自己项目的时候都不写 Interface ,真的用不上
    Bingchunmoli
        24
    Bingchunmoli  
       2022-05-26 16:15:41 +08:00 via Android
    代码生成的,也方便后续自己写其他实现..
    Bingchunmoli
        25
    Bingchunmoli  
       2022-05-26 16:20:15 +08:00
    1. Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib
    2. service 不写接口 有可能被 leader review 的时候打回来
    3. 代码生成无成本
    dcalsky
        26
    dcalsky  
       2022-05-26 16:25:04 +08:00
    @asanelder Service 也可能 mock 呀,只要被依赖了,就应该被 mock 。
    zzzkkk
        27
    zzzkkk  
       2022-05-26 16:29:21 +08:00
    @asanelder
    一直没找到这种标准是从哪里来的... 找不到出处啊, 铁子
    ===================
    出处肯定可以追朔到 j2ee 早期 从 interface 这东西诞生以后
    lengyuqu
        28
    lengyuqu  
       2022-05-26 16:31:05 +08:00
    因为这样的模板开发过程中不容易出错,而且可以大量使用码农投入开发。

    任何大规模普及的开发模式一定不是出于技术角度,而是商业运行的角度。显然这个更符合商业运作
    lanlanye
        29
    lanlanye  
       2022-05-26 16:34:46 +08:00
    现实确实是大部分接口只有一种实现,但对外使用接口能让你在更改实现的时候更好做一些,另外就是上面提到的需要 mock 的场景,这个可能更常见。

    在 Golang 里还有避免写 * 这个理由……
    SMGdcAt4kPPQ
        30
    SMGdcAt4kPPQ  
       2022-05-26 16:35:33 +08:00 via Android
    有人用 interface 做 mixin 吗?
    nicevar
        31
    nicevar  
       2022-05-26 16:35:56 +08:00
    再怎么吐槽,这都是 Java 一个非常好的地方,就是再烂历史包袱再重的项目随便换个人来接手,还能干得下去,换成其他语言实现的,都不想瞧一眼。
    cubecube
        32
    cubecube  
       2022-05-26 16:37:01 +08:00
    框架用 interface 无可厚非,业务代码实现 interface 不香么
    Huelse
        33
    Huelse  
       2022-05-26 16:41:05 +08:00
    留下足够丰富的信息确保项目可以持续迭代,哪怕是 shi
    chendy
        34
    chendy  
       2022-05-26 16:43:05 +08:00
    repo 用接口,方便多实现 / mock
    往上的其实直接 class 就行了
    spring 很早就自带 cglib ,没接口不能出代理的时代已经过去了……
    cheneydog
        35
    cheneydog  
       2022-05-26 16:47:03 +08:00
    我觉得 java 的 Interface 挺好的,语法上也没强制要写呀,只是习惯上要写,我也写,默认实现怎么快怎么来,期待着未来能改进。

    我也希望 nodejs 中能写 interface ,但是不想用 ts 。
    darksword21
        36
    darksword21  
       2022-05-26 16:52:32 +08:00 via iPhone
    如果突然某一层要换的话确实很方便,比如数据库,上层基本不用变,当然在公司里一般写完也不会变了

    我是说我在 go 中这么写,java 没经历过
    guxingke
        37
    guxingke  
       2022-05-26 16:53:58 +08:00   ?? 1
    如无必要 勿增实体

    ---
    不妨从自己做起,没必要声明的时候就不声明呗。
    毕竟真有必要的时候,再抽出一个接口并不困难。
    Kaiv2
        38
    Kaiv2  
       2022-05-26 16:56:42 +08:00
    说下这种模式的优点
    IUserService

    UserSeriveImpl

    我开发一个依赖 UserService 的模块, 你负责 UserService 模块的开发,但是还没实现。你可以先提供接口给我。

    类似的 ( dubbo 服务也是这样)
    slimhigh
        39
    slimhigh  
       2022-05-26 17:04:20 +08:00
    你的理解是对的。大部分情况下是没什么用的,大家生搬硬套罢了。
    retrocode
        40
    retrocode  
       2022-05-26 17:06:12 +08:00
    规范嘛, 恶心是真滴恶心, 不过好处是有这么一套通用甚至垄断的规范在, 不至于太恶心,不然高情商点百花齐放,低情商则神魔乱舞,一个人一套规范,天天吵最佳实现谁也不服谁那才是真的恶心了
    ThinkCat
        41
    ThinkCat  
       2022-05-26 17:09:11 +08:00
    如果不涉及到多实现,那可以不用 interface ,直接写 class 实现就行了。但是如果明确在后期存在扩展的情况,一定要定为接口,避免后期大范围的修改代码
    potatowish
        42
    potatowish  
       2022-05-26 17:14:21 +08:00 via iPhone
    有规范就容易产生模板式的代码,但是没有规范,大家各写各的,不利于团队开发
    forbreak
        43
    forbreak  
       2022-05-26 17:16:42 +08:00
    大部分情况下没用,但是一旦要用,你之前写了跟没写 差距久出来了。 我只一个旧项目,改 rpc 调用,之前写了 inteface 很容易久迁移好了。没写的话,就得重新写一遍。。
    FreshOldMan
        44
    FreshOldMan  
       2022-05-26 17:21:13 +08:00
    不容易出错
    FreshOldMan
        45
    FreshOldMan  
       2022-05-26 17:21:33 +08:00
    相当于注释了吧
    panpanpan
        46
    panpanpan  
       2022-05-26 17:23:15 +08:00
    虽然 Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib
    但是实际上大家都用 springboot, springboot2.0 之后默认情况下不管你有没有接口统统用 CGLib
    yazinnnn
        47
    yazinnnn  
       2022-05-26 17:30:54 +08:00
    写 spring 不会写,都是单实现,基本不会写接口

    写 vertx 时会, 因为会用到 service proxy 和 codegen

    基于 future 的接口 client, 会把 reactive 的 client 给你包好
    基于 future 的接口服务, 会把 eventbus proxy 生成好


    现在改用 quarkus,然后又不写接口了....
    lixiaohui0812
        48
    lixiaohui0812  
       2022-05-26 17:34:36 +08:00
    test + 多个实现
    v2orz
        49
    v2orz  
       2022-05-26 17:38:28 +08:00
    因为我真的见到过有多种实现的情况
    mekingname
        50
    mekingname  
       2022-05-26 17:41:49 +08:00
    写 java 的人,骨子里就喜欢过度设计。他们很多人写的代码一辈子都不会重构或者增加新的功能了,但是他们总是抱着:未来要增加新的功能,所以要面向接口来设计。
    sparky
        51
    sparky  
       2022-05-26 17:48:54 +08:00
    面向接口而非实现的编程思想
    越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性
    dajj
        52
    dajj  
       2022-05-26 18:00:27 +08:00
    无脑重复前人的代码, 毒瘤模板而已
    yangyaofei
        53
    yangyaofei  
       2022-05-26 18:25:18 +08:00
    很多原因吧, 比如: 1. 被诟病的 封装, 设计设计设计, 设计模式啊, blbla... 2. 正常原因 java 不能多继承,只能用 interface 来做(其实还好) 3. 卷 4. 包屎
    asanelder
        54
    asanelder  
    OP
       2022-05-26 18:56:50 +08:00
    @statumer #19 嗯, 这样说也有点道理, 关键是好多接口和实现是一个人来写的...

    @mgcnrx11 #22 不明白需求增长了, 为啥要替换实现?
    @chendy #34 俺也是这么个意思
    @darksword21 #36 持久层可以抽象的, 俺的意思是业务层为啥也要抽象...
    @Kaiv2 #38 这个确实也是一种场景. 俺忽略了
    @yazinnnn #47 看来这写不写接口不是设计上的考虑, 有时更多是框架的限制...
    fpure
        55
    fpure  
       2022-05-26 19:32:20 +08:00
    @dcalsky mock 也可以不用接口的
    cool4food
        56
    cool4food  
       2022-05-26 19:34:28 +08:00
    对 OO SOLID 稍微理解深入一点的话,应该就不会有那种尬黑吐槽的言论了
    RadishWind
        57
    RadishWind  
       2022-05-26 19:41:30 +08:00
    之前接手过一个屎山就没有 interface+impl 结果有个方法很慢 找到后没法使用 @Cache 注解进行优化 Spring 很多特性是依赖动态代理的
    icylogic
        58
    icylogic  
       2022-05-26 19:42:40 +08:00
    超出必须的设计,无非就是方便调试 /测试 /扩展,如果未来一段时间内,你发现你实现新需求 /调试 /测试的时候,需要从这里继承实现一个不一样的,那说明这设计至少算不上错,如果你发现你这项目到死都没有过这种事,那就是过度设计,要么是思维上懒惰,要么是对未来需求预估错误。如果你发现你可能需要,但你觉得有更好的方式,那就是你们团队之间选择谁来适应谁的问题。
    haah
        59
    haah  
       2022-05-26 19:46:25 +08:00   ?? 1
    为啥 C/C++er 要写头文件呢?
    CoderGeek
        60
    CoderGeek  
       2022-05-26 20:05:34 +08:00
    看下 jdbc mycat 的源码 - -
    luzemin
        61
    luzemin  
       2022-05-26 20:18:41 +08:00
    1. 为了实现 OOP SOLID 中 D ,依赖抽象而不依赖具体,为了 N 年后的随时换掉具体实现而规划
    2. 方便测试
    3. 约束方法名称:具体实现类必须继承并且实现同名方法

    以上都是理论,实际往往偏差比较大,基本是因为“模版就是这样”“业内都这样”而跟着做的。
    vincent7245
        62
    vincent7245  
       2022-05-26 20:39:04 +08:00
    规范,规范,还是 TMD 规范,这就是为什么 java 可以做超级大型的项目。当你一个人做项目的时候可以随意写,当四五个人做项目的时候,一般的口头沟通就可以了。当几百个人同时做一个项目的时候,没有规范你啥都做不了。当你做过大型项目你就明白了。这里的大型项目是指代码至少 10W+起步
    ration
        63
    ration  
       2022-05-26 20:39:49 +08:00 via Android
    面向对象基本都是这样,除了多个实现,依赖注入外,还有其他好处。比如你可以只看接口就知道实现了什么功能,而看具体的类就有一大堆代码了。接口这种东西一开始是来源于硬件而不是软件。
    qq1009479218
        64
    qq1009479218  
       2022-05-26 21:44:10 +08:00
    不做单测吧
    qbmiller
        65
    qbmiller  
       2022-05-26 22:08:31 +08:00
    大多数项目用不上.
    大型项目确实要, 防止写飞
    实战为准. 确实没必要
    别的语言从没这么多破事
    Rocketer
        66
    Rocketer  
       2022-05-26 22:36:34 +08:00 via iPhone
    各种设计模式都是为了方便项目规模成长的,所以绝大多数“没必要”都是因为团队 /项目还不够大。

    等规模大到设计模式显示出优势时,大概率就很难改了,最后变成?山。

    当然,一直写那种代码的程序员也不会意识到设计模式的优势,他们宁可把代码复制粘贴到一百个地方,也不愿把代码写得一劳永逸。只要不跳出舒适区,我就是舒适的?
    vone
        67
    vone  
       2022-05-26 22:40:47 +08:00
    方便单元测试和多实现。

    但是现实是没卵用,因为这些复制粘贴的垃圾代码既没有单元测试也没有多实现。
    HiShan
        68
    HiShan  
       2022-05-26 22:42:37 +08:00
    可以了解一下 DDD
    git00ll
        69
    git00ll  
       2022-05-26 23:14:25 +08:00
    确实,我同事也有人喜欢整这些接口,每个 server 都整一个接口,我感觉没必要。
    上面提单测的,单测与接口有什么关系,大部分情况下没接口使用 mockito 或 spock 都能搞定,遇到一点点搞不定的再整接口也行啊
    RedBeanIce
        70
    RedBeanIce  
       2022-05-26 23:26:28 +08:00
    还是网上流传的那句话,网友本科生 5%? v2exer 写业务的 5%?
    ychost
        71
    ychost  
       2022-05-26 23:31:09 +08:00
    当你写 framework 的时候,接口就很重要了,还有 IOC 、SPI 都非常方便
    RiceNoodle
        72
    RiceNoodle  
       2022-05-27 00:57:29 +08:00
    事实是,面向接口编程对写单元测试非常友好。
    优秀的项目愿意这么设计是因为用得着,不代表每个项目都这么优秀。
    asanelder
        73
    asanelder  
    OP
       2022-05-27 01:51:46 +08:00
    @ychost #71 framework 大量用接口俺感觉正常, 毕竟要考虑通用性, 但 web 项目嘛...
    @git00ll #69 嗯,好像俺写测试时不用接口感觉也没啥
    xuanbg
        74
    xuanbg  
       2022-05-27 02:42:06 +08:00
    别问,问就是规范和习惯。

    虽然没啥用,而且 Java 也早就支持接口的默认实现,但大家还是这么写而不是写成默认实现。
    Kontinue
        75
    Kontinue  
       2022-05-27 08:42:50 +08:00
    有好处也有包袱
    cherryas
        76
    cherryas  
       2022-05-27 09:01:35 +08:00
    因为写个 interface 没几分钟,写完还能自动生成 impl 。
    micean
        77
    micean  
       2022-05-27 09:46:43 +08:00
    写 framework 、library 是一定要的,业务上很多就多余。别提 mock……
    Narcissu5
        78
    Narcissu5  
       2022-05-27 09:58:21 +08:00
    - 有些地方需要接口,比如 java 动态代理
    - 如果你的接口几乎都只有一种实现,那么你的抽象可能不够。实际上你没有用到 OO 最重要的能力也就是多态
    - 如果你对多态不感兴趣,建议转 Go 。实际上 Go 更符合大多国内程序员的思维模式
    wangxin13g
        79
    wangxin13g  
       2022-05-27 10:06:44 +08:00
    吐槽接口的写代码不写单元测试吗
    写项目的时候就不考虑后期有人重构的吗
    写项目就一个人吗?
    Akagi201
        80
    Akagi201  
       2022-05-27 10:13:59 +08:00
    其实面向 interface 没有问题, 主要是要程序员要理解什么是 interface, 为什么会有 interface, 有的低级开发复制粘贴惯了, 直接把实现都复制过来这样根本没有意义. interface 本来就是让你自己梳理你的模块的接口的, 让功能自洽, 合理的设计接口, 而现实有的低级开发只是把一堆乱七八糟的东西堆到 interface.
    qiumaoyuan
        81
    qiumaoyuan  
       2022-05-27 10:48:17 +08:00
    这个问题说到底是预先设计 v.s 重构的问题。很多人所谓的“重构”其实是重写,没办法重构只好预先设计出接口。
    zzzkkk
        82
    zzzkkk  
       2022-05-27 11:48:38 +08:00
    通用性
    可扩展

    对小型项目 来说都是垃圾
    过度设计是万恶之源
    2NUT
        83
    2NUT  
       2022-05-27 13:07:34 +08:00
    我觉得是非常好的 编程习惯, 从整个项目的视角
    Akagi201
        84
    Akagi201  
       2022-05-27 14:00:07 +08:00
    有人说换种实现可以不换 interface 的, 可是有的低级开发设计 interface 时候就没考虑换个实现的兼容性考虑. 还是得一起重构. 而且除了库, 业务服务往往只会用到一种实现.不会存在两种实现共存的情况
    VictorJing94
        85
    VictorJing94  
       2022-05-27 14:15:08 +08:00
    好像这个是某些教程里的..刚从 java 转出来时候还很不适应
    chanchan
        86
    chanchan  
       2022-05-27 18:00:00 +08:00
    有的时候有用,写了的话也增加不了多少成本,有 ide,所以...
    magiclz233
        87
    magiclz233  
       2022-05-28 02:07:33 +08:00
    你要看啥情况,如果是一个大项目,很多人合作的公司项目,那这样搞,最简单的就是有一个规章,扩展性也更强。
    要是你自己练手的项目,interface 不说了,你直接接口里面调 sql 都无所谓,自己开心就行
    kongg
        88
    kongg  
       2022-05-28 11:03:57 +08:00
    这个问题平时感觉很正常,你一说,我竟然也想了 这是为什么?
    changz
        89
    changz  
       2022-05-28 13:01:00 +08:00
    你们不写单元测试的咩。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2301 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 03:48 · PVG 11:48 · LAX 20:48 · JFK 23:48
    Developed with CodeLauncher
    ? Do have faith in what you're doing.


    http://www.vxiaotou.com