腾讯大佬总结的代码重构原则,看完再也不怕面试官问啦!

四面腾讯pcg后端开发岗,一个星期面完成功拿到20K的offer。分享面经 前言 感觉运气爆棚了... 间隔不长一面面完第二天二面 然后隔了两天三面和HR面一起面的,总得来说面试体验很好,面试官经验也很丰富,偶尔答不上来的都会引导你往你知道的知识点上!顺利上岸拿到20K的offer,接下来请大家先看看我在面试腾讯PCG的时候,都问了那些面试题吧! 腾讯pcg后端一面 说说项目经历,印象最深的地方 项目重构了是吧,说说如何重构-一个项目? 重构项目如何处理与之间老接口的切换? 说说你的web框架,你如何实现- - -个get post的表单 如果多人访问一个写的接. 阅读详情

前言

上一篇开闭原则最有用的代码改动是基于 “修改” 的方式来实现新功能的。如果我们遵循开闭原则,也就是 “对扩展开放、对修改关闭”。那如何通过 “扩展” 的方式,来实现同样的功能呢?

重构

我们先重构一下之前的 Alert 代码,让它的扩展性更好一些。重构的内容主要包含两部分:

  1. 第一部分是将 check () 函数的多个入参封装成 ApiStatInfo 类;

  2. 第二部分是引入 handler 的概念,将 if 判断逻辑分散在各个 handler 中。

具体的代码实现如下所示:

public class Alert {

  private List<AlertHandler> alertHandlers = new ArrayList<>();



  public void addAlertHandler(AlertHandler alertHandler) {

    this.alertHandlers.add(alertHandler);

  }

  public void check(ApiStatInfo apiStatInfo) {

    for (AlertHandler handler : alertHandlers) {

      handler.check(apiStatInfo);

    }

  }

}

public class ApiStatInfo {// 省略 constructor/getter/setter 方法

  private String api;

  private long requestCount;

  private long errorCount;

  private long durationOfSeconds;

}

public abstract class AlertHandler {

  protected AlertRule rule;

  protected Notification notification;

  public AlertHandler(AlertRule rule, Notification notification) {

    this.rule = rule;

    this.notification = notification;

  }

  public abstract void check(ApiStatInfo apiStatInfo);

}

public class TpsAlertHandler extends AlertHandler {

  public TpsAlertHandler(AlertRule rule, Notification notification) {

    super(rule, notification);

  }

  @Override

  public void check(ApiStatInfo apiStatInfo) {

    long tps = apiStatInfo.getRequestCount()/ apiStatInfo.getDurationOfSeconds();

    if (tps > rule.getMatchedRule(apiStatInfo.getApi()).getMaxTps()) {

      notification.notify(NotificationEmergencyLevel.URGENCY, "...");

    }

  }

}

public class ErrorAlertHandler extends AlertHandler {

  public ErrorAlertHandler(AlertRule rule, Notification notification){

    super(rule, notification);

  }

  @Override

  public void check(ApiStatInfo apiStatInfo) {

    if (apiStatInfo.getErrorCount() > rule.getMatchedRule(apiStatInfo.getApi()).getMaxErrorCount()) {

      notification.notify(NotificationEmergencyLevel.SEVERE, "...");

    }

  }

}

上面的代码是对 Alert 的重构,我们再来看下,重构之后的 Alert 该如何使用呢?具体的使用代码我也写在这里了。

其中,ApplicationContext 是一个单例类,负责 Alert 的创建、组装(alertRule 和 notification 的依赖注入)、初始化(添加 handlers)工作。


public class ApplicationContext {

  private AlertRule alertRule;

  private Notification notification;

  private Alert alert;



  public void initializeBeans() {

    alertRule = new AlertRule(/*. 省略参数.*/); // 省略一些初始化代码

    notification = new Notification(/*. 省略参数.*/); // 省略一些初始化代码

    alert = new Alert();

    alert.addAlertHandler(new TpsAlertHandler(alertRule, notification));

    alert.addAlertHandler(new ErrorAlertHandler(alertRule, notification));

  }

  public Alert getAlert() { return alert; }

  // 饿汉式单例

  private static final ApplicationContext instance = new ApplicationContext();

  private ApplicationContext() {

    instance.initializeBeans();

  }

  public static ApplicationContext getInstance() {

    return instance;

  }

}

public class Demo {

  public static void main(String[] args) {

    ApiStatInfo apiStatInfo = new ApiStatInfo();

    //... 省略设置 apiStatInfo 数据值的代码

    ApplicationContext.getInstance().getAlert().check(apiStatInfo);

  }

}

