太大的数据对象

时间:2009-03-21 10:16:09

标签: php refactoring

最近,我在其中一个项目中发现了非常强大的代码味道,我正在努力。

特别是在其成本计算功能方面。要计算某些操作的总成本,我们必须将许多类型的信息传递给“解析器类”。

例如:

  • 电话号码
  • 所选广告系列
  • 选定的模板
  • 已选择的联系人
  • 选定的群组
  • 以及大约2-4种信息类型

在重构之前,所有这些参数都通过构造函数传递给Counter类(8个参数,你可以想象......)。

为了提高可读性,我引入了一个名为CostCountingData的Data类,其中包含所有这些属性的可读getter和setter。

但我认为,在重构之后,该代码变得更具可读性:

$cost_data = new CostCountingData();
$cost_data->setNumbers($numbers);
$cost_data->setContacts($contacts);
$cost_data->setGroups($groups);
$cost_data->setCampaigns($campaigns);
$cost_data->setUser($user);
$cost_data->setText($text);
$cost_data->setTotalQuantity($total_quantity);

$CostCounter = new TemplateReccurentSendingCostCounter($cost_data);  
$total_cost = $CostCounter->count();

您能否告诉我此代码段的可读性是否存在问题? 也许你可以看到任何代码味道,并可以指向我...

我有如何重构此代码的唯一想法是将这个大数据对象拆分为多个,包括相关的数据类型。但我不确定我是否应该这样做..

你怎么看待它?

4 个答案:

答案 0 :(得分:3)

如果您想要的是命名参数(它在我看来是您想要实现的),您是否会考虑传入一个关联数组,名称为键?还有命名参数成语I can only find a good reference for this for C++ though,也许它被PHP程序员称为其他东西。

为此,您将在CostCountingData上更改方法,以便它们都返回原始对象。这样你就可以重写你的顶级代码:

$cost_data = new CostCountingData();
$cost_data
 ->setNumbers($numbers)
 ->setContacts($contacts)
 ->setGroups($groups)
 ->setCampaigns($campaigns)
 ->setUser($user)
 ->setText($text)
 ->setTotalQuantity($total_quantity);

所以有两种选择。我可能会自己选择命名参数idiom,因为它是自我记录的,但我不认为差别太大。

答案 1 :(得分:1)

如果我需要数据对象(以及称为“数据”的类本身就是一种气味),我会在其构造函数中设置其值。但有趣的问题是这些价值来自哪里?值的来源本身应该是某种对象,它可能是你真正感兴趣的对象。

编辑:如果数据来自POST,那么我会让这个类成为POST数据的包装器。我不会提供任何setter函数,并且会使读取访问器看起来像这样(我的PHP不仅仅是生锈了):

class CostStuff {

   constructor CostStuff( $postdata ) {
       $mypost = $postdata;
   }

   function User() {
      return $mypost[ "user_name" ];
   }

   ...

}

答案 2 :(得分:1)

这里有一些可能性:

  • 如果您每次只需要一些参数,那么本答案中其他地方建议的named parameter approach是一个很好的解决方案。

  • 如果您总是需要所有参数,我会建议气味来自计算成本所需数据的破坏语义模型

无论你如何打电话给一个带有八个论点的方法,事实上需要八个据称不相关的信息来计算某些东西。

退后一步:

  • 八个单独的参数是否真的都是无关的,或者你能组合反映现实情况的中间对象好一点吗?产品?发票项目?还有别的吗?

  • 是否可以将成本方法拆分为较小的方法,根据较少的参数计算部分成本,以及通过累加组件成本产生的总成本?

答案 3 :(得分:0)

您认为您的代码段有什么问题?如果您已经使用了几个变量,现在需要进入$ cost_data,那么您需要依次设置每个变量。没有办法解决这个问题。

问题是,为什么你有这些变量$ number,$ contracts等,你现在决定你需要进入$ cost_data?

您正在寻找的重构可能是您设置$ number的代码中的点实际上应该是您设置$ cost_data->数字的点,并且拥有$ numbers变量是多余的?

E.g。

$numbers=getNumbersFromSomewhere() ; 
// do stuff
$contracts=getContracstFromSomewhere() ;
// do stuff 
$cost_data=new dataObject() ; 
$cost_data->setNumbers($numbers);
$cost_data->setContracts($contracts) ; 
$cost_data->someOperation() ; 

变为

$cost_data=new dataObject() ; 

$cost_data->setNumbers(getNumbersFromSomewhere()) ; 
// do stuff
$cost_data->setContracts(getContractsFromSomewhere()) ; 
// do stuff
$cost_data->someOperation() ;