dephpend/dephpend

PHP 的依赖分析

0.8.1 2021-05-02 14:10 UTC

This package is auto-updated.

Last update: 2024-09-09 16:22:13 UTC


README

Build Status Coverage Status Packagist Version License MIT PHP 7.2 Join the chat at Gitter

在您的架构出现依赖地狱之前,检测架构中的缺陷...

它做什么

dePHPend 帮助您将 PHP 项目恢复到最佳状态。在一个项目的过程中,我们通常会添加越来越多的依赖项。这些依赖项往往隐藏在单例或服务定位器后面,很快就会变成维护(以及测试!)的噩梦。

dePHPend 分析您的应用程序并尝试找到您所依赖的一切。

有了这些信息,您可以

  • 快速了解应用程序的结构
  • 开始进行必要的重构
  • 跟踪架构违规(可能您的视图不应该告诉模型做什么?)
  • 找出为什么您的更改破坏了测试

系统要求

  • PHP >= 7.2
  • plantuml(UML 类图)

安装

Docker

如果您不希望担心 PHP 版本、Composer 依赖等问题,您可以从 Docker 容器中运行 dePHPend

# replace $PATH_TO_INSPECT with whatever path you would live to inspect
docker run --rm -v $PATH_TO_INSPECT:/inspect mihaeu/dephpend:latest text /inspect

Phive

Phive 是安装不直接链接到您的代码的 QA 工具的首选方法。如果您从未听说过它,我建议您去了解一下。一旦安装,只需使用

phive install dephpend

# or

phive install --copy dephpend

Composer

您可以在全局范围内安装 dePHPend,但这样可能会因为其他全局安装的 QA 工具使用不同的 PhpParser 版本等问题而导致问题。

composer global require dephpend/dephpend:dev-main

手动下载 .phar 文件

通过从 GitHub 发布 选择最新文件来下载 PHAR 文件。

Git

git clone git@github.com:mihaeu/dephpend.git
# or
git clone https://github.com/mihaeu/dephpend.git

cd dephpend
composer install

用法

您几乎总是应该在没有 XDebug 的情况下运行 QA 工具(除非您当然需要代码覆盖率)。您可以使用一个不加载 XDebug 的单独的 php.ini 文件并将该文件传递给 php,或者您可以直接使用 -n 选项(但这将不会加载任何扩展,因此您必须单独指定它们)。

