国企“高级”程序员写的那些问题代码

前言

我是[提前退休的java猿],一名7年java开发经验的开发组长,分享工作中的各种问题!

👴我们公司都是只招 “高级java开发”,每个开发必须具备独立主导项目研发的能力,需要需求评审、技术调研、技术方案选型,开发工时评估。

😁今天就来看看我们写的代码都会犯些什么错,如果你是一名初中级开发,那么这篇文章请你一定看完。最后还对我们公司中、高级开发的能力做了主观的评价

“高级程序员”的代码

一、分布式锁运用

简单描述一下业务场景,就是活动报名。主要的逻辑就是判断用户是否报名,没有报名就插入报名记录,并且报名的剩余名额减一。

逻辑和秒杀的逻辑看起来还差不多呢😁,只是我们这个业务没有什么并发量。看以下代码吧,看看你能找出几个问题。

原代码

controller 层伪代码如下:

java

体验AI代码助手

代码解读

复制代码

public Response cancelActivityEnroll(@RequestBody Param req) { RLock lock = redissonClient.getLock(RedisKeyConstant.ACTIVITY_ENROLL_KEY + req.getActivityId()); try { lock.lock(); service.cancelActivityEnroll(req); return Response.ok(); } finally { lock.unlock(); } }

点评

  1. 建议直接锁用户吧,Key改成活动ID+userID,这样能提高并发,提升用户体验
  2. 不能立即获取到锁,直接返回
  3. 假设lock方法报错,没有获取锁,finally岂不是把其他请求的锁给解开了(当然RedissonLock解锁的时候会自动判断是否当前线程持有,其他实现的就要注意了)

java

体验AI代码助手

代码解读

复制代码

