When your module needs to do something that isn’t directly related to user interaction, you should consider creating a service. A service is any reusable utility and may not necessarily be unique to your application or web page. You can think of a service as a library of functionality that may be used in multiple places.
Services are defined by calling
Box.Application.addService(). This method accepts two arguments: the service ID and a creator function. This is similar to
Box.Application.addModule() but with one important exception: the argument passed to the creator function is
Box.Application. That’s because services are considered to be extensions of
Box.Application and therefore are able to access all of the available functionality (as opposed to modules, which only may access a subset of the functionality).
The basic format for services is:
There are no predefined patterns for services, so you are free to create an interface that is appropriate for your needs. There’s also no lifecycle for services, as they are simply libraries of functionality that must define their own lifecycle (or lack thereof).
In the credit card validator example, the actual credit card validation functionality is a good candidate to be a service because credit card number validation is a generic algorithm that could be used anywhere. It’s comprised of Luhn algorithm for checksum validation of the credit card number and ensuring the expiration date is in the future. Here’s the credit card validation service:
The service exposes three methods:
isExpired(). There’s also one private function called
doLuhnCheck() that performs the actual checksum validation. Keep in mind that not every consumer of this service will use all of these methods, however, all of the methods are useful on their own and make it easier to write tests for service.
When a module or another service wants to access this service, it can do so using
context.getService() (in modules) or
application.getService() (in services) and passing in the service ID. For example:
All services are lazily-initialized, so the service creator function isn’t called until the first time a module requests the service. The call to
getService() returns the object that was returned from the service’s creator function.
In the credit card validation example, here’s how the module uses the service:
In this code, the module stores a reference to the credit card service in
creditCardService. That object is then used to validate the credit card number when the validate button is clicked. Depending on the validity of the credit card, a message is populated on screen.
For this example, you’ve seen how to separate functionality between a module and a service. For most features, you’ll begin with a module and then determine what functionality belongs in one or more services. In general, it’s a good idea to put functionality into services whenever there’s a possibility that it may be necessary somewhere else in the application.
The full example is available online.