4

I'm not sure how to start to explain my question, but here goes.

We have just finished an MVC application that hits 2 WCF services. But there has been a bit of a disagreement between those who worked on the project and some who haven't over the design used. What we have is two WCF services, one on each site (site specific data) and another at head office (data shared/common between all sites). Normally we would have two apps, one for site and another for head office. In this case I decided from a UX point of view that it would be better to have it look like one app from the users point of view so they would not need know two urls. Basically, the user does not know if they are hitting site or head office.

Now comes the design decision that has caused the disagreements. The MVC App has controllers that need to hit either a site wcf service or a head office WCF service. So to prevent the need of the controllers needing to be aware of the two WCF communications layers and converting the WCF results into a model the controllers could use, I created a layer in between the controllers and WCF Proxies. Which accepts a request from a controller, then calls the appropriate site or central WCF proxy call, then if needed, convert the WCF result into a model that the controller can use.

This layer, I called a Mediator, but after much discussion, I am of the opinion that it is not the correct description for it. Anyway, the reason for this layer is when tring to keep to the SOILD object oriented principles, in particular the Single Responsibility Principal. The controllers responsibility is to handle client requests and return a view/result. It should not need to know or maintain a WCF proxy and convert its result. (It could go directly to a database instead of a WCF call but the controller shouldn't be responsible or even aware of that because it is responsible for the view) The same goes for the WCF proxy, it should not know what is consuming its result and that the WCF data contract should be converted into a model specific for each controller. The mediator layer in between is what decides which WCF service and method to call and then either via a extension method or a specific handler converts the result to a model the controller can use. (sometimes it may take several wcf calls to create the model).

Controller1 -> Mediator -> HeadOfficeWCFProxy
Controller2 -> Mediator -> SiteWCFProxy
  • So the controller asks for data (not knowing where it comes from)
  • The mediator converts and passes the request to the appropriate WCF Proxy(s)
  • The WCF Proxy(s) make the calls across the wire and return the results.
  • The mediator then converts the result(s) into a model (if needed) via an extension method and returns it to the controller.
  • The controller renders the view using said model.

Now what I described here was just on the MVC side. I have a similar setup on the WCF service side but the mediators benefit is clearer.

On the head office WCF service

WCFListener -> Mediator -> DataLayer (LinqToSQL)
                        -> SiteSyncHandler (sends change to all sites asyncronously)
                        -> ThirdPartyContentManagementHandler (via web service)

Now the devs that have worked on the project, like the separation of concerns alot as it is very clear where everything belongs and keeps code to a minimum in each layer. But the down side in the MVC app is for a lot of the calls the mediator just makes a single WCF call and doesn't even need to convert the result (most of the time the data contract is fine for use as a model) resulting in a fair amount of one liner method boiler plate code. The mediator doesn't really add much in that scenario except to keep things consistent across controllers. Some devs that haven't worked on the project, insist that there is no need at all for the Mediator layer and that it could be all handled by the controllers themselves. Which means maintaining the appropriate WCF Proxy in each controller. This in my mind violates the Single Responsibility principle. To which they argue that SOLID is more like a set of guidelines, and not to be blindly followed. Which while I kinda agree with that statement its also not to be blindly ignored.

I have conceded that the term mediator is not really appropriate (perhaps director or relay), but I still think the basic design is valid, and would use it again. The same can be said for those who have worked on the project. I would like to know what other people think. Is there a better solution or have I "over complicated it". (I still don't agree that is is complicated, its a very simple concept and easy to maintain)

1
  • 1
    IMO Facade would be a better name than Mediator. Jul 27, 2012 at 7:48

5 Answers 5

3
The mediator doesn't really add much in that scenario 
except to keep things consistent across controllers. 

Well, actually it does.

Keeping things consistent is, in my opinion, in and of itself a huge advantage well worth the trouble.

The added benefits I see is that having the Mediators:

  • allows you to add other sites
  • provides a covenient point for adding load balancing
  • allows you to change the communication method/framework
  • ... (a whole bunch more)

And all without changing a single line of code outside of the mediators!

Basically it means your app is better modularized, and I have not yet come across a situations where that wasn't beneficial, even if the things that it insulates your app code from never change. It just makes all the other stuff less complicated simply because setting up the provider is no longer a concern.

So stick to your SRP guns. Convenience is hardly ever a good advisor when it comes to building maintable systems.

An interesting presentation on the simples versus complex and how we mistake ease for simplicity: http://www.infoq.com/presentations/Simple-Made-Easy It was a "ah yes, finally someone who puts what I have been thinking/feeling about this subject into words" experience.

1
  • That was a great link. I like way he describes simple vs easy. I'm still finding my feet when it comes to implementing OO principles, so when I get comments like "it's over engineered", I find it hard to defend against. I just know/feel its better than what I was doing. All these answers and that link just reinforced that I'm heading in the right direction. Many thanks for your answer. Jul 30, 2012 at 11:02
2

Sounds well thought out. One thing web developers often don't get is, that servers (or the WCF service in your case) and clients (web application, mobile application or whatever) are two separate things, and should NOT be mixed up. You find plenty of so called MVC implementations that think it's a good idea to place controller and model at the server, and have the view on the client. They feel all not really satisfying.

When it comes to web development, somehow good developers stop to think. Somehow they don't spend any thoughts at a clean and reliable architecture. So, you did it well. Full stop. Leave the context, name it module "A" and module "B", whatever, and suddenly it doesn't look arguable anymore.

A clean way would be to have a full MVC stack at client side. Of course your Controller doesn't want to know how exactly your data is stored. Thats the model job, after all. If the model works with a database or a web-service doesn't matter, right? Your idea with the mediator in place is a good one, for every reason you mentioned.

2

I hope I understood the situation, but for sure, I try to summarize it.

You have a separated "master" (shared tools, common data and functions), and (multiple?) "satellite" (site specific) services. Your application connects to one satellite (depending on the login, or the client logs into the site?) and also uses the services of the master. It is a natural decision that the users should not be aware of the fact that they use both within the same application - the question is how to handle this scenario programmatically. Of course, I don't know enough about the actual situation to answer this question, so I just throw in my view that you may find useful.

Your single application "hosts" several components: units with their data, business logic and user interface. Together they build up the whole app: the menu or a dashboard activate them, and perhaps multiple components can appear on a single screen, perhaps from different WCF services. Some of them may "be around" in the app for other components to use them.

The question here is: how you view the role of the application? It may either be

  • heavyweight, "I MANAGE" type: it hides the heterogeneous nature of the system, showing a single entry point to any service and dispatch the requests to the appropriate servers (therefore I would call this Dispatcher, but I don't know if this is a reserved word in the world of patterns)
  • lightweight, "I SERVE" type: knowing that there are different servers and their possibly independent services (growing, changing), it does not try to mimic a single "virtual cover" layer above all, but contain multiple server connections, from which the components select their own.

Without knowing too much about your task (and absolutely zero knowledge on WCF), the second approach seems more comfortable. I think you are right in that components should not own their connection, because many of them share the same (head or site) - but they could refer to it. Your Mediator (that now appears to be all-in-all) should only resolve these references for the components, and also do housekeeping (state, communication, error management, etc.). With this approach, you would

  • keep the central role of the Mediator (a location for logging, throttling, caching, etc., no "quick and dirty" direct solutions in components), but
  • forget about managing the global service layer all the time when new sites appear, or any service is modified (although if you need app level management for the connectors, you should inject that into them - but this time your implementation adapts to their interface).

My 2 cents.

If this sounds good, the transition is not too complex. You already have the multiple connection management layer, you only have to open it and let the components access it directly. The dark side is that you have to move the central management part down, from the global cover layer into local cover layers above each connection.

I don't say this because I think you should change anything, I know far too little to have such opinion [EDIT: I don't even know whether this approach is viable in WCF, I have spent only 3 weeks with C# in my life, and I have found it quite quick and handy], but I think you should consider both options objectively by the required implementation and maintenance cost, both in short and long term.

2
  • It's actually a far simpler scenario. The website only talks to one site service at any one time. There is a site switcher module that allows the user to change which site service the mediator uses, but the rest of application has no idea it has been switched. In truth, the mediator doesn't even know that it's using wcf. It just has a reference to an object it passes calls onto. that object can be swapped out at any time. Wcf being very easy to implement and create proxies at runtime, means I just need to store a list of uri's on the central server that I can add to or remove as needed. Jul 30, 2012 at 7:23
  • I assumed that the mediator implementation is something like this, and it is fine. My problem is that the interface of this mediator, used by the the system modules, "contains" the union of services behind it (if I got it right), instead of providing a simple transparent layer for them to access "their" server channel (URL, a proxy object, or whatever it is). I would prefer the latter for the reasons I have mentioned in the answer - but it depends on the actual environment, and the complexity of management features you have in your current mediator: your solution can be the right answer. Jul 30, 2012 at 8:43
1

I favor your side of the argument:

The controllers responsibility is to handle client requests and return a view/result. It should not need to know or maintain a WCF proxy and convert its result. (It could go directly to a database instead of a WCF call but the controller shouldn't be responsible or even aware of that because it is responsible for the view)

When using the MVC pattern, you must keep your controllers skinny.

Furthermore, if you put the client proxies directly in the controller, you lose your ability to use dependency injection and perform automated unit-testing.

0

What you are suggesting is a service that seems desirable to abstract away from the controllers. It should also improve the ability to test the controllers by removing the concrete calls to the service (the D part of SOLID).

Maybe instead of "Mediator" call it a "Service Bus" as it is more likely to draw recognition and is catchier.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.