Как правильно обрабатывать вычисленные свойства в объекте? - PullRequest
0 голосов
/ 23 февраля 2019

Из того, что я могу сказать, есть два основных способа сделать это:

  • Вариант 1: Рассчитать каждое свойство "по требованию" с помощью их метода получения (например, getTotal()).
  • Вариант 2: Заполните все вычисляемые свойства при построении и каждый раз, когда изменяется публичное свойство, используя общий метод calculate().

Я создал два примера, используя простой объект страхового полиса.Каждый класс инициализируется с несколькими свойствами, такими как premiumRateBase, brokerFee, termYears, effectiveDate и agentCommissionRate.Рассчитанные столбцы могут быть такими, как пропорционально premiumRate, total или agentCommission.

. Вот пример варианта 1:

component {

    // public properties (getters + setters)
    property name="premiumRateBase";
    property name="brokerFee";
    property name="effectiveDate";
    property name="termYears";
    property name="agentCommissionRate";

    function init(
        required numeric premiumRateBase,
        required numeric brokerFee,
        required date effectiveDate,
        required numeric termYears,
        required numeric agentCommissionRate
    ) {

        // setters
        ...

        return this;

    }

    function getExpirationDate() {
        return dateAdd( 'yyyy', effectiveDate, termYears );
    }


    function getPremiumRate() {

        // run proration and calcuation determination 
        // based on premiumRateBase, getExpirationDate(), and maybe a few other methods
        ...

        return premiumRate;

    }


    function getTotal() {
        return getPremiumRate() + brokerFee;
    }


    function getAgentCommission() {
        return getPremiumRate() * agentCommissionRate
    }


    function getAgentCompensation() {
        return getAgentCommission() + brokerFee
    }

}

В приведенном выше примеревычисления выполняются каждый раз, когда вы вызываете метод, подобный getTotal().Преимущество этого подхода в том, что код довольно прост.Недостаток этого подхода заключается в том, что если вам нужно запустить getTotal(), getAgentCommission(), а затем getAgentCompensation(), вы получите много лишней математики.Для этого примера это не будет означать много дополнительного времени обработки, но в более сложном примере я мог бы увидеть это суммирование.

Вот пример варианта 2:

component {

    // public properties (getters + setters)
    property name="premiumRateBase";
    property name="brokerFee";
    property name="effectiveDate";
    property name="termYears";
    property name="agentCommissionRate";


    function init(
        required numeric premiumRateBase,
        required numeric brokerFee,
        required date effectiveDate,
        required numeric termYears,
        required numeric agentCommissionRate
    ) {

        // setters
        ...

        // run the calculation
        calculate();

        return this;

    }


    // primary calculation method which sets all private properties
    function calculate() {

        variables.expirationDate = calculateExpirationDate();
        variables.premiumRate = calculatePremiumRate();
        variables.total = calculateTotal();
        variables.agentCommission = calculateAgentCommission();

    }


    /***************************
        Public Getters
    ***************************/

    function getExpirationDate() {
        return expirationDate;
    }

    function getPremiumRate() {
        return premiumRate;
    }

    function getTotal() {
        return total;
    }

    function getAgentCommission() {
        return agentCommission;
    }


    /***************************
        Private Calculations
    ***************************/

    private function calculateExpirationDate() {
        return dateAdd( 'yyyy', effectiveDate, termYears );
    }


    private function calculatePremiumRate() {

        // run proration and calcuation determination 
        // based on premiumRateBase, expirationDate and maybe a few other variables
        ...

        return premiumRate;

    }


    private function calculateTotal() {
        return premiumRate + brokerFee;
    }


    private function calculateAgentCommission() {
        return premiumRate * agentCommissionRate;
    }


    private function calculateAgentCompensation() {
        return agentCommission + brokerFee;
    }


}

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

Каков наилучший метод или правильный подход к решению проблемы такого типа?

1 Ответ

0 голосов
/ 23 февраля 2019

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

Еще один аспект, о котором стоит подумать, - это устаревание вычисляемого свойства.Вариант № 2 выполняет вычисления только после инициализации, и, возможно, свойства, участвующие в вычислениях, могут впоследствии измениться.Рассчитанная метрика будет устаревшей.Вы можете исправить это, пересчитав метрики при модификации.Это еще больше увеличит сложность кода.Если эта модификация не очень хорошо инкапсулирована, ответственность за пересчет будет разделена и с вызывающей стороной!

Таким образом, для дешевых вычислений я бы предпочел вариант № 1, а для сложных вычислений я бы сначала инкапсулировал модификации для обеспечения пересчета при каждом обновлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...