Chu*_*ess 4 php oop dependency-injection global-variables
我正在使用较旧的代码库,它将数据库连接传递给每个模型类中的大多数函数.db连接创建为全局,并在应用程序中的任何位置传递:
$user = new User();
$user->loadById($db, $userId);
Run Code Online (Sandbox Code Playgroud)
与单个连接相比,我们可以获得哪些优势,整个模型的继承方式类似于大多数框架目前的工作方式?
任何见解都会非常有帮助.
完全披露: 我这样问这个问题,因为这就是我们在工作中这样做的方式.我不喜欢我们传递数据库连接.我试图找到这种方法的支持者,看看我的思想是否可以改变.这就是为什么我试图将讨论转移到这个对话的PRO方面而不被阻止为一个坏问题.它奏效了.我没有被禁止,但伟大的StackOverflow社区并没有让我失望.看来我不是在左边的领域,我对这个问题的看法.
主要优点是:它更容易.就像在,它是最简单的事情,因为结果,你没有应用程序架构.你正在抓住来自世界各地的事物,因为你不知道如何得到它们,这就使得可维护性非常差.猜猜这种代码库5年后会发生什么?巨大的遗留技术债务,很可能你的开发人员没有使用面向对象编程 - 更有可能在类中推断程序代码.
我不打算解释有关全局状态的问题,因为程序员已经存在一个很棒的答案.一小段摘录:
简而言之,它使程序状态变得不可预测.
要详细说明,假设您有两个使用相同全局变量的对象.假设您在任一模块中的任何位置都没有使用随机源,那么在执行该方法之前,如果已知系统状态,则可以预测(并因此测试)特定方法的输出.
但是,如果其中一个对象中的方法触发了更改共享全局状态值的副作用,则在另一个对象中执行方法时,您不再知道启动状态是什么.现在,您无法再预测执行该方法时将获得的输出,因此无法对其进行测试.
您会发现一些开发人员纯粹是出于懒惰或缺乏对SOLID基本概念的了解/理解.如果你访问全局状态(比如数据库),那么你正在编写的漂亮的,孤立的类,理论上可以传递给任何其他开发人员,并且也可以自己测试,现在可以在某个地方耦合到这个对象.云.
除了上述内容之外,您还在欺骗对象API.每个对象应该通过它的构造函数/方法签名,准确指定它需要运行的所需外部对象.这允许:
你的代码不应该脆弱.你应该完全有信心在庞大的代码库中进行更改,而不必担心在其他地方破坏某些东西.您的单元测试将涵盖此内容.我强烈建议阅读The Clean Coder,因为它详细阐述了其中的一些概念.
AlmaDO有一张关于Singletons的好图像的图片,它基本上是返回对象的单个实例的对象,如数据库或记录器.因此,如果您从中请求一个新数据库,您要么获得一个新数据库,要么只返回已存在的数据库.在传统的请求/响应/死亡上下文中,这是完全不必要的.如果你有一个非常长时间运行的过程,也许这可能是必要的,特别是在其他语言中,但作为PHP的一般经验法则; 除非您正在运行PHP Web套接字服务器或类似服务器,否则DI是一种更好的可维护性方法.
这与再次调用完全相同StaticObject::Database - 可以从任何地方访问.
这是关于PHP中Singletons的一个非常好的帖子,以及它们根本不需要它们 - 该帖子还有很多有用的链接.
基本上 - 不要懒惰并掌握SOLID.它存在的原因是,它当然不仅仅适用于PHP.人们这样做的主要原因是因为他们不知道更好而且更容易,而且更容易并不总是最好的方式.
此外,还有一些额外的说明.我们没有"模特".我们有一个模型,它是一个层.这是对"MVC"的大规模误解,我们甚至没有用PHP('经典mvc').我们将关注点分开,就是这样.
您的用户不应该知道数据库.它应该是一个实体.Active Record Pattern不是前进的方式.看看DataMapper.您的存储库将使用数据库对象并返回一个User对象数组.在上下文中,访问数据库的用户也没有意义.
大多数框架都不能通过访问实体中的数据库来工作 - 这不再是PHP 4,从那时起它已经取得了很大的进步;-)我强烈建议远离CakePHP(它不是 MVC)并采取看看像Symfony这样的框架,它仍然存在缺陷 - 了解所选框架的缺陷非常重要