我的代码位于:https://github.com/maniator/SmallFry
我应该这样做,以便App该类不必使用静态函数,但同时能够从任何地方设置和设置应用程序的变量?
或者我应该保留它现在的方式App::get和App::set方法?
两者的优点和缺点是什么?
如果我要承担它,我将如何完成第一项任务?
示例代码:
//DEFAULT TEMPLATE
App::set('APP_NAME', 'SmallVC');
//END DEFAULT TEMPLAT
//
//DEFAULT TEMPLATE
App::set('DEFAULT_TEMPLATE', 'default');
//END DEFAULT TEMPLATE
//DEFAULT TITLE
App::set('DEFAULT_TITLE', 'Small-VC');
//END DEFAULT TITLE
//LOGIN SEED
App::set('LOGIN_SEED', "lijfg98u5;jfd7hyf");
//END LOGIN SEED
App::set('DEFAULT_CONTROLLER', 'AppController');
Run Code Online (Sandbox Code Playgroud)
if(App::get('view')){
$template_file = $cwd.'/../view/'.App::get('view').'/'.App::get('method').'.stp';
if(is_file($template_file)){
include $template_file;
}
else {
include $cwd.'/../view/missingview.stp'; //no such view error
}
}
else {
App::set('template', 'blank');
include $cwd.'/../view/missingfunction.stp'; //no such function error
}
Run Code Online (Sandbox Code Playgroud)
我觉得你有一种静止不好的感觉.我发布的内容似乎相当疯狂,因为它是一个巨大的变化.至少希望它能提出一个不同的世界观.
MiškoHevery写的静态方法是可测性的死亡.
我喜欢测试,因此我不使用它们.那么,我们还能如何解决这个问题呢?我喜欢用我认为是一种依赖注入来解决它.Martin Fowler在这里有一篇很好但很复杂的文章.
对于构造中的每个对象,我传递它们操作所需的对象.从你的代码我将使AppController成为:
class AppController
{
protected $setup;
public function __construct(array $setup = array())
{
$setup += array('App' => NULL, 'Database' => NULL);
if (!$setup['App'] instanceof App)
{
if (NULL !== $setup['App'])
{
throw new InvalidArgumentException('Not an App.');
}
$setup['App'] = new App();
}
// Same for Database.
// Avoid doing any more in the constructor if possible.
$this->setup = $setup;
}
public function otherFunction()
{
echo $this->setup['App']->get('view');
}
}
Run Code Online (Sandbox Code Playgroud)
依赖项默认为最有可能的值(if语句中的默认构造).因此,通常您不需要通过设置.但是,当您正在测试或想要不同的功能时,您可以传入模拟或不同的类(源自正确的基类).您也可以使用接口作为选项.
编辑更纯粹的依赖注入形式涉及进一步的变化.它要求您传递始终传递所需的对象,而不是在未传递对象时让类默认为一.我在+ 20K LOC的代码库中经历了类似的变化.实施之后,我看到了全程的好处.对象封装大大改进.它让你觉得你有真正的对象,而不是依赖于其他东西的每一段代码.
如果不注入所有依赖项,则抛出异常会导致您快速修复问题.通过在某些引导代码中使用set_exception_handler设置良好的系统范围异常处理程序,您可以轻松查看异常并快速修复每个异常.然后代码在AppController中变得更简单,构造函数中的检查变为:
if (!$setup['App'] instanceof App)
{
throw new InvalidArgumentException('Not an App.');
}
Run Code Online (Sandbox Code Playgroud)
对于每个类,然后编写所有对象将在初始化时构建.此外,对于对象的每个构造,您将传递所需的依赖项(或者让您提供的默认依赖项)实例化.(当您忘记执行此操作时,您会注意到,因为在测试之前必须重写代码以取出依赖项.)
这似乎是很多工作,但课程反映现实世界更接近,测试变得轻而易举.您还可以在构造函数中轻松查看代码中的依赖项.