needle 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/benchmarks/instantiation.rb +39 -0
  2. data/doc/faq/faq.yml +137 -102
  3. data/doc/manual-html/chapter-1.html +15 -19
  4. data/doc/manual-html/chapter-2.html +52 -23
  5. data/doc/manual-html/chapter-3.html +7 -9
  6. data/doc/manual-html/chapter-4.html +6 -8
  7. data/doc/manual-html/chapter-5.html +16 -19
  8. data/doc/manual-html/chapter-6.html +31 -8
  9. data/doc/manual-html/chapter-7.html +19 -8
  10. data/doc/manual-html/chapter-8.html +8 -11
  11. data/doc/manual-html/chapter-9.html +7 -6
  12. data/doc/manual-html/index.html +5 -3
  13. data/doc/manual/manual.yml +2 -1
  14. data/doc/manual/parts/01_alternatives.txt +2 -1
  15. data/doc/manual/parts/02_services.txt +33 -0
  16. data/doc/manual/parts/logging_logfactory.txt +9 -0
  17. data/doc/manual/parts/models_models.txt +4 -0
  18. data/doc/manual/parts/models_pipelines.txt +1 -0
  19. data/lib/needle/container.rb +64 -19
  20. data/lib/needle/definition-context.rb +34 -6
  21. data/lib/needle/lifecycle/multiton.rb +64 -0
  22. data/lib/needle/lifecycle/singleton.rb +2 -2
  23. data/lib/needle/lifecycle/threaded.rb +4 -3
  24. data/lib/needle/pipeline/collection.rb +10 -1
  25. data/lib/needle/pipeline/element.rb +6 -0
  26. data/lib/needle/registry.rb +18 -5
  27. data/lib/needle/service-point.rb +21 -10
  28. data/lib/needle/version.rb +1 -1
  29. data/test/lifecycle/tc_multiton.rb +43 -0
  30. data/test/lifecycle/tc_singleton.rb +18 -2
  31. data/test/lifecycle/tc_threaded.rb +12 -6
  32. data/test/pipeline/tc_collection.rb +26 -2
  33. data/test/services.rb +8 -0
  34. data/test/tc_container.rb +82 -0
  35. data/test/tc_definition_context.rb +63 -7
  36. data/test/tc_registry.rb +13 -1
  37. data/test/tc_service_point.rb +49 -0
  38. metadata +4 -2
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Needle Version: <strong>1.1.0</strong><br />
18
- Manual Last Updated: <strong>2004-11-11 17:31 GMT</strong>
17
+ Needle Version: <strong>1.2.0</strong><br />
18
+ Manual Last Updated: <strong>2004-11-18 15:36 GMT</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -220,8 +220,7 @@
220
220
 
221
221
 
222
222
  <div class="section">
223
- <p>Needle is a dependency injection (also, inversion of control) container for <a href="http://www.ruby-lang.org">Ruby</a>.<br />
224
- </p>
223
+ <p>Needle is a dependency injection (also, inversion of control) container for <a href="http://www.ruby-lang.org">Ruby</a>.</p>
225
224
  </div>
226
225
 
227
226
 
@@ -239,7 +238,6 @@
239
238
  <p>But what, <em>specifically</em>, can Needle do for you?</p>
240
239
 
241
240
  <p>Try these on for size:</p>
242
-
243
241
  <ul>
244
242
  <li><a href="#logexec">Log Method Execution</a></li>
245
243
  <li><a href="#refsvc">Reference Another Service</a></li>
@@ -255,6 +253,7 @@
255
253
 
256
254
  <p>Consider the following code, demonstrating how this would be done without Needle:</p>
257
255
 
256
+
258
257
  <pre>
259
258
  def foo( arg1, arg2 )
260
259
  @log.debug( "in foo with #{arg1} and #{arg2}" ) if @log.debug?
@@ -267,31 +266,31 @@
267
266
  raise
268
267
  end
269
268
  </pre>
270
-
271
269
  <p>Now, multiply that by the number of methods in your class&#8230; 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.</p>
272
270
 
273
271
  <p>Now, consider the same method using Needle&#8217;s integrated logging framework&#8230;</p>
274
272
 
273
+
275
274
  <pre>
276
275
  def foo( arg1, arg2 )
277
276
  ...
278
277
  return the_result_of_the_method
279
278
  end
280
279
  </pre>
