对一个排序程序的不断重构



最近写了一个排序的程序
需求从最开始的只要能对数组进行升序排序不断的进化
最后成为以下的样子:

 1 可以升序和降序排序
 2 能够自由的扩充排序算法而不需改动原有程序
 3 能纪录排序的比较次数、交换次数、排序用时
 4 通过扩展,能够对任意对象进行排序
 5 通过扩展,能够将排序过程相关的信息打印在任何位置

所以代码从最开始的一个简单的函数被重构成了
包含3个 接口、N个类的包


o_Class%20Diagram.gif

程序的输出入下:

**********************************************
2005-10-12 0:16:57
The original array is :
2005-01-01 6:06:06,2004-01-01 6:06:06,2006-01-01 6:06:06,2005-01-01 6:06:07

Now using BubbleSorter, direction : Descending
Sort was finished.
Sort took 40.0576 ms.
Sort compared 6 times.
Sort swapped 4 times.

The sorted array is :
2006-01-01 6:06:06,2005-01-01 6:06:07,2005-01-01 6:06:06,2004-01-01 6:06:06

**********************************************
2005-10-12 0:16:57
The original array is :
1,3,2,4,5,6.5,7,8

Now using BubbleSorter, direction : Ascending
Sort was finished.
Sort took 20.0288 ms.
Sort compared 13 times.
Sort swapped 1 times.

The sorted array is :
1,2,3,4,5,6.5,7,8

………………(其余部分省略)


起初,BubbleSorter的代码如下

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif    
/// 冒泡排序算法,使用了策略模式避免了对具体比较器的依赖
ExpandedBlockEnd.gif    
/// </summary>

None.gif      public   class  BubbleSorter : SorterBase
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 构造器
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif         public BubbleSorter():this(new CommonComparer(),new ConsolePrinter())
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif         }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 构造器
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <param name="comparer">比较器实例</param>

InBlock.gif         public BubbleSorter(IComparer comparer):this(comparer,new ConsolePrinter())
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockEnd.gif         }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 构造器
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="comparer">比较器实例</param>
ExpandedSubBlockEnd.gif        
/// <param name="printer">打印器实例</param>

InBlock.gif        public BubbleSorter(IComparer comparer,IPrinter printer)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Initialize(comparer,printer);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
InBlock.gif         
public override void Sort(Array arrayToSort,SortDirection sortDirection)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(arrayToSort == nullthrow new ArgumentNullException("arrayToSort");
InBlock.gif
InBlock.gif            StartSort(
this,arrayToSort,sortDirection);
InBlock.gif            
InBlock.gif            
bool isSwap = false ; 
InBlock.gif
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
for(int i = 0 ; i <=  arrayToSort.Length - 1  ; i ++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    isSwap 
= false ;
InBlock.gif                    
for(int j = arrayToSort.Length-2 ; j >= i  ; j --)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                         
if(CompareAndSwap(arrayToSort,j,j+1))
InBlock.gif                            isSwap 
= true;
ExpandedSubBlockEnd.gif                     }

InBlock.gif                    
if(!isSwap) break ;
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                FinishSort(arrayToSort); 
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                RegisterException(ex);
InBlock.gif                
throw;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif         }
 
ExpandedBlockEnd.gif     }


当只有冒泡排序算法的时候,我对上面的程序感觉相当满意。
但是,在我实现插入排序的话,我发现了几个很不爽的事情

1。基本我要实现跟冒泡排序一样的3个构造方法
2。对于Sort方法 我必须作参数校验
3。为了显示排序信息,我必须在排序过程前后调用StartSort(this,arrayToSort,sortDirection)和FinishSort(arrayToSort)方法
4。在BubbleSorter类中和SortBase类中,很多方法都在传递arrayToSort这个参数

于是我做了几件事
1。用Extra Method将真正排序的那段代码提取到一个叫做DoSort()的方法中
2。将Sort方法提取到Super Class中,在Sort中调用抽象的 DoSort方法。--- 这刚好是模板模式。
3。将arrayToSort提升为域字段
4。去除了3个烦躁的构造函数,转而使用工厂进行构造

经过3步重构后,排序的算法保持得很纯洁,如下:

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif    
/// 冒泡排序算法
ExpandedBlockEnd.gif    
/// </summary>

None.gif      public   class  BubbleSorter : SorterBase
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif         
protected override void DoSort()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif               
bool isSwap = false ; 
InBlock.gif
InBlock.gif             
for(int i = 0 ; i <=  arrayToSort.Length - 1  ; i ++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                isSwap 
= false ;
InBlock.gif                
for(int j = arrayToSort.Length-2 ; j >= i  ; j --)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                     
if(CompareAndSwap(j,j+1))
InBlock.gif                        isSwap 
= true;
ExpandedSubBlockEnd.gif                 }

InBlock.gif                
if(!isSwap) break ;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif           }

ExpandedBlockEnd.gif     }



插入排序的代码

ExpandedBlockStart.gif ContractedBlock.gif /**/ /// <summary>
InBlock.gif    
/// 直接插入排序
ExpandedBlockEnd.gif    
/// </summary>
None.gif      public   class  InsertSorter : SorterBase
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <url>element://model:project::Sorter/design:view:::zm86v8buarhrn1i_v</url>
ExpandedSubBlockEnd.gif        
/// <url>element://model:project::Sorter/design:view:::kg8jy20srni144i_v</url>

InBlock.gif         protected override void DoSort()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif             
for(int i=1;i< arrayToSort.Length;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//依次与前面的记录进行比较,如比它小就交换
InBlock.gif
                for(int j=i;j>0;j--)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if!CompareAndSwap( j-1 , j) ) break;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif         }

ExpandedBlockEnd.gif    }

编码采用了TDD,如果没有单元测试,重构会是一场噩梦。
对于用于测试的代码也经过了重构
最开始只有一个类用于测试冒泡排序代码
后来加入了插入排序算法以后
发现原先的测试代码没有办法重用,于是抽象出了一个测试基类TestSorterBase,这个类里面存在大量的测试方法,但是这个类没有被标记[TestFixture]
从里面派生出的两个类 TestInsertSorter & TestBubbleSorter,被标记为[TestFixture],却没有声明任何[Test]特性的方法
代码如下

ExpandedBlockStart.gif ContractedBlock.gif          /**/ /// <summary>
InBlock.gif    
/// TestInsertSort 的摘要说明。
ExpandedBlockEnd.gif    
/// </summary>

None.gif     [TestFixture]
None.gif    
public   class  TestBubbleSorter : TestSortBase
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
protected override SorterBase CreateSorter()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return SorterFactory.GetSorter( typeof( BubbleSorter ) );
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif     }

这个稍候再作详细的介绍。

呵呵 偶还在增加需求 继续重构

转载于:https://www.cnblogs.com/QuitGame/archive/2005/10/11/252677.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值