如何将活动记录用作DTO到我的业务对象

时间:2017-12-28 12:29:45

标签: python django architecture

我很长时间都在努力解决这个问题。我搜索并搜索了整个互联网的解决方案,但没有什么是可以接受的。

简而言之,请回应丹尼尔的评论:

我想使用Django的Active Record ORM对象,但只能作为DTO,能够将数据保存回数据库,包括复杂的关系。 这样,我的业务对象将独立于它的数据源,并且它们只包含行为。

长版:

我们开始了一个项目,在所需的业务逻辑方面看起来很简单,所以我选择了Django作为一个框架,使事情变得更容易。问题变得复杂,也许实现将在更大的项目中使用,所以我想将业务对象对象与activerecord分离,并且我想仅将django用作数据库后端以及使用我的对象的东西。 UI已经从开始分离,它只调用django后端提供的REST API。

我的一个例子问题: 我有一个Request模型,它连接到许多其他模型。此请求包含一些与网络相关的需求规范。这些网络与云模型相关联。云下的网络将连接到从请求生成的预留(当前它们连接到请求的nw描述符以确定查询期间的配置)。

class Request(Model):
  ...  # bunch_of_stuff_here

class NetworkDescriptor(Model):
  request = ForeignKey(Request)
  configA = ...
  configB = ...

class Cloud(Model):
   ...

class Network(Model):
   cloud = ForeignKey(Cloud)
   used_by = ForeignKey(NetworkDescriptor)

我考虑过的解决方案:

1)将模型嵌入BO并委托给他们。 这会导致以下问题:当我尝试访问云的网络并简单地委派时,例如使用

def get_networks:
  return orm_dto.networks

我找回AR对象,这很糟糕。我不想在这里泄露AR细节。我必须编写一个从ORMNetworks到BOnetworks的映射器,它跟踪网络( network.used_by=request )的变化。这个定义了一个Object Mapper ...我已经拥有(即ORM),我不想要这个。 :)

2)嵌入模型但只允许高级别的交互。这听起来更像面向对象,但仍然不知道如何做到这一点:

class Cloud:
  def serve_request(bo_request):
    ???

结果应该是一堆网络,其中used_by字段设置为BORequest参数后面的ORMRequest对象。我该如何获得这些信息?如果我不想泄漏ORM细节,那么......我必须写一些跟踪BO对象并可以将它们映射到AR对象的东西,例如:

class Cloud:
  def serve_request(bo_request):
    for net in self._find_matching_networks(bo_requsets)
      net.used_by = repo.get_ar_from_bo(bo_request)

这又是......不是最好的解决方案,因为我必须编写映射器,但在这种情况下,它似乎更容易,因为我不必处理相关字段。

3)使用模板方法模式,使AR对象只是一个数据源。

class Request(Model, Resource):
  def get_cpu():
    return self._cpu

class Resource(object)
  def __le__(self, other:Resource):
    return self.get_cpu() <= other.get_cpu()

这又是一个我不喜欢的解决方案,因为在这种情况下AR仍然是BO。我无法在不到达数据库的情况下有效地对其进行单元测试,但至少在代码级别,业务部分与数据访问部分是分开的。

4)完全交换到SqlAlchemy。问题是通过Django管理AR对象比使用炼金术更容易,但也许这是最终的解决方案。

0 个答案:

没有答案