看了架构师的代码,切身感受到了代码可扩展性高的魅力

性能优化—代码层面优化 我们以前看到的很多架构变迁或者演进方面的文章大多都是针对架构方面的介绍,很少有针对代码级别的性能优化介绍,这就好比盖楼一样,楼房的基础架子搭的很好,但是盖房的工人不够专业,有很多需要注意的地方忽略了,那么在往里面填砖加瓦的时候出了问题,后果就是房子经常漏雨,墙上有裂缝等各种问题出现,虽然不至于楼房塌陷,但楼房也已经变成了危楼。那么今天我们就将针对一些代码细节方面的东西进行介绍,欢迎大家吐槽以及提建议。 一、服务器环境 服务器配置:4核CPU,8G内存,共4台 MQ:RabbitMQ 阅读详情

前言

开发有个著名的设计原则:开闭原则,即对扩展开放,对修改关闭。但是实际开发中鲜有人能运用纯熟,少侠在开发中接触的例子就是,大多数人就是if…else…这样难以扩展的条件判断。那么应该如何优雅的精简掉复杂的逻辑判断呢?当然抽象共性是从产品思维角度的优化方案,今天少侠想说的是通过技术手段实现。

业务背景

首先简单介绍一下业务背景,背景很简单,就是有若干渠道源,如阿里巴巴,腾讯等,针对不同的渠道需要有不同的数据处理逻辑,并且渠道来源之后会不断扩展。

初步实现

先建立一个简单的枚举类:

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public enum SourceEnum {
    /**
     * 阿里巴巴
     */
    ALIBABA("ALIBABA"),
    /**
     * 腾讯
     */
    TENCENT("TENCENT"),
    ;
    public String name;
    SourceEnum(String name) {
        this.name = name;
    }
    //匹配
    public static SourceEnum match(String name){
        SourceEnum[] values = SourceEnum.values();
        for (SourceEnum value : values) {
            if(value.name.equals(name)){
                return value;
            }
        }
        return null;
    }
    public String getName() {
        return name;
    }
}

再来看看业务层接口和具体的实现类(注意实现类上的@Service注解是指定的了别名的,方便之后利用 @Qualifier注解调用):

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public interface DataService {
    String dataProcess();
}
/**
 * @author Carson
 * @date 2020/8/24 下午3:14
 */
@Service("alibabaServiceImpl")
public class AlibabaServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Alibaba Process++++++++++++++";
    }
}

/**
 * @author Carson
 * @date 2020/8/24 下午3:12
 */
@Service("tencentServiceImpl")
public class TencentServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Tencent Process++++++++++++++";
    }
}

再来看看接口层的实现,主要是让用户传入渠道源source(真实环境中这个可能是从cookies里的用户信息获取,这里且不讨论),然后根据不同的渠道进行判断,注意看代码里的switch…case…语句,如果之后渠道扩展了,这里势必是要做改动的。有人可能觉得,看着还阔以啊,干净整洁,但是之后要是渠道很多呢,万一百八十个渠道,这里看着就很臃肿,并且万一出错排查起来也不方便,说得专业一点,就是扩展性不好。

/**
 * @author Carson
 * @date 20-8-20 下午5:00
 */
@RestController
public class CommonController {
    private final Logger logger = LoggerFactory.getLogger(CommonController.class);
    @Qualifier(value = "alibabaServiceImpl")
    @Autowired
    private AlibabaServiceImpl alibabaServiceImpl;
    @Qualifier(value = "tencentServiceImpl")
    @Autowired
    private TencentServiceImpl tencentServiceImpl;
    @GetMapping("/dataHandler")
    public String dataHandler(String source) {
        if (StringUtils.isBlank(source)) {
            return "Empty data";
        }
        SourceEnum sourceEnum = SourceEnum.match(source);
        if (sourceEnum == null) {
            return "Empty data";
        }
        switch (sourceEnum) {
            case ALIBABA:
                return alibabaServiceImpl.dataProcess();
            case TENCENT:
                return tencentServiceImpl.dataProcess();
            default:
                return "Empty data";
        }
    }
}

代码优化

优化的第一步是从枚举类开始,为每个枚举类指定对应的Service实现类对象,注意,Spring中接口不能被加载成Bean实例,所以需要为属性和方法添加@Lookup注解)。

