心得总结随笔
其实现在干了这么久,觉得所有的互联网公司及工程项目,无非就是处理流和查询流,也就是说,要么是花式的数据处理,要么是花式的数据查询。在为了实现这些需求的时候,有很多时候会采取一些辅助性的手段,比如消息队列、分布式、相应的数据库等。
话又说回来,有时候会在想,要是去做游戏,又会有什么不同的呢?本来以为会有所不同的,其实仔细想想,游戏主要是人机交互,无非还是有一整套的数据处理流,再就是非常独立的一系列的计算处理功能的有序结合。
感觉无论是互联网公司还是游戏公司,其实做出来的产品都是实现了一定的功能,能给使用者带来一定的帮助或功效。
而作为开发者,就是为了更好地实现这些功能。作为产品分析人员,就是要更好地挖掘用户的需求,设计出更符合用户需求的产品、功能。
作为一个java开发的角度,最常见的就是查询流,因为java确实能非常快速地构建一套web应用体系。其次就是处理流,对进来的数据进行处理,然后再输出出去。
不过话又说回来,这不就是计算机能做的事情嘛,输入、运算、输出。所谓的编码,其实顾名思义就是对代码的编排,而被编排的每一条代码都完成了对应粒度的原子性的功能。基于这个观点,汇编语言的每一条代码都是cpu指令粒度的代码编排,C/C++应该就是C语义对应的汇编指令组的粒度的代码编排,JAVA应该就是java虚拟机指令集粒度的代码编排。
那既然是对指令代码的编排,就好比编剧对剧情桥段的编排。编排得当,情节自然且紧凑,甚至还会有意想不到的情节或者神转折。编排不妥,有些情节就莫名其妙非常突兀,有的又臭又长甚至剧情无法自圆其说。
所以编码应该是一样的道理,起承转合,提纲挈领,写出来的代码犹如文章,犹如诗歌。但cpu按照顺序执行代码指令,但难以直接反映代码执行到哪一步,而为了能直接反映代码的进度,我们一般使用日志来进行记录和反映。
于是,从某个角度来讲,代码写得好不好,一方面是代码实现的合理与紧凑,是否实现的每一步都是最必要的,是否能覆盖所有的功能场景;另一方面,应该就是你日志记录得是否合适,比如日志等级是否恰当,该info的就别debug;比如日志结构是否恰当以便于追踪各个功能流程或便于日志监控、日志统计;比如日志内容是否恰当,是否便于形成上下文以快速清晰准确定位功能的进度或恰当地反映执行的结果。
但是代码写得好只是一方面,需求设计得好又是一方面。当你写代码的时候发现需求不合理,还能帮助改进改善的时候,说明你已经开始从一个产品的角度来考虑问题了。IT这个行业有很多岗位,作为一个IT从业者对自己该如何定位会比较好呢?如果只是一个程序员,只是一个功能实现者,或许这条路的高处也就是一个熟练工了吧?如果不只是一个程序员,而是一个程序设计者,或许这条路的高处也就是一个架构师了吧?如果不只是一个程序设计者,那还会有一个怎样的职责定位呢?是战术性的角色还是战略性的角色?
我很多时候总想写点什么厉害的东西,但是什么是厉害的东西呢?现在总觉得自己写的东西不厉害,似乎自己写不出来的东西就厉害。有些时候我觉得能写现行的微服务架构就很厉害,有些时候我觉得能写一些牛逼的算法就很厉害,还有一些时候我觉得能写出动态画面很牛逼。虽然总是告诉自己,这些代码不过就是对CPU的那些指令集的有序调用,但是这些有序的最终结果确实看起来很棒呀。
所以经过一段时间思考之后,我似乎明白了这样一个道理,没有最强的代码,只有更强的程序员。有时候返璞归真、大巧不工中往往蕴藏着真正的灵性。其实业务逻辑的复杂度总归是有一个尽头的,那么最后总是能通过有限的简单的代码来完成相应的逻辑功能。甚至如果从汇编的角度来考虑,其可用的代码无非就那么多种,一样地最后能写出厉害的有用的工程。
那么,问题的核心显而易见了,如何才能聚沙成塔,然后再树塔成林呢?沙粒散乱,如何才能凝聚成塔?沙塔林立,如何遥相呼应呢?我认为这个凝聚力的一个重要因素就是一个良好的习惯,良好的代码习惯,一个合情合理的、可延续可扩展的代码约规——其实说到底,就是规范。
java有java的代码规范,汇编、C、Python也各有各的规范。对于规范、约规,很多时候当约定优先于配置的时候,能给大家带来很多方便——当然,也屏蔽了很多内容。不过总的来说,遵守规范能更好地进行合作开发,能减少错误的产生。但是当很多人在遵守规范的时候,突然有人不遵守规范了,就很容易酿成灾难。
除了合情合理大家公认的规范,聚沙成塔还需要一个好的架构体系,要不然就会一推就倒。话又说回来,你不管写什么代码,都需要一个架构,代码层级就是代码的结构,工程层级就是工程的结构,这些结构大概应该也许就是架构了吧。以写文章来比对写代码,写文章也是有行文结构的,行文紧凑流畅,叙述清晰准确,这样的文章才能准确地表词达意。而怎样的代码结构才是合理的,就需要根据相应的具体的业务逻辑来决定了——但总的来说还是要高内聚低耦合等等一系列的工程结构设计原则。
当这些都准备得差不多的时候,就该考虑一下对应的细节问题了。很多时候都是说细节决定成败。很多时候就是一个if判断条件写得不对导致分支进不去,根本就没有进行相应的业务处理最后惶惶恐恐。这个时候你说写注释吧,万一你实现的逻辑和你注释的逻辑对不上,然后每次review的时候都只看了注释,就把代码逻辑给忽略过去了;你说不写注释吧,万一你的这个判断条件的逻辑很复杂,一口气读不出来也容易出错。所以,没那么多万一,认认真真,养成良好习惯,该写注释写注释,该进行单元测试就把每一个分支都测试到。
说到单元测试,从最低层次来讲是验证自己写的代码是否实现了相应的功能,从高层次来讲是对每一次代码变更的稳定性的检验保障。单元测试对于代码开发来讲是非常有用的,那么如何进行有效地单元测试以更好地保证代码质量是我们最关心的,比如对于某些测试场景,我门可以通过mock的方式来进行有效地模拟测试。
往往很多人喜欢直接写一个main方法来进行运行测试,因为java代码运行的入口就是main方法,但是我个人还是更喜欢用单元测试来进行,因为一个Java类只能有一个main方法,但是可以有多个单元测试的case,不过如果使用main方法就可以不用依赖junit这个包,然而现在IDE都集成了junit,一般构建工程的时候也已经要么是maven要么是gradle了,对于依赖的处理也都是很便捷的。
说到maven和gradle就是要好好考虑工程体系的问题。如果说一个功能只是“一个”文件,然后在对应的环境上运行,我个人是更倾向于称之为脚本,例如sehll脚本就是一个文件,很少有写好几个shell脚本文件然后互相调用的——虽然shell也能很方便地实现这种将功能分散到各个文件中以复用的形式。Python也常常用来写脚本,perl也是地地道道的脚本解释器,称之为脚本主要还是因为往往就只有一个文件,然后实现的功能一般也是单而专,然后写很多个脚本,放在一起,需要用哪个功能就调用哪个功能。不过从单一职责原则来看,一个工程其实本身就是由很多个脚本组合起来形成一个功能完善的工程的。
计算机软件的目标应该就是通过计算机实现人的目标,给人提供便利的功能,那么软件工程我的理解就是一组软件的有序集合。那么如何组织这样一组软件能使得效率最高、使用的资源最合理,这就是工程需要关注的内容。在Java中,Spring就是一个开源的流行的工程构建框架。
有了工程,那么对应的就是发布和部署。程序员可不只是写代码,还要了解代码是运行在怎样的环境,需要进行哪些配置,怎么部署。这一块对应的就是版本控制、发布流程。
这些都是团队协作的内容,注重的合作与沟通,接口之间的调用、数据的传递应该怎样做是最合适的。除了团队协作的内容,我们也应该更多地考虑一下个人能力的方面——甚至说我们应该将主要关注点放在个人能力、个人风格上。
团队协作的本质还是一个一个人之间的共同工作,但在代码开发中的合作很容易出现两个人的开发效率明显低于一个人的开发效率的现象,其实这往往是心不齐或者说沟通阻碍导致的。很多时候,我希望我给个眼神,我的队友就能体会我的想法并将之实现,我也希望我的队友能言简意赅,往往一个想法只需要几个关键字我们就能达成共识。
这样就需要个人充分具备对业务的理解能力,需要个人具备足够的设计能力。写文章的时候我们常常会先写提纲,根据大纲来行文。编码其实也一样,我们在对业务功能、业务逻辑进行理解剖析之后,制定出相对合理的编码大纲后再开始进行编码。这个大纲怎么制定就体现了个人能力,有的人制定的大纲是合理且完备的,有的就不合理还丢三落四。虽然有时候我们照着大纲写也可能写漏了或者写错了,但是这个大纲也还是得有,特别是要合理。
对于业务的充分理解,就考察了个人对事物的剖析、抽象的能力。有些事情业务看似描述比较复杂,但是抽象下来其实也就那么几个步骤,但是有些业务的描述就一句话,但是拆分成具体步骤后却非常复杂,需要考虑非常多的具体情况。这不禁让我想起小时候我爷爷给我讲的一个故事,说有一户人家要卖房子,就要写房契,这个人就在数房子有多少块砖有多少方土地,就像资产盘点一样搞了三天都没弄完,于是买房的人等不及了,就找了个读书人来帮忙写,写的时候就写的是上至青天,下至地心,篱笆所围四方之内的东西悉数出售。所以这个例子就可以看出软件工程就得去数砖块去丈量土地,但是需求就只需要划定一个范围即可。
虽然我很注重个人能力,但毕竟个人能力是有限的,还是会需要别人来分担一些工作的。如果你这时候对整体流程没有一个整体概念的话,往往就会沟通得很难受,有时候就会觉得如果早知道你那边能那样,我这边也就不用这样了……也就是说,在一个个人能力都很优秀而且具有团队协作意识的团队中,那工作起来就很愉快,很多时候真的就是一个眼神就知道对方的意图,然后能迅速实现功能,而且还能互相review以保障质量。
代码review并不是说是你友情帮其他同事做的一个工作,而是分内的工作,review其他同事的代码是一个开发的本职工作。review主要是看有没有什么空指针的情况,有没有什么代码结构不合理的点,有没有什么明显的业务逻辑上的错误。但虽然是本职工作,但往往还是有很多人会草草了事,会觉得这个人写的代码一定没问题就不看了的这种情况。review代码往往在遇到业务逻辑部分的时候很少有人会继续深究吃透,因为很多人觉得自己不负责这一块的逻辑的实现就不去看不去理解不去设计,自然在review的时候就看不懂。我觉得作为一个心系项目的有担当的人就应该要去关注这些内容,不仅要做到,而且还要做好。
代码重构就是到了考验智慧和勇气的时候,这是对过去架构的否认,甚至是对过去的自己的否认,所以一定要想好,而且要紧跟项目的节奏。
我一直很想将项目重构成纯spring框架的项目,因为这样的工程结构虽然隐藏了很多细节,但是却让工程体系更加紧凑。当前的项目体系是通过一个容器工程来整合各个构件,通过在容器中增删对构件的依赖来控制工程的结构,这样的结构相对松散,构件的复用程度较高,容器工程的主体jar包大致相似,但是,这个项目对象的使用和依赖就全都是new出来的,这就让人感觉很low。毕竟spring的优势就是非侵入式的编程,不会过多地侵入已有的代码中,在配置文件中即可完成。那随之而来的疑问就是某些工程我只用到了某些构件的部分功能,如果不是spring装配的话我就有些构件就不用引入,因为那些没用到的功能的代码根本就不会走到,也就不会出现传递依赖的情况。其实后来想想,spring不也有条件装配的配置方式嘛,所以其实涵盖很广,需要的功能其实也都是能实现的。不过spring让整个项目成为了一个整体,如果spring初始化失败的话,整个项目也是不可用的,但是如果是构件化放入容器的这种形式就可以以部分功能不可用的状态成功启动,且仍有部分功能是可用的。
其实工程以残缺的状态启动成功那又如何?如果是为了达到应用快速启动的目的,那说到底启动是变快了,但是你提供服务的速度却没有变快,该加载的还是得加载完成了之后才能使用,所以我觉得快速启动和残缺状态启动根本毫无意义。
说到工程的构建,国内常用maven来构建java项目,常用gradle来构建Android项目。Gradle没流行起来的一个可能的原因是DSL这个领域专用语言可能没那么好理解吧?其实就相当于又学了一种语言,只是具有某些特定的语法规则和解释规则而已。但确实当你对这种语法熟悉之后,这写出来的代码读起来就像行云流水一般能比较好地描述问题描述要执行的动作。
有些人就觉得这些东西我不会也不影响我的工作,那我还要了解他干嘛。诚然,现在很多技术已经帮我们屏蔽了很多细节,我们不了解这些细节也不影响我们的工作,但是因为不了解也不影响工作所以我们就不去了解了吗?完成工作时本分,更好地完成工作是一种品格。既然参加了工作,那我们就应该具备这样的品格并展现这种品格。
学习能力我认为是IT这个行业的一个最重要的素质,要持续学习,快速学习,然后再深度学习。有些东西看起来是我们平时工作已经不用了,不过这些东西也分两类,一类是确实已经过时了不合适当前的环境,还有一类是虽然已经不用了但却是我们认识某些事物理论的必由之路。就比如我们在开发一个web应用时,我们现在常用Spring MVC的框架来进行开发,即使我们不知道Servlet、JSP技术我们也能很轻松地开发rest接口的服务。但是,这些都是Java的基础,这应该是每个JavaEE程序员必知必会的东西,你只有在理解了Servlet,理解了JSP之后才能更好地去理解Spring MVC的思想。
说到思想,我们在查问题的时候也应该要有查的思路,不能在遇到阻碍后就一脸懵逼了,要想办法去挣扎一下。查问题的时候,我们常常可能面临线索不足的情况,这个时候我们就类似于重案组办案,要想办法去搜集线索来破解这些无头悬案。我们的常规思路就是咀嚼现有的信息,挖掘每个信息的内在关联点,去深挖,然后再尝试。如果日志打印不出来,也不能就此放弃,想办法把环境拉取到本地,然后替换代码再复现一次。方式方法有很多,不是到了真正的山穷水尽的时候,就还再挣扎一下。
来源:CSDN
作者:x362829417
链接:https://blog.csdn.net/x362829417/article/details/79492841