前言
介于团队成员开新项目编码风格不统一,
(主要是因为大家容易混淆 service/model/control 之间的关系,导致代码流程不清晰,可读性略差)
造了一个「风火轮」,并实现了以下的链式 service 效果
DEMO1. 这是一个简历置顶的例子
service_manager::instance(resume_service::class)
->find($id)// 找到当前简历
->permission($uid)//检查权限
->get_current('site_id')// 从当前简历中找到 site_id
->join(site_service::class) // 切换 site_service
->find_by_last_response() // 通过上次找到的 site_id 取到站点配置
->get_current('top') // 取到当前站点配置的置顶设置
->join(resume_service::class)// 切换 resume_service
->top_validate($days) // 验证用户选择的置顶天数是否正确
->top_prepare_amount() // 为扣取余额准备参数
->join(amount_service::class)// 切换 amount_service
->use_money_by_last_response() // 根据 resume_serivce 返回的参数进行支付
->join(resume_service::class) // 切换 resume_service 上下文
->set_top() // 保存置顶
->top_prepare() // 为 top_service 的 create 准备参数
->join(top_service::class) // 切换 top_service
->create_by_last_response() // 根据上次准备的参数进行创建
->exec(); // 执行
DEMO2. 这是一个发布简历的例子
service_manager::instance(site_service::class)
->find($site_id) // 找到当前站点
->get_current('resume', 'freepubs') // 取得免费发布条数
->join(resume_service::class) // 切换 resume_service
->set_user_id($uid) // 设置 uid
->set_site_id($siteid) // 设置 站点 id
->top_validate($top_days) // 验证发布时是否选择置顶
->create_validate($_POST) // 创建简历前数据验证
->create() // 创建简历
->create_prepare_amount() // 为创建简历支付余额准备参数
->join(amount_service::class) // 切换 amount_service
->use_money_by_last_response() // 根据上次准备的参数进行使用余额
->join(resume_service::class) // 切换 resume_service
->set_top() // 如果用户有置顶,则置顶
->top_prepare() // 为 top_service 准备创建置顶数据
->join(top_service::class) // 切换 top_service
->create_by_last_response() // 根据上次准备的数据进行创建置顶记录
->exec(); // 执行
实现:
service_manager (入口) -> service_proxy ( service 代理类) -> service ( service 实体类)
关于 service_manager
由 service_manager::instance 创建 service_proxy 类。
关于 service_proxy
service_proxy 的魔术 call 方法代理 service,将所有的调用方法和参数存入栈,
service_proxy 方法进入 exec 时,
会回调 service_manager 去遍历所有的调用栈,逐步执行方法。
链式中断操作均是 throw new Exception
关于 service:
实例所有 service 均为单例。
运行 service 时,会有一个 context(上下文),和 reponse (前一次调用)的默认属性。
也可以根据方法名(带有 response )的会默认传回上一个非 join 方法的执行结果。
初衷
- 业务分层,至少能让 control 层的逻辑更加清晰
- 微服务,后期可直接替换为 RPC 等协议
最后
转了 N 圈,没发现业界有这么做的案例,心里有一点虚。
不知道各位大神们有什么要喷或者讨论的,特来诚心讨教一下利弊。
已知的好处:
- 业务线清晰
- service 执行颗粒明确
- service 之前可以避免直接调用
- 后期 service 可快速更换为微服务
已知的弊端:
- 传参数只能在类内部进行传参
- 部分性能损耗,内存消耗可能会双倍( service_proxy 会暂存所有调用栈的方法参数)
- service 提供服务,如果要提供不同的 Exception 会比较难受
- service 之间事务控制不太友好
- 链式的代码提示是个问题