apache lucene_Apache Lucene的结构

apache lucene

无可估量的高贵的Apache软件基金会(Apache Software Foundation)产生了许多巨大的产品(Ant,CouchDB,Hadoop,JMeter,Maven,OpenOffice,Subversion等),这些产品有助于构建我们的数字世界。 Lucene也许是一个鲜为人知的瑰宝,“……提供基于Java的索引和搜索技术,以及拼写检查,命中突出显示和高级分析/令牌化功能。” 尽管从标题上避开了,Lucene还是许多Apache(和第三方)项目中一个安静但不可或缺的组成部分。

lucene-package-anim

让我们看一下这个出色而成功的产品的基础结构。

在开始之前,请先进行以下四个警告。

  1. 作为一种语法结构分析,此评论对程序语义或无论多么精致的交付用户体验都不在乎 。
  2. 结构本身值得进行调查,因为它支配着变更潜在成本的可预测性。 结构不良的系统表现出过度的互连性,其中的连锁React会严重影响更改成本估算的准确性。 结构良好的系统维护和升级的费用不一定便宜,但是通常它们带来的麻烦更少。
  3. 该分析将包装结构描绘为斯波克林图 ,其中圆圈表示包装,直线表示从上方绘制的包装到下方绘制的包装的依赖性,而曲线表示从下方绘制的包装到上方绘制的包装的依赖性。 。 程序包的颜色表示它所参与的可传递程序包依赖关系的相对数量:越红,可传递程序依赖关系越多。
  4. 没有图可以证明结构价值或成本。 高级分析仅在提示问题的答案被埋在代码的地质层之下时才会进行。

因此,为了生意……

崛起 …

图1:Lucene 1.4.3版的程序包结构。

图1:Lucene 1.4.3版的程序包结构。

图1显示了仍归档的Lucene的最早版本之一,版本1.4.3。 回想一下,简单的结构测试表明随机选择了一个程序包,并询问:“如果该程序包发生更改,它最有可能影响其他哪些程序包?”

索引为例。 很明显的QueryParser跨度都依赖于它,因此可以通过任何变化指标受到影响,而曲线显示, 搜索就靠它呢。 这种容易的依赖关系识别是整个图形的特征​​,使其结构合理。

布拉沃(Bravo),露西娜(Lucene),您的开局很好。

图2:Lucene 2.0版的程序包结构。

图2:Lucene 2.0版的程序包结构。

图2显示了2.0版(请注意,我们不会研究每个发行版,而是在整个发行路径上均匀地布置里程碑),并且互连的简单性仍在继续。 尽管方法的数量从1.4.3的1,637版增加到2.0的2,085版,但程序包的数量却从11个减少到10个。这促使有效耦合效率从41%降至37%略有下降,但是好的设计原则显然可以精通此系统。

图3:Lucene 2.4版的软件包结构。

图3:Lucene 2.4版的软件包结构。

上面的图3中呈现的2.4版本虽然远没有明显的不良结构,但却显示出困扰的最初迹象。

的确,许多包裹与邻居之间有着明显的联系。 但是现在有些没有。 特别是搜索索引似乎已经陷入彼此的事务中。

但是,这种结构的轻微退化掩盖了幕后发生的动荡变化。 在2.0版有2,085个方法的地方,2.4版的大小增加了一倍多,达到4,176个方法。 在版本2.0仅具有9,767个传递依赖项的情况下,版本2.4在繁重的48,370个传递依赖项之下下垂。 正如我们将看到的那样,一些结构性的裂缝已经在方法级别上深层拉开,以触发依赖关系的五倍增长,这是Lucene的程序员从未发现或密封的裂缝,并且困扰着后来的修订版。

不仅依赖关系的数量急剧增加,而且程序的深度(其传递依赖关系的平均长度)也有所增加,从2.0版的7升级到2.4版的8.6,不仅为涟漪效应可能会扑朔迷离,但将这些音轨延伸到更远的地方以分流虚假的冲击。

