当前位置: 首页 > 科技观察

如何快速识别项目级别?

时间:2023-03-20 00:36:29 科技观察

软件开发是一个非常有趣的复制+粘贴活动。在开发业务代码时,大多数人不会不假思索地添加代码。毕竟聪明的产品经理/项目经理想出了一个天才的办法,用代码行数来计算KPI,或者用提交次数来评估——虽然小步提交是件好事,但是拜托,大有人不加练习是掌握不了的。最近跟朋友说,他们公司打算每天只强制提交一次代码。这绝对是继代码行数计算KPI之后的又一伟大创举。如果我有权直接授予诺贝尔奖,我一定会给他一座奖杯。好了,回到主题。自上而下的代码分析最近因为项目的关系,需要对某个系统的代码行数进行分析。通过一系列的复制+粘贴和Excel操作,我大致有了一个DIY的自动化分析方案:自上而下的代码分析。当然,这绝对不是我先发明的,一定有论文、代码和工具在某处。只是我根据自己的想法和需求,对现有的方案进行了改进。要知道,现在已经有很多代码分析工具了。其实整体思路很简单:itemlinenumber->packagelinenumber->modificationhistory->referenceanalysis。具体来说,就是:使用代码行数(LOC)统计工具统计整体的代码情况。结合代码行(LOC)统计工具,统计每个包的代码状态,获取Git提交历史,统计修改频率高的包或类。构建语法树,分析产品(如jar),统计引用次数最多的包。唯一的麻烦是做一些自动化。于是,我把这些功能完善到Coca中,笑~。好吧,让我们看一个例子。这里我们以开源项目intelli-community(即IDEA社区版)为例。项目级代码行数市面上已经有大量的行数统计工具,大家可以自行查找。这里我使用的是Coca(GitHub:https://github.com/phodal/coca),它集成了Go中三方实现的CLOC统计功能。首先我们要实现的是分析整个项目cocacloc的行数:LanguageFilesLinesBlanksCommentsCodeComplexity─────────────────────────────────────────────────────────────────────────────────────────────────Java6655451723016880545126303971617603221Python10017424614316293487635810922329Kotlin6383602814891303566047802451292PlainText4105635689579906298900Groovy339715481723296123641191574683XML25494940741005630084810100HTML23296333129883623567200SVG2124210782387209680JSON115534679535203464430Shell535829511387346423811Markdown42596601434082260PropertiesFile3844206925451348381760YAML38432642025530070XMLSchema3451966491796301786860JavaScript1693056915625151238563895...─────────────────────────────────────────────────────────────────────────────────合计10190883899848988936294976861594703260───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────开发成本估计$288,297,976EstimatedScheduleEffort132.017220monthsEstimatedPeopleRequired258.681675嗯,从规模上来说,这真的是一个超级大的工程,接近700万兴的规模所以,第一次看到的时候,不知从何说起,就想能不能从包(目录)结构上解决这个问题。PS:Coca目前只支持单体分析。考虑到多模块和微服务系统的存在,以后我会在需要的时候加上相应的实现。按目录分析简单来说就是我们可以按目录执行cloc,然后总结结构。因此,进一步,我们可以执行cocacloc。-通过directory获取CSV数据并根据我们的需求进行编辑:包装摘要JavaPythonKotlin纯文本平台180054214606861062445864669JAVA14798911059891105982803522222426797992插件5983860715151515151515151515151515151515151515151515151515151515151515151515151515151515115151515151515151515151515159999999EMNRRO2400802876412462617855xml8669261087940207jps174471666716343701498729也可以画成图形。此外,我还提供了一个--top-file--top-size10参数来了解行数最多的文件。|长度|复杂性|位置||--------|------------|-----------------------------------||1642|236|ConstraintLayoutHandler.java||1492|375|ConstraintComponentUtilities.java||1189|166|CommonActions.java||1184|325|ConstraintWidget。java||1169|129|SingleWidgetView.java||1115|213|ScoutArrange.java||1097|281|ScoutWidget.java||1081|224|3d/Rasterize.java||1016|159|LayoutlibSceneManager.java||1014|220|TimeLinePanel.java|然后,我们只需要一层层往下推,就可以分析出系统中哪个部分是最复杂的。下图中的复杂点依次为:platforms、java、plugins、android。更改频率之后,我们可以通过获取Git提交历史来了解对应文件的修改变化。在这里,我仍然使用cocagit-t。来自gitlog--all--date=short--pretty="format:[%h]%aN%ad%s"--numstat--reverse--summary命令的分析结果,有兴趣的读者可以参考Coca的源码,自己写不同版本对应的实现。可怕的是,我在intellij-community中执行cocagit-t后,生成了一个241M的文件,回GitHub一看:一共290459次commit。在我没有意识到应该是第一次记录日志之后,我又重新做了一遍。最后,拿到了结果:|ENTITYNAME|REVSCOUNT|AUTHORCOUNT||--------------------------------------------------------------------------------------------------------|------------|------------||platform/util/resources/misc/registry.properties|2473|224||platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java|1211|149||platform/platform-api/resources/messages/IdeBundle.properties|1209|181||platform/platform-resources/src/META-INF/LangExtensions.xml|1206|192||plugins/InspectionGadgets/InspectionGadgetsAnalysis/resources/messages/InspectionGadgetsBundle.properties|1113|159||platform/platform-resources-en/src/messages/ActionsBundle.properties|1004|161||platform/platform-resources/src/META-INF/PlatformExtensions.xml|937|162||platform/util//src/com/intellij/util/ui/UIUtil.java|779|120||platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java|763|133||平台/平台-资源/src/META-INF/LangExtensionPoints.xml|762|150||平台/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java|684|126||java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java|675|117||platform/platform-resources/src/idea/PlatformActions.xml|671|139|然后看一下registry.properties是一个1800+行的配置文件,EditorImpl.java就是一个Java代码有5000+行,而UIUtil.java也有3600+行……嗯,效果也挺理想的,看UIUtil.java这个名字,很适合重构.高引用终于可以进入慢步,分析代码,生成AST。考虑一下IDEA社区中的代码量。演示我就不重复了,以GitHub的例子为例cocacount:+------------+--------------------------------------------------------------------+|REFSCOUNT|METHOD|+------------+--------------------------------------------------------------------------+|2|com.phodal.pholedge.book.BookRepository.byId||2|com.phodal.pholedge.book.model.Book.toRepresentation||2|com.phodal.pholedge.book.BookRepository.save||2|com.phodal.coca.analysis.JavaCallApp.parse||2|com.phodal.pholedge.book.BookRepository.save||2|com.phodal.coca.analysis.JavaCallApp.parse||1|com.phodal.pholedge。book.model.Book.save|最后,我们又回到了这个模型。高引用和高修改考虑到AST有多慢,我已经有了更好的实现。结论分析代码是一件非常有趣的事情。经过一些操作,你可以学到很有趣的东西。本文转载自微信?「phodal」,可通过以下二维码关注。转载本文请联系phodal公众号。