应用程序设计,面向对象不可取?

时间:2017-10-21 21:31:27

标签: oop

未来很长时间。

我必须写一个商业应用程序,我得出结论,传统的做法是一个糟糕的选择。我将在这里揭示我的观点,并希望听到一些意见和批评,或者反过来,对我的想法的一些确认。

CONTEXT

公司出售一些高度复杂的金融合约。外部客户联系该公司以询问价格。它们提供了他们希望的产品的一组参数,用于制作价格。提供的参数并不完全明确:客户通常会购买特定产品,因此非常大量的参数是隐含的,只有负责此特定国家/地区的特定客户的销售人员才知道。

销售员希望自动化定价过程。显然,由于每个特定客户和每个特定销售人员的所有隐含参数,他的知识是我正确地提出价格请求的唯一方式。从销售方面来看,所有金融产品都按其家庭分类。从IT方面来看,只有一个巨大的所有可能参数的平面列表,它们的某种组合使得销售人员称之为"产品A"或"产品B"。

该应用程序应该将Salesman视角映射到IT角度并回馈价格。

扩展现有解决方案:

产品系列是对象层次结构的相当好的代理,并且相互继承。默认情况下会设置大量参数,或者在子类中重写这些参数。然而问题是,班级'方法不仅取决于参数的数量或类型,还取决于某些商业逻辑,如特定的销售员,特定客户(整个点)或国家。显然,可以快速添加或删除客户端和销售人员,因此非常希望“参数化”和“参数化”。这个。这是一个如何看待它的例子(至少,我如何想象):

class AbstractProduct:
    pass

class ProductA(AbstractProduct):
    def __init__(self, a,b, ... z, client_name=None, sales_name=None ...):
        self.a=a
        # ....


    def make_a_price(self):
        if self.sales_name == "A.J" and self.client_name="Homer.S":
            request = {
                "a":self.a,
                "b":self.b,
                "c": 23,
                "d":"blah"
            }
        elif self.sales_name =="B.J" :
            request = {
                "a": self.a,
                "b": self.b,
                "c": 23,
                "d": "tom",
                "e":"dummy",
                "f":"dummy"
            }
        else:
            request = {
                "K":42
            }
        # ...
        # ...
        request["common_parameter1"]="a"
        request["common_parameter2"]="b"
        # ...

        price = send_request_for_price()
        return price

的问题:

在我看来,在价格请求逻辑中混合任何类型的商业逻辑都是无稽之谈,因为:

  • 我需要为任何商业原因更新我的代码库

  • 我没有任何领域知识,因此我可能会在修改其他客户端的功能时为某个产品或客户端破坏某些东西......我不能保证没有回归(需要进行大量测试)

  • 再一次,我没有任何领域知识,所以我无法得出对象之间的继承或组合关系的任何结论。

  • 添加if语句以检查Salesman / Client / Country是否愚蠢

  • 我可以创建一堆工厂,但这只会提高复杂性:我最终会处理对象级别的商业案例,而不是变量级别。

  • 好吧,仅仅因为商业逻辑(国家/销售/客户特定的隐含参数)与定价无关。

建议的解决方案:

A'产品'只是一组参数,其中一些参数在商业范围内是恒定的(对于特定的客户/国家/ ..),其中一些是免费的(Free + Constant =整个Univers)。因此,让我们在数据库中存储所有常量参数,并将商业范围作为主键。

剩下的所有自由参数都必须有一个函数,该函数返回该参数作为结果。将这些函数名称也存储在数据库中。这些函数由其他函数组成......等等递归,直到所有组合函数都被分解为原子函数'它只接受变量,或者只作为参数(没有其他函数),并且可以有验证函数(谓词,只返回True / False,因此参数格式正确)。将所有这些函数及其参数名称存储在数据库中。

写一个评估员'对于给定的商业范围,从数据库中读取一系列常量参数并将其设置为价格请求;以及为了设置Free参数而运行的函数列表。此Evaluator将组合函数分解为原子一次,并在上下文中递归调用它们。验证函数在每个原子函数(如果有的话)之前运行

这会给我带来什么?:

  • 我可以保证没有回归,因为每个功能都是唯一的'并附加到我的数据库中的ID(没有通过继承或组合共享代码)
  • 我的代码中没有业务逻辑
  • 直接实现(至少在我看来):每个函数都是完全独立的,Evaluator长度为30行(不包括SQL请求)
  • 如果引入或替换新的商业规则,我只需要将我的数据库条目重新指向另一个函数
  • 我可以为函数添加新参数,为每个参数添加新的格式验证函数,就像在数据库中添加行一样。

那么......利润?

1 个答案:

答案 0 :(得分:2)

我认为讨论像你这样的问题是非常重要的,因此我会在作为意见基础之前快速回答:)

你提出的最具启发性的观点,以及你认为你的观点存在缺陷的原因是:你不是领域专家

这可能不仅仅是我的意见,因为Domain Driven Design基于我们开发人员在编写任何类型的代码之前需要首先理解域的想法。使用相同的语言,企业使用(无处不在的语言)不仅仅是谈论我们的软件,而是在内部。

这个想法远非新鲜事。在软件开发的早期阶段,开发人员基本上都是领域专家,他们也承担了开发任务。

我知道,找到一个"快速"技术解决方案在短期内更容易。你甚至不必理解它为什么需要,它只是作为要求传递,所以无论如何,对吧?但我认为这确实使IT成为一个成本中心,而不是合作伙伴。

所以,如果采用传统方式"你的意思是将业务逻辑放在代码中,然后是的,这仍然是我希望的目标。但是,如果您对现有设计存在具体问题,我建议您再次发布该问题,并提供更多详细信息。