8. Service Libraries

8.1. Overview

Using Needle as it has been presented so far works fine when you are dealing with a single application, all self-encapsulated. When you start dealing with combining multiple libraries, each potentially written by a different author, into a single registry, things get a little more complicated.

Needle provides a way for service authors to share their services. All it requires is that authors centralize their service configuration.

8.2. Creating Libraries

This centralization is implemented by creating a module for each library you want to have services for. That module should then define a module function called (by default) register_services. This function should accept a single parameter—the Needle container that the services will be added to.

For example, if I had a library of cryptographic routines and I wanted to make them accessible as Needle services, I would create a module to contain the service definitions. Typically, this module will be defined in a file called “services.rb”, although you can certainly name it whatever you like.

Needle-enabled library example [ruby]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Crypto
  
  def register_services( container )
    container.namespace_define( :crypto ) do |b|
      b.prng do
        require 'crypto/prng'
        PRNG.new
      end

      b.des do
        require 'crypto/des'
        DES.new
      end

      ...
    end
  end
  module_function :register_services

end

Notice that there are no explicit dependencies on Needle, only on the interfaces Needle publishes. Thus, third-parties can add service configuration modules to their libraries without introducing dependencies on Needle.

Once a service library has been created, it can then be accessed from another library or application that wishes to import those services.

8.3. Using Libraries

Using the libraries is as simple as requiring the file that has the service definitions, and then invoking the #register_services module function:

Example of using a Needle-enabled library [ruby]
1
2
3
4
5
6
7
8
9
10
11
require 'needle'

reg = Needle::Registry.new
reg.define do |b|
  b.foo { Foo.new }

  require 'crypto/services'
  Crypto.register_services( reg )
end

prng = reg.crypto.prng

To make this easier, the Container class has a convenience method named #require:

Example of using Container#require [ruby]
1
2
3
4
5
6
7
8
9
require 'needle'

reg = Needle::Registry.new
reg.define do |b|
  b.foo { Foo.new }
  b.require 'crypto/services', "Crypto"
end

prng = reg.crypto.prng

The Container#require method will require the file, and then look for a #register_services method of the named module. It will execute that method, passing the container as an argument.