# or bin/dephpend depending on how you installed this
$ php -n -d extension=tokenizer.so -d extension=json.so -d extension=mbstring.so dephpend.phar                                                                                                 
      _      _____  _    _ _____               _ 
     | |    |  __ \| |  | |  __ \             | |
   __| | ___| |__) | |__| | |__) |__ _ __   __| |
  / _` |/ _ \  ___/|  __  |  ___/ _ \ '_ \ / _` |
 | (_| |  __/ |    | |  | | |  |  __/ | | | (_| |
  \__,_|\___|_|    |_|  |_|_|   \___|_| |_|\__,_| version 0.8.1

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  dsm            Generate a Dependency Structure Matrix of your dependencies
  help           Displays help for a command
  list           Lists commands
  metrics        Generate dependency metrics
  test-features  Test support for dependency detection
  text           Prints a list of all dependencies
  uml            Generate a UML Class diagram of your dependencies

过滤器

没有过滤器,大型应用程序的输出会非常臃肿,这就是为什么我实现了一些过滤器来帮助您获得想要的输出。

      --no-classes                         Remove all classes and analyse only namespaces.
  -f, --filter-from=FILTER-FROM            Analyse only dependencies which originate from this namespace.
      --filter-namespace=FILTER-NAMESPACE  Analyse only classes where both to and from are in this namespace.
  -d, --depth[=DEPTH]                      Output dependencies as packages instead of single classes. [default: 0]
  -e, --exclude-regex=EXCLUDE-REGEX        Exclude all dependencies which match the (PREG) regular expression.

      --dynamic=DYNAMIC                    Adds dependency information from dynamically analysed function traces, for more information check out https://dephpend.com
  -u, --underscore-namespaces              Parse underscores in Class names as namespaces.
      --internals                          Check for dependencies from internal PHP Classes like SplFileInfo.

有关更多信息,请运行 php dephpend.phar help text

文本

为了快速调试,请使用 text 命令。假设您想找出哪些类依赖于 XYZ 以及 XYZ 依赖于什么,您将运行

php dephpend.phar text src | grep XYZ

# or for more complex applications use filters
php dephpend.phar text symfony --no-classes --depth 3 --exclude-regex='/Test/'

UML

生成源代码的 UML 类或包图。需要安装 PlantUML

您可以选择运行

php dephpend.phar uml --output=uml.png src

# or for post-processing
php dephpend.phar uml --output=uml.png --keep-uml src

但您最可能想使用 --no-classes--depth[=DEPTH] 选项。如果您的应用程序有超过 20 个类,如果不使用命名空间而是使用类级别,UML 将会变得混乱。尝试不同的深度值,但通常深度为 2 或 3 是您想要的。

依赖结构矩阵

如果您以前尝试过解码大量的 UML 图表,您知道它们对于大型应用程序来说变得非常难以解释。DSM 允许您快速了解应用程序和依赖热点所在的位置。

此功能仍在建设中,目前使用起来并不有趣。如果您仍然想尝试,请运行

php dephpend.phar dsm src > dependencies.html

php dephpend.phar dsm src --no-classes | bcat

或者将其输出到类似bcat的工具。

度量

最常见的包度量指标已经实现,但还有更多即将到来。通过运行以下命令来查看它们:

php dephpend.phar metrics src

此功能尚未准备好用于生产环境,因此最好依赖PHP Depend来完成。

动态分析

如果您想分析一个很少使用类型提示和其他静态信息的老旧遗留应用程序,这使其难以分析,那么考虑使用动态分析。

dePHPend可以分析XDebug跟踪文件并将该信息添加到静态结果中。

设置

请确保已安装XDebug并将其包含在您的php.ini文件中。还要确保在php.ini的XDebug部分包含以下内容:

; you should already have this somewhere in your php.ini
zend_extension=path-to-your-xdebug/xdebug.so

[xdebug]
...

; add this for tracing function calls
xdebug.auto_trace=1
xdebug.collect_params=1
xdebug.collect_return=3
xdebug.collect_assignments=1
xdebug.trace_format=1

这将大幅降低PHP的性能,因此最好将其放入单独的文件,如php-with-traces.ini,然后使用php -c /path/to/php-with-traces.ini调用dePHPend。

用法

首先,通过在您的php.ini中设置上述设置来运行任何PHP脚本(或网站)以创建样本数据。

# use your tests (but make sure to exclude unwanted data using filters)
php -c php-with-traces.ini vendor/bin/phpunit

# or using PHP's inbuilt server etc.
php -c php-with-traces.ini -S localhost:8080

样本运行越好,覆盖的应用程序范围越广,结果就越好。然后使用--dynamic选项处理跟踪文件。

php dephpend.phar text src                  \
    --no-classes                            \
    --filter-from=Mihaeu\\PhpDependencies   \
    --exclude-regex='/(Test)|(Mock)/'       \
    --dynamic=/tmp/traces.12345.xt          

您可能总是会使用如--filter-from之类的过滤器,因为动态解析器解析所有内容,而不仅仅是提供的目录中的内容。因此,所有第三方内容都将显示出来。

默认情况下,跟踪文件将位于您的系统临时文件夹中。您可以通过在php.ini中设置xdebug.trace_output_dirxdebug.trace_output_name来更改此设置(请参阅XDebug功能跟踪)。

示例

架构约束

使用text命令创建一个验证您架构的脚本是相当直接的。

#!/usr/bin/env php
<?php

$output = shell_exec('php dephpend.phar text src --no-classes');
$constraints = [
    'OS --> .*Analyser',
    'Analyser --> .*OS',
];
if (preg_match('/('.implode(')|(', $constraints).')/', $output)) {
    echo 'Architecture violation'.PHP_EOL;
    exit(1);
}

将其保存在您的.git/hooks/pre-commit.git/hooks/pre-push中,您就永远不会再次违反项目经理的信任了。您也可以在每个Travis或Jenkins CI构建中包含它,但我更喜欢在可以自己检查时不要打扰CI。

架构时间线

在任意分支上执行dePHPend的度量命令git log --pretty=%H并使用convert -delay 100 -loop 0 *.png dephpend-timeline.gif,您可以创建一个详细说明架构演变的动画。

dePHPend Timeline

它是如何工作的

基本过程可以分解为四个步骤(实际工作要复杂得多,对感兴趣的人,我将在今年晚些时候发表一篇关于它的论文)

  • 找到所有相关的PHP文件
  • 使用Nikita Popov的神奇php-parser生成抽象语法树
  • 遍历树,沿途收集依赖关系
  • 将信息传递给格式化器

支持的功能

查看tests/features以获取支持的特性的示例,或运行bin/dephpend test-features以获取支持的检测功能的列表

[✓]  creating objects
[✓]  using traits
[✓]  extending other classes
[✓]  type hints in method arguments
[✓]  param return throws in doc comment
[✓]  implementing interfaces
[✓]  php7 return value declaration
[✓]  call to static method
[✗]  return value of known method
[✗]  method arguments and return value from doc
[✗]  known variable passed into method without type hints
[✗]  creating objects from strings

故障排除

内存不足

对于大型应用程序,PHP-Parser可能会占用大量的RAM。您可以在php.ini中调整RAM限制,但更安全的解决方案是通过添加php -n -d memory_limit=1024M dephpend.phar ...来调用dePHPend。

许可证

请参阅LICENSE文件