4

I'm trying to expose a fairly complicated class library as a service, I think WCF, but am pretty green and am struggling to understand what I can and cannot do architecturally. If my clients are to be .NET as well (let's say WinForms, WPF, and/or ASP.NET MVC3), it seems like overkill to write a bunch of contracts to re-expose public classes, or to serialize complex objects. It's hard to know from the many tutorials out there, because so many of them only work with value/primitive types.

Is WCF the way to go? If so, which flavor is the simplest to implement if the class library will manage all aspects of data and expose only objects?

A simple analogy: a HumanBody class that needed to be exposed as a service allowing for multiple users, always on, etc. If I have a .NET Applause client, and I want to do something like

ServiceName.HumanBody myBody = new HumanBody();
myBody.Parts.Hands.Clap();  

I'd have to turn those objects into interfaces and write a bunch of wrapper methods, but the objects are "complete" as they exist--this is why it feels like overkill to me. (I know I'm not thinking about this correctly--that's the reason for the question. If these questions are too vague, I will refine on comment/answer.)

(Also, please note that I am not asking how to accomplish this practically--there are many versions of that question already on SO, with a couple notable good answers here and here. There's also a very useful tutorial on how to build your own WCF architecture without the VS auto-added clutter here. I am working through the construction on my own.)

Community
  • 1
  • 1
downwitch
  • 1,362
  • 3
  • 19
  • 40

2 Answers2

3

WCF is most likely the best route for you. However, before you start thinking about how to approach it, I think we need to clarify what a service is just a bit.

A service, regardless of the transport layer that it uses (HTTP, HTTPS, TCP, UDP, MSMQ, carrier pidgeons, etc.) is just a list of operations that take parameters. You cannot, per-se, expose your "HumanBody" class as a service as it is. Services are not object-oriented; they're very much like procedural programming.

You can, of course, send over complex object graphs as parameters or return them as the return value of a service operation. You can also write your client library in such a way that your interface to the service is object oriented, but your actual service commands will not be that way.

To use your above example, you'd have this as a service interface:

public interface IHumanBodyService
{
    ClapHands(<parameters>);
}

<parameters> here would be whatever identifying information is necessary to send to the service so that it can know what to do. That might be the whole myBody object graph (serialized, of course, but WCF will take care of that for you as long as your class is properly annotated), or it might be something as simple as a BodyId or PersonId value.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • Very helpful already... one place I get confused is between what you're suggesting--sending object graphs etc.--and what Anders suggests below, i.e. required simplicity of data transfer objects. Every parameter must also itself be an interface or a serialized object, is what you mean, correct? – downwitch Apr 20 '12 at 14:50
  • Every parameter must be serializable; it doesn't really have anything to do with interfaces. All built-in primitive data types support serialization, and you can use the `[DataContract]` and `[DataMember]` attributes to mark up your own custom types to support serialization. Ideally, you want to send and receive as little data as possible over the network in order to conserve bandwidth. – Adam Robinson Apr 20 '12 at 14:54
  • There's not really a choice between object graphs and DTO's, as you could certainly have a graph of DTO's get sent to or returned from a given service operation. DTO's are just purpose-built classes that exist to carry information to and from a service library (rather than sending larger classes that contain more than the minimum information required). Whether or not you use DTO's in a given operation really come down to a value judgement. How much "extra" information is in the non-DTO class? How often will the operation be called? (cont.) – Adam Robinson Apr 20 '12 at 14:57
  • How difficult would it be to use DTO's and perform the necessary conversions to and from the DTO both on the client and the service? All of these things weigh in that decision. – Adam Robinson Apr 20 '12 at 14:57
  • Yes these are great questions, and I will have to do more research to understand the options, but thank you for presenting them. I think my class library is economically built and, relatively speaking, on the light side already. If I don't enable WCF attributes on every property or method, does that "lighten" the transfer? (Having already built a good DAL/ORM and a good business layer, I am trying to avoid having to code up yet another set of objects. It seems a lot to maintain all told.) – downwitch Apr 20 '12 at 15:05
  • Just to be clear, your classes *will not serve as the service*. They can't. They can *only* serve as objects used to send and receive data to/from the service. You will have to have a dedicated service interface (to define the contract) and class (to implement it). These are technical requirements, not best-practices. – Adam Robinson Apr 20 '12 at 15:08
  • Thanks, I do understand that already, though it was a hurdle in my thinking a while back. Esp. because I essentially built host-type classes into my library, before I understood the separation necessary. I *believe* these classes will ultimately come out into the service assembly, but how best to decouple them is still what I'm puzzling through. – downwitch Apr 20 '12 at 15:11
2

Any interface that is to be run over the network should strive to be as non-chatty as possible. That is, it should preferably perform most operations in one round-trip over the network.

Your example with chaining method calls is a good object-oriented API, but unfortunately it is very chatty with all those function calls. To expose that as a good network-enabled service, it has to be wrapped in a service layer which contains one method for each basic function that the client needs. The data to be transferred has to be grouped into data transfer objects - classes with only properties and no behaviour.

WCF is designed to support this design principle. There is an operation-only service contract interface and data-only data contract classes.

I think that WCF is a good choice, as it helps you to wrap your object-oriented design in a network-optimized service layer.

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
  • Also very helpful. But is it chatty if I cache an object, do stuff to it, and then persist it back? (I realize this is not what my example indicates, exactly.) Also, what is "data" if everything is objects and properties? The objects themselves? – downwitch Apr 20 '12 at 14:55
  • 1
    @downwitch: "Data" is whatever is sent to the service. Your objects and properties will get serialized into some format (XML, SOAP, JSON, binary, etc.) and sent over the wire to the service. Without speaking for Anders, what you need to aim for is send *only as much data as necessary* and *only as frequently as necessary*. – Adam Robinson Apr 20 '12 at 15:00
  • Ok so to state that one more way, data is the actual serialized output, regardless of what it contains? – downwitch Apr 20 '12 at 15:06
  • @Adam Robinson: with that well formulated answer you're welcome to speak for me :-) A comment on the first question: If you get data, do several things to it and send it back it is typically non-chatty. As stated, that's however not what your example indicates. – Anders Abel Apr 20 '12 at 15:41