Реализация изменяющейся бизнес-логики в классе Python - PullRequest
0 голосов
/ 20 мая 2019

Я хочу реализовать бизнес-логику в python, в которой часто происходят изменения. Обновление этой бизнес-логики должно быть легким, а старую логику следует сохранить.

Моя текущая идея выглядит так:

class Item():
    def __init__(self):
        pass        

    def __call__(self, company, time):
        if time < "2017Q1":
            return self.calc_base(company, time)
        elif time < "2018Q2":
            return self.calc_after2017Q1
        else:
            return self.calc_after2018Q2

    def calc_base(self, company, time):
        return income(company, time) + costs(company, time)

    @time_after("2017Q1")
    def calc_after2017Q1(self, company, time):
        intermediate = self.calc_base(company, time)
        return max(intermediate, 100_000) #Haircutt due to article xxx

    @time_after("2018Q2")
    def calc_after2018Q2(self, company, time):
        intermediate = self.calc_after2017Q1(company, time)
        intermediate -= 20_000 #Correction due to xxx

Идея состоит в том, чтобы вызвать экземпляр этого класса с указанием компании и времени. Внутри класс будет искать, какую бизнес-логику использовать в течение этого времени, и направлять к правильной функции расчета. Всякий раз, когда логика меняется, просто добавляется новая функция и документируется ее отличие от предыдущих вычислений.

Эта реализация требует некоторой обработки с помощью if .. elif .. else в self. call . Кто-нибудь может подумать о питонном и умном способе автоматизации этого? Я думал в духе декораторов (как показано в этом примере, но они не реализованы), где я могу указать, с какого времени новая логика действительна, пока следующая не заменит ее.

Наконец, я чувствую, что заново изобретаю колесо, поскольку это, вероятно, очень стандартная проблема. Но почему-то мне не хватает словарного запаса, чтобы найти хорошие результаты в этом направлении. Поэтому я также был бы признателен за подсказки в правильном направлении.

1 Ответ

1 голос
/ 20 мая 2019

Что ж, более подход ООП будет иметь абстрактный класс для определения базовой функции calc.Создайте After201Q1 как класс, выходящий из этого абстрактного класса и реализующий функцию calc.Затем создайте After2018Q2 как класс, выходящий из After201Q1 Затем напишите функцию factory, чтобы получить реализацию, основанную на этом времени.Я не думаю, что сравнение времени меньше, чем со строкой, является правильным способом.Я думаю, что прямая индексация - это правильный путь.Я создал образец кода.Код в основном будет выглядеть так, как показано ниже.Тем не менее, вам может потребоваться несколько модификаций в соответствии с вашими потребностями.Но я продемонстрировал основную идею.


from abc import ABC, abstractmethod
from collections import OrderedDict


def income(*args):
    return 1


def costs(*args):
    return 2


# Abstract class
class Item(ABC):

    def calc_base(self, company, time):
        print('Base calc_base')
        return income(company, time) + costs(company, time)

    def calc(self, company, time):
        print('Base calc')
        intermediate = self.calc_base(company, time)
        return self.calc_specific(intermediate, time)

    @abstractmethod
    def calc_specific(self, company, time):
        pass


class After2017Q1(Item):
    def calc_specific(self, company, time):
        print('Running After2017Q1')
        return max(company, 100000)  # Haircutt due to article xxx


class After2018Q2(After2017Q1):
    def calc_specific(self, company, time):
        print('Running After2018Q2')
        intermediate = super().calc_specific(company, time)
        return intermediate - 20000


def factory(time):
    object_factory = OrderedDict([
        ('2017Q1', After2017Q1()),
        ('2018Q2', After2018Q2())
    ])
    return object_factory[time]


print(factory('2017Q1').calc(None, None))
print('-'*20)
print(factory('2018Q2').calc(None, None))



Вы можете добавить любое количество подклассов и написать только функцию calc_specific, а затем добавить ее в функцию фабрики, так что она будет вызываться в зависимости от времени.значение.

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