学会自我提问
业务开发是技术能力的试金石,如果日常开发总会有各种状况,需要开发者提起重视。
今天着重唠一唠我总结的业务功能开发中提高效率的小技巧。
在开始重点内容之前,我先列几个扪心自问的问题:
- 多任务并发,如何有条不紊的进行工作?
- 某次需求难,难的是UI、交互还是数据存储?
- 来来回回的这几个页面功能变更,我的开发效率提升了吗?
- 接连三个需求之后,我的哪种开发能力变强了?开发效率?思维敏捷性?解决问题速度?新技术的掌握和应用?
- 为什么别人的功能开发总是想的那么全面?
一般公司都有项目复盘,尤其大型项目上线之后,针对开发过程中遇到的问题,进行复盘,能够总结开发经验。自我提问,可以当成一次自我复盘。一段时间做一次,可以查漏补缺。
曾子曰:“吾日三省吾身:为人谋而不忠乎?与朋友交而不信乎?传不习乎?”
技术人的三省吾身:“我问题解决了吗?我技术进步了吗?我开发速度变快了吗?”
设计文档
“磨刀不误砍柴工。”讲的就是开发前设计文档的撰写。
我的设计文档主要包括开发排期、需求梳理、重点功能设计。撰写设计文档的主要目的是,评估开发周期和合理设计开发功能。我所在的技术部门,每次都要进行设计评审,只有设计文档中的功能设计得到认可之后,才能进入开发阶段,否则需要重新进行功能设计。所以我每次都会认真设计我要开发的功能。
开发排期
我一般做开发排期时,到页面维度,根据具体页面的难易程度计划开发时间,以小时为单位。
而联调排期,也是到页面维度,根据当前页面的接口的数量和接口的入参以及返回的结构难易进行评估,以小时为单位。
我是在保险科技公司,主要负责理赔业务的开发。下面是我某次开发时的排期:
修改(新增)页面 |
开发时间/h |
联调时间/h |
理赔列表页 |
6 |
3 |
理赔详情页 |
2 |
2 |
上面表格中的排期,是经过以下三个阶段之后,最终确定的排期。
简单页面开发如何排期
对于相对简单的页面功能,我一般先梳理修改项是什么,比如文案修改、新增展示内容、哪些可以用公共组件,哪些可以做成公共组件。简单页面基本在需求梳理结束之后,心里就有一个开发预期了,时间上也能比较有比较准确的评估。
比如像详情页,因为我们有现成的组件。只需要根据页面内容组成展示数组通过props传给详情组件即可。所以我开发评估了2h,联调时考虑到返回的数据较多、结构较为复杂,所以我也评估了2h。
详情页组件的开发,我之前写了一篇文章【工作小记】后台系统代码简洁之路-详情页设计。
复杂页面开发如何排期
复杂页面,我一般都先进行拆解。复杂的逻辑经过拆解之后,会分出很多细项,细项中还是区分简单和复杂,但是这个时候难点不在是凭空感觉的,而是很明确知道的难点在哪,时间评估自然也会准确很多。
比如像后台列表页类的页面,因为我们的项目已经有搜索项组件和列表组件,所以列表页一般1h就能搞定。
而列表上的操作项往往是较复杂的表单功能。比如新增报事,需要填写的内容较多,所以我评估了4h。
而其他的取消、删除、日志等都有现成的组件,所以1h就能完成。这样一个页面,开发时间的6h就出来了。
而联调方面,取消、删除、日志组件已经将接口请求也考虑进去,所以联调排期只需要考虑添加操作即可。添加操作考虑到数据结构的复杂和编辑的回显,所以我评估了3h。
反问方式确定最终排期
我在做完全部的排期之后,并不会着急发出来,我会最后审查一下所有的开发时间。
这个时候我会在心里反问自己几个为什么。
- 这个页面为什么排期时间长,是哪个功能比较复杂、复杂点在哪?然后向下找一下复杂功能,看一下设计方案,最终确定它的复制程度以及实现难点在哪。然后再次评估时间的准确性。
- 这个页面为什么排期这么短,页面的交互、UI、操作是不是都很简单,可以很快完成开发。再次确认功能复杂性确实不高的时候,就能确定最终的开发时间了。
- 我的整个排期计划是否合理,有没有压缩或者夸大排期。夸大排期会影响个人技术的成长,而压缩排期会有延期的风险。两个都不推荐,合理性考虑是开发排期最终的自我检验。
详细的功能设计
详细的功能设计有助于更加合理的预估排期。我一般会以单个页面为开发纬度,每个页面的UI、交互、表单操作等难易程度不一,甚至同一个页面不同的操作难易程度也不一样。所以功能梳理会协助更好的评估排期。
所有的功能都需要列出实现方案吗?
并不是所有的功能都需要列出具体的实现方案。有些文案修改、新增展示内容、或者新增的操作已经有现成组件等,只需要列出需求的内容和实现描述即可。有些相似的功能,比如添加/编辑弹窗,只需撰写添加的实现方案即可。
重点功能怎么设计?
复杂的交互包括几种,操作流程过长、嵌套层级过多,联动项过多,不同场景的功能不一样等。
流程图
流程图是开发很好的帮手。比如登录流程,复杂的登录流程,流程较长,会根据用户的状态的不同做不同的处理,这个时候凭空想象,总会出现遗漏。不如动手画一下流程图,可以帮助避免遗漏。
复杂功能拆解
复杂的功能,也有简单的部分。比如嵌套层级过多的功能,每一层的功能可能并不复杂。所以对于这类需求,我会先进行功能剥离处理,再耦合在一起。比如我曾经有共需求是查询不同年的不同月份下的不同状态的理赔数据,并且可以进行点击跳转到不同页面。我根据年、月、状态,进行了三层数据处理,在将处理后的数据整合在一起。这样不同维度的功能处理不受干扰。
熟悉业务
对业务的熟悉程度也能间接的提升开发速度和开发质量。
在开发中,通过对业务认知的加深,掌握举一反三的能力,可以再功能设计上增加功能的复用性和可扩展性。
- 详情页组件,也将原本复杂的案件详情页面简化了,只需将页面内容按照原型中给定的内容重组成数组,通过props传给详情页组件即可。且支持特殊展示内容和操作功能,也大大缩短了详情页的开发时间。
- 不同业务之间的相似操作,比如列表的批量删除操作,这个操作我在其他业务开发时遇到过,后面理赔业务也需要开发这个功能,因为已经有现成的功能,所以我直接拿过来用了。这个操作,我之前也总结过一篇文章【功能实现】多个批量操作的链式实现。
- 在做重构时,熟悉之前的业务,可以简化某些判断逻辑。比如图片的有效期,会根据产品性质的不同区分是否需要,之前在页面展示和提交时都做了判断。重构时,我将判断提前到了获取页面数据的位置,展示和提交时不需要做二次处理。
老页面修改的功能隔离
在修改老页面的时候,如果新增功能和老的页面功能能够区分开,即能减少因不熟悉代码导致的漏提测功能问题,也能够减轻测试的压力。
比如新增的图片有效期的功能。
数据回显
componentDidUpdate() { // 获取图片信息this.getImgInfo(); } /** * 获取图片信息 */getImgInfo= () => { //letresData=res; // 接口数据letimgInfo=resData.imgInfo|| {}; this.formRef.current.setFieldsValue({ imgInfo, }); this.setState({ imgInfo, }) };
页面展示
/** * 图片有效期展示内容 */imgContent= () => { return ( <><Form.Itemlabel='图片有效期'name='imgEndFlag'rules={[{ required: true }]}><Radio.Group><Radiovalue={1}>短期</Radio><Radiovalue={2}>长期</Radio></Radio.Group></Form.Item></> ); }; {this.imgContent()}
数据提交
/** * 表单提交操作 */submit=value=> { let { imgInfo } =this.state; letparams= { value }; // 有图片时if (imgInfo.hasImgType===1) { params.imgEndFlag=value.imgEndFlag; } };
自问自答
前面自我提问的几个问题,归根结底是对自己开发效率、开发质量、开发能力的盘问和深思。
并行可行
工作中难免会遇到并行任务,我们熟知四象限法则能很好的帮助我们合理安排工作。但是实际开发中的并行需求,可能完成时间都差不多,所以不能简单的按照紧急程度进行排期。
我领导教我的方法是,将一天的时间进行拆分,根据任务量进行时间划分,比如简单的任务,可以划分2小时去做开发,内容较重的任务花6小时进行开发。
做好任务分工,我在工作中挺游刃有余的。一般2-3个任务同时进行对我来说压力不是太大,再多就有压力了。
全面可全
再说一下这个考虑全面的问题。
一般复杂情况漏掉某些场景的情况,可以通过画流程图和设计图避免。
另外就是对自己要做的功能所处的业务充分熟悉,有些特定场景也的业务功能,可以通过阅读代码注释、结合上下文、结合前后页面进行更详细的了解。
提升是必然
你十分清楚自己要做的事情的时候,无形中就节省了一些走弯路的时间。而设计文档就可以帮助你清楚要做哪些事。