needle 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/doc/manual-html/chapter-1.html +138 -78
  2. data/doc/manual-html/chapter-2.html +180 -99
  3. data/doc/manual-html/chapter-3.html +111 -75
  4. data/doc/manual-html/chapter-4.html +80 -48
  5. data/doc/manual-html/chapter-5.html +106 -56
  6. data/doc/manual-html/chapter-6.html +82 -34
  7. data/doc/manual-html/chapter-7.html +74 -38
  8. data/doc/manual-html/chapter-8.html +70 -41
  9. data/doc/manual-html/chapter-9.html +88 -63
  10. data/doc/manual-html/index.html +6 -6
  11. data/doc/manual-html/needle.png +0 -0
  12. data/doc/manual-html/{manual.css → stylesheets/manual.css} +83 -10
  13. data/doc/manual-html/stylesheets/ruby.css +17 -0
  14. data/doc/manual/chapter.erb +20 -0
  15. data/doc/manual/img/Needle.ai +0 -0
  16. data/doc/manual/img/needle.png +0 -0
  17. data/doc/manual/manual.rb +80 -5
  18. data/doc/manual/manual.yml +3 -3
  19. data/doc/manual/page.erb +1 -1
  20. data/doc/manual/parts/01_use_cases.txt +70 -70
  21. data/doc/manual/parts/02_creating.txt +19 -19
  22. data/doc/manual/parts/02_namespaces.txt +29 -29
  23. data/doc/manual/parts/02_services.txt +40 -41
  24. data/doc/manual/parts/03_conventional.txt +20 -20
  25. data/doc/manual/parts/03_locator.txt +44 -44
  26. data/doc/manual/parts/04_overview.txt +1 -1
  27. data/doc/manual/parts/04_setup.txt +32 -32
  28. data/doc/manual/parts/customizing_contexts.txt +14 -14
  29. data/doc/manual/parts/customizing_interceptors.txt +25 -25
  30. data/doc/manual/parts/customizing_namespaces.txt +12 -12
  31. data/doc/manual/parts/interceptors_attaching.txt +29 -30
  32. data/doc/manual/parts/interceptors_custom.txt +16 -16
  33. data/doc/manual/parts/interceptors_ordering.txt +5 -5
  34. data/doc/manual/parts/libraries_creating.txt +18 -18
  35. data/doc/manual/parts/libraries_using.txt +19 -19
  36. data/doc/manual/parts/logging_configuration.txt +13 -13
  37. data/doc/manual/parts/logging_logfactory.txt +21 -22
  38. data/doc/manual/parts/models_models.txt +8 -8
  39. data/doc/manual/parts/models_overview.txt +1 -1
  40. data/doc/manual/parts/models_pipelines.txt +22 -22
  41. data/doc/manual/{manual.css → stylesheets/manual.css} +83 -10
  42. data/doc/manual/stylesheets/ruby.css +17 -0
  43. data/lib/needle/definition-context.rb +3 -2
  44. data/lib/needle/lifecycle/proxy.rb +1 -1
  45. data/lib/needle/version.rb +1 -1
  46. metadata +94 -85
@@ -14,7 +14,7 @@ product: !^product
14
14
  name: Needle
15
15
  tagline: to the point -->
16
16
  version: !!eval require "../../lib/needle/version"; Needle::Version::STRING
17
- #logo: needle.png
17
+ logo: needle.png
18
18
  urls:
19
19
  - Project Page: http://rubyforge.org/projects/needle
20
20
  - User Manual: http://needle.rubyforge.org
@@ -23,8 +23,8 @@ product: !^product
23
23
  - Needle Wiki: http://needle.rubyforge.org/wiki/wiki.pl
24
24
 
25
25
  recent_updates:
26
- - Described parameterized services
27
- - Added multiton service models to list of available models
26
+ - Added Needle graphic (thanks to Bruce Williams)
27
+ - Added syntax highlighting to code blocks
28
28
 