现在,我们再来看下,基于重构之后的代码,如果再添加上面讲到的那个新功能,每秒钟接口超时请求个数超过某个最大阈值就告警,我们又该如何改动代码呢?主要的改动有下面四处。

  1. 第一处改动是:在 ApiStatInfo 类中添加新的属性 timeoutCount。
  2. 第二处改动是:添加新的 TimeoutAlertHander 类。
  3. 第三处改动是:在 ApplicationContext 类的 initializeBeans () 方法中,往 alert 对象中注册新的 timeoutAlertHandler。
  4. 第四处改动是:在使用 Alert 类的时候,需要给 check () 函数的入参 apiStatInfo 对象设置 timeoutCount 的值。

改动之后的代码如下所示:


public class Alert { // 代码未改动... }

public class ApiStatInfo {// 省略 constructor/getter/setter 方法

  private String api;

  private long requestCount;

  private long errorCount;

  private long durationOfSeconds;

  private long timeoutCount; // 改动一:添加新字段

}

public abstract class AlertHandler { // 代码未改动... }

public class TpsAlertHandler extends AlertHandler {// 代码未改动...}

public class ErrorAlertHandler extends AlertHandler {// 代码未改动...}

// 改动二:添加新的 handler

public class TimeoutAlertHandler extends AlertHandler {// 省略代码...}

public class ApplicationContext {

  private AlertRule alertRule;

  private Notification notification;

  private Alert alert;



  public void initializeBeans() {

    alertRule = new AlertRule(/*. 省略参数.*/); // 省略一些初始化代码

    notification = new Notification(/*. 省略参数.*/); // 省略一些初始化代码

    alert = new Alert();

    alert.addAlertHandler(new TpsAlertHandler(alertRule, notification));

    alert.addAlertHandler(new ErrorAlertHandler(alertRule, notification));

    // 改动三:注册 handler

    alert.addAlertHandler(new TimeoutAlertHandler(alertRule, notification));

  }

  //... 省略其他未改动代码...

}

public class Demo {