281
-
282
280
  <p>Then, when you define the service that you want to add the logging to:</p>
283
281
 
282
+
284
283
  <pre>
285
284
  registry.register( :service_name_here ) { |reg| ... }
286
285
  registry.intercept( :service_name_here ).with! { logging_interceptor }
287
286
  </pre>
288
-
289
287
  <p>That&#8217;s right. There&#8217;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.</p>
290
288
 
291
289
  <h3>Reference Another Service <a name="#refsvc"></a></h3>
292
290
 
293
291
  <p>Invariably in a large application services will reference other services. This is typically accomplished through something like this:</p>
294
292
 
293
+
295
294
  <pre>
296
295
  class Component
297
296
  ...
@@ -306,11 +305,11 @@
306
305
  ...
307
306
  end
308
307
  </pre>
309
-
310
308
  <p>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).</p>
311
309
 
312
310
  <p>With Needle, you just declare a setter for the service, and then tell Needle that the class depends on the other service:</p>
313
311
 
312
+
314
313
  <pre>
315
314
  class Component
316
315
  attr_writer :service
@@ -327,7 +326,6 @@
327
326
  c
328
327
  end
329
328
  </pre>
330
-
331
329
  <p>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.</p>
332
330
 
333
331
  <h3>Unit Testing <a name="#unittest"></a></h3>
@@ -338,15 +336,16 @@
338
336
 
339
337
  <p>Consider this tightly coupled example:</p>
340
338
 
339
+
341
340
  <pre>
342
341
  def foo( args )
343
342
  @some_dependency ||= MyNewDependency.new
344
343
  @some_dependency.do_something(args)
345
344
  end
346
345
  </pre>
347
-
348
346
  <p>It is impossible to test the method <code>#foo</code> without also testing the MyNewDependency class. However, if the <code>@some_dependency</code> object is made a property that is set externally, you can replace it at test time with a blank:</p>
349
347
 
348
+
350
349
  <pre>
351
350
  attr_writer :some_dependency
352
351
 
@@ -354,9 +353,9 @@
354
353
  @some_dependency.do_something( args )
355
354
  end
356
355
  </pre>
357
-
358
356
  <p>The unit test would become something like this:</p>
359
357
 
358
+
360
359
  <pre>
361
360
  def test_foo
362
361
  @obj.some_dependecy = MyMockDependency.new
@@ -364,7 +363,6 @@
364
363
  assert @obj.is_in_some_state
365
364
  end
366
365
  </pre>
367
-
368
366
  <h3>Lifecycle Management <a name="#lifecycle"></a></h3>
369
367
 
370
368
  <p>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.</p>
@@ -389,14 +387,14 @@
389
387
 
390
388
  <div class="section">
391
389
  <p>Needle is not the only fish in the dependency-injection pond, even when it comes to Ruby. Other containers at your disposal include:</p>
392
-
393
390
  <ul>
394
391
  <li><a href="http://copland.rubyforge.org">Copland</a>. Copland aims to be an &#8220;application framework&#8221;, taking something of a heavy-weight approach to DI. In so doing, it provides functionality that Needle does not, but at the cost of performance. It also uses external (YAML) configuration files. It is inspired by a Java framework (<a href="http://jakarta.apache.org/hivemind">HiveMind</a>), and so has a vaguely Java-ish flavor to it.</li>
395
392
  <li><a href="http://www.picocontainer.org/Rico">Rico</a>. Rico is another project inspired by a Java project (<a href="http://www.picocontainer.org">PicoContainer</a>). It is very lean, and appears to be experimental.</li>
396
393
  <li><a href="http://sourceforge.jp/projects/nihohi/">Tudura</a>. I do not have any information on this project, as the information is all in Japanese. If someone with more information about Tudura would like to step forward, I&#8217;d be happy to post a summary here.</li>
394
+ <li><a href="http://redshift.sourceforge.net/mindi/">MinDI</a> is a recent contender that takes a very novel approach to dependency injection. Instead of instantiating a container and adding services to it, you declare a class, mixin a DI module, and add services to the class as methods, thereby making the class the container.</li>
397
395
  </ul>
398
396
 
399
- <p>There is, at the time of this writing, at least one other project on RubyForge devoted to DI, although it has no public releases yet.</p>
397
+ <p>There is, at the time of this writing, at least one other project on RubyForge devoted to <span class="caps">DI </span>(<a href="http://rubyforge.org/projects/pith">Pith</a>), although it has no public releases yet.</p>
400
398
 