@Service
public interface DataService {
    // 注意,此处必须加此@Lookup注解,否则容器无法启动
    @Lookup
    String dataProcess();
}
public class AlibabaServiceImpl implements DataService {
    public AlibabaServiceImpl(){}
    @Override
    public String dataProcess() {
        return "Alibaba Process++++++++++++++";
    }
}
public class TencentServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Tencent Process++++++++++++++";
    }
}

然后是改进后的枚举类:

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public enum SourceEnum {
    /**
     * 阿里巴巴
     */
    ALIBABA("ALIBABA", new AlibabaServiceImpl()),
    /**
     * 腾讯
     */
    TENCENT("TENCENT", new TencentServiceImpl()),
    ;
    public String name;
    public DataService dataService;
    SourceEnum(String name, DataService dataService) {
        this.name = name;
        this.dataService = dataService;
    }
    //匹配
    public static SourceEnum match(String name) {
        SourceEnum[] values = SourceEnum.values();
        for (SourceEnum value : values) {
            if (value.name.equals(name)) {
                return value;
            }
        }
        return null;
    }
    public String getName() {
        return name;
    }
    public DataService getDataService() {
        return dataService;
    }
}

然后接口层的改造如下,注意看这里的注解只是配置了接口的自动装配(并未注解所有的实现类),然后通过多态实现具体调用。

@RestController
public class CommonController {
    private final Logger logger = LoggerFactory.getLogger(CommonController.class);
    
    @Autowired
    private DataService dataService;
    @GetMapping("/dataHandler")
    public String dataHandler(String source) {
        if (StringUtils.isBlank(source)) {
            return "Empty data";
        }
        SourceEnum sourceEnum = SourceEnum.match(source);
        if (sourceEnum == null) {
            return "Empty data";
        }
        AbstractDataService dataService = sourceEnum.dataService;
        if (dataService == null) {
            return "Empty data";
        }
        return dataService.dataProcess();
    }
}

小结

通过使用枚举类,在枚举中将 属性与规则具体实现进行绑定。通过改变可以减少if -else使得代码更加优雅 如果需要新增渠道,我们只需要在编写具体规则实现类时实现DataService接口,并在枚举类中新增的枚举,而不需要改动到原先的任何代码。这符合了开闭原则。
由于Spring默认是单例模式,所以正常开发一个接口有多个实现类都是一个一个指定(@Qualifier)装配,但是如果想利用多态,让程序决定由哪个具体实现类执行,可以将@Service注解配置在接口上,同时为接口属性/方法添加@Lookup注解。

点点关注,不会迷路

Xilinx VU+系列多DIE FPGA时序约束与跨DIE信号优化策略 本文深入探讨了Xilinx VU+系列多DIE FPGA的时序约束与跨DIE信号优化策略。针对2.5D/3D封装技术带来的时序挑战,详细解析了SLR区域约束、Laguna寄存器配置及跨时钟域约束等关键技术,提供了实用的TCL脚本和RTL优化示例,帮助开发者有效提升设计性能和时序收敛效率。 阅读详情

相关推荐

嵌入式设备电量显示实战:MCP3421 ADC采集从原理到代码全解析(附避坑指南)

本文详细解析了嵌入式设备中MCP3421 ADC芯片在电量显示应用中的硬件设计、寄存器配置、I2C通信调试及低功耗优化策略。通过实战代码和避坑指南,帮助开发者实现高精度电量监测,特别针对I2C时序和分压电路设计等常见问题提供解决方案,适用于物联网终端和移动设备开发。

weixin_42525632的博客 386

写扩展性好的代码:函数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34261739的博客 335

ESP32-S3驱动雨滴传感器实战:从原理到ADC/GPIO双模式数据采集

本文详细介绍了ESP32-S3驱动雨滴传感器的实战教程,涵盖其工作原理及ADC/GPIO双模式数据采集方法。通过解析传感器利用水的导电性检测雨量的核心机制,提供了完整的硬件连接方案与软件驱动代码,包括模拟量(AO)的ADC读取和数字量(DO)的GPIO读取,并附有调试技巧,帮助开发者快速实现雨滴检测功能。

