- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我一直在阅读/观看很多推荐 Material ,最近是这个 - MVC for advanced PHP developers .出现的一件事是单例是不好的,它们在类之间创建依赖关系,而依赖注入(inject)很好,因为它允许单元测试和解耦。
在我编写程序之前,一切都很好。我们以网店的产品页面为例。首先我有我的页面:
class Page {
public $html;
public function __construct() {
}
public function createPage() {
// do something to generate the page
}
public function showPage() {
echo $this->html;
}
}
到目前为止一切正常,但是页面需要一个产品,所以让我们传入一个:
class Page {
public $html;
private $product;
public function __construct(Product $product) {
$this->product = $product;
}
public function createPage() {
// do something to generate the page
}
public function showPage() {
echo $this->html;
}
}
我使用依赖注入(inject)来避免让我的页面类依赖于产品。但是,如果页面有多个公共(public)变量,并且在调试时我想查看其中的内容怎么办。没问题,我只是var_dump()
页面实例。它给了我页面中的所有变量,包括产品对象,所以我也得到了产品中的所有变量。
但是 product 不仅具有包含实例化产品的所有详细信息的所有变量,它还具有获取这些产品详细信息的数据库连接。所以现在我的 var_dump()
也有数据库对象。现在它开始变得有点长并且更难阅读,即使在 <pre>
中也是如此。标签。
产品也属于一个或多个类别。为了争论起见,我们假设它属于两类。它们在构造函数中加载并存储在包含数组的类变量中。所以现在我不仅拥有产品和数据库连接中的所有变量,而且还有类别类的两个实例。当然类别信息也必须从数据库中加载,所以每个类别实例也有一个数据库私有(private)变量。
所以现在当我 var_dump()
我的页面 我有所有页面变量、所有产品变量、数组中类别变量的倍数以及数据库变量的 3 个副本(一个来自产品实例,一个来自每个类别实例)。我的输出现在很大而且难以阅读。
现在单例怎么样?让我们看看我使用单例的页面类。
class Page {
public $html;
public function __construct() {
}
public function createPage() {
$prodId = Url::getProdId();
$productInfo = Product::instance($prodId)->info();
// do something to generate the page
}
public function showPage() {
echo $this->html;
}
}
我也在 Product 类中使用类似的单例。现在当我var_dump()
我的 Page 实例我只得到我想要的变量,那些属于页面的变量,没有别的。
但这当然会在我的类之间创建依赖关系。并且在单元测试中没有办法不调用产品类,这使得单元测试变得困难。
我怎样才能获得依赖注入(inject)的所有好处,同时仍然可以使用 var_dump()
轻松调试我的类? ?我怎样才能避免将所有这些实例存储为我的类中的变量?
最佳答案
我会尝试在这里写几件事。
关于var_dump()
:
我使用 Symfony2 作为默认框架,有时,var_dump()
是快速调试的最佳选择。但是,它可以输出如此多的信息,以至于您无法阅读所有内容,对吗?比如,转储 Symfony 的 AppKernel.php
,或者更接近您的情况,一些具有 EntityManager
依赖项的服务。恕我直言,当您调试少量代码时,var_dump()
很不错,但是大型和复杂的产品会使 var_dump()
无效。我的替代方案是使用与您的 IDE 集成的“真正的”调试器。使用 PhpStorm 下的 xDebug,我不再需要 var_dump()
。
关于“为什么?”的有用链接和“如何做?”是here .
关于 DI 容器:
它的忠实粉丝。它很简单,使代码更稳定;它在现代应用程序中很常见。但我同意你的看法,背后有一个真正的问题:嵌套依赖。这是过度抽象,它会通过添加有时不必要的层来增加复杂性。
Masking the pain by using a dependency injection container is making your application more complex.
如果您想从您的应用程序中删除 DIC,并且您确实可以做到,那么您根本就不需要 DIC。如果您想替代 DIC,那么...Singleton 被认为是不可测试代码和应用程序的巨大状态空间的不良做法。 服务定位器对我来说有no benefits at all .所以看起来唯一的方法就是学习正确使用 DI。
关于您的示例:
我立即看到一件事 - 通过 construct()
注入(inject)。这很酷,但我更喜欢可选的传递依赖关系而不是需要它的方法,例如通过服务 config.yml
中的 setter 。
class Page
{
public $html;
protected $em;
protected $product;
public function __construct(EntityManager $em) {
$this->em = $em;
}
//I suppose it's not from DB, because in this case EM handles this for you
protected function setProduct(Product $product)
{
$this->product = $product;
}
public function createPage()
{
//$this->product can be used here ONLY when you really need it
// do something to generate the page
}
public function showPage()
{
echo $this->html;
}
}
我认为当您在执行期间只需要一些对象时它提供了所需的灵 active ,并且在给定的时刻您可以在您的类中看到您只需要的属性。
结论
请原谅我宽泛而肤浅的回答。我真的认为您的问题没有直接答案,任何解决方案都将基于意见。我只是希望您可能会发现 DIC 确实是最好的解决方案,缺点有限,而且集成调试器而不是倾倒整个类(构造函数、服务等...)。
关于php - 你能在使用依赖注入(inject)的同时避免大量的私有(private)变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28574297/
据我所知,在 C# 中,所有字段默认都是私有(private)的,如果没有另外标记的话。 class Foo { private string bar; } class Foo { strin
这个问题在这里已经有了答案: Why is it allowed to access Java private fields via reflection? (7 个答案) 关闭 6 年前。 使用反
在 C#(和许多其他语言)中,访问相同类型的其他实例的私有(private)字段是完全合法的。例如: public class Foo { private bool aBool; pu
使用私有(private)方法通过将一些决策点重构为单独的方法来降低 CC 会降低实际方法的 CC 并易于阅读,但不会减少在测试中获得完整分支覆盖的工作量。 这合理吗?你有什么现场经验? 最佳答案 好
在下面的例子中,模块outer有一个私有(private)类型Private和一个私有(private)内部模块inner。 inner 能够访问Private(因为子模块可以访问其父级的私有(pri
class Person def one @var = 99 self.two end private def two p @var end end p=P
我在 Azure 中创建了 VNET。我放入了一个子集 Azure Private Link,它在 VNET 之外和另一台虚拟机中调用 Azure Function。 当我尝试通过专用 IP 调用专用
我在 Azure 中创建了 VNET。我放入了一个子集 Azure Private Link,它在 VNET 之外和另一台虚拟机中调用 Azure Function。 当我尝试通过专用 IP 调用专用
我正在尝试获得良好的 Ruby 编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用 self.。但是现在我偶然发现了这个: class MyClass "method" a
今天遇到一个案例类构造函数的奇怪问题。我想将构造函数设为私有(private),看来这不是问题。所以我已经在我的一个项目中尝试过它并且它有效。但在另一个项目中,我可以调用私有(private)构造函数
我想坚持使用记录,并且不想返回对象。所以我想知道是否可以将记录的字段设置为私有(private)?或者创建记录的私有(private)成员。其他具体类型(例如可区分联合)怎么样? 或者,这个要求是否违
我正在通过 Flickr API 进行经过身份验证的调用来访问照片。但我只得到我的公开照片,而没有任何私有(private)照片。 下面给出的是我正在使用的代码, Flickr f; Request
这两个类的行为不同;原因似乎与使用 private[this] 声明而不是 private 有关。有人可以解释一下为什么吗? 私有(private): class Person( private
在 private 中的 1000 秒 private 之后,我想到可能不需要它 public class Outer { private static class Inner { // yo
我有以下代码: class C { private enum E { // ... } } private extension C { func f(e: E)
OOP 语言中是否有object-private 的概念??我的意思是比经典的私有(private)访问限制更多? Private (or class-private) restricts the a
swift 3.0 我知道fileprivate访问级别修饰符将函数/属性的使用限制在声明它的源文件和 private - 仅限于声明的词法范围。但似乎这条规则不适用于扩展。例如。此代码有效: cla
即将推出的 Delphi 版本中启用该功能的功能怎么样? 也许它可能是一个编译器开关,促进所有 ** private **s to ** strict private **小号。 ... 或者它可能是
我可以通过将函数放入类的私有(private)扩展中来创建私有(private)函数,而不是通过不断调用 private func functionName(){} 来创建新的私有(private)函
部署专用端点并需要专用 IP 地址作为输出,但似乎无法正确获取值查询。下面的结果是“模板输出'主机名'无效:语言表达式属性|'privateIPAddress'具有无效的数组索引..(代码:Deplo
我是一名优秀的程序员,十分优秀!