关于后台实践的一些疑问、思考与建议

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012107143/article/details/78781107

1. 关于工具类

  1. 建议一个公司或者一个产品线的项目,使用统一的工具包,而不是每个项目都建立自己的工具类。包括一些枚举类,基础抽象类等也建议加到项目的基础工具包中。

  2. 如果要在自己项目中编写的工具类,尽量多实现一些常用的函数。或者让工具类直接继承一些框架中的常用工具类,如StringUtils可以继承common.lang中的StringUtils。

2. 关于日期和时间

从controller的参数,到数据库的存储,一律使用时间戳或者Long,只有在展示的时候在格式化为字符串。

3. 关于注释

为了多平台的兼容性和国际化交流,我们鼓励使用英文。但是如果为此造成表意不清,则得不偿失。所以在此推荐开发人员使用自己的日常语种书写注释,包括代码注释和git提交的commit-message信息等。如此,虽然传播时不太便利,但是至少可以保证作者首次表达的准确性、完整性和丰富程度。

4. 关于缓存

程序只对相对稳定的系统资源进行缓存,而不直接对接口进行缓存。接口的缓存不在系统中进行,而是有专门的更便于管理的缓存机制。

5. 关于Controller层的设计

  1. 尽量不要在接口当中要求属性必填,而是在程序中多做些缺省判断与默认参数。除非这个参数是核心参数,缺省后没办法设置默认参数,并且后续逻辑都无法运行。数据库中的非空属性同理。

  2. 我们常常把创建与更新的写在一个接口里,而它们的行为可能会有很大差异,要小心。对业务提供的接口和对工具(比如爬虫)等提供的接口在实现上也有很大差异,业务接口相对简单稳定,工具接口要求全面灵活。

  3. 在rest风格的api中,”/A/{A_id}/B”:表示查询id为A_id的A下面的B资源;但是如果批量查询多个A下面的B资源呢?【这时,api应该直接写为”/B”,A_id只是B的查询条件。】

  4. 系统中有A、B两种资源,它们就有联系又相互所属,那么:“查询A资源下的B资源”的接口应该放在A的Controller中还是B的Controller中?即,Controller层的分类应该按照查询条件还是返回结果?【推荐按照返回结果分类。根据B的属性查询B放在B的Controller中,根据A的属性查询B也放在B的Controller中,它们本质上都是对B的查询,只不过查询条件不同,所以api应该设计为:”/B”;但是如果是查询A(要求附带返回A关联的B),这时应该放在A的Controller中,api应该设计为:”/A”(或者”/A_with_B”)。】

  5. 后台Controller的分类是按照:前台页面进行分类比较好?还是按照后台资源分类比较好?【Controller按照前台页面分类,Service按照后台资源分类如何?】

  6. Controller层的职责:校验和转换参数;调用Service层,组装和整合各类系统资源;捕获和处理异常;多语言处理等等。

  7. 常见误区:把Controller层作为对Service层,点对点的单个函数的封装,如此的话Controller层实际上就失去它的意义了。

  8. 建议把对某个资源的所有的查询放在一个接口里,然后增加一个searchType字段去表示需要传过来的查询参数的个数与类型,如:searchType=1表示按a属性查,searchType=2表示按b属性查,searchType=3表示按照a,b,c,d这4个属性一起查。如果不这样做,每有一个查询需求写一个查询接口,接口数量增长太快,api都不好命名。
    或者,如果觉得上面的做法,不符合“对修改关闭,对扩展开放”的设计原则,也可以这样做:把基本属性的查询放在”/A”;特殊查询,比如根据B的属性查询A,放在”/A_filter_by_B”;如果查询A时需要关联着查出B来,可以归到”/A”下,可以单独写作”/A_with_B”;如果前端需要返回的只是A的部分属性,可以另外单独写一个DTO,”/SimpleA” 。

  9. 如何实现rest风格中的一切皆资源,如何把动作转为资源,需要不断的在实践当中思考、理解和练习。

  10. rest风格接口的返回值,不应该用ResponseDTO等实体进行包装,应该直接返回内容,或抛出异常(不能直接抛出程序异常,应该是封装过的异常)。

  11. 动态接口(即和用户相关的接口),不同的用户返回不同数据,不能缓存,需要动态计算,请求的数据应该尽量少,尽量简化逻辑,只给出必要关联数据,然后由客户端来组装成完整数据。静态接口则可以多做一些冗余,因为其可以被缓存,所以对效率的影响不大。

6. 关于数据库设计

  1. id应该用uuid,还是自增?应该由前端生成,后端生成,还是数据库生成?
    建议:前端生成uuid,这样可以解决重复保存的问题,并且可以直接拿到id不需要等接口返回,保存接口也不需要有返回值。(如果是数据库生成的自增id,那么前端要在保存接口返回数据后才能拿到id。在此期间,如果保存了2次,数据库里将会有2条记录,造成重复保存。)(当然,也可以由前端来控制重复提交的逻辑,给ajax加锁,进行ajax时锁关闭,ajax调用成功后把锁打开。)

7. 开发前的工作(开发六定)

  1. 需求阶段
    • 定需求:明确这个系统的作用,以及系统需要具有哪些功能
    • 定边界:明确哪些功能应该放在这个系统里,哪些不应该放在这个系统里
    • 定界面:明确实际系统使用者的操作和使用流程
  2. 设计阶段
    • 定接口:明确前后台数据交互,要精确到输入输出字段,保存字段的名称和属性
    • 定数据:明确数据库设计和数据流动过程,确保可以支持接口功能,要给出数据模型
    • 定架构:明确系统整体架构,保证系统的非功能性需求

8. 关于发布

发布时间一般定在一个月的最后一个周四。

9. 客户端和管理系统对接口要求的不同

  1. 客户端对接口的要求:只返回必要数据。(像是创建时间、更新时间、版本号等不必要的数据库字段,不需要的就不要返回)
  2. 管理系统对接口的要求:尽可能的灵活,数据结构尽可能的完整。(上面提到的数据库字段最好也返回,可能用于排序)
    注:最好是管理系统拿到所有数据,也提交所有数据,这样可以简化接口实现,防止多次查询

猜你喜欢

转载自blog.csdn.net/u012107143/article/details/78781107
今日推荐