2017/7/8 11:30:54
1.最近和同事排查BUG的时候想到这样一个问题,在开发时,懂前端又懂后端的人不多。业务API的良好设计,仍需要好好琢磨。比如某项业务,其数据完整性应该是AB两张表都进了数据,并且先进A再进B。同事在设计这个模块的时候,拆成两个接口,分别对应A表B表。这样会有风险出现,若A接口失败,必然会带来B接口失败。这项业务是需要完整性原子性的,要么都成功,要么都失败。拆分两接口的设计,容易导致数据不一致性。
2.我们项目有这么一个功能,前端IOS和服务器同步最新的学生数据,其设计方式是这样的:该同步接口有一个可选入参,为时间戳。一开始,IOS发起请求时不传时间戳,服务器返回所有学生,并扔一个当前时间戳给IOS。IOS记住这个时间戳,接下来在下次同步的时候,拿这个时间戳T给服务器,服务器里找到更新时间大于这个时间戳T的学生数据给IOS。如此往复。
这种方案漏洞在一些并发场景下极易报错,如用时间戳T请求学生数据的时候,另外有地儿并发插入学生数据,这个插入的学生数据,IOS可能拿不到。我现在也还没想到要如何改进,会更合适。你们工作中有遇到类似的场景吗,是如何处理的?
3.这周我在修改一个python脚本,该脚本末端调用了另外一个shell脚本。整套脚本都是从别的环境迁移到新环境,有一堆参数要改。shell脚本里的一些参数我老是忘记改。我调试的时候总是直接跑主python脚本,然后要等很长时间才能进到shell脚本部分。每改一个参数,就重新跑一次,浪费了很多时间!其实我直接改一下参数,直接调试被调用的这个shell就好了!!!!我也不知道我当时怎么那么犯晕!!平时写java的时候也知道若是整体main函数要跑很久才能走到被调用方,那一定要直接去先把被调函数调试好啊先!!!
2017/5/6 9:58:29
1.我的某个接口,该接口中有一个list,要求里边的对象里的一个string属性不能有重复,但前端同事这段时间每次改版调用后都会产生问题。而我的日志打印得不全,调用这个接口的json没打印出来。每次接到BUG报错我都战战兢兢地看是不是自己接口有问题,跟踪下去发现是前端调用的入参json有问题。现在想来,在前端同事多次调用都出现他们端的问题时,我应该加上日志记录,把list里的这个string打印出来,这样排查起问题就会方便很多。
2.用liquibase获取了一个数据库升级脚本,把这个脚本全部小写化了,未曾想到一些业务数值是要有大写的,结果产生bug。(其实当时我只是想把liquibase产生的datalog表小写化,因为我库里这个表是小写的,而liquibase产生出来的升级脚本是大写的)。另外我们这儿MYSQL数据库都是大小写不敏感的,不知道以后会不会有什么坑出现。
3.测试环境某项目的日志有两个,一个是mywar.log,一个是myWar.log,目前项目打包用的都是myWar,应看myWar.log才对,但早期打包的时候用的是mywar,那个mywar.log也一直没人给删掉。某次和前端联调的时候不小心看到了mywar.log,发现日志啥动静都没有,心里先入为主就认为人家前端没有发起调用操作。又一次被名字坑了浪费了时间。
2017/2/14 21:19:49
这阵子做这么个事情:把一个日志ZIP文件用python按需处理成几个独立的文件,导入到mongodb。做下来有以下几点收获:
1.之前未想到,用python处理文件耗时很长,处理过程中的临时文件,我都是放在同一个文件夹下。第1个日志还未处理完成,假如第2个处理日志请求也进来,会同时操作这个临时文件夹,带来并发操作上的不确定性。后来修改了脚本,将每个日志放在各自独立的文件夹下处理(文件夹为日志的文件名,文件名是UUID)
2.购买了主机的云mongodb服务,可能是选购了参数较小的,跑起来性能特别慢,170万条数据,之前用开发机自己搭的mongodb跑,只需要不到2分钟,这会儿居然要10分钟。后来就还是用自己搭建的mongodb。
3.在开发环境上搭建的mongodb是无密登陆的,用云mongodb的时候是要用户和密码的,在登陆认证的时候花了很多时间才找到解决方案(用超管账号新建操作账号,新建库,授权该操作账号对该库的读写权限)
4.其它收获是,这阵子这样工作状态有些辛苦,python和mongodb是现学现用,踩了不少坑.
2017/1/12 18:01:04
前端打包的时候连成开发同事的本地接口了。应该弄TEST环境的接口的。而我们后端还在一直查,为什么中间件里没日志,为什么登陆不上, 浏览器里F12一下就可以知道原因了,头昏眼花的时候就容易犯这些低级的错误。
2017/1/11 14:24:23
做分页功能的时候;
修改完LIST的,一定要记得把count的那一段也修改!!
2017/1/5 11:15:25
今天调试我自己写的一个过程的时候,花了很多时间;
后来发现是registration表改了,里边新增了participant_id字段 ;
2016/12/7 10:26:47
这周优化了一段代码。原来逻辑是这样子的:1编写模型、整理对应消息数据2找出订阅者3发出去。
后来想想,应该先改成1先找订阅者,这样更好,因为没有订阅者的话,根本就没必要组装模型。
这个道理有点类似于“首先~~~ 你要有一个女朋友 ”
2016/12
今天遇到一个BUG,前端的同事说返回给他们的模型里的LIST里的每个model的ID都没有了。
我跟踪代码后找到问题出在insertBatch批量插入。现用的mybatis仍不支持批量插入数据后返回批量ID。我在找到BUG点之后并不好下手修改,因为这块代码是A写的,并不知道会不会有其它影响,他又请假了。
待他来之后,他说这个BUG,我很早已经将批量插入改成了循环单插。看了文件版本发现之前的循环单插被同事B在修改其它BUG时顺手改成了批量插入(就是改自己的BUG,影响了别人的东西这么一回事)。然后我也瞅见这个版本历史上赫然写着A的改动记录。
也就是说我白改了这个BUG。我应该早点查看这个文件的近期版本变动。这样不会盲目修改。而mybatis返回批量插入的ID的解决方案,我并没有太大必要去死抠这个技术细节。以上是一个重要的经验与收获。
2016/11/1 15:17:01
/{param1}/{param2}
采用这种风格的话,param1里边不能有/字符
如果param1非得传/
只能改成?c1={param1}&c2={param2}
2016/10/8 16:55:51
(a+b+c)*d
better than a*d+b*d+c*d
201610总结
一、
同事A写了个接口T1,接着我写了个接口T2,T2包含一个返回字段C1在T1中存在,我之前没有接触C1有关的业务,不清楚这个字段经历哪些改动变化,与我配合的安卓前端同事,也不清楚这个字段,他只是告诉我,你造着T1的样子去开发,而负责C1有关业务的产品同事正好休假,我就没有再往上联系产品经理,就直接复制了同事A的部分代码。后来同事A接到C1的业务变动需求,他改了他的C1部分。
同事A不知道我开发的T2中引用了C1,他自然不会通知我进行相关修改,他也不会有时间来全盘检查还有哪里用到了C1。项目上线的时候,T1、T2对C1的业务展现就是不一样的了,造成了BUG。
你们工作中一定也遇到过类似的情况,你们又是如何有效合理地解决团队中的这些沟通漏洞?
二、
和两个同事做一个功能,我给A组同事提供POST接口以增加数据,给B同事提供GET接口返回数据,在部署测试环境时发生一些因沟通上造成的工作效率低下问题,回述如下:
1.我在开发环境建库的时候,建的数据库是share-center(这是一个不合规的名字,中间应用_不应用-)。我让运维的同事C帮我在测试数据库新建一个该库,他帮我建的是share_center。我在测试环境一调接口,页面上总是报access denied for user ***@127.0.01 to database share-center,而我思维定势认为是C没有帮我配127.0.0.1的用户权限(mysql中给某用户授某库的权限时,还分ip的)。然后C临时外出1小时。A找我要接口的时候,我说还得等C回来帮配个权限才可以。我给C截图发了我java代码中连接串配置属性,他也没有看到我的图片中用的是share-center,直到他亲自到我座位上对着电脑瞄了一眼,他说这里库写错了。
2.A组和B之间的沟通没有及时,A组一名同事休假,导致和B的对接出了些问题,迟迟没有确定最后的JSON数据格式。
3.A组同事在获取我的接口的时候一直没有正确处理好测试环境的连接串,用的还是开发环境的,而我在慌乱之中居然忘了这事情。
201609总结
一、
安卓组的A和我说要增加一个接口T1。我收到任务之后,去找A沟通。A不在位置,于是我找他同组的B,B翻出公司的WIKI说,你照着这个接口T2去开发,我们要的新接口T1和T2在模型上是几乎一样的。
于是我打开T2的文档,照着开发,开发得挺顺利的,因为照着T2的模型,我可捕获到的入参teamId(队ID)很便于我写SQL。
他们组的A同事调我的接口T1,说有数据,一切正常。我就放心回家了。
第二天,他们组的C同事调我的接口T1,说没数据,我开始DEBUG。
调试了很久发现,他们组在调我这个接口T1之前只能捕获到参数schoolId(学校ID),并以schoolId来向我要数据。可是我怎么就会以为他们能提供teamId呢!
我找WIKI,找开发T2的同事D了解情况,D说他的接口T2是提供给苹果组用的。于是我明白了,B当时是说错了,他应该是要我照着接口T3去开发的才对!因为T3和T2在文档上名字长得很像,B很有可能看走眼,告诉我错误的消息。
一翻折腾,重新编写调试。
这件事总结如下:
1.最好的还是一开始就找A沟通,因为他是任务发起方啊。
2.A说调接口的时候,我就该到系统里看一下他们的入参,而不是听凭他口头上说,就停止检查。在我们系统中schoolId是小于1000的id值,teamId通常是大于1000的,只需一看日志就能发觉异常。
3.因为我以为他们能提供teamId给我,所以我最先给他们的接口代码中,入参的命名也是teamId,A调接口的时候没有任何异议,C调接口的时候说怎么这里又多了一个teamId的东西,我们之前只拿到过schoolId啊!我个人觉得A看到入参是teamId时要有一定反应,之前都是好好的school字眼,为何突然多了一个team字眼。
4.同事D开发的T2接口、T3接口,在产品功能上是相似的,T2提供给苹果组,T3提供给安卓组。为什么同样功能的接口,提供给安卓、苹果,一个提供schoolId,一个提供teamId!虽然这两个字段都能二次入参进入到其它接口,实现其它功能的开发,但显然teamId比schoolId更便利。(业务上解释:一个学校会有多个队,如果要找某队队员,显然直接提供队名最便捷!)
二、
最近做的一个项目涉及参赛报名,报名需要填写参赛队员。我在设计时,报名填写的球员,就是关联的球员表。那就产生一个问题,如果报名之后,我把球员改名改成“张三”,报名信息那儿也会变成“张三”。当然,你说这是否符合常理,都各有道理。不过,我们产品经理的意思是,报名之后,报名信息就会锁定,不可能再更改,他当初报名参赛叫“张三”,这时即使修改球员个人资料,改成“李四”,但当初的报名信息也仍应叫“张三”。然后他告诉我PRD某某页有一行小小的字提到了这个事儿。
我只好给表增加冗余字段,冗余了报名时的报名资料。
这件事情总结如下:
1.在做一些如“人才成长库”、“人员管理”等这种涉及到“人员历史”、涉及到忆往昔如何如何、涉及到人员可能离职、调岗、转移到新组织这样的项目时,要多考虑考虑,要有项目的远瞻大局观,多和产品经理聊天,多了解项目未来还会做什么新功能,会做什么新子项目,要知道哪里要留一手不能写死。
2.对PRD上的很小很小的字都不要放过,以免日后扯皮。
三、
项目中涉及到一个业务数据的搜索功能出现了一个BUG,按日期范围,开始时间、结束时间为同一天,如2016年9月30号时查不到数据。DEBUG后发现,前端传给我的两个时间戳是一样的,是2016年9月30号的0点0分0秒的戳,我的SQL里是这么写的,match_date between begin_data and end_data,自然取不到数据。
在改这个BUG的时候我当时脑子里一时还没有反应过来。因为我第一家公司的证券项目几乎不涉及到时分秒,它都是日期between某天and某天,算某交易日的业务数据如何,那时的前端日期也是很简单粗暴地传一个20160930的数值型给后端(也没有传unix时间戳,不知道它那种技术细节是如何实现的)。
改这个BUG很简单,将入参的requestModel里的endData的set方法改成加上了23小时59分59秒的即可。
总结:
不应固守昨日的经验,用经验的同时也应尽量避免思维定势。
四、
项目投产了,线上有不少用户账号相同的问题,导致登陆失败。
账号的生成规则是"学校ID"+00+"该校已有的用户数"。
产品经理的设计是这样的:打开创建用户的页面,页面上方就给出了提前生成的账号和初始密码。
这有一个漏洞存在,假设这学校有两个用户都能创建新用户(在我们系统中创建新用户是由一个超管用户来操作的)。第一个用户打开网页,网页上分配的账号是008,先不提交创建。第二个用户打开网页,看到的分配账号必然也还是008!
而我们的新增用户接口中并没有判断账户是否已存在的这个check!
这块功能代码不是我开发的。当时我在翻PRD,我看到文档上这么说,我有怀疑过,也和某个同事说过我的疑虑,不过那时候开发任务太赶太着急,谁也无暇顾及。
现在想起来,我应该据理力争一下会更合适吧。
五、
和四类似的一件事情。查看某业务统计数据的一个小项目,数据来源于三个地方A、B、C。凭着以前的经验,我认为三方来源的数据,一但存在一方缺失的问题,会带来不少问题。因该统计功能大多业务字段来源于A,其他同事开始都用A为主表去left join B和C,若是A数据缺失,那这种写法会导致B、C的数据也不能返回给前端啊!于是我开会的时候我就说了,给我些时间,动工之前,我想先整表,整视图,但是没什么同事理会啊。
接下来我遇到了两件事情。
第一件,我说表A可以再冗余一些字段,会更便于咱们这个项目开发。表A是组A传给我们的,我说组A若能将他们之前获取到的某某字段再回传给我们,我们会省事很多,然后我就去找组A的组长说事,我说这样子做,我们会好查很多,性能会提高很多,对于整体来说也是最省事的办法。但显然,组长是有些不悦的吧,反复问了我好几次,大意就是恁什么要我这里多工作量,给你们提供这些多余的东西,你们自己不会在库里先查出来吗?
后来就有些尴尬了。A组大概是向上层反映这件事情,说我们随意改动,又无落地文字需求。我心里当时是想“我其实就是在求你顺手做个人情,传个东西给我,我这里好省事一些",当然了我没有从事过A组的工作,我想当然的认为,他那里额外传一个东西给我们不会费太多事情,比我们这里自己找值来的工作量小,并且对项目整体性能都更好。
第二件,表A的数据最源头是J组在做。我在项目上线一周前协助QA测试时,便发现不少数据异常问题,也整理了我的记录内容发给QA,我觉得QA会尽快和所有人知会这事情的,同时我也整理了记录发给了J组的同事,J组好像并没有太重视。过了几天我也忙着其它工作,我以为,我都反馈这事情给他们了,他们会解决吧,我只是个新人,和上面提了这事情就好了,我操什么心呢。后来出现的问题是,项目到deadline的时候,意识到不少数据都还有问题。
整个事情总结如下:
1.有时候说话太实诚了,我不应该和A组组长说,你们若传数据给我们,我们这里会更好查一些,你我他构建起来的整个大项目性能都会提升一点点。这是真话没错,但是人家一听你这知就知道了,一但这么做,会牺牲他们小团队的利益来提高大团队的利益。
2.我一开始就要早早把视图做好,给其它同事用的!我应该努力积极说服他们,应该建立有效积极的讨论,集思广益,我虽是做数据库开发出身,但也未必轻松想到某些视图如何编写,三表的全相联本就不好做,后来是灵机闪现,想到一个好idea才写出来。
3.在提出数据异常问题而别人没有重视的时候,我就应该要找我的组长反馈,让他来调度协调资源。有些东西,我一开始就要力争的。
2015年
年初的时候离开原公司,离开熟悉的数据库开发方向,回到厦门,做起Java程序员,希望在厦门重新开始,成长为一名合格的程序员。期间找工作经历了不少辛酸,最后来到**,经过近一年时间,收获了很多东西。
刚进公司那段时间,先熟悉公司框架。这些在之前做CRM项目时都接触过的组织、菜单、功能权限、数据权限等东西,上手起来并不麻烦。同事喜哥教我做单页面的增删改查,明细页面的查看、保存,父子表的页面设计,花了大概半个月,我能通过复制粘贴同事的代码做出一个像样的demo,对公司框架的分层也有了一些了解。而在之前的公司,我们用敏捷开发工具开发项目,并不需要掌握如hibernate、spring、mybatis等知识,只需熟悉业务之后,在后台写存储过程就能完成项目开发。未学习公司框架之前,我都不知道什么是低耦合高内聚,什么是面向接口编程,什么是设计模式,什么是分层。
记得刚用公司的框架时,自己经常因为配置层面的东西如XML没写好,jar包没导好等,花费很多时间。还好有热心的同事们带领我这个新手解决很多问题。
慢慢地开始看些技术视频,知道hibernate是数据持久层,知道javabean,知道如何在mybatis里写sql等等,只不过我了解的多是一些皮毛,对深层的原理是不清楚的。spring是对类(还是实例)的管理,控制反转(IoC)和面向切面(AOP)这些概念是什么,我至今也说不出个所以然来。
6月份开始对现场进行一些技术支持,一边测试框架、整理BUG,做出反馈。自己很喜欢改好BUG后的成就感,记得当时现场有一个用润乾报表开发遇到的BUG,大家都解决不了,后来我想应该可以联系润乾公司客服人员帮助解决BUG。果然,问题出在他们产品身上,BUG得以修复。
6月份后,Java后台并没有太多开发工作量,自己也苦于不知如何学习,每天下了班也是看着视频熟悉Java的一些东西,像泛型、IO操作、线程等这些曾自学过现已生疏的东西。自己业余也写了一些小DEMO,像定时器、抽奖器之类的,都是小打小闹,没有什么代码含量。那段时间自己特别迷茫。比如做解析XML文件、文件IO操作,可以用A公司的jar包,也可以用B公司的jar包,用A用B哪个更好,我不知道。我只会在网上复制代码,让我理解原理后纯手写一个解析XML的轮子,我恐怕很难做到。我感觉到Java的庞大,感觉到因自己技术的薄弱带来的迷茫,自己也没有较多的编码量,十分苦恼。
接下一段时间自己还学习过一阵子DB2、MYSQL,对比着ORACLE进行学习,十分有趣。也和同事“导师”交流技术、交流数据库,十分欣赏他的丰富经验和解决问题的角度、思路。
慢慢地时间到了下半年,进入到另外一个小组,参与旧代码的迁移工作,需要一些web前端的知识。这时候我才猛然醒悟,自己居然连html、css、jdbc、servlet、jsp这些很基础的知识都不具备。于是开始狂补知识,在这段时间,我知道了一定要讲究方法,快速学习。
参与旧代码迁移工作,是15年最完整的一块工作内容。了解了迁移规范,熟悉了大体控件,就开始迁移了。期间有很多琐碎的事情,比如新框架的不稳定性,浏览器兼容性问题,对业务的不熟悉带来的效率低下,还好,自己都一一克服了。迁移时也会参考别人的代码,甚至是成段成段的复制,再修改成自己的,这时就会感觉到规范、统一性是多么重要!有的同事代码风格良好,命名规整,复制过来时甚至全局替换成自己的变量名,就能完成迁移任务。自己在做这份工作的时候,也意识到自己有时候在工作模式上的一些不足,比如闷头做事缺少交流,不及时问同事导致时间的浪费。
时间过得很快,15年的收获简单讲述到这里,对于2016年,我的想法有:
1.自己要多写代码,写出好用易维护好扩展的代码。
2.要把手上的工作做好,配合好同事,向同事们多学习,学习良好的编码思想,优良的产品设计理念,好的做事风格。
3.在做好工作的同时,要加强自身能力建设,拥抱开源,多看别人的代码,有机会有能力有时间要参与到别人的轮子建设中。
4.学习的过程最好是结合工作,伴随着工作的使用进行深入学习,切忌盲目学习,切忌心浮气躁眼高手低,一定要专注一定要专注一定要专注。
5.同时要多了解业务,多了解烟草行业,了解金融行业,这样才能站在较商业的层面去理解产品,才能更好的与客户与同事交流。
6.数据库仍然是自己的强项,应不能放弃,要偶尔回顾,有机会可以多检查产品表情况,多熟悉公司产品表的设计风格、设计模式。
7.同时仍要加强自己的技术博客编写,坚持整理自己的工作经验文档、记录找BUG改BUG的思想,多写产品文档、技术文档,提高文字表述能力。抽出时间多和同事同行交流技术、分享经验。