  public static void main(String[] args) {

    ApiStatInfo apiStatInfo = new ApiStatInfo();

    //... 省略 apiStatInfo 的 set 字段代码

    apiStatInfo.setTimeoutCount(289); // 改动四:设置 tiemoutCount 值

    ApplicationContext.getInstance().getAlert().check(apiStatInfo);

}

重构之后的代码更加灵活和易扩展。如果我们要想添加新的告警逻辑,只需要基于扩展的方式创建新的 handler 类即可,不需要改动原来的 check () 函数的逻辑。而且,我们只需要为新的 handler 类添加单元测试,老的单元测试都不会失败,也不用修改。

重点回顾

如何理解 “对扩展开放、对修改关闭”?

添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。关于定义,我们有两点要注意。第一点是,开闭原则并不是说完全杜绝修改,而是以最小的修改代码的代价来完成新功能的开发。第二点是,同样的代码改动,在粗代码粒度下,可能被认定为 “修改”;在细代码粒度下,可能又被认定为 “扩展”。

更多java原创阅读:https://javawu.com

程序员圣经(设计模式,代码重构) 设计模式,代码重构设计模式,代码重构设计模式,代码重构设计模式,代码重构设计模式,代码重构 立即下载

相关推荐

软件重构技术(重构介绍、重构原则、代码的坏味道。。。)

任何一个傻瓜都能写出计算机可以理解的程序,只有写出人类容易理解的程序才是优秀的程序员

代码重构原则和方法

代码重构原则和方法 参考: 《安卓开发进阶——从小工到专家》 重构原则: 我们重构代码的原则很简单,就是我往让代码保持:1、清晰2、简单3、可扩展。 重构方法: 1、      提取子函数 2、      上移至父类 3、      下移至子类 4、      封装固定的调用逻辑 5、      使用泛型去除重复逻辑 6、      使用对象避免过多的参数 7、    

子敬的技术博客 5623

代码重构-重构是设计演进的基本方法

软件设计是演进过程,而重构是设计演进的基本方法。重构是指不改变软件行为的前提下,修改程序内部结构。重构说简单,做不简单。首先,需要知道代码的好坏,即代码异味,设计原则等。其次,需要以自动测试作为保障。

代码重构的五大心法

最近在团队工作中花了不少心思主导建设了测试平台,前期的建设思路是能用就行,随着建设的深入,逐渐需要学习下代码架构设计方面的内容了。于是参加了公司组织的代码重构与模式的培训,通过培训,感觉收获颇丰,故整理此篇学习笔记

shanshan3003的专栏 1324

代码重构方向原则指导

代码重构方向原则指导.重构是一种对软件进行修改的行为,但它并不改变软件的功能特征,而是通过让软件程序更清晰,更简洁和更条理来改进软件的质量。代码重构之于软件,相当于结构修改之于散文。   重构是一种对软件进行修改的行为,但它并不改变软件的功能特征,而是通过让软件程序更清晰,更简洁和更条理来改进软件的质量。代码重构之于软件,相当于结构修改之于散文。每次人们对如何对代码进行重构的讨论就像是讨论如果对一篇文学作品进行修订一样无休无止。所有人都知道应该根据项目的自身情况来对代码进行重构,而重构是无止境的。莫扎特从来不不对他的作品进行修订,特罗洛普对自己作品修订的恰到好处,大多数作家认为他们俩这样做都是

数据标注工具:AiLabel.js实现标注 超详细教程 案例分享

背景:在前端开发过程中难免遇到针对图片的缩放平移;以及在图片上进行矢量数据、文本、标注的展示;如果你有上面的任何需求,恭喜你,找到组织了.... 在此背景下,AILabel.js出生了。 前面文章我们已经介绍过AiLabel.js了; https://blog.youkuaiyun.com/u012967771/article/details/113148527 npm下载地址:https://www.npmjs.com/package/ailabel github地址:https://github.com/d.

前端互助会 9365

代码重构原则有哪些

单一职责原则 一个类只负责完成一个职责或者功能,不要存在多于一种导致类变更的原因。单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、松耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。开放-关闭原则添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。开

weixin_57763462的博客 792

STM32硬件SPI驱动W5500以太网模块全流程(附避坑指南)

本文详细介绍了STM32硬件SPI驱动W5500以太网模块的全流程,包括硬件架构设计、SPI接口选型、官方驱动移植、网络协议栈配置与优化等关键步骤。通过实战案例和性能对比数据,帮助开发者快速实现稳定高效的网络连接,特别提供了常见问题排查指南和性能调优技巧。

weixin_29194693的博客 269

手把手教你重构乱糟糟的代码

点击蓝色“架构文摘”关注我哟加个“星标”,每天上午 09:25,干货推送!来 源:www.jianshu.com/p/3f04b6aebad2作者:小村医重构不止是代码整理,它提供了一种...

架构文摘 590

银河麒麟arm64 V10 SP1桌面系统高效部署onnxruntime推理环境实战

本文详细介绍了在银河麒麟arm64 V10 SP1桌面系统上高效部署onnxruntime推理环境的完整实战流程。从系统环境准备、关键依赖安装,到onnxruntime的安装验证,并以YOLOv5模型部署为例进行性能对比分析,提供了在国产化飞腾D2000平台上进行AI边缘推理的实用指南和避坑技巧。

ss78901的博客 636

12V转5V稳压电路详细分析(7805三端稳压,LM2596稳压)

7805线性三端稳压 DCDC的意思是直流变到直流(不同直流电源值的转换),只要符合这个定义都可以叫DCDC转换器,或称之为开关电源或开关调整器。 7805属于常用的线性三端稳压器,输入电压范围不大于35V,输入输出压差2V,最大输出电流1.5A,下图为原理图,其原理简单,使 用方便,深受很多用户的喜爱。但是其不足之处就是效率低,特别是压差越大时其效率越低。比如这里12V转5V的效率为 5V/12V≈41.7%。 如上电路是最经典的7805稳压5V电路,电路中有两个电容,电容的作用如下: ...

a2001444的博客 9万+

重构代码原则

狗屎一样的代码如何重构?重构不止是代码整理,它提供了一种高效且受控的代码整理技术。(一)重构原则1、何谓重构对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。另一种解释是:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。2、为何重构改进软件设计:如果没有重构,程序的设计会逐渐变质,重构很像是在整理代码,你所做的就是让所有的东西回到应处的位置上。 帮助找到bug:对代码进行重构,可以深入理解代码的作为,在搞清楚程序结构的同时,想不把bug揪出来都难

z_ssyy的博客 1065

VS2022下C# WPF项目一键打包成独立exe的完整指南

本文提供了一份在Visual Studio 2022中将C# WPF项目一键打包成独立可执行exe文件的完整指南。通过配置项目属性、启用单文件发布和自包含模式,开发者无需依赖第三方工具,即可生成可在未安装.NET运行时的电脑上直接运行的独立程序,极大简化了桌面应用的分发流程。

weixin_28831399的博客 673

当面试官问 “为什么想来我们公司?”如何回答

我在前公司主导过React+TypeScript的重构,而贵司的技术栈正好以React为主,我的经验可以直接复用。“贵司的[某产品/技术,如抖音的推荐算法/腾讯的微信生态]在行业内有很强的标杆作用,我一直希望参与这样规模的项目。业务岗:体验其产品,找可优化的点(如“我发现某功能交互有卡顿,我的性能优化经验能帮助改进”)。✅ 改成:“我研究了贵司去年的技术博客,对[某技术方案]印象深刻,这正是我想深入的方向。如果面的是外企,可强调文化匹配(如“贵司的远程协作和文档优先文化和我工作风格一致”)。

Alexander_Ljx的博客 1638

基于STM32的3D打印机控制

通过本项目,我们成功搭建了一个基础的3D打印机控制系统,能够控制步进电机和加热元件。这为使用STM32开发功能丰富的3D打印机提供了基础,您可以在此基础上继续扩展功能,如增加LCD显示、SD卡存储、联网控制等功能。在这个项目中,我们将使用STM32微控制器开发一个基础的3D打印机控制系统。通过控制步进电机、加热元件和温度传感器,我们将实现一个简单的FDM(熔融沉积制造)3D打印机控制。- 检查PWM信号的生成功能,确认加热元件的控制逻辑是否正常。- 增加适当的滤波和校准算法,以提高温度读取的准确性。

2401_88938661的博客 1504

13、深入理解 Microsoft 365 的安全与合规概念

本文深入探讨了 Microsoft 365 的安全与合规概念,涵盖文档存储、文件共享、审计、保留、eDiscovery、分类和保护以及网络等多个关键方面。通过合理配置这些功能,组织可以更好地管理和保护其数据资源,满足法规要求,并提升工作效率。文章还提供了最佳实践建议及流程图,帮助读者全面理解 Microsoft 365 的安全架构和管理策略。

k8s6orchestrator的博客 212

腾讯暑期日常实习前端面试

腾讯日常实习前端面试 我是23毕业的,所以我想找个暑假的实习,看了看没有多少公司要日常实习的,只有腾讯、字节、小米、美团招日常实习,所以我先投了腾讯和美团试试。 一面 一面约的时间是在2021-03-09 15:00,面试面了51 min,本身自我感觉良好的,写了一年博客,基础都学个七七八八,但是!重要的就在但是上,面试官就给了我当头一棒,问啥啥不会,也没怎么问基础,都是问项目,我这项目真的就是比较简单的项目啊,没有那么多技术沉淀啊,欲哭无泪,而且确实是慌了,项目是有一些亮点的但是真的没展示出来,除了会错意

WindRunnerMax 932

C# 工业视觉性能极致优化:多线程推理池 + 对象复用 + 批量检测,速度提升 10 倍实战

set;} // 输入图像set;} // 异步返回结果set;} // 用于监控延迟性能优化不是魔法,而是对资源生命周期的精细管理和对硬件特性的充分利用。多线程池解决了 CPU/GPU 闲置问题。对象池解决了 GC 停顿问题。零拷贝解决了总线带宽瓶颈。严格的 Dispose解决了内存泄漏问题。这套架构已在多个高速锂电、3C 电子检测产线落地,轻松应对 200ms 甚至 50ms 的严苛节拍。记住,在工业领域,稳定性与速度同等重要。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 308

腾讯2017校招实习生面试总结 腾讯实习生面试经验 (已拿offer)

从三月份开始,就投入了紧张的校招实习生准备当中。因为自己深知这次机会的重要性以及必要性。一开始,只锁定了腾讯和阿里的内推。三月初,在支付宝师兄的帮助下,成功获得内推资格。师兄给了很多建议,支付宝可能更喜欢问架构、设计以及思考相关的问题。实际上,这样开放性的考纲更难去复习。因为自己本科一直使用Java开发,读研期间,在百度实习用的是PHP。所以,复习的时候基本是突击Java高阶与虚拟机相关的知识点。...

doleria的专栏 3万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

新腾讯前端面试题:“大公司问的核心在于JavaScript”

腾讯面试对基础比较看重,然后需要你有两三个比较好的项目,一面重视面试者对前端基础的把握,还要手写代码,不过不难,二面部门的leader面,这一面比较难,面试官会对你的项目细节进行深挖,所以说项目要牛逼一点,最后还会有一道逻辑题,三面是HR面,如果你想进大公司的话,下面这些技术是肯定要掌握的:html5,css3,JavaScript,略懂一点jQuery源码,Node.js,express,mon...

明月如霜丶 1689

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

DDD落地:从腾讯视频DDD重构之路,看DDD极大价值

视频会员部门正在推进一个领域驱动的项目,期望运用 DDD 的一些理论,对会员技术体系的进行全面梳理。复杂度:业务复杂性(包括播放、购买、活动、内容展示、内容互动等全场景),以及技术复杂性(如业务规则、模块繁多、高并发、信息安全等),需要全面考虑。跨部门合作:目前的会员内容体系,涉及会员、直播中台、腾讯云、安平审核等多个部门,是一个典型的跨部门合作项目。体系梳理:会员业务涵盖内容展示、内容互动、内容合作和内容创新四个方面。领域模型:本文将重点借助领域图,将整个会员内容体系以直观的方式展现出来。

架构师尼恩 1229

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

python爬腾讯视频地址_腾讯视频爬虫

其实事情是这样的,上个礼拜我去面试一家公司,工作是做爬虫。然后有了以下对话。面试官:你是自学的,我有一些问题问你,python的浅拷贝和深拷贝是什么?我:呵呵面试官:额。。。你能不能说一说你是怎么理解python的面向对象编程?我:呵呵面试官:额。。。。好吧,我不问你基础了。你有没有爬过动态的网页?我:有啊,我爬过豆瓣啊。面试官:那我让你爬视频网站你怎么爬?F12里查看器是看不到视频地址的!我:看...

weixin_30877741的博客 2350

前端面经分享 | 腾讯

写在前面 笔者原来在北京360企业安全工作,当时因为大学四年的学业是在北京完成的,所以就顺势通过校招在北京工作了。但家里是南方的,对南方的饮食和生活习惯更加喜欢一些,所以对深圳广州的公司特别是腾讯觊觎已久,所以就在今年2月中旬左右开始准备面试,经历了一个多月的面试流程,在3月中旬喜提深圳腾讯的offer,现在已经入职半个月有余。在准备面试的过程中,在掘金上看了很多面经,对自己有非常大帮助。暂且在...

javajavajava 800

百度智能云上新:一手实测!0门槛、分钟级打造智能体

大模型时代真正的价值在于AI原生应用”继腾讯云推出高性能应用服务HAI,10分钟创建AIGC应用之后,百度云昨天在智算大会上也发布了AI云生应用平台AppBuilder,号称0门槛、分钟级打造智能体agent。AI赛道好不热闹。小编今天就带大家来实测一把。“大模型元年”下半年,话题焦点,已经显现出从技术向的基础模型,向“agent(智能体)”这样的应用关键词转移之势。从各家大模型厂商最新卷出的花样中,亦可见一斑——刚刚,百度智能云就率先露了一手:分分钟,打造一个“面试官”智能体。

Enweitech Software Works 2409

腾讯一面---视频面

中午1点,接到视频面试,面试官上来确认信息,然后岗位是成都的,问我要不要调给杭州上海的面试官面试,我说实习嘛,哪里都可以的,不要紧,然后接着他又说,如果实习留任的话,还是会在本地的岗位,我思考了一下,没问题。接下来则进入正题: 1.你都写过什么代码啊? 讲了一下老师让我们做的项目,虽然项目做得不好,但是还是有点心得的,balabala一大堆,讲得特别乱,面试官也没多问。 2.http了解吗?...

AiChiMomo的博客 877

“运气爆棚”一个礼拜面完拿到20K的offer -腾讯pcg后端开发面经,

前言 感觉运气爆棚了... 间隔不长一面面完第二天二面 然后隔了两天三面和HR面一起面的,总得来说面试体验很好,面试官经验也很丰富,偶尔答不上来的都会引导你往你知道的知识点上!顺利上岸拿到20K的offer,接下来请大家先看看我在面试腾讯PCG的时候,都问了那些面试题吧! 腾讯pcg后端一面 说说项目经历,印象最深的地方 项目重构了是吧,说说如何重构-一个项目? 重构项目如何处理与之间老接口的切换? 说说你的web框架,你如何实现- - -个get post的表单 如果多人访问一个写.

yuandengta的博客 266
上一篇: 还在用httpclient请求接口?那你就out了
下一篇: 深入理解Java的继承特性
大盛玩java
博客等级 码龄5年 0粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值