简介SimianSimilarity Analyser是一款面向软件开发者的代码重复检测工具主要用于扫描代码库中的冗余片段与复制粘贴式代码帮助团队在持续集成环节控制复杂度、降低缺陷率。它支持Java、C#、C、C、JavaScript等多种语言适合需要提升代码可维护性的中高级开发者与项目团队。资源包共59个文件约3.43MB以38个html文档为主涵盖更新日志、特性说明、安装指南与客户案例等站点页面同时包含dll、jar、exe等可执行与依赖组件以及gif、png、jpg等界面图像、dtd与xsl报告格式定义文件、pdf许可文档和gz日志归档结构上兼顾工具运行与说明查阅。目前已有1416人学习下载。借助其中的报告格式定义与安装说明读者可快速将Simian接入Maven或Gradle构建流程配置检测规则与敏感度阈值并依据生成的重复代码报告定位问题从而持续优化代码质量、减少维护成本。1. simian 代码重复检测工具为什么你复制粘贴的代码正在拖垮项目接手一个跑了三年的老项目时我最先崩溃的不是架构混乱而是同一个工具类在七个文件里各有一份几乎一模一样的拷贝。改一个日期格式化逻辑得全局搜索替换七次漏一处就出线上问题。这种“复制粘贴式复用”在快速迭代的项目里极其常见而 simianSimilarity Analyser就是专门用来把这类重复代码揪出来的静态检测工具。它扫描指定目录下的源码文件按行比对找出连续多行高度相似的片段输出重复块的位置、行数和相似度。simian 适合谁用适合接手遗留系统需要评估技术债的工程师、想在 CI 里卡住重复代码增量的团队以及做代码审查时想用数据说话的人。它不重构代码只告诉你“哪里重复了、重复了多少”把判断权留给你。这一篇就按“装什么、怎么跑、参数怎么调、坑在哪”的顺序把 simian 从零到落地讲透。2. simian 的检测逻辑与最小可跑环境2.1 它到底怎么判断“重复”基于行窗口的相似度比对simian 的核心逻辑并不复杂但理解它才能调好参数。它把每个源文件按行切分忽略空行和纯注释行默认行为可通过参数调整然后用一个滑动窗口在文件内和文件间比对。窗口大小由-threshold控制默认是连续 6 行。也就是说两个片段只要有连续 6 行非空非注释达到设定的相似度阈值就被判定为重复块。相似度阈值由-similarity参数控制默认值因版本而异常见默认是 90% 左右。这个百分比不是字符级比对而是行级比对——两行只要“足够像”就算匹配。比如int count getCount();和int num getCount();在行级比对里很可能算匹配因为结构一致、只有变量名不同。这就是 simian 能抓出“改了变量名的复制粘贴”的原因也是它误报的来源。它支持的语言覆盖很广Java、C#、C/C、Python、JavaScript、Ruby、PHP、COBOL、VB 等几十种靠文件扩展名识别。检测时不需要编译纯文本扫描所以跑得很快。一个十万行级别的项目通常几秒到几十秒就能出结果。注意simian 是商业工具有免费试用期。网上能搜到一些老版本 jar 包但版本号和授权状态我不在这里编造你需要以实际获取到的版本为准。常见做法是团队采购 license 后把 jar 包放进内部工具仓库统一分发。2.2 最小可跑命令一条命令扫出全项目重复块假设你已经拿到了 simian 的可执行 jar 包放在tools/simian.jar项目源码在src/目录下。最小可跑命令如下java -jar tools/simian.jar -threshold6 -similarity90 -languagejava src/**/*.java这条命令的含义逐项拆开-threshold6连续 6 行相似才报告。调大这个值报告变少但更精准调小会抓出更多短重复但噪音也大。-similarity90行级相似度达到 90% 才算匹配。调到 95 以上更严格调到 80 会抓出更多“形似神不似”的块。-languagejava限定只扫 Java 文件。不指定的话 simian 会按扩展名自动识别但显式指定能避免把配置文件误判进来。src/**/*.java扫描路径。不同 shell 对通配符处理不同Windows cmd 下可能需要写成src\**\*.java或者直接用目录路径让 simian 递归。跑完后控制台会输出类似这样的结果Found 23 duplicate blocks: src/main/java/com/example/DateUtil.java:45-62 matches src/main/java/com/example/legacy/OldDateUtil.java:12-29 (18 lines, 94% similarity)每一条包含源文件位置、匹配到的另一个文件位置、重复行数、相似度。这就是你后续做技术债评估和重构排期的原始数据。2.3 把结果落成文件输出格式与 CI 集成方式控制台输出适合人看但要集成到 CI 或做趋势分析得落成结构化文件。simian 支持-output参数指定输出文件格式由扩展名决定java -jar tools/simian.jar -threshold6 -similarity90 -languagejava -outputreports/simian.xml src/**/*.java输出 XML 后可以用脚本解析出重复块数量、总重复行数、涉及文件数然后在 CI 里设阈值卡住。比如# 解析 simian XML统计重复块数量 BLOCK_COUNT$(grep -c block reports/simian.xml) if [ $BLOCK_COUNT -gt 50 ]; then echo 重复块数量 $BLOCK_COUNT 超过阈值 50请检查新增代码 exit 1 fi这段脚本的逻辑是每次构建时跑 simian如果重复块总数超过 50 就失败。阈值 50 需要根据项目历史数据来定——先跑一周只记录不卡看基线在哪再设一个略高于基线的值。常见做法是只卡“新增重复”而不是卡总量因为老代码的重复不可能一夜清完。要实现只卡增量需要对比本次和上次的 XML找出新增的重复块位置这属于进阶用法后面章节会讲。提示CI 里跑 simian 时建议把-threshold设得比本地开发时大一点比如本地用 6CI 用 10。这样 CI 只卡“严重重复”不会因为一些无伤大雅的短片段频繁失败导致团队对告警麻木。3. 参数调优threshold、similarity 和语言识别的实战取值3.1 threshold 怎么定从 6 到 15 的取舍-threshold是 simian 最影响结果的参数。默认 6 行意味着只要连续 6 行非空非注释代码相似就报告。在实际项目里6 行太敏感了——getter/setter、简单的 if-else 分支、try-catch 模板都会触发。我一般会按项目规模分档项目规模建议 threshold理由小于 5 万行8-10小项目重复块少稍严格一点减少噪音5 万到 20 万行10-12中等项目模板代码多10 以上能过滤掉大部分无意义重复大于 20 万行12-15大项目重复块基数大阈值低会导致报告爆炸调 threshold 的方法先跑一次 threshold6看报告里有多少条是“确实该重构的”有多少条是“模板代码不用管”。如果后者占比超过一半就往上调 2再跑一次直到报告里大部分条目你都认可。这个过程通常跑三轮就能找到合适值。3.2 similarity 的边界90% 和 95% 差在哪里-similarity控制行级匹配的宽松度。90% 意味着 10 行里有 1 行不同也算匹配95% 则是 20 行里允许 1 行不同。实际测试中90% 能抓出“改了变量名和字符串”的复制粘贴95% 只能抓出几乎逐字相同的块。我一般这样用第一轮扫描用 90%目的是“宁可多报不可漏报”把所有可疑块都列出来。然后人工过一遍把“确实该合并”的标记出来。第二轮用 95% 再扫一次这次出来的基本是“铁证”可以直接排重构任务。两轮结果的差集就是那些“像但不确定”的块留给代码审查时讨论。注意similarity 调低到 80% 以下时误报会急剧增加。我试过 75%结果两个完全不同的业务逻辑因为都用了相似的循环结构被判定为重复。除非你明确知道自己在找什么否则不建议低于 85%。3.3 语言识别翻车现场扩展名不对扫了个寂寞simian 靠扩展名识别语言但有些项目里.java文件里其实混了 Groovy 或 Kotlin 片段或者.js文件里是 JSX。这时候 simian 会按 Java 或 JavaScript 的规则去解析导致行切分错误要么漏报要么误报。解决办法是显式指定-language参数并且把文件路径写精确。比如一个混合项目# 分别扫描不同语言避免扩展名混淆 java -jar tools/simian.jar -languagejava -threshold10 src/main/java/**/*.java java -jar tools/simian.jar -languagejavascript -threshold8 src/main/webapp/**/*.js java -jar tools/simian.jar -languagepython -threshold8 scripts/**/*.py如果项目里有.vue或.tsx这类 simian 不直接支持的文件常见做法是先提取出其中的 script 块存成临时.js文件再扫或者干脆跳过用 ESLint 的no-duplicate-code类规则补位。simian 不是万能药它擅长的是传统后端语言的重复检测。4. 避坑与排查simian 跑不出结果时的五个血泪经验4.1 现象命令执行后没有任何输出也不报错原因最常见的是路径通配符没被 shell 展开simian 收到的是字面量src/**/*.java找不到文件就静默退出。Windows cmd 和 PowerShell 对**的处理不同Linux bash 需要globstar开启才支持**。解决先用ls src/**/*.java确认 shell 能展开。不能的话直接传目录路径srcsimian 会递归扫描或者用find生成文件列表再传给 simian。我一般直接传目录省事。4.2 现象报告里全是 getter/setter 和简单 if-else原因threshold 太低把模板代码也抓进来了。Java 项目里一个标准 POJO 的 getter/setter 连续 6 行几乎一模一样simian 默认就会报。解决把 threshold 调到 10 以上并且在扫描时排除自动生成的代码目录比如target/generated-sources、build/。simian 支持-exclude参数java -jar tools/simian.jar -threshold10 -exclude**/generated/** src4.3 现象两个文件明明很像但 simian 没报原因相似度没达到阈值或者中间有注释行打断了连续窗口。simian 默认忽略空行和纯注释行但如果注释和代码混在一起比如int x 1; // 初始化这行会被当作代码行参与比对可能导致相似度下降。解决先确认-similarity是不是设太高了降到 85 试试。如果还不报检查两个片段之间是不是有超过 threshold 数量的不相似行。simian 要求连续相似中间断开了就不算一个块。4.4 现象XML 输出里中文乱码原因simian 默认编码和项目文件编码不一致。Java 项目常见 UTF-8但 simian 在某些环境下默认用系统编码。解决跑 simian 时加 JVM 参数-Dfile.encodingUTF-8java -Dfile.encodingUTF-8 -jar tools/simian.jar -outputreports/simian.xml src4.5 现象CI 里 simian 偶尔超时或内存溢出原因项目太大或者扫描路径里包含了node_modules、.git这类不该扫的目录。解决用-exclude排除无关目录并且给 JVM 加内存参数java -Xmx2g -jar tools/simian.jar -exclude**/node_modules/**,**/.git/** src-Xmx2g给 2GB 堆内存一般十万行项目 1GB 就够二十万行以上建议 2GB。如果还超时把项目拆成多个模块分别扫最后合并报告。5. 把 simian 塞进 CI增量卡点与趋势看板的具体做法5.1 只卡新增重复对比两次 XML 的差异全量卡重复块总数会让老项目永远无法通过。更合理的做法是只卡“本次提交新增的重复块”。实现思路CI 里保留上一次成功构建的 simian XML本次跑完后用脚本对比找出新增的重复块位置。import xml.etree.ElementTree as ET def load_blocks(xml_path): tree ET.parse(xml_path) blocks set() for block in tree.iter(block): # 用文件路径起始行作为唯一标识 key f{block.get(file)}:{block.get(startLine)} blocks.add(key) return blocks old_blocks load_blocks(reports/simian_baseline.xml) new_blocks load_blocks(reports/simian_current.xml) added new_blocks - old_blocks if len(added) 0: print(f新增重复块 {len(added)} 处) for loc in sorted(added): print(f {loc}) exit(1)这段脚本的逻辑把每个重复块的“文件路径起始行”作为唯一键对比新旧两次结果差集就是新增的。CI 里如果added不为空就失败并打印出具体位置开发者一眼能看到自己新引入的重复在哪。参数上startLine比endLine更稳定因为重构可能改变结束行但不改变起始位置。5.2 趋势看板用重复行数占比衡量技术债除了卡增量还可以把每次构建的“重复行数占总行数比例”记录下来画成趋势图。比例上升说明技术债在增加比例下降说明重构有成效。# 从 simian XML 里提取总重复行数和总扫描行数 TOTAL_LINES$(find src -name *.java | xargs wc -l | tail -1 | awk {print $1}) DUP_LINES$(grep -oP lines\K[0-9] reports/simian.xml | awk {sum$1} END {print sum}) RATIO$(echo scale2; $DUP_LINES / $TOTAL_LINES * 100 | bc) echo 重复行占比: ${RATIO}%这个比例我一般控制在 5% 以内算健康5%-10% 需要关注超过 10% 就要排专项重构了。当然不同项目基线不同关键是看趋势而不是绝对值。5.3 一个我踩过的坑baseline 文件别放在构建产物目录最开始我把simian_baseline.xml放在build/reports/下结果每次clean就被删了导致增量对比永远拿不到基线每次都全量报。后来改成放在项目根目录的.ci/下并且提交到版本库才稳定下来。这个文件不大通常几百 KB提交到仓库完全可接受。提示baseline 文件需要定期更新。我一般每两周手动跑一次全量扫描把当前结果作为新 baseline 提交这样增量对比的基准不会太旧。更新 baseline 的 commit 单独提不要和业务代码混在一起方便回溯。5.4 和代码审查结合把 simian 报告变成 review 清单CI 卡住只是第一步真正减少重复要靠代码审查。我习惯在 MR/PR 里附上 simian 对本次变更文件的扫描结果reviewer 看到新增重复块时可以直接评论“这里和 XX 文件的 YY 方法重复建议抽成公共方法”。这样重复代码在合并前就被拦住而不是等 CI 失败再回头改。具体做法是在 CI 脚本里加一步只扫描本次变更涉及的文件输出重复块贴到 MR 评论里。这需要拿到变更文件列表不同平台命令不同但思路一致——缩小扫描范围让报告更聚焦。6. 用 simian 做重构排期从重复块到合并方案的落地技巧跑出重复块只是起点真正难的是决定“先改哪个、怎么改”。我的习惯是按“重复行数 × 涉及文件数”排序优先处理影响面大的块。比如一个 50 行的重复块出现在 8 个文件里合并后能减少 350 行冗余代码收益远大于一个 10 行重复块出现在 2 个文件里。具体操作时我会先用 simian 的 XML 输出生成一张排期表重复块 ID行数涉及文件数预估重构工时优先级B0015284hP0B0023053hP1B0031231hP2优先级规则行数 × 文件数 200 的排 P0100-200 排 P1小于 100 排 P2。工时按“每 10 行重复块 0.5 小时”粗估包含抽方法、改调用、跑测试的时间。这个估算当然不准但用来排优先级足够了。重构时有个技巧不要一次改所有文件。先在一个文件里抽出公共方法跑通测试然后再逐个替换其他文件。每替换一个就提交一次这样出问题容易回滚。我见过有人一次性改 8 个文件结果测试挂了不知道是哪个改动引起的排查了一下午。另一个技巧是对于“相似但不完全相同”的块不要强行合并。simian 报 90% 相似意味着有 10% 的差异。如果这 10% 是业务逻辑差异强行合并会引入 if-else 分支反而降低可读性。我的判断标准是如果合并后需要加超过 2 个参数或 3 个 if 分支来兼容差异就不合并而是保留重复但加注释说明“此处与 XX 文件相似修改时需同步”。这样至少让后来者知道这里有坑。最后说一个我自己的习惯每次 simian 扫描后我会把报告里“确认不重构”的块标记出来记录原因比如“模板代码合并收益低”“业务差异大强行合并会降低可读性”。下次再扫到同样的块直接跳过不重复纠结。这个标记文件我放在.ci/simian-ignore.txt里格式就是文件路径:起始行 # 原因。时间长了这个文件本身就是一份技术债决策记录新人接手时能看懂为什么有些重复被保留了。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
基于Kubernetes的多Agent编排与workspace隔离实践 1. 从“ax”这个标题说起:一个被低估的Agent编排入口第一次看到“ax”这个标题,很多人会以为是某个命令行工具的缩写,或者某个内部代号。但结合热搜词里的 agent、orchestrator、kubernetes、workspace 这几个关键词,基本可以判断… · 2026/9/25 6:15:26
Atlas 300V 24G上部署YOLO模型:从环境搭建到性能调优全指南 先回答那个热搜问题:Atlas 300V 24G确实是运算加速卡,而且是一张专门为AI推理设计的加速卡。我在这上面部署YOLO模型前后折腾了小半个月,踩了不少坑,也把一套完整流程跑通了。如果你正准备入手Atlas系列,或者手里已经有… · 2026/9/25 6:15:26
投研智能体实战:用Harness搭建可编排的研究管线 做投研的人应该都有同感:每天打开行情软件,消息推送几百条,公告、研报、社交媒体观点混在一起,真正有价值的信息往往被淹没在噪音里。最近 Z Waves 对 Panda AI 李昱琦的专访在圈子里讨论度不低,核心观点很直接——用 … · 2026/9/25 6:15:20
Atlas 300V 24G推理卡部署YOLOv5实战:从环境配置到性能调优 最近好多人在问 Atlas 300V 24G 是不是一张“运算加速卡”,还有人问我能不能拿它来训练 YOLO。这个问题的答案其实就一句话:它是推理加速卡,不是训练卡,但搞定 YOLO 目标检测的线上部署,它确实是一把好手。我去年在 At… · 2026/9/25 6:52:25
Union Alpha限免实测:从zcode配置到机械臂操控全流程 最近圈子里被一个叫Union Alpha的模型刷屏了,宣传口径特别直接:性能逼近Astra,限免一周。我一开始以为又是哪个实验室放出来的营销烟雾弹,结果测了三天发现这玩意儿确实有点东西,尤其是在工具调用和视觉控制这块&#… · 2026/9/25 6:52:19
深度解析 Hypothesis 测试执行次数:`max_examples` 的完整运行语义与底层实现 测试开发工具 【免费下载链接】hypothesis The property-based testing library for Python 项目地址: https://gitcode.com/gh_mirrors/hy/hypothesis 点击查看 免费下载 本指南聚焦 Hypothesis(Python 属性测试库)中一个看似简单实则微妙的… · 2026/9/25 6:52:13
BentoML Keras 集成实战:save_model、load_model 与 get 三大 API 全解析 模型推理服务人工智能后端大模型MLOpsLLMOps 【免费下载链接】BentoML The easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more! 项目地址: https://gitcode.com/gh_mirrors/be/BentoM… · 2026/9/25 6:52:13
【Coze】在Coze平台使用源码创建工作流 Coze 提供了图形化的工作流搭建平台,适用于低代码构建自动化任务流程。通过资源管理、节点配置与流程连接,可实现多种业务逻辑的在线部署。
本文介绍如何在 Coze 中创建工作流资源、导入流程 JSON 配置,并完成起止节点的连接与字段设置,直至试运行与发布上线的全过程。 文… · 2026/9/25 6:52:07
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37