从我们在Global Personals项目中使用Github并且following Github
Flow开始到现在已经将近两年的时间。在这段时间中,我们以很高的频率提交了上千次的pull请求,虽然没有太多如何改善或提高程序的建议和想法,但是
我仍获得了如此广泛和珍贵的经验。其中,有一些建议是和项目相关的,同时,也包含了大量可以在团队内分享的Ruby开发小技巧。
由于我担心将从这个项目中获得和学习到的如此珍贵的技巧和经验所遗忘,于是我挑出了其中最好的最有价值的部分和大家分享,同时进行了一点小小的扩
展。每个人都有自己的工作方式和风格,所以我会简洁明了地和大家阐述。并不是每部分内容对每个人来说都是新的,但是希望你在这里可以或多或少都有所收获。
我将文章分为了几块内容,以免你一口气读完5000个字,同时将它们归类为几个部分以便于参考。
- 代码块(Blocks) 和 区间(Ranges)
- 重构(Destructuring) 和 转换方法(onversion Methods)
- 异常(Exceptions)和模块(Modules)
- 调试(Debugging),项目结构(Project Layout)和文档(Documentation)
- 其他(Odds and Ends)
让我们进入第一部分。
代码块(Blocks)
代码块是Ruby非常重要的一部分,你随处都见到它们被广泛使用。如果你没有使用,那么你将发现许多人使用方法关联代码块,甚至仅仅是让代码结构变得清晰而已。
代码块有三种主要的作用:循环(looping),初始化和销毁(setup and teardown),以及回调和延迟执行(callbacks or
deferred action)。
下面这个例子演示了如何使用代码块循环输出菲波那切数列。它使用block_given?方法判断是否关联了一个代码块,否则将从当前方法返回一个枚举器。
yield关键字用来在方法中执行一个代码块,它的参数将传递给代码块。当代码块执行完毕,将返回调用方法,并执行下一行代码。方法返回值为在最大数(max)之前的最后一个菲波那切数。
- def fibonacci(max=Float::INFINITY)
- return to_enum(__method__, max) unless block_given?
- yield previous = 0
- while (i ||= 1) < max
- yield i
- i, previous = previous + i, i
- end
- previous
- end
- fibonacci(100) {|i| puts i }
下一个例子将把设置、销毁以及错误处理等操作代码放到方法中,将方法的主要逻辑放到代码块中。通过这种方式,样板代码就不需要在多个地方重复,另外当你需要改变错误处理代码时,只需要做少量的修改。
yield语句的返回结果,即代码块的返回值,将保存到一个局部变量中。这样,可以将代码块的执行结果作为方法的返回值。
- require "socket"
- module SocketClient
- def self.connect(host, port)
- sock = TCPSocket.new(host, port)
- begin
- result = yield sock
- ensure
- sock.close
- end
- result
- rescue Errno::ECONNREFUSED
- end
- end
- # connect to echo server, see next example
- SocketClient.connect("localhost", 55555) do |sock|
- sock.write("hello")
- puts sock.readline
- end
下一个例子不会使用yield关键字。这里有另外一种使用代码块的方法:将‘&’作为方法最后一个参数的前缀,将把关联代码块作为一个Proc对
象保存到此参数当中。Proc对象拥有一个call实例方法,可以用来执行代码块,传递给call方法的参数将作为代码块的参数。在这个例子中,你可以保
存代码块最为一个回调稍后执行,或者在你需要的时候执行延迟的操作。
- require "socket"
- class SimpleServer
- def initialize(port, host="0.0.0.0")
- @port, @host = port, host
- end
- def on_connection(&block)
- @connection_handler = block
- end
- def start
- tcp_server = TCPServer.new(@host, @port)
- while connection = tcp_server.accept
- @connection_handler.call(connection)
- end
- end
- end
- server = SimpleServer.new(5555)
- server.on_connection do |socket|
- socket.write(socket.readline)
- socket.close
- end
- server.start
区间(Ranges)
区间在Ruby代码中也很常见,通常区间的形式是(0..9),包含0到9之间的所有数字,包括9。也有另一种形式(0…10),包含0到10之间的所有数字,不包括10,即和前一种形式都包含0到9之间的所有数字,包括9。这种形式并不常见,但有时却非常有用。
有时候你会看到像这样的代码:
- random_index = rand(0..array.length-1)
使用不包含结尾的区间将更加整洁:
- random_index = rand(0...array.length)