Wrapper NServiceBus.IHandleMessages

I am asked to develop a layer that will act as a shared bus without any direct links to NServiceBus. Which is still thanks to the support of unobtrusive messages are not too complicated. Except now, I was asked to provide our own definition for IHandleMessages and find a way to map it during connection. So I think something like this:

public class MessageHandlerAdapter<T> : IHandleMessages<T> { IUnityContainer container; public MessageHandlerAdapter(IUnityContainer container) { this.container = container; } #region IMessageHandler<T> Members public void Handle(T message) { var handler = container.Resolve<IHandle<T>>(); handler.Handle(message); } #endregion } 

Where IHandle will be our own definition (which, by the way, is exactly the same as IHandleMessages). I would expect to flip AppDomain and find all the classes that implemented IHandle and register them in the container, and then register a MessageHandlerAdapter with the same type T.

My problem is that I have not used NServiceBus for almost two years, and I do not remember where you can connect to similar functions in the NSB pipeline.

+7
source share
1 answer

You may not like this answer, but ... do not write abstraction layers for the tools you use.

I have seen many times when people tried to write an abstraction layer around certain tools. In most cases, these are journaling and ORM frameworks. Now people have good intentions when they do this. They want to "be able to easily switch the X library." Unfortunately, this is a bad idea for several reasons.

  • Incompatible concepts. In your example, you can extract the NSB Saga timeout concept. However, there is no guarantee that this concept will behave the same as in the theoretical “library to switch in the future", or that the concept will exist at all. Usually these “layers of abstraction” turn out to be a direct map of a separate library and are generally not portable.
  • Added complexity. You will add a lot of complexity to your decision.
  • Samples will not work. when you look at the library samples, you will need to "display in your" layer of abstraction.
  • Barrier to enter. Although new developers joining your team may have used this library, they will not understand your shell
  • Fighting the API. No library has ever been designed with the ability to "be able to extract a common implementation." Because of this, the API will actively struggle with you, performing this activity.
  • Debugging An extra layer will make it harder to debug your solution.
  • Performance. In general, more code is slower than code. Also often these layers of abstraction should use reflection ...
  • Support service. It will be more difficult for you to get support from people who own the library because it will be difficult to document how you interact with the library.
  • Ongoing changes. Each time the corresponding library adds or modifies the API, you will need to add a mapping code before you can use this functionality in your solution.
  • Documentation. Often a huge amount of man-hours was spent creating documentation for libraries. It will be a significant effort on your part to bring the documentation for your abstraction to this level.

It all comes down to time. You are trying to waste time abstracting the tool. Hoping to save more time in the future. The problem is that you will spend much more time creating and maintaining this abstraction than you will ever save if you decide to switch. This should be your answer to your colleagues.

Here's an interesting post from Ayende that talks about the vices of abstraction. A lot of this applies to this scenario http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer Quote

... try to avoid unnecessary complexity ... Adding additional layers of abstractions usually only complicates.

+42
source

All Articles