当前位置: 首页 > Web前端 > HTML

码农如何提升品味

时间:2023-03-29 11:00:46 HTML

作者:京东科技文涛农民伯伯赚的血汗钱),其次自嘲这个行业真辛苦,没时间收拾,即使没有驼背脱发的加持。但是时间长了,外人真的认为程序员就是一群鸡肋、沉闷的下流货,大部分的文学作品也是这样表现程序员的。但是今天我想说说我的感受,编程是一门艺术,程序员是最聪明的一群人,我们的品味也可以像艺术家一样。言归正传,你觉得我今天要教你怎么穿吗?不不不,这还是一篇技术文章。想学穿衣打扮,女人可以跟陈淑婷(《狂飙》里的小姑子)学,男人找个陈淑婷这样的女朋友就好了。笔者今天教大家如何写出有“味道”的代码。以下几点可以提高“品味”的解释:以下是笔者的体验,部分主观。如果您不同意,欢迎您发表评论。如果你想系统地提高你的编码技能,推荐阅读《XX公司Java编码规范》、《Effective Java》、《代码整洁之道》。下面几点有的是通用的,有的是限于java语言,其他语言的同学可以绕过。优雅反重作者打算写一篇系统的反重讲解。今天只讲一个优雅的方式:如果你的业务场景满足以下两种情况:1.业务接口重复调用的概率不是很高2输入参数有明确的业务主键如:订单ID,商品ID、文章ID、运单ID等。在这种场景下,非常适合做乐观防复制。思路是代码处理不会主动做防重复,只有在检测到重复提交后才做相应的处理。如何监控重复提交?MySQL唯一索引+org.springframework.dao.DuplicateKeyException代码如下:publicintcreateContent(ContentOverviewEntitycontentEntity){}catch(DuplicateKeyExceptiondke){log.warn(":repeat}"content,contentEntity.toString());}return0;}善用lambda表达式Lambda表达式已经是一个常见的话题。笔者认为,初级程序员晋级中级的唯一途径就是攻克lambda表达式。Lambda表达式和面向对象编程是两个编程概念。《架构整洁之道》中提到了三种编程范式,结构化编程(面向过程编程)、面向对象编程和函数式编程。第一次接触lambda表达式,肯定特别难受,但是熟悉了之后,你会打开一种新的编程思维。本文不讲lambda,只讲下面的例子:比如你想对一个二维表数据进行分组,可以用下面这行代码实现ListactAggs=....Map>collect=actAggs.stream().collect(Collectors.groupingBy(ActionAggregation::containWoNosStr,LinkedHashMap::new,Collectors.toList()));这个建议基本都包含在各大领域的JAVA编程规范中,但是我在看过的代码中,并没有很好的使用。guard语句对于提高代码的可维护性有很大的作用。想象一下,在一个10层if缩进的界面中找到代码逻辑是多么痛苦。有人说,怎么会有10层压痕呢?更何况,作者竟然在一个微服务的核心接口中看到了这样的代码。这个接口被太多人接管了,才导致了这样的情况。.系统接管太多人后,代码腐败的速度超乎你的想象。下面是一个例子:没有guard语句的代码,多级缩进if(title.equals(newTitle)){if(...){if(...){if(...){}}else{}}else{}}代码使用守卫,减少缩进{returnzzz;}避免双循环简单来说,双循环会将代码逻辑的时间复杂度扩大到O(n^2)。如果有两个list通过key匹配的场景,推荐以下方法:1将MapList12LoopList2从map中获取值代码示例如下:ListallPre=...Listchains=...MappreMap=allPre.stream().collect(Collectors.toMap(WorkOrderChain::getWoNext,item->item,(v1,v2)->v1));chains.forEach(item->{WorkOrderChainpreWo=preMap.get(item.getWoNo());if(preWo!=null){item.setIsHead(1);}else{item.setIsHead(0);}});使用@see@link设计RPC的API程序员经常自嘲。:API工程师,中间件装配师等由于我们平时会写很多API,所以会写到极致@see@link功能是让用户方便的链接到枚举类型的对象,方便阅读的例子如下如下:@Data@Builder@NoArgsConstructor@AllArgsConstructorpublicclassContentProcessDtoimplementsSerializable{/***内容ID*/privateStringcontentId;/***@seecom.jd.jr.community.common.enums.ContentTypeEnum*/privateIntegercontentType;/***@seecom.jd.jr.community.common.enums.ContentQualityGradeEnum*/privateIntegerqualityGrade;}日志打印避免只打印整个参数。为了省事,输入参数往往是这样打印的log.info("operateRelationParam:{}",JSONObject.toJSONString(request));日志进入日志系统后,查找日志时根据业务主键很难排查问题。如果改进为下面的方法,可以方便的查找日志。log.info("operateRelationParam,id:{},req:{}",request.getId(),JSONObject.toJSONString(request));如上:只需要匹配“operateRelationParam,id:111”全字,就可以找到业务主键111的业务日志,使用异常捕获AlternativeMethodParameterPassing我们经常遇到的一种情况是:从中获取返回值一个确定程序下一步方向的子方法,我认为这不够优雅。例子:下面代码paramCheck和deleteContent方法返回这两个方法的执行结果,调用者判断程序是否要publicRpcResultdeleteContent(ContentOptDtocontentOptDto){log.info("deleteContentParam:{}",contentOptDto.toString());try{RpcResultparamCheckRet=this.paramCheck(contentOptDto);if(paramCheckRet.isSgmFail()){returnRpcResult.getSgmFail("非法参数:"+paramCheckRet.getMsg());}ContentOverviewEntitycontentEntity=DozerMapperUtil.map(contentOptDto,ContentOverviewEntity.class);RpcResultdelRet=contentEventHandleAbility.deleteContent(contentEntity);if(delRet.isSgmFail()){returnRpcResult.getSgmFail("业务处理异常:M+delsRet());}}catch(Exceptione){log.error("deleteContent异常:",e);returnRpcResult.getSgmFail("内部处理错误");}returnRpcResult.getSgmSuccess();}我们可以通过self定义异常的方式解决:子方法抛出不同的异常,调用者捕获不同的异常用于不同的逻辑处理,让调用者特别清爽,不需要判断返回结果。代码示例如下:尝试{this.paramCheck(contentOptDto);ContentOverviewEntitycontentEntity=DozerMapperUtil.map(contentOptDto,ContentOverviewEntity.class);contentEventHandleAbility.deleteContent(contentEntity);pe.getMessage(),pe);returnRpcResult.getSgmFail("非法参数:"+pe.getMessage());}catch(BusinessExceptionbe){log.error("deleteContentBusinesserror:"+be.getMessage(),be);returnRpcResult.getSgmFail("业务处理异常:"+be.getMessage());}catch(Exceptione){log.error("deleteContent异常:",e);returnRpcResult.getSgmFail("内部处理错误");}返回RpcResult.getSgmSuccess();}自定义SpringBoot的Banner不要让你的SpringBoot启动banner是一样的。Spring支持自定义横幅。这个技能对于业务功能的实现没有什么用处,但是会给枯燥的编程生活增添一点乐趣。以下是官方文档的说明:https://docs.spring.io/spring-boot/docs/1.3.8.RELEASE/reference/htmlsingle/#boot-features-banner另外,你还需要一个ASCII艺术词生成工具:https://tools.kalvinbg.cn/txt/ascii效果如下:_____(_|_)_______||________||________||____|||'_\/_`|/_`|/_\|'_\/_`||'_\/_\/_\|__/__|||||||(_|||(_||(_)||||(_|||_)|(_)|(_)||_\__\_/|_|_||_|\__,|\__,_|\___/|_||_|\__,||_.__/\___/\___/\__|___/|__/|___/|___/多用途Java语法sugar编程语言中java的语法比较繁琐,用过golang或者scala的人感觉特别明显,java提供了10多种语法糖,在写代码的时候经常用到,给人一种“这位哥们用的java很好。例如:try-with-resource语法,当外部资源的handle对象实现了AutoCloseable接口时,JDK7可以使用try-with-resource语法更优雅的关闭资源,消除形式化代码。try(FileInputStreaminputStream=newFileInputStream(newFile("test"))){System.out.println(inputStream.read());}catch(IOExceptione){thrownewRuntimeException(e.getMessage(),e);}使用链式编程链式编程,又称级联编程,在调用对象的函数时,返回一个指向对象本身的this对象,达到链式效果,可以级联调用。链式编程的优点是:编程性强,可读性强,代码简洁。示例:如果觉得官方容器不够方便,可以自定义。代码如下,但建议使用开源且经过验证的类库如guava包中的工具类/**chainmap*/publicclassChainMap{privateMapinnerMap=newHashMap<>();publicVget(Kkey){returninnerMap.get(key);}publicChainMapchainPut(Kkey,Vvalue){innerMap.put(key,value);归还这个;}publicstaticvoidmain(String[]args){ChainMapchainMap=newChainMap<>();chainMap.chainPut("a","1").chainPut("b","2").chainPut("c","3");}}未完待续,欢迎评论区补充