尽管如此,这种结构仍然没有解决任何问题。 专注于设计可以恢复早期版本所具有的简单性。

图4:Lucene 3.0版的程序包结构。

图4:Lucene 3.0版的程序包结构。

las,版本3.0(如上图4所示)似乎仍在继续呈下降趋势。 再次,图4并没有呈现出一种不可挽回的结构:我们可以通过拆开包装来了解它们之间如何相互连接。 但是,这项任务变得更加困难。

分析跨度都被搜索索引所吸引。 预测更改这四个软件包中任何一个的影响现在似乎需要对所有其他软件包进行自动调查。

为增加互连性做出的贡献是在此修订版中增加了800种方法。 即使传递依存关系的数量已下降到46,917,但平均长度却再次增加,这次是9.3。

系统的结构是否超出了希望? 一点也不:许多软件包与同事之间都享有明确的依赖关系。 然而,即将到来的是版本3.5和大量传递依赖,尽管不是立即致命,但证明对所有药物都具有抗药性。

还有秋天……

图5:Lucene 3.5版的程序包结构。

图5:Lucene 3.5版的程序包结构。

令人欣慰的是,如上图5所示,版本3.5引入了额外的三个软件包(总数达到18个),以尝试分发和分离系统的功能。 慷慨的还可能会提出,尽管软件包的结构已从上一版明显地再次衰减了,但这种衰减仍然在一定程度上是局部的:坏男孩分析跨度搜索索引继续使Lucene镇表现良好的其他人群感到恐惧。

但是慷慨到此为止。

尽管仅增加了1800种方法,修订版3.5的传递依赖项数量却猛增到109,357,这些依赖项的平均长度达到11种方法,这是整个演进过程中最大的遗憾。 鉴于结构复杂性的这种显着上升,我们想知道包装设计的效果如何–确实如此和谐无济于事,因为应变最终破坏了下一个修订里程碑中的所有控制外观。

图5:Lucene 4.0版的程序包结构。

图5:Lucene 4.0版的程序包结构。

如图5所示,修订版4.0在先前的修订版中增加了1600种方法,使总数达到8,474,并且传递依赖项的数量相对适度地增加到116,211,但是从图中可以看出,发生了一些可怕的事情。

先前版本的Swift发展的互连性突然系统化,导致该结构内陷到可怕的缠结的球状关系中,这使代码影响预测极为不可靠。

的确,此修订版增加了另外两个软件包–将潜在的耦合效率提高到43%–并将(轻微)传递依赖项长度减少到10.4,但是控制如此大量的传递依赖项的巨大努力只是破坏了系统。 它不会恢复。

图6:Lucene 4.5版的软件包结构。

图6:Lucene 4.5版的软件包结构。

在图6所示的修订版4.5中,一些英勇的行动将传递依赖的数量减少到106,242,同时仍将方法的数量增加到9,562,也许某些软件包设法使自己远离系统上狂躁的黑洞。核心。 但是工作太少了,太迟了。

图7:Lucene 5.0版的软件包结构。

图7:Lucene 5.0版的软件包结构。

如图7所示,修订版5.0尝试通过删除200种方法来驯服野兽,但这奇怪地导致可传递依赖项的数量再次增加到113,556。

版本5.0看起来和版本4.5一样糟糕吗? 好吧,也许不是。 看起来有点干净。 但是,我们不应该让这种情况使我们对图7所示的巨大混乱视而不见:该系统痛苦不堪。 预测更改任何这些中央软件包的成本已经变得很困难。

为什么?

要了解破坏系统初始结构完整性的原因,我们必须检查3.5版。 再说一次,这看起来好像不是最糟糕的结构,但是这次修订预示了最终导致破产的变化。

主要的变化不仅是规模上的变化:更大的系统不一定会陷入结构不良的境地。 修订版3.5将方法数量增加了35%,但修订版2.4将方法数量增加了100%以上,而不会破坏整个组织。

相反,罪魁祸首是传递依赖的数量及其在系统中的分布。

