跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Spring 里 Service 层分成接口+Impl 的好处是什么?
未分類
28 12 月 2020

Spring 里 Service 层分成接口+Impl 的好处是什么?

Spring 里 Service 层分成接口+Impl 的好处是什么?

資深大佬 : AAASUKA 6

分开写感觉很累赘,为什么很多人这么选择?
为什么不直接用一个 Service 类实现

大佬有話說 (68)

  • 資深大佬 : hcx0

    现在对 99%的项目来说没有好处,就是机械的遵照惯例

  • 資深大佬 : dorothyREN

    我就懒的写 impl,直接 service 真香

  • 資深大佬 : jzmws

    1. 接口说要做什么
    2.impl 说明如何做
    现在大部分都是一个接口一个 impl ,最早的设计思想应该是接口对应多个 impl

    用接口的好处是我无需关注他是如何实现的,你一个接口可以有多重实现类 , 后期方便维护, 屏蔽底层实现细节

    不好的地方是 代码量变多了

  • 資深大佬 : araaaa

    业务代码里没卵用的设计

  • 資深大佬 : tidezyc

    首先面向接口设计肯定是一种合理和标准的编程规范,其次当十几个人维护同一份代码的时候,遵守这样的标准规范是保证代码质量和可维护性的前提,当然你要自己一个人写着玩就随意了

  • 資深大佬 : AlisaDestiny

    如果你能明白 java.util.List 接口存在的意义你自然就知道为什么这样设计。

  • 資深大佬 : laminux29

    详细原理与实施经验在软件工程课程里,建议找书仔细看看。

  • 資深大佬 : Cbdy

    这样做很蠢,请不要这么做

  • 資深大佬 : hantsy

    1,大型项目,基于接口的设计是比较理想的。(对于中国公司来讲,大部分还是套用三层结构,没有架构设计成分)
    2,在 Spring 中 Proxy 无处不在,早期 Spring 的技术限制,比如使用了某些技术,创建 Proxy 只能用于接口。

  • 資深大佬 : freebird1994

    没有用。就像上说的,其实你的接口只有一个实现。没有任何卵用

  • 資深大佬 : chendy

    现在没用
    1. 现在的项目很少需要多个实现
    2. 抽接口主要因为 java 自己的动态代理机制需要接口,但是现在用的 cglib 子类的并不需要
    3. 有的时候还是需要的,需要的时候抽就行,IDE 的重构工具抽个接口很快的

  • 資深大佬 : xuanbg

    好处是我可以只写 service,impl 交给别人去写。

  • 資深大佬 : quantal

    你在问这个东西的时候就说明不需要,需要也就不用问了

  • 資深大佬 : tedzhou1221

    举个我现实的栗子

    我一个功能接口,有三套逻辑,根据类型去判断到底用哪套逻辑。不同逻辑就是不同实现类

    所以我要用接口。

    再使用策略模式+spring 的注入机制。我调用层只注入接口就可以。

    但很多时候,还是一个接口一个实现类。

    有很多同事都习惯把不同逻辑的全放到一个实现类。各种 if 判断……

  • 資深大佬 : tedzhou1221

    接受上,如果有增减实现类需求,可以通过 @congfiguratong 去从配置里控制,或者用 spring spi 去实现。

  • 資深大佬 : tedzhou1221

    手机打字,打错了几个字……

  • 資深大佬 : yetone

    为了可以写测试啊同学们……

  • 資深大佬 : ElmerZhang

    Java 写得不多,只想请教一下,不用 Interface 的话,单测怎么写呢?

  • 資深大佬 : cheng6563

    curd 的业务没用,其他的局部功能才有用。

  • 資深大佬 : extreme

    面向接口而不是具体实现进行开发
    一方面解耦
    另一方面,我觉得也是最重要的一方面,就是方便单元测试

  • 資深大佬 : hantsy

    @chendy 多个实现的场景太多。

    只是国内的架构师,做软件设计的角色,没有起到相应的作用,其根源也是国内的公司都是猴急一样的做项目,没有回到软件系统设计本身,各种文档,各种形式很足,做出来的东西一团糟。

    对于复杂的业务流程,都是可以完全接口调用方式设计,完全先不管具体实现,用一个 Dummy 实现先去验证设计上的逻辑是否能够合理。

    我在国内公司呆那么多年,从来没有哪个公司会让你花时间写 POC 去验证一套流程的合理性。如果做国外的产品项目就完全不一样,你有很多机会去想如何才能做到真正的逻辑上的解耦。

  • 資深大佬 : hantsy

    @extreme
    @ElmerZhang
    @yetone 早期写测试,Mocking 的时候,的确需要接口。但现在最流行的 Mockito 一样是可以 Mock 类的,Spring 进行了集成,可以直接 @MockBean,@SpyBean 。

  • 資深大佬 : hantsy

    @ElmerZhang Spring 测试工具太成熟了,我的测试例子:

    https://github.com/hantsy/spring-reactive-jwt-sample/tree/master/src/test/java/com/example/demo

  • 資深大佬 : hantsy

    MockBean 实例: https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/test/java/com/example/demo/PostControllerTest.java

  • 資深大佬 : Lxxyx

    理论上这种面向接口编程可以做到先思考,再实现等诸多优点。

    实际上很多业务的接口都是一对一的,不会复用,也不会留足时间给你慢慢先思考再上线。。更多的是 CRUD 莽代码。

    但自己还是要知道这种编程范式和带来的优势的(上都说过了),用不用那是另外一回事。

  • 資深大佬 : hantsy

    不过这里本身使用了 SpringData,Repsoitory 就是接口,用具体的类也是一样的测试。

  • 資深大佬 : hantsy

    真正的软件产品开发,你应该花一半时间去思考如何实现(接口抽象的阶段),另外一半时间去写实现和测试。

  • 資深大佬 : young1lin

    1. 面向接口编程,而非实现(其实这个是屁话,更多的是代码遗留问题,因为以前的项目都是贫血模式开发的,这个也适合中小项目)。

    2. 如果你实际编程中由于某些原因想替换掉其中一个方法的话,可以替代 @Lookup 注解,直接换另一个实现类。

    3. 还有一个是 RPC 调用,引入接口即可,然后通过 Annotation*BeanPostProcessor 之类的将接口装饰成具体代码调用。例如 @DubboService 这种。你定义入参就行了,不用关心其具体的实现,你在其他 Service 或者 Controller 直接构造方法注入就 ok 了。

  • 資深大佬 : ruoxie

    跟创建代理有关吧,没写过 java,Spring 里应该是一堆的 IOC,AOP 。之前写过 c#,c# 里创建代理要么基于接口实现,要么是重写虚方法,一般都是基于接口实现。

  • 資深大佬 : simonlu9

    c 语言也是这样的,先声明下头文件,然后再写实现,后来 spring 的引入,让这个更加有说服力

  • 資深大佬 : hantsy

    @ruoxie 早期 Proxy 都是需要接口的。

  • 資深大佬 : anzu

    1. 可以让技术负责人之类的专注于业务框架的搭建,具体实现让组员来做。
    2. 微服务,调用者需要知道接口参数,但不需要知道接口实现。
    3. 安全性,算是微服务的延伸,比如 UserAuthService 之类的,无关人员只需以 git submodule 引入接口项目即可使用,做到了代码的保密性。

  • 資深大佬 : hantsy

    @anzu Microservice 一个原则,各服务应该自治,根本就不关心其他服务的代码层面的实现(不管是接口还是 Impl ),每个服务都是可以用不同的语言和框架实现。

    服务之间交互通过轻量协议( Http,Message Broker,gRPC,RSocket 等)定义。

  • 資深大佬 : tianlan

    最近在看设计模式。 书上说 桥接模式 是将一个工程的 抽象与实现分离,从而在开发的时候独立使用。 我想 这个是一个扩展

  • 資深大佬 : idoggy

    可以建议团队内部放弃这种写法,很好推动的,根本不会有阻力。除非是很老早的 spring 那没办法得带上接口,现在项目里接口也就用在多态上,普通流程都是 controller 调 service 调 dao 完事。

  • 資深大佬 : taowen

    你感受不到好处,就是没好处,不要怀疑。

  • 資深大佬 : 312ybj

    首先这个是有用的。
    面向接口编程的优势很大,策略模式可以借助接口实现具体策略的导入。
    你慢慢实践设计模式,你就会发现设计模式里都是这种设计,

  • 資深大佬 : Cbdy

    @ElmerZhang mockito

  • 資深大佬 : charlie21

    保障 JAVA 大军的就业人口

  • 資深大佬 : zxCoder

    不知道 学的时候大家都这样写,去公司实习,发现大佬们也是这样写,就跟着写了

  • 資深大佬 : Hadoop270

    这个问题 在我刚学 java 的时候也想到了- –

  • 資深大佬 : xiangyuecn

    以前也写过 XXXService XXXImpl,还有 XXXMapper.java XXXMapper.xml , 还有 XXXEntity 还有 XXXController

    繁琐,堆砌,复用说不上,难看才是真的

    现在只剩 XXXController,其他的除非确实必要,否则一概不写

  • 資深大佬 : zhazi

    粘一段 Jhispter 对这里的理解

  • 資深大佬 : zhazi

    Should we use interfaces with our Service Beans?

    Short answer: No.

    If you want the long answer, here it is:

    One of the main interests of using Spring is AOP. This is the technology that allows Spring to add new behaviors on top of your Beans: for instance, this is how transactions or security work.

    In order to add those behaviors, Spring needs to create a proxy on your class, and there are two ways of creating a proxy:

    If your class uses an interface, Spring will use a standard mechanism provided by Java to create a dynamic proxy.

    If your class doesn’t use an interface, Spring will use CGLIB to generate a new class on the fly: this is not a standard Java mechanism, but it works as well as the standard mechanism.

    Some people will also argue that interfaces are better for writing tests, but we believe we shouldn’t modify our production code for tests, and that all the new mocking frameworks (like EasyMock) allow you to create very good unit tests without any interfaces.

    So, in the end, we find that interfaces for your Service beans are mostly useless, and that’s why we don’t recommend them (but we leave you with the option to generate them!).

  • 資深大佬 : loongwang

    降低其他人的阅读难度, 例如你这个 service 代码很多,有很多 private 方法, 当其他人用到或者阅读你的代码时, 可以直接从接口中获取到必要的信息,而不是去读一遍你的代码才能获得必要的知识,

  • 資深大佬 : asanelder

    @hantsy #21 “猴急” 这个词用的真实。。。

    “如果做国外的产品项目就完全不一样,你有很多机会去想如何才能做到真正的逻辑上的解耦。”

    国外真的这样么?

    @hantsy #27 俺遇到的基本都是:设计和测试是最不给时间的,每天都是写写写,然后早会汇报完成了多少多少。

    你要是连着几天汇报在搞设计,上面会认为你在没有任何产出。。。

    有时真不知道这些“上面”当初是如何写软件的。难道他们也不是过来人么?难道他们体会不到这东西也要设计,也要 demo 的么。。。

  • 資深大佬 : asanelder

    俺感觉主面对的项目是这样子的。

    1. 贫血模型:从 dao 层查出来的只是数据,而且是和具体 dao 层字段绑定的格式(如 mysql )
    2. 所有的业务都在 service 层( service 中各种对贫血模型字段的判断和处理)

    因为”业务”本身就不是抽象的,不需要多实现,所以,导致的就是 service 接口和对应一个 service impl 这种鸡肋的形式存在。你想想,同一 service 接口,你还能有其它什么实现么?

    真正需要接口的是需要抽象时,需要和具体实现无关时,如

    一个接口 UserRepository 表示用户数据仓库

    而实现可以是

    FileUserRepository
    DBUserRepository
    XXXUserRepository

    这样多实现是有意义的。

    而业务都写在 service 类里,那么业务的多实现指的又是什么呢?

    造成主的困惑原因,可能就是”前人都这样写,那我也这样写吧”

    于是,就这样了

  • 資深大佬 : qiumaoyuan

    高级

  • 資深大佬 : fkdog

    我觉得我们应该用发展的眼光看问题.
    service-impl 以及设计模式不是啥圣经, 大部分项目开发搞这些玩意纯属没事找事.

  • 資深大佬 : liuxey

    我的个人见解:就是历史糟粕

  • 資深大佬 : xcstream

    可以按代码量算 kpi

  • 資深大佬 : NilXuan

    从数量上来看,一个 Service 可以对应一个多个 Impl ;面向接口编程可以使多个 Impl 之间的替换变得极为简单;比如,开发时,我把验证码发送到控制台;上线后切换到真实运营商服务,只需改变注入的 Bean,而无需到处修改;这就是好处(之一);
    需要考虑的问题是,是用不到还是没有用?如果用不到,是设计没设计好,还是根本没设计?是本来就用不到,还是应该用到,但是没有用到?我认为不能简单地说有用还是没用;个人不认同“历史糟粕”或者“历史遗留”这种看法;至少这种一对多的关系,就是比一对一要灵活;

  • 資深大佬 : kkeep

    对我来说只有一个好处,就是强迫自己设计接口。而不是 impl 里面随意加函数。

  • 資深大佬 : joecqupt

    接口可以用 JDK 做动态代理,方便之后暴露 RPC 或者其他什么逻辑处理

  • 資深大佬 : Aresxue

    老月经贴了,继承->接口实现->容器->注解,当你能清晰弄清楚它们的依赖程度并能在项目中选择合适的时候你就不会有困惑了。当然这是对于需要精细打磨的项目而言,而大多数的项目本身就是对业务,本身就是一种快消品罢了

  • 資深大佬 : reed2020

    我接触到的一些这样写的项目,它们的 service 和 impl 都是一一对应的,没啥卵用。

  • 資深大佬 : Zhancha

    项目经历应该会很爽,直接看就行,不需要看里面的。

  • 資深大佬 : jk1030

    面向接口,重构的时候及其舒爽
    另外还有一个就是代理呵 rpc 吧

  • 資深大佬 : jason19659

    @loongwang #36 但是现在所有 ide 都有 schema 啊

  • 資深大佬 : hyqCrystal

    @joecqupt 但实际上即便是暴露给 RPC 大多数是 API 层暴露给 RPC

  • 資深大佬 : iceneet

    增加代码量

  • 資深大佬 : hantsy

    @NilXuan 大部分人没这么用过吧。可能是对于很多就用完全两个不同的 Service 类吧,Console 和运营两个类呗,见太多了。

    对于很多人用类,接口跟 PHP4 的函数没差别,只是堆代码,没有从语言和软件的角度考虑为什么有接口和类这些不同的玩意。

    我说过,我以前很多时候写 POC,比如银行对账的一个简单的流程,将请求类,响应类,各种异常路径包装成异常,所有的行为用接口来描述。用简单的 Dummy/Fake 实现类(伪数据填充出来的),用测试验证一个流程中各接口的合理性,一步步连接起来是否通畅,是否所有异常路径都是可以顾及到。

    经过反复讨论过后,再把接口抽出来 ,切换到真实场景去实现( Bank Credit,Stripe 等)。

  • 資深大佬 : securityCoding

    多数情况下业务 service 这样写基本没啥卵用 , 多态你得有多个实现类的场景撒 .

    比如你想写个缓存小组件,可以基于 memory/redis ,这时你定义一个接口就有用了…

  • 資深大佬 : caizs320525

    现在的感受是,为了写注释能够更清晰,与业务代码分离

  • 資深大佬 : qwerthhusn

    增加代码量,代码统计的时候,你写的代码不比别人少

  • 資深大佬 : vanishxiaoma

    我之前提问过一个相似的问题
    https://www.v2ex.com/t/592647#reply36
    可以参考下大佬的回答

  • 資深大佬 : hhyygg

    @asanelder #47 这个例子不错,学习了

  • 資深大佬 : KarmaWu

    我司的项目,不同版本会根据策略模式跳转到不同的 Impl 类,高版本的继承低版本的 Impl

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具