【问题标题】:Implement changing business logic in python class在 python 类中实现更改业务逻辑
【发布时间】:2019-05-20 15:24:37
【问题描述】:

我想在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

这个想法是用公司和时间作为参数调用这个类的一个实例。在内部,该类将查看该时间将使用哪个业务逻辑,并将其路由到正确的计算函数。每当逻辑发生变化时,只需添加一个新函数并记录它与以前的计算有何不同。

这个实现需要对 self.call 函数中的 if .. elif .. else 进行一些处理。谁能想到一种自动化的pythonic和智能方式?我在考虑装饰器的思路(如本示例中所述,但未实现),我可以在其中指定新逻辑从哪个时间开始有效,直到下一个逻辑取代它。

最后,我觉得我在这里重新发明了轮子,因为这可能是一个非常标准的问题。但不知何故,我似乎缺乏正确的词汇来在这个方向上找到好的结果。因此,我也希望能得到正确方向的提示。

【问题讨论】:

    标签: python business-rules


    【解决方案1】:

    好吧,更多的 OOP 方法是有一个抽象类来定义基本计算函数。创建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函数,然后添加到工厂函数中,这样就可以根据时间值调用了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多