作為開發者的你平時作業時是怎么判斷并清理死代碼的?也許你猜到了這篇文章要講什么,
是的,我們是有一些清理死代碼的好方法推薦給你……在認真考慮了各種自動化工具之余,我們還希望能夠遍歷所有的代碼,分析每一個 .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(X,rand: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").
-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_macros
Hank 還有一條規則,它將檢測專案中未使用的宏,這些宏可能定義在了源代碼中的任何檔案中,但是從未使用,因此,這些宏都是沒有必要的,可以洗掉,
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
如果你正在自學編程,正在敲代碼,不防和我們一起交流學習,避免走很多彎路~
我們給你提供:
1、海量學習大禮包免費領取
2、同行之間的交流學習
3、多年編程經驗大佬在線教學、解答問題
4、如何獲取——《+Q裙:1151395975免費領取》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/253422.html
標籤:其他
