在设计Rails数据库架构时如何避免使用关注点?

黑暗的推子

我读过许多博客,经常遇到的主题之一是担忧(至少是Rails定义它们的方式)正在损害软件。总的来说,我同意-将行为纳入模型只是违反了单一责任原则。您最终会做得太多。

但是,正如从博客中收集到的许多意见一样,很少提供替代架构。

因此,让我们以一个示例应用程序为例,基于我必须维护的一个应用程序。正如许多Rails应用程序倾向于的那样,它本质上是CMS。

当前,每个模型都有很多问题。让我们在这里使用一些:

class Article < ActiveRecord::Base
  include Concerns::Commentable
  include Concerns::Flaggable
  include Concerns::Publishable
  include Concerns::Sluggable
  ...
end

您可以想象,“可注释”仅需要向文章中添加少量代码。足以与注释对象建立关系并提供一些实用的方法来访问它们。

可标记性允许用户标记不适当的内容,最终在模型中添加了一些字段:flagged, flagged_by, flagged_at例如。以及一些添加功能的代码。

Sluggable会添加一个Slug字段,以在URL中进行引用。还有更多代码。

可发布可添加发布日期和状态字段,以及更多代码。

现在,如果我们添加一种新的内容会怎样?

class Album < ActiveRecord::Base
  include Concerns::Flaggable
  include Concerns::Sluggable
  include Concerns::Publishable
  ...
end

相册有些不同。您无法对它们发表评论,但仍可以发布它们并对其进行标记。

然后,我添加其他一些内容类型:假设是事件和个人资料。

我看到这种体系结构存在一些问题:

  • 我们有多个具有完全相同字段(flagged_by, published_on等)的数据库表
  • 我们无法通过单个SQL查询一次检索多种内容类型。
  • 每个模型都支持包含所关注问题的重复字段名称,从而赋予每个类多个职责。

那么有什么更好的方法呢?

我已经看到装饰器被提升为在需要的地方添加功能的一种方式。这可以帮助解决所包含的代码的问题,但是数据库结构不一定得到改善。它看起来也很多余,涉及到在代码中添加额外的循环来装饰模型数组。

到目前为止,我的想法是这样的:

创建一个通用的“内容”模型(和表):

class Content < ActiveRecord::Base
end

关联的表可能很小。它可能应该具有某种“类型”字段,并且可能具有绝对所有内容共有的一些东西,例如可能是URL的类型标记。

然后,我们可以为每个行为创建一个关联的模型,而不是添加关注点:

class Slug < ActiveRecord::Base
  belongs_to :content
  ...
end

class Flag < ActiveRecord::Base
  belongs_to :content
  ...
end

class Publishing < ActiveRecord::Base
  belongs_to :content
  ...
end

class Album < ActiveRecord::Base
  belongs_to :content
  ...
end
...

这些中的每一个都与一个内容相关联,因此外键可以存在于要素模型中。与该功能有关的所有行为也可以仅存在于该功能的模型上,从而使OO纯粹主义者更加快乐。

为了实现通常需要模型挂钩的行为,before_create例如,我可以看到观察者模式更有用。(一旦发送了一个“ content_created”事件,就会创建一个段,等等。)

看起来它将清理一切都没有尽头。现在,我可以通过一个查询来搜索所有内容,数据库中没有重复的字段名称,也不需要在内容模型中包含代码。

在我愉快地将其发布到下一个项目之前,是否有人尝试过这种方法?能行吗?还是将事情分解成这么多最终会导致SQL查询,联接和纠结的代码陷入困境?你能建议一个更好的选择吗?

最大限度

基本上,顾虑只是围绕mixin模式的薄包装。这是一种围绕可重用​​特征组成软件的非常有用的模式。

单表继承

在多个模型中具有相同列的问题通常可以通过“单表继承”解决。但是,STI仅在模型非常相似时才真正适用。

因此,让我们考虑一下您的CMS示例。我们有几种不同类型的内容:

Page, NewsArticle, BlogPost, Gallery

具有几乎相同的数据库字段:

id
title
content
timestamps
published_at
published_by
# ...

因此,我们决定摆脱重复并使用公用表。调用它会很诱人,contents但这是非常模棱两可的-内容的内容...

因此,让我们复制Drupal并调用我们的普通类型Node

class Node < ActiveRecord::Base
  include Concerns::Publishable
end

但是我们希望每种类型的内容都有不同的逻辑。因此,我们为每种类型创建子类:

class Node < ActiveRecord::Base
  self.inheritance_column = :type 
  include Concerns::Publishable
end

class NewsArticle < Node
  has_and_belongs_to_many :agencies
end

class Gallery < Node
  has_and_belongs_to_many :photos
end

# ...

在STI模型开始彼此差异太大之前,这一直很好。那么,与试图将所有内容都塞进同一张表所造成的大量复杂性相比,数据库模式中的某些重复所造成的问题要小得多。大多数建立在关系数据库上的CMS系统都在解决此问题。一种解决方案是使用无模式非关系数据库。

