【发布时间】:2015-10-29 08:34:57
【问题描述】:
在我的示例中,我使用的是 PHP 框架 Yii2,但我认为这适用于大多数 OO 语言。
我有一个 ActiveRecord 基类,我的大部分业务对象都从它扩展而来,例如Project.
目前,如果我想要一个 Project 实例,我会调用
Project::findOne(['id' => $id]);
findOne 是ActiveRecord 的静态方法(它是Yii2 框架的一部分)。所以这是一种不好的形式,因为在编写单元测试时我不能轻易地模拟/存根这个调用的返回。
但是解决这个问题的最佳方法是什么?
我可以创建一个继承自 ActiveRecord 的类 CActiveRecord 并将静态调用包装在一个非静态调用中并在任何地方使用它 - 但是我必须按顺序实例化一个丢弃的 Project 对象获取实际实例。如果Project 对象需要一些繁重的配置来实例化怎么办 - 我会将随机的废话传递给构造函数只是为了获取一个实例。
总结: 简单地将静态变量更改为非静态变量似乎是错误的 - 我不应该将函数也移动到其他地方吗?如果有,在哪里?
【问题讨论】:
-
尝试搜索 PHP LSB(Late Static Bindings)。
-
谷歌全局状态。也使您的代码难以测试。另一种方法是实例化您的对象并通过依赖注入传递它们。只有架构较差的代码库才需要静态。忽略那些说什么都有位置的人,比如
goto,因为少了一个操作码。 -
此外,活动记录是一种非常幼稚的模式,它将您的域与其持久性相结合。看看 DataMapper。
-
虽然这确实可能是一个不好的做法,但听起来你选择了框架,然后你应该选择框架(或找到更好的库)。
-
@Gerry 问题是许多框架强加给你的结构非常糟糕,最终会在为时已晚时咬你一口。你至少必须真正理解你在“使用框架”时同意的权衡并决定它是否值得(例如,因为项目现在并且将保持“小”,框架完全符合预期用途并减少了几周到几个小时的工作来生成你的模型等等)。