Apache Lucene的结构

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

lucene-package-anim

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

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

  1. 作为一种语法结构分析,此评论对程序语义或无论多么精致的交付用户体验都不太在意。
  2. 结构本身值得进行调查,因为它支配着变更潜在成本的可预测性。 结构不良的系统表现出过度的互连性,其中的连锁反应会严重影响变更成本估算的准确性。 结构良好的系统维护和升级的费用不一定便宜,但是通常它们带来的麻烦更少。
  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种方法,使总数增加到8474,并且传递依赖项的数量相对适度地增加到116211,但是从图中可以看出,发生了一些可怕的事情。

先前版本的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

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

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

相关文章

comcerter无法识别串口_基于FPGA 的MXN维字符识别的实现

基于FPGA 的MXN维字符识别的实现1 概述本文的灵感来源于杨淑英老师的一张PPT(手写数字识别),在此特别鸣谢杨淑英老师。一般机器视觉对事物是没有感知的,比如摄像头采集到一张苹果的图片,它本身是不知道那是什么东西&am…

嵌套的json ajax,通过jquery或javascript通过AJAX读取嵌套的JSON并输出到表中

我真的很想有一个快速便捷的方法来遍历JSON中的多个记录,每个记录都有潜在的深层嵌套。我只想输出到表。我不确定$ .each()或$ .ajax()成功的javascript方法需要通过function()传递哪些参数。所有示例似乎都使用通用词“data”或“ obj”,但它们使我感到…

难题:嵌套computeIfAbsent

总览 Java 8库在地图上有一个新方法,computeIfAbsent。 这是一种非常有用的将地图变成与键关联的对象的缓存的方法。 但是,您可能没有考虑过一种组合。 如果您在内部调用computeIfAbsent会发生什么。 map.computeIfAbsent(Key.Hello, s -> {map.com…

python扩展文件_1. 使用 C 或 C++ 扩展 Python

1.12.给扩展模块提供C API很多扩展模块提供了新的函数和类型供Python使用,但有时扩展模块里的代码也可以被其他扩展模块使用。例如,一个扩展模块可以实现一个类型 "collection" 看起来是没有顺序的。就像是Python列表类型,拥有C AP…

swal ajax,Sweetalert详细介绍

好长时间没有更新文章了,年底工作比较忙,确实是没有时间来写文章。今天忙里偷闲,总结了一款前端提示框的插件——sweetalert——推荐给大家。Sweetalert安装Sweetalert官方为我们提供了三种安装方式:方法一 通过bower安装$ bower …

构造函数必须没有代码

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

一个路由器两个网段互通_如何判断两个IP地址是否在同一个网段?什么是子网掩码?...

前几天咱们了解:三种方法告诉你项目超过255个摄像机怎么设置IP?什么是公网ip?什么又是内网ip?为什么ip地址通常以192.168开头?也学习了:二、三层交换机与路由器的区别!但是有好多人对IP这个概念还是不太清…

服务器appcrash的问题怎么修复,win7的ie出现APPCRASH问题怎么处理?

问题事件名称: APPCRASH 怎么解决?这是Win7或者是Vista特有的一个棘手的问题.APPCRASH(app是程序的意思,crash是坠机的意思。就是程序崩溃了/程序撞车……)(APPCRASH是Win7和Vista中特有的故障,就是程序崩溃引起APPCRASH错误的问题很多 如dll加载错误 软…

Jira 随便总结

一、JIRA与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。 JIRA创建的问题类型包括New Feature、Bug、Task和Improvement四种,还可以自己定义,所以它也一是过程管理系统。 JIR…

http 路径 |_HTTP 请求與响应的格式及 curl 命令使用

介绍 HTTP,主要内容有HTTP 请求包括哪些部分,如何用Chrome开发者工具查看 HTTP 请求内容HTTP 响应包括哪些部分,如何用Chrome开发者工具查看 HTTP 响应内容如何使用 curl 命令HTTP 请求的格式1 动词 路径 协议/版本 2 Key1: value1 2 Key2: v…

A new start!

从今天起,开始每天晚上拿出来半个小时到一个小时的时间来总结今天我做的那些事情,有哪些进步,有哪些不足,有哪些心得和笔记。 以前的学习都是每天学完就往脑袋后面一放,导致很多东西当时学会了,但是后面就都…

华为y7可以人脸识别吗_华为手机经常弹出“系统更新”提示,可以不更新吗?看完涨知识了...

众所周知,无论是手机,还是电脑,我们所使用的系统到了一定的时间,都会进行“系统更新”,尤其是我们使用的苹果手机、华为手机等,就经常会跳出提示,提醒用户“更新系统”,尤其是当我们…

Apache骆驼丝攻示例

如果您想监视,调试,排除流经路由的消息,而又不必从通道中永久消耗消息,那么就需要使用电线 。 有线分流器充当接收者列表,该列表消耗输入通道之外的消息并将其发布到两个输出通道。 第一个是作为主要信道的实际目的地…

微软的翻译书签

http://labs.microsofttranslator.com/bookmarklet/1.选择语言; 2.添加 Translate 链接到收藏夹或书签. 转载于:https://www.cnblogs.com/del/p/3391181.html

参考文献中会议名称怎么缩写_期刊缩写查询总结

介绍英文论文写作中,经常会插入参考文献。那么参考文献中的期刊名称,时常需要使用缩写。但是有时候,查了半天,怎么也查不着,让人抓狂。今天小编总结了几个查询期刊缩写的网址,方便大家进行期刊缩写的查询。…

ET的异常翻译

前段时间,我写了一篇有关用AspectJ进行异常转换的小博客文章。 在此博客文章中,我们将看到如何使用ET及其较轻的Java 8方法来完成相同的任务。 动机 异常转换(或异常转换)是将一种类型的异常转换为另一种类型的过程。 转换异常的…

7. SVM松弛变量

我们之前讨论的情况都是建立在样例线性可分的假设上,当样例线性不可分时,我们可以尝试使用核函数来将特征映射到高维,这样很可能就可分了。然而,映射后我们也不能100%保证可分。那怎么办呢,我们需要将模型进行调整&…

mysql 8.0认证失败_解决mysql8.0因密码认证插件导致的链接不上

简介今天在迁移zabbix的数据库,每次链接到自己的mysql都报错,mysqlAuthentication plugin caching_sha2_password cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_passwordzabbix总是提示**** MySQL server is not available. Waiting 5 secon…

关于Servlet和异步Servlet

Servlet API是Java EE标准的一部分,自1998年正式发布2.1规范以来,一直是基于Java的企业体系结构的重要组成部分。 它是一种自以为是的API,用于服务围绕一些基本概念构建的请求/响应协议: 兼容的容器 ,这是一个专用的…

linux c++ 运行时报 段错误 的一个原因

很长时间没有写 c/c了 这次依据一些代码写了一个linux上的小东西,结果在运行时用new 创建对象的时候,报: 段错误 有可能还出现如下报错信息: *** glibc detected *** ./selectServer: malloc(): memory corruption: 0x0000000000fba740 *** 研究了一会儿…