401
399
  <p>So, which one should you choose? It comes down to an issue of personal preference, mostly, but also one of what you are wanting to accomplish. Needle excels at providing an unobtrusive, light-weight container for managing your dependencies. The cost of it being light-weight is that there is functionality it does not provide, which other containers may. If you really need that missing functionality, you are required to either implement it yourself, or select a different container.</p>
402
400
 
@@ -417,8 +415,7 @@
417
415
 
418
416
  <p>This manual (in any form, be it source or otherwise) and the scripts and templates used to generate it, are all distributed under the <a href="http://creativecommons.org">Creative Commons</a> <a href="http://creativecommons.org/licenses/by-sa/2.0">Attribution-ShareAlike</a> license.</p>
419
417
 
420
- <p>If you desire permission to use either Needle or the manual in a manner incompatible with these licenses, please contact the copyright holder (<a href="mailto:jgb3@email.byu.edu">Jamis Buck</a>) in order to negotiate a more compatible license.<br />
421
- </p>
418
+ <p>If you desire permission to use either Needle or the manual in a manner incompatible with these licenses, please contact the copyright holder (<a href="mailto:jgb3@email.byu.edu">Jamis Buck</a>) in order to negotiate a more compatible license.</p>
422
419
  </div>
423
420
 
424
421
 
@@ -431,8 +428,7 @@
431
428
 
432
429
 
433
430
  <div class="section">
434
- <p>Mailing lists, bug trackers, feature requests, and public forums are available (courtesy of <a href="http://rubyforge.org">RubyForge</a>) at Needle&#8217;s RubyForge project page. Just direct your browser to <a href="http://rubyforge.org/projects/needle">http://rubyforge.org/projects/needle</a>.<br />
435
- </p>
431
+ <p>Mailing lists, bug trackers, feature requests, and public forums are available (courtesy of <a href="http://rubyforge.org">RubyForge</a>) at Needle&#8217;s RubyForge project page. Just direct your browser to <a href="http://rubyforge.org/projects/needle">http://rubyforge.org/projects/needle</a>.</p>
436
432
  </div>
437
433
 
438
434
 
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Needle Version: <strong>1.1.0</strong><br />
18
- Manual Last Updated: <strong>2004-11-11 17:31 GMT</strong>
17
+ Needle Version: <strong>1.2.0</strong><br />
18
+ Manual Last Updated: <strong>2004-11-18 15:36 GMT</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -222,8 +222,7 @@
222
222
  <div class="section">
223
223
  <p>The registry is at the heart of any dependency-injected application or library. All services are registered with the registry, so that when an application needs an instance of a particular service, it may obtain that service reference by querying the registry.</p>
224
224
 
225
- <p>In order to use Needle, you only really <em>need</em> to understand how to create and manipulate registry objects.<br />
226
- </p>
225
+ <p>In order to use Needle, you only really <em>need</em> to understand how to create and manipulate registry objects.</p>
227
226
  </div>
228
227
 
229
228
 
@@ -238,44 +237,43 @@
238
237
  <div class="section">
239
238
  <p>Creating a registry is as simple as calling <code>Needle::Registry.new</code>. This will give you a new registry object, bootstrapped to contain a few general services.</p>
240
239
 
240
+
241
241
  <pre>
242
242
  require 'needle'
243
243
 
244
244
  registry = Needle::Registry.new
245
245
  </pre>
246
-
247
246
  <p>Once you have the reference to the registry, you can register services with it, create new namespaces in it, and so forth.</p>
248
247
 
249
248
  <p>Alternatively, you can pass a block to <code>#new</code>:</p>
250
249
 
250
+
251
251
  <pre>
252
252
  registry = Needle::Registry.new do |r|
253
253
  ...
254
254
  end
255
255
  </pre>
256
-
257
256
  <p>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.</p>
258
257
 
259
258
  <p>Another convenience method is <code>#define!</code>:</p>
260
259
 
260
+
261
261
  <pre>
262
262
  registry = Needle::Registry.define! do
263
263
  ...
264
264
  end
265
265
  </pre>
266
-
267
266
  <p>This block accepts no parameters, and evaluates the block as if it were passed to <code>Registry#define!</code> (see below).</p>
268
267
 
