神物体 - 降低耦合到一个“主”对象(God object - decrease coupling

2019-08-19 09:23发布

我有一个会从方法飘来飘去方法向下和向上调用树,跨包边界的对象调用的参数。 它有大约五十状态变量。 每种方法可以使用一个或两个变量来控制其输出。

我认为这是一个坏主意,怎么一回事,因为我不能轻易看到的方法需要的功能,或者即使有对模块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);

Answer 1:

首先,在说明明显的风险:经过它们由方法使用,而不是神的对象的参数。

然而,这可能是因为他们调用其他方法,它调用反过来,等等其他方法导致一些方法需要的参数巨额资金。 这是可能是把一切都在神的对象的灵感。 我给了太多参数这种方法的简化例子; 你必须想象“太多” == 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);
}

顺便说一句,这种关注点分离和依赖注入的是良好的不仅仅是消除参数的更多。 如果您访问的合作者通过接口的对象,然后,让你的类

  • 非常灵活:您可以设置FilteredReportPrinter与任何滤波器/打印机实现你能想象的
  • 很可测试:你可以通过与罐头回应模拟合作者,并确认他们在单元测试中正确使用


Answer 2:

如果所有方法都使用相同的Parameters类,那么也许它应该与它相关的方法的类的成员变量,那么你可以传递Parameters到这个类的构造函数,将其分配到一个成员变量和所有的方法可以用具有将其传递作为参数使用。

开始重构这个神级的一个好方法是通过分割成更小碎片。 查找相关性的群体,打破他们出到自己的类。

然后,您可以重新依赖于方法Parameters ,看看你可以与你创建的小班的更换。

很难给没有一些代码样本和现实世界的情况下,一个好的解决方案。



Answer 3:

这听起来像你是不是在你的设计中应用面向对象(OO)的原则。 既然你提到这个词“对象”我想你是某种OO范式内工作。 我建议你转换你的“调用树”成模型,你是解决问题的对象。 “天神对象”是肯定的东西,以避免。 我想你可能会丢失一些基本的东西......如果您发布一些代码的例子,我也许能够更详细地回答。



Answer 4:

查询每个客户对他们所需要的参数,并注入他们?

例如:每个“对象”,需要“参数”是一个“客户”。 每个“客户”公开通过“配置代理”查询客户端为它所需的参数的接口。 配置代理再“注入”的参数(只有那些由客户端需要)。



Answer 5:

对于规定行为的参数,可以实例化呈现所配置的行为的对象。 然后客户端类简单地使用实例化对象 - 无论是客户端还是服务都知道该参数的值。 例如,对于告诉何处读取数据的参数,有FlatFileReader,XMLFileReader和DatabaseReader都继承相同的基类(或实现相同的接口)。 实例其中之一的参数的值的基础上,然后将读卡器类的客户只要求数据实例化对象读者不知道如果数据来自一个文件或数据库。

要开始,你可以打破你的大ParametresExecution全班分成几类,每包一个,只保持了包的参数。

另一个方向可以是通过在施工时间ParametresExecution对象。 你将不必通过它围绕在每一个函数调用。



Answer 6:

(我假定这是一个Java或.NET环境中)转换定义为单例。 添加一个名为“的getInstance()”静态方法或类似的调用来获取名称 - 值捆绑的东西(和停止“流浪”它周围 - 见章的“代码大全”一书10)。

现在最困难的部分。 据推测,这是一个Web应用程序或某些其他非批量/单线程环境中。 因此,要获得正确的实例,当对象是不是一个真正的真实单身,你要隐藏的静态访问内部选择逻辑。

在Java中,你可以设置一个“线程本地”的提法,并且每个请求或子任务启动时初始化。 然后,在线程本地的条款码的访问。 我不知道类似的东西在.NET中存在,但你可以随时与使用当前线程实例作为密钥字典(哈希,地图)捏造事实。

这是一个开始......(总是有斑点本身的分解,但我建立了之内具有非常相似的半全局值店的框架)



文章来源: God object - decrease coupling to a 'master' object