Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop God对象-减少耦合到a';硕士';对象_Oop_Refactoring_God Object - Fatal编程技术网

Oop God对象-减少耦合到a';硕士';对象

Oop God对象-减少耦合到a';硕士';对象,oop,refactoring,god-object,Oop,Refactoring,God Object,我有一个名为Parameters的对象,它在调用树中从一个方法抛出到另一个方法,跨越包边界。它有大约50个状态变量。每个方法可能使用一个或两个变量来控制其输出 我认为这是一个坏主意,因为我不容易看到一个方法需要实现什么功能,甚至不知道如果模块Y的某个参数组合与我当前的模块完全无关,会发生什么情况 有什么好的技术可以减少与这个神的物体的耦合,或者理想地消除它 public void ExporterExcelParFonds(ParametresExecution parametr

我有一个名为Parameters的对象,它在调用树中从一个方法抛出到另一个方法,跨越包边界。它有大约50个状态变量。每个方法可能使用一个或两个变量来控制其输出

我认为这是一个坏主意,因为我不容易看到一个方法需要实现什么功能,甚至不知道如果模块Y的某个参数组合与我当前的模块完全无关,会发生什么情况

有什么好的技术可以减少与这个神的物体的耦合,或者理想地消除它

        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);

查询每个客户机所需的参数并注入它们


示例:每个需要“参数”的“对象”都是一个“客户机”。每个“客户机”都公开一个接口,“配置代理”通过该接口向客户机查询其所需的参数。然后,配置代理“注入”参数(并且仅注入客户机所需的参数)。

如果所有方法都使用相同的
参数
类,那么它可能应该是包含相关方法的类的成员变量,然后您可以将
参数
传递到此类的构造函数,将它分配给一个成员变量,您的所有方法都可以将其作为参数传递

开始重构这个god类的一个好方法是将它拆分成更小的部分。找到相关的属性组,并将它们划分为各自的类

然后,您可以重新访问依赖于
参数的方法,并查看是否可以将其替换为您创建的较小类之一


如果没有一些代码示例和实际情况,很难给出一个好的解决方案。

听起来您在设计中没有应用面向对象(OO)原则。既然你提到了“对象”这个词,我想你是在某种OO范式下工作的。我建议您将“调用树”转换为对象,对您正在解决的问题进行建模。“上帝客体”绝对是要避免的。我想你可能错过了一些基本的东西。。。如果您发布一些代码示例,我可能能够更详细地回答。

(我假设这是在Java或.NET环境中)将类转换为单例。添加一个名为“getInstance()”的静态方法或类似于call的方法来获取名称-值绑定(并停止“拖拉”它——请参阅“代码完成”一书的第10章)

现在是最难的部分。这可能是在web应用程序或其他一些非批处理/单线程环境中。因此,要在对象不是真正的单例时访问正确的实例,必须将选择逻辑隐藏在静态访问器中

在java中,您可以设置一个“线程本地”引用,并在每个请求或子任务启动时初始化它。然后,根据本地线程对访问器进行编码。我不知道.NET中是否存在类似的东西,但是你可以用一个字典(Hash,Map)来伪造它,它使用当前线程实例作为键


这是一个开始。。。(blob本身总是有分解,但我构建了一个框架,其中有一个非常类似的半全局值存储)

首先,冒着陈述显而易见的风险:传递方法使用的参数,而不是god对象

然而,这可能导致一些方法需要大量的参数,因为它们调用其他方法,而这些方法又反过来调用其他方法,等等。这可能是把一切都放在神的物体里的灵感。我将给出一个带有太多参数的这种方法的简化示例;您必须想象“太多”==3,这里:-)

所以问题是,我们如何在不诉诸上帝对象的情况下减少参数的数量?答案是摆脱程序化编程,充分利用面向对象设计。对象可以相互使用,而无需知道用于初始化其协作者的参数:

// 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);
}
顺便说一句,这种关注点和依赖项注入的分离不仅仅适用于消除参数。如果您通过接口访问collaborator对象,那么您的类

  • 非常灵活:您可以使用您可以想象的任何过滤器/打印机实现来设置FiltereReportPrinter
  • 非常可测试:您可以传递带有固定响应的模拟协作者,并验证它们是否在单元测试中正确使用

对于指示行为的参数,可以实例化显示已配置行为的对象。然后,客户机类只使用实例化的对象——客户机和服务都不必知道参数的值是什么。例如,对于告诉从何处读取数据的参数,让FlatFileReader、XMLFileReader和DatabaseReader都继承相同的基类(或实现相同的接口)。根据参数的值实例化其中一个,然后reader类的客户端只向实例化的reader对象请求数据,而不知道数据是来自文件还是来自数据库

首先,您可以将大ParameterSexecution类拆分为几个类,每个包一个,这些类只保存包的参数


另一个方向可能是在构造时传递ParameterSexecution对象。您不必在每次函数调用时都传递它

“参数”是配置对象吗?是的。用于让UI携带业务层可能需要的任何参数。您能否在此基础上进行扩展,也许可以举个例子?我想我同意这一点,但我想确定一下。非常甜蜜。我在考虑你的解决方案的后果。是的,这是一个遗留系统,而且写得很差,我同意。请发布一个代码示例。。。你怎么样
public void Print(data)
{
   var filteredData = this.dataFilter.Filter(data);
   this.reportPrinter.Print(filteredData);
}