Академический Документы
Профессиональный Документы
Культура Документы
• Contract/Interface
• Transport
• Location
• Time
• Login
• Validate Order
• Place Order
This should look funny to begin with for a few reasons. First of all this looks a lot more
like an API than a service, and second you can see there is probably some sort of order
expected for these operations,
but it is not clearly defined. You would need a separate read me document to tell you that
you must first call the Login operation, then Add Item to Basket, then Validate Order
before calling Place Order.
WS-Policy is one way to solve the order of operations, but it would only mask the
problem (mostly because it is not widely adopted or understood).
This example service also violates other principles: Autonomy and Statelessness (these
will be covered in a later post). By requiring multiple separate operations to be sent in a
specific order this service implicitly
contains state within it (if it didn’t it wouldn’t know about your shopping cart or the items
in it) and it forces consumers to understand its internal working (the order of operations).
These are bad signs as changes
to the service will almost certainly impact the consumer. Let’s suppose your service now
needed to calculate tax or shipping. This type of service would have no real place for
them.
This service should really exist as one operation: Place Order. In the implementation of
this service the validation and login should all take place together in one unit of work or
transaction script.
The continuum of coupling
Service design is a series of tradeoffs; the impacts of which are not always immediately
clear and thus coupling is really a continuum and where your services fall on this
continuum will vary with every implementation
based upon these tradeoffs. For instance the goal of flexibility is in direct opposition with
the goals of validation and control. This is why service design deserves careful attention
before you begin implementation.
This is the essence of contract-first development, and it is a good idea both in code and in
services. Test Driven Development really shines here because you will get to know what
your services are like before you are stuck with their legacy implementations.
Definition of Loose Coupling
When I alluded to that definition of loose coupling I would probably break it down like
this: Something is loosely coupled if its interactions are separated by abstractions of type,
transport, platform, and state.
So how can you tell if a service (or code for that matter) is loosely coupled? This part is
strangely simple. If it is difficult to test a service, class, or method then it is probably not
loosely coupled. Inversely, code
that can be easily tested without major setup and teardown is loosely coupled. To be clear
when I say test, I mean effective, completely automated tests. It’s very easy to make tests
that are almost useless without
realizing it. A test suite for even a single service should cover all the major expected
scenarios for valid and invalid service invocation.
This is one of those “Code Smells” Martin Fowler writes about in Refactoring and you
should be aware of it. When you start to realize your setup and teardowns are very large
and cumbersome your code is
slipping into tight coupling. This is the same for services and code in general (which is
normally service implementations). This is probably the last warning sign that you’re
about to have major maintenance problems;
unless you don’t have adequate tests, in which case you’ll end up with major production
problems.