如何設計出漂亮的 Ruby APIs

Python012

如何設計出漂亮的 Ruby APIs,第1张

1.Argument Processing

Ruby 使用了 Symbols 和 Hash 来达到虚拟关键字参数(Pseudo-Keyword Arguments)。这种技巧被广泛应用在 Ruby 的函式库和 Rails 中,增加了阅读性,也很容易使用。

def blah(options)

puts options[:foo]

puts options[:bar]

end

blah(:foo =>"test", :bar =>"test")

Ruby 也可以将参数列当成阵列使用:

def sum(*args)

puts args[0]

puts args[1]

puts args[2]

puts args[3]

end

sum(1,2,3)

如此就可以设计出不固定参数列、十分弹性的 API。类似於 C++ 的 function overloading。在 Rails 中也十分常见这样的 API 设计,例如 link_to 就支援了两种用法:

# USAGE-1 without block

<% link_to 'Posts list', posts_path, :class =>'posts' %>

# USAGE-2 with block

<% link_to posts_path, :class =>'posts' do %>

Posts list

<% end %>

搭配虚拟关键字参数使用的话,可以参考 ActiveSupport#extract_options! 这个小技巧取出 Hash 值。

2. Code Blocks

程式区块(Block)是 Ruby 最重要的特色,除了拿来做迭代(Iteration)之外,也可以包装前後置处理(pre- and Post-processing),一个最基本的例子就是开档了,一般程序式的写法如下:

f = File.open("myfile.txt", 'w')

f.write("Lorem ipsum dolor sit amet")

f.write("Lorem ipsum dolor sit amet")

f.close

使用 Block 之後,我们可以将 f.close 包装起来,不需要明确呼叫。只要程式区块结束,Ruby 就会自动关档。程式一来因为缩排变得有结构,二来也确定档案一定会关闭(不然就语法错误了)

# using block

File.open("myfile.txt", 'w') do |f|

f.write("Lorem ipsum dolor sit amet")

f.write("Lorem ipsum dolor sit amet")

end

另一个程式区块的技法,是用来当做回呼(Dynamic Callbacks)。在 Ruby 中,程式区块也是物件,於是我们可以将程式区块如透过”注册”的方式先储存下来,之後再依照需求找出来执行。例如在 Sinatra 程式中:

get '/posts' do

#.. show something ..

end

post '/posts' do

#.. create something ..

end

我们”注册”了两个回呼:一是当浏览器送出 GET ‘/posts’ 时,会执行 show something 的程式区块,二是 POST ‘/posts’ 时。

3. Module

模组(Module)是 Ruby 用来解决多重继承问题的设计。其中有一招 Dual interface 值得一提:

module Logger

extend self

def log(message)

$stdout.puts "#{message} at #{Time.now}"

end

end

Logger.log("test") # as Logger’s class method

class MyClass

include Logger

end

MyClass.new.log("test") # as MyClass’s instance method

Ruby 的 extend 作用是将模组混入(mix-in)进单件类别(singleton class),於是 log 这个方法除了可以像一般的模组被混入 MyClass 中使用,也可以直接用 Logger.log 呼叫。

要将 Ruby 模组的混入成类别方法(class method),也有一些常见的 pattern 模式,可以将模组设计可以同时混入实例方法(instance method)和类别方法,请参阅投影片范例。这在撰写 Rails plugin 时非常常用。

4. method_missing?

Ruby 的 Missing 方法是当你呼叫一个不存在的方法时,Ruby 仍然有办法处理。它会改呼叫 method_missing 这个方法,并把这个不存在的方法名称传进去当做参数。这个技巧在 Rails 的 ActiveRecord 中拿来使用:

class Person <ActiveRecord::Base

end

p1 = Person.find_by_name("ihower")

p2 = Person.find_by_name_and_email("ihower", "[email protected]")