修订版3.5中引入的新的传递依赖项数量惊人,从46,917增至109,357。 这使依赖方法比达到了动脉硬化16。

图8:比较Lucene的方法传递依存关系比率。

图8:比较Lucene的方法传递依存关系比率。

依赖于方法的比率已经太高了。 但是,在以前的版本中,这些可传递依赖项在很大程度上只限于一个或两个程序包。 在版本3.0中,所有可传递方法依赖项的95%终止于其原始包或仅在一个依赖项中的包中终止。 这给了希望,从某种意义上讲,变更可能会将自己限制在接近原点的区域,而很少有变更能够溢出到整个系统中,并且无法进行成本预测。

但是,修订版3.5看到该数字暴跌至75%。 这意味着所有修订版3.5的传递依赖项中有25%溢出到三个或更多程序包中。 结合这两个因素,我们发现有33,000多个依赖项需要等待远远超出其起源的弹射变化。 最重要的是,这注定了产品会进一步结构衰减。

图9:Lucene传递依赖项的百分比,少于3个包。

图9:Lucene传递依赖项的百分比,少于3个包。

然后,这结束了对Lucene包级别结构的检查。 我们是否应该深入研究套餐级别? 我们是否应该梳理各个软件包以检查各种类别的星座? 不行 。根据Blighttown的推论 ,如果包装级别的结构不好,我们不希望在下面找到钻石。 所以我们不会。

最终成绩

让我们尝试对Lucene的结构进行客观评分(其最终修订版本此处为5.0)。

我们将使用四个因素的平均值。 第一个度量Lucene试图限制可能形成的依赖关系数量的尝试。 第二和第三次尝试捕获传递依赖项的长度,第四次尝试捕获传递依赖项的数量。 当然,大型系统总会比小型系统具有更多的依赖关系,因此我们不能仅仅因为系统A的依赖关系少就说系统A的结构比系统B更合理。 取而代之的是,我们必须通过标准化大小或使测量在某种意义上具有自参考性来得出可以公平比较的测量。

首先,我们将测量其绝对理想效率:这将分析结构的潜在耦合 ,并基本询问封装了多少种方法而不使用其他方法,因此可以想象会创建多少依赖关系。 如果将每种方法都放在一个类中,那么每种方法对彼此都是可见的,因此效率为0%。 随着方法的私有化并把它们放在单独的包私有类中,这种方法的价值不断提高,从而使方法之间的封装越来越多。

Lucene得分为44%,表明它至少已尝试封装其功能,但还有更多工作要做。

其次,我们将以一种允许程序之间公平比较的形式来衡量Lucene的传递依赖项的长度。 为此,我们将使用CDF图来显示Lucene的传递方法依赖项占其最长传递依赖关系的百分比。

图10:Lucene的传递依赖CDF。

图10:Lucene的传递依赖CDF。

在上面的图10中,我们看到Lucene的传递依存关系的一半短于最长的传递依存关系的长度的45%。 这不好。 系统对纹波效应的抵抗力取决于其大部分依赖关系是否短暂。 例如, JUnit的传递依赖的一半仅占其最长依赖关系长度的30%。

当我们需要一个具有改进结构的数字时,我们将使用100减去该数字,因此Lucene的得分为100 – 45 = 55,该值应接近70。

我们将要讨论的第三个因素是:跨越两个或更少程序包的方法所占的百分比,这个数字为75.5%。 听起来不错,但是使用现代结构技术 ,几乎没有理由将该值小于90%。

最后,我们需要一个因素来衡量系统中有多少依赖项,因为依赖项的数量越少越好。 为了规范化大小,我们想测量每个方法的方法相关性数量。 不幸的是,在这里我们必须估算出行业最低的分数。 一些研究表明25似乎是一个合适的数字:如果系统每个方法包含25个以上的依赖项,则该系统的结构是如此糟糕,以至于所有其他所有其他指标都失去了重要性。

