service层和dao层之间是怎么调用的 service层和dao层区别

网友提问:

Service层和Dao层真的有必要每个类都加上接口吗?

优质回答:

你反思说明你开启智商了。我也曾问过很多程序员包括自己,为什么每写一个类都要找写一个接口,再写一个实现类Impl?竟然没有一个程序员能正确回答,大部分都竟然说老师或者书上都这么教的,而且学spring框架都这么干。前面有人也回复了接口是稳定的,实现类不稳定,经常要改。但一般代码都是你自己写的,稳不稳定自己不清楚吗?如果一定要改,连接口一起改岂不是更费劲。所以往深层次思考,连spring框架都要去质疑了。

所以我的结论是,国内的开发习惯导致了这个疑问。因为作为团队开发来讲,规范的开发习惯是先写接口和测试用例,实现类甚至会写一个伪代码以保证测试代码能正确运行。测试驱动的软件开发是一定要实现和接口分离的,从J2EE到Spring架构的演化都是遵循这个目标。

现实是一个程序员自己搞定好几层,然后没有一行测试代码。这种情况下每个类都写一个接口再写一个实现类,岂不是画蛇添足吗!

这是我的见解,欢迎拍砖。

其他网友回答

这个问题是一个非常好的问题,很多程序员在刚开始工作的时候,接触到的项目都是这样做的,一个接口对应一个实现类,然后就一直保持了这个习惯,但是可能并没有考虑过为什么要这么做,或者并没有想过这么做的好处是什么。

从工程化的角度来看,面向接口的编程是很有必要的,不过我们还是要结合实际情况来考虑。

“如果实现类可能会变化,那么最好使用面向接口编程,让每一层代码解耦,减少后期的修改工作量。”但后期真的会变化么?

这句话看起来是没有问题的,比如我们要实现一个给用户发送短信的功能:

项目刚开始的时候,公司买了阿里云的服务,直接调用阿里云的一个接口进行短信发送;项目运行一段时间,又改成和腾讯云合作,那么发送短信的代码就需要修改;为了避免领导说“再改回去吧”,这里写一个接口、两个实现,上层方法只面向接口编写,就会方便很多。

不过,这一切都是我们“假想”出来的,至少我工作十多年,几乎没见过这种变来变去的需求,至于 Dao 层都加接口,避免项目做数据库迁移,原来用 Oracle 现在要换成 MySQL 之类的… 从来没有遇到过。

“接口相当于一个标准、一个规范,制定接口的人和实现接口的人,可能不是同一拨人。”如果是在同一个项目中呢?

这句话没有错,通常这种情况确实适合使用面向接口的编程,比如 JDBC 的实现:

Oracle 公司(之前的 Sun)提供 JDBC 标准(接口)。

各个数据库厂商提供针对自家数据库的实现。

我等码农在 Java 中敲代码访问数据库。

这时候接口制定、接口实现和接口使用就是不同的人;

但是如果在同一个项目中呢?

如果项目是一个人开发的,那不用说,接口制定、实现和使用都是一个人,这时候还费这劲儿干啥;

我们大多数项目,接口类和实现类都是一个人来做的,很少有项目是领导把接口写好,然后说“各位小弟,实现类就看你们的了”;

那么实现和使用的人呢?大部分时候也是同一个人,但也有例外,比如一个需求设计两个功能模块的修改,A 模块的开发要用 B 模块的一个功能,这时候可以 B 模块的开发把接口先定好,这样 A 和 B 就可以同时开发了;

当然 B 模块的开发也可以先写一个空方法:方法名称、入参和出参都制定好,中间没有逻辑,然后先提交一版,这样 A 模块的开发就可以快乐地 new() 了;不过我不太建议这样做的原因是:通常开发 commit 一次,提交的内容应该是完整的。

那么既然我们的项目中,接口和实现类通常是一一对应的,而且开发的人也是同一个人,又没有更换实现类的可能,那么还有必要面向接口编程么?

可以从以下几方面考虑:

如果你的业务需要通过 RPC 的方式暴露给其他系统调用,这时候接口是有必要的,调用方只关注接口,不关心你的实现类,也不会因为你的实现类变更而受到影响;

测试驱动开发,在具体的实现类完成之前,需要先根据结构编写测试用例;

现在有些框架只需要开发人员写结构了,比如 Spring Data JPA、Feign 等等;

除了以上种种必须或最好使用接口的场景,我认为只要项目稍具规模,最好还是面向接口开发,就算一个接口对应一个实现类;当你带领一个团队的时候,可能这个团队并不大,只有三五个开发人员,但是随着项目的推进迭代,如果没有使用面向接口开发的话,你会惊奇地发现,项目的代码越来越复杂、越来越乱了,一个类有几十个方法,一个方法有几百行代码,新来的组员看的一头雾水,甚至你这个项目经理都不想看其中的代码;

不要提什么制定代码规范,规范一直都在,但是总有人不遵守,防是防不住的;

如果项目的 Service 层和 Dao 层,都是接口-实现类这样做的,大多数时候代码还是可以看的,相当于多了一个方法目录,比如可以让开发人员在写一个新方法之前,看看能不能复用之前的方法;

当然,你不这么做的话,开发人员也可以直接在实现类中看现有的方法,只是相对来说说,在一个几十上百行的目录中翻找,和在一个成千上万行的实现类的实现类中翻找(尽管有各种快捷的方法罗列出方法列表),相比还是前者更容易些。

我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。

其他网友回答

不要为了模式而模式。

其他网友回答

这是必须的,我们的开发手册中不允许出现Service层中方法是非实现接口的方法。

在DAO层中,如果是采用Mybatis3.0以上,本身我们编写的方法都是基于接口的,所以不存在这个问题。

在Service层中,我们为了代码规范、方法复用,我们必须定义接口。举个简单的例子:

我们一个业务系统中可能有多个业务模块都有CRUD的方法,那我们是要在每个Service接口的方法中定义add、get、update等CRUD的方法吗?当然不是。我们只要定义一个接口,接口中定义好这些方法,相应的业务类去实现这些接口就行,然后在各自的实现类去实现这些接口即可。

所以说,为了代码规范和接口复用,我们需要定义接口。

其他网友回答

接口不是为了替换实现。如果从mysql改成Oracle,只要把方法内容改变即可。不改变方法声明就行。做接口,是为了共存。接口往往都会和工厂模式一起用。比如,发送代办,可以做一个send的接口。这样可以有多个实现类。比如短信,邮件,微信,钉钉等。至于service和dao是否需要接口,我觉得如果是做产品,则需要接口。定制时,只要通过继承原实现类并重写方法实现。否则定制只能通过修改源代码实现。至于修改了某个类的方法导致1000个调用了此方法的类要重编译,那要看是否修改了方法声明。即便使用接口,接口申明改了也要全部编译的。只要不是产品,或者通用组件,纯业务上的service和dao没有太大必要使用接口。日志,代办,消息等通用服务组件上使用接口还是有必要的。当然使用了接口,在转变为微服务上,成本会小很多。通过接口代理,可以实现该业务实现类在不同的架构上的重用。

版权声明