why javaer 什么都要搞一个 interface?

讨论 未结 85 39
asanelder
asanelder 会员 2022年5月26日 07:26 发表
<p>最近看了几个 web 项目, 不明白的是, 为什么到处都是 interface? 而且很多 interface 只有一种实现? </p> <p>俺理解的是, 只有在抽象的情况下, 以及可能有多种实现的情况下, 才需要 interface, 比如一个</p> <p>IUserRepo 表示用户数据的存储, 而存储方式可能是有多种情况, 为了不在业务层耦合到具体的存储方式, 所以使用接口没问题.</p> <p>但像以下这种</p> <p>IUserService</p> <p>UserSeriveImpl</p> <p>对于这种业务层为什么还要抽象一种接口? 俺好像没见过 IUserService 这种接口有多种实现的情况?</p>
收藏(0)  分享
相关标签: 灌水交流
注意:本文归作者所有,未经作者允许,不得转载
85个回复
  • dcalsky
    2022年5月26日 07:58
    如果经常写测试你就会发现除了正常的实现,还有一种叫 mock 实现。 结论:写 interface 是方便测试的时候 mock 以及今后多实现拓展;但是现实却是很多人压根不写测试,活生生把 interface 玩成样板模板。
    0 0
  • eote
    2022年5月26日 07:58
    使用 interface 进行 AOP 效率比较高,因为对外暴露的方法已经确定了。还有就是 web 领域外包遗毒,DDD 模式深入骨髓
    0 0
  • Oktfolio
    2022年5月26日 07:58
    Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib
    0 0
  • zzzkkk
    2022年5月26日 07:58
    那种设计已经成了业界标准 更恶心的是 有人竟然把这套东西搬到 php 这套东西最没技术含量
    0 0
  • pavelpiero
    2022年5月26日 07:58
    你好,其实你举例的 userservice 最贴近这种场景了,因为多样化的登录方式会涉及到不同的实现,比如密码登录,扫码登录,刷系统授权登录。
    0 0
  • asanelder
    2022年5月26日 07:58
    #2 应该是 mock 的 repo 吧, 比如, 测试的时候, 可能不依赖真实的数据库, 而是依赖内存存储之类的, 本来就是要测试业务逻辑的, 不应该 mock UserService 这咱吧... @ #4 第二种不是效率更好么? @ #5 一直没找到这种标准是从哪里来的... 找不到出处啊, 铁子 @ #8 俺理解的是, 如果登陆方式要抽象的话, 设计一个 ILogin 接口就好, UserService 依赖这个, 而不必把 UserService 也搞成接口
    0 0
  • JaguarJack
    2022年5月26日 07:58
    明明业务里面只有一种实现,为什么还需要定义 Interface ?我也有这样的疑问
    0 0
  • yohole
    2022年5月26日 07:58
    对于大型项目或者可预见会持续迭代的中大型需求,面对接口编程没有错,成本也是基本客户忽略 但是实际情况下正如你所说的,很多系统或者需求可能在第一次上线之后,基本很少改动或者不会有变化了,这种情况下完全可以直接写实现的,不需要任何接口的实现 如果一定要扯远一点,这有可能是因为 JAVA 从诞生的那一刻的定位和宣传都是企业级,可维护性和可扩展性可能是要放首位的 然后很多后来者不断受着各种设计模式和大量开源项目的影响,于是就慢慢变成现在的"标准"和事实了
    0 0
  • Oktfolio
    2022年5月26日 07:58
    JDK 动态代理从 1.8 开始就比 cglib 高了吧。不过大多数人不会考虑这个问题,按照“传统”来就是了
    0 0
  • makelove
    2022年5月26日 07:58
    php 作者绝对是个脑残 java 粉,连语法都抄 java,甚至以前半官方的 Zend 框架都一股子恶臭 Java 味。
    0 0
  • LeegoYih
    2022年5月26日 08:27
    有没有一种可能,人家用 interface 是为了 RPC 准备的
    0 0
  • offswitch
    2022年5月26日 08:27
    你的理解是对的,很多人不懂,就喜欢这样呗,没办法。
    0 0
  • wolfie
    2022年5月26日 08:27
    面向 kpi 设计带来的习惯,只有一个实现不需要这么做。 系统性搞过架构的毕竟少数。
    0 0
  • statumer
    2022年5月26日 08:27
    这种做法对于项目管理是有好处的,不要觉得用接口就是为了替换实现。 如果搞个 Interface ,开发者就只能暴露方法,不会乱暴露对象成员变量,减少 caller 做 hack 的可能性。
    0 0
  • elintwenty
    2022年5月26日 08:27
    某些情况比如 rpc 需要 interface 、或低版本的一些实现方式,而且 interface 就算只有一个实现类的情况,可以起到 中高级开放人员编写 interface 交给其他人开发 的管理作用,或者更方便的看提供接口,直接看实现类代码量较大(虽然这个可以被插件或 ide 取代)
    0 0
  • BBCCBB
    2022年5月26日 08:27
    为什么我在只有一个实现的时候就不搞?
    0 0
  • mgcnrx11
    2022年5月26日 08:27
    经历过麻木写 Interface ,然后变成觉得都是一种了就不写 Interface ,到最后维护的项目需求确实增长超出预期又退回去老老实实写 Interface 的阶段 这种设计模式嘛,你不知道后面会不会有用得上的时候,当真的用得上多种实现,就会庆幸当年没有偷懒写一个 Interface 了
    0 0
  • MicroGalaxy
    2022年5月26日 08:27
    模板吧,我见过项目绝大部分都是只有一个实现。况且我写自己项目的时候都不写 Interface ,真的用不上
    0 0
  • Bingchunmoli
    2022年5月26日 08:27
    代码生成的,也方便后续自己写其他实现..
    0 0
  • Bingchunmoli
    2022年5月26日 08:27
    1. Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib 2. service 不写接口 有可能被 leader review 的时候打回来 3. 代码生成无成本
    0 0
  • dcalsky
    2022年5月26日 08:56
    Service 也可能 mock 呀,只要被依赖了,就应该被 mock 。
    0 0
  • zzzkkk
    2022年5月26日 08:56
    一直没找到这种标准是从哪里来的... 找不到出处啊, 铁子 =================== 出处肯定可以追朔到 j2ee 早期 从 interface 这东西诞生以后
    0 0
  • lengyuqu
    2022年5月26日 08:56
    因为这样的模板开发过程中不容易出错,而且可以大量使用码农投入开发。 任何大规模普及的开发模式一定不是出于技术角度,而是商业运行的角度。显然这个更符合商业运作
    0 0
  • lanlanye
    2022年5月26日 08:56
    现实确实是大部分接口只有一种实现,但对外使用接口能让你在更改实现的时候更好做一些,另外就是上面提到的需要 mock 的场景,这个可能更常见。 在 Golang 里还有避免写 * 这个理由……
    0 0
  • nicevar
    2022年5月26日 08:56
    再怎么吐槽,这都是 Java 一个非常好的地方,就是再烂历史包袱再重的项目随便换个人来接手,还能干得下去,换成其他语言实现的,都不想瞧一眼。
    0 0
  • cubecube
    2022年5月26日 08:56
    框架用 interface 无可厚非,业务代码实现 interface 不香么
    0 0
  • Huelse
    2022年5月26日 08:56
    留下足够丰富的信息确保项目可以持续迭代,哪怕是 shi
    0 0
  • chendy
    2022年5月26日 08:56
    repo 用接口,方便多实现 / mock 往上的其实直接 class 就行了 spring 很早就自带 cglib ,没接口不能出代理的时代已经过去了……
    0 0
  • cheneydog
    2022年5月26日 08:56
    我觉得 java 的 Interface 挺好的,语法上也没强制要写呀,只是习惯上要写,我也写,默认实现怎么快怎么来,期待着未来能改进。 我也希望 nodejs 中能写 interface ,但是不想用 ts 。
    0 0
  • darksword21
    2022年5月26日 08:56
    如果突然某一层要换的话确实很方便,比如数据库,上层基本不用变,当然在公司里一般写完也不会变了 我是说我在 go 中这么写,java 没经历过
    0 0
  • guxingke
    2022年5月26日 08:56
    如无必要 勿增实体 --- 不妨从自己做起,没必要声明的时候就不声明呗。 毕竟真有必要的时候,再抽出一个接口并不困难。
    0 0
  • Kaiv2
    2022年5月26日 09:25
    说下这种模式的优点 IUserService UserSeriveImpl 我开发一个依赖 UserService 的模块, 你负责 UserService 模块的开发,但是还没实现。你可以先提供接口给我。 类似的 ( dubbo 服务也是这样)
    0 0
  • slimhigh
    2022年5月26日 09:25
    你的理解是对的。大部分情况下是没什么用的,大家生搬硬套罢了。
    0 0
  • retrocode
    2022年5月26日 09:25
    规范嘛, 恶心是真滴恶心, 不过好处是有这么一套通用甚至垄断的规范在, 不至于太恶心,不然高情商点百花齐放,低情商则神魔乱舞,一个人一套规范,天天吵最佳实现谁也不服谁那才是真的恶心了
    0 0
  • ThinkCat
    2022年5月26日 09:25
    如果不涉及到多实现,那可以不用 interface ,直接写 class 实现就行了。但是如果明确在后期存在扩展的情况,一定要定为接口,避免后期大范围的修改代码
    0 0
  • potatowish
    2022年5月26日 09:25
    有规范就容易产生模板式的代码,但是没有规范,大家各写各的,不利于团队开发
    0 0
  • forbreak
    2022年5月26日 09:25
    大部分情况下没用,但是一旦要用,你之前写了跟没写 差距久出来了。 我只一个旧项目,改 rpc 调用,之前写了 inteface 很容易久迁移好了。没写的话,就得重新写一遍。。
    0 0
  • panpanpan
    2022年5月26日 09:55
    虽然 Spring 在 AOP 的时候,类实现了接口就使用 JDK 动态代理,没有则使用 CGLib 但是实际上大家都用 springboot, springboot2.0 之后默认情况下不管你有没有接口统统用 CGLib
    0 0
  • yazinnnn
    2022年5月26日 09:55
    写 spring 不会写,都是单实现,基本不会写接口 写 vertx 时会, 因为会用到 service proxy 和 codegen 基于 future 的接口 client, 会把 reactive 的 client 给你包好 基于 future 的接口服务, 会把 eventbus proxy 生成好 现在改用 quarkus,然后又不写接口了....
    0 0
  • v2orz
    2022年5月26日 09:55
    因为我真的见到过有多种实现的情况
    0 0
  • mekingname
    2022年5月26日 09:55
    写 java 的人,骨子里就喜欢过度设计。他们很多人写的代码一辈子都不会重构或者增加新的功能了,但是他们总是抱着:未来要增加新的功能,所以要面向接口来设计。
    0 0
  • sparky
    2022年5月26日 09:55
    面向接口而非实现的编程思想 越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性
    0 0
  • dajj
    2022年5月26日 10:25
    无脑重复前人的代码, 毒瘤模板而已
    0 0
  • yangyaofei
    2022年5月26日 10:55
    很多原因吧, 比如: 1. 被诟病的 封装, 设计设计设计, 设计模式啊, blbla... 2. 正常原因 java 不能多继承,只能用 interface 来做(其实还好) 3. 卷 4. 包屎
    0 0
  • asanelder
    2022年5月26日 11:25
    #19 嗯, 这样说也有点道理, 关键是好多接口和实现是一个人来写的... @ #22 不明白需求增长了, 为啥要替换实现? @ #34 俺也是这么个意思 @ #36 持久层可以抽象的, 俺的意思是业务层为啥也要抽象... @ #38 这个确实也是一种场景. 俺忽略了 @ #47 看来这写不写接口不是设计上的考虑, 有时更多是框架的限制...
    0 0
  • fpure
    2022年5月26日 11:55
    mock 也可以不用接口的
    0 0
  • cool4food
    2022年5月26日 11:55
    对 OO SOLID 稍微理解深入一点的话,应该就不会有那种尬黑吐槽的言论了
    0 0
  • RadishWind
    2022年5月26日 11:55
    之前接手过一个屎山就没有 interface+impl 结果有个方法很慢 找到后没法使用 注解进行优化 Spring 很多特性是依赖动态代理的
    0 0
  • icylogic
    2022年5月26日 11:55
    超出必须的设计,无非就是方便调试 /测试 /扩展,如果未来一段时间内,你发现你实现新需求 /调试 /测试的时候,需要从这里继承实现一个不一样的,那说明这设计至少算不上错,如果你发现你这项目到死都没有过这种事,那就是过度设计,要么是思维上懒惰,要么是对未来需求预估错误。如果你发现你可能需要,但你觉得有更好的方式,那就是你们团队之间选择谁来适应谁的问题。
    0 0
  • haah
    2022年5月26日 11:55
    为啥 C/C++er 要写头文件呢?
    0 0
  • luzemin
    2022年5月26日 12:25
    1. 为了实现 OOP SOLID 中 D ,依赖抽象而不依赖具体,为了 N 年后的随时换掉具体实现而规划 2. 方便测试 3. 约束方法名称:具体实现类必须继承并且实现同名方法 以上都是理论,实际往往偏差比较大,基本是因为“模版就是这样”“业内都这样”而跟着做的。
    0 0
  • vincent7245
    2022年5月26日 12:55
    规范,规范,还是 TMD 规范,这就是为什么 java 可以做超级大型的项目。当你一个人做项目的时候可以随意写,当四五个人做项目的时候,一般的口头沟通就可以了。当几百个人同时做一个项目的时候,没有规范你啥都做不了。当你做过大型项目你就明白了。这里的大型项目是指代码至少 10W+起步
    0 0
  • ration
    2022年5月26日 12:55
    面向对象基本都是这样,除了多个实现,依赖注入外,还有其他好处。比如你可以只看接口就知道实现了什么功能,而看具体的类就有一大堆代码了。接口这种东西一开始是来源于硬件而不是软件。
    0 0
  • qbmiller
    2022年5月26日 14:25
    大多数项目用不上. 大型项目确实要, 防止写飞 实战为准. 确实没必要 别的语言从没这么多破事
    0 0
  • Rocketer
    2022年5月26日 14:55
    各种设计模式都是为了方便项目规模成长的,所以绝大多数“没必要”都是因为团队 /项目还不够大。 等规模大到设计模式显示出优势时,大概率就很难改了,最后变成💩山。 当然,一直写那种代码的程序员也不会意识到设计模式的优势,他们宁可把代码复制粘贴到一百个地方,也不愿把代码写得一劳永逸。只要不跳出舒适区,我就是舒适的😄
    0 0
  • vone
    2022年5月26日 14:55
    方便单元测试和多实现。 但是现实是没卵用,因为这些复制粘贴的垃圾代码既没有单元测试也没有多实现。
    0 0
  • git00ll
    2022年5月26日 15:25
    确实,我同事也有人喜欢整这些接口,每个 server 都整一个接口,我感觉没必要。 上面提单测的,单测与接口有什么关系,大部分情况下没接口使用 mockito 或 spock 都能搞定,遇到一点点搞不定的再整接口也行啊
    0 0
  • RedBeanIce
    2022年5月26日 15:55
    还是网上流传的那句话,网友本科生 5%? v2exer 写业务的 5%?
    0 0
  • ychost
    2022年5月26日 15:55
    当你写 framework 的时候,接口就很重要了,还有 IOC 、SPI 都非常方便
    0 0
  • RiceNoodle
    2022年5月26日 17:25
    事实是,面向接口编程对写单元测试非常友好。 优秀的项目愿意这么设计是因为用得着,不代表每个项目都这么优秀。
    0 0
  • asanelder
    2022年5月26日 17:55
    #71 framework 大量用接口俺感觉正常, 毕竟要考虑通用性, 但 web 项目嘛... @ #69 嗯,好像俺写测试时不用接口感觉也没啥
    0 0
  • xuanbg
    2022年5月26日 18:55
    别问,问就是规范和习惯。 虽然没啥用,而且 Java 也早就支持接口的默认实现,但大家还是这么写而不是写成默认实现。
    0 0
  • cherryas
    2022年5月27日 01:25
    因为写个 interface 没几分钟,写完还能自动生成 impl 。
    0 0
  • micean
    2022年5月27日 01:55
    写 framework 、library 是一定要的,业务上很多就多余。别提 mock……
    0 0
  • Narcissu5
    2022年5月27日 02:25
    - 有些地方需要接口,比如 java 动态代理 - 如果你的接口几乎都只有一种实现,那么你的抽象可能不够。实际上你没有用到 OO 最重要的能力也就是多态 - 如果你对多态不感兴趣,建议转 Go 。实际上 Go 更符合大多国内程序员的思维模式
    0 0
  • wangxin13g
    2022年5月27日 02:25
    吐槽接口的写代码不写单元测试吗 写项目的时候就不考虑后期有人重构的吗 写项目就一个人吗?
    0 0
  • Akagi201
    2022年5月27日 02:25
    其实面向 interface 没有问题, 主要是要程序员要理解什么是 interface, 为什么会有 interface, 有的低级开发复制粘贴惯了, 直接把实现都复制过来这样根本没有意义. interface 本来就是让你自己梳理你的模块的接口的, 让功能自洽, 合理的设计接口, 而现实有的低级开发只是把一堆乱七八糟的东西堆到 interface.
    0 0
  • qiumaoyuan
    2022年5月27日 02:55
    这个问题说到底是预先设计 v.s 重构的问题。很多人所谓的“重构”其实是重写,没办法重构只好预先设计出接口。
    0 0
  • zzzkkk
    2022年5月27日 03:55
    通用性 可扩展 对小型项目 来说都是垃圾 过度设计是万恶之源
    0 0
  • 2NUT
    2022年5月27日 05:25
    我觉得是非常好的 编程习惯, 从整个项目的视角
    0 0
  • Akagi201
    2022年5月27日 06:25
    有人说换种实现可以不换 interface 的, 可是有的低级开发设计 interface 时候就没考虑换个实现的兼容性考虑. 还是得一起重构. 而且除了库, 业务服务往往只会用到一种实现.不会存在两种实现共存的情况
    0 0
  • VictorJing94
    2022年5月27日 06:25
    好像这个是某些教程里的..刚从 java 转出来时候还很不适应
    0 0