4

I have a symfony2 application which consist of a site, with many games.

So I have created a CoreBundle (the site), and a bundle for every games which interact with the core.

Games bundle interact with the core (update player score), and the core notifies games when something has changed and game should do something (for example a game instance has been created in the core, so the game should initialize data related to itself).

Bundles architecture

At this moment, I am hesitate between two architectural point of view.

  • Firstly, to do this, I created an interface that each games must implement. In this interface, many method are called at differents moments of the game workflow. That works, but it is not a very nice pattern, and methods in the interface are growing again and again, and even if I created an Adapter, that makes too many methods a game must implement.

  • Secondly, I so decided to use events to make the interface lighter, and a game can listen to some event triggered by the core.

That works too, and it is a good pattern, but another inconvenient comes to me:

Every game listen to a same event, so if a player creates a game instance of any game (then the core dispatch the event event.game.created), every game is notified.

I can add a condition in every game listener method like if (game.name !== 'chess') return;

But I have too many game, and that makes too many methods called for nothing, for every event...

That is why I returned to the first method, call an interface method, then I am sure that the method of the good game bundle is called, and not all games methods when core notifies a game instance creation or any other event.

An inconvenient stays again:

I have many games, then many game bundles that are booted for nothing, because only core bundle and maybe one game bundle are used in a query.

Do you have some ideas or the same problem ?

Alcalyn
  • 1,531
  • 14
  • 25
  • The caching makes it challenging to control which bundles are loaded based on routes. Instead of game bundles consider thinking of them as libraries and have the core pick which library to use based on the route. For example, the core would determine the type of game and then activate the listener for that game type. And then start dispatching messages. – Cerad Jul 17 '14 at 12:58
  • Well, I think to have found a begin of solution when you said "_activate the listener for that game type_". Games are actually declaring theirs listeners in theirs services.yml, but I should try to use event subscribers (http://symfony.com/doc/current/components/event_dispatcher/introduction.html#using-event-subscribers), then subscribe only the current game subscriber... I will try – Alcalyn Jul 17 '14 at 14:47
  • I have implemented event subscribers, and I subscribe only the one which correspond to the game, and that works. So I can use events, and only one game bundle listen to events – Alcalyn Jul 18 '14 at 10:22
  • 1
    Would you consider your question to be answered? If so, you might go ahead add the answer. – Cerad Jul 18 '14 at 12:53

1 Answers1

0

So we can't boot bundles or not depending of the route, because as Cerad said, it would be challenging for the cache. Even if we can boot bundles depending of the environment.

So I achieved my problem by using event dispatcher component, especially events subscribers (http://symfony.com/doc/current/components/event_dispatcher/introduction.html#using-event-subscribers):

$this->get('event_dispatcher')->addSubscriber(new PartyEventSubscriber());

instead of register event listeners in services.yml:

services:
    games.chess:
        class: %chess.class%
        tags:
            - { name: kernel.event_listener, event: event.party.created, method: onPartyCreated }
            - { name: kernel.event_listener, event: event.party.started, method: onPartyStarted }
            - { name: kernel.event_listener, event: event.party.ended, method: onPartyEnded }

Sure that on dev environment, bundles are always loaded, but in prod environment, the cache do its work...

Alcalyn
  • 1,531
  • 14
  • 25