其中 find_by_name 和 find_by_email 就是这样的方法。不过这个技巧不是万能丹,它的执行效率并不好,所以只适合用在你没办法预先知道方法名称的情况下。不过也不是没有补救之道,如果同样的方法还会继续呼叫到,你可以在 method_missing 之中用 define_method 或 class_eval 动态定义此方法,那麼下次呼叫就不会进来 method_missing,进而获得效能的改善。事实上,ActiveRecord::Base 的 method_missing 就是这麼做的。(感谢 BigCat 留言提醒我有此补救之道)

另一个 Missing 方法的绝妙 API 设计,是拿来构建 XML 文件:

builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)

builder.person do |b|

b.name("Jim")

b.phone("555-1234")

b.address("Taipei, Taiwan")

end

# <person>

# <name>Jim</name>

# <phone>555-1234</phone>

# <address>Taipei, Taiwan</address>

# </person>

搭配了区块功能,就能用 Ruby 语法来写 XML,非常厉害。

5. const_missing

除了 method_missing,Ruby 也有 const_missing。顾名思义就是找不到此常数时,会呼叫一个叫做 const_missing 的方法。现实中的例子有 Rails 的 ActiveSupport::Dependencies,它帮助我们不需要先载入所有类别档案,而是当 Rails 碰到一个还不认识的常数时,它会自动根据惯例,找到该档案载入。

我们也可以利用这个技巧,针对特定的常数规则来处理。例如以下的程式会自动将 U 开头的常数,自动转译成 Unicode 码:

class Module

original_c_m = instance_method(:const_missing)

define_method(:const_missing) do |name|

if name.to_s =~ /^U([0-9a-fA-F]{4})$/

[$1.to_i(16)].pack("U*")

else

original_c_m.bind(self).call(name)

end

end

end

puts U0123 # ģ

puts U9999 # 香

6. Methods chaining

方法串接是一个很常见的 API 设计,透过将方法的回传值设成 self,我们就可以串接起来。例如:

[1,1,2,3,3,4,5].uniq!.reject!{ |i| i%2 == 0 }.reverse

# 5,3,1

7. Core extension

Ruby 的类别是开放的,可以随时打开它新增一点程式或是修改。即使是核心类别如 Fixnum 或是 Object(这是所有类别的父类别) 都一样。例如 Rails 就定义了一些时间方法在 Fixnum 里:

class Fixnum

def hours

self * 3600 # 一小时有多少秒

end

alias hour hours

end

Time.now + 14.hours

Ruby 的物件模型与元编程(Meta-programming)

在 Ruby 中,所有东西都是物件。甚至包括类别(class)本身也是物件。这个类别物件(class object)是一个叫做 Class 的类别所实例出来的物件。而所有的物件(当然也包括类别物件),都有一个 metaclass (又叫做 singleton, eigenclass, ghost class, virtual class 等名字)。定义在 metaclass 里的方法,只有该物件能够使用,也就是 singleton method (单件方法),只有该物件才有的方法。

了解什麼是 metaclass 是 Ruby 元编程的一个重要前提知识。Ruby 元编程最常用的用途,就是因应需求可以动态地定义方法,例如在 Rails ActiveRecord 中常见的 Class Macro 应用。

要能随心所欲动态定义方法的关键重点,就是 variable scope (变数的作用域) 了。例如以下我们透过 class_eval 和 define_method 帮 String 定义了一个 say 方法,注意到整个 variable scope 都是通透的,没有建立新的 scope:

name = "say"

var = "it’s awesome"

String.class_eval do

define_method(name) do

puts var

end

end

"ihower".say # it’s awesome

class_eval 可以让我们改变 method definition 区域(又叫做 current class)。除了本投影片,建议可以阅读 Metaprogramming in Ruby: It’s Allhe Self 和 Three implicit contexts in Ruby 这两篇文章深入了解 self 和 current class。

8. Class Macro (Ruby’s declarative style)

Class Macro 是 Ruby Meta-programming 非常重要的一个应用,例如在 Rails ActiveRecord 中:

class User <ActiveRecord::Base

validates_presence_of :login

validates_length_of :login,:within =>3..40

validates_presence_of :email

belongs_to :group

has_many :posts