269
268
  <p>There can be problems with using <code>define!</code>, however, since it uses <code>instance_eval</code> to evaluate the block within the context of another object. If you find yourself running into scoping issues, you might want to consider using <code>#define</code>:</p>
270
269
 
270
+
271
271
  <pre>
272
272
  registry = Needle::Registry.define do |b|
273
273
  ...
274
274
  end
275
275
  </pre>
276
-
277
- <p>This block accepts a single parameter&#8212;a &#8220;builder&#8221; object to aid in registering services&#8212;and evaluates the block as if it were passed to <code>Registry#define</code> (see below).<br />
278
- </p>
276
+ <p>This block accepts a single parameter&#8212;a &#8220;builder&#8221; object to aid in registering services&#8212;and evaluates the block as if it were passed to <code>Registry#define</code> (see below).</p>
279
277
  </div>
280
278
 
281
279
 
@@ -290,14 +288,15 @@
290
288
  <div class="section">
291
289
  <p>Registering services with a Needle registry is very straightforward. The simplest way to do it is:</p>
292
290
 
291
+
293
292
  <pre>
294
293
  registry.register( :foo ) { Bar.new }
295
294
  </pre>
296
-
297
295
  <p>The above will register a new service with the registry, naming it <code>:foo</code>. When <code>:foo</code> is requested from the registry, a new instance of <code>Bar</code> will be instantiated and returned.</p>
298
296
 
299
297
  <p>You get services from the registry in either of two ways:</p>
300
298
 
299
+
301
300
  <pre>
302
301
  # Treating the registry as a Hash
303
302
  svc = registry[:foo]
@@ -305,13 +304,13 @@
305
304
  # Treating the service as a property of the registry
306
305
  svc = registry.foo
307
306
  </pre>
308
-
309
307
  <h3>Convenience Methods</h3>
310
308
 
311
309
  <p>Because you will often need to register many services with a registry at once, two convenience methods have been provided to make this use case lean and mean.</p>
312
310
 
313
311
  <p>The first is <code>define</code>. Just pass a block to define that accepts one parameter. This parameter will be a &#8220;builder&#8221; object that allows you to define services just by sending them as messages to the builder:</p>
314
312
 
313
+
315
314
  <pre>
316
315
  registry.define do |b|
317
316
  b.foo { Bar.new }
@@ -319,9 +318,9 @@
319
318
  ...
320
319
  end
321
320
  </pre>
322
-
323
321
  <p>Alternative, you can call <code>define!</code>, passing a block that accepts no parameters. This block will be evaluated in the &#8220;builder&#8221; object&#8217;s context, with any unrecognized method call being interpreted as a new service registration of that name:</p>
324
322
 
323
+
325
324
  <pre>
326
325
  registry.define! do
327
326
  foo { Bar.new }
@@ -329,22 +328,53 @@
329
328
  ...
330
329
  end
331
330
  </pre>
332
-
333
331
  <p>Both of the above will register two new services with the registry, <code>:foo</code> and <code>:bar</code>.</p>
334
332
 
335
333
  <h3>Default Lifecycle</h3>
336
334
 
337
335
  <p>By default, a service is only instantiated once per registry. This means that (using the above example) if the service <code>:foo</code> were queried twice, the registry would return the same object for both queries:</p>
338
336
 
337
+
339
338
  <pre>
340
339
  svc1 = registry.foo
341
340
  svc2 = registry.foo
342
341
 
343
342
  p svc1.object_id == svc2.object_id #=&gt; true
344
343
  </pre>
