1 Star 1 Fork 0

好未来技术团队 / fend-doc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
layering.md 8.37 KB
一键复制 编辑 原始数据 按行查看 历史
thinkpc 提交于 2020-07-21 15:58 . init

框架分层规范

PHP行业常见框架分层为基础MVC,但是对于企业级应用且研发团队超过10人以上时并不适用

为了规范分层概念及研发标准特此在此文档进行分层规范详细定义

此类规范并无绝对标准,重在统一规范,分层过多会带来一定维护成本和代码,各个开发团队根据业务形态自行调整,如不确定可找我们进行讨论分析。

层级隔离性建议

  • 同层代码切勿相互引用调用,如出现此情况,建议将相互引用模块中某个模块降级到下一层,此举可提高业务代码隔离性
  • 上层服务可调用下层服务,不可下层服务反向调用上层服务,简化降低业务代码复杂度

通过以上设计,可以大量减少引用层级,方便未来业务管理拆分,代码纵向切面清晰完整。

关于最大分层

最大分层是指当业务复杂到一定程度,极限情况下的分层设计。

如业务简单则可对如下分层进行合并无需完全实现,具体可根据业务情况自行划分。

具体分层如下:

  • Controller
  • ServiceHelper
  • Service
  • Module
  • Model

分层的好处在于每一层完全隔离下一层所有细节接口规范统一,方便调用,对外提供服务规范文档,对内提供服务方便简单。

下面将会对具体分层功能职责、功能、规范进行详细介绍

注意:特殊情况特殊分析,欢迎找我们进行讨论进一步分析。


Controller

  • 对外业务封装层,所有对外接口页面封装必须都在此层,其他层级代码外部请求皆不可访问
  • 本层支持多级目录,默认请求路径与controller目录层级一致,如/user/login默认请求路径为www.xxx.com/user/login
  • 外部请求常见在url中包含参数,本框架也支持此方式但此举不推荐,主要原因对未来数据监控整理会带来大量工作
  • Controller层代码禁止调用Controller层代码,限制过度引用可大量降低后续维护成本,如有此类业务需求,请将被调用代码降级到下一层内引用。
  • 禁止在此层直接调用Service层及以下模块,如model、module、ORM配置层
  • 本层只调用Service进行业务拼装,调用Service不建议直接new Service类,请使用ServiceHelper封装对Service进行调用
  • 所有用户请求参数必须做安全过滤验证,后续会对输入输出数据用Request及Response进行统一封装

代码示范:

ServiceHelper

  • Controller调用Service服务时,强烈建议统一使用此类调用,这样Controller层与Service层没有直接关联关系,并且能够统一规范Service所有行为,后续如果出现特殊情况可以在此层加入Hack代码临时解决问题,换取后续有充足时间进行无痛无感优化,注意一旦实现hack代码逻辑事后一定要清理迁移,不要长时间留技术债在公共基础功能类内。
  • Service 以下层级出现逻辑或系统错误时皆会抛出Exception,此Helper会对所有Exception进行拦截,以此保证Controller层不会因为Exception出现500或白屏故障,Exception自带msg、code、backtrace对于debug更方便直观。
  • 通过此层封装 Controller层和后端服务完全隔离、若需要RPC化直接改此层内部实现代码即可实现前后端分离,如需对Service调用情况进行统计也可在此层增加统计分析代码等操作。
  • 此层可做服务熔断,降级,cache,根据需要进行拦截管理

代码示范:

$result = APIHelper::invoke("ServiceName",array("param1"=>array(),"param2"=>1));
if(!$result->isok()){
      echo "错误原因:" . $result->getMsg() . "(" . $result->getState(). ")";
      return;
}
//获取返回数据
$data = $result->getData;

