June 21, 2007
- A service should use convention over configuration so there should be minimal configuratios required.
- A configuration name should be descriptive and should include service name if it is required.
- A configuration should support aggregation of properties from different sources. For example, you may be combining some configuration properties from multiple files.
- A configuration should support property overrides, either using embedded property files. external property files or runtime arguments.
- A configuration should support hierarchical properties.
- A configuration should be reloadable either using file touch or database refresh.
- The service should provide a way to dump the configurations it is using.
- The configuration files should support symbols that can be provided by the runtime environment. For example, in certain cases, you may need to define similar configurations for different environments such as database name for US is US_myapp and for Canada, it is CA_myapp.
- A service container should independently load each service and all dependent configurations so that they are managed indpendently.
- The configuration system should support annotations based properties if supported by underlying language.
- A service should be language and platform independent and should be easily locatable via registries such as LDAP, UDDI, ebXML. Though, lower level services or closely cohesive services can use native languages or protocols. A service should have a unique name and a version number, so that different versions can be running at the same time.
- A service should require a minimal installation. In other words, clients should not be required to install any software locally, though a simple jar file is acceptable that can be easily embedded on the client. However, a service should ideally use protocols that are already available on most computers such as TCP/UDP or HTTP, which can be easily done for REST based services.
- A service should fail fast. During service initialization or invocation, it should verify all inputs and dependencies and throw informative errors right away.
- A service should provide meaningful and specific error messages or error codes. There should not be messages like InternalError or unknown-error. Additionally, if stack trace is available then it should pass a copy of it as well.
- Though, some high level services can be stateful, but in general services should be stateless.
- A service should provide a way to pass batch of input data, i.e, they should be easily composable. However, in order to minimize memory consumptions, it could provide scrolling APIs instead of return list of items.
- A service should provide a way to invoke asynchronously. This allows service to reduce dependencies. Also, services should be easily recoverable in case of crashes, i.e., no messages are lost.
- A service implementation should use queues for incoming requests, which can be done either by using messaging middleware or via some connection queue. The queues can also be persistent for reliable services so that when a service is down, the requests are not lost. Also, messages should be ordered so that execution of those messages are also performed in order. For example, when insert request and update requests are not in order, then data can be corrupted.
- A service implementation should use pull instead of push for invocation. This helps scalability because when server is busy, service can throttle requests.
- A service should provide logging, monitoring, life-cycle management and for financial or secured services authentication and auditing capabilities. A good lifecycle management can also be used to hot deploy service, where a new version of the service can listen for new requests and old service can serve existing requests and then dies off once it’s done. A service should be easily configurable and should support an API to dump the configuration. One of the parameter I like to have for a service is timeout.
June 12, 2007
Powered by WordPress