end

编程语言的分类主要有:JavaScript、PHP、C、C++、java。

1、C语言:实模式、保护模式、调度、中断、调用栈、回调……基本上计算机科学里面的基本概念都会涉及。结构化编程,即将解决方案描述为一个清晰的过程,这其中会涉及数据的建模,接口的定义,项目整体的组织结构。

2、c++语言:虚函数、虚表、内联、多继承、const、泛型、模板(语言相关)opencv、OGRE、3D渲染、GPU、mesh、skeleton、帧循环、DX、GUI、MFC、Qt、消息队列、非阻塞IO。适合领域:多媒体、高性能网络服务器等较讲究效率的应用程序。

3、java:字节码、虚拟机、垃圾回收、接口、多线程、包、程序库、反射、框架、集成、组件、http、web、数据库、SSH、javaee。java的程序比较讲究扩展性和可维护性,一般会使用比较多的设计模式,常用的程序组织形式是MVC、监听者模式等。

4 、Javascript:闭包、对象、函数、CSS、DOM、Ajax、HTML5、node.js、V8。基于prototype的OO,以及基于闭包的函数式编程(后者用的更多)。常用代码组织形式:事件触发的回调机制(node.js与前端的区别是其自己定义、触发事件)、基于非阻塞异步IO的框架(node.js)。

5、PHP即“超文本预处理器”,是一种通用开源脚本语言。PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言。PHP独特的语法混合了C、Java、Perl以及 PHP 自创的语法。利于学习,使用广泛,主要适用于Web开发领域。

参考资料来源:百度百科—编程语言

福猪噜比Ruby商品说明;

福猪噜比(Ruby)独特可爱的造型是由著名的雕塑家及卡通创意大师共同精心设计,它采用高科技的语音识别技术,并有很高的识别效果,它是集喜、怒、哀、乐,调皮,捣蛋又善解人意为一身的高智能人性化电子宠物。它能唱会跳更会讲故事,由微电脑芯片控制的尾巴、鼻子、嘴巴及行走的动作人见人爱。它的闹钟,录音留言功能更是具有超高的实用价值!解读星座,戏说运气更是福猪噜比(Ruby)的拿手好戏!福猪噜比(Ruby)将是六十年一遇的金猪年最好的礼物!

1、特 点:会唱歌、跳舞、录音留言、闹钟提醒、准确报时、触摸发音、方向感知、语音对话、解释星座、讲故事、讲笑话。

2、体 积:长 28 CM X 15 CM * 高 15 CM

3、重 量: 500 克

4、产品包括:福猪噜比 、合格证、保修凭证、

赠 品: 福猪专用配件包,金猪年福猪纳福小秘笈,限量版豪华聚财山庄等。

5、 供能模式: 3 节5号干电池。(装入3节5号电池,注意正、负极)

6、 耗电情况: 3节电池可以用2个星期左右。

录音留言:将你想说的话录下来让福猪噜比( Ruby )来传递;

同时按住左右耳按键持续 3 秒,语音提示“进入录音留言状态,您有 30 秒时间,听到嘀声后开始录音,确认请按我的左耳,需重新录制请按我的右耳,嘀”,录音结束按左耳键确认,超过 30 秒时间录音将自动确认,放音按右耳键即可,如重新录制留言将删除上一段录音。

闹钟提醒:福猪噜比( Ruby )可以按你所设置的时间“风趣”的叫醒你;

闹铃设定方法:开机状态下按右耳键持续 3 秒后,语音提示 “进入闹铃设置状态,确认请按右耳,重新设置请按左耳,(报原闹铃时间)”。

保留原闹铃时间:按右耳键即可;

