java项目小结

坚持了两个月终于上线,在这过程中经历的一切估计只有自己能理解了。由于是工作以来第一个自己独立负责的项目,所以现在想把这过程记录一下,顺便谈谈自己的不足以及收获,由于项目本身比较小以及个人经验和能力的欠缺,所以写的东西可能质量不行,但是起码态度还行,仅供自己和新人参考。

需求分析阶段

这个阶段应该是最痛苦的吧,虽然项目和难度都不大,但由于是公司自主研发的产品,所以在没有任何需求的情况下,只能借鉴多个不同的优秀产品然后取其所长,再结合自己的实际应用场景,一个一个功能点的对比分析,经过多次开会反复确认后,终于把初期的需求基本确定下来,也许这部分不是一个程序员的分内之事,但是没办法,公司较小没有专门的产品经理,所以只能自己也参与其中了。这部分的内容我不知道该讲些什么,但是感觉是最烦的一部分,因为功能是否合理以及用户体验对我来说真的不好估算。所以在你不确定需求是否合理以及能否完成的时候,只能多花精力去研究牛逼的产品是怎么玩的了。

原型设计阶段

本以为第一阶段过去了就会很轻松,毕竟需求是自己最不擅长的,所以需求确定下来以后就会觉得很简单。但是发现我错了,因为这次项目是自己独立负责,所以需求讨论完以后剩下的所有工作基本都是自己做决定,这是一件好事,因为自己的权力变大,可以按照自己的习惯或者要求去编码,但难过的是前端,UI,经理都要找到我,所以我要负责把所有流程的功能点全部串联起来,每个字段的确定,表结构的设计,流程图等等。不然UI无法去画原型,前端也无法开展工作。嗯,就这样又坚持了一两周,把表结构给确定了,所有的页面和字段元素都给了设计以后就着急的开始了编码。。。emmmmm。。这个阶段貌似又把需求理了一遍

编码阶段-1

同样的,本以为第二阶段坚持过去以后,编码阶段就是最爽了。事实也确实如此。但是在第二阶段我并没有给全所有页面以及跳转的细节和元素,导致在编码阶段还存在漏页面和字段的情况,但是这时你的思维已经基本固定了,最糟糕的是在分析和确定需求阶段没有严格的文档记录,只有那几个零乱的.txt文件,所以我觉得最最重要的一个血的教训就是文档了。需求讨论完的前几天也许会记住80%,结合当时的笔记还能全部确定。但是一周后,两周后记的那些笔记已经完全凌乱了,因为我发现我在不同的笔记中出现了互相矛盾的内容,可以理解为代码没有复用吧,所以在出现了两处需求相似的内容时我自己也不能确定到底哪个是最终确定的了。所以到这里为止,只想说一点,那就是文档,至于文档的重要性在此就不多说了,只有亲身经历过才会明白。(给个小建议,文档一定要有结构且加上日期等判断版本问题,确保自己能判断哪些是最新的内容)

开始言归正传,以上部分也许是很多程序员不曾经历的,可能很多程序员都是按照现有的需求直接编码即可,甚至表都已经设计好。但是能参与到需求中并完全理解以后,也不是坏事,所谓磨刀不误砍柴工还是很有道理的,这样在设计代码的时候,能够比较准确的解决相关需求问题,而且会更有可能写出"好"的代码。

编码阶段-2

在这里就不具体谈论项目的名称和功能了。大概说下背景吧,主要框架是springboot+mybatis,同时还用到了springcloud做微服务架构,因为需要和其他的服务有一些关联,比如单点登陆、消息服务、用户管理等等,所以也用了redis做了全局的缓存服务器。项目采用完全前后端分离的模式,pc端主要是后台管理功能,移动端是微信小程序,开发团队是两个前端,两个后端。以下就列出几点在本次开发过程中的总结或者是走过的坑。

1.应该使用全局统一的返回模型

至于返回模型里面的参数可以根据实际需求确定,但是一般都有3-4个参数,返回值:code,返回消息:message,返回数据:data。本次项目的框架里面就是使用的这3三个。主要是继承了map的对象来维护。建议message与code值全局统一维护,这样业务代码里面不会存在硬编码,而且前后端都可以对返回状态值统一处理,从而方便应对业务的变更。举个例子,一个按钮有两种操作状态,而且多个页面中都有该按钮,那么前端肯定是对该按钮中的返回内容做了统一的封装处理。假如此时需求有变,该按钮又多了一个状态,那么此时前端该怎么做?由于之前是统一处理的,所以现在要么是单独在页面中判断一次,不合符再走封装的那个逻辑;要么就是直接在统一封装的方法中直接加条件即可。那要是逻辑再变呢?所以答案很明显,我们肯定是要前后端都做统一处理,这样在不破坏原有功能的基础上更加方便功能的扩展和变动。假如对于返回值不做统一处理,后期真的会超级麻烦。

