Tom*_*man 21 ruby ruby-on-rails
在他的RailsConf演讲中大约19:00 ,David Heinemeier Hansson谈到了以下方面的缺点instance_eval
:
很长一段时间我咆哮并且反对
instance_eval
,这是不使用屈服参数(如do |people|
)的概念,只是直接do something
然后评估你来自哪个范围内的那个块里的东西(我甚至不知道那是不是连贯的解释)很长一段时间我都不喜欢这样,因为从某种意义上说它感觉更复杂.如果你想把你自己的代码放在那里你会触发已经存在的东西吗?你要覆盖一些东西吗?当你产生一个特定的变量时,你可以将所有东西都链接起来,你可以知道[你]并没有搞乱其他人的东西
这听起来很有趣,但是a)我不知道如何instance_eval
在第一时间起作用和b)我不明白为什么它可能是坏的/增加复杂性.
谁能解释一下?
Jör*_*tag 31
这样instance_eval
做的是它在不同实例的上下文中运行块.换句话说,它改变了意义,self
这意味着它改变了实例方法和实例变量的含义.
这会产生认知断开:块运行的上下文不是它在屏幕上显示的上下文.
让我用@Matt Briggs的例子稍微改变一下来证明这一点.假设我们正在构建电子邮件而不是表单:
def mail
builder = MailBuilder.new
yield builder
# executed after the block
# do stuff with builder
end
mail do |f|
f.subject @subject
f.name name
end
Run Code Online (Sandbox Code Playgroud)
在这种情况下,@subject
是的实例变量的对象和name
是的方法的类.您可以使用漂亮的面向对象分解并将主题存储在变量中.
def mail &block
builder = MailBuilder.new
builder.instance_eval &block
# do stuff with builder
end
mail do
subject @subject
name name # Huh?!?
end
Run Code Online (Sandbox Code Playgroud)
在这种情况下,@subject
是邮件构建器对象的实例变量!它甚至可能不存在!(或者更糟的是,它可能存在并包含一些完全愚蠢的值.)有没有办法让你可以访问你的对象的实例变量.你怎么称呼name
对象的方法呢?每次尝试调用它时,都会获得邮件构建器的方法.
基本上,instance_eval
很难在DSL代码中使用自己的代码.因此,它实际上应该仅用于可能需要这种情况的机会.
Mat*_*ggs 17
好的,所以这里的想法不是这样的
form_for @obj do |f|
f.text_field :field
end
Run Code Online (Sandbox Code Playgroud)
你得到这样的东西
form_for @obj do
text_field :field
end
Run Code Online (Sandbox Code Playgroud)
第一种方式非常简单,你最终会得到一个看起来像这样的模式
def form_for
b = FormBuilder.new
yield b
b.fields.each |f|
# do stuff
end
end
Run Code Online (Sandbox Code Playgroud)
你产生了一个构建器对象,消费者在其上调用方法,然后调用构建器对象上的方法来实际构建表单(或其他)
第二个更神奇
def form_for &block
b = FormBuilder.new
b.instance_eval &block
b.fields.each |f|
#do stuff
end
end
Run Code Online (Sandbox Code Playgroud)
在这一个中,我们不是将构建器放到块中,而是在构建器的上下文中对块进行评估
第二个增加了复杂性,因为你喜欢玩范围游戏,你需要了解它,消费者需要理解这一点,而编写你的构建者的人需要理解这一点.如果每个人都在同一个页面上,我不知道这在某种程度上是一件坏事,但我确实质疑成本与成本之间的关系,我的意思是,仅仅强调f是多么困难.在你的方法面前?
归档时间: |
|
查看次数: |
4230 次 |
最近记录: |