前面我们看到,Lucene每个方法有12个巨大的依赖关系; 因此我们将使用的数字为25-12 = 13,以25的百分比表示,得出52%。 如图8所示,其他系统的每种方法的依赖关系低至6,这个指标的收益率超过70%。

这使得Lucene的最终得分为226.5 / 400分,即57%。 根据牢固的结构原理,现代程序的分数很容易超过80%,所以这是一个很差的分数,表示,这是一个糟糕的结构。 Lucene在本系列到目前为止所分析的系统的排行榜中排名倒数第二。

因子 得分
绝对势偶效率% 44
100 –(最长依赖关系长度的一半,即一半系统短于该长度) 55
方法传递相关性百分比,范围不超过2个软件包 75.5
((25-(每个方法的传递方法依赖项数)/ 25),以25的百分比表示 52
平均 57%

表1:Lucene 5.0的结构评估。

摘要

程序 结构得分
Spoiklin Soice 84%
JUnit的 67%
Struts 67%
FitNesse 62%
弹簧 60%
Lucene 57%
蚂蚁 24%

表2:Lucene在排行榜上的位置。

可以做的更好。

翻译自: https://www.javacodegeeks.com/2015/05/the-structure-of-apache-lucene.html

apache lucene

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

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

相关文章

mysql 排序 过滤_【MYSQL】-3 排序与过滤

上周加入数据蛙二期培训,结束了孤独战斗的现状。断断续续自学了3个月(当然看了各种视频和各种书,一把辛酸泪。。。),现在选择报班,主要还是觉得一个靠谱的组织和团队,可以极大缓解我学习过程中不时闪现的焦虑和无助&am…

构造函数 构造代码块_构造函数必须没有代码

构造函数 构造代码块构造函数中应完成多少工作? 在构造函数内部进行一些计算然后封装结果似乎是合理的。 这样,当对象方法需要结果时,我们将准备好它们。 听起来是个好方法? 不,这不对。 这是一个坏主意,原…

C语言按位逻辑运算符总结-与、或、非、异或

点击上方蓝字关注我,了解更多咨询C中有按位逻辑运算符:按位取反、按位与、按位或、按位异或。这4个运算符可以用于整型,包括char类型。按位操作针对每一个位进行操作,不影响左右两边的位。4个运算符的作用总结如下:一、…

C语言的本质——位运算

点击上方蓝字关注我,了解更多咨询位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。C语言提供的位…

Java创新型模式_java设计模式--创建型模式(一)

2016-04-24 10:10:34创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)这三种模式从上…

原来这就是C语言的基本结构—循环结构?!

