Service层内容是更具哪个来写

我很好奇,大家的 service 层是围绕,哪个来写的,是更具 model 里面的功能来写单独的模块,然后再 controller 里面组合,还是直接更具 controller 里面的内容来写,我更具 controller 来写,感觉其实写直接在 controller 里面差不多,只能说一部分的功能可以重复调用,大部分还是无法的复用,感觉有点点鸡肋的感觉

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

最大的作用就是解耦和提高复用性,试想一下,例如我的很多个模块都需要查询一次用户信息,以往的做法都是在各个控制器中写一次:

$user = User::query()->find($id);

如果我做成服务,那就可以这样写:

// 控制器:
$user = $this->userService->findUserById($id);

// userService
return $this->userRepository->findUserById($id);

// userRepository(数据仓库)
return User::query()->find($id);

后续如果有更改,我只需要更改 userService 中的代码就可以,不需要每个调用的地方都要去修改。或者以往获取数据都是通过 User 这个模型去获取,我需要加缓存层来获取用户信息,那么我只需要修改 userRepository 中的代码就可以。 使用 service 有好几种写法:

一种是控制器处理简单的数据校验,调用 serviceservice 里调用不同的数据仓库组合完成一组服务;

// 控制器
$order = $this->userService->getOrderByOenId($openId);

// service
$user = $this->userRepository->getUserByOpenId($openID);
if($user) {
  $order = $this->orderRepository->getOrderByUserId($user->id);
}

一种是 service 和数据仓库一样符合单一原则,控制器除了数据校验,就是通过调用单一的 service 来组合完成需要完成的事,后续 service 的调用依赖于前面 service 返回的结果。

// 控制器
$user = $this->userService->getUserByOenId($openId);
if($user) {
  $order = $this->orderervice->getOrderByUserId($user->id);
}

还有一种就是 service 实现 interfaceinterface 里写好了传的参数类型、个数和返回值的类型。

1年前 评论
讨论数量: 9

最大的作用就是解耦和提高复用性,试想一下,例如我的很多个模块都需要查询一次用户信息,以往的做法都是在各个控制器中写一次:

$user = User::query()->find($id);

如果我做成服务,那就可以这样写:

// 控制器:
$user = $this->userService->findUserById($id);

// userService
return $this->userRepository->findUserById($id);

// userRepository(数据仓库)
return User::query()->find($id);

后续如果有更改,我只需要更改 userService 中的代码就可以,不需要每个调用的地方都要去修改。或者以往获取数据都是通过 User 这个模型去获取,我需要加缓存层来获取用户信息,那么我只需要修改 userRepository 中的代码就可以。 使用 service 有好几种写法:

一种是控制器处理简单的数据校验,调用 serviceservice 里调用不同的数据仓库组合完成一组服务;

// 控制器
$order = $this->userService->getOrderByOenId($openId);

// service
$user = $this->userRepository->getUserByOpenId($openID);
if($user) {
  $order = $this->orderRepository->getOrderByUserId($user->id);
}

一种是 service 和数据仓库一样符合单一原则,控制器除了数据校验,就是通过调用单一的 service 来组合完成需要完成的事,后续 service 的调用依赖于前面 service 返回的结果。

// 控制器
$user = $this->userService->getUserByOenId($openId);
if($user) {
  $order = $this->orderervice->getOrderByUserId($user->id);
}

还有一种就是 service 实现 interfaceinterface 里写好了传的参数类型、个数和返回值的类型。

1年前 评论

基本上就是控制器的逻辑多了 然后封装一个无状态的 service 出来

1年前 评论

Service 要介于 Model 和 Controller 中间。一般来说,Model 也不应该和 Service 有直接关系,数据应该由 Repository 来处理,换句话说 Service 就应该做到独立、解耦、可复用。

Service 中至少不应该直接调用 request 或者使用其他方法来获取超全局变量,这些值的来源都应该作为参数传进来,尽可能减少 “魔法依赖”。

单个服务还应尽可能考虑单一性,打个比方的说,对于处理用户登录、注册。这种情况应该怎么办?创建一个 UserService ,在里面分别创建 login 和 register 方法?还是分别创建 RegisterService 和 LoginService ?

两种方法都是可以,但是如果是前者的话,那就相当于把 Controller 直接搬到了 Service 了。但是也要视情况而定,对于前者来说,如果业务简单,自然是没有问题。对于复杂的业务而言,那可能后者会是更优的选择。

