【问题标题】:Decoupling output in Symfony command lineSymfony 命令行中的解耦输出
【发布时间】:2016-10-18 13:44:49
【问题描述】:

注意:我在我的问题中经常提到 Symfony 控制台组件,但我认为如果在任何用户界面的上下文中考虑这个问题,可以认为这个问题更广泛。

我正在使用Symfony Console component 创建控制台应用程序。我试图将类耦合降至最低,因为它使单元测试更容易并且通常是更好的实践。

我的应用程序有一些进程可能需要一些时间才能完成,因此我希望在运行时使用进度条和一般文本输出让用户了解正在发生的事情。 Symfony 需要一个 Symfony 控制台输出接口的实例来传递给任何命令的执行方法。到现在为止还挺好;我可以随意创建进度条和输出文本。但是,我的应用程序的所有繁重工作都不会发生在命令的执行方法中,而是在我的应用程序的核心类中。这些类不应该也不知道它们正在控制台应用程序中使用。

我很难保持这种方式,因为我不知道如何在不将输出类注入我的核心的情况下向控制台(或任何用户界面)提供反馈。这样做会导致控制台输出类和我的应用程序核心之间的紧密耦合。我曾考虑过使用事件调度器(Symfony 有一个),但这也意味着我的核心将与调度器耦合(也许这很好)。理想情况下,我需要将我的应用程序状态“冒泡”备份到被调用命令的执行方法,然后我可以在其中执行输出。

请有人指出我正确的方向吗?我觉得这实际上一定是一个很常见的案例,但找不到太多关于它的信息。

提前感谢您的宝贵时间!

【问题讨论】:

    标签: php symfony decoupling


    【解决方案1】:

    我之前已经成功使用过事件分派器方法。例如,您可以在处理开始、进度和结束时触发事件,并让事件侦听器根据这些更新进度条。

    <?php
    
    $progress = $this->getHelperSet()->get('progress');
    $dispatcher = $this->getContainer()->get('event_dispatcher');
    
    $dispatcher->addListener('my_start_event', function (GenericEvent $event) use ($progress, $output) {
        $progress->start($output, $event->getArgument('total'));
    });
    
    $dispatcher->addListener('my_progress_event', function () use ($progress) {
        $progress->advance();
    });
    
    $dispatcher->addListener('my_finish_event', function () use ($progress) {
        $progress->finish();
    });
    

    如果你真的想避免在你的服务中耦合事件调度器,你可以扩展或装饰你的类(可能实现一个共享接口),并且只在那里使用事件调度器。您需要在基类中添加一个扩展点(公共或受保护的方法),以便能够通知任何进度。

    【讨论】:

    • 这听起来确实是最简单的解决方案。我想至少那时我的应用程序核心将不了解用户界面,并且只会额外关注触发进度事件。啊,是的,我明白您关于扩展我的服务(如 EventAwareService 或其他东西)并在原始服务中使用受保护方法的意思。
    猜你喜欢
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 2018-10-25
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多