weixin_32005771的博客 154

架构师:优秀的代码都是如何分层的?

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习已经将知识体系整理好(源码,笔记,PPT,学习视频)《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

2401_84046895的博客 866

基于 Simulink 的三相四线制整流器在三相不平衡负载下的中点电位平衡控制实战教程。

本文介绍了三相四线制整流器在不平衡负载下的中点电位平衡控制方法。首先分析了中点电位漂移的物理机理和控制策略(零序电压注入)。接着详细讲解了Simulink建模步骤:搭建三相四线制主电路、设计平衡控制算法、实现PWM调制。通过对比有无平衡控制的仿真结果,验证了控制方法的有效性。最后提供了工程建议:零序注入需限幅、考虑中性线寄生电感影响、采用稳健的PI参数。该方案能有效抑制中点电位波动,保障三电平系统在不平衡工况下的稳定运行。

MHD0815的博客 60

城市仿真软件:AnyLogic_(8).行人与人群动态仿真

定义行人个体的行为和属性,如行走速度、目标位置等。// 创建一个行人// 设置行走速度为1.5 m/s// 设置目标位置为入口// 创建另一个行人// 设置行走速度为1.2 m/s// 设置目标位置为出口// 创建行人// 创建乘客行人与人群动态仿真在城市规划、交通管理和紧急疏散等领域具有广泛的应用。通过AnyLogic提供的行人模型模块,可以有效地模拟行人的个体行为、群体动态和与环境的交互。

kkchenjj的博客 1250

架构师的道法术:架构师是否需要下场写代码?

架构师是否需要下场写代码,并没有一个简单的“是”或“否”的答案。写代码对于架构师来说是一种能力,它帮助架构师保持技术敏感度,验证设计的可行性,并与开发团队保持紧密联系。但随着架构师职责的不断拓展,编写代码的深度和广度将不再是唯一的衡量标准。架构师的“道”在于深刻理解业务需求,设计出可行的技术架构;“法”在于通过团队协作和技术领导来确保架构的实施;而“术”则是依赖架构师在技术实践中积累的经验。

947

【第三方互联】12、支付宝(Alipay)授权第三方登录

我们创建了支付宝开放平台的网页&移动应用,审核通过后,我们需要拿到appid,支付宝公钥,私钥进项开发 一、添加应用信息至项目环境中 我们保存了 appid、应用私钥、支付宝公钥、支付宝回调地址等信息,这里的公钥为支付宝开放平台为我们生成的“支付宝公钥” 二、引入 Maven 依赖 <!-- 支付宝SDK --> <dependency> <g.........

JACKAL 21万+

DataProcessorService

