关闭

如何快速识别烂项目

时间: 2020-12-31阅读: 181标签: 项目

软件开发是一个非常有意思的复制 + 粘贴活动。开发业务代码的时候,大部分人都不会不加思索地添加代码。毕竟,聪明的产品经理/项目经理们,天才式地想出了用代码行数的方式来计算 KPI,又或者是通过提交次数来进行考核 —— 虽然小步提交是个好东西,但是吧,大部分人不经过练习还是掌握不会的。

最近,我还我的朋友们说到,她们公司的打算强制一天只能提交一次代码。这绝对是代码行数计算 KPI 之后的,又一个伟大地创举式的地发明。如果我有直接颁发诺贝尔奖的权力,我一定给送给他一奖杯。

好了,回到正题。


自上而下的代码分析

最近,刚好因为项目的关系,需要分析某一系统的代码行数。通过一系列的复制 + 粘贴和 Excel 操作,我大致有了一套 DIY 的自动化分析方案:自上而下的代码分析。当然了,这肯定不是我先发明的,在某处一定有论文和代码、工具。只是我依据自己的想法和需求,完善了一下现有的方案。要知道,已经有大量地代码分析工具了。

其实总体的思路非常简单:项目行数 -> 包行数 -> 修改历史 -> 引用分析。

具体来说,就是:

  1. 通过代码行数(LOC)统计工具,统计总体的代码情况。
  2. 结合代码行数(LOC)统计工具,统计各个包的代码情况
  3. 获取 Git 提交历史,统计出经常修改的包或者是类。
  4. 构建语法树、制品(如 jar)分析,统计出引用次数最多的包。

唯一麻烦的地方就是做一些自动化。所以,这些功能就被我完善到 Coca 里了,笑~。

好了,让我们来看个示例。这里以开源项目 intelli-community (即 IDEA 的社区版)为例。


项目级代码行数

