image

PHPStan:无需写测试就能找到代码中的 Bug

每当我看到开发人员从 Java 或 C# 等编译语言切换到 PHP 这样的解释语言时解放了生产力后感到很高兴。除了这些常规的执行模型(发起、处理请求和结束请求)和更短的反馈环(无需等待编译器)外,还有一个能解决开发人员日常问题的开源框架生态系统,因此,PHP 是目前来说 web 开发中最流行的语言。

但它有一个缺点。

你会在什么时候发现错误?

编译型语言需要在程序运行之前了解每个变量的类型,每个方法的返回类型。这就是为什么编译器需要确保程序是没有错误的,并且会在源码中向你指出这些类型的错误,比如调用了未定义的方法或者是向某个函数传递了错误数量的参数。在把应用程序部署到生产环境前,编译器算是第一道防线。

然而 PHP 就不会这样了。如果程序出错,会执行到错误的代码的时候崩溃。在测试 PHP 应用时,不管是自动化测试还是手动测试,开发人员都会花费大量时间去查一些其它编译型语言不会犯的错从而减少测试实际业务逻辑的时间。

我想改变这一点。

欢迎来到 PHPStan 的世界

现阶段 PHP 实践所产生的代码库中,我们可以确定大部分数据的类型,并且转换为静态类型的语言,尽管还保留着一些动态语言的特性。人们把现在的 PHP 代码库变得跟其他语言一样更加有趣。面向对象,依赖注入以及设计模式的使用已经变得非常普遍。

这让我想到了 PHP 的 静态分析工具,它将替代其他语言的编译器角色。我花了很多时间研究它,并且已经使用它的各种开发版本来检查我们的代码库超过一年。

它就是 PHPStan, 开源且免费

它目前校验什么?

有关类中涉及的,对象实例, 错误/异常捕获,类型约束以及其他语言结构的存在性。 PHP 照旧不会检查这些, 但是会展现其中未被使用的代码。

被调用的方法和函数的存在性和可访问性。同样也会检查他们的参数个数。

方法是否返回了它声明的返回值类型。

被访问成员变量的存在性和可见性。它也可指出是否将一个其他的类型的值赋给了既定类型的成员变量。

sprintf/printf 函数基于格式化字符串所应接收的参数个数。

分支和循环范围中的变量的存在性。

无用的形式指定。例如 (string) 'foo' ,以及不同类型变量间的严格比较 (=== 和 !==),因为他们的结果总为 false。

这个清单的内容随着每次发布都在递增。但成就 PHPStan 也不会只仰赖此一技之微。

PHPStan 迅疾如飞...

它设法一次性检查整个代码库。 它无需多次遍历代码。 只需浏览您想要分析的代码,例如 你写的代码。它无需解析和分析第三方依赖项。 相反,它使用反射来找出有关你代码库中引用的他人代码的有用信息。

PHPStan 能在一分钟里检查我们的代码库 (6000 个文件, 600k LOCs) 。它可在一秒内完成自查。

...可扩展性

即便当前正在使用静态类型,开发者也可以合法的使用 PHP 的动态语法特性,例如 **get, **set 和 __call 这些魔术方法。它们可以在运行时去定义新属性和方法。通常,静态分析都会爆出属性和方法未定义,但是有一种机制可以告诉引擎如何创建新的属性和方法。

它得益于对允许用户扩展的原生 PHP 反射的自定义抽象。更多细节可查看 README 中类反射扩展章节。

某些方法返回的类型取决于它的参数。它可以取决于你传递给它的类名,也可能返回与传递的对象相同的类的对象。这就是 动态返回类型扩展 的用途。

压轴语: 如果你想自己出一个 PHPStan 的新的检查项, 你可以自力更生。可以提出基于特定框架的规则,例如检查 DQL查询中引用的实体和字段是否存在,或者你选择的 MVC 框架中生成的链接是否和现存的控制器有关。

选择规范级别

我使用过其他工具,并将之集成进现有的代码库中,这种体验真是往事不堪回首。他们爆出成千上万的错误让你没法使用。

取而代之,我回顾如何集成 PHPStan 到刚进入开发阶段的代码库中。 首个版本的功能不是很强大,这时并未发现多少错误。但从集成的角度来看,它还是非常不错的 --- 有空时,我就为它增加新规则,我修复了它在版本库中找到的错误,并将新代码合并到主分支。我们会使用新版本几周用来发现其找到的错误,并不断重复这件事。这种逐级增加的规范性的做法在实践中看来大有裨益,所以我使用 PHPStan 的现有功能来模拟它。

默认情况下,PHPStan 只检查它确定的代码---常量,实例化,调用$ this的方法,静态调用的方法,函数和各种语言结构中的现有类。 通过增加级别(从默认值0到当前值4),您还可以增加它对代码所做的假设数量以及它检查的规则数量。

如果内建级别无法满足你的要求,你同样也可以自定义规则。

少写单元测试! (披沙拣金)

可能这个建议你闻所未闻。即便是非常细碎的代码,开发者也不得不编写单元测试,因为这方面犯错的几率都是均等的,例如简单的拼写错误或者忘记将结果赋值给变量。为那些经常出现在控制器或者门脸中的转发代码编写单元测试是很不划算的事。

