Skip to content

TrevorDArcyEvans/SwampMonster

Repository files navigation

SwampMonster - making sense of the 'event swamp'

Swamp Monster

Use Roslyn to analyse your solution to quickly trace events through your system and see where events are raised and where they go.

Screenshots

Main page

Main page

Source file

Source file

Searching for an event

Searching for an event

What is an 'event swamp' aka 'event soup'?

'Event soup' is an anti-pattern in which components communicate with each other via an event bus or similar messaging system. As the system grows, the problem then becomes that interactions and dependencies are non-obvious. Further, components which receive a message may then, in turn, generate more messages; and the sequence of messages is entirely non-obvious.

redux

That scenario that Flux tries to avoid is sometimes known as "event soup", and it happens a lot
in applications that rely on event buses or similar, where events get chained in unexpected ways,
sometimes get triggered multiple times without the developer realizing it, specially when
dispatches are triggered inside if clauses.

Angular

This is not an accident, it's by design and probably to avoid event soup scenarios that the use
of solutions similar to a service bus like in AngularJs $scope.$emit() and $scope.$broadcast() 
tend to accidentally create.

These type of mechanisms tend to end up creating tight dependencies between different places of
the application that should not be aware of each other, also events end up being triggered
multiple times or in a sequence that is not apparent while just looking at one file.

This anti-pattern is called 'event soup' due to it's lack of structure and non-obvious interactions - just like a bowl of soup! Here we also call it an 'event swamp' - just like a bowl of soup which has been left too long, gone rotten and contains monsters waiting to bite you!

Prerequisites

  • .NET Core 6.0 or higher

Getting Started

Building

$ git clone https://github.com/TrevorDArcyEvans/SwampMonster.git
$ cd SwampMonster
$ dotnet build SwampMonster.sln

Running

$ cd SwampMonster.CLI/bin/Debug/net5.0/
$ ./SwampMonster.CLI.exe ../../../../EventSwamp.sln -o EventSwamp

Terminology

Sinks

External events to which an object subscribes. Typically, subscriptions are established in an object's constructor or when the object gains ownership of another object.

Sources

Events which an object raises to zero or more subscribers. The object does not know how many subscribers there are. Further, the order in which subscribers receive the events is indeterminate.

How to Use

As a practical example, we have used Swamp Monster on another open source project, nERD, which makes extensive use of events.

Finding an event

document-opening

This is the main page (index.html) which is generated by Swamp Monster. You can browse for an event or search for it in the search box. Once you have found an event of interest, either click on Find or the link to the event.

In this case, we are interested in the ModelView.DocumentOpening event.

Going to the event source

model-view

We are now at the class (ModelView.cs) where the event is defined (and raised). There are several sections of information:

Sinks

Sinks are all events which are coming into the class ie all events the class is sinking. Each event has an indication as to the origin (class + file location) and clicking on a link will go to this class.

Sources

Sources are events which are raised by (or going out of) this class ie all events the class is sourcing. Each event has an indication of the file location.

Code

This is the C# source code of this class.

Notes

  • events on interfaces will be sourced/sinked on every object which implements the interface. This is at least consistent with Find usages functionality in JetBrains Rider.

Third Party Components

Further Information:

Further Work:

  • support WPF IEventAggregator
  • highlight source code where event is sinked/sourced
  • generate a sink/source graph
    • could be difficult to visualise for all but the most trivial cases