Service

  • Service 服务层内是具体业务逻辑,可使用Moduel及Model对业务进行组装,对输入验证,输出格式都有统一的类进行封装管理
  • 本层支持多级目录,具体可根据业务需要进行多层级封装,不推荐超过两层。如\v1(版本,可选)\user(类)\login(函数)
  • Service接口文档后续会提供自动生成功能,但需要使用统一输入验证类方可(注意:此功能还在制作中)
  • 建议封装成可灵活组装业务逻辑的粒度供Controller层组合,若牵扯事物建议最好在一个Service封装完成
  • Service层后续升级必须考虑兼容性,除非十分确认使用方会跟随升级
  • 底层及本层所有逻辑异常或底层异常会抛出Exception,此类Exception皆由ServiceHelper进行拦截,非必要、不要拦截
  • 异常分两种:业务异常请使用正整数(用户未登录),底层异常及框架异常请使用负数(Mysql connect error,redis went away)作为错误码,通过这个简单定义可以让客户端研发人员更好区分错误类型。
  • 可复用性建议,同一个模块或服务数据实体仅存一份文件不要出现同一个数据实体分布在多个目录内情况,如User用户相关操作最终对外提供Service服务时必须所有定义在一个Service主体内,如:用户登陆有同样三种封装在不同文件内。 具体可以参考OOP设计思想进行设计,下面的module、modle也建议如此设计
  • 同层Service代码不允许调用或引用同层Service,如果出现建议将一些逻辑降级到Moduel或model层内。
  • 请保证每一个Service都是无状态的服务,不存在私有变量、static变量(factory变量除外)

代码示范:

Service 调用返回格式:
array(
     "state"=>1,//返回1代表正常,其他都为异常,不同模块不同错误码前缀
     "msg"=>"错误信息",
     "data"=>数据数组,
     "backtrace"=>"如果有错误,这里是错误的backtrace,方便调试"
)

Module

  • Module层是一个可选的分层,如果底层数据结构不是十分复杂可以忽略此层
  • 若底层数据来源存在多种,可以使用此层将复杂的多来源的数据进行聚合 **例如:**数据源来自Redis、Mysql以及第三方API协作,这样可以汇总多来源Model
  • 完全隔离底层数据来源及特征,对外提供标准的业务封装及数据操作功能,对业务研发人员只需简单调用即可使用
  • 出现错误会抛出异常由业务组合层决定是否重试或提示用户,也可以底层自带多次重试,最后仍旧失败后抛出异常
  • 此层只能调用Model及ORM层配置定义且同上面几层一样,同层禁止相互调用,但是可以如下方式组合使用/module/user.php调用 /module/user/login.php使用,但不可反向,但是Service层尽量调用/module/user.php而/module/user/login.php属于私有文件不上层提供任何服务。
  • 如上其他层:一个数据实体对象只能存在一份定义和出入口
  • 关于Cache,若数据来源复杂,可在此层对汇总后数据进行Cache

代码示范:

Model

  • Model层有很多种数据来源,目前已知Redis,Mysql,其他服务提供的API,如果有多种来源有两种组织方式。 根据数据来源分目录后再根据对象名称分子目录或文件如/model/redis/user/user.php,不同来源不同目录 根据model层内代码汇总所有操作如/model/user/user.php(内含,api,redis,mysql所有操作)
  • Model层对所有数据具体操作进行隔离,对外提供简单调用即可实现对数据的增删改查操作,此类封装只做基础封装不做具体业务封装,并不能保证业务事务完整性,如有此类联动多数据源操作一应封装在Module或Service层。
  • 其中外层应保证传递数据做一些基础的安全过滤,Model为了效率没有对传递参数有效性做过多验证检测
  • Fend底层也会做一定安全过滤,但由于一些限制能做的范围有限。
  • Model异常常见有两种,操作失败(Redis,Mysql,API请求失败,断开连接,事务失败),传递参数错误,此类都会抛出Exception
  • 关于Cache,Model层的Cache只能保存常见的单条数据以及一些不太复杂的查询结果,如果对数据实时性较高不建议进行Cache,如来源是第三方提供的数据源(Mysql,Redis,API)是无法保证实时同步更新Cache的,此类情况可另外做订阅更新,此类问题已经超出框架范畴。

ORM

  • 一般来说此层是隐含的,极少出现涉及本层单独定义情况,如果业务使用大量Redis key且需要统一定义管理才会使用本层。
1
https://gitee.com/ta-tech-team/fend-doc.git
git@gitee.com:ta-tech-team/fend-doc.git
ta-tech-team
fend-doc
fend-doc
master

搜索帮助