1年前 评论

考虑 service 的时候不要考虑 mvc 的东西,service 类就是纯代码逻辑。

我一开始写的时候也有迷茫,当时写的时候控制器写一个方法, 然后在 service 实现, service 内部的方法之间也没有什么内聚, 感觉不优雅。

后来优雅起来是因为我开始写自己的包,定义接口,然后接口的功能实现在 service 里面,就感觉特别自然, 复用也很 OK, 感觉这才是 service 的合理用法。

不一定只有自己写包才能使用 service , 我上面的例子只是说明我学习的一个过程。现在我的项目工程文件也有 service 它的逻辑和我包里的 service 是一个逻辑。 就是 service 它是某个接口的实现。这个接口是某个功能模块开发前定义的对外的公开方法。和 控制器 模型 视图啥的关系都不大。 一个 service 类可能多个控制器会调用, 也可能依赖多个数据模型。

1年前 评论

其实楼上说的都没错,核心就是解耦,避免流水账一样的代码,使用功能单一原则,提高代码复用率,让可维护性和可扩展性得到提升,只有合理的分割,后期维护后者迭代的时候才能顺畅

1年前 评论
sanders

其实有没有 Service 层全看业务复杂程度,如果都是简单的资源访问,那便是不要 Service 层也可以。 一旦你发现某些控制器、队列任务或监听器的方法代码出现大量复制甚至是处理的模型也都一模一样的时候,那就该考虑是不是要拆出来一个 Service 层来保存这部分逻辑并在控制器间进行调用,或者被其他的 Service 调用。

1年前 评论

最大的作用就是解耦和提高复用性,试想一下,例如我的很多个模块都需要查询一次用户信息,以往的做法都是在各个控制器中写一次:

$user = User::query()->find($id);

如果我做成服务,那就可以这样写:

// 控制器:
$user = $this->userService->findUserById($id);

// userService
return $this->userRepository->findUserById($id);

// userRepository(数据仓库)
return User::query()->find($id);

后续如果有更改,我只需要更改 userService 中的代码就可以,不需要每个调用的地方都要去修改。或者以往获取数据都是通过 User 这个模型去获取,我需要加缓存层来获取用户信息,那么我只需要修改 userRepository 中的代码就可以。 使用 service 有好几种写法:

一种是控制器处理简单的数据校验,调用 serviceservice 里调用不同的数据仓库组合完成一组服务;

// 控制器
$order = $this->userService->getOrderByOenId($openId);

// service
$user = $this->userRepository->getUserByOpenId($openID);
if($user) {
  $order = $this->orderRepository->getOrderByUserId($user->id);
}

一种是 service 和数据仓库一样符合单一原则,控制器除了数据校验,就是通过调用单一的 service 来组合完成需要完成的事,后续 service 的调用依赖于前面 service 返回的结果。

// 控制器
$user = $this->userService->getUserByOenId($openId);
if($user) {
  $order = $this->orderervice->getOrderByUserId($user->id);
}

还有一种就是 service 实现 interfaceinterface 里写好了传的参数类型、个数和返回值的类型。

1年前 评论

我感觉你在使用 Service 定位有点乱了,
我的话 Service 对应 Controller,查询数据在 Model 中或者增加 Business 来查询数据。Service 主要用于在组装数据。

1年前 评论

看过不少项目写的 service 层,现在维护的一个很多年的 symfony 项目里的 service 层也看过,我感觉自定义的 service 层在目前看来就是鸡肋,至少写出职责分明低耦合的 service 是一件很花精力的事,我现在一般都把逻辑全部放在 controller 里面了。

真想复用逻辑的话可能用一下其他的成熟的包提供的封装思路比较好,比如 easywechat 里面的事件推送,数据查询层面上封装一下 repository 啥的,像我目前处理文章的投稿流程,文章表十几个状态,已经考虑采用状态机了。

另外就是我觉得就是不要拘泥于呆板的 service 层这个概念,不要把 service 跟 mvc 绑定起来,可以写一些具象的服务,玩点设计模式,然后把操作类注入一下,比如一些 handler (manager, processor, factory, builder) 之类的,这样不是很好吗。

1年前 评论
Complicated

项目大了 自然就能体会到什么样的代码要写在 service 层了。只不过往往做不到这么大的项目

1年前 评论