Ошибка, не определенная конструктором после установки полей даты как нулевых при создании объекта

#date #constructor #salesforce #wrapper #apex

#Дата #конструктор #salesforce #оболочка #вершина

Вопрос:

Я создал класс-оболочку для создания объекта и отправки его в качестве запроса в стороннюю систему. Он работал хорошо. Но после того, как я добавил два новых аргумента типа данных Date, я получаю приведенную ниже ошибку.

 Constructor not defined: [SFDC_DataObject.CustomerAccountObject].<Constructor>(Id, String, Id, String, Id, String, Integer, NULL, String, String, Id, String, NULL, String, String, String, String)
 

Запрос, который я создаю и отправляю, выглядит следующим образом.

 SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject(o.AccountId, o.Customer_Name__c, o.Agency_Name__r.Id,o.Agency_Name_OB__c, o.Opportunity.OwnerId, o.Opportunity.Owner.FederationIdentifier, PrimarySalesSplitPercent, null, secSOSalesforceId.get(o.OpportunityId), secSOSalesforceEmail.get(o.OpportunityId), o.Opportunity.Customer_Success_Manage__r.Id, o.Opportunity.Customer_Success_Manage__r.FederationIdentifier, null, o.Billing_Email__c, o.Billing_Phone__c, o.Bill_To_Name__c, o.Billing_Notes__c);
 

Мой класс-оболочка для того же объекта, как показано ниже.

 public class CustomerAccountObject {
        public String  sfCustomerId;
        public String  customerName;
        public String  sfAgencyId;
        public String  agencyName;
        public String  sfPrimarySalesOwnerId;
        public String  primarySalesOwnerEmail;
        public Integer primarySalesOwnerPercentage;
        public Date    primarySalesOwnerEffectiveFrom;
        public String  sfSecondarySalesOwnerId;
        public String  secondarySalesOwnerEmail;
        public Date    secondarySalesOwnerEffectiveFrom;
        public String  sfAccountManagerId;
        public String  accountManagerEmail;
        public String  billingEmail;
        public String  billingPhone;
        public String  billingName;
        public String  billingNotes;

        public CustomerAccountObject() {}

        public CustomerAccountObject(String sfCustomerId, String customerName, String sfAgencyId, String agencyName, String sfPrimarySalesOwnerId, String primarySalesOwnerEmail, Integer primarySalesOwnerPercentage, Date primarySalesOwnerEffectiveFrom, String sfSecondarySalesOwnerId, String secondarySalesOwnerEmail, Date secondarySalesOwnerEffectiveFrom, String sfAccountManagerId, String accountManagerEmail, String billingEmail, String billingPhone, String billingName, String billingNotes) {
            this.sfCustomerId                     = sfCustomerId;
            this.customerName                     = customerName;
            this.sfAgencyId                       = sfAgencyId;
            this.agencyName                       = agencyName;
            this.sfPrimarySalesOwnerId            = sfPrimarySalesOwnerId;
            this.primarySalesOwnerEmail           = primarySalesOwnerEmail;
            this.primarySalesOwnerPercentage      = primarySalesOwnerPercentage;
            this.primarySalesOwnerEffectiveFrom   = primarySalesOwnerEffectiveFrom;
            this.sfSecondarySalesOwnerId          = sfSecondarySalesOwnerId;
            this.secondarySalesOwnerEmail         = secondarySalesOwnerEmail;
            this.secondarySalesOwnerEffectiveFrom = secondarySalesOwnerEffectiveFrom;
            this.sfAccountManagerId               = sfAccountManagerId;
            this.accountManagerEmail              = accountManagerEmail;
            this.billingEmail                     = billingEmail;
            this.billingPhone                     = billingPhone;
            this.billingName                      = billingName;
            this.billingNotes                     = billingNotes;
        }
    }
 

Я начал получать ошибку после того, как добавил значение null для аргументов даты, т.е. primarySalesOwnerEffectiveFrom и secondarySalesOwnerEffectiveFrom во время создания объекта.

Может кто-нибудь, пожалуйста, дайте мне знать, что я здесь делаю не так.

Ответ №1:

Порядок неправильный.

В определении c-tor у вас есть

Строка sfCustomerId, строка CustomerName, строка sfAgencyId, Строка agencyName, строка sfPrimarySalesOwnerId, строка primarySalesOwnerEmail, целое число primarySalesOwnerPercentage, Дата primarysalesownereffective from, Строка sfSecondarySalesOwnerId, строка secondarySalesOwnerEmail, Дата secondarysalesownereffective from еще 6 строк

