大型应用程序的ActiveRecord设计问题

时间:2018-11-17 06:43:37

标签: php laravel oop design-patterns eloquent

在大多数框架中,您都有代表数据库中行的模型类。

例如php代码:

class User extends Model {}

我给了Laravel雄辩的例子,但是对于大多数php框架都是如此。

然后在类中添加关系:

public function pictures()
{
    return $this->hasMany('App\Picture');
}

然后您添加一些类似的方法:

public function deleteComments()
{
    // delete comments code here
}

我的第一个问题是:这是一个好的设计体系结构,因为在项目规模扩大后,您将拥有许多关系(图片,评论,帖子,订阅等与用户连接)。 该类可能会变成1万行左右的代码。

在这种情况下,该类将变得非常庞大且难以维护。 另外,由于您在一个类中有太多方法,因此可能会违反“单一责任原则”。

如果我想在另一个应用程序中使用该类,我也不能,仅因为我必须在第二个应用程序(网站)中提取图片,注释等。

如果我创建“ UserPictures”,“ UserPictureDeleter”等其他类,则代码将变得更加复杂。

这是一种好的做法,如果没有,那么您对如何使代码不被太多方法but肿却易于使用提出了建议。 您是否同意所有这些方法都属于User类?

4 个答案:

答案 0 :(得分:13)

Laravel和其他框架在其模型的基础类中提供了Active Record概念。 Active Record的主要思想是将表行表示为一个对象,其中包括行的数据和数据库的工作方法。

在小型简单应用程序中使用Active Record模式是完全合理的,因为该模式提供了快速开发应用程序的能力。但是,如果您的应用程序具有大量代码和困难的业务逻辑,则Active Record将在应用程序的体系结构中造成许多问题。 Active Record可能会出现以下问题:

  • 违反了单一责任原则,使代码code肿。 Active Record始终违反此原则,因为它始终承担两个责任:它实现业务逻辑和数据库工作方法
  • 违反低耦合原理(GRASP),使代码重用更加困难
  • 如果使用Active Record模式,很难创建合格的抽象

解决这些问题的方法是使用OOP抽象,而不是使用表行抽象。例如,您可以使用Domain ModelDomain-driven design。对于大型应用程序,此方法优于Active Record模式。

不幸的是,这些概念的内容量太大,无法在本文中进行解释,但是您可以阅读Eric Evans的“域驱动设计”。这是一本有关应用程序设计的好书。另外,您可以在Google中找到许多有关这些概念的文章。例如Building a Domain ModelImplementing Domain-Driven Design in PHP(Laravel)

答案 1 :(得分:2)

  

该类可能会变成1万行代码左右

每个关系函数是2-4行代码,因此,除非您有2500-5000个关系,否则此类不会是10k行代码。如果这样做,您已经有不好的数据库设计。

  

也可能因为您违反了“单一责任原则”   一类中的方法太多。

SRP在任何地方都不能声明一个类中不能包含太多方法。它指出,一个班级应该只有一个责任/理由。

  

如果我想在另一个应用程序中使用该类,我也不能,   因为我还必须拉出图片,评论等   第二个应用程序(网站)。

此类是Model类。它的责任是代表一个数据库表。如果您在其他应用程序中具有相同的表结构,则可以,您应该引入此类,并且由于具有相同的表结构,因此还需要引入图片,注释等。如果没有,则不应将其拉入。我在这里看不到任何问题。

答案 2 :(得分:1)

您可以使用Interfaces改进模型。 如果您需要一个类继承设计了接口的其他行为所共有的某种行为,则需要新类仅实现接口。

Interfase based programming

coding to interfase in PHP

答案 3 :(得分:1)

请考虑以下来自亚当·沃特汗(Adam Wathan)的talk。他解决了命名中的一个问题,这导致课程膨胀。如果考虑他的命名方法和转移职责的方法,您将得到较小的类,并且更易于阅读代码。

此外,不要让自己被编程中存在的一些规则和“法律”所灌输。如果您需要一个10k行的类,但是它是可读的,那就去做吧。