制作一个复杂的构造函数是不好的实践吗?

6

我正在制作一个PHP网站,用于浏览我在本地网络上的电影收藏。它经历了几次迭代,现在我认为面向对象是正确的方式。在目前的状态下,我有几个函数从数据库中获取电影信息。因此,每当我需要电影信息时,我必须调用几个函数来获取所有信息,并将其传递给其他函数以完成我想要的操作。

我的面向对象版本的想法是在构造函数中完成所有这些“getinfo”函数。因此,我只需创建一个电影对象,即可使用$movieobj->title等方式轻松获取所有信息。

我尝试了一下,并得出了以下测试结果:

class movie{
public $tite = Null;

function __construct($id, $conn){

//set title property
$sql_select = $conn->prepare("SELECT title FROM movie.title 
                              WHERE `movieID` = {$id} LIMIT 1");
$sql_select->execute();
$sql_select->bind_result($val);
$sql_select->fetch();
$this->title = $val;
}

这样做可以实现我想要的效果,可以使用以下方式获取电影标题:

$movie = new movie(100,$db);

echo $movie->title;

但实际上,我在构造函数中可能还有几个类似的代码块来获取电影的其他信息。

这样使用构造函数是否不正确?它应该更简单,然后有其他方法从数据库中提取这些信息吗?拥有复杂的构造函数可以使其他代码更加简单,但这是不好的做法吗?或者会引起我没有看到的问题吗?


是的,在构造函数中进行计算是不好的实践,因为它使代码极难测试。如果您需要在对象可以在其他地方使用之前“准备”该对象,则应使用工厂/构建器来隔离所有这些准备工作。 - tereško
3个回答

4

一般来说,我个人只会使用构造函数来设置基本的属性值,例如连接,并且尽可能使构造函数代码简单。而所有真正的代码都会放在其他方法中,例如一个fetch方法(例如getMovie())来实际执行数据库检索,而不是直接访问电影属性(将该属性设置为私有或受保护的)。


没错。通常情况下,构造函数的使用是基于约定的。一般来说,构造函数的参数范围应该由其中包含的方法的需求来决定。也就是说,我认为最好将构造函数留空或只接收应用程序所需的最基本数据,例如数据库连接。 - Giacomo1968

2
当你在谷歌上搜索“构造函数中的数据库查询”时,你会发现即使你强调复杂性,这个问题已经被反复询问。
我的看法是,在构造函数中查询数据库是不好的做法。
从“低层次”来看,没有直接的成本,人们的不适感更普遍。现在,很容易忽略这种非特定的反对意见,在实践中,当你这样做时,你可能会做得很好,并且与将数据库查询分离为抓取方法相比同样出色。事实上,你还需要编写更多的代码,一个额外的行来获取数据。
在这种情况下,你所获得的好处是在另一个层面上,而不是你面前具体的小项目:你迫使自己使用一种平均而言更有益的风格,即使在短期内你有(微小的)劣势。
好处在于,当你习惯于分离数据库查询时,你会获得灵活性和“秩序”:如果代码稍后更改,因为你想在对象的生命周期内重新加载数据,你必须重构你已经编写的内容(包括在实例化这样的对象的所有地方,如果其他人使用你的代码作为模块,他们也必须这样做),或销毁/重新创建对象。如果从一开始就有抓取函数,它将无论如何都能工作!
因此,你的第一个建议对于那些每年只在周末写自己的个人爱好项目的人来说是可以的,如果你是或想成为一个职业程序员,原因远远超出了任何一个特定的项目,你应该选择更可维护和“有序”的长期方案。长期意味着在企业环境中以快速和“肮脏”的方式编程的项目,因为它们被认为是小型项目而在5年后变成了“怪物”,因为在前两年内程序员认为这样的捷径是可以接受的,因为“这只是一个小项目”。
我认为,这就是这种约定的真正目的,照顾你看不见的东西(未来)。

+1,但最好不要在评论中升级分歧。忽略那些你认为没有建设性的贡献,我认为。 (我已经请求管理员考虑删除)。 - halfer

1
您可以将数据库访问与构造函数隔离开来。然后,您的构造函数应该用于设置类的属性,例如在这种情况下的电影类。我的电影类将会有一个类似这样的签名:Movie($title, $director, $year, ... )。一个电影对象将代表我数据库中的一行。如果我需要进行重复的数据库调用,我会考虑将其放在电影类的静态函数中,或者作为一个外部函数,我只会调用一次。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接