从实战项目总结的Ruby小技巧(第四部分)

从我们在Global Personals项目中使用Github并且following Github Flow开始到现在已经将近两年的时间。在这段时间中,我们以很高的频率提交了上千次的pull请求,虽然没有太多如何改善或提高程序的建议和想法,但是我仍获得了如此广泛和珍贵的经验。其中,有一些建议是和项目相关的,同时,也包含了大量可以在团队内分享的Ruby开发小技巧。

由于我担心将从这个项目中获得和学习到的如此珍贵的技巧和经验所遗忘,于是我挑出了其中最好的最有价值的部分和大家分享,同时进行了一点小小的扩展。每个人都有自己的工作方式和风格,所以我会简洁明了地和大家阐述。并不是每部分内容对每个人来说都是新的,但是希望你在这里可以或多或少都有所收获。

这是Ruby小技巧系列的第四部分,这些技巧是我们从过去两年的实战经验中所收获的。

 

调试(Debugging)

Rails控制台(Rails console)对于交互式调试非常有用,这种方式对于非rails应用来说也是非常方便的。通过stdlib中的irb,让你的项目启动并运行变得出奇的简单。

这个例子假设你将代码放到了lib/目录下,并且你的项目明确指出可以通过require加载所有代码。

我增加了一个设置Sequel数据库连接的例子,你可以使用你需要的初始化设置的代码去替换它,或者仅仅是将它移除。如果你不使用Bundler,你也可以移除require "bundler/setup"

将上面的代码保存到项目的根目录并命名为console,同时在命令行输入chmod +x console使文件变为可执行的。现在,你可以通过运行项目根目录下的./console文件来开启一个控制台。

任何在IRB.start之前声明的方法,实例变量,以及常量在整个控制台会话期间都是可用的。但是它会创建一个新的作用域,因此局部变量是不可用的。之后的语句将会在退出时执行。

当你在控制台调试时,irb将输出在每个表达式值执行结果上调用方法#inspect的结果。通过这会给你一个美观的,低层次的展现方法,这对调试非常有用。然而,对于浮点数(Floats)这并不会十分有用。由于Ruby(以及大多数编程语言)需要根据你的指定来显示精确的值,因此,一种显示浮点数精确的值的方式是使用sprintf

其他的一些时候,你会遇到相反的问题,#inspect的输出结果对于你所期望的过于模糊。

在这种情况下,你可以在当前的测试中或控制台脚本中重新定义类的#inspect实例方法来返回一些更加直观的内容。

出于同样的原因,在你自己的类中实现#inspect方法也是非常有帮助的。

有时候你想要调试一个bug,但是却得到两个非常相似的输出结果。你肯定不愿意通过输出的结果自己寻找bug。但是,如果你把每个输入结果保存到文件中,使用diff命令查看又是非常费劲的,尤其是当你做连续的修改,边运行边调试的时候。幸运地,在Ruby标准库中有一个diff方法可以方便的进行操作。

输出:

作为一种高度动态语言,可以允许你在任何时间改变任何东西,有时候在Ruby中找到一个方法真正定义的地方是非常令人迷惑的,Ruby可以为你记录这些信息。

上面的结果显示,Array实例中的#to_set方法来自Enumerable模块,但是它被真正定义的地方是在标准库(stdlib)中set.rb文件中的第635行。

 

项目布局(Project Layout)

Ruby总没有统一的方式构建程序的布局,但是如果你将代码按gem包的方式构建将会是一种很好的方式,同时也便于其他项目使用。

RubyGems将每一个gem的文件夹路径增加到加载路径(load path)中。你不会希望这个路径成为项目的根路径,由于你希望其他的一些附属文件(Gemfile, tests, build scripts等)在gem对于其他的用户是可用的。在这种情况下,通常将你的代码放到lib文件夹下,并且在gemspec文件中设置require_path指向lib

现在,在lib文件夹中的文件都可以通过require "name"来加载。这通常工作的很好,对于核心类和模块。但是假设你有一个名为api.rb的文件,这是一个常见的命名有可能和其他的gem或者其他用户的代码发生冲突。由于这个原因,一个好的做法是在lib文件夹下建立一个单独的主文件,然后再将其他的代码放到以主文件名称命名的文件夹中。

其他一些附属的文件可以放到根目录下,同时大多数人也会在根目录下建立testspec)目录。

通常你会每个类使用一个文件,以类的名字命名文件,以下划线的方式而不使用驼峰式。在lib下的文件夹和命名空间相匹配,因此文件lib/my_project/foo.rb中的内容结构如下:

 

我经常会有一些文件不会直接映射到一个类,文件lib/my_project/errors.rb包含项目所有的异常类,文件lib/my_project/constants.rb包含项目所有的常量。

没有必要严格遵守 “一个文件一个类的规则”,如果你只是有一些小的帮助类被另外一个所使用,完全可以将它们放在一起。

当你在项目中包含文件时,你需要使用require_relativerequire是一种加载gems以及标准库(stdlib)文件的很好的方式,但是它只会从全局变量$:$LOAD_PATH)搜索文件,你并不能明确要加载的文件。require_relative总是从当前文件所在的目录开始搜索文件,不管怎样总是能找到相同的文件。在测试中非常有用,你总是能明确你测试的是哪些代码。

通常一种很好的做法是在lib/my_project.rb文件中加载所有的类,至少是核心类。通过这种方式,如果将代码带包为一个gem或者写测试,脚本等的时候,可以通过一个“入口文件”加载所有的类。

 

文档(Documentation)

Ruby包含丰富的文档,还有一个好用的搜索小工具ri。它的使用非常简单,只需要在命令行运行ri。当它运行之后,输入一个类名之后,你可以得到一个类的概要介绍和方法列表。你可以输入ClassName.method查看类方法,输入ClassName#method查看实例方法。

所有安装的gem都可以通过ri查看文档,如果它的作者撰写了相关文档。

你也可以运行gem server,通过http://0.0.0.0:8808查看gem的文档。

你可以使用rdoc来为你自己的代码构建文档,只需要将代码的文件夹和一些附加的文件传递给rdoc。它将输出一个doc目录,使用浏览器打开doc/index.html即可看到生成的内容。

像上面一样会生成类和方法的概述,但是你可以生成对别人更加有用的文档,通过使用rdoc格式的注释。下面的这些注释,rdoc将输出为类和方法的描述。

下一部分很快会和大家见面……

1 2 收藏 评论

关于作者:geekerzp

Ruby Geek (新浪微博:@geekerzp) 个人主页 · 我的文章

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部