【问题标题】:OOD using PHP versus Functional service-based Architecture使用 PHP 的 OOD 与基于功能服务的架构
【发布时间】:2014-08-15 16:15:20
【问题描述】:

我一直主要使用功能范例来构建我的应用程序架构,特别是针对我从头开始构建的部件/模块。现在,我也在尝试OOD。在基于 PHP、MySQL、IdiORM 的应用程序中,用于跟踪音乐曲目信息;我的下一步是构建搜索功能,如果它是正确的方法,我计划在哪里创建一个类。我非常熟悉一般的 OOP 理论概念,如继承、多态等。

在我过去几年的典型工作流程中,我会在包含目录中创建一个名为 search.inc.php 的文件,实现如下功能:

function search_by_artist($artist_name){
...
} 
function search_by_track($track_name){
...
}

然后将其编码为一项服务,该服务根据从数据库中获取的结果返回 JSON,并使用表单中的 POST 值创建 WHERE 子句。

我的问题是,在这种情况下,将这些实现移至名为 Search 的类是否有意义。如果是这样,这个类的实例在逻辑上代表什么? 很抱歉问了一个幼稚的问题,但由于我的大部分背景都是函数式 PHP 和 JavaScript 中的原型继承,所以我不太熟悉正统的 OOD 在这里如何应用。此外,是否建议将 add.inc.php 或通常将所有 CRUD 服务文件转换为类?

一般来说,在什么样的场景下应该首选基于功能服务的架构,什么时候使用OOD更好?

【问题讨论】:

  • 如果它有效,请不要修复它。如果您不了解面向对象的编程,请按原样离开生产并学习开发
  • @DarylGill 是的。确实 !制作很好,就像我从头开始编写大部分代码一样完美。我希望扩大我的视野,所以我正在制作一个本地副本以了解 OOD 的细微差别,以用于未来的项目,以便我可以在它使结果更有效时使用它。 :)
  • 如果设置正确,面向对象的编程绝对是一颗明星。使它有条理和更清晰的代码。开发人员应了解何时在当前部署之上实现扩展的抽象类

标签: php mysql oop search


【解决方案1】:

OOP 可以在应用程序中改进的一件大事是解耦不同的部分。使用函数(注意我不是说函数代码),您的搜索函数可能看起来像这样:

function search_by_artist($artist_name) {
    global $db;
    $db->query(...)
    ...
}

该函数被硬编码为依赖于特定的数据库连接。

使用 OOP,您可以解耦:

class Search {

    protected $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }

    public function byArtist($name) {
        $this->db->query(...);
        ...
    }

}

拥有一个对象构造器是一件很强大的事情。构造函数必须在类中的任何其他方法运行之前运行,从而允许您施加某些先决条件。除非您在对象构造时获得有效的 Database 实例,否则任何类方法都无法运行。这意味着没有一个类方法需要关心数据库连接,他们可以简单地假设在$this->db 有一个可用的。它如何到达那里是构造函数的工作以及调用它的代码。您在代码库中创建了一个接缝,您可以在该接缝处灵活传递不同的数据库实例,同时确保数据库实例可用。

在实际的功能代码中,函数应该是这样的:

function search_by_artist(Database $db, $name) {
    ...
}

函数应该完全作用于它的输入并返回定义的输出,它不应该依赖隐式环境变量或产生副作用。与 OOP 的不同之处在于您不必将 $db 实例单独传递给每个函数,您可以使用依赖项实例化对象一次,然后将其作为一个封装包传递。

【讨论】:

  • 请注意,数据库只是一个非常容易实现的示例。如果您将这种带有依赖注入的 OO 设计严格应用到所有内容中,您最终将得到一个极其模块化的应用程序,您可以在各种场景中以各种方式将其组合在一起。纯函数式编程可以做同样的事情,但是在 PHP 中处理将所有必需的参数传递给所有函数可能会很麻烦。 Haskell 等函数式语言更适合以函数式方式传递此类依赖项和状态。
  • 我现在有了一个使用 mysqli 接口或其他东西的通用项目的想法。但是,当我将其分析为 OOD 的竞争者时;我正在使用 IdiORM,因此,我不需要传递任何数据库连接。例如,ORM::for_table()->find_array() 在整个环境中都可用,因此可以在所有函数中访问。
  • 在这里查看我对静态方法调用的看法:How Not To Kill Your Testability Using Statics。随处可见ORM::* 并不比global $db 好。
  • 嗯..实际上,函数式编程概念是关于无状态(所以,如果谈论纯函数式概念,则没有常识)
  • @AlmaDo 当然,函数本身和环境是无状态的(尽可能)。但是每个应用程序都需要某种形式的状态。在函数式编程中,状态只是作为参数和返回值传递。状态通过无状态函数传递而改变。这就是为什么在像 Haskell 这样的纯函数式语言中,您主要处理非常复杂的类型声明,因为您需要将所有这些状态封装在更复杂的类型中。
猜你喜欢
  • 2020-07-22
  • 2012-02-06
  • 1970-01-01
  • 2017-08-29
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多