重新设置:按左耳键,首先设置小时数,按左耳键递增,右耳键递减, 3 秒钟后自动确认;同法设置分钟数, 福猪噜比( Ruby ) 将准时“幽默、风趣”地闹醒你。(懒猪起床!懒猪起床!我来看猪 .. 猪在床上 ……

假如小朋友不按时睡觉,他会提醒小朋 友睡觉,告诉小朋友不要吵啦等等,每天早上福猪“噜比”可以替代父母叫醒儿童,更容易被儿童所接受,可以养成小朋友不赖床的良好生活习惯。也可以减少大人不少麻烦。 “噜比”到时间就睡觉给孩子树立了好榜样,可以帮助儿童养成按时起床的好习惯。

准确报时:

在关机状态下可以按左耳键报时,开机状态可以按左耳键或直接语音询问:“几点了” 福猪噜比( Ruby )将准确报时。

全天候报时(现在是七点 不浪费一分一秒 这是猪的至理名言 ……… )

可以增强小孩子的时间观念。这样小朋友就可以更好更有效的利用时间,合理的学习和娱乐啦。

唱儿歌:

( 1 )儿歌播放,无需任何按键,直接对福猪噜比( Ruby )说: “ 唱首儿歌吧 ” ,福猪噜比( Ruby )就会唱儿歌。完毕,可继续接“再来一个”,继续听不同的儿歌。

( 2 )若福猪噜比( Ruby )拒绝了你的要求,并提出帮你解读今天的运气或星座的时候,可继续接“好啊”或“不好”。

解释星座:把你的生日告诉它,它会解读你的星座,还能风趣的解读你的性格、爱好、成就呢,神奇吧!

( 1 )你可以直接说:“算算我的星座吧”

福猪噜比( Ruby ) 会说“好啊!告诉我你的生日吧!请按照说明提示,按按我的耳朵,请输入你的生日日期。”

( 2 )或者福猪噜比( Ruby )说:“我给你算算星座吧!”这时你只要回答它:“好啊!”福猪噜比( Ruby )语音提示:“告诉我你的生日吧!请按照说明提示,按按我的耳朵,请输入你的生日日期。”

( 3 )输入生日:

A .按照福猪噜比( Ruby )语音提示按左耳键递增,按右耳键递减,设置年, 3 秒钟后自动确认。

B. 继续语音提示“设置月” “设置日”,同法依次设置;

( 4 )正确的输入生日后你会得到福猪噜比( Ruby )对于你星座的独特解读:“哇 ~` !你是狮子座,狮子座的你 … ”

( 5 )有意思吧,福猪噜比( Ruby )的解读方式更是与众不同,即使你遇到同年同月的知己,福猪噜比( Ruby )的解读内容也会不断变换、丰富多彩哦 ~ !

声音信号与福猪噜比( Ruby )的反应功能:

( 1 )如果你不跟福猪噜比( Ruby )说话 , 5 分钟内它会主动和你交谈或自言自语, 5 分钟后再没有声音信号输入 福猪噜比( Ruby ) 进入潜睡模式,按任意键便可进入游戏模式。

( 2 )如果 福猪噜比( Ruby ) 没有识别出您说的话,他会有相应提示。例如: “ 阿嚏,这是我今天第一百零一个喷嚏,你刚才说什么”等。 如果 福猪噜比( Ruby ) 听到的是噪声或者同时有很多人跟他说话, 福猪噜比( Ruby ) 就会视它心情而定说 相应的话。

讲笑话:

直接对福猪噜比( Ruby )说:“讲个笑话听听。” 福猪噜比( Ruby )就会讲笑话,完毕,可以对它说:“再来一个”,继续听不同的笑话。

戏说运气:

直接对福猪噜比( Ruby )说:“我今天运气好吗?”便可,福猪噜比( Ruby )就会用它独特的方式戏说你当日的运程,当然是戏说,信不信由你,每天都不相同哦,快来试试吧!

互动功能:摸摸福猪噜比( Ruby )的头或提起它的尾巴,它会有喜、怒、哀、乐不同的表现,可逗了!

( 1 )摸摸福猪噜比( Ruby )的脑袋;

( 2 )拉住福猪噜比( Ruby )的尾巴,使福猪噜比( Ruby )倒挂在空中。

福猪噜比( Ruby )能真正做到与主人之间的互动,善解人意的它会让你有意想不到的收获哦!