Итак

 ... Integer, Date, String, String, Date, ...
 

Но код, который его вызывает, идет

o.AccountId, o.Customer_Name__c, o.Agency_Name__r.Id , o.Агентство_Название_OB__c, o.Возможность.OwnerId, o.Возможность.Владелец.FederationIdentifier, PrimarySalesSplitPercent, null, secSOSalesforceId.get(o.OpportunityId), secSOSalesforceEmail.get(o.OpportunityId), o.Opportunity.Заказчик_Успех_Управление__r.Идентификатор, о.Возможность.Заказчик_Успех_Управление__r.FederationIdentifier, null, 4 строки

Перед 2-м нулем есть дополнительные 2 строки. И только 4 строки после нее. Вам нужно ввести это значение сразу после secSOSalesforceEmail ?

Со временем это будет только ухудшаться. Рассмотрите возможность создания простого конструктора и предоставления общедоступных свойств. Затем вы можете установить их после конструктора при обычном вызове. И если вам не нужны даты, вы просто не пишете строку, которая задает поля даты, вместо того, чтобы вводить null в нужное положение.

Последующее редактирование

Не уверен, есть ли официальное руководство по этому методу или сообщение в блоге. Такие инструменты, как Apex-PMD, жалуются, когда вы создаете методы со слишком большим количеством аргументов, правила типа «Избегайте длинных списков параметров».

Одним из способов было бы сделать что-то вроде этого:

 SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject();
cusAccObj.sfCustomerId                      = o.AccountId;
cusAccObj.customerName                      = o.Customer_Name__c;
cusAccObj.sfAgencyId                        = o.Agency_Name__c;
cusAccObj.agencyName                        = o.Agency_Name_OB__c;
cusAccObj.sfPrimarySalesOwnerId             = o.Opportunity.OwnerId;
cusAccObj.primarySalesOwnerEmail            = o.Opportunity.Owner?.FederationIdentifier;
cusAccObj.primarySalesOwnerPercentage       = PrimarySalesSplitPercent;
// cusAccObj.primarySalesOwnerEffectiveFrom = null; // just don't bother with the line?
cusAccObj.sfSecondarySalesOwnerId           = secSOSalesforceId.get(o.OpportunityId);
// ..
 

Это не очень объектно-ориентированный, не очень элегантный, но вызывающий имеет полный контроль над отображением. Проблема будет, если вам нужно сопоставить новое поле, а оно было скопировано и вставлено в 10 мест. Вам придется обновить их все (что будет проще, чем добавить N-й параметр в длинный вызов, но все же)

Другим способом было бы создать базовый конструктор, который принимает весь Order объект (это Порядок, верно?), Он бы отображал поля внутри. Затем, если необходимо, вы указываете некоторые дополнительные поля после конструктора. Или, может быть, сделать несколько конструкторов?

 public CustomerAccountObject(){
    // I'm parameterless, I'm doing nothing! I'm just here if somebody needs a really custom field mapping or JSON deserialisations need a parameterless one
}
public CustomerAccountObject(Order o){
    // I can map all fields from Order! Want to map new field? Just chuck it in here!
    sfCustomerId = o.AccountId;
    // ...
}
public CustomerAccountObject(Order o, Map<Id, String> secSOSalesforceId, Map<Id, String> secSOSalesforceEmail){
    // I can do everything above and few more fields too!
    this(o);
    sfSecondarySalesOwnerId = secSOSalesforceId.get(o.OpportunityId);
    secondarySalesOwnerEmail = secSOSalesforceEmail.get(o.OpportunityId);
}
 

У вас есть немного повторного использования кода, сопоставление полей порядка определено только в 1 месте, всего 1 строка для изменения в будущем. У вас больше нет оргии this везде. И затем ваш вызов, если вам действительно нужен последний конструктор, или вы вызовете тот, который просто принимает Order o , а затем установите 2 дополнительных поля после его завершения.

Комментарии:

1. facepalm Спасибо. Я этого не заметил. Не могли бы вы предоставить мне какую-либо ссылку, такую как ссылка на блог или другой ответ, в котором конструктор был определен так, как вы упомянули выше. Чтобы я мог работать над своим кодом на основе этих примеров?

2. Лучше? Я не знаю, есть ли официальное название для этого «шаблона проектирования» или что-то в этом роде. Просто выглядит более чистым передавать целые объекты, а не разлагать их на отдельные свойства поля. Объектно-ориентированное программирование? : D