我是一个试图遵循那些来到我面前的人的DRY方法的铁杆菜鸟。 我知道我做错了什么 - 我只是不确定那是什么或如何克服它。
基本上,我的问题是如何让这段代码更加面向对象?
我有一个类Podcast,此时它只包含一堆类方法,可以从网络上搜集各种数据。
因此,例如,此类方法尝试从其网站发现播客推特或Facebook提要:
def self.social_discovery(options = {})
new_podcasts_only = options[:new_podcasts_only] || false
if new_podcasts_only
podcast = Podcast.find(:all, :select => 'id, siteurl, name', :conditions => ['created_at > ? and siteurl IS NOT ?', Time.now - 24.hours, nil])
Podcast.podcast_logger.info("#{podcast.count}")
else
podcast = Podcast.find(:all, :select => 'id, siteurl, name', :conditions => ['siteurl IS NOT ?', nil])
end
podcast.each do | pod |
puts "#{pod.name}"
begin
# Make sure the url is readable by open-uri
if pod.siteurl.include? 'http://'
pod_site = pod.siteurl
else
pod_site = pod.siteurl.insert 0, "http://"
end
# Skip all of this if we're dealing with a feed
unless pod_site.downcase =~ /.rss|.xml|libsyn/i
pod_doc = Nokogiri.HTML(open(pod_site))
pod_name_fragment = pod.name.split(" ")[0].to_s
if pod_name_fragment.downcase == "the"
pod_name_fragment = pod.name.split(" ")[1].to_s unless pod.name.split(" ")[1].to_s.nil?
end
doc_links = pod_doc.css('a')
# If a social url contains part of the podcast name, grab that
# If not, grab the first one you find within our conditions
# Give Nokogiri some room to breathe with pessimistic exception handling
begin
begin
twitter_url = doc_links.find {|link| link['href'] =~ /twitter.com\// and link['href'].match(/#{pod_name_fragment}/i).to_s != "" unless link['href'] =~ /share|status/i}.attribute('href').to_s
rescue Exception => ex
if doc_links.find {|link| link['href'] =~ /twitter.com\// unless link['href'] =~ /share|status/i}.nil?
twitter_url = nil
else
twitter_url = doc_links.find {|link| link['href'] =~ /twitter.com\// unless link['href'] =~ /share|status/i}.attribute('href').to_s
end
end
begin
facebook_url = doc_links.find {|link| link['href'] =~ /facebook.com\// and link['href'].match(/#{pod_name_fragment}/i).to_s != "" unless link['href'] =~ /share|.event/i}.attribute('href').to_s
rescue Exception => ex
if doc_links.find {|link| link['href'] =~ /facebook.com\// unless link['href'] =~ /share|.event/i}.nil?
facebook_url = nil
else
facebook_url = doc_links.find {|link| link['href'] =~ /facebook.com\// unless link['href'] =~ /share|.event/i}.attribute('href').to_s
end
end
rescue Exception => ex
puts "ANTISOCIAL"
# Ensure that the urls gets saved regardless of what else happens
ensure
pod.update_attributes(:twitter => twitter_url, :facebook => facebook_url)
end
puts "#{twitter_url}" + "#{facebook_url}"
Podcast.podcast_logger.info("#{twitter_url}" + "#{facebook_url}")
end
rescue Exception => ex
puts "FINAL EXCEPTION: #{ex.class} + #{ex.message}"
end
end
end
同样,我知道这是糟糕的代码。请帮助我理解为什么? 我将永远为你负债。
谢谢,
哈里斯
答案 0 :(得分:2)
我在代码中看到的主要内容是代码重复。如果你仔细观察,获取twitter网址的代码和facebook网址的代码几乎完全相同,除了'twitter.com'和'facebook.com'部分。我的建议是将其拉出一个单独的方法,该方法将doc_links
变量作为参数以及用于查找链接的正则表达式。另外,我不太清楚为什么你在这里做“除非...”部分:
if pod_name_fragment.downcase == "the"
pod_name_fragment = pod.name.split(" ")[1].to_s unless pod.name.split(" ")[1].to_s.nil?
end
如果你不执行该行的“除非...”部分,则会定义pod_name_fragment但nil
,但如果你不包含它,如果你试图引用它将会出现异常到pod_name_fragment
。
此外,你几乎不应该拯救Exception
。请改用StandardError
。假设您的程序正在运行,并尝试使用Ctrl-C取消它。这引发了SystemExit
(我不是100%确定名称)异常,它是异常退出的子类。在大多数情况下,您会想立即退出。我知道这不适用于Rails应用程序,但我很确定还有其他原因可以捕获SystemError。
可能有更多,一种简单的方法来查找“错误代码”是指查看指标。 Ryan Bates在指标(http://railscasts.com/episodes/252-metrics-metrics-metrics)上做了一个很好的Railscast,我建议你特别看看Reek找到“代码味道”。检查他们的wiki,了解不同内容的含义。