点击上方蓝字关注我,了解更多咨询今天我们就着重说说循环结构。循环结构分为三种,分别是for、while、dowhile;我们首先说第一种:for循环..他的代码格式为:for(判断的数值初始化;判断条件;改变判断数值大小){循环语句块&#xff1b…

java count 在哪一类里_java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用...

先来讲解一下Semaphore信号灯的作用:可以维护当前访问自身的线程个数,并提供了同步机制,使用semaphore可以控制同时访问资源的线程个数例如,实现一个文件允许的并发访问数。请看下面的演示代码:1 public classSemaphoreTest2 {3 public stati…

C/C++入门易错点及常用小技巧

点击上方蓝字关注我,了解更多咨询C语言诞生至今已有30多个年头了,主要集中在需要运行效率比较高的行业,比如现在的游戏开发以及高效服务器等等。C学习难度比其它语言都要高,这是不可否认的,其学习难度主要在于它的复杂…

quasar_Quasar和Akka –比较

quasaractor模型是用于容错和高度可扩展系统的设计模式。 角色是独立的工作程序模块,它们仅通过消息传递与其他角色进行通信,可以与其他角色隔离而失败,但是可以监视其他角色的故障并在发生这种情况时采取一些恢复措施。 角色是简单&#xff…

什么是自定义函数?精简回答

点击上方蓝字关注我,了解更多咨询1、自定义函数是程序员根据所要完成的功能,自己写出的源代码实现该功能。2、自定义函数和库函数一样,具有函数名,返回值类型,和函数参数。示例1:写一个函数找出两整数的值。…

C++ 创建文件夹的几种方式汇总确定不来看看???

点击上方蓝字关注我,了解更多咨询1、使用 system() 调用 dos 命令。2、使用头文件 direct.h 中的 access 和 mkdir 函数。关于 direct.h 我觉得 维基百科 上介绍的不错3、调用 Windows API 函数。4、调用 MFC 封装好的接口函数。不推荐此方法,出错的话会…

java socket 传送进度_java-★-Socket文件上传/进度条

客户端代码:1、客户端运行程序:package wtb.khd;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.OutputStream;import …

c语言中typedef和define的区别

点击上方蓝字关注我&#xff0c;了解更多咨询1、typedef仅限于为类型定义符号名称。define不仅可以为类型定义别名&#xff0c;还可以为数值定义别名。例如&#xff0c;可以将1定义为ONE。2、typedef由编译器解释&#xff0c;define语句由预编译器处理。实例#include <stdio…

c语言中预处理器是什么?

点击上方蓝字关注我&#xff0c;了解更多咨询1、C语言有预处理器&#xff0c;Java中没有这个概念&#xff0c;其实只是文本替换工具。2、C的预处理器&#xff0c;即CPP&#xff0c;将在实际编译器中完成处理&#xff0c;所有预处理命令将从#开始。实例#include <stdio.h>…

垃圾回收算法以及垃圾回收器_什么是垃圾回收?

垃圾回收算法以及垃圾回收器以下是我们的垃圾收集手册中的一个示例&#xff0c;该手册将在接下来的几周内发布。 同时&#xff0c;花点时间熟悉垃圾收集的基础知识-这将是本书的第一章。 乍一看&#xff0c;垃圾收集应该处理顾名思义的问题–查找并丢弃垃圾。 实际上&#xff…

c语言中fgetc函数的介绍

点击上方蓝字关注我&#xff0c;了解更多咨询1、fgetc函数返回的字符实际上是文件流中位置指针指向的字符。当fgetc函数读取错误时&#xff0c;返回EOF并设置文件错误标志位。2、该函数以无符号char强制转换为int的形式返回读取的字符&#xff0c;如果到达文件末尾或出现读错&a…

花5分钟了解C语言基本语法元素快来

点击上方蓝字关注我&#xff0c;了解更多咨询C语言是一种编程语言&#xff0c;和其它语言一样&#xff0c;也定义了自己的语法和词汇。学习C语言&#xff0c;首先要学习C语言的词汇&#xff0c;再学习C语言的语法规则&#xff0c;然后由词汇构成语句&#xff0c;由语句构成源程…

c语言中ftell函数是什么

点击上方蓝字关注我&#xff0c;了解更多咨询1、C语言函数ftell用于获取文件位置指针当前位置相对于文件首的偏移字节数。2、通过ftell函数获取当前文件的大小&#xff0c;然后通过fread函数读取缓冲区。返回值&#xff0c;如果成功&#xff0c;该函数返回位置标识符的当前值&a…

jdk入门_JDK 9 REPL:入门

jdk入门会议是聚会Java名人的好地方。 Devoxx France是与Java语言架构师&#xff0c;前同事和老朋友Brian Goetz&#xff08; briangoetz &#xff09;见面的一个机会。 我们谈论了JDK 9&#xff0c;而他全都热衷于REPL。 他提到&#xff0c;尽管Java SE 9中有很多重要功能 &am…

c语言中局部变量是什么

点击上方蓝字关注我&#xff0c;了解更多咨询1、函数内部定义的变量称为局部变量&#xff0c;其作用域仅限于函数内部&#xff0c;离开函数后无效&#xff0c;使用后报错。2、局部变量只能在函数内部使用&#xff0c;离开函数后无效&#xff0c;再次使用会报错。实例#include &…