Typically, in a layered architecture, the top layers are aware of the lower layers and start logic in the lower layers. But, the lower layers are not aware of the layers above and can not start logic in the layers above. However, in highly complex situations, the lower layers might need to fire logic in the top layers.
This situations are typically tackled by using patterns like Observers and Events, where top layer logic is started when a lower layer fires an event. Identifying the situations where events should be used can be tricky. These are some guidelines to help decide when to use the events system:
- Something happening in a lower layer needs to start logic in a top layer. For example, when a model is saved by the ORM, we could fire an event, who would then start logic in one or several services. In most cases, however, this specific situation is handled by using Observers;
- Occasionally, for convenience we can also use the event system when something happening in several places should fire a predetermined set of actions, although they are in the same architectural layer. For example, we can launch events in success/failure of service actions. We could then attach logging to those events and also sending an email when there is an failure event. However this is only for convenience because in this case we could also inject the logger into the service and log things directly, without the need for an event system, and have the logger use an emailService to send emails when the log level is above warning;