善待Erlang 代码 -- Xref 实践
Xref 是一个交叉引用工具,通过分析定义的函数间的调用关系,用于查找函数、 模块、 应用程序和版本之间的依赖关系。
通俗而言,Xref 可以检查代码中函数的调用关系。比如在 moduleA 中的 funA 调用了moduleB 中的funB, 但是moduleB 中并未定义funB,此错误在代码编译期间不能被发现,但是可以通过Xref 检查。
栗子
使用reabr 创建一个application ,命名为xref_test,目录结构如下:
$ tree
.
├── ebin
│ ├── test.beam
│ ├── xref_test.app
│ ├── xref_test_app.beam
│ └── xref_test_sup.beam
├── rebar
├── src
│ ├── test.erl
│ ├── xref_test.app.src
│ ├── xref_test_app.erl
│ └── xref_test_sup.erl
└── xref.config directories, files
其中 test.erl 的代码为:
$ cat ./src/test.erl
-module(test).
-export([start/]).
start() ->
test_2:start().
在test module 中定义start/0 函数,其中调用了test_2:start/0 函数,但是此函数并没有定义。这种情况,必然会引发错误,但是在编译期间,并不能发现。
$ ./rebar com
==> xref_test (compile)
Compiled src/xref_test_app.erl
Compiled src/test.erl
Compiled src/xref_test_sup.erl
OK,上述执行是顺利完成的。但是在运行时,必然会发生错误。
> test:start().
** exception error: undefined function test_2:start/
那么,怎样才能在运行之前发现这个错误呢?Xref 就应该隆重登场了。
rebar xref
在rebar 中,集成了xref 工具,相关的配置信息如下:
{xref_warnings, false}.
%% optional extra paths to include in xref:set_library_path/.
%% specified relative location of rebar.config.
%% e.g. {xref_extra_paths,["../gtknode/src"]}
{xref_extra_paths,[]}.
%% xref checks to run
{xref_checks, [undefined_function_calls, undefined_functions,
locals_not_used, exports_not_used,
deprecated_function_calls, deprecated_functions]}.
%% Optional custom xref queries (xref manual has details) specified as
%% {xref_queries, [{query_string(), expected_query_result()},...]}
%% The following for example removes all references to mod:*foo/
%% functions from undefined external function calls as those are in a
%% generated module
{xref_queries,
[{"(XC - UC) || (XU - X - B"
" - (\"mod\":\".*foo\"/\"4\"))",[]}]}.
在rebar.config 文件中,配置好这些信息,执行:
$ ./rebar xref
==> xref_test (xref)
Warning: test_2:start/ is undefined function (Xref)
src/test.erl:: Warning: test:start/ calls undefined function test_2:start/ (Xref)
ERROR: xref failed while processing /Users/redink/erlang/test/xref_test: rebar_abort
这个时候,错误就能够清晰的看出来了。
xref_runner
xref_runner 是独立于rebar xref 的一个工具,支持在非rebar 组织的项目中使用xref ,友好度很高。
https://github.com/inaka/xref_runner
在rebar node 组织的Erlang release 中,可以使用xref_runner 方便的对apps 目录下的application 进行xref 检查。
xrefr.config 定义:
$ cat xrefr.config
[
{xref, [
{config, #{dirs => ["./apps/appname/ebin"],
extra_paths => [
"./deps/***/ebin"]}},
{checks, [
undefined_functions
, undefined_function_calls
, locals_not_used
%%, exports_not_used
, deprecated_function_calls
, deprecated_functions
]},
{xref_default, {verbose}}
]
}
].
总结
Xref 非常有用,能帮我们在运行之前尽快的发现代码的错误以及潜在的错误。
扩展阅读:
http://www.erlang.org/doc/apps/tools/xref_chapter.html
善待Erlang 代码 -- Xref 实践的更多相关文章
- 善待Erlang 代码 -- 巧用 user_default
这是一篇水文 ----------------------------------------------------- 很好用的一个技巧 http://www.erlang.org/doc/man/ ...
- HTML 代码复用实践 (静态页面公共部分提取复用)
原文:HTML 代码复用实践 上面的链接里面安装配置步骤已经非常详细,这里主要记录我操作过程中遇到的几个问题 gulp-file-include 的使用 按上面的步骤安装之后,node_mod ...
- Tsung脚本中使用动态参数(一)---直接在脚本里编写Erlang代码
杀死一个程序猿,只要改三次需求.同理,杀死一个接口自动化测试人员,只要改三次接口数据处理方式.我目前的状态,改了一次接口数据处理方式,有一种胸闷的感觉. 因为改需求,所以,要改脚本.T_T.所以,才有 ...
- elixir 调用erlang 代码
备注: 项目比较简单,主要是elixir 混合erlang 代码,elixir 调用erlang 模块方法 1. 初始化项目 mix new erlangelixirdemo 项目结构如 ...
- 理想的DevOp流程怎么做?看看Slack的代码部署实践 原创 Michael Deng 高可用架构 今天
理想的DevOp流程怎么做?看看Slack的代码部署实践 原创 Michael Deng 高可用架构 今天
- git 操作 :从远程仓库gitLab上拉取指定分支到本地仓库;git如何利用分支进行多人开发 ;多人合作代码提交实践
例如:将gitLab 上的dev分支拉取到本地 git checkout -b dev origin/dev 在本地创建分支dev并切换到该分支 git pull origin dev 就可以把git ...
- 敏捷开发中高质量 Java 代码开发实践
Java 项目开发过程中,由于开发人员的经验.代码风格各不相同,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入 和周期等问题. 这些问题在一个项目组初建.需 ...
- erlang代码片段
转载自http://blog.csdn.net/sw2wolf/article/details/6797708 .列表操作 lists:foreach(fun(X) -> io:format(& ...
- Android ------ 美团的Lint代码检查实践
概述 Lint是Google提供的Android静态代码检查工具,可以扫描并发现代码中潜在的问题,提醒开发人员及早修正,提高代码质量.除了Android原生提供的几百个Lint规则,还可以开发自定义L ...
随机推荐
- POJ 3422 Kaka's Matrix Travels(拆点+最大费用流)题解
题意:小A从左上角走到右下角,每个格子都有一个价值,经过这个格子就把价值拿走,每次只能往下或往右走,问你走k次最多能拿多少价值的东西. 思路:这里有一个限制条件就是经过之后要把东西拿走,也就是每一格的 ...
- autofac 在webapi中拿到当前request的scope
https://stackoverflow.com/questions/31321386/autofac-web-api-get-current-scope Unless you are usin ...
- autofac &web api 切换数据库
https://stackoverflow.com/questions/24188025/is-there-another-way-of-changing-database-instance-in-a ...
- Cache与主存地址映像计算例题
一.全相连映像 主存中任何一个块均可以映像装入到Cache中的任何一个块的位置上.主存地址分为块号和块内地址两部分,Cache地址也分为块号和块内地址.Cache的块内地址部分直接取自主存地址的块内地 ...
- POJ 3468 A Simple Problem with Integers(线段树:区间更新)
http://poj.org/problem?id=3468 题意: 给出一串数,每次在一个区间内增加c,查询[a,b]时输出a.b之间的总和. 思路: 总结一下懒惰标记的用法吧. 比如要对一个区间范 ...
- ref用于类类型
static void Main(string[] args) { Fruit f = new Fruit() { Weight = 1, Color = "&qu ...
- hdu 5701 中位数计数 思路题
中位数计数 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- python 获取5天前的日期
from datetime import date, timedelta dt = date.today() - timedelta() print('Current Date :',date.tod ...
- JSP 表单处理
JSP 表单处理 我们在浏览网页的时候,经常需要向服务器提交信息,并让后台程序处理.浏览器中使用 GET 和 POST 方法向服务器提交数据. GET 方法 GET方法将请求的编码信息添加在网址后面, ...
- UVA-536 Tree Recovery (二叉树遍历)
题目大意:给出对一棵二叉树先序遍历和中序遍历的顺序,找出后序遍历的顺序. 题目分析:无非就是对字符串的输出顺序做个变化,递归就行了. 代码如下: # include<iostream> # ...