2.时间格式问题

这个问题不大但是也不小,因为前期不做统一处理的话,后面会存在不同浏览器之间的兼容问题,所以前期就要统一下关于时间问题的传值与返回值的格式问题,建议统一用时间戳。因为这次就踩坑了,一开始没有考虑到这个问题,就自己强行用sql转成前端想要的格式然后用字符串返回,后面就出现了用Safari浏览器回显和传值不兼容的问题。

3.前后端权限问题

关于用户角色权限这部分,相信很多公司都已经有自己的一套体系框架了,不会经常去写这部分的功能。但是这次正好是全部重写,所以简单记录下。

pc端的就不说了,很简单,用户角色权限还有两个中间表。至于怎么实现用户的操作权限问题,可以去看下这篇文章:在spring boot中使用shiro进行简单的权限拦截。还有数据权限的问题,这个也很简单,就是把当前用户拥有的权限数据查询出来再作为条件去查询相应的业务数据。

移动端也可能会存在狠多权限问题,而且移动端的权限问题比较杂乱无章,举个例子,比如一个部门下面有活动,活动里面可以报名,也可以评论,或者上传图片等等。而每一个操作都可能对应操作权限。移动端这个权限跟后端的唯一区别就是功能菜单不固定,而且移动端没有角色管理,用户的角色可能由自己来决定(用户不加入部门就是路人,加入了部门以后就是成员,此时角色改变,拥有的权限也就不同),说了这么多废话,其实就是想说假如需求不像pc那么固定的话,我们无法使用或者不方便使用工具统一处理的话,可以自己封装一个工具类。之前也简单了解过8421法,由于不适用该项目,然后就自己针对项目功能模块以及所有涉及到的操作权限问题,进行了简单的封装。思路如下:(1)对功能a进行判断,然后获取能够操作a的所有角色列表。(2)获取当前用户的角色。(3)然后让1和2进行取交集运行,有返回结果则表明该用户有权限操作该功能。 这样可能比较烦,但是方便需求的变更及扩展,而且与业务代码完全分离。附上一些代码:

​
public R checkPremessionAlumni(Integer alumniId, String privilege) {
        //根据操作权限拿到所有合适的角色列表
        List roleList1 = queryRolesByAlumniIdAndPermission(alumniId, privilege);
        //拿到当前用户的角色
        List roleList2 = queryRolesByAlumniIdAndFansId(alumniId);
        //开始比对:方法如下
        return compare(roleList1, roleList2);
    }

/**
     * 比对两个列表 判断粉丝是否有指定角色列表中的权限操作
     * @param roleList1
     * @param roleList2
     * @return
     */
    private R compare(List roleList1, List roleList2) {

        if (Utils.isAnyEmpty(roleList1, roleList2)) {
            return R.Error(M.ERR_DATA);
        }

        //需要的角色身份
        Integer needIdentity = roleList1.get(0);
        roleList1.retainAll(roleList2);
        if (roleList1.size() > 0) {
            return R.Success(M.SUCCESS);
        } else {
            //走到这里说明没用交集
            
            if (needIdentity.equals(Constants.IDENTITY_MEMBER)) {
                R r = new R(-2, "您不是成员,请加入!");
                return r;
            }
            if (needIdentity.equals(Constants.IDENTITY_SCHOOLMATE)) {
                R r = new R(-3, "您未认证,请认证!");
                return r;
            }
            return R.Error("没有权限,操作失败!");
        }
    }


​

4.日志及消息队列问题

日志平常就分为操作日志(需要记录入库的),还有错误日志,关于错误日志怎么排查以及在什么地方加这种日志比较合适,说实话我也很蒙蔽,每次排查错误就基本靠猜了,实在不行才逐行打印排查,这个问题可能是因为我觉得比较烦把,所以还不太适应,以后有必要注意下这个问题。关于消息队列的问题,其实项目中本来想用来玩玩的,后来由于服务器原因没有搭环境就放弃了,但是这种异步的思想还是很好用的,而且与业务分离,还可以提高性能。所以不一定要用队列,可以使用观察者或者监听器等等来实现同样的效果。关于不同类型的操作日志也可以封装一些工具类,用起来比较爽,但是不爽的就是封装的工具代码可能稍微烦一点了。

5.常用方法封装问题

假如一个项目从头到尾都你一个人或者两个人开发的话,你会发现有很多功能是可以复用的,假如多人协同开发,存在重复代码可以理解。但是全程只有一两个人开发的话,我觉得方法的提取就非常必要了,要完全杜绝重复代码。

所以关于方法的封装有个小建议:假如是全局的与业务无关的功能,可以放到common里面,使用统一的工具类来封装。比如日期,对象的判断等等。假如是业务功能的方法,可以根据功能模块来划分。我觉得不用担心工具类太多而把所有的方法都写到一起,这样反而不太好找。

