神对象-减少与“主"对象的耦合 [英] God object - decrease coupling to a 'master' object

查看:70
本文介绍了神对象-减少与“主"对象的耦合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为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);

解决方案

首先,冒着陈述明显的风险:传递方法使用的参数,而不是上帝对象.

但是,这可能会导致某些方法需要大量参数,因为它们调用其他方法,而后者又依次调用其他方法,等等.那可能是将所有东西都放在上帝物体中的灵感.我将给出一个带有太多参数的这种方法的简化示例.您将不得不想象这里太多" == 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
  • 非常可测试:您可以传递带有罐头响应的模拟协作者,并验证它们是否在单元测试中正确使用

I have an object called Parameters that gets tossed from method to method down and up the call tree, across package boundaries. It has about fifty state variables. Each method might use one or two variables to control its output.

I think this is a bad idea, beacuse I can't easily see what a method needs to function, or even what might happen if with a certain combination of parameters for module Y which is totally unrelated to my current module.

What are some good techniques for decreasing coupling to this god object, or ideally eliminating it ?

        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
            {

The caller would do :

                PortefeuillesReference pr = new PortefeuillesReference();
            pr.ExporterExcelParFonds(parametres);

解决方案

First, at the risk of stating the obvious: pass the parameters which are used by the methods, rather than the god object.

This, however, might lead to some methods needing huge amounts of parameters because they call other methods, which call other methods in turn, etcetera. That was probably the inspiration for putting everything in a god object. I'll give a simplified example of such a method with too many parameters; you'll have to imagine that "too many" == 3 here :-)

public void PrintFilteredReport(
   Data data, FilterCriteria criteria, ReportFormat format)
{
   var filteredData = Filter(data, criteria);
   PrintReport(filteredData, format);
}

So the question is, how can we reduce the amount of parameters without resorting to a god object? The answer is to get rid of procedural programming and make good use of object oriented design. Objects can use each other without needing to know the parameters that were used to initialize their collaborators:

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

Now the FilteredReportPrinter.Print method can be implemented with only one parameter:

public void Print(data)
{
   var filteredData = this.dataFilter.Filter(data);
   this.reportPrinter.Print(filteredData);
}

Incidentally, this sort of separation of concerns and dependency injection is good for more than just eliminating parameters. If you access collaborator objects through interfaces, then that makes your class

  • very flexible: you can set up FilteredReportPrinter with any filter/printer implementation you can imagine
  • very testable: you can pass in mock collaborators with canned responses and verify that they were used correctly in a unit test

这篇关于神对象-减少与“主"对象的耦合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