#10 Refactoring User Name Part 1
从这一集开始,我们一起探讨一下关于重构的话题。重构是指在不改变软件功能的前提下对代码进行优化,以达到去除冗余代码、提高代码可读性及可维护性的的目的。
下面页面是一个用户列表,点击用户名后显示用户资料。需要注意的是,有些用户有中间名(middle name)有些则没有。
浏览器中显示的列表页及用户资料页.
先看看列表页的代码:
<h1>Users</h1> <ul> <% for user in @users %> <li> <a href="<%= user_path(user) %>"> <%= user.first_name %> <%= "#{user.middle_initial}." unless user.middle_initial.nil? %> <%= user.last_name %> </a> </li> <% end %> </ul>
列表页代码
上面的代码先是获取所有的用户对象,进行循环。<a>标签中的三行代码用来显示用户名。接下来,是用户资料页面:
<h1>Profile</h1> <p> Name: <%= @user.first_name %> <%= "#{@user.middle_initial}." unless @user.middle_initial.nil? %> <%= @user.last_name %> </p> <%= link_to 'Users List', users_path %>
用户资料页代码
用户资料页面和列表页一样,也用三行代码显示用户名。很明显做了重复的工作,这里便成为我们的优化点。分析一下代码,其中第一行和第三行分别显示名称和姓氏;第二行是当有中间名时显示外加一个点,没有中间名的时候什么都不显示。
如何开始这次重构?
可以把这个通用逻辑抽取到一个工具方法中,但我觉得这三行逻辑与User
模型的关联更紧密些。所以应该将它们抽取到模型中更加合理。在User
类中增加一个名为full_name
的方法.将页面中的代码移动到这个方法中,给一个局部变量赋值并返回。
class User < ActiveRecord::Base def full_name name = first_name + ' ' name += "#{middle_initial}. " unless middle_initial.nil? name += last_name name end end
增加了full_name
方法的User
类
直接将代码拷贝到这里肯定是行不通的,@user
变量在User
类中不存在。我们需要把它去掉,因为这是一个实例方法,当前操作的对象就是这个用户本身。
检查重构是否正确。
该在页面中调用full_name
方法来替代之前的那三行代码。下面是修改后的列表页面代码。
<a href="<%= user_path(user) %>"> <%= user.full_name %> </a>
使用full_name
的列表页面代码。
代码依然还有提升的空间,创建超链接的<a>标签使用起来太麻烦,可以被Rails提供的link_to
方法替代。
<%= link_to user.full_name, user_path(user) %>
使用了link_to
方法的列表页面。
这样一来,页面代码是否变得清爽多了?我们去掉了冗余代码,又把本应该由模型负责的逻辑移到适当的位置。其实还有优化的余地,且听下回分解。
重构之后的代码
class User < ActiveRecord::Base def full_name name = first_name + ' ' name += "#{middle_initial}. " unless middle_initial.nil? name += last_name name end end
重构后的User
类。
<h1>Users</h1> <ul> <% for user in @users %> <li><%= link_to user.full_name %></li> <% end %> </ul>
重构后的列表页(index
)。
<h1>Profile</h1> <p>Name: <%= @user.full_name %></p> <%= link_to 'Users List', users_path %>
重构后的用户资料页(show
)。