A few collected thoughts & notes from around the web regarding what makes a good component/service.

  • Interface - all implementations share this. Should have few methods, use data objects as return values, take primitives as inputs, throw only custom exceptions, and be very, very well documented.
  • Implementations - implement the logic behind the service. May provide extra features such as caching, or such things as optional collaborations.
  • Data - data objects this service deals with. Should be immutable, comparable, cloneable as much as is possible. Should be serializable/XML/Persistance annotated in most languages.
  • Storage - Data (or data.io) package should define storage API, and an in-memory data store. Allow other services/projects/subprojects to define database backed or other kinds of data stores.
  • Cache - Data.Cache packages should define cache API? (or can this be standard per runtime?) Who should be in charge of caching? The service itself, or the user of the service?
  • Use dependency injection for all services/data stores it requires. Use constructor-injection as much as possible.
  • Throw errors early - in constructor if possible.
  • Exceptions - custom exceptions for high level categories of erroneous behavior (try not to do one for every possible condition - classify, and wrap). * Don’t re-throw exceptions from other frameworks - wrap in custom exception.
  • Make behavior configurable via dep injection as much as possible. Use filters or strategies.
  • Inject 1 configuration object instead of many options. Standardize on configuration API/Framework for each runtime/language.
  • Standardize on logging framework/API for each runtime/language, and make sure it’s used (instead of System.out or similar)
  • Provide events/messages and/or hooks for important happenings so others can do things pre/post.