А почему нет? :) На самом деле, это нормальный способ синхронной (и двусторонней!) передачи информации через события, безотносительно типа коммуницирующих сторон. Можно конечно и по-другому делать: контроллер Foo стреляет событие "printrequest", контроллер Print обрабатывает и в ответ стреляет событие "printresponse", которое Foo ловит. Или даже передавать ссылку на контроллер Foo в аргументах события, и т.п... Но я бы не рекомендовал так делать, т.к. можно легко насоздавать себе проблем с рекурсией, циклами событий и прочими прелестями односторонней синхронности. А уж про тестирование таких вариантов я просто молчу - фактически это будет означать взаимную зависимость обоих контроллеров друг от друга.
Важно понимать, что в предложенном решении инициатором запроса является ViewController, а глобальный контроллер лишь пассивно реагирует на запрос. Такой подход даёт вполне чистое концептуальное разграничение между модулями программы, которую в дальнейшем проще поддерживать и тестировать.
А если на событие printrequest подпишутся два обработчика, то объект options по возврату будет содержать потенциально конфликтную информацию. Но этот случай тоже довольно легко отловить:
onPrintRequest: function(options) {
//<debug>
if (options.success != null) {
throw "Whoa there!";
}
//</debug>
}
На практике такое бывает довольно редко - мы же говорим о глобальных контроллерах, правда? Они ведь должны существовать в одном экземпляре, так ведь? И вы ведь это точно протестировали? ;)