单元测试也有其成本。它们同样也是代码,难逃编写和维护的窠臼。最理想的做法就是在持续集成服务器上,每次更改时都运行 PHPStan,从而在无需单元测试的情况下防止此类错误的产生。实现100%的代码覆盖率真的很难,并且非常昂贵,但你可以静态分析100%的代码。

至于单元测试的重点应当集中在静态分析代码难以察觉的,容易出错的地方。包括:复杂的数据过滤,循环,条件判断,乘除法包含舍入的计算等。

站在巨人的肩膀上

如果不是 Nikita Popov 创建了 PHP Parser。就不会有 PHPStan 的出现。

PHP 在 2016 年开始广泛使用 包管理, 单元测试 和 编码标准 的工具。然而到现在也没有一个广泛使用的工具,可以在不运行代码的情况下检查代码中的错误。所以我创建了一个易于使用,快速,可扩展的版本,既不会对您的代码有严格的要求,你还会从这些检查中受益。查看 GitHub 仓库 ,了解如何将其集成到您的项目中!

php静态检测工具,PHP工具箱:PHPStan —— PHP 静态代码分析工具相关推荐

  1. PVS-Studio C/C++/C++11 静态代码分析工具

    PVS-Studio C/C++/C++11 静态代码分析工具 静态代码分析仪是一种检测代码缺陷.分析对比 商业代码的工具,它分析源代码和它生成的目标 文件,但并不实际运行源代码.应用于对安全性. 稳 ...

  2. 静态代码分析工具列表--常用静态代码分析工具介绍

    代码检测简介 本文是一个静态代码分析工具的清单,但是为公司产品需要付费使用.共有37个公司,有些公司包含多个工具.其中27个公司有多语言 工具,1个公司为PHP工具.2个公司为.NET工具.1个公司为 ...

  3. 2021.C/C++静态代码分析工具

    静态代码分析工具 1 cppcheck 静态代码分析工具 1 cppcheck 静态代码分析工具 参考博客 使用cppcheck检测代码警告.错误 ubuntu下安装cppcheck sudo apt ...

  4. 静态代码分析工具列表分析---代码分析工具列表(30款工具)

    本文是一个静态代码分析工具的清单,共有30个工具.包括4个.NET工具.2个Ada工具.7个C++工具.4个Java工具.2个JavaScript工具.1个Opa工具.2个Packaging工具.3个 ...

  5. 静态代码分析工具清单:开源篇(各语言)

    本文是一个静态代码分析工具的清单,共有26个工具.包括4个.NET工具.2个Ada工具.7个C++工具.4个Java工具.2个JavaScript工具.1个Opa工具.2个Packaging工具.3个 ...

  6. 静态代码分析工具清单:开源篇

    http://hao.jobbole.com/static_code_analysis_tool_list_opensource_lang/?utm_source=blog.jobbole.com&a ...

  7. 静态代码分析工具汇总

    静态代码扫描,借用一段网上的原文解释一下(这里叫静态检查):"静态测试包括代码检查.静态结构分析.代码质量度量等.它可以由人工进行,充分发挥人的逻辑思维优势,也可以借助软件工具自动进行.代码 ...

  8. 静态代码分析工具简介

    静态代码分析工具简介 什么是静态代码分析 静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法.结构.过程.接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌套语句 ...

  9. 【翻译】Google在构建静态代码分析工具方面的经验教训

    软件bug耗费开发者和软件公司大量的时间和金钱. 以2014年为例,被广泛使用的SSL协议实现中的一个("goto fail")bug导致可接受无效的SSL证书,另外一个与日期格式 ...

  10. 软文推荐:常用 Java 静态代码分析工具的分析与比较

    http://www.uml.org.cn/j2ee/201107114.asp 常用 Java 静态代码分析工具的分析与比较 作者:赵卓 , 发布于2011-07-11 , IBM 简介: 本文首先 ...

最新文章

  1. 触发器deleted 表和 inserted 表详解(转)
  2. show in Breadcrumb
  3. vi 编辑器跳转到指定行数
  4. flowable 表结构大全
  5. objective-c block 旧版详解
  6. Linux下TTY与PTY的区别
  7. numpy.argmin 使用
  8. C51单片机串口通信之上位机交互
  9. win10一共几个版本,有什么区别?win10版本区别
  10. 【智慧家科教2023新春首训】东方昱老师畅谈新发展之路:前途是光明的 未来是可期的
  11. 2021年如何低成本开启创业?
  12. Java读取MARC元数据 代码
  13. matlab中计算标准差std函数
  14. ubuntu18.04安装微信和wineQQ
  15. 如何突出显示重点数据?
  16. Google 天气预报 API
  17. 数据结构与算法——前缀、中缀、后缀表达式
  18. iTunes 4.9播客
  19. 层净高怎么算_楼层高度如何算 楼层高度标准
  20. json字符串转list<对象>

热门文章

  1. 【android】Android 破解实例(二)
  2. 统计学习第四弹--随机变量的概率分布
  3. java mouse_JAVA MouseEvent实现纪要
  4. 代码保护技术:控制流混淆
  5. try catch finally机制分析
  6. 高级信息系统项目管理师—论文—进度管理
  7. arguments函数
  8. c语言入门报告,c语言学习心得报告
  9. matlab和Verilog之截位,四舍五入和饱和处理
  10. 【图像去噪】基于matlab非线性扩散PM算法图像去噪【含Matlab源码 2130期】