Separation of SOA services
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 param开发者_如何转开发eters. 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.
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.
- 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.
- 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
- 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.
- 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.
- 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.
I would suggest reading the Pattern of Enterprise Architecture by Martin Fowler. This should give lots of organisation tactics for service oriented software.
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
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.
精彩评论