我有一个名为Parameters的对象,它跨越包边界,从方法向下向上抛出调用树。它有大约五十个状态变量。每种方法都可以使用一个或两个变量来控制其输出。
我认为这是一个坏主意,因为我无法轻易看到方法需要运行什么,甚至如果模块Y的某些参数组合与我当前的模块完全无关,可能会发生什么。< / p>
有什么好的技巧可以减少与这个上帝对象的耦合,或者理想地消除它?
public void ExporterExcelParFonds(ParametresExecution parametres)
{
ApplicationExcel appExcel = null;
LogTool.Instance.ExceptionSoulevee = false;
bool inclureReferences = parametres.inclureReferences;
bool inclureBornes = parametres.inclureBornes;
DateTime dateDebut = parametres.date;
DateTime dateFin = parametres.dateFin;
try
{
LogTool.Instance.AfficherMessage(Variables.msg_GenerationRapportPortefeuilleReference);
bool fichiersPreparesAvecSucces = PreparerFichiers(parametres, Sections.exportExcelParFonds);
if (!fichiersPreparesAvecSucces)
{
parametres.afficherRapportApresGeneration = false;
LogTool.Instance.ExceptionSoulevee = true;
}
else
{
来电者会这样做:
PortefeuillesReference pr = new PortefeuillesReference();
pr.ExporterExcelParFonds(parametres);
答案 0 :(得分:9)
首先,冒着陈述明显的风险:传递方法使用的参数,而不是上帝对象。
然而,这可能导致某些方法需要大量参数,因为它们调用其他方法,依次调用其他方法,等等。这可能是把一切都放在上帝对象中的灵感。我将给出一个具有太多参数的这种方法的简化示例;你必须想象“太多了”== 3这里:-)public void PrintFilteredReport(
Data data, FilterCriteria criteria, ReportFormat format)
{
var filteredData = Filter(data, criteria);
PrintReport(filteredData, format);
}
所以问题是,如何在不诉诸上帝对象的情况下减少参数数量?答案是摆脱程序编程并充分利用面向对象的设计。对象可以相互使用,而无需知道用于初始化其协作者的参数:
// dataFilter service object only needs to know the criteria
var dataFilter = new DataFilter(criteria);
// report printer service object only needs to know the format
var reportPrinter = new ReportPrinter(format);
// filteredReportPrinter service object is initialized with a
// dataFilter and a reportPrinter service, but it doesn't need
// to know which parameters those are using to do their job
var filteredReportPrinter = new FilteredReportPrinter(dataFilter, reportPrinter);
现在FilteredReportPrinter.Print方法只能用一个参数实现:
public void Print(data)
{
var filteredData = this.dataFilter.Filter(data);
this.reportPrinter.Print(filteredData);
}
顺便说一句,这种关注点和依赖注入的分离不仅仅是消除参数。如果您通过接口访问协作者对象,那么这将使您的类
答案 1 :(得分:1)
如果你的所有方法都使用相同的Parameters
类,那么它可能是一个包含相关方法的类的成员变量,那么你可以将Parameters
传递给这个类的构造函数,将其分配给成员变量,所有方法都可以使用它,并将其作为参数传递。
开始重构这个神级的一个好方法是将它分成更小的部分。查找相关的属性组,并将它们分解到自己的类中。
然后,您可以重新访问依赖于Parameters
的方法,看看是否可以将其替换为您创建的较小类之一。
如果没有一些代码示例和现实世界的情况,很难提供一个好的解决方案。
答案 2 :(得分:0)
查询每个客户端的所需参数并注入它们?
示例:需要“参数”的每个“对象”都是“客户端”。每个“客户端”都公开一个接口,“配置代理”通过该接口向客户端查询其所需的参数。然后,配置代理“注入”参数(并且仅注入客户端所需的参数)。
答案 3 :(得分:0)
听起来您并未在设计中应用面向对象(OO)原则。既然你提到“对象”这个词,我认为你是在某种OO范式内工作。我建议您将“调用树”转换为对您正在解决的问题进行建模的对象。一个“上帝对象”绝对是值得避免的。我想你可能会遗漏一些基本的东西......如果你发布一些代码示例,我可以更详细地回答。
答案 4 :(得分:0)
对于指示行为的参数,可以实例化展示已配置行为的对象。然后客户端类只使用实例化对象 - 客户端和服务都不必知道参数的值是什么。例如,对于告诉从哪里读取数据的参数,让FlatFileReader,XMLFileReader和DatabaseReader都继承相同的基类(或实现相同的接口)。根据参数的值实例化其中一个,然后读者类的客户端只是向实例化的读者对象请求数据,而不知道数据是来自文件还是来自数据库。
首先,您可以将您的大型ParametresExecution类分成几个类,每个类一个,只保存包的参数。
另一个方向可能是在构造时传递ParametresExecution对象。您不必在每次函数调用时都传递它。
答案 5 :(得分:-2)
(我假设这是在Java或.NET环境中)将类转换为单例。添加一个名为“getInstance()”的静态方法或类似于调用的方法来获取名称 - 值包(并停止“踩踏”它 - 参见“代码完成”一书的第10章)。
现在困难的部分。据推测,这是在Web应用程序或其他非批处理/单线程环境中。因此,要在对象不是真正的单例时访问正确的实例,您必须在静态访问器内隐藏选择逻辑。
在java中,您可以设置“线程本地”引用,并在每个请求或子任务启动时对其进行初始化。然后,根据该线程本地对访问者进行编码。我不知道.NET中是否存在类似的东西,但你总是可以使用当前线程实例作为键的Dictionary(Hash,Map)伪造它。
这是一个开始......(总是会分解blob本身,但我构建了一个框架,其中包含一个非常类似的半全局值存储)