344
+ <p>You can change this behavior, with <em>service models</em>. See the chapter on Service Models for more information.</p>
345
+
346
+ <h3>Parameterized Services</h3>
347
+
348
+ <p>Needle also supports <em>parameterized services</em>. These are services that, when requested, require contextual information to be passed as a parameter so that the service can be correctly initialized.</p>
349
+
350
+ <p>Consider the following example, in which some hypothetical <code>Printer</code> class represents any of a number of printers, based on a parameter given to its constructor.</p>
351
+
352
+
353
+ <pre>
354
+ registry.register( :printer, :model =&gt; :multiton ) do |c,p,name|
355
+ Printer.new( c.log_for( p ), name )
356
+ end
357
+
358
+ mono = registry.printer( :monochrome )
359
+ color = registry.printer( :color )
360
+ </pre>
361
+ <p>There are a few things to note about the above example:</p>
362
+ <ol>
363
+ <li>The <code>:multiton</code> model is explicitly requested. This is necessary because the default service model (<code>:singleton</code>) does not allow parameterized services. Most of the time, you&#8217;ll use the multiton service model with parameterized services, but you don&#8217;t have to. You could also use any of the prototype models as well.
364
+ </li>
365
+ <li>The constructor block for the <code>:printer</code> service takes three parameters, <code>c</code>, <code>p</code>, and <code>name</code>. The first two parameters, <code>c</code> and <code>p</code>, represent the container and the service point, respectively. Any parameters after those two are the contextual parameters given when the service is requested. In this case, there is only one contextual parameter: the name of the printer.
366
+ </li>
367
+ <li>Notice the first parameter to the Printer constructor: <code>c.log_for(p)</code>. This is itself invoking a parameterized service, named <code>:log_for</code>, and passing <code>p</code> as the contextual information. This will return a new logger handle for the service point <code>p</code> (i.e., the current service point).
368
+ </li>
369
+ <li>See how the printer service is requested on the last two lines. In this case, the <code>#printer</code> message is sent to the registry with a single parameter. You can also request the service in two other ways:</li>
370
+ </ol>
345
371
 
346
- <p>You can change this behavior, with <em>service models</em>. See the chapter on Service Models for more information.<br />
347
- </p>
372
+
373
+ <pre>
374
+ dot_matrix = registry[ :printer, :dot_matrix ]
375
+ ink_jet = registry.get( :printer, :ink_jet )
376
+ </pre>
377
+ <p>Choose the style that works best for you.</p>
348
378
  </div>
349
379
 
350
380
 
@@ -358,7 +388,6 @@
358
388
 
359
389
  <div class="section">
360
390
  <p>Namespaces allow you to organize your services. The feature has many different applications, including:</p>
361
-
362
391
  <ol>
363
392
  <li>Third-parties may distribute Needle-enabled libraries without worrying about their choice of service names conflicting with the service names of their clients.</li>
364
393
  <li>Developers may organize complex applications into modules, and the service definitions may be stored in the registry to reflect that organization.</li>
@@ -367,53 +396,53 @@
367
396
 
368
397
  <p>Creating a namespace is as easy as invoking the <code>#namespace</code> method of the registry (or of another namespace):</p>
369
398
 
399
+
370
400
  <pre>
371
401
  registry.namespace :stuff
372
402
  </pre>
373
-
374
403
  <p>This would create a new namespace in the registry called <code>:stuff</code>. The application may then proceed to register services inside that namespace:</p>
375
404
 
405
+
376
406
  <pre>
377
407
  registry.stuff.register( :foo ) { Bar.new }
378
408
  ...
379
409
  svc = registry.stuff.foo
380
410
  </pre>
381
-
382
411
  <p>Here&#8217;s a tip: <em>namespaces are just a special kind of service.</em> This means that you can access namespaces in the same ways that you can access services:</p>
383
412
 
413
+
384
414
  <pre>
385
415
  svc = registry[:stuff][:foo]
386
416
  </pre>
387
-
388
417
  <h3>Convenience Methods</h3>
389
418
 
390
419
  <p>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 <code>namespace</code>. The block will receive a reference to the new namespace:</p>
391
420
 
421
+
392
422
  <pre>
393
423
  registry.namespace :stuff do |spc|
394
424
  spc.register( :foo ) { Bar.new }
395
425
  ...
396
426
  end
397
427
  </pre>
398
-
399
428
  <p>If you prefer the <code>define</code> approach to registering services, you may like <code>namespace_define</code>, which creates the new namespace and immediately calls <code>define</code> on it:</p>
400
429
 
430
+
401
431
  <pre>
402
432
  registry.namespace_define :stuff do |b|
403
433
  b.foo { Bar.new }
404
434
  ...
405
435
  end
406
436
  </pre>
407
-
408
437
  <p>And, to mirror the <code>namespace_define</code> method, there is also a <code>namespace_define!</code> method. This method creates a new namespace and then does a <code>define!</code> call on that namespace.</p>
409
438
 
439
+
410
440
  <pre>
411
441
  registry.namespace_define! :stuff do
412
442
  foo { Bar.new }
413
443
  ...
414
444
  end
415
445
  </pre>
416
-
417
446
  <p>The above code would create a new namespace called <code>:stuff</code> in the registry, and would then proceed to register a service called <code>:foo</code> in the new namespace.</p>