public void unlock() { try { get(unlockAsync(Thread.currentThread().getId())); } catch (RedisException e) { ........ }

service 层代码如下:

java

体验AI代码助手

代码解读

复制代码

@Transactional public Response activityEnroll(WorkersActivityEnrollCreateReq req) { LoginUser user = UserUtil.getUser(); Activity activity = service.getById(req.getActivityId()); //1.校验活动信息:是否有剩余报名名额,活动状态是否正常............................. Boolean checkRet = checkActivity(); if(!checkRet){ Response.error("活动已结束...."); } //2.查询用户是否存在报名信息,含HTTP请求 Boolean enroll = getUserEnroll(user.getId,req.getActivityId); if(enroll){ Response.error("已经报过名了....."); } //3.插入报名信息 baseMapper.insert(enrollEntity); //4.活动剩余名额 -1 service.lambdaUpdate().eq(Activity::getId, req.getActivityId()). set(Activity::getCouldEnrollNum, activity.getCouldEnrollNum() -1).update(); return Result.OK(); }

点评

  1. 事务的范围可以缩小,HTTP请求不要放到事务内
  2. 名额扣减得时候可以使用"update t set num =num-1 where id =? and num>1"形式防止名额报超(update by Id 行锁比分布式锁更加可靠)
优化后的代码

controller:锁用户,防止用户重复点击;锁优化防止极端情况解锁到其他线程的持有锁;

java

体验AI代码助手

代码解读

复制代码

// 1.调整为锁用户 RLock lock = redissonClient.getLock(RedisKeyConstant.ACTIVITY_ENROLL_KEY + req.getActivityId() + userID); try { //获取锁,设置释放锁时间; 或者不指定释放时间,启动看门狗机制(默认最长续期30s) Boolean lockRet = lock.tryLock(0,10, TimeUnit.SECONDS); // 获取成功,执行业务,失败则直接返回 return lockRet ? lbWorkersActivityEnrollService.activityEnroll(req) : Result.error("网络繁忙"); } catch (InterruptedException e) { log.error("lock fail",e); return Result.error("网络繁忙"); } finally { // 解锁的时候,判断是否是当前线程持有 if(lock.isHeldByCurrentThread()){ lock.unlock(); } }

service:缩小事务范围,用编程式事务或者把前置校验单独提出来,写到controller层。扣减优化,防止锁失效命令报超的情况。

java

体验AI代码助手

代码解读

复制代码

public Response activityEnroll(WorkersActivityEnrollCreateReq req) { LoginUser user = UserUtil.getUser(); //1.校验活动信息、用户信息:是否有剩余报名名额,活动状态是否正常............................. checkMethod() //2.校验成功、插入数据、名额扣减 //通过execute方法执行事务逻辑 transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try { baseMapper.insert(enrollEntity); // 调整更新语句SQL,防止名额报超:update t set num =num-1 where id =? and num>1 Boolean suc = service.updateNumById(); // 名额扣减失败 if(!suc){ thorw new RuntimeException("xxxx"); } } catch (Exception e) { // 手动标记事务回滚(可选,默认异常会触发回滚) status.setRollbackOnly(); throw new RuntimeException("报名失败", e); } } }); return Response.OK(); }

二、定时发送短信、语音...

简单描述一下业务场景,用户需要在后台可以批量选择用户,同时可以多选发送的方式比如 短信+语音。 然后设计的思路是,RabbitMQ延迟队列实现定时触发,策略模式来实现业务逻辑。 看一下代码吧,看看你能发现这些问题么

原代码

消费者

java

体验AI代码助手

代码解读

复制代码

@RabbitListener(queues = RabbitMqConstant.SMS_DELAY_QUEUE) public void doSmsTask(Message message, Channel channel ) { String id = new String(message.getBody()); //执行发送业务逻辑 service.actionSendTask(id); }

点评: 没有捕捉异常(没有绑定死信),没有做幂等;异常之后会出现重复消费消息

处理业务逻辑

java

体验AI代码助手

代码解读

复制代码

public void actionSendTask(Long id) { Task task = getById(id); //1.校验状态 checkTask(); //2.查询手机号 List<String> phones = queryPhones(); //3.获取任务发送的类型,根据类型执行对应的策略 String[] types = getTaskType().split(COMMA_EN); // 遍历任务 类型,根据类型执行对应的策略 for (String type : types) { // 注意这个地方 获取到策略类 之后,设置到context的属性上 strategyContext.setSmsStrategy(StgFactory.getStrategy(Integer.valueOf(type))); // 执行发送业务逻辑(底层封装http调用三方接口) smsStrategyContext.send(task, phones); } }

点评:

  1. 异常处理:for循环里面遍历策略,可能中途的某个策略会报错。要么做好异常捕捉处理,要么丢尽线程池执行
  2. 线程安全:这个把具体的策略实现 设置到smsStrategyContext的属性上存在线程安全问题。
    (比如我多个线程同时调用setSendSmsStrategy,执行完成之后多个线程 在调用send的时候,执行的策略就是最后生效的那一个了)

StrategyContext.java

java

体验AI代码助手

代码解读

复制代码

public class StrategyContext { private ISmsStrategy smsStrategy; public void setSmsStrategy(ISmsStrategy smsStrategy) { this.smsStrategy = smsStrategy; } /** * 发送信息 * * @param task * @param phones */ public Boolean send(Task task, List<String> phones) { //发送 短信、语音......... smsStrategy.sendSms(task,phones); //后置处理 smsStrategy.sendAfterHandle(task); return true; } ........................................ }

线程安全问题如下图:

📕上面这块代码确实问题也挺多的,结合实际业务场景,按照严重级别排序的话,应该是线程安全<----异常处理<------消息幂等

优化后的代码

消息消费:除了以下的修改,还绑定了死信队列(出现了异常直接丢入到死信队列)。

java

体验AI代码助手

代码解读

复制代码

public void doSmsTask(Message message, Channel channel ) { String id = new String(message.getBody()); String redisKey = MESSAGE_PREFIX + messageId; // 检查Redis中是否存在该消息ID Boolean suc = redisTemplate.opsForValue().setIfAbsent(redisKey, "processed", EXPIRATION_TIME, TimeUnit.SECONDS); // 没有被消费过 if(suc){ service.actionSendTask(id); } }

处理业务逻辑: 存在多个策略,各策略之间的执行互不影响,且执行策略的方法为线程安全.同时处理异常情况

java

体验AI代码助手

代码解读

复制代码

public void actionSendTask(Long id) { Task task = getById(id); //1.校验状态 checkTask(); //2.查询手机号 List<String> phones = queryPhones(); //3.获取任务发送的类型,根据类型执行对应的策略 String[] types = getTaskType().split(COMMA_EN); // 遍历任务 类型,根据类型执行对应的策略 for (String type : types) { try { smsStrategyContext.sendByType(task, phones,type); } catch (Exception e) { log.error("策略异常:",e); } } }

StrategyContext.java: 调整成线程安全的类,加锁或者使用ThreadLocal进行策略接口的存储,下面就改成简单的方式把,用锁的方式

java

体验AI代码助手

代码解读

复制代码

public class StrategyContext { private ISmsStrategy smsStrategy; @Resouce private StgFactory stgFactory; private void setSmsStrategy(ISmsStrategy smsStrategy) { this.smsStrategy = smsStrategy; } /** * 发送信息: 加锁,设置策略,执行策略 * * @param task * @param phones */ public synchronized Boolean sendByType(Task task, List<String> phones,Integer type) throws Exception{ //设置策略 setSmsStrategy(StgFactory.getStrategy(type)); //发送 短信、语音......... smsStrategy.sendSms(task,phones); //后置处理 smsStrategy.sendAfterHandle(task); return true; } ........................................ }

三、一些细节和规范问题

多此一举的分布式锁

本身这个定时任务用的是Quartz定时任务,配置中也是开启了集群模式的,有些同事还是自己去实现了分布式锁,多此一举了哈🤪

java

体验AI代码助手

代码解读

复制代码

@Slf4j public class DeptSyncJob implements Job { @Resource private RedissonClient redissonClient; @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { RLock lock = redissonClient.getLock(RedisKeyConstant.DEPT_SYNC_JOB); if (lock.tryLock()) { ....................... } }

魔法变量、select*

数据量大的情况,mybatis plus 查询不指定查询字段,默认查询所有 还是比较吃性能。

java

体验AI代码助手

代码解读

复制代码

// 魔法变量 if (activity.getPushStatus()==1) {...} if(activity.getJoinCondition()==2){...} // mybatis plus 没有指定查询字段, 等同与 select * List<ActivityEnroll>activityEnrolls = this.lambdaQuery().eq(ActivityEnroll::getId, req.getId()) .eq(ActivityEnroll::getUserId, req.getUserId()) .eq(ActivityEnroll::getIsDel, false).list();

“高级程序员”和 “中级程序员”的区别

基于我司的情况说一下个人主观的感受吧,技术上表现最大的差别就是 设计思路 和 代码规范(可读性)上吧。综合能力上就是 工时的评估、风险的预判。
中级程序员:
经常设计的表有点死板了,不能很多的结合业务场景去设计表,经常会出现表设计冗余,思路有点绕。以及代码的可读性,可维护性确实还是有明显差别

  1. 明明一个表可以实现的,非得拆成多个,同时还喜欢在SQL放很多case when 等逻辑;
  2. 页面配置列表居然设计出来没有ID,编辑一行数据 需要把整个列表全部提交全部覆盖;
  3. 一个方法里面需要调用第三方的多个HTTP请求,异常也没处理,中间步骤第三方可能需要等待一段时间才会查询到结果,直接就对线程sleep一分钟🤪。 (请求多一点服务就炸,还会引起脏数据)

高级程序员:
说一下我们公司的“高级程序员”吧😁
他们参与整个项目的周期上,从需求评估——>工时评估——>设计、编码 这个过程没有啥大问题,都能独立的负责项目。

从技术上来说的话,基本的规范,代码的扩展性、可读性、表设计都没啥问题。但是在一些常用技术的原理理解上还是比较缺乏的。

  1. 比如上面说的分布式锁的运用,到底是锁库存还是锁用户。不会利用数据锁,去实现超卖问题
  2. 解决问题的能很多还是停留在search阶段,有明显的报错的,但是网上没有解决方案的,就不知道通过debug源码的方式去解决
  3. 比如 一个left join 查询缓慢,但是数据都不多,不知道去分析执行计划,不了解left join 的底层算法

🤞当然,技术的知识点很多,有些不知道 不了解的很正常。但是常用技术原理上,以及解决疑难杂症问题的能力还有待提高。我们公司优秀的高级开发也有,编码速度非常快、bug还很少、代码也非常的规范(还是名校🙈)

总结

分享了最近公司同事,出现的一些典型的代码问题。同时在文章末尾也对身边的高级开发 和 中级开发的能力做了一个主观的评价。希望这篇文章能帮到你,感谢点赞评论的朋友!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1150356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FramePack智能视频创作:从静态图像到动态动画的完整工作流

FramePack智能视频创作&#xff1a;从静态图像到动态动画的完整工作流 【免费下载链接】FramePack 高效压缩打包视频帧的工具&#xff0c;优化存储与传输效率 项目地址: https://gitcode.com/gh_mirrors/fr/FramePack 想要将普通照片变成生动的视频内容吗&#xff1f;Fr…

XGBoost完整安装配置指南:从入门到精通

XGBoost完整安装配置指南&#xff1a;从入门到精通 【免费下载链接】xgboost dmlc/xgboost: 是一个高效的的机器学习算法库&#xff0c;基于 C 开发&#xff0c;提供用于提升分类、回归、排序等任务的性能。 项目地址: https://gitcode.com/gh_mirrors/xg/xgboost XGBoo…

【Windows 文件系统管理工具】实用工具之XYplorer 完全指南:专业级文件系统管理的终极解决方案

前言&#xff1a; 在信息爆炸的数字化工作时代&#xff0c;高效、智能的文件管理已成为提升工作效率的核心竞争力。传统的 Windows 资源管理器虽然满足了基础需求&#xff0c;但在面对复杂的文件操作、多项目并行管理和高级搜索场景时&#xff0c;其功能局限日益凸显。今天为您…

计算机深度学习毕设实战-基于python-CNN卷积神经网络对猫是否疲劳识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

番茄小说下载器:打造离线阅读的终极解决方案

番茄小说下载器&#xff1a;打造离线阅读的终极解决方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为网络信号不稳定而无法畅读小说烦恼吗&#xff1f;番茄小说下载器…

Scarab空洞骑士模组管理器:5分钟快速上手指南

Scarab空洞骑士模组管理器&#xff1a;5分钟快速上手指南 【免费下载链接】Scarab An installer for Hollow Knight mods written in Avalonia. 项目地址: https://gitcode.com/gh_mirrors/sc/Scarab 还在为空洞骑士模组安装的繁琐流程而头疼吗&#xff1f;Scarab空洞骑…

深度学习毕设选题推荐:基于python-CNN卷积神经网络对猫是否疲劳识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

番茄小说下载器:3步搞定离线阅读的终极方案

番茄小说下载器&#xff1a;3步搞定离线阅读的终极方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为网络信号不好而错过精彩小说情节烦恼吗&#xff1f;番茄小说下载…

【计算机毕业设计案例】基于python-CNN卷积神经网络对猫是否疲劳识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

番茄小说下载器:简单三步打造离线图书馆的终极方案

番茄小说下载器&#xff1a;简单三步打造离线图书馆的终极方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 还在为网络不稳定错过精彩小说情节而懊恼吗&#xff1f;番茄小说…

Zoplicate插件完整指南:彻底告别Zotero重复条目困扰

Zoplicate插件完整指南&#xff1a;彻底告别Zotero重复条目困扰 【免费下载链接】zoplicate A plugin that does one thing only: Detect and manage duplicate items in Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zoplicate 作为一名Zotero用户&#xff0c…

深度学习计算机毕设之基于python-CNN卷积神经网络对猫是否疲劳识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

深度学习毕设选题推荐:基于python-CNN卷积神经网络的鱼类识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Windows系统瘦身终极指南:告别卡顿与臃肿

Windows系统瘦身终极指南&#xff1a;告别卡顿与臃肿 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更改以简化和改善你的Windo…

深度学习计算机毕设之基于python-深度学习的混凝土马路和泥地马路识别

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围::小程序、SpringBoot、SSM、JSP、Vue、PHP、Java、pyth…

Infinigen完全指南:从零开始构建程序化虚拟世界

Infinigen完全指南&#xff1a;从零开始构建程序化虚拟世界 【免费下载链接】infinigen Infinite Photorealistic Worlds using Procedural Generation 项目地址: https://gitcode.com/gh_mirrors/in/infinigen 想要探索程序化生成的无限可能吗&#xff1f;Infinigen这个…

彼得林奇对公司研发效率与专利质量关系的分析

彼得林奇对公司研发效率与专利质量关系的分析 关键词:彼得林奇、研发效率、专利质量、公司分析、投资决策 摘要:本文深入探讨了彼得林奇对于公司研发效率与专利质量关系的分析。彼得林奇作为投资界的传奇人物,其投资理念对分析公司价值有着重要指导意义。通过研究公司研发效…

Win11Debloat:一键清理Windows冗余,让你的电脑重获新生

Win11Debloat&#xff1a;一键清理Windows冗余&#xff0c;让你的电脑重获新生 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更…

【课程设计/毕业设计】基于python-CNN卷积神经网络对猫是否疲劳识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【无人机追踪】联盟组建 + 精准 Dubins 曲线能耗计算 + 多无人机协同作战附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…