`
鳄鱼旭
  • 浏览: 76428 次
文章分类
社区版块
存档分类
最新评论

代码去重的艺术

 
阅读更多

重复的代码在软件开发过程中是会带来很大隐患的东东,尤其是当重复的代码发生变更时,很多莫名其妙的Bug就随之而来。我做面试官的时候曾经问过应聘者:去除重复代码有哪些种方法?有些人回答很简单,抽取出来一个函数,把重复代码移动进去。事实上真的是这样么?

 

本文试图阐述几个问题?A)去除重复代码在软件结构中的意义;B)列举代码去重过程中的一些方法,但只是抛砖引玉的作用,并不能完全枚举出来;C)讨论一些特殊的情况下,适当地忍受一些重复逻辑的存在;

 

首先,什么是重复代码?我是这样定义的:重复代码指的是那些相同、或者相近(完成的业务逻辑相近)的代码。产生的根源根源有如下几种情况:

    . Copy操作产生的:我曾经半开玩笑的和同事说过,按Ctrl+C的程序员不是好程序员,仔细分下下来也有

           两种情况,一种是Copy过来,直接使用;另外一种是稍作修改后使用。

    . 没有设计好造成的:比如张三和李四有一段类似的事情要做,由于沟通、设计等原因,每个人写了一份出来。

 

去除重复代码在软件结构中的意义:如果一个软件系统没有重复代码,或者几乎没有重复代码,那么软件系统的结构一般情况下不会太差。当然,也有例外的情况,我曾经参与过一个的一个项目,重复的代码确实不多,但是开发者把可能用到的东西都抽象到一个Utility类里面了,结果那个Utility非常复杂,做了很多的业务逻辑(在一些项目里面还发现过Utility类引用了一堆的Spring Bean,做具体的逻辑),几百行之多。很多的Service引用到了该函数,传入了7、8个参数,根据每种Service的业务做了If判断,每次读完了之后回家都做噩梦。所以去除重复代码(以下简称为去重)也并非是一件很简单的问题。

 

去重的方法,我做了简单归纳,将其分为两类进行阐述(只是我个人的分类方法):A)模式去重;B)设计调整去重 C)短代码去重。模式去重着重于针对GOF设计模式在去重方面的贡献、关键点;短代码去重着重于Utility的设计;

 

模式去重:实际上很多模式在去重方面都是卓有成效的,只是一些程序员平时不是很关注而已(面试的时候还有程序员奇怪,为什么我问设计模式相关的只是,认为设计模式只是一个理论化的东西,没有实际用处。究其本质,是因为没有真正的理解设计模式本身),下面我们一几个模式作为例子,分析其在去重方面的贡献:

1)工厂方法与模板方法

工厂方法与模板方法的结构实际上是很类似的,甚至有人将工厂方法看做是特殊的模板方法(只是抽象的部分负责创建一个对象而已:

 

工厂方法:


模板方法:


如果把模板中的primitveOperation1()变为一个创建对象的操作,那么实际上模板方法就是一个工厂方法了。因此下文我们只讨论模板方法。从去重的角度去看,如果不使用模板方法,那么ConcreteClass的TemplateMethod需要重新实现,如果是多个ConcreteClass的情况下,就产生了类似的代码。至于为什么采用模板方法解决这个问题,而不是其他的方式(比如把公共的部分抽象成一个工具类等),不作为本文讨论的内容。 
 

2)Builder模式





 
 

Builder在去重方面的作用比较明显,因为如果不使用Builder的话,Client需要自行实现构建过程,那么多个Client的构建的代码必将是重复的。 

 

3)代理(Proxy)模式



 代理实际上在Proxy层面对RealSubject进行了访问控制,比如if特定的逻辑下才进行操作RealSubject。为了实现这样的目标,引入了Proxy,比如数据库连接池就是典型的使用代理的例子。如果没有Proxy呢? 则每个使用Subject的地方都需要加入这样的判断if(xxx) realSubject.request(); 这个实际上也是重复的。

 

以上都是从设计模式角度上看,有哪些可以从去重的角度出发而引入的设计方法。实际上有些比较小粒度的设计手段虽然不构成模式,但是也很好的起到了去重的作用。

 

设计调整去重:

   有待完善。

短代码去重:

    有待完善。

 

参考资料:

《设计模式:可复用面向对象软件设计方法》

《实现模式》

Apache-commons

 

  • 大小: 17.8 KB
  • 大小: 12.7 KB
  • 大小: 17.7 KB
  • 大小: 15 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    SQL 语言艺术 SQL 语言艺术

    书中可能会介绍如何使用`JOIN`、`WHERE`、`GROUP BY`、`HAVING`和`DISTINCT`等子句进行多表联接、过滤、分组和去重。 2. 数据更新:`UPDATE`语句允许修改已存在的数据。书中可能讲解如何定位特定记录并执行精确的...

    ScummVM模拟器,一个设计用来在现代硬件上玩老式冒险游戏的程序,源代码和可执行程序

    从最早的基于文本的冒险游戏到 2D 像素艺术、全动态视频和 3D 游戏,冒险游戏类型为我提供了很多美好的回忆。 有时我想重温那些老游戏,但它们很多都是在 Linux 出现之前发布的,那么我如何去重玩这些游戏呢?我...

    14JVM调优.md,学习代码

    总结,JVM调优是一门深奥的艺术,涉及到内存管理、垃圾收集、性能监控等多个方面。通过理解JVM的工作机制,熟练掌握相关工具,以及在实践中不断调整优化策略,我们能够显著提升Java应用的性能和稳定性。在日常开发中...

    初中语文文摘人生减也是加

    这个故事发生在艺术创作的背景下,但其核心思想可以广泛应用于各个领域,包括信息技术的优化与设计。 【标签】: "资料"表明这篇文章可能作为教学素材,帮助学生理解减法思维的重要性,以及如何在实际问题中应用这一...

    python实现集句诗

    2. **预处理**:收集到的诗句需要进行预处理,包括去除标点、分词和去重等步骤,这通常会用到nltk或jieba等自然语言处理库。 3. **关键词匹配**:根据所要嵌入的人名,程序会寻找含有人名关键词的诗句。这里可能...

    tagua-开源

    Tagua编译器可能包含优化策略,如数据压缩、去重和智能缓存,以有效地在有限的资源下操作。 2. **客户端-服务器通信**:编译器的目标是在移动电话(客户端)与通过蜂窝网络连接的服务器节点之间高效地进行数据交换...

    MediaOrganiser-开源

    1. **元数据管理**:MediaOrganiser能够读取并处理各种媒体文件的元数据,如艺术家、专辑、歌曲标题等(对于音乐文件),以及视频文件的标题、导演、演员等信息。这些信息通常储存在文件的ID3标签中。 2. **文件...

    第十届Python组省赛试题.zip

    2. **分形树.py** - 分形树是一种使用递归实现的艺术图形,这表明试题可能会涉及Python中的递归算法和图形绘制库如turtle,同时测试了选手对分形理论的理解。 3. **递归.py** - 递归是编程中的核心概念,尤其是...

    sexyimg-spider:性感美女图片爬虫

    "sexyimg-spider-master"文件夹很可能是项目源代码,通常包含以下部分: - `spider.py`:爬虫主程序,定义爬取规则和逻辑。 - `settings.py`:配置文件,设定爬虫运行参数。 - `items.py`:定义爬取数据的结构。...

    leetcode分类-leetcode:leetcode

    4. **哈希表(Hash Tables)**:利用键值对快速查找,解决计数、查找、去重等问题。 5. **字符串(Strings)**:处理字符串的拼接、查找、替换、反转等,以及模式匹配等高级问题。 6. **二叉树(Binary Trees)**...

    Guitar Tab Sorter-开源

    2. **轻松搜索**:内置的搜索引擎使用户能快速定位到所需的标签,无论是按照曲名、艺术家还是特定的关键词,都能迅速找到目标。 3. **去重功能**:软件具有检测和删除重复标签的功能,避免了因重复标签造成的困扰,...

    Excel-165个VBA自定义函数大全

    去重是数据清洗的关键步骤,此函数帮助用户统计唯一值的数量,优化了数据质量和分析效果。 #### 59. 摘取子字符串 从长字符串中提取特定部分是数据处理的常见需求,该函数提供了这一功能,增强了数据的可操作性。 ...

Global site tag (gtag.js) - Google Analytics