418
447
  </div>
419
448
 
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Needle Version: <strong>1.1.0</strong><br />
18
- Manual Last Updated: <strong>2004-11-11 17:31 GMT</strong>
17
+ Needle Version: <strong>1.2.0</strong><br />
18
+ Manual Last Updated: <strong>2004-11-18 15:36 GMT</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -223,7 +223,6 @@
223
223
  <p>The <em>service locator</em> design pattern can be considered a subset of dependency injection. Because it is simpler, it is as good of a place to start teaching DI as any.</p>
224
224
 
225
225
  <p>To demonstrate both techniques, we&#8217;ll pretend we&#8217;re going to write an online forum application. To start, let&#8217;s come up with a rough design by cataloging the components we&#8217;ll need.</p>
226
-
227
226
  <ul>
228
227
  <li><code>Logger</code>. This will be used to write messages to a file.</li>
229
228
  <li><code>Authenticator</code>. This will be used to validate whether a user is who they say they are.</li>
@@ -236,7 +235,6 @@
236
235
  <p>(Of course, a <em>real</em> online forum application would be significantly more complex, but the above components will do for our purposes.)</p>
237
236
 
238
237
  <p>The dependencies between these components are:</p>
239
-
240
238
  <ul>
241
239
  <li><code>Authenticator</code> <em>has</em> <code>Database</code> (for querying user authentication information) and <code>Logger</code></li>
242
240
  <li><code>Database</code> <em>has</em> <code>Logger</code> (for indicating database accesses and query times)</li>
@@ -257,6 +255,7 @@
257
255
  <div class="section">
258
256
  <p>A conventional architecture will have each component instantiate its own dependencies. For example, the <code>Application</code> would do something like this:</p>
259
257
 
258
+
260
259
  <pre>
261
260
  class Application
262
261
  def initialize
@@ -268,9 +267,9 @@
268
267
  end
269
268
  end
270
269
  </pre>
271
-
272
270
  <p>However, the above is already flawed, because the <code>Authenticator</code> and the <code>Session</code> both need access to the <code>Database</code>, so you really need to make sure you instantiate things in the right order and pass them as parameters to the constructor of each object that needs them, like so:</p>
273
271
 
272
+
274
273
  <pre>
275
274
  class Application
276
275
  def initialize
@@ -282,9 +281,7 @@
282
281
  end
283
282
  end
284
283
  </pre>
285
-
286
- <p>The problem with this is that if you later decide that <code>View</code> needs to access the database, you need to rearrange the order of how things are instantiated in the <code>Application</code> constructor.<br />
287
- </p>
284
+ <p>The problem with this is that if you later decide that <code>View</code> needs to access the database, you need to rearrange the order of how things are instantiated in the <code>Application</code> constructor.</p>
288
285
  </div>
289
286
 
290
287
 
@@ -299,6 +296,7 @@
299
296
  <div class="section">
300
297
  <p>The <em>service locator</em> pattern makes things a <em>little</em> easier. Instead of instantiating everything in the constructor of the <code>Application</code>, you can create a factory method somewhere that returns the new <code>Application</code> instance. Then, inside of this factory method, you assign each new object to collection, and pass that collection to each constructor.</p>
301
298
 
299
+
302
300
  <pre>
303
301
  require 'needle'
304
302
 
@@ -334,7 +332,6 @@
334
332
 
335
333
  ...
336
334
  </pre>
337
-
338
335
  <p>This has the benefit of allowing each object to construct itself <em>� la carte</em> from the objects in the locator. Also, each object no longer cares what class implements each service&#8212;it only cares that each object implements the methods it will attempt to invoke on that object.</p>
339
336
 
340
337
  <p>Also, because Needle defers the instantiation of each service until the service is actually requested, we can actually register each item with the locator in any arbitrary order. All that is happening is the block is associated with the symbol, so that when the service is requested, the corresponding block is invoked. What is more, by default each service is then cached, so that it is only instantiated once.</p>
@@ -343,6 +340,7 @@
343
340
 
344
341
  <p>In the interest of brevity, the <code>create_application</code> could have been written like this, using a &#8220;builder&#8221; object (called <code>b</code> in the example below) to help register the services:</p>
345
342
 
343
+
346
344
  <pre>
347
345
  def create_application
348
346
  locator = Needle::Registry.define do |b|