views:

39

answers:

2

I have an application that uses WCF for all DataAccess. It returns some business objects and it has some operations.

Should this code exist in my Client or in my Service? If in the service, HOW should I implement it? Can I simply add it as an interface to my business object? Will that come through the WCF Service Proxy Code?

(This is a sample from MSDN, I'd like to get some feedback before I implement my own, but it will be 99% the same)

// Custom comparer for the Product class.
class ProductComparer : IEqualityComparer<Product>
{
    // Products are equal if their names and product numbers are equal.
    public bool Equals(Product x, Product y)
    {

        // Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        // Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        // Check whether the products' properties are equal.
        return x.Code == y.Code && x.Name == y.Name;
    }

    // If Equals() returns true for a pair of objects,
    // GetHashCode must return the same value for these objects.

    public int GetHashCode(Product product)
    {
        // Check whether the object is null.
        if (Object.ReferenceEquals(product, null)) return 0;

        // Get the hash code for the Name field if it is not null.
        int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode();

        // Get the hash code for the Code field.
        int hashProductCode = product.Code.GetHashCode();

        // Calculate the hash code for the product.
        return hashProductName ^ hashProductCode;
    }
}
+2  A: 

Remember that data transmitted over WCF (or via any sort of SOAP-based service) are messages only. They carry no behavior (it wouldn't be interoperable), so all your nice behavior will be lost in translation.

This means you really only have one option: Your business logic must reside in the service, as it can't reside on the client.

That said, there are a few ways you can share code between service and client, but unless you are using WCF purely as a communications stack, it is not recommended, as it will tie client and service together, and make it close to impossible to vary those two independently (let alone let new clients use the service).

Mark Seemann
excellent - well said!
marc_s
Thats what I thought -- so I need to make a method that exposes this Comparer that is exposed from my WCF Service?
Nate Bross
My objective is to be able to do this on the client, doing my own comparison: productsA.Except(productsB) (where both are IEnumerable).
Nate Bross
@Nate Bross: I noticed in your comment to Marc Gravell that your comparison is mainly for display purposes. If that is the case, you should implement that functionality solely in the client, as it's not a piece of business logic...
Mark Seemann
+2  A: 

Well, the WCF-generated proxies are partial classes, so you can add behaviour at the client, even if you are using mex-generation.

You can also use assembly-sharing (/reference at the command-line, or check the boxes in the IDE) - then you can use the exact same type at client and server, but it breaks most rules of "pure" SOA.

It depends on how "pure" you feel, I guess. The pain of being pure but having to maintain two similar code bases may outweigh the convenience but dirtyness of assembly-sharing. It depends on what the app is. I've happily used assembly-sharing on a number of occasions, and I feel no guilt; it was the most sensible option for the scenario.

Just remember that client code is a convenience - always treat the client as hostile, so even if your client uses assembly sharing, remember that a hostile client may not, so won't adhere to your rules; always validate at the server.

Marc Gravell
I'm thinking it'll make the most sense to do this at the Client level, because the end result of this compare is for display purposes.
Nate Bross