Chinaunix首页 | 论坛 | 博客
  • 博客访问: 139750
  • 博文数量: 40
  • 博客积分: 1935
  • 博客等级: 上尉
  • 技术积分: 430
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-11 08:14
文章分类

全部博文(40)

文章存档

2011年(2)

2009年(11)

2008年(27)

我的朋友

分类:

2011-03-20 02:25:00

一个转换导出数据的代码,原先放在一个巨型函数内部,大致过程分为四段:从别的服务中提取数据、对数据进行一些转换操作、导出为另一格式、释放过程中的资源。具体的巨型函数的内容记不太清楚。
private List dataset; //save intermediate result
Export() 
{
    try
{
openService();
if(!sendRequest(callbackOnReceiveData))
{
return; //发送请求失败了。
}
processData();

exportToFile();
}
catch
{
blabla();
}
finally
{
a.close();b.close();c.close();
}
}

看到巨型函数,就考虑了重构,分解为四个方法。

Export()
{
try
{
retrieveData();
processData();
exportToFile();
}
finally
{
ReleaseResource();
}
}
在执行Extract Method的时候,引入了一个逻辑错误。
retrieveData()
{
    openService();
    if(!sendRequest(callbackOnReceiveData))
    {
        return; //发送请求失败了。
    }
}

因为,这个方法失败返回的仅仅是retrieveData,后续依然会继续执行,而原来,是直接退出Export()终止整个过程的。重构引起程序的行为发生了变化,重构失败。虽然,后面的处理过程会检查dataset中是否有数据,以进行后续操作。

修改的办法是,将retrieveData加入返回标记,再进一步处理。

retrieveData()
{
    openService();
    return sendRequest(callbackOnReceiveData);
}
Export()
{
try
{
if(retrieveData())
{
processData();
exportToFile();
}
}
finally
{
ReleaseResource();
}
}

导致这个错误的一个原因,这三个方法具有调用顺序的耦合,这属于语义耦合。而代码本身没有显示出来。通过引入标记解决了这个问题,但是,潜在的引入了一个无关的概念——提取数据操作是否成功,某种程序上增加了复杂度。我觉得更理想的一种方案,是将dataset将级为局部变量,使用dataset本身来体现数据处理过程的选择顺序。

retrieveData()
{
    openService();
    if (sendRequest(callbackOnReceiveData))
return dataset;
return null;
}
Export()
{
try
{
var dataset = retrieveData();
var result = processData(dataset);
exportToFile(result);
}
finally
{
ReleaseResource();
}
}

通过参数传递的方式显示的表明了这三个方法之间的先后顺序。

阅读(461) | 评论(0) | 转发(0) |
0

上一篇:无题

下一篇:没有了

给主人留下些什么吧!~~