2016-10-18 2 views
0

참고 : 필자는 Symfony Console 구성 요소를 제 질문에서 많이 언급했지만,이 질문은 사용자 인터페이스의 컨텍스트에서 생각하면 더 넓다고 생각할 수 있습니다.Symfony 명령 줄에서 디커플링 출력

Symfony Console component을 사용하여 콘솔 응용 프로그램을 만듭니다. 나는 단위 테스트를 더 쉽게 만들고 일반적으로 더 나은 연습으로 클래스 연결을 최소한으로 유지하려고 노력하고있다.

내 응용 프로그램에는 완료하는 데 약간의 시간이 걸릴 수 있으므로 진행 상황 막대와 일반적인 텍스트 출력을 사용하여 어떤 일이 일어나고 있는지 사용자에게 알려주고 싶습니다. Symfony는 Symfony Console OutputInterface의 인스턴스를 명령의 execute 메소드로 전달해야합니다. 여태까지는 그런대로 잘됐다; 내가 원하는대로 진행률 막대 및 출력 텍스트를 만들 수 있습니다. 그러나, 내 애플 리케이션의 무거운 리프팅의 모든 명령 '실행 메서드에서 발생하지 않고 대신 내 응용 프로그램의 핵심 클래스 내에 있습니다. 이 클래스는 콘솔 응용 프로그램에서이 클래스를 사용하고 있다는 사실을 알 필요가 없습니다.

출력 클래스를 내 코어에 주입하지 않고 콘솔 (또는 사용자 인터페이스)에 피드백을 제공하는 방법을 모르기 때문에 이런 식으로 유지하는 데 어려움을 겪고 있습니다. 그렇게하면 콘솔 출력 클래스와 응용 프로그램 코어 사이의 긴밀한 결합이 발생합니다. 이벤트 디스패처 (Symfony는 하나)를 사용하는 것에 대해 생각해 보았습니다.하지만 그 역시 내 코어가 디스패처와 결합 될 것입니다 (아마도 괜찮습니다). 이상적으로, 필자는 응용 프로그램 상태를 호출 된 명령의 execute 메소드로 되돌려 놓아야 출력을 수행 할 수 있습니다.

누군가 올바른 방향으로 나를 가리킬 수 있습니까? 나는 이것이 실제로는 아주 일반적인 경우가되어야하지만 그것에 대해 많이 알지 못한다고 생각합니다.

미리 감사드립니다.

답변

3

이전에는 이벤트 디스패처 접근 방식을 성공적으로 사용했습니다. 예를 들어 처리 시작, 진행 및 종료시 이벤트를 트리거하고 이벤트 수신기가이를 기반으로 진행 막대를 업데이트하게 할 수 있습니다.

<?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(); 
}); 

당신이 정말로 당신의 서비스에 이벤트 발송자의 커플 링을 피하려면, 당신은 확장 할 수 또는 (아마 공유 인터페이스를 구현) 클래스를 장식하고, 단지 거기 이벤트 디스패처를 사용합니다. 그러나 진행 상황을 알릴 수 있도록 기본 클래스에서 확장 점 (공개 또는 보호 된 메서드)이 필요합니다.

+0

이것은 가장 간단한 해결책처럼 들립니다. 적어도 내 애플 리케이션 코어는 사용자 인터페이스에 대한 지식이 없으며 진행 상황을 해고하는 것에 더 관심이있을 것이라고 생각한다. 아 그래, 내 서비스를 확장 (예 : EventAwareService 또는 무언가)하고 원래 서비스에서 보호 된 메소드를 갖는 것에 대한 의미를 알 수 있습니다. –

관련 문제