关于对业务代码编写的思考

关于对业务代码编写的思考

我为什么有这篇思考?

我在一次偶然的时间点产生了“致力于打通黑白盒测试”的想法,然后开始了漫长的自学编码的“生涯”。这个过程是坎坷的,其中产生很多问题,本文是我遇到并且克服的问题之一——众所周知,在开始学习一个新知识或者技能的时候,我们都是满怀激情的,但是随着遇到的困难或者说游戏难度的增加,大家都会逐渐焦虑。但是本着不抛弃不放弃的精神,我们需要努力战胜一个又一个阻碍。

我们在学习了一个个单个技术的时候可能一马平川,勇猛精进,但是在结合这些知识进行完整的业务编码时却是犯了难。怎么将学习的编码知识运用到实践中呢?本文所述的即是我对这个过程的思考总结。我在这块一度卡壳,我猜大多数同学曾经都可能遇到过这样的问题。

本篇我们以一个开源论坛项目的通用逻辑编写作为案例。(参考小滴课堂的课程demo)

怎么定位,与处理字段?

编写业务中的数据处理逻辑时,可以查看sql与实体中的字段,分析哪些字段需要特别处理(需要从dao层逆推到service层)。

例如,分页查询回复接口中,需要向前端返回一个具备页码、页面大小、总页数以及当前页的数据,service层会先获取总的回复记录数作为需要查询的数据条数,作为limit??的第二个参数。(其实第一个参数也算属于特殊处理的,它通过(page-1)*pagesize计算得出从多少条数据之后进行查询。)

这种处理是基于sql语句中的用法来考虑的——limit??表示从a+1条数据开始,查询b条数据。(其中a、b分别代表第一个、第二个占位的参数)

分析数据是输入型还是输出型?

对于数据处理中,还有根据情况分析是输出型处理还是输入型处理。

输出型数据一般是提供给用户使用 考虑的是友好可理解,还是例如上文的例子——用户需要的不是一个大列表数据,而是一个具备页码等元素的ui,它的实现要求后端返回的是一个包含多层的复杂对象的json字符串。

在这种情况下,我们要通过数据的组装,然后往外输出。例如 一直讨论中的分页查询逻辑中,将输入进接口的页码、页面size大小、经过计算得出页数(通过查询出来的总记录数/页面size,这个计算在dto中进行)以及最后查询得出的列表对象 一起组装 进一个分页dto中,最后返回出去。

输入型数据与输出型数据关系紧密,正是由于有输出数据的要求,导致在某些情况下输入型需要获取一些比较麻烦的数据。

例如增加逻辑中,例如评论发布(我认为增加逻辑也是和输出联系的,因为任何逻辑流程都是有输入输出的 增加逻辑也不例外,从接口层面来看它增加成功后也会给一个字段反馈, 从业务层面来看,有的场景会及时更新页面,也就是查询一次页面)输入的数据有文章的id、文本内容,但是插入到数据库中时,我们需要的还要插入的用户信息(用户id、名称、头像等)、评论的创建时间、更新时间、逻辑删除标志、评论的楼层等。

在这个例子中,除去输入的文章id、文本之外,其它数据都足以处理。它们分别有各自不一点获取方式——用户id可以从session中获取,用户其它信息则额外通过查询用户表来得知;因为是增加行为,日期时间通过自己创建,如果是更新动作,那么创建的时间需要通过查询历史记录;楼层是通过查询不要来得知上一个评论的位置;因为是新增操作,删除标志位设置为0(假设0为未删除,一般0表示false)。

得到上面这些数据之后,根据编码规范 也不会硬生生的直接 传要堆参数到下一层,而是能够装入对象的就分别转入对象中(存在多个对象的情况下分别传多个对象),然后再传入到下一层。

下一层就是dao层,在dao层处理则清晰多了,因为是与数据库进行操作,这里考虑的更多是数据库需要什么,我有什么?如果没有,那么就需要返回上一层甚至是上上层进行获取了。当然这个思考在编写service层的时候就需要根据dao层的处理进行逆推考虑。

在controller层进行处理还是在service层进行处理

这段我先从“”非专业的野路子开始逆推思考”。分析在哪一层进行处理一个数据,不如分析这个数据是属于哪一个“范围“的,例如用户session信息在request范围,我们肯定不会去,下一层进行处理。还有处于不同的service层的方法,我们也是在更高的一 层进行处理。这样看显而易见了,原则就是范围最小化处理

其实如果是“正统”的技术路线出发,大概不会这种烦恼。因为javaweb有一个MVC的分层设计,基础数据都在数据模型中进行处理的,也就是Model中,然后Model提供数据给控制层进行处理。
在这里插入图片描述

注意接口的约定

参照事先约定的接口要求,可以得知最初的controller层输入与输出的要求。

假定这些输入是恰当的,我们就可以开始分析需要输出的数据应该从哪些服务中获取(写好对应的方法需要的输入),如果这些服务中没有相关方法则需要对其进行补充。这个时候在service 层我们考虑的是controller层调用的方法,对该service的输入输出约定。

编写到对应service层之后,我们就开始考虑该层需要的数据从哪个dao层中进行获取以及向其输入什么样的数据,其实也就是对dao 层的方法进行了一个约定。

其中,在进行输入时,比如说更改时,需要考虑更改的实体的字段。有些情况下传入的参数不能刚好满足,需要经过从表中再次查询或者通过一些简单的计算等获取到。

这就是整个编写过程了。

怎么使得编写的思路变得清晰

即便以上文章叙述了很大的篇幅,看上去准备充分了,编写的时候仍然卡壳在怎么办?

我们来理一理思路,如果我们开始已经确定了接口约定,也就上我知道要这个接口输入什么和输出什么,即已确定了controller 层的输入输出了。

接下来应该根据dao层所需来逆推其它层需要处理的数据。即便我们dao层方法可能还不具备,但是我们在约定接口之前就进行er图设计、写好了实体类以及建立了对应的数据表。所以我们是清楚的知道这个 程序的这个接口是要进行一个怎么样的数据库操作(例如,输入多少数据进行 插入)。

只不过我们不是一次“干脆点“输入——而是输入一部分,再通过其它办法获取一部分,再拼装在一块数据表。

所以对于一个插入接口,如果我将实体类字段与er设计图摆在旁边,我是清楚的知道我除了用户端传入的数据之外,还要通过程序自己的处理要获取的数据有哪些。

到了这个阶段,我需要分析的则是哪些数据在哪一层获取比较合适。这个我们可以遵循范围最小化处理的原则进行 。(其实这里通过背景的补充,我们知道它们是在遵循MVC/MTV设计)

同理,对于返回的数据也可以这样考虑。不论是输入还是输出,它们都有一个共同的特点——可能不是一次性处理就可以得到的,而是需要进行一定的组装。

思考到这里,我们可以发现,接口代码的编写不是线性思考的,而是类似立体的考虑的。当然经验的积累有助于这一能力。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值