如果一个物体知道很多它的拥有者,这是一种代码味吗? [关闭]

问题描述 投票:4回答:2

在我们的Delphi 2007应用程序中,我们使用了很多以下结构

FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));

FindOwnerClass向上移动当前组件的Owner层次结构以查找特定类(在示例中为TdmBasicData)。生成的对象存储在Field变量FdmBasic中。我们主要使用它来传递数据模块。

示例:生成报告时,生成的数据将被压缩并存储在通过数据模块TdmReportBaseData访问的表的Blob字段中。在我们的应用程序的单独模块中,有一些功能可以使用ReportBuilder以分页形式显示报表中的数据。此模块的主代码(TdmRBReport)使用类TRBTempdatabase将压缩的blob数据转换为可在Reportbuilder运行时报表设计器中使用的不同表。 TdmRBReport可以访问TdmReportBaseData以获取各种与报告相关的数据(报告类型,报告计算设置等)。 TRBTempDatabase在TdmRBReport中构建,但必须能够访问TdmReportBasedata。所以现在使用上面的结构完成:

constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
  inherited Create(aOwner);

  FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }

我的感觉是,这意味着TRBTempDatabase知道很多它的拥有者,我想知道这是某种代码气味还是反模式。

你对此有何看法?这是代码味吗?如果是这样,有什么更好的方法?

delphi design-patterns
2个回答
5
投票

在这里给出的描述中,我认为这是有点臭。但是,它似乎很容易修复。

我倾向于将dmReportBaseData对象传递给需要它的任何组件的构造函数。这使合同在编译时变得清晰,而不是像目前那样在运行时强制执行。

按照目前的情况,您执行的合同比您需要的更强。虽然TRBTempDatabase只需要一个dmReportBaseData实例,但它只有在能从TdmRBReport报表对象中获取该实例时才会起作用。

做出这一改变也会让TRBTempDatabaseTdmRBReport离婚并仍能成功运作。正如@Lieven在评论中指出的那样,这可能会使测试变得更容易。


2
投票

如果您在基类中所做的只是维护对父对象的引用,那么不,它不是代码味道,它是完全合法的用法。您可以明确地设计一个基类来携带有关“可能会在以后发生的事情”的信息。

如果基类依赖于本身不存在的派生类的某些特征(即广义类依赖于其子节点之一的特化)那么是的,这可能有点时髦。

© www.soinside.com 2019 - 2024. All rights reserved.