29
29
  chapters:
30
30
 
@@ -1,7 +1,7 @@
1
1
  <html>
2
2
  <head>
3
3
  <title><%= manual.product.name %> Manual<% if object %> :: <%= object.page_title %><% end %></title>
4
- <link type="text/css" rel="stylesheet" href="manual.css" />
4
+ <link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
5
5
  </head>
6
6
 
7
7
  <body>
@@ -7,7 +7,7 @@ Try these on for size:
7
7
  * "Log Method Execution":#logexec
8
8
  * "Reference Another Service":#refsvc
9
9
  * "Unit Testing":#unittest
10
- * "Lifecycle Management":#lifecycle
10
+ * "Lifestyle Management":#lifestyle
11
11
 
12
12
  (Thanks to Howard Lewis Ship for his "HiveMind":http://jakarta.apache.org/hivemind documentation, from which some of the above bullet points were adapted.)
13
13
 
@@ -18,36 +18,36 @@ Needle has an integrated logging framework, and the ability to log execution tra
18
18
 
19
19
  Consider the following code, demonstrating how this would be done without Needle:
20
20
 
21
- <pre>
22
- def foo( arg1, arg2 )
23
- @log.debug( "in foo with #{arg1} and #{arg2}" ) if @log.debug?
24
- ...
25
- result = the_result_of_the_method
26
- @log.debug( "finishing foo with #{result}" ) if @log.debug
27
- return result
28
- rescue Exception => e
29
- @log.debug( "foo raised exception #{e.message} (#{e.class})" ) if @log.debug?
30
- raise
31
- end
32
- </pre>
21
+ {{{lang=ruby,number=true,caption=Logging method execution without Needle
22
+ def foo( arg1, arg2 )
23
+ @log.debug( "in foo with #{arg1} and #{arg2}" ) if @log.debug?
24
+ ...
25
+ result = the_result_of_the_method
26
+ @log.debug( "finishing foo with #{result}" ) if @log.debug
27
+ return result
28
+ rescue Exception => e
29
+ @log.debug( "foo raised exception #{e.message} (#{e.class})" ) if @log.debug?
30
+ raise
31
+ end
32
+ }}}
33
33
 
34
34
  Now, multiply that by the number of methods in your class... the logging messages quickly overpower the rest of the code, and detract from the flow of your program. This makes your program harder to debug, test, and maintain.
35
35
 
36
36
  Now, consider the same method using Needle's integrated logging framework...
37
37
 
38
- <pre>
39
- def foo( arg1, arg2 )
40
- ...
41
- return the_result_of_the_method
42
- end
43
- </pre>
38
+ {{{lang=ruby,number=true,caption=Logging method execution with Needle
39
+ def foo( arg1, arg2 )
40
+ ...
41
+ return the_result_of_the_method
42
+ end
43
+ }}}
44
44
 
45
45
  Then, when you define the service that you want to add the logging to:
46
46
 
47
- <pre>
48
- registry.register( :service_name_here ) { |reg| ... }
49
- registry.intercept( :service_name_here ).with! { logging_interceptor }
50
- </pre>
47
+ {{{lang=ruby,number=true,caption=Adding the logging interceptor to a service
48
+ registry.register( :service_name_here ) { |reg| ... }
49
+ registry.intercept( :service_name_here ).with! { logging_interceptor }
50
+ }}}
51
51
 
52
52
  That's right. There's no explicit logging code in there. Instead, you just tell Needle that the methods of the class should be logged, and away it goes. This has the added benefit of allowing your objects to be unit tested, without spewing log messages everywhere.
53
53
 
@@ -55,41 +55,41 @@ h3. Reference Another Service <a name="#refsvc"></a>
55
55
 
56
56
  Invariably in a large application services will reference other services. This is typically accomplished through something like this:
57
57
 
58
- <pre>
59
- class Component
60
- ...
61
- def foo( parms )
62
- @service ||= lookup_service
63
- @service.do_something( parms )
64
- end
65
-
66
- def lookup_service
67
- ...
68
- end
58
+ {{{lang=ruby,number=true,caption=Looking up services without Needle
59
+ class Component
60
+ ...
61
+ def foo( parms )
62
+ @service ||= lookup_service
63
+ @service.do_something( parms )
64
+ end
65
+
66
+ def lookup_service
69
67
  ...
70
68
  end
71
- </pre>
69
+ ...
70
+ end
71
+ }}}
72
72
 
73
73
  Whether the lookup is done lazily, as shown above, or when the class is first instantiated is irrelevant. The point is that you either have to implement a bunch of code to look up a service based on some criteria, or you hard code the class of the service (which creates tight coupling and makes things like unit testing harder).
74
74
 
75
75
  With Needle, you just declare a setter for the service, and then tell Needle that the class depends on the other service:
76
76
 
77
- <pre>
78
- class Component
79
- attr_writer :service
80
- ...
81
- def foo( parms )
82
- @service.do_something( parms )
83
- end
84
- ...
77
+ {{{lang=ruby,number=true,caption=Wiring services with Needle
78
+ class Component
79
+ attr_writer :service
80
+ ...
81
+ def foo( parms )
82
+ @service.do_something( parms )
85
83
  end
84
+ ...
85
+ end
86
86
 
87
- registry.register( :component ) do |reg|
88
- c = Component.new
89
- c.service = reg.some_other_service
90
- c
91
- end
92
- </pre>
87
+ registry.register( :component ) do |reg|
88
+ c = Component.new
89
+ c.service = reg.some_other_service
90
+ c
91
+ end
92
+ }}}
93
93
 
94
94
  Then, when your service is instantiated, Needle will automatically look for and instantiate the dependencies for you. This makes for cleaner code, and looser coupling between services.
95
95
 
@@ -101,34 +101,34 @@ Needle, by its very nature, encourages loose coupling of components. Also, becau
101
101
 
102
102
  Consider this tightly coupled example:
103
103
 
104
- <pre>
105
- def foo( args )
106
- @some_dependency ||= MyNewDependency.new
107
- @some_dependency.do_something(args)
108
- end
109
- </pre>
104
+ {{{lang=ruby,number=true,caption=Tight coupling
105
+ def foo( args )
106
+ @some_dependency ||= MyNewDependency.new
107
+ @some_dependency.do_something(args)
108
+ end
109
+ }}}
110
110
 
111
111
  It is impossible to test the method @#foo@ without also testing the MyNewDependency class. However, if the @@some_dependency@ object is made a property that is set externally, you can replace it at test time with a blank:
112
112
 
113
- <pre>
114
- attr_writer :some_dependency
113
+ {{{lang=ruby,number=true,caption=Loose coupling
114
+ attr_writer :some_dependency
115
115
 
116
- def foo( args )
117
- @some_dependency.do_something( args )
118
- end
119
- </pre>
116
+ def foo( args )
117
+ @some_dependency.do_something( args )
118
+ end
119
+ }}}
120
120
 
121
121
  The unit test would become something like this:
122
122
 
123
- <pre>
124
- def test_foo
125
- @obj.some_dependecy = MyMockDependency.new
126
- @obj.foo( args )
127
- assert @obj.is_in_some_state
128
- end
129
- </pre>
123
+ {{{lang=ruby,number=true,caption=Unit testing with a mock object
124
+ def test_foo
125
+ @obj.some_dependecy = MyMockDependency.new
126
+ @obj.foo( args )
127
+ assert @obj.is_in_some_state
128
+ end
129
+ }}}
130
130
 
131
- h3. Lifecycle Management <a name="#lifecycle"></a>
131
+ h3. Lifestyle Management <a name="#lifestyle"></a>
132
132
 
133
133
  Singleton objects are a fact of life in complex systems. The singleton design pattern is powerful and useful. However, using the Singleton mixin, or declaring methods at the class level, can make your code difficult to unit test since the state of such objects cannot be easily reset.
134
134
 
@@ -136,6 +136,6 @@ Needle has a solution. You can tell Needle to treat a service as either a _proto
136
136
 
137
137
  Your object is still just a plain ol' ordinary Ruby object, but Needle has effectively transformed it into a singleton. This means you can unit test it as if it were nothing special, but when it is used in your application it will act like a singleton.
138
138
 
139
- Lifecycle management also means that you can control _when_ a service is instantiated. The _prototype_ and _singleton_ models will always be instantiated as soon as they are requested. Sometimes, though, you don't want that--you'd like the instantiation to be deferred as late as possible.
139
+ Lifestyle management also means that you can control _when_ a service is instantiated. The _prototype_ and _singleton_ models will always be instantiated as soon as they are requested. Sometimes, though, you don't want that--you'd like the instantiation to be deferred as late as possible.
140
140
 
141
141
  With Needle, you can indicate that a service should use deferred instantiation. This will cause the service to not actually be instantiated until a method is actually invoked on it. Using this model, you can have services depend on themselves, or other forms of cyclical dependencies.
@@ -1,39 +1,39 @@
1
1
  Creating a registry is as simple as calling @Needle::Registry.new@. This will give you a new registry object, bootstrapped to contain a few general services.
2
2
 
3
- <pre>
4
- require 'needle'
3
+ {{{lang=ruby,number=true,caption=Creating a registry
4
+ require 'needle'
5
5
 
6
- registry = Needle::Registry.new
7
- </pre>
6
+ registry = Needle::Registry.new
7
+ }}}
8
8
 
9
9
  Once you have the reference to the registry, you can register services with it, create new namespaces in it, and so forth.
10
10
 
11
11
  Alternatively, you can pass a block to @#new@:
12
12
 
13
- <pre>
14
- registry = Needle::Registry.new do |r|
15
- ...
16
- end
17
- </pre>
13
+ {{{lang=ruby,number=true,caption=Creating a registry with a block
14
+ registry = Needle::Registry.new do |r|
15
+ ...
16
+ end
17
+ }}}
18
18
 
19
19
  The parameter to the block will be a reference to the registry. This allows you to register services with the registry as soon as it is created.
20
20
 
21
21
  Another convenience method is @#define!@:
22
22
 
23
- <pre>
24
- registry = Needle::Registry.define! do
25
- ...
26
- end
27
- </pre>
23
+ {{{lang=ruby,number=true,caption=Creating a registry with #define!
24
+ registry = Needle::Registry.define! do
25
+ ...
26
+ end
27
+ }}}
28
28
 
29
29
  This block accepts no parameters, and evaluates the block as if it were passed to @Registry#define!@ (see below).
30
30
 
31
31
  There can be problems with using @define!@, however, since it uses @instance_eval@ to evaluate the block within the context of another object. If you find yourself running into scoping issues, you might want to consider using @#define@:
32
32
 
33
- <pre>
34
- registry = Needle::Registry.define do |b|
35
- ...
36
- end
37
- </pre>
33
+ {{{lang=ruby,number=true,caption=Creating a registry with #define
34
+ registry = Needle::Registry.define do |b|
35
+ ...
36
+ end
37
+ }}}
38
38
 
39
39
  This block accepts a single parameter--a "builder" object to aid in registering services--and evaluates the block as if it were passed to @Registry#define@ (see below).
@@ -6,51 +6,51 @@ Namespaces allow you to organize your services. The feature has many different a
6
6
 
7
7
  Creating a namespace is as easy as invoking the @#namespace@ method of the registry (or of another namespace):
8
8
 
9
- <pre>
10
- registry.namespace :stuff
11
- </pre>
9
+ {{{lang=ruby,caption=Creating a namespace
10
+ registry.namespace :stuff
11
+ }}}
12
12
 
13
13
  This would create a new namespace in the registry called @:stuff@. The application may then proceed to register services inside that namespace:
14
14
 
15
- <pre>
16
- registry.stuff.register( :foo ) { Bar.new }
17
- ...
18
- svc = registry.stuff.foo
19
- </pre>
15
+ {{{lang=ruby,number=true,caption=Registering services in a namespace
16
+ registry.stuff.register( :foo ) { Bar.new }
17
+ ...
18
+ svc = registry.stuff.foo
19
+ }}}
20
20
 
21
21
  Here's a tip: _namespaces are just a special kind of service._ This means that you can access namespaces in the same ways that you can access services:
22
22
 
23
- <pre>
24
- svc = registry[:stuff][:foo]
25
- </pre>
23
+ {{{lang=ruby,caption=Accessing a namespace
24
+ svc = registry[:stuff][:foo]
25
+ }}}
26
26
 
27
27
  h3. Convenience Methods
28
28
 
29
29
  Because it is often the case that you will be creating a namespace and then immediately registering services on it, you can pass a block to @namespace@. The block will receive a reference to the new namespace:
30
30
 
31
- <pre>
32
- registry.namespace :stuff do |spc|
33
- spc.register( :foo ) { Bar.new }
34
- ...
35
- end
36
- </pre>
31
+ {{{lang=ruby,number=true,caption=More registering services in a namespace
32
+ registry.namespace :stuff do |spc|
33
+ spc.register( :foo ) { Bar.new }
34
+ ...
35
+ end
36
+ }}}
37
37
 
38
38
  If you prefer the @define@ approach to registering services, you may like @namespace_define@, which creates the new namespace and immediately calls @define@ on it:
39
39
 
40
- <pre>
41
- registry.namespace_define :stuff do |b|
42
- b.foo { Bar.new }
43
- ...
44
- end
45
- </pre>
40
+ {{{lang=ruby,number=true,caption=Creating namespaces with #namespace_define
41
+ registry.namespace_define :stuff do |b|
42
+ b.foo { Bar.new }
43
+ ...
44
+ end
45
+ }}}
46
46
 
47
47
  And, to mirror the @namespace_define@ method, there is also a @namespace_define!@ method. This method creates a new namespace and then does a @define!@ call on that namespace.
48
48
 
49
- <pre>
50
- registry.namespace_define! :stuff do
51
- foo { Bar.new }
52
- ...
53
- end
54
- </pre>
49
+ {{{lang=ruby,number=true,caption=Creating namespaces with #namespace_define!
50
+ registry.namespace_define! :stuff do
51
+ foo { Bar.new }
52
+ ...
53
+ end
54
+ }}}
55
55
 
56
56
  The above code would create a new namespace called @:stuff@ in the registry, and would then proceed to register a service called @:foo@ in the new namespace.
@@ -1,20 +1,20 @@
1
1
  Registering services with a Needle registry is very straightforward. The simplest way to do it is:
2
2
 
3
- <pre>
4
- registry.register( :foo ) { Bar.new }
5
- </pre>
3
+ {{{lang=ruby,caption=Registering services
4
+ registry.register( :foo ) { Bar.new }
5
+ }}}
6
6
 
7
7
  The above will register a new service with the registry, naming it @:foo@. When @:foo@ is requested from the registry, a new instance of @Bar@ will be instantiated and returned.
8
8
 
9
9
  You get services from the registry in either of two ways:
10
10
 
11
- <pre>
12
- # Treating the registry as a Hash
13
- svc = registry[:foo]
11
+ {{{lang=ruby,number=true,caption=Accessing services
12
+ # Treating the registry as a Hash
13
+ svc = registry[:foo]
14
14
 
15
- # Treating the service as a property of the registry
16
- svc = registry.foo
17
- </pre>
15
+ # Treating the service as a property of the registry
16
+ svc = registry.foo
17
+ }}}
18
18
 
19
19
  h3. Convenience Methods
20
20
 
@@ -22,36 +22,36 @@ Because you will often need to register many services with a registry at once, t
22
22
 
23
23
  The first is @define@. Just pass a block to define that accepts one parameter. This parameter will be a "builder" object that allows you to define services just by sending them as messages to the builder:
24
24
 
25
- <pre>
26
- registry.define do |b|
27
- b.foo { Bar.new }
28
- b.bar { Foo.new }
29
- ...
30
- end
31
- </pre>
25
+ {{{lang=ruby,number=true,caption=Defining services
26
+ registry.define do |b|
27
+ b.foo { Bar.new }
28
+ b.bar { Foo.new }
29
+ ...
30
+ end
31
+ }}}
32
32
 
33
33
  Alternative, you can call @define!@, passing a block that accepts no parameters. This block will be evaluated in the "builder" object's context, with any unrecognized method call being interpreted as a new service registration of that name:
34
34
 
35
- <pre>
36
- registry.define! do
37
- foo { Bar.new }
38
- bar { Foo.new }
39
- ...
40
- end
41
- </pre>
35
+ {{{lang=ruby,number=true,caption=Defining services via #define!
36
+ registry.define! do
37
+ foo { Bar.new }
38
+ bar { Foo.new }
39
+ ...
40
+ end
41
+ }}}
42
42
 
43
43
  Both of the above will register two new services with the registry, @:foo@ and @:bar@.
44
44
 
45
- h3. Default Lifecycle
45
+ h3. Default Lifestyle
46
46
 
47
47
  By default, a service is only instantiated once per registry. This means that (using the above example) if the service @:foo@ were queried twice, the registry would return the same object for both queries:
48
48
 
49
- <pre>
50
- svc1 = registry.foo
51
- svc2 = registry.foo
49
+ {{{lang=ruby,number=true,caption=Demonstrating singleton service behavior
50
+ svc1 = registry.foo
51
+ svc2 = registry.foo
52
52
 
53
- p svc1.object_id == svc2.object_id #=> true
54
- </pre>
53
+ p svc1.object_id == svc2.object_id #=> true
54
+ }}}
55
55
 
56
56
  You can change this behavior, with _service models_. See the chapter on Service Models for more information.
57
57
 
@@ -61,14 +61,14 @@ Needle also supports _parameterized services_. These are services that, when req
61
61
 
62
62
  Consider the following example, in which some hypothetical @Printer@ class represents any of a number of printers, based on a parameter given to its constructor.
63
63
 
64
- <pre>
65
- registry.register( :printer, :model => :multiton ) do |c,p,name|
66
- Printer.new( c.log_for( p ), name )
67
- end
64
+ {{{lang=ruby,number=true,caption=Parameterized services
65
+ registry.register( :printer, :model => :multiton ) do |c,p,name|
66
+ Printer.new( c.log_for( p ), name )
67
+ end
68
68
 
69
- mono = registry.printer( :monochrome )
70
- color = registry.printer( :color )
71
- </pre>
69
+ mono = registry.printer( :monochrome )
70
+ color = registry.printer( :color )
71
+ }}}
72
72
 
73
73
  There are a few things to note about the above example:
74
74
 
@@ -80,10 +80,9 @@ There are a few things to note about the above example:
80
80
 
81
81
  # See how the printer service is requested on the last two lines. In this case, the @#printer@ message is sent to the registry with a single parameter. You can also request the service in two other ways:
82
82
 
83
- <pre>
84
- dot_matrix = registry[ :printer, :dot_matrix ]
85
- ink_jet = registry.get( :printer, :ink_jet )
86
- </pre>
83
+ {{{lang=ruby,number=true,caption=Accessing parameterized services
84
+ dot_matrix = registry[ :printer, :dot_matrix ]
85
+ ink_jet = registry.get( :printer, :ink_jet )
86
+ }}}
87
87
 
88
88
  Choose the style that works best for you.
89
-