简体   繁体   中英

Event subscription best practices

I recently stumbled across the following in our application and I'm curious to know whether this is good or bad practice. What I see is events being subscribed to on different levels in the application, business logic and ultimately our framework.

We have functionality to authenticate and authorize users, which is orchestrated by an HttpModule which basically does the following (I only included the most relevant parts):

    public class FooModule : IHttpModule
    {
        private IIdentityProvider _identityProvider;

        public void Init(HttpApplication context)
        {
            _identityProvider = TypeFactory.Create<IIdentityProvider>("...type string from configuration...");
            identityProvider.Init(context, ...);

            context.PostAuthenticateRequest += OnAuthenticateRequest;
            context.PostAuthenticateRequest += OnAuthenticateRequestLogging;
        }

        ...
    }

So far, so good: the HttpModule identifies the configured identity provider, initializes it and subscribes to some events. The event handlers are not in question here, so I omitted them.

Then, in the initialization of an arbitrary identity provider:

public class BarIdentityProvider : IIdentityProvider
{
    public void Init(HttpApplication httpApplication, ...)
    {
        var authorizer = new BarAuthorizationProvider();
        authorizer.Init(httpApplication, ...);

        httpApplication.PostAuthenticateRequest += httpApplication_PostAuthenticateRequest;
        httpApplication.AuthorizeRequest += httpApplication_AuthorizeRequest;
    }

    ...
}

And in the AuthorizationRequestHandler the following happens:

public class BarAuthorizationProvider
{
    public void Init(HttpApplication httpApplication, ...)
    {
        httpApplication.PostAuthorizeRequest += OnAuthorizeRequest;
    }

    ...
}

As you can see, there are events being subscribed to in FooModule, BarIdentityProvider and BarAuthorizationProvider which, to me, comes across as event spaghetti. Also, when doing this:

var authorizer = new BarAuthorizationProvider();
authorizer.Init(httpApplication, ...);

I do not expect the authorizer to subscribe to various events and work 'magically'.

As a software developer I expect either:

  1. one HttpModule which subscribes to the necessary events and requests the identity provider and authorization provider for identity and access information. Event handling is minimized in the providers.
  2. multiple HttpModules (ie an authentication and an authorization module) which each subscribe to the necessary events. Event handling is minimized in the providers.

Am I correct or are there arguments against my expectation?

My first question would be, is it important that "Event handling is minimized in the providers"? Ie what specific advantage is there to achieving that goal?

I also wonder what "event spaghetti" is supposed to mean. I mean, it clearly references the age-old concept of "spaghetti code", but that concept refers to code where the path of execution is convoluted, most often due to the use of unstructured flow-control (ie goto statements). I don't see how when discussing event handling, there's anything resembling spaghetti.

In other words, the phrase "event spaghetti" simply seems prejudicial here. Ie the word "spaghetti" is just being thrown in because it's already understood as a pejorative. But lacking a clear objection to the implementation, the pejorative seems unjustified on its own, and the word "spaghetti" does not seem to offer a genuinely useful metaphor as it does in the context of "spaghetti code".


So, back to "minimizing event handling in the providers". Why should this be important? You write that "the event handlers are not in question here", but that seems to indicate that the handlers in the providers are appropriate. Ie they do work that is relevant to the provider (likely only to the provider). So how else are they to do that work?

In my opinion (the fact that I wrote that suggests that your question might be considered off-topic, being "primarily opinion-based", but I think there's an objective way to look at this, even if that's simply my opinion :) ), one of the big advantages of the event-based programming model is reduced coupling. Assuming the work has to be done somewhere , the alternative to these provider objects subscribing to these events is for some other object to understand the needs of the provider object, and to fulfill that need on the provider objects' behalf.

But then you've just laden that other object with specific knowledge of the provider object. Which increases coupling between the types. Which is generally a bad thing.


If on the other hand, you feel that the event handlers in the providers can be moved to some other type without coupling the types more strongly, then that suggests the event handlers are indeed inappropriate in the providers. But in that case, the specific details of those event handlers most certainly is pertinent here, contrary to your assertion.

Ie where the event handler goes depends a great deal on what it does. But since you don't seem concerned with the specific content of those handlers, that suggests they are right where they belong, and thus the subscription to events is not a problem at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM