【问题标题】:Refactoring a method containing conditional with extremely different code blocks that are the same ;)重构一个包含条件的方法,该方法具有相同的极其不同的代码块;)
【发布时间】:2009-12-04 02:44:08
【问题描述】:

所以我有这个臭方法,两个条件块做几乎完全相同的事情,但参数完全不同(至少在我看来)。我想用鲍勃叔叔的风格清洁它,但我一辈子都想不出一个整洁的方法。所以我来找你,我的书呆子朋友,看看你如何能把它提炼成一种不会让人想挖出他们眼睛的东西。代码是 AS3,但在我看来这并没有什么不同。

/**
 * Splits this group into two groups based on the intersection of the group
 * with another group. The group is split in a direction to fill empty
 * cells left by the splitting group.
 *
 * @param onGroup
 * @param directionToMoveSplitCells
 * @return
 *
 */
public function split(onGroup:CellGroup, directionToMoveSplitCells:String):CellGroup
{
    if (!hasIntersection(onGroup))
        return this;
    var numCellsToSplit:int = 0;
    var splitCells:Array;
    var newGroup:CellGroup;
    var numberOfCellsToSplit:int;
    var splitStartIndex:int;
    var resultingGroupStartIndex:int;

    if (directionToMoveSplitCells == "RIGHT")
    {
        numberOfCellsToSplit = endIndex - onGroup.startIndex + 1;
        splitStartIndex = length - numberOfCellsToSplit;
        splitCells = trimCells(splitStartIndex, numberOfCellsToSplit);
        resultingGroupStartIndex = onGroup.endIndex + 1;

        if (splitCells.length > 0)
        {
            newGroup = row.createGroup(splitCells, resultingGroupStartIndex)
            newGroup.nextGroup = nextGroup;
            if (newGroup.nextGroup)
                newGroup.nextGroup.previousGroup = newGroup;
            newGroup.previousGroup = this;
            nextGroup = newGroup;

        }
    }
    else
    {
        numberOfCellsToSplit = onGroup.endIndex - startIndex + 1;
        splitStartIndex = 0;
        splitCells = trimCells(splitStartIndex, numberOfCellsToSplit);
        resultingGroupStartIndex = onGroup.startIndex - splitCells.length;

        if (splitCells.length > 0)
        {
            newGroup = row.createGroup(splitCells, resultingGroupStartIndex)
            newGroup.previousGroup = previousGroup;
            if (newGroup.previousGroup)
                newGroup.previousGroup.nextGroup = newGroup
            previousGroup = newGroup;
            newGroup.nextGroup = this;
            var newX:int = (onGroup.endIndex + 1) * cellSize.width;
            x = newX;
        }

    }

    removeArrayOfCellsFromGroup(splitCells);
    row.joinGroups();
    row.updateGroupIndices();
    repositionCellsInGroup();

    return newGroup;
}