6.多人配合 相似或者重复方法问题

至于这个问题,我是被困扰了很久,因为我们是两个人写的后端。代码快写完了才发现我们俩写了很多的重复代码。而且我自己写的代码都有可能重复,更别说两个人甚至更多人了,因为我没有在大公司呆过太久,所以对于平时的编码规范和意识都不是很好。所以对于这种问题,我还没想出有什么好的解决方法,估计只有规范的文档和代码注释了。。。所以合适的文档还是很重要的感觉。

7.包的划分问题

这个问题看似不大,但是前期要是没有合理的规划和预期,后面挪代码还是很烦的。所以只要前期做个合理的规划,怎么分包,问题应该不会太大,但是也不能忽略这个问题。

8.缓存使用问题

只能说缓存是个好东西,但是如何用好缓存,其实网上有很多大神的文章可以看看,这里就不敢多说了,毕竟自己也不熟悉。只想说在更新数据的时候,不要忘记更新缓存就好了。还有一个小问题就是,有时候要注意缓存对象和库中的使用,因为缓存里面的对象可能不是最新的而导致NPE问题。

9.表中冗余字段问题

关于表中冗余字段的问题,其实还是要根据实际情况来定。对于一些数量的统计,我觉得是可以用冗余字段来做的,只要在增删改的时候去动态刷新一下就好。还有一种是名称的使用,对于名称经常变化的我觉得还是不要用了。

10.测试流程

一开始觉得测试很烦,要考虑到各种情况,所以大部分程序员写完的代码估计就跑一遍就完事了。导致后面又被别人测出很多意想不到的问题。其实只要在写完代码的时候能够把自己考虑的情况都测一遍,然后再考虑到相关联的数据变化情况,问题基本不大,除非是自己的业务逻辑没考虑到位。建议在写代码的时候,也就是趁自己思路最清晰的时候最好能顺便写个简单的测试用例或者测试流程。

11.接口文档及前后端沟通问题

关于接口文档,我不知道别人都是怎么玩的,我在网上也找了很多第三方工具,功能很实用,可以放在云端,也可以在本地使用。我这里就是自己写了两个简单的页面(列表和查询),方便自己和前端使用,可以实时修改。

由于接口文档都是后端来定,所以不仅要考虑到后端功能的可行性,对于复杂点的功能还要考虑到前端是否能够实现,不能只考虑后端。所以对于这种情况,最好不要擅自决定,在跟前端确认无误后然后各自开发。

12.代码生成工具

网上有很多这类的工具,但是有的并不使用,建议自己能够改善或者写一套属于自己的工具,生成适合自己的代码,这样开发起来真的很爽。磨刀不误砍柴工嘛,深有体会。

13.全局相关

在整个项目中,关于错误提示,或者成功提示,包括前端的一些弹出框,或者提示页面等等,文字大小,消息提醒等等这些问题。看似是小问题,但是假如能在项目初期就考虑进去,实现全局统一,后面真的会带来不一样的效果。也许很多公司都已经有了自己的规范,不会出现这种低级问题。但是我们还真的没有,这个坑还比较严重,所以先记录下。

14.线程同步问题

这个问题很多人在写业务代码时很容易忽略,而且一般情况下测不出来,所以这个坑经历了好几次。需求是这样,在提交一个复杂表单的时候涉及到多张表,因此做了异步操作。所有的子表都与主表关联,在所有子表入库完成后再完成主表的入库。但是由于没有对主表进行同步操作,还是画个草图吧:

java项目小结_第1张图片

其实上面这个图跟同步并无多大关联,但是我新增数据前主表的id是先确定的,所以假如不对主表进行线程同步,就会出现重复主键异常。貌似废话说的比较多,就是想提醒下自己需要有这种线程同步的意识。

代码优化相关:

1.方法复用问题

2.冗长方法拆分、业务功能可使用异步解决

3.全局变量使用、枚举类,静态内部类   去除魔法值

4.过长参数列表  Pojo类封装

5.异常和日志的合理使用

6.开关控制(对于一个功能存在多个开关的话,最好拆分成多个,然后组合使用,其实就是代码复用问题)

结束语:

现在能想到的就是这么多了,可能内容比较简单没有深度,写的也比较繁琐,没有给出相关的代码案例 emmmm。。。其实目的很简单,就是想经过这次的总结,然后能对比半年后或者一年以后的想法,在对写码和工作上的一个认知的变化。也许现在还比较菜,不过都无所谓了,能够看到自己的变化,也希望给别人带来哪怕一点点的帮助算是没有白写了。。。

 

 

 

 

 

 

 

 

你可能感兴趣的:(个人总结)