有没有更优雅的方式来编写这个CoffeeScript?

时间:2013-02-07 22:38:07

标签: coffeescript

这是有效的,但有没有建议以更简化/更优雅的方式来写这个?:

if @mediaAddQueue[''+mid]['mediaType'] is 'photo' and
  @mediaAddQueue[''+mid]['econ_status'] is 'loaded' and
  @mediaAddQueue[''+mid]['medium_status'] is 'loaded' and
  @mediaAddQueue[''+mid]['thumb_status'] is 'loaded' and
  not @mediaAddQueue[''+mid]['targetEventRecord']?
    @addMedia @mediaAddQueue[''+mid]['targetEventRecord'], mid, @mediaAddQueue[''+mid]['mediaType']
else if @mediaAddQueue[''+mid]['mediaType'] is 'video' and
  @mediaAddQueue[''+mid]['video_status'] is 'loaded' and
  not @mediaAddQueue[''+mid]['targetEventRecord']?
    @addMedia @mediaAddQueue[''+mid]['targetEventRecord'], mid, @mediaAddQueue[''+mid]['mediaType']

3 个答案:

答案 0 :(得分:4)

当然可以。总有某些可以重构。

临时变量

@mediaAddQueue[''+mid]

无处不在。通过引入临时辅助变量来考虑重构:

elem = @mediaAddQueue[''+mid]

代码会突然变得更具可读性。

功能,功能,功能!

我看到你执行了一种特定类型的检查(我假设我们有elem变量):

elem['econ_status'] is 'loaded' and
elem['medium_status'] is 'loaded' and
elem['thumb_status'] is 'loaded'

您可以编写一个函数,它接受elem(或任何对象)并执行此检查,其参数是对象,要比较的值和对象的键。由于splats,这在咖啡中非常容易。

##
# Check whether all obj's keys are set to value.
checkAllKeys = (obj, value, keys...) ->
    for k in keys
        if obj[k] != value
           return false

    return true

现在之前的代码块将成为:

checkAllKeys(elem, 'loaded', 'econ_status', 'medium_status', 'thumb_status')

如果您知道经常检查“已加载”值,请自行创建另一项功能:

checkLoaded = (elem, keys...) ->
    checkAllKeys(elem, 'loaded', keys...)

如果经常一起检查'econ_status', 'medium_status', 'thumb_status'个密钥,那么即使是另外一个功能也可能是个好主意:

checkPhotoLoaded = (photo) ->
    checkLoaded(photo, 'econ_status', 'medium_status', 'thumb_status')

我的重构规则是,应该为所有重复两次以上的东西编写一个函数。 CoffeeScript使编写函数变得有趣而且快速。

我希望这会有所帮助。

答案 1 :(得分:3)

当然!首先,请注意@mediaAddQueue[''+mid]遍布整个地方,您可以用变量替换它。此外,如果属性具有有效的标识符作为名称,则无需访问something['prop']之类的属性;你可以做something.prop。改变这两件事已经很清楚了代码:

media = @mediaAddQueue[mid]

if media.mediaType is 'photo' and
  media.econ_status is 'loaded' and
  media.medium_status is 'loaded' and
  media.thumb_status is 'loaded' and
  not media.targetEventRecord?
    @addMedia media.targetEventRecord, mid, media.mediaType
else if media.mediaType is 'video' and
  media.video_status is 'loaded' and
  not media.targetEventRecord?
    @addMedia media.targetEventRecord, mid, media.mediaType

然后,请注意ifelse if内的代码是相同的。我认为如果你能给这些条件赋一些有意义的名字会很好,这样代码就会变得更加自我记录和干燥。我不太了解这段代码的上下文,所以我会猜测变量名称;尝试尽可能清楚地使用能够解释其含义的东西:

media = @mediaAddQueue[mid]

isValidPhoto = media.mediaType is 'photo' and
  media.econ_status is 'loaded' and
  media.medium_status is 'loaded' and
  media.thumb_status is 'loaded' and
  not media.targetEventRecord?

isValidVideo = media.mediaType is 'video' and
  media.video_status is 'loaded' and
  not media.targetEventRecord?

if isValidPhoto or isValidVideo
  @addMedia media.targetEventRecord, mid, media.mediaType

答案 2 :(得分:0)

从流行病学家的回答中,我仍然会对此进行一些重构:

media = @mediaAddQueue[mid]

typeValidationMap =
  'photo' : (m) ->
    m.econ_status is 'loaded' and
    m.medium_status is 'loaded' and
    m.thumb_status is 'loaded'
  'video' : (m) ->
    m.video_status is 'loaded'
  'default': () -> no

isValidMedia = (m) ->
  return no if m.targetEventRecord?
  validate = typeValidationMap[m.mediaType] or typeValidationMap.default
  validate m

if isValidMedia media
  @addMedia media.targetEventRecord, mid, media.mediaType

旁注:我注意到你在这种情况下传递了一个始终为null的targetEventRecord