【问题讨论】:

    标签: oop refactoring coding-style


    【解决方案1】:
    public function split(onGroup:CellGroup, directionToMoveSplitCells:String):CellGroup
    {
        if (!hasIntersection(onGroup))
            return this;
    
        var newGroup:CellGroup;
    
        if (directionToMoveSplitCells == "RIGHT")
        {
            newGroup = splitGroupAndMoveSplitCellsRight(onGroup);
            if (!newGroup)
                return;
    
            insertAsNextGroupInLinkedList(newGroup);
        }
        else
        {
            newGroup = splitGroupAndMoveSplitCellsLeft(onGroup);
            if (!newGroup)
                return;
    
            insertAsPreviousGroupInLinkedList(newGroup);
    
            x = (onGroup.endIndex + 1) * cellSize.width;
        }
    
        removeArrayOfCellsFromGroup(splitCells);
        row.joinGroups();
        row.updateGroupIndices();
        repositionCellsInGroup();
    
        return newGroup;
    }
    
    
    private function splitGroupAndMoveSplitCellsRight(onGroup:CellGroup):CellGroup
    {
        var numCellsToSplit:int = endIndex - onGroup.startIndex + 1;
        var splitStartIndex:int = length - numberOfCellsToSplit;
    
        var splitCells:Array = trimCells(splitStartIndex, numberOfCellsToSplit);
        if (!splitCells.length)
            return null;
    
        var resultingGroupStartIndex:int = onGroup.endIndex + 1;
    
        return row.createGroup(splitCells, resultingGroupStartIndex);
    }
    
    private function splitGroupAndMoveSplitCellsLeft(onGroup:CellGroup):CellGroup
    {
        var numCellsToSplit:int = onGroup.endIndex - startIndex + 1;
        var splitStartIndex:int = 0;
    
        var splitCells:Array = trimCells(splitStartIndex, numberOfCellsToSplit);
        if (!splitCells.length)
            return null;
    
        var resultingGroupStartIndex:int = onGroup.startIndex - splitCells.length;
    
        return row.createGroup(splitCells, resultingGroupStartIndex);
    }
    
    private function insertAsNextGroupInLinkedList(group:CellGroup):void
    {
        var currentNextGroup:CellGroup = nextGroup;
        if (currentNextGroup)
        {
            group.nextGroup = currentNextGroup;
            currentNextGroup.previousGroup = group;
        }
    
        group.previousGroup = this;
        nextGroup = group;
    }
    
    private function insertAsPreviousGroupInLinkedList(group:CellGroup):void
    {
        var currentPreviousGroup:CellGroup = previousGroup;
        if (currentPreviousGroup)
        {
            group.previousGroup = currentPreviousGroup;
            currentPreviousGroup.nextGroup = group;
        }
    
        group.nextGroup = this;
        previousGroup = group;
    }
    

    【讨论】:

    • 有点自虐的练习,因为你宁愿假设类中其他方法的功能!它非常适合我的时间凌晨 4 点,因为我无法入睡 :) 既然你提到了 Bob 叔叔,我试图保持单一责任原则。我看到自从我开始编辑我的回复以来,其他人已经指出要考虑到链表管理代码 - 绝对如此。另外,我将逻辑分为左移和右移,但如果 Anon 建议的反射性有效,那么这可以做得更整洁。希望对您有所帮助。
    • 我打算这样做,但方法仍然是几乎相同的代码,这很烦人,但在这种情况下可能是不可避免的。
    【解决方案2】:
    /**
     * Splits this group into two groups based on the intersection of the group
     * with another group. The group is split in a direction to fill empty
     * cells left by the splitting group.
     *
     * @param onGroup
     * @param directionToMoveSplitCells
     * @return
     *
     */
    public function split(onGroup:CellGroup, directionToMoveSplitCells:String):CellGroup
    {
            if(!hasIntersection(onGroup)) return this;
            var numCellsToSplit:int = 0;
            var splitCells:Array;
            var newGroup:CellGroup;
            var numberOfCellsToSplit:int;
            var splitStartIndex:int;
            var resultingGroupStartIndex:int;
    
      numberOfCellsToSplit = (directionToMoveSplitCells == "RIGHT" ? (endIndex - onGroup.startIndex) : (onGroup.endIndex - startIndex)) + 1;
      splitStartIndex = directionToMoveSplitCells == "RIGHT" ? (length - numberOfCellsToSplit) : 0;
      splitCells = trimCells(splitStartIndex, numberOfCellsToSplit);
      resultingGroupStartIndex = directionToMoveSplitCells == "RIGHT" ? (onGroup.startIndex - splitCells.length) : (onGroup.endIndex + 1);
    
      if (splitCells.length > 0)
            {
                    newGroup = row.createGroup(splitCells, resultingGroupStartIndex)
                    newGroup.nextGroup = nextGroup; //not sure how to not set this from jump
                    newGroup.previousGroup = previousGroup; //not sure how to not set this from jump
                    if (newGroup.previousGroup){
         newGroup.previousGroup.nextGroup = newGroup;
         previousGroup = newGroup;
         var newX:int = (onGroup.endIndex + 1) * cellSize.width;
                     x = newX;
        }
                    if (newGroup.nextGroup) newGroup.nextGroup.previousGroup = newGroup;
        else{
         newGroup.nextGroup = this;
         newGroup.previousGroup = this;
                     nextGroup = newGroup;
        }
            }
    
            removeArrayOfCellsFromGroup(splitCells);
            row.joinGroups();
            row.updateGroupIndices();
            repositionCellsInGroup();
    
            return newGroup;
    }
    

    【讨论】:

    • 当然,这只是减少线条的糟糕尝试,但是嗯。 :-) 伙计,堆栈顶起那个代码。我的错。
    • 代码现已修复。看起来好多了。
    • 这似乎没有必要。你最终测试了多少次方向?你真的需要多少次?
    • 完全没有必要。 :-)
    【解决方案3】:

    这就是我所想到的。链表真的是一个单独的细节......所以也许它可以被重构出来......

        public function split(onGroup:CellGroup, directionToMoveSplitCells:String):CellGroup
    {
            if (!hasIntersection(onGroup))
                    return this;
            valr splitCells:Array;
            var newGroup:CellGroup ;
            var numberOfCellsToSplit:int;
            var splitStartIndex:int;
            var resultingGroupStartIndex:int;
    
            if (directionToMoveSplitCells == "RIGHT")
            {
                    numberOfCellsToSplit = this.endIndex - onGroup.startIndex + 1;
                    splitStartIndex = this.length - numberOfCellsToSplit;
            splitCells = trimCells(splitStartIndex, numberOfCellsToSplit);
                    resultingGroupStartIndex = onGroup.endIndex + 1;
    
                    if (splitCells.length > 0)
                    {
                            newGroup = row.createGroup(splitCells, resultingGroupStartIndex);
                            nextGroup=insertGroup(newGroup,this,nextGroup);
                    }
            }
            else
            {
                    numberOfCellsToSplit = onGroup.endIndex - startIndex + 1;
                    splitStartIndex = 0;
            splitCells = trimCells(splitStartIndex, numberOfCellsToSplit);
                    resultingGroupStartIndex = onGroup.startIndex - splitCells.length;
    
                    if (splitCells.length > 0)
                    {
                            newGroup = row.createGroup(splitCells, resultingGroupStartIndex);
                            previousGroup=insertGroup(newGroup,previousGroup,this);
                            var newX:int = (onGroup.endIndex + 1) * cellSize.width;
                            x = newX;
                    }
    
            }
    
            removeArrayOfCellsFromGroup(splitCells);
            row.joinGroups();
            row.updateGroupIndices();
            repositionCellsInGroup();
    
            return newGroup;
    }
    
    private function insertGroup(toInsert:CellGroup,prior:CellGroup,next:CellGroup):CellGroup
    {
        toInsert.nextGroup = next;
        toInsert.previousGroup = prior;
        if (toInsert.nextGroup )
                toInsert.nextGroup.previousGroup = toInsert;
        if (toInsert.previousGroup )
            toInsert.previousGroup.nextGroup = toInsert;
        return toInsert;
    }
    

    我对 splitCells 分配的取消缩进是为了表明它是块中的 inoly 非条件行。 我考虑按照 Anon 的建议去做,但我看不出有任何方法可以让代码实际上变得更好。

    【讨论】:

      【解决方案4】:
      var groupThatWillReceiveCells = this;
      var groupThatWontReceiveCells = onGroup;
      
      if (directionToMoveSplitCells == "RIGHT")
      {
          groupThatWillReceiveCells = onGroup;
          groupThatWontReceiveCells = this;
      }
      

      根据需要重命名。

      【讨论】:

        猜你喜欢
        • 2017-07-03
        • 2018-12-21
        • 1970-01-01
        • 1970-01-01
        • 2011-09-10
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        • 1970-01-01
        相关资源
        最近更新 更多