提出疑虑

没什么说担心需要您存储在模型表上的。让我们看一下您列出的一些问题:

Flaggable
Sluggable
Commentable

每个部分都会使用一个表flagsslugscomments关键是使与它们所标记,附加或注释的对象的关系具有多态性。

comment:
  commented_type: string
  commented_id: int
slugs:
  slugged_type: string
  slugged_id: int
flags:
  flagged_type: string
  flagged_id: int
# ...

class Comment
  belongs_to: :commented, polymorphic: true
end

module Concerns::Commentable
  # ...
  has_many: :comments
end

我建议您看一些解决这些常见任务的库,例如FriendlyIdActsAsTaggedOn等,以了解它们的结构。

结论

并行继承的想法从根本上没有错。而您应该放弃它只是为了满足某种极端的OO纯度理想的想法是荒谬的。

特质是其他任何构图技术中面向对象的一部分。但是,担忧并不是许多博客文章都相信的魔咒。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Rails 5,关注点-他们可以引用数据库表吗?

来自分类Dev

如何在Rails中使用模型关注点

来自分类Dev

是否可以在Rails之外使用关注点

来自分类Dev

Rails 4-使用关注点进行布线

来自分类Dev

如何在红宝石路线上使用关注点

来自分类Dev

在Rails 3和命名空间模型中使用关注点时,仅包含类方法一次

来自分类Dev

使用OOPS设计数据库表架构?

来自分类Dev

Mongo DB如何分离关注点

来自分类Dev

Rails数据库架构

来自分类Dev

设计表单的数据库架构

来自分类Dev

关注点分离

来自分类Dev

如何创建一个带有参数的Rails 4关注点

来自分类Dev

Rails:如何从包含的关注点覆盖或私有化给定范围?

来自分类Dev

Ruby On Rails-在控制器中使用关注点

来自分类Dev

使用关注点覆盖Rails引擎模型,获取未初始化的常量Concerns :: Models

来自分类Dev

布尔标志字段的架构设计(数据库架构)

来自分类Dev

Rails 4多态关联和关注点

来自分类Dev

Rails 4关注点:给类实例变量建模

来自分类Dev

如何设计以避免在初始化我的字段时对主线程异常进行数据库访问?

来自分类Dev

使用微服务架构时如何保持数据库同步?

来自分类Dev

使用Lambda和Aurora Postgresql时如何处理数据库架构迁移?

来自分类Dev

使用原始sql时,如何跟踪数据库架构更改?

来自分类Dev

记录横切关注点需要访问数据层

来自分类Dev

使用asp.net在数据库中插入数据时如何避免重复值?

来自分类Dev

在为SaaS应用程序设计数据库架构时需要帮助

来自分类Dev

在为SaaS应用程序设计数据库架构时需要帮助

来自分类Dev

如何设计数据库架构来存储具有n元树格式的数据

来自分类Dev

如何实现策略模式的创建/工厂关注点?

来自分类Dev

如何防止从关注点外部访问/覆盖方法?

Related 相关文章

  1. 1

    Rails 5,关注点-他们可以引用数据库表吗?

  2. 2

    如何在Rails中使用模型关注点

  3. 3

    是否可以在Rails之外使用关注点

  4. 4

    Rails 4-使用关注点进行布线

  5. 5

    如何在红宝石路线上使用关注点

  6. 6

    在Rails 3和命名空间模型中使用关注点时,仅包含类方法一次

  7. 7

    使用OOPS设计数据库表架构?

  8. 8

    Mongo DB如何分离关注点

  9. 9

    Rails数据库架构

  10. 10

    设计表单的数据库架构

  11. 11

    关注点分离

  12. 12

    如何创建一个带有参数的Rails 4关注点

  13. 13

    Rails:如何从包含的关注点覆盖或私有化给定范围?

  14. 14

    Ruby On Rails-在控制器中使用关注点

  15. 15

    使用关注点覆盖Rails引擎模型,获取未初始化的常量Concerns :: Models

  16. 16

    布尔标志字段的架构设计(数据库架构)

  17. 17

    Rails 4多态关联和关注点

  18. 18

    Rails 4关注点:给类实例变量建模

  19. 19

    如何设计以避免在初始化我的字段时对主线程异常进行数据库访问?

  20. 20

    使用微服务架构时如何保持数据库同步?

  21. 21

    使用Lambda和Aurora Postgresql时如何处理数据库架构迁移?

  22. 22

    使用原始sql时,如何跟踪数据库架构更改?

  23. 23

    记录横切关注点需要访问数据层

  24. 24

    使用asp.net在数据库中插入数据时如何避免重复值?

  25. 25

    在为SaaS应用程序设计数据库架构时需要帮助

  26. 26

    在为SaaS应用程序设计数据库架构时需要帮助

  27. 27

    如何设计数据库架构来存储具有n元树格式的数据

  28. 28

    如何实现策略模式的创建/工厂关注点?

  29. 29

    如何防止从关注点外部访问/覆盖方法?

热门标签

归档