Background
There are many different approaches to developing software, but in my opinion, the opposite ends of the spectrum end up being:
- Knowing how the whole system looks, feels, and operates before coding a single line
- Having an idea of what the user wants and coding to make it happen
Although I'm generalizing a lot here, it's sort of like the battle between Waterfall and Agile. Okay, great. So what am I rambling on about here?
Well, in the first case, you know all the ins and outs of the system. You can structure your system so that almost no matter how complex it is, you can ensure that method A is always run immediately after method B which is etc. The design is completely controlled. You have a spec for how all the components work together. The problem? Well, most of this will be reserved for another write-up, but in our case there's no flexibility. If that spec changes after your complicated system is already in place, how much code do you have to go change?
Enter: Events
Okay, so I hinted at why something like Waterfall might cause some headaches, but you don't need to develop your software in an agile fashion to have flexibility. Events can help you with that!
If you're not already familiar with what an event is, it's simply a delegate that one would call when some particular criteria is met. In C#, which is what I'll be assuming for this write-up, you add event handlers to an event so that when the event is invoked, the event handlers get called (and they get called in the order that they were "hooked" onto the event). Splendid.
So what's great about events? How are they going to fix your brittle code? Well, if you approach software design in terms of components in a system and how they interact, it's really beneficial to think about how certain things react to each other. If you're planning your whole system out ahead of time, you could just always call method A, then method B, and then method C in order every time you want something in particular to happen. But is that flexible? What happens when method B now calls an additional method, let's say method D, due to some architectural changes that had to be made. Well... That's all fine and dandy unless you have scenarios where you don't want to run D in your A,B,C method calls you have everywhere.
So, what if you had thought about it this way:
- I want B to run once A is run.
- I need an event for A.
- I need to call method B in my event handler for event A.
- I want C to be run once B is run.
- I need an event for B
- I need to call method C in my event handler for event B.
And then someone comes along and throws method D into the mix. Well, you know that there is at least one particular case where you want D to be run after B is run... So make another event handler! Your listing now changes to:
- I want B to run once A is run.
- I need an event for A.
- I need to call method B in my event handler for event A.
- I want C to be run once B is run.
- I need an event for B.
- I need to call method C in my event handler for event B.
- I want D to be run when condition X is met after B is run.
- I need an event for B (which I already have!).
- I need to call method C in my event handler for event B.
- I can add a whole second event handler for event B (so I get C then D called)
- OR I can modify the existing event handler that calls method C to conditionally call method D when necessary
And now how do you check the condition? Pass in some fancy event args with your state.
Summary
Events can help you keep your code flexible when your structure is changing because they provide hooks into the code when certain conditions are met. You don't need to rely on a firmed-up design for how methods are required to be called in some particular order. If your design changes because you want something to execute under different conditions, just hook up to the event that meets those conditions instead and re-write minimal code.
I'm huge on using events in my architectures, so I'll try to write up a few more posts on events and why I like them. The flexibility I just described is only one very small part of it, and it certainly requires that you shift your perspective on how components in a system interact.
CodeProject