上帝对象 - 减少与"主"对象的耦合

And*_*scu 8 oop refactoring god-object

我有一个名为Parameters的对象,它跨越包边界从方法到方法向下和向上抛出调用树.它有大约五十个状态变量.每种方法可能使用一个或两个变量来控制其输出.

我认为这是一个坏主意,因为我不能轻易看到方法需要运行什么,甚至如果模块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
            {
Run Code Online (Sandbox Code Playgroud)

来电者会:

                PortefeuillesReference pr = new PortefeuillesReference();
            pr.ExporterExcelParFonds(parametres);
Run Code Online (Sandbox Code Playgroud)

Wim*_*nen 9

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

然而,这可能会导致某些方法需要大量参数,因为它们调用其他方法,这些方法依次调用其他方法,等等.这可能是把一切都放在上帝对象中的灵感.我将给出一个具有太多参数的这种方法的简化示例; 你必须想象"太多了"== 3这里:-)

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

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

// 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);
Run Code Online (Sandbox Code Playgroud)

现在FilteredReportPrinter.Print方法只能用一个参数实现:

public void Print(data)
{
   var filteredData = this.dataFilter.Filter(data);
   this.reportPrinter.Print(filteredData);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这种关注点和依赖注入的分离不仅仅是消除参数.如果您通过接口访问协作者对象,那么这将使您的类成为可能

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