傻大方


首页 > 人文 >

删除|你写的代码是死代码吗?如何判断和清理,一招搞定~



按关键词阅读:

删除|你写的代码是死代码吗?如何判断和清理,一招搞定~

作为开发者的你平时工作时是怎么判断并清理死代码的?也许你猜到了这篇文章要讲什么 。
是的 , 我们是有一些清理死代码的好方法推荐给你……在认真考虑了各种自动化工具之余 , 我们还希望能够遍历所有的代码 , 分析每一个 .erl 和 .hrl 文件 , 并输出所有可以删除和/或重构代码的候选列表 。
本文介绍的这款工具 Hank 可以帮助你确定哪些是死代码 。

Hank 与其他现有工具的区别你可能想问:“为什么我要选择 Hank?这类的工作可以通过 linter 解决!”
答案是:不 , Hank 与 linter 不同 。
关于代码的 linting , 我们使用 Elvis , 它会审核我们的 Erlang 代码风格 , 比如函数命名、嵌套层级、每一行的长度、变量命名约定等等 。
这些不属于 Hank 的工作范围 。
Xref 是一种交叉引用工具 , 可用于查找函数、模块、应用程序以及发行版本之间的依赖关系 。 它会分析函数的定义和函数的调用 , 并警告我们源代码中已定义、但从未使用过的函数 。
这些也不属于 Hank 的工作范围 。
那么 Dialyzer 呢?Dialyzer 是一种静态分析工具 , 可识别软件差异 , 例如成功类型的错误 , 以及由于编程错误而变得无效或无法访问的代码 , 以及不必要的测试等 。 它的分析基于的是成功类型的概念 。
Hank 不依赖于规范 , 也不评估函数参数/返回中的“语义”
Hank 的功能那么 , Hank 究竟有哪些功能?
Hank 会检测并警告你代码库中可以被删除 , 或者可以根据规则重构的代码 。
它适用于整个项目(与 Elvis 不同 , 后者只能处理单个文件) , 源代码(与 Xref 不同 , 后者只能处理已编译的代码) , 以及单个项目(与 Dialyzer 不同 , 后者将分析整个系统 , 包括 OTP 以及依赖项) 。
如何使用 rebar3_hank你只需要将下列代码添加到rebar.config(项目或全局的~/.config/rebar3/rebar.config):
{plugins [rebar3_hank
.

然后运行:
rebar3 hank

接下来就是见证奇迹的时刻!
跳过规则在某些情况下 , 你可能需要跳过某些规则 , 比如正在开发的库 , 你可以在其中定义供其他使用的 hrl 或模块 。
在这种情况下 , 你可能需要忽略一些规则(例如single_use_hrl_attributes) 。
【删除|你写的代码是死代码吗?如何判断和清理,一招搞定~】使用 Xref 也会发生类似的情况 。
为此 , hank 可以忽略模块级别的规则:
% ignoring all the rules for this module
-hank ignore


% or ignoring specific rules
-hank [single_use_hrl_attributes


或者 , 在 rebar.config 中添加以下配置:
{hank [{ignore [
   {\"test/*.erl\" unused_ignored_function_params


.

规则以下是我们创建好的规则 , 你可以直接在 Hank 中使用 。
unused_ignored_function_params随着函数的不断发展 , 以前的某些参数可能已不再使用了 。 最简单的解决方案可能就是忽略它们 , 然后忘掉这个问题 。
Hank 会检测出所有函数中被忽略的参数 , 并告知你可以删除这些参数 , 并重构函数的调用 , 这样就可以让代码更加简洁 。
例如 , 在分析这个模块时……
-module(my_module).


-export([external_fun/1
).


external_fun(X) ->
    multi_fun(Xrand:uniform() undefined).


%% A multi-clause function with unused 3rd param
multi_fun(undefined _ _) ->
    ok;
multi_fun(Arg1 Arg2 _Arg3) when is_binary(Arg1) ->
    Arg2;
multi_fun(Arg1 _ _) ->
    Arg1.

Hank 的输出结果为:
$ rebar3 hank
===> Looking for code to kill with fire...
===> The following pieces of code are dead and should beremoved:
src/my_module.erl:9: Param #3 is not used at 'multi_fun/3'

为了避免这种警告 , 你可以删除未使用的参数 。
single_use_hrls有时 , 你会将一些代码放入应该在多个模块之间共享的头文件中 , 但最终你只编写了一个使用该头文件的模块 。 在这种情况下 , 最好将头文件的内容直接放入模块内 。 Hank 有这样的一个规则!
假设有一个文件 header.hrl:
-define(APP_HEADER \"this is a header from an app that willbe used in just one module\").分页标题#e#
-define(SOME_MACRO(A) A).


-module(app_include_lib).


-include(\"header.hrl\").


-export([my_function/0
).


my_function() ->
  % those are only usedhere!
 ?SOME_MACRO(?APP_HEADER).

Hank 的输出结果为:
$ rebar3 hank
===> Looking for code to kill with fire...
===> The following pieces of code are dead and should beremoved:
header.hrl:0: This header file is only included at:src/app_include_lib.erl

将这个 hrl 文件的内容直接放入使用该文件的模块中 , 就不会再看到这则警告了 。
single_use_hrl_attrs有时 , 情况会更微妙 。 有时 , 整个文件并非仅在一个模块中使用 , 可能在许多模块之间共享 。 但是某些属性并非如此 , 例如宏或记录 , 它们在头文件中定义 , 但仅在单个模块中使用 。 Hank 有一条规则 , 建议你将这些属性放在模块内 , 以减少不必要的共享内容 。
对于上述文件 , 假设 hrl 包含在另一个文件中:
-module(app_include_lib_2).

-include(\"header.hrl\").

Hank 的输出结果为:
$ rebar3 hank
===> Looking for code to kill with fire...
===> The following pieces of code are dead and should beremoved:
include/header.hrl:2: ?SOME_MACRO/1 is used only at src/app_include_lib.erl

unused_hrls有时 , 情况会更加恶劣 , 有的 hrl 文件可能没有包含在任何模块中 。 Hank 会检测到它们 , 并告知你可以将其完全删除 , 因为实际上它们没有任何作用 。
添加一个未包含在任何模块中的 header_2.hrl 文件 , Hank 的输出结果为:
$ rebar3 hank
===> Looking for code to kill with fire...
===> The following pieces of code are dead and should beremoved:
include/header_2.hrl:0: This file is unused

unused_macrosHank 还有一条规则 , 它将检测项目中未使用的宏 。 这些宏可能定义在了源代码中的任何文件中 , 但是从未使用 。 因此 , 这些宏都是没有必要的 , 可以删除 。
unused_record_fields
这个规则很重要 。 根据这个规则 , Hank 会发现某些记录声明带有字段定义(甚至为它们提供默认值) , 但从未使用过 。 Hank 认为访问或写入记录字段就是在使用它 。
你可以通过这个警告 , 删除记录中未使用的字段 , 从而减小记录的大小 。
可扩展性我们非常注重该项目的可扩展性 , 任何人都可以通过实现 hank_rule 的行为来编写自己的项目规则 。
但是 , 如果你觉得新规则具有广泛适用性的话 , 可以贡献到 rebar3_hank 的 GitHub 社区!你可以查看未解决的议题 , 并随时创建新的议题!
测试 Hank 的威力为了让你了解 Hank 的功能 , 我们决定在一个很大的代码库中对其进行测试 。
我们决定尝试使用 Erlang / OTP 。 由于这个项目主要由各种库组成 , 因此我们必须限制应用哪些规则 , 以免产生一些虚假的结果 。 我们使用了以下配置:
{hank [
    {ignore[\"**/test/**\" %% Just \"production\" code no tests
    {rules [
       unused_ignored_function_params
        unused_hrls
        unused_macros
       unused_record_fields
    


.

我们知道会找到大量警告 , 但是最终的结果还是超出了预期 。 Hank 找到了 OTP 生产代码中的 4000 多条死代码 。
虽说并不是所有收到警告的代码都应该被删除 , 但是通过这个例子 , 你也看出了 Hank 的威力 。 以下是 Hank 输出的警告……
记录中未使用的字段Hank 找到了 130 多个包含未使用字段的记录 , 例如 erl_tidy 或 remote_logger 。
未使用的宏Hank 在 OTP 中发现了 1000 多个未使用的宏 , 其中大多数出现在 megaco 应用程序的大型模块中 , 还有一些出现在其他宏中 , 比如 xmerl_uri 。
未使用的参数Hank 还发现了 2000 多个函数带有未使用的参数 。 其实有些不是真正的错误 , 但有些值得仔细检查 。
比如这个例子:
(https://github.com/erlang/otp/blob/6378a0c825db64df91e01ee39e3a268f4ba050b7/lib/inets/src/http_lib/http_uri.erl#L257-L266) , 该参数从未使用过第一个参数 。
文章参考链接:https://tech.nextroll.com/blog/dev/2021/01/06/erlang-rebar3-hank.html分页标题#e#


    来源:(编程CPP)

    【】网址:/a/2021/0128/kd651151.html

    标题:删除|你写的代码是死代码吗?如何判断和清理,一招搞定~


    上一篇:离岸人民币|美元指数大涨0.6%,在岸和离岸人民币双双跌超200点

    下一篇:bilibili|同个视频,微博上热搜,B站被限流,B站用户凭啥看不起其他平台?


    人文

    花椒|川菜和湘菜有什么区别呢?

    阅读(35)

    文章图片 两大菜系都博大精深,历史悠久,较明显的区别体现在以下几点:味型:川菜以麻辣为主,同时 ,因使用调料种类众多,所以烹制出来的味型也较多,比如有:麻辣味型、酸辣味型、红油味型、怪味味型等,多达24种味型,所以有句话叫:“食在广东,味在四...

    人文

    宜业成|成都将在7月下旬发放超过200万个消费券包

    阅读(23)

    作为成都今年下半年的重磅促消费活动,“成都美好生活夏季购物节”联动市级相关部门、各区(市)县政府、消费相关行业商协会、消费市场主体企业、消费类资源平台积极参与。文、商、旅、体等多领域企业共同加入,精选策划了八大领域活动。成都市商务局相关负责...

    人文

    事件|北京西城区发生伤医事件,作案者已被刑拘

    阅读(30)

    【事件|北京西城区发生伤医事件,作案者已被刑拘】 北京市公安局西城分局@西城警讯 5月28日消息:2020年5月28日9时许 , 在北京大学第一医院第二住院部一医生办公室内 , 患者家属谷某月(女 , 32岁)因对手术安排不满 , 将与其沟通解答的医生打伤 。 接报...