views:

76

answers:

4

Hi, I am looking to write some webservices.

What defines one unit of "service". I note that as apart of one project you can have multiple .svc service files.

How do you normally segment your services? For example, a banking app:

Would you have one service (.svc) for?

  • Client
    • AddClient(Client newClient)
    • DeleteClient(Client client)
  • Account
    • SetName(string name)
    • SetType(AccountType type)
  • Transfer
    • SendMoney(Client client, etc)
    • ReceiveMoney(Client client, etc)
  • HomeLoan
    • AddNewHomeLoan();
    • RemoveHomeLoan

Is there a method of grouping the entities? For example, instead of having a transfer service, you could put send and receieve money in account service because you receive and send out of accounts.

This also brings another question in regards to methods and parameters. If I wanted to add an edit client, would one normally add a method like EditClient(Client client, Client newClient), and replace the whole client with another client object? Or would you add separate methods for editing a client for example: EditName(Client client, string name) under Client service?

I'd like to properly lay out where the operationcontracts will fit in my web services.

+2  A: 

I would suggest reading the Pattern of Enterprise Architecture by Martin Fowler. This should give lots of organisation tactics for service oriented software.

Preet Sangha
Fowler is a hack, I'd avoid him like the plague.
Pierreten
Disagree strongly. I've never heard anyone say that about Fowler. Care to elaborate?
John Saunders
+2  A: 

I prefer to separate my services by function rather than structure. This technique is discussed in depth in Domain Driven Design by Eric Evans. One of the drivers behind this is rate of change. Functional areas tend to change at a similar rate.

Structural (bad):

  • Client
  • Account
  • Loan

Functional (good):

  • Billing
  • Provisioning
  • LoanApproval
Michael Valenty
+3  A: 

There are a couple of rough rules that I like to follow when designing webservices, especially for a exposed (where the services might be consumed by apps/users outside of some defined group) services.

  1. Maximal Units of work: Webservices (really any RPC service) is another piece of software running on a seperate (usually) machine, you have an expense in making the call to it (unlike a local function call) even if its on the same machine. Keep this in mind and build functions that were possible accept as much data as possible. Dont rely on roundtrips between servers to communicate and complete units of business operation. For instance, dont have a process "create account" which requires a call to "add user", "create account", "associate user with account", "update user details", "activate account" just to complete the process. Instead have a "createUserWithAccount" function that does it in one trip.
  2. Minimal Wait time: Remember these services are called inline, and if your process takes to long its possible for the process to be killed, either by an impatient user, a service in between or a watchdog process assuming there has been an error. You might consider preferring services which return "tickets" that the caller can then check on later. In most circumstances this is not strictly necessary, but for processes that might take more than a minute to run you might want this approach
  3. Well defined interfaces: Make sure your services have well defined, and preferably type agnostic definitions. Type agnostic defined here as making sure you use common types that are easily communciated, and have little chance of having unintended side effects for client implementers. Lots of people prefer to use XML as the basic of message transmission and hide all their details inside of that.
  4. Plan for changes: Services are in place for a long time (by design) and simultaneously exposed to external implementers. This means that they will need to change, but customer requirements may prevent you from doing it easily. When building your interfaces consider either versioning, or using transport encodings (like XML) which allow you to modify the data transmitted without modifying the calling interface. Look at how APIs (like the windows API) deal with this to get some ideas about how it can be problematic.
  5. Security as a first-class design goal: Service interfaces can be called by anyone. You have to expect that they will be called by all kinds of users, who may or may not have authenticated, and may or may not be malicious in nature. Plan security to occur at appropriate places, and don't rely on just one mechanism for verifying that everything is secure. There are several ways to approach security, and if your service is used internally you can relax some things but for public services you will need to consider how you want security to work and make sure it remains consistent across all of your services.

Hope that helps.

  • These are general strategies taken from Fowler and others. Just my take on how it should be approached.
GrayWizardx
GrayWizardx has obviously actually developed working services! The only point I would add to try to keep the interfaces which make sense to a Buisness User. eg "CreateCustomer" and not "InsertCnumToAccTable".
James Anderson
Thank you for your very detailed answer.
Mike
Are you recommending that it should replace the whole client object, if editing a client to save calls back and forth between the client and the service?
Mike
depends on how you want to implement it. Sometimes you seperate your logic into a backend service and a client object structure that does part of the business processing. This is ok if you control the client, if you do not control the caller you will have to encapsulate all of the logic in the service, in which case you should prefer high-level functionality as described by a few others.
GrayWizardx
+2  A: 

In addition to GrayWizardx's excellent answer I would add one further point.

Try to keep all your service definitions at a functional/business level. Service names should have nice high level "ChangeDeliveryAddress", "QueryOrderStatus" type names and the interface definitions themselves should contain only business entities and a minimal number of "technical" fields. i.e. A complete separation of interface from implementation.

If you find yourself with services like "NextOrderLineWithinPage" then probaly something has gone wrong with your design.

James Anderson
Your answer actually gave me another question. Say you want to list of all your clients, and you have 100,000 clients. You'll want some sort of pagination function. Should pagination be used in the webservice? I.e. GetClients(int page, int perPage, string searchTerm) ? or should that be handled by the client?
Mike
Thats a nasty one with no clear answer. In princple its better to encasulate everything within a single server, but the "request/do the work/format the reply/send the reply" pattern does not work so well when you get 1000s of entries in the reply. Usually the interface includes "Start After" and "Max Replies" parameters so the client can manage pagination.
James Anderson