public IDataReader GetFunctionInfo(int functionId) { this.PoolConnect(); SqlParameter para = new SqlParameter("@FUNCTION_ID", functionId); return SqlHelper.ExecuteReader(this....

weixin_30426879的博客 151

Qt实现窗口等比例缩放

在Qt中,实现窗口的等比例缩放是一个常见的需求。通过对窗口的尺寸进行调整,使得窗口的内容在缩放过程中保持相同的比例,可以提供更好的用户体验。通过以上的代码,我们实现了一个可以等比例缩放的Qt窗口。在调整窗口大小时,窗口中的标签和按钮将按比例缩放,保持内容的比例不变。首先,我们需要在Qt中创建一个窗口,并设置其内容。在该事件中,我们将根据窗口的新尺寸计算出合适的比例因子,并将其应用到窗口的内容上。现在,我们将添加功能,使得窗口可以等比例缩放。最后,我们将缩放因子应用到窗口中的标签和按钮上,调整它们的尺寸。

2301_79330511的博客 3958

基于最小二乘法(LS)和最小均方误差(MMSE)算法的导频信道估计

导频信道估计在无线通信系统中起着至关重要的作用,它用于估计无线信道的特性,以便在接收端进行正确的信号解调和解码。最小二乘法(LS)和最小均方误差(MMSE)是两种常用的导频信道估计算法,它们在估计精度和计算复杂度之间取得了良好的平衡。首先,我们提取当前的导频符号,然后将接收到的信号与导频符号相乘得到接收导频信号。最小二乘法是一种经典的导频信道估计算法,它通过最小化接收信号与预测信号之间的均方误差来估计信道。下面将详细介绍基于LS和MMSE算法的导频信道估计,并提供相应的MATLAB代码实现。

pytorchCode的博客 680

DataService系列教程 (一)

DataService系列教程 (一) 之前做了一些小项目,用到了DataService这个数据调用框架,所以根据自己实际理解和网上的一些参考,自己做了一些小随笔,方便以后记忆! 关于ADO.NET Entity Framework部分的内容见ADO.NET Entity Framework(1-4) http://kb.cnblogs.com/page/43963/ 本文例子下载:ht...

weixin_30335353的博客 2052

第25节:cesium 地形开挖综合实例-地下管网(含源码+视频)

地图开挖综合示例,包括底图切换,绘制开挖区域,移除开挖区域,影藏地图等等。

qq_29384639的博客 1782

多图详解:七种具体方法增强代码可扩展性

欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习 1 六大原则 在设计模式中有六大设计原则: 单一职责原则:一个类只做一件事 里式替换原则:子类可以扩展父类 依赖倒置原则:面向接口编程 接口隔离原则:高内聚低耦合 迪米特法则:最少知道原则 开闭原则:关闭修改,开放新增 我认为在这六个原则中开闭原则最为重要,开闭原则是可扩展性的重要基石。 第一个原因是需求变化时应该通过新.

JAVA前线技术专栏 3198

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

让你的代码有更好的扩展性

      代码有良好的扩展性,这每个开发人员的愿望。可是在无尽的需求改动增加和改动下,还有多少人在时时刻刻坚持。更多的时候是思考不到位或贪一时之快写下很多的if/else或者“硬代码”,为后续的需求修改带来很大的麻烦。      今天就遇到一个这样的例子。一个游戏。前后台各维护这一份用户道具的数据。用户购买道具时,为了减少前后台的交互, 前台会自己去对用户道具数据进行操作,但是每个道具购买后逻辑不一样。之前改一个bug,为了快速修复,后台针对一种道具返回对应数据,但是现在又有对不同道具的新需求。考虑到我们

greatwzz的专栏 4527

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

代码质量之可扩展性

  可扩展性的动力——不断变化的用户需求 世界上不变的是变化,软件需求不会变化?不可能!一个系统是否拥抱变化是由它的可维护性和可扩展性决定的,软件环境的变化(可能是业务环境,运行环境)导致软件要进行改动才能满足人们对它的要求,这种系统本身适应变化的能力就是可扩展性。   可扩展性的设计忠告 可扩展性对系统的性能和复杂度都有影响,复杂度很高的项目很难维护,亦很难测试,我比较推崇可预见的...

cantellow 1194

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

如何提高代码的扩展性

如何提高代码的扩展性 如何提高代码的扩展性 一、架构的高可用?(不是本文的重点) 二、软件项目的变化(为什么要提高代码的可扩展性(背景)) 软件设计的唯一产出物—代码 面向对象的目的是模块化 三、什么是高内聚、低耦合 1、搞清楚模块是什么 例如:如果模块A直接操作了模块B的数据,这种操作模块与模块之间就为强耦合,甚至可以认为这种情况之下基本算没有分模块!如果A只是通过数据与B模块交互,这种我们称之为弱耦合!微服务独立的模块,方便去维护,或者写单元测试等等…如果木块之间的依赖非常严重,将会非常不易于维护。 四

qq_34871037的博客 1625

我是如何提高代码的可扩展性的

最近写了一个逻辑表达式引擎(everlogic),对于如何提高代码的可扩展性做了一些思考,在这里做个总结,希望对大家有所启发。 该引擎想要达到的目标是传入一组参数,判断参数是否满足一定的逻辑条件。如传入参数 A 和 B,判断A、B是否都大于100,且 A 大于 B,逻辑表达式如下 A > 100 and B > 100 and A > B 除支持简单的逻辑表达式,还支持多个表达式的聚合,如 (A > 100 and B > 100 and A > B) and (C &g

Mengxiang's Blog 1405

重构-改善既有代码设计_实用代码重构,第3部分-可扩展性

重构-改善既有代码设计In part 2 of this series I shared questions that dealt with code refactoring for Readability. In this part we’ll spend some time with another aspect, Extensibility. We’ll take the same pra...

culi4814的博客 537

用代码来说明,为什么需要面向扩展的设计

在基本的面向对象编程中,你只能直接调用一个类的方法,而这些方法是由这个类的作者定义的,这对于面向用户设计的类来说是没有问题的。此外,在 20 - 30 年前,在大型标准库和开源库被大量复用之前,大部分代码通常是跟自己的代码中的类来一起工作的 —— 也就是你自己的团队或公司维护的代码。然而,在现代代码世界中,我们经常会使用其他人编写的类。 业务逻辑通常大量使用包括字符串和集合等标准库功能、以及第三方库中的一些类,我们受到这些类提供的操作的限制。例如,当我们需要用破折号替换字符串中的空格时,我们会这样编写代码

勇往直前的专栏 398

编写优质软件——代码可扩展性的几种实施方式

文章目录代码可扩展性的几种实施方式基于接口的设计插件架构状态机 代码可扩展性的几种实施方式 《ThePragmaticProgrammer》(Addison-Wesley,1999)一书的作者DaveThomas和AndyHunt曾经说过,所有编程工作都是维护的一种形式。一个类在首次键入几分钟后就会进入无限的维护循环。大多数时候,维护要求把现有代码库重构成模式或者更简洁的设计。然而,维护的能力具备...

Star_Inori的博客 2760

helloworld代码_十年架构师教你用最简单的代码实现Java基础编程—Hello World!

用Java输出HelloWorld可能有很多小伙伴在这里会有一个疑问:为什么学习每一种编程语言要学习第一个程序都是输出helloworld呢?Hello World ,中文意思:你好,世界。世界上的第一个程序就是Hello World,由Brian Kernighan创作,它简洁实用,因此它广泛适用至今。这个程序相当简单,其功能就是告知计算机显示Hello World这句话,以前程序员一般用这个程...

weixin_39934296的博客 375

一个小例子看编程的扩展性

当码农已经20多年了,从上大学开始,被人面试了无数次,也面试了很多人。从2005年以后,我就开始面试别人,发现很多程序员编程的时候,不会考虑编程的扩展性和执行效率。我自己出了一个简单的面试题,居然很多人没有给出我想要的答案,题目如下,如果你想测试你自己的能力,你也可以做一下,但千万不要看我下面的答案哟。 字符串 1.  A1,B1,C1,C2,B2,A2,D1,D2,D3 2.  E1,E2

huangyuncong的博客 3042

浅谈利用多态,继承和接口来封装代码,提高Java代码的可扩展性

一个人做项目的时候是最爽的, 因为可以肆无忌惮的按照自己的想法去"策马奔腾", 因为往往会优先选择实现成本最低且个人偏好的方式去实现, 简单的说就是, 怎么爽就怎么做.这样的情况,项目在实现时候如果只考虑方便快捷而忽略了关键的需求分析和架构设计, 虽然可能很快就能做出来,但质量不高. 并且一个具有生命期的项目, 它的代码是应该具有相当规范的.这个项目应当是, 即使其他工程师加入项目组中也能较快较容

Alex Tam 的专栏 6717

多种负载均衡算法及其Java代码实现

转载自:http://www.duzhi.me/article/864.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io 首先给大家介绍下什么是负载均衡(来自百科) 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提

小虾米的博客 5215

架构漫谈(八):从架构的角度看如何写好代码 + 我的思考

我的总结:当先前对于利益相关者的关系理清了,系统基本架构和测试方法等也有了,进入实际Coding阶段。在Coding前,需要我们考虑好业务功能的分配,关注于功能会频繁变更的部分,为未来的维护和扩展打下良好基础。诚然,这确实是一个基础,限于当时的资源、环境等约束,难以将所有问题一步到位的解决,还待于后期的功能修复和完善。 功能模块、功能模块,以期达到松耦合、高弹性的效果,便于后期维护和新功能的部署。...

Sudouble的专栏 1万+
上一篇: 【搞定面试官】系列:缓存雪崩、缓存击穿、缓存穿透
下一篇: MySQL深度分页的问题及优化方案:千万级数据量如何快速分页
少侠露飞
博客等级 码龄9年 214粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值