市面上已经有大量的行数统计工具,大家可以自行寻找。这里我用的是 Coca (GitHub:https://github.com/phodal/coca ),集成了三方用 Go 实现的 CLOC 统计功能。

首先呢,我们要实现的是分析整个项目的行数情况 coca cloc . :

───────────────────────────────────────────────────────────────────────────────
Language                 Files     Lines   Blanks  Comments     Code Complexity
───────────────────────────────────────────────────────────────────────────────
Java                     66554   5172301   688054    512630  3971617     603221
Python                   10017    424614    31629     34876   358109      22329
Kotlin                    6383    602814    89130     35660   478024      51292
Plain Text                4105    635689     5799         0   629890          0
Groovy                    3397    154817    23296     12364   119157       4683
XML                       2549    494074    10056      3008   481010          0
html                      2329     63331     2988      3623    56720          0
SVG                       2124     21078       23        87    20968          0
jsON                      1155    346795      352         0   346443          0
Shell                      535      8295     1138       734     6423        811
Markdown                   425      9660     1434         0     8226          0
Properties File            384     42069     2545      1348    38176          0
YAML                       384      3264      202        55     3007          0
XML Schema                 345    196649    17963         0   178686          0
JavaScript                 169     30569     1562      5151    23856       3895
...
───────────────────────────────────────────────────────────────────────────────
Total                   101908   8389984   898893    629497  6861594     703260
───────────────────────────────────────────────────────────────────────────────
Estimated Cost to Develop $288,297,976
Estimated Schedule Effort 132.017220 months
Estimated People Required 258.681675
───────────────────────────────────────────────────────────────────────────────

嗯,从规模上来看,这真的是一个超级大的项目,接近 700 万行的规模。所以,我第一次看到的时候,也不知道从哪里下手,于是我便想着是不是从包(目录)结构能解决这个问题。

PS:Coca 当前只支持单体分析,考虑有多模块和微服务系统的存在,我会在未来必要的时候,添加对应的实现。


按目录分析

简单来说就是,我们可以按目录执行 cloc,然后汇总结构即可。

所以,进一步地我们就可以执行 coca cloc . --by-directory,得到一个 CSV 数据,根据自己的需要进行编辑:

packagesummaryJavaPythonKotlinPlain Text
platform180054214606861062445864669
java14798911059828035224267792
plugins176569598386070301151816150158
android186501076943752325659101848
python6647602400802876412462617855
xml8669261087940207174471
jps666716343701498729

还可以绘制成图表。

除此,我还提供了一个 --top-file --top-size 10 的参数,以了解行数最多的几个文件。

| LENGTH | COMPLEXITY |             LOCATION              |
|--------|------------|-----------------------------------|
|   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 提交历史来知道,对应文件的修改变化。这里,我依旧使用的是 coca git -t。它源自于对于 git log --all --date=short --pretty="format:[%h] %aN %ad %s" --numstat --reverse --summary 命令的分析结果,有兴趣的读者可以参考 Coca 的源码,自行编写不同版本地对应实现。

可怕的是,我在 intellij-community 执行了 coca git -t 之后,生成了一个 241M 的文件,回去 GitHub 看了一眼:累计 290,459 次提交。

在我第一次没意识到应该记录下 log 之后,我又重新执行了一遍。最终,拿到了结果:

|                                                                                            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 |
| platform/platform-resources/src/META-INF/LangExtensionPoints.xml                                            |       762 |         150 |
| platform/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 是一个有 5000+ 行的 Java 代码,UIUtil.java 也有 3600+ 行……。嗯,效果是不是也相当理想,再看看 UIUtil.java 这一个名字,一看就非常适合重构。


高引用

最后,可能会进入慢的一步,分析代码,生成 AST。考虑到 IDEA Community 的这个代码量。我就不重复演示了,以 GitHub 的示例为例 coca count:

+------------+--------------------------------------------------------------------------+
| REFS COUNT |                                  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 的慢的程度,我已经有一个更好的实现方式。


结论

分析代码是一件很有意思的事情。一番操作下来,能学习到非常有意思的东西。

来自:https://www.phodal.com/blog/how-to-quick-analysis-project-levels/


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/9996

关闭

pm2 快速部署前端项目

pm2 大家应该都知道,主要是用来管理 node 进程,但是同样可以用来部署前端代码。也可以手动添加 public key 到服务器上的 ~/.ssh/authorized_keys,

关于小型长周期项目的一些建议

我不是专业的项目经理,这里不讨论大型项目管理的事情。我们比较常遇到的可能是小型的长周期项目,比如2-4个人,做半年甚至一年的项目。这种项目通常不会有专职的项目经理

Vue如何刷新当前页面

项目需求是:在课程详情页 点击 相关课程 还在当前页面看此课程详情;功能实现:这时候点击相关课程需要重新加载刷新当前路由;this.$router.go(0)。这种方法虽然代码很少,只有一行,但是体验很差。

谈谈项目中单点登录的实现原理?

单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求。

spa项目如何计算首屏

对于首屏的定义,浏览器没有给出标准的指标,因为不同网站对于首屏的要求也是不尽相同的。我们从谷歌的第一次有效时间(first meaningfull paint)得到了一些启发,例如,一个新闻网站文字跟字体对于它来说是更重要的

为什么node不适合大型项目?

首先要明确什么是大型应用,其实这是仁者见仁、智者见智的问题,并且它是一个哲学问题,不是一个技术问题。假如有人问你,一个可以进行线上销售的网站,比如优衣库,大不大?你可能会说大,因为这与你平常所见的博客

node适合做什么项目

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,一个让 JavaScript 运行在服务端的开发平台。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。善于I/O,不善于计算。因为Node.js最擅长的就是任务调度,如果你的业务有很多的 CPU 计算

当了项目经理才明白的10件事!

项目经理这个神奇的职位,改变了我很多工作处事的方式,从前性情纯真的耿直boy,现在变成了人鬼皆爱的老油条, 以下是我当了项目经理之后明白的10件事, 如有雷同,真是太巧。

物联网项目选择JavaScript的5大理由

在一个以数字化为主导的世界中,物联网(IoT)在改变我们的生活和开展业务方式方面发挥着至关重要的作用。从智能生活到工作场所协作,以及与现场员工的联系,物联网将一如既往地节省时间和提高生产力。

如何创建一个NodeJs命令行交互项目?

通过原生的NodeJs API,可见,argv中第一个参数为node应用程序的路径,第二个参数为被执行的js程序文件,其余为执行参数。通过yargs获取命令行参数,方法如下

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!