Tell, don't ask 原则 Source: http://www.aqee.net/tell-dont-ask/
前些时间我曾经翻译过一篇叫做《这里我说了算!》的文章,里面作者讲述了关于“命令,不要去询问(Tell, Don’t Ask)”原则:
我看到的最多被违反的原则是“命令,不要去询问(Tell, Don’t Ask)”原则。这个原则讲的是,一个对象应该命令其它对象该做什么,而不是去查询其它对象的状态来决定做什么(查询其它对象的状态来决定做什么也被称作‘功能嫉妒(Feature Envy)’)。
这篇文章里有个很生动的例子,我至今记忆犹新:
if (person.getAddress().getCountry() == “Australia”) {
这违反了得墨忒耳定律,因为这个调用者跟Person过于亲密。它知道Person里有一个Address,而Address里还有一个country。它实际上应该写成这样:
if (person.livesIn(“Australia”)) {
非常的明了。今天我又看到一个关于“Tell, Don’t Ask”原则的文章,里面提供了4个关于这个原则的例子,都很有价值。
例一
不好:
<% if current_user.admin? %> <%= current_user.admin_welcome_message %> <% else %> <%= current_user.user_welcome_message %> <% end %>
好:
<%= current_user.welcome_message %>
例二
不好:
def check_for_overheating(system_monitor)
if system_monitor.temperature > 100
system_monitor.sound_alarms
end
end
好:
system_monitor.check_for_overheating
class SystemMonitor
def check_for_overheating
if temperature > 100
sound_alarms
end
end
end
例三
不好:
class Post
def send_to_feed
if user.is_a?(TwitterUser)
user.send_to_feed(contents)
end
end
end
好:
class Post
def send_to_feed
user.send_to_feed(contents)
end
end
class TwitterUser
def send_to_feed(contents)
twitter_client.post_to_feed(contents)
end
end
class EmailUser
def send_to_feed(contents)
# no-op.
end
end
例四
不好:
def street_name(user)
if user.address
user.address.street_name
else
'No street name on file'
end
end
好:
def street_name(user)
user.address.street_name
end
class User
def address
@address || NullAddress.new
end
end
class NullAddress
def street_name
'No street name on file'
end
end
好的面向对象编程是告诉对象你要做什么,而不是询问对象的状态后根据状态做行动。数据和依赖这些数据的操作都应该属于同一个对象。
命令,不要去询问!
本文深入探讨了面向对象编程中的“命令,不要去询问”原则,通过四个实例详细阐述了如何遵循这一原则以提高代码质量和可维护性。实例包括用户权限判断、系统监控、邮件发送和地址信息获取等场景。

1908

被折叠的 条评论
为什么被折叠?



