Wiring objects, IoC and Service Locator

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Wiring objects, IoC and Service Locator

Vitor Medina Cruz
Hello,

I would like to know how people in Pharo ecosystem do to deal with object wiring, as described by Marting Fowler in https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:

"A common issue to deal with is how to wire together different elements: how do you fit together this web controller architecture with that database interface backing when they were built by different teams with little knowledge of each other."

He gives an example, I will leave it in java as it is simple enough to understand:

"class MovieLister...
  public Movie[] moviesDirectedBy(String arg) {
      List allMovies = finder.findAll();
      for (Iterator it = allMovies.iterator(); it.hasNext();) {
          Movie movie = (Movie) it.next();
          if (!movie.getDirector().equals(arg)) it.remove();
      }
      return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]); 
  }"

The question is how to provide the finder object in a decoupled matter, a naive approach would be:

" private MovieFinder finder;
  public MovieLister() {
    finder = new ColonDelimitedMovieFinder("movies1.txt"); 
  }"

Which couples the MovieLister to the specific ColonDelimitedMovieFinder class.

Fowler explains how to decouple using an IoC framework or a Service Locator. In Java and .Net IoC is used most of the time. I Googled how this problem is approached in Smalltalk/Pharo, and I generally I found answers "that is easy to do in Smalltalk, so there is no need of a framework", what I miss is a description on *how* to do that:


I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message. As long an object that responds to this message is provided, I can create as many derivations I want and the MovieLister will be decoupled from the MovieFinder. That way, however, I still have to wire things by hand, and I am not sure if this is what I am supposed to do in order to solve the decouple problem.

Can you explain me how this is done in Pharo? It's is usually wiring by hand? Is there a simple construction that deals with the wiring problem that I cannot foresee?

Thanks in advance,
Vitor



Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Ben Coman
Sorry I'm not familiar with the pattern, so I don't have a direct answer, 
and the following might not have a direct answer either,  but in general I'd strongly suggest 
two books for adapting from static OO languages.   

1. The Design Patterns Smalltalk Companion, Alpert, Brown & Woolf - including some discussion on why certain patterns required for static-OO are redundant in Smalltalk.  My naive guess is the Factory, Strategy and/or Template patterns may apply.

2. A Mentoring Course on Smalltalk, Valloud


On Mon, Jun 5, 2017 at 5:17 AM, Vitor Medina Cruz <[hidden email]> wrote:
Hello,

I would like to know how people in Pharo ecosystem do to deal with object wiring, as described by Marting Fowler in https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:

"A common issue to deal with is how to wire together different elements: how do you fit together this web controller architecture with that database interface backing when they were built by different teams with little knowledge of each other."

He gives an example, I will leave it in java as it is simple enough to understand:

"class MovieLister...
  public Movie[] moviesDirectedBy(String arg) {
      List allMovies = finder.findAll();
      for (Iterator it = allMovies.iterator(); it.hasNext();) {
          Movie movie = (Movie) it.next();
          if (!movie.getDirector().equals(arg)) it.remove();
      }
      return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]); 
  }"

The question is how to provide the finder object in a decoupled matter, a naive approach would be:

" private MovieFinder finder;
  public MovieLister() {
    finder = new ColonDelimitedMovieFinder("movies1.txt"); 
  }"

I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'.
 

Which couples the MovieLister to the specific ColonDelimitedMovieFinder class.

Fowler explains how to decouple using an IoC framework or a Service Locator. In Java and .Net IoC is used most of the time. I Googled how this problem is approached in Smalltalk/Pharo, and I generally I found answers "that is easy to do in Smalltalk, so there is no need of a framework", what I miss is a description on *how* to do that:

Just to satisfy my curiosity, I did find... "MVC was invented on Smalltalk and is arguably the original Inversion of Control framework. ... I think that IOC or the Dependency Injection pattern solves a problem that doesn't really exist in the Smalltalk environment. Smalltalk is an untyped dynamic language and uses message passing to communicate. This makes for objects that are loosely coupled by nature at the language level"

And this... "In an explicitly-typed language like C++, C#, or Java, it is necessary to define an explicit interface for the injected collaborator. The real collaborator and the substitute both have to implement the interface. In a dynamically-typed language like Ruby [& Smalltalk], explicit interfaces are not necessary. We can just take advantage of 'duck-typing'."

And GIlad Bracha knows a bit about Java... "I think that if you’re stuck with a mainstream language, [dependency Injection] may be a reasonable work around. It requires a significant degree of preplanning, and makes your application dependent on one more piece of machinery that has nothing to do with the actual problem the application is trying to solve. On the positive side, it helps guarantee employment for software engineers. That said, it’s important to understand that DIFs are just a work around for a deficiency in the underlying language. So why not get rid of constructors and have a class declaration create a factory object instead? Well, Smalltalk did just that a generation ago. Every time you define a class, you define the factory object for its instances."

btw, following Randy's example the two steps #new & #finder: should hidden/combined by renaming MovieLister>>finder:   
to MovieLister>>initializeWithFinder: 
and adding...
MovieLister class >> newWithFinder: finder
    ^ self basicNew initializeWithFinder: finder

to be used like this...
    lister := MovieLister newWithFinder: (ColonDelimitedMovieFinder on: 'movies1.txt'). 
    movies := lister moviesDirectedBy: 'Tarantino'.


btw, while you are at it, if you haven't done this before, try implementing this using Smalltalk's version of TDD...

In a clean image, first implement the following method and run the test, then fill code as needed just-in-time...  

MovieListerTest>>testColonDelimitedFinder
   lister := MovieLister newWithFinder: (ColonDelimitedMovieFinder on: 'movies1.txt').
   movies := lister moviesDirectedBy: 'Tarantino'.
   self assert: (movies includes: 'Pulp Fiction')


I see similar comments to my references in these.  I hope the bits I've focussed on are not redundant .
 
I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message. As long an object that responds to this message is provided, I can create as many derivations I want and the MovieLister will be decoupled from the MovieFinder.

Reading this, I think maybe all I've done with my example is echo this.  So what I'm not clear on is what you mean by "wire things by hand"
 
That way, however, I still have to wire things by hand, and I am not sure if this is what I am supposed to do in order to solve the decouple problem.

I would say use Pharo's TDD approach of coding-from-within-the-debugger.  The beauty of it is not that you get a lot of test coverage.  There other significant benefits are:

A. Your API ends up designed "in the most natural way to be used" since each time you code how you want to use your API before you define the implementation.     

B. You only need to code the minimum to get that API aspect working.  So you get a faster feedback loop on your design. 

C. 

You consistency API implementation, you might define a test like... 
MovieListerTest>>testAllFinders
    AbstractMovieFinder allSubclasses do: [ :finderclass |  
       lister := MovieLister newWithFinder: (finderclass on: 'movies1.txt').
       movies := lister moviesDirectedBy: 'Tarantino'.
       self assert: (movies includes: 'Pulp Fiction').  ]

and then each time you add an AbstractMovieFinder subclass, you implementation is again just work through fixing the tests from within the debugger.  


Can you explain me how this is done in Pharo? It's is usually wiring by hand? Is there a simple construction that deals with the wiring problem that I cannot foresee?

TDD helps you avoid worrying about problems that might not exist.  

cheers -ben
 

Thanks in advance,
Vitor




Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Stephane Ducasse-3
In reply to this post by Vitor Medina Cruz
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:

> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Vitor Medina Cruz
Thanks for the answer Ben and Stephane. 

I already read A Mentoring Course on Smalltalk, Valloud, there is nothing there I could use in this case :( . I will look after for The Design Patterns Smalltalk Companion. Most of the sources provided I already know of or went in the same lines lines of what I have already found. 

About TDD, I am experienced with the discipline and have tested it on Pharo living system already, but I could not understand how this is related with object wiring, DI and service locator.


From ben:

"I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

and Stephane:

Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

That was what I meant when I said: "I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message.". The code I had in mind is a bit of mix from the one provided by you both:

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: aMovieFinderBuilder
    finder := aMovieFinderClass new.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder builderOn: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

But that means I will have to wire dependencies by hand whenever I create a MovieLister and seek through code when and if those dependencies change. When there are lot's of dependencies it's is a considerable and tedious work. Let's see an image from Fowlers article:

Inline image 1

In this case, the service locator provides me with an instance and I configure the instance in the assembler, the scheme is alike for an IoC, and that would mean my implementation could be like this:


MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>initialize
    finder := ServiceLocator locate: FinderClass   <--- This would bring the instance of finder class configured by the assembler

to be used like this...
    lister := MovieLister new.
    movies := lister moviesDirectedBy: 'Tarantino'."

and the assembler:

Assember class>>configure:

aMap put: (ColonDelimitedMovieFinder builderOn: 'movies1.txt') at: FinderClass 

My assembler and service locator could be even more elaborated, and provide a different MovieFinder in test scope, for different classes or wharever. 

It is a little convenience for Smalltalk, I will give that, but I was wandering if there was something alike in Pharo, by your answers I assuming there is nothing like that.


If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

I didn't understand that, could you elaborate?


On Mon, Jun 5, 2017 at 6:41 AM, Stephane Ducasse <[hidden email]> wrote:
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:
> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Ben Coman


On Tue, Jun 6, 2017 at 1:26 AM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the answer Ben and Stephane. 

I already read A Mentoring Course on Smalltalk, Valloud, there is nothing there I could use in this case :( . I will look after for The Design Patterns Smalltalk Companion. Most of the sources provided I already know of or went in the same lines lines of what I have already found. 

About TDD, I am experienced with the discipline and have tested it on Pharo living system already, but I could not understand how this is related with object wiring, DI and service locator.

I guess I don't properly understand your need and those topics.  That was my quick pass.  Now if I take the time to actually read Fowler's long article

"the inversion is about how they lookup a plugin implementation ... to ensure that any user of a plugin follows some convention that allows a separate assembler module to inject the implementation into the lister."

"The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface. There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection."

Now there was too much syntactical noise in those Java examples for me to think clearly, so I converted them all to Smalltalk.


##CONSTRUCTOR INJECTION

Object subclass: MovieLister
    instanceVariables: 'finder'


MovieLister class >> newWith: aFinder
    ^ self basicNew initializeWith: aFinder

MovieLister >> initializeWith: aFinder
    finder := aFinder


ColonMovieFinder class >> newWith: aFilename
    ^ self basicNew initializeWith: aFilename

ColonMovieFinder >> initializeWith: aFilename
    filename := aFilename.


ConstructorInjectionContainer >> new
    container := DefaultContainer new.  "the article doesn't specify where this comes from"
    finderParams := ConstantParameter newWith: 'movies1.txt'.
    container registerComponentInterface: MovieFinderInterface 
                          implementation: ColonMovieFinder 
                          params: finderParams.
    container registerComponentImplementation: MovieLister
    ^container

to be used like this...
ConstructorInjectionTest >> testWithContainer
    container := ConstructorInjectionContainer new.
    lister := container getComponentInstance( MovieLister ).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article poorly defines registerComponentXXX: or getComponentInstance:
methods, so I don't dwell on them.  I presume its little relevant to the main theme.


##SETTER INJECTION

MovieLister >> setFinder: aFinder
    finder := aFinder.

ColonMovieFinder >> setFilename: aFilename
    filename := aFilename.

SetterInjectionTest >> testWithConfigurationFile
    ctx := SomeXmlApplicationConfiguration on: 'config.xml'.
    lister := ctx getConfigOf: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


##INTERFACE INJECTION

MovieLister >> injectFinder: aFinder
    finder := aFinder

ColonMovieFinder >> injectFilename: aFilename
    filename := aFilename

InterfaceInjectionTest >> configureContainer
    container := InterfaceInjectionContainer new.
    self registerComponents.
    self registerInjectors.
    container start.

InterfaceInjectionTest >> registerComponents
    container registerComponent: 'MovieLister' with: MovieLister.
    container registerComponent: 'MovieFinder' with: ColonMovieFinder.

InterfaceInjectionTest >> registerInjectors
    container registerInjector: Injector  with: (container lookup: 'MovieFinder').
    container registerInjector: InjectorFinderFilename  with: FinderFilenameInjector new.

ColonMovieFinder >> inject: anObject
    anObject injectFinder: self.

FinderFilenameInjector >> inject: anObject
    anObject injectFilename: 'movies1.txt'.

InterfaceInjectionTester >> testInterface
    self configureContainer.
    lister := container lookup: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article doesn't define InterfaceInjectionContainer, but I guess it could look like this...

InterfaceInjectionContainer >> registerComponent: componentName with: aComponent
    container ifNil: [ container := Dictionary new].
    container at: componentName put: aComponent

InterfaceInjectionContainer >> lookup: componentName
    ^ container at: componentName
    

##SERVICE LOCATOR

"The basic idea behind a service locator is to have an object that knows how to get hold of all of the services that an application might need. So a service locator for this application would have a method that returns a movie finder when one is needed. Of course this just shifts the burden a tad, we still have to get the locator into the lister"

MovieLister >> initialize
    finder := ServiceLocator movieFinder.


Object subclass: ServiceLocator
    instanceVariable: 'movieFinder'
    classVariable: 'SoleInstance'

ServiceLocator class >> load: aServiceLocator
    SoleInstance := aServiceLocator

ServiceLocator class >> soleInstance  
    ^ SoleInstance

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinder

ServiceLocator >> movieFinder
    ^movieFinder


ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 


ServiceLocator class >> newWith: aMovieFinder
    ^ self basicNew initializeWithFinder: aMovieFinder

ServiceLocator >> initializeWithFinder: aMovieFinder
    movieFinder := aMovieFinder


ServiceLocatorTest >> testSimple
    self configure.
    lister := MovieLister new.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')
   
So it seems that a service locator is just a Singleton pattern having a class variable for each service of interest ??
So in good faith** I ask... "Is it any more complicated than that?" 

**Since its taken me a couple of hours to convert the Java to this point so I stopped reading to seek your feedback. 
Is that enough insight to adapt to your needs, or is there something else further down the article that invalidates my analysis?






From ben:

"I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."


So per Fowler, the above is equivalent to "Setter Injection with Spring"
 

and Stephane:

Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

That was what I meant when I said: "I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message.". The code I had in mind is a bit of mix from the one provided by you both:

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: aMovieFinderBuilder
    finder := aMovieFinderClass new.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder builderOn: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

But that means I will have to wire dependencies by hand whenever I create a MovieLister and seek through code when and if those dependencies change. When there are lot's of dependencies it's is a considerable and tedious work. Let's see an image from Fowlers article:

Inline image 1

In this case, the service locator provides me with an instance and I configure the instance in the assembler, the scheme is alike for an IoC, and that would mean my implementation could be like this:


MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>initialize
    finder := ServiceLocator locate: FinderClass   <--- This would bring the instance of finder class configured by the assembler

No, like this... 
    finder := ServiceLocation movieFinder.

Now if you want to store a class rather than an instance as I did higher up, you just do this...

Object subclass: ServiceLocator
    instanceVariable: 'movieFinderClass'
    classVariable: 'SoleInstance'

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinderClass new

 


to be used like this...
    lister := MovieLister new.
    movies := lister moviesDirectedBy: 'Tarantino'."

and the assembler:

Assember class>>configure:
aMap put: (ColonDelimitedMovieFinder builderOn: 'movies1.txt') at: FinderClass 

Assembler class>>configure
    ServiceLocator load: 
          (ServiceLocator new
               movieFinder: (ColonMovieFinder newWith: 'movies1.txt')
               otherService: MyCustomService new) 
 

My assembler and service locator could be even more elaborated, and provide a different MovieFinder in test scope, for different classes or wharever. 

Really, the test should not be updating the class variable global like this...
ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 

you probably want something like (its rough but shows the point...)
Object subclass: #MovieLister
    instanceVariables: 'serviceLocator'

MovieLister >> initialize
    serviceLocator ifNil: [ serviceLocator := ServiceLocator soleInstance ].
    finder := serviceLocator movieFinder.
 
MovieLister class >> newWithServiceLocator: aServiceLocator
    ^ (self basicNew initializeWithServiceLocator: aServiceLocator) initialize.

MovieLister >> initializeWithServiceLocator: aServiceLocator
    serviceLocator := aServiceLocator

ServiceLocatorTest >> testSimple2
    lister := MovieLister newWithServiceLocator: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


cheers -ben
 

It is a little convenience for Smalltalk, I will give that, but I was wandering if there was something alike in Pharo, by your answers I assuming there is nothing like that.



On Mon, Jun 5, 2017 at 6:41 AM, Stephane Ducasse <[hidden email]> wrote:
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:
> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Stephane Ducasse-3
Tx ben.
When I see all this complexity for something that looks not that complex: I prefer to pass the class and get done. 
May be I missed something obvious... but when I see something too complex I start to get worried. 

I think that thinking about the contract between classes at runtime is important and to me a MovieLister should be using at runtime and instance of the *Finder* 
Now needing an extra class just to set this should really be evaluated with the tradeoff: "flexibility win" (our simple solution is still really flexible - I decide when I want to pass the correct finder) vs. the code and conceptual bloat. 


I'm happy not to face the hyper super over engineering of Java "solutions".

I like the "Of course this just shifts the burden a tad, we still have to get the locator into the lister"
but the solution is super simple let us use another "Singleton and a Factory...." :)

Stef

On Mon, Jun 5, 2017 at 8:43 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 1:26 AM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the answer Ben and Stephane. 

I already read A Mentoring Course on Smalltalk, Valloud, there is nothing there I could use in this case :( . I will look after for The Design Patterns Smalltalk Companion. Most of the sources provided I already know of or went in the same lines lines of what I have already found. 

About TDD, I am experienced with the discipline and have tested it on Pharo living system already, but I could not understand how this is related with object wiring, DI and service locator.

I guess I don't properly understand your need and those topics.  That was my quick pass.  Now if I take the time to actually read Fowler's long article

"the inversion is about how they lookup a plugin implementation ... to ensure that any user of a plugin follows some convention that allows a separate assembler module to inject the implementation into the lister."

"The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface. There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection."

Now there was too much syntactical noise in those Java examples for me to think clearly, so I converted them all to Smalltalk.


##CONSTRUCTOR INJECTION

Object subclass: MovieLister
    instanceVariables: 'finder'


MovieLister class >> newWith: aFinder
    ^ self basicNew initializeWith: aFinder

MovieLister >> initializeWith: aFinder
    finder := aFinder


ColonMovieFinder class >> newWith: aFilename
    ^ self basicNew initializeWith: aFilename

ColonMovieFinder >> initializeWith: aFilename
    filename := aFilename.


ConstructorInjectionContainer >> new
    container := DefaultContainer new.  "the article doesn't specify where this comes from"
    finderParams := ConstantParameter newWith: 'movies1.txt'.
    container registerComponentInterface: MovieFinderInterface 
                          implementation: ColonMovieFinder 
                          params: finderParams.
    container registerComponentImplementation: MovieLister
    ^container

to be used like this...
ConstructorInjectionTest >> testWithContainer
    container := ConstructorInjectionContainer new.
    lister := container getComponentInstance( MovieLister ).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article poorly defines registerComponentXXX: or getComponentInstance:
methods, so I don't dwell on them.  I presume its little relevant to the main theme.


##SETTER INJECTION

MovieLister >> setFinder: aFinder
    finder := aFinder.

ColonMovieFinder >> setFilename: aFilename
    filename := aFilename.

SetterInjectionTest >> testWithConfigurationFile
    ctx := SomeXmlApplicationConfiguration on: 'config.xml'.
    lister := ctx getConfigOf: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


##INTERFACE INJECTION

MovieLister >> injectFinder: aFinder
    finder := aFinder

ColonMovieFinder >> injectFilename: aFilename
    filename := aFilename

InterfaceInjectionTest >> configureContainer
    container := InterfaceInjectionContainer new.
    self registerComponents.
    self registerInjectors.
    container start.

InterfaceInjectionTest >> registerComponents
    container registerComponent: 'MovieLister' with: MovieLister.
    container registerComponent: 'MovieFinder' with: ColonMovieFinder.

InterfaceInjectionTest >> registerInjectors
    container registerInjector: Injector  with: (container lookup: 'MovieFinder').
    container registerInjector: InjectorFinderFilename  with: FinderFilenameInjector new.

ColonMovieFinder >> inject: anObject
    anObject injectFinder: self.

FinderFilenameInjector >> inject: anObject
    anObject injectFilename: 'movies1.txt'.

InterfaceInjectionTester >> testInterface
    self configureContainer.
    lister := container lookup: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article doesn't define InterfaceInjectionContainer, but I guess it could look like this...

InterfaceInjectionContainer >> registerComponent: componentName with: aComponent
    container ifNil: [ container := Dictionary new].
    container at: componentName put: aComponent

InterfaceInjectionContainer >> lookup: componentName
    ^ container at: componentName
    

##SERVICE LOCATOR

"The basic idea behind a service locator is to have an object that knows how to get hold of all of the services that an application might need. So a service locator for this application would have a method that returns a movie finder when one is needed. Of course this just shifts the burden a tad, we still have to get the locator into the lister"

MovieLister >> initialize
    finder := ServiceLocator movieFinder.


Object subclass: ServiceLocator
    instanceVariable: 'movieFinder'
    classVariable: 'SoleInstance'

ServiceLocator class >> load: aServiceLocator
    SoleInstance := aServiceLocator

ServiceLocator class >> soleInstance  
    ^ SoleInstance

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinder

ServiceLocator >> movieFinder
    ^movieFinder


ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 


ServiceLocator class >> newWith: aMovieFinder
    ^ self basicNew initializeWithFinder: aMovieFinder

ServiceLocator >> initializeWithFinder: aMovieFinder
    movieFinder := aMovieFinder


ServiceLocatorTest >> testSimple
    self configure.
    lister := MovieLister new.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')
   
So it seems that a service locator is just a Singleton pattern having a class variable for each service of interest ??
So in good faith** I ask... "Is it any more complicated than that?" 

**Since its taken me a couple of hours to convert the Java to this point so I stopped reading to seek your feedback. 
Is that enough insight to adapt to your needs, or is there something else further down the article that invalidates my analysis?






From ben:

"I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."


So per Fowler, the above is equivalent to "Setter Injection with Spring"
 

and Stephane:

Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

That was what I meant when I said: "I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message.". The code I had in mind is a bit of mix from the one provided by you both:

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: aMovieFinderBuilder
    finder := aMovieFinderClass new.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder builderOn: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

But that means I will have to wire dependencies by hand whenever I create a MovieLister and seek through code when and if those dependencies change. When there are lot's of dependencies it's is a considerable and tedious work. Let's see an image from Fowlers article:

Inline image 1

In this case, the service locator provides me with an instance and I configure the instance in the assembler, the scheme is alike for an IoC, and that would mean my implementation could be like this:


MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>initialize
    finder := ServiceLocator locate: FinderClass   <--- This would bring the instance of finder class configured by the assembler

No, like this... 
    finder := ServiceLocation movieFinder.

Now if you want to store a class rather than an instance as I did higher up, you just do this...

Object subclass: ServiceLocator
    instanceVariable: 'movieFinderClass'
    classVariable: 'SoleInstance'

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinderClass new

 


to be used like this...
    lister := MovieLister new.
    movies := lister moviesDirectedBy: 'Tarantino'."

and the assembler:

Assember class>>configure:
aMap put: (ColonDelimitedMovieFinder builderOn: 'movies1.txt') at: FinderClass 

Assembler class>>configure
    ServiceLocator load: 
          (ServiceLocator new
               movieFinder: (ColonMovieFinder newWith: 'movies1.txt')
               otherService: MyCustomService new) 
 

My assembler and service locator could be even more elaborated, and provide a different MovieFinder in test scope, for different classes or wharever. 

Really, the test should not be updating the class variable global like this...
ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 

you probably want something like (its rough but shows the point...)
Object subclass: #MovieLister
    instanceVariables: 'serviceLocator'

MovieLister >> initialize
    serviceLocator ifNil: [ serviceLocator := ServiceLocator soleInstance ].
    finder := serviceLocator movieFinder.
 
MovieLister class >> newWithServiceLocator: aServiceLocator
    ^ (self basicNew initializeWithServiceLocator: aServiceLocator) initialize.

MovieLister >> initializeWithServiceLocator: aServiceLocator
    serviceLocator := aServiceLocator

ServiceLocatorTest >> testSimple2
    lister := MovieLister newWithServiceLocator: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


cheers -ben
 

It is a little convenience for Smalltalk, I will give that, but I was wandering if there was something alike in Pharo, by your answers I assuming there is nothing like that.



On Mon, Jun 5, 2017 at 6:41 AM, Stephane Ducasse <[hidden email]> wrote:
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:
> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>




Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Ben Coman


On Tue, Jun 6, 2017 at 5:11 AM, Stephane Ducasse <[hidden email]> wrote:
Tx ben.
When I see all this complexity for something that looks not that complex: I prefer to pass the class and get done. 
May be I missed something obvious... but when I see something too complex I start to get worried. 

I think that thinking about the contract between classes at runtime is important and to me a MovieLister should be using at runtime and instance of the *Finder* 
Now needing an extra class just to set this should really be evaluated with the tradeoff: "flexibility win" (our simple solution is still really flexible - I decide when I want to pass the correct finder) vs. the code and conceptual bloat. 


I'm happy not to face the hyper super over engineering of Java "solutions".

I like the "Of course this just shifts the burden a tad, we still have to get the locator into the lister"
but the solution is super simple let us use another "Singleton and a Factory...." :)

Stef

On Mon, Jun 5, 2017 at 8:43 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 1:26 AM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the answer Ben and Stephane. 

I already read A Mentoring Course on Smalltalk, Valloud, there is nothing there I could use in this case :( . I will look after for The Design Patterns Smalltalk Companion. Most of the sources provided I already know of or went in the same lines lines of what I have already found. 

About TDD, I am experienced with the discipline and have tested it on Pharo living system already, but I could not understand how this is related with object wiring, DI and service locator.

I guess I don't properly understand your need and those topics.  That was my quick pass.  Now if I take the time to actually read Fowler's long article

"the inversion is about how they lookup a plugin implementation ... to ensure that any user of a plugin follows some convention that allows a separate assembler module to inject the implementation into the lister."

"The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface. There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection."

Now there was too much syntactical noise in those Java examples for me to think clearly, so I converted them all to Smalltalk.


##CONSTRUCTOR INJECTION

Object subclass: MovieLister
    instanceVariables: 'finder'


MovieLister class >> newWith: aFinder
    ^ self basicNew initializeWith: aFinder

MovieLister >> initializeWith: aFinder
    finder := aFinder


ColonMovieFinder class >> newWith: aFilename
    ^ self basicNew initializeWith: aFilename

ColonMovieFinder >> initializeWith: aFilename
    filename := aFilename.


ConstructorInjectionContainer >> new
    container := DefaultContainer new.  "the article doesn't specify where this comes from"
    finderParams := ConstantParameter newWith: 'movies1.txt'.
    container registerComponentInterface: MovieFinderInterface 
                          implementation: ColonMovieFinder 
                          params: finderParams.
    container registerComponentImplementation: MovieLister
    ^container

to be used like this...
ConstructorInjectionTest >> testWithContainer
    container := ConstructorInjectionContainer new.
    lister := container getComponentInstance( MovieLister ).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article poorly defines registerComponentXXX: or getComponentInstance:
methods, so I don't dwell on them.  I presume its little relevant to the main theme.


##SETTER INJECTION

MovieLister >> setFinder: aFinder
    finder := aFinder.

ColonMovieFinder >> setFilename: aFilename
    filename := aFilename.

SetterInjectionTest >> testWithConfigurationFile
    ctx := SomeXmlApplicationConfiguration on: 'config.xml'.
    lister := ctx getConfigOf: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


##INTERFACE INJECTION

MovieLister >> injectFinder: aFinder
    finder := aFinder

ColonMovieFinder >> injectFilename: aFilename
    filename := aFilename

InterfaceInjectionTest >> configureContainer
    container := InterfaceInjectionContainer new.
    self registerComponents.
    self registerInjectors.
    container start.

InterfaceInjectionTest >> registerComponents
    container registerComponent: 'MovieLister' with: MovieLister.
    container registerComponent: 'MovieFinder' with: ColonMovieFinder.

InterfaceInjectionTest >> registerInjectors
    container registerInjector: Injector  with: (container lookup: 'MovieFinder').
    container registerInjector: InjectorFinderFilename  with: FinderFilenameInjector new.

ColonMovieFinder >> inject: anObject
    anObject injectFinder: self.

FinderFilenameInjector >> inject: anObject
    anObject injectFilename: 'movies1.txt'.

InterfaceInjectionTester >> testInterface
    self configureContainer.
    lister := container lookup: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article doesn't define InterfaceInjectionContainer, but I guess it could look like this...

InterfaceInjectionContainer >> registerComponent: componentName with: aComponent
    container ifNil: [ container := Dictionary new].
    container at: componentName put: aComponent

InterfaceInjectionContainer >> lookup: componentName
    ^ container at: componentName
    

##SERVICE LOCATOR

"The basic idea behind a service locator is to have an object that knows how to get hold of all of the services that an application might need. So a service locator for this application would have a method that returns a movie finder when one is needed. Of course this just shifts the burden a tad, we still have to get the locator into the lister"

MovieLister >> initialize
    finder := ServiceLocator movieFinder.


Object subclass: ServiceLocator
    instanceVariable: 'movieFinder'
    classVariable: 'SoleInstance'

ServiceLocator class >> load: aServiceLocator
    SoleInstance := aServiceLocator

ServiceLocator class >> soleInstance  
    ^ SoleInstance

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinder

ServiceLocator >> movieFinder
    ^movieFinder


ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 


ServiceLocator class >> newWith: aMovieFinder
    ^ self basicNew initializeWithFinder: aMovieFinder

ServiceLocator >> initializeWithFinder: aMovieFinder
    movieFinder := aMovieFinder


ServiceLocatorTest >> testSimple
    self configure.
    lister := MovieLister new.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')
   
So it seems that a service locator is just a Singleton pattern having a class variable for each service of interest ??

It was late and I mispoke here, of course this should have said... 
* a Singleton pattern having an instance variable for each service of interest
* a Singleton pattern having a getter method (with hidden implementation) for each service of interest

 
So in good faith** I ask... "Is it any more complicated than that?" 

**Since its taken me a couple of hours to convert the Java to this point so I stopped reading to seek your feedback. 

but I'll add, it was so much simpler to understand without all that Java typing boiler plate.

cheers -ben
 
Is that enough insight to adapt to your needs, or is there something else further down the article that invalidates my analysis?






From ben:

"I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."


So per Fowler, the above is equivalent to "Setter Injection with Spring"
 

and Stephane:

Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

That was what I meant when I said: "I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message.". The code I had in mind is a bit of mix from the one provided by you both:

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: aMovieFinderBuilder
    finder := aMovieFinderClass new.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder builderOn: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

But that means I will have to wire dependencies by hand whenever I create a MovieLister and seek through code when and if those dependencies change. When there are lot's of dependencies it's is a considerable and tedious work. Let's see an image from Fowlers article:

Inline image 1

In this case, the service locator provides me with an instance and I configure the instance in the assembler, the scheme is alike for an IoC, and that would mean my implementation could be like this:


MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>initialize
    finder := ServiceLocator locate: FinderClass   <--- This would bring the instance of finder class configured by the assembler

No, like this... 
    finder := ServiceLocation movieFinder.

Now if you want to store a class rather than an instance as I did higher up, you just do this...

Object subclass: ServiceLocator
    instanceVariable: 'movieFinderClass'
    classVariable: 'SoleInstance'

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinderClass new

 


to be used like this...
    lister := MovieLister new.
    movies := lister moviesDirectedBy: 'Tarantino'."

and the assembler:

Assember class>>configure:
aMap put: (ColonDelimitedMovieFinder builderOn: 'movies1.txt') at: FinderClass 

Assembler class>>configure
    ServiceLocator load: 
          (ServiceLocator new
               movieFinder: (ColonMovieFinder newWith: 'movies1.txt')
               otherService: MyCustomService new) 
 

My assembler and service locator could be even more elaborated, and provide a different MovieFinder in test scope, for different classes or wharever. 

Really, the test should not be updating the class variable global like this...
ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 

you probably want something like (its rough but shows the point...)
Object subclass: #MovieLister
    instanceVariables: 'serviceLocator'

MovieLister >> initialize
    serviceLocator ifNil: [ serviceLocator := ServiceLocator soleInstance ].
    finder := serviceLocator movieFinder.
 
MovieLister class >> newWithServiceLocator: aServiceLocator
    ^ (self basicNew initializeWithServiceLocator: aServiceLocator) initialize.

MovieLister >> initializeWithServiceLocator: aServiceLocator
    serviceLocator := aServiceLocator

ServiceLocatorTest >> testSimple2
    lister := MovieLister newWithServiceLocator: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


cheers -ben
 

It is a little convenience for Smalltalk, I will give that, but I was wandering if there was something alike in Pharo, by your answers I assuming there is nothing like that.



On Mon, Jun 5, 2017 at 6:41 AM, Stephane Ducasse <[hidden email]> wrote:
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:
> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>





Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Vitor Medina Cruz
Thanks for the detailed answer ben :)

I will try to clarify a little: the question is how to loosely wire objects, such as MovieLister to MovieFinder, so that changes in the wiring can be made without effort. In Java, people use DI containers and xml files or annotations to provide the wiring configuration, which is easy to switch entirely. For example, I could have a xml file for production code and another for testing purposes. 

Also, another advantage is that the container takes care of ordering object creation for me. For example, if the object A, B and C needed to be injected on the object Y, I just have to declare each one of those objects on the configuration file, the container arranges the creation order for me. 

I started, however, to question DI as a valid mechanisms because of it's complexities and other problems. The article from Fowler provides the service locator as an alternative which seems to me much simpler and completely fine solution for the problem. 

So, to answer you question "Is it any more complicated than that?": In the DI approach, yes it can be, but I don't think so in the service locator approach.

I am asking here because I wanted to know how people from Smalltalk deal with this problem. As it seems there is no standard approach, nor this is perceived as a problem... You think it is enough to do the wiring by hand? It is ok to use a service locator approach? Or wouldn't you care about that?


but I'll add, it was so much simpler to understand without all that Java typing boiler plate.

Yeah, that's for sure! I am just used to read Java code.

[]s,
Vitor

On Mon, Jun 5, 2017 at 9:46 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 5:11 AM, Stephane Ducasse <[hidden email]> wrote:
Tx ben.
When I see all this complexity for something that looks not that complex: I prefer to pass the class and get done. 
May be I missed something obvious... but when I see something too complex I start to get worried. 

I think that thinking about the contract between classes at runtime is important and to me a MovieLister should be using at runtime and instance of the *Finder* 
Now needing an extra class just to set this should really be evaluated with the tradeoff: "flexibility win" (our simple solution is still really flexible - I decide when I want to pass the correct finder) vs. the code and conceptual bloat. 


I'm happy not to face the hyper super over engineering of Java "solutions".

I like the "Of course this just shifts the burden a tad, we still have to get the locator into the lister"
but the solution is super simple let us use another "Singleton and a Factory...." :)

Stef

On Mon, Jun 5, 2017 at 8:43 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 1:26 AM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the answer Ben and Stephane. 

I already read A Mentoring Course on Smalltalk, Valloud, there is nothing there I could use in this case :( . I will look after for The Design Patterns Smalltalk Companion. Most of the sources provided I already know of or went in the same lines lines of what I have already found. 

About TDD, I am experienced with the discipline and have tested it on Pharo living system already, but I could not understand how this is related with object wiring, DI and service locator.

I guess I don't properly understand your need and those topics.  That was my quick pass.  Now if I take the time to actually read Fowler's long article

"the inversion is about how they lookup a plugin implementation ... to ensure that any user of a plugin follows some convention that allows a separate assembler module to inject the implementation into the lister."

"The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface. There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection."

Now there was too much syntactical noise in those Java examples for me to think clearly, so I converted them all to Smalltalk.


##CONSTRUCTOR INJECTION

Object subclass: MovieLister
    instanceVariables: 'finder'


MovieLister class >> newWith: aFinder
    ^ self basicNew initializeWith: aFinder

MovieLister >> initializeWith: aFinder
    finder := aFinder


ColonMovieFinder class >> newWith: aFilename
    ^ self basicNew initializeWith: aFilename

ColonMovieFinder >> initializeWith: aFilename
    filename := aFilename.


ConstructorInjectionContainer >> new
    container := DefaultContainer new.  "the article doesn't specify where this comes from"
    finderParams := ConstantParameter newWith: 'movies1.txt'.
    container registerComponentInterface: MovieFinderInterface 
                          implementation: ColonMovieFinder 
                          params: finderParams.
    container registerComponentImplementation: MovieLister
    ^container

to be used like this...
ConstructorInjectionTest >> testWithContainer
    container := ConstructorInjectionContainer new.
    lister := container getComponentInstance( MovieLister ).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article poorly defines registerComponentXXX: or getComponentInstance:
methods, so I don't dwell on them.  I presume its little relevant to the main theme.


##SETTER INJECTION

MovieLister >> setFinder: aFinder
    finder := aFinder.

ColonMovieFinder >> setFilename: aFilename
    filename := aFilename.

SetterInjectionTest >> testWithConfigurationFile
    ctx := SomeXmlApplicationConfiguration on: 'config.xml'.
    lister := ctx getConfigOf: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


##INTERFACE INJECTION

MovieLister >> injectFinder: aFinder
    finder := aFinder

ColonMovieFinder >> injectFilename: aFilename
    filename := aFilename

InterfaceInjectionTest >> configureContainer
    container := InterfaceInjectionContainer new.
    self registerComponents.
    self registerInjectors.
    container start.

InterfaceInjectionTest >> registerComponents
    container registerComponent: 'MovieLister' with: MovieLister.
    container registerComponent: 'MovieFinder' with: ColonMovieFinder.

InterfaceInjectionTest >> registerInjectors
    container registerInjector: Injector  with: (container lookup: 'MovieFinder').
    container registerInjector: InjectorFinderFilename  with: FinderFilenameInjector new.

ColonMovieFinder >> inject: anObject
    anObject injectFinder: self.

FinderFilenameInjector >> inject: anObject
    anObject injectFilename: 'movies1.txt'.

InterfaceInjectionTester >> testInterface
    self configureContainer.
    lister := container lookup: 'MovieLister'.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')

The article doesn't define InterfaceInjectionContainer, but I guess it could look like this...

InterfaceInjectionContainer >> registerComponent: componentName with: aComponent
    container ifNil: [ container := Dictionary new].
    container at: componentName put: aComponent

InterfaceInjectionContainer >> lookup: componentName
    ^ container at: componentName
    

##SERVICE LOCATOR

"The basic idea behind a service locator is to have an object that knows how to get hold of all of the services that an application might need. So a service locator for this application would have a method that returns a movie finder when one is needed. Of course this just shifts the burden a tad, we still have to get the locator into the lister"

MovieLister >> initialize
    finder := ServiceLocator movieFinder.


Object subclass: ServiceLocator
    instanceVariable: 'movieFinder'
    classVariable: 'SoleInstance'

ServiceLocator class >> load: aServiceLocator
    SoleInstance := aServiceLocator

ServiceLocator class >> soleInstance  
    ^ SoleInstance

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinder

ServiceLocator >> movieFinder
    ^movieFinder


ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 


ServiceLocator class >> newWith: aMovieFinder
    ^ self basicNew initializeWithFinder: aMovieFinder

ServiceLocator >> initializeWithFinder: aMovieFinder
    movieFinder := aMovieFinder


ServiceLocatorTest >> testSimple
    self configure.
    lister := MovieLister new.
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')
   
So it seems that a service locator is just a Singleton pattern having a class variable for each service of interest ??

It was late and I mispoke here, of course this should have said... 
* a Singleton pattern having an instance variable for each service of interest
* a Singleton pattern having a getter method (with hidden implementation) for each service of interest

 
So in good faith** I ask... "Is it any more complicated than that?" 

**Since its taken me a couple of hours to convert the Java to this point so I stopped reading to seek your feedback. 

but I'll add, it was so much simpler to understand without all that Java typing boiler plate.

cheers -ben
 
Is that enough insight to adapt to your needs, or is there something else further down the article that invalidates my analysis?






From ben:

"I'm not really familiar with IoC or DI patterns, so just taking your example at face value, in Pharo I'd do...

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: movieFinder
    finder := movieFinder.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder on: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."


So per Fowler, the above is equivalent to "Setter Injection with Spring"
 

and Stephane:

Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

That was what I meant when I said: "I know that in Smalltalk I can make MovieLister to receive, upon construction, a class representing MovieFinder and call it construction message.". The code I had in mind is a bit of mix from the one provided by you both:

MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>finder: aMovieFinderBuilder
    finder := aMovieFinderClass new.

to be used like this...
    lister := MovieLister new finder: (ColonDelimitedMovieFinder builderOn: 'movies1.txt').
    movies := lister moviesDirectedBy: 'Tarantino'."

But that means I will have to wire dependencies by hand whenever I create a MovieLister and seek through code when and if those dependencies change. When there are lot's of dependencies it's is a considerable and tedious work. Let's see an image from Fowlers article:

Inline image 1

In this case, the service locator provides me with an instance and I configure the instance in the assembler, the scheme is alike for an IoC, and that would mean my implementation could be like this:


MovieLister>>moviesDirectedBy: director
    allMovies := finder allMovies.
    ^ allMovies select: [ :movie | movie getDirector = director ].
    "although typically #getDirector would be renamed #director"

MovieLister>>initialize
    finder := ServiceLocator locate: FinderClass   <--- This would bring the instance of finder class configured by the assembler

No, like this... 
    finder := ServiceLocation movieFinder.

Now if you want to store a class rather than an instance as I did higher up, you just do this...

Object subclass: ServiceLocator
    instanceVariable: 'movieFinderClass'
    classVariable: 'SoleInstance'

ServiceLocator class >> movieFinder
    ^ self soleInstance movieFinderClass new

 


to be used like this...
    lister := MovieLister new.
    movies := lister moviesDirectedBy: 'Tarantino'."

and the assembler:

Assember class>>configure:
aMap put: (ColonDelimitedMovieFinder builderOn: 'movies1.txt') at: FinderClass 

Assembler class>>configure
    ServiceLocator load: 
          (ServiceLocator new
               movieFinder: (ColonMovieFinder newWith: 'movies1.txt')
               otherService: MyCustomService new) 
 

My assembler and service locator could be even more elaborated, and provide a different MovieFinder in test scope, for different classes or wharever. 

Really, the test should not be updating the class variable global like this...
ServiceLocatorTest >> configure
    ServiceLocator load: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')) 

you probably want something like (its rough but shows the point...)
Object subclass: #MovieLister
    instanceVariables: 'serviceLocator'

MovieLister >> initialize
    serviceLocator ifNil: [ serviceLocator := ServiceLocator soleInstance ].
    finder := serviceLocator movieFinder.
 
MovieLister class >> newWithServiceLocator: aServiceLocator
    ^ (self basicNew initializeWithServiceLocator: aServiceLocator) initialize.

MovieLister >> initializeWithServiceLocator: aServiceLocator
    serviceLocator := aServiceLocator

ServiceLocatorTest >> testSimple2
    lister := MovieLister newWithServiceLocator: (ServiceLocator newWith: (ColonMovieFinder newWith: 'movies1.txt')).
    movies = lister moviesDirectedBy: 'Sergio Leone'.
    self assert: (movies includes: 'Once Upon a Time in the West')


cheers -ben
 

It is a little convenience for Smalltalk, I will give that, but I was wandering if there was something alike in Pharo, by your answers I assuming there is nothing like that.



On Mon, Jun 5, 2017 at 6:41 AM, Stephane Ducasse <[hidden email]> wrote:
Why don't you simply pass the class and use that class in your MovieLister?

MovieLister new
     finderClass: MySuperCoolFinderClass

...
MovieLister finder
      finderClass new .....

What is wrong with that.

If you do not want to have a reference at runtime to a Finder then you
need to use announcement and registration.

Stef



On Sun, Jun 4, 2017 at 11:17 PM, Vitor Medina Cruz <[hidden email]> wrote:
> Hello,
>
> I would like to know how people in Pharo ecosystem do to deal with object
> wiring, as described by Marting Fowler in
> https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection:
>
> "A common issue to deal with is how to wire together different elements: how
> do you fit together this web controller architecture with that database
> interface backing when they were built by different teams with little
> knowledge of each other."
>
> He gives an example, I will leave it in java as it is simple enough to
> understand:
>
> "class MovieLister...
>
>   public Movie[] moviesDirectedBy(String arg) {
>       List allMovies = finder.findAll();
>       for (Iterator it = allMovies.iterator(); it.hasNext();) {
>           Movie movie = (Movie) it.next();
>           if (!movie.getDirector().equals(arg)) it.remove();
>       }
>       return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
>
>   }"
>
> The question is how to provide the finder object in a decoupled matter, a
> naive approach would be:
>
> " private MovieFinder finder;
>
>   public MovieLister() {
>     finder = new ColonDelimitedMovieFinder("movies1.txt");
>
>   }"
>
> Which couples the MovieLister to the specific ColonDelimitedMovieFinder
> class.
>
> Fowler explains how to decouple using an IoC framework or a Service Locator.
> In Java and .Net IoC is used most of the time. I Googled how this problem is
> approached in Smalltalk/Pharo, and I generally I found answers "that is easy
> to do in Smalltalk, so there is no need of a framework", what I miss is a
> description on *how* to do that:
>
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc
> https://stackoverflow.com/questions/2684326/is-there-a-dependency-injection-framework-for-smalltalk
> https://stackoverflow.com/questions/243905/smalltalk-and-ioc/347477#347477
>
> I know that in Smalltalk I can make MovieLister to receive, upon
> construction, a class representing MovieFinder and call it construction
> message. As long an object that responds to this message is provided, I can
> create as many derivations I want and the MovieLister will be decoupled from
> the MovieFinder. That way, however, I still have to wire things by hand, and
> I am not sure if this is what I am supposed to do in order to solve the
> decouple problem.
>
> Can you explain me how this is done in Pharo? It's is usually wiring by
> hand? Is there a simple construction that deals with the wiring problem that
> I cannot foresee?
>
> Thanks in advance,
> Vitor
>
>
>






Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Attila Magyar
In reply to this post by Vitor Medina Cruz
I don't think using a DI container worth the effort. They add lots of complexities and solve very little. For some reason DI containers became very popular in the Java world, but if you take a look at other programming communities you'll realize that many people are perfectly happy without using these containers. Using DI and using a DI container is orthogonal. As you also said you can just pass dependencies to objects to achieve loose coupling. Yes, you have to do this manually but what's the big deal? We're talking about code with cyclomatic complexity of 1. Calling a constructor is not a problem that need to be solved. Using an external XML configuration to describe object wiring is the worst idea ever.

Here is an article about using plain old object composition to do DI

http://blog.davidpeterson.co.uk/2011/01/object-oriented-example.html

Some more thoughts about the problems associated with DI containers:

http://www.natpryce.com/articles/000783.html
http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook
Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Ben Coman
In reply to this post by Vitor Medina Cruz


On Tue, Jun 6, 2017 at 9:11 PM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the detailed answer ben :)

I will try to clarify a little: the question is how to loosely wire objects, such as MovieLister to MovieFinder, so that changes in the wiring can be made without effort. In Java, people use DI containers and xml files or annotations to provide the wiring configuration, which is easy to switch entirely. For example, I could have a xml file for production code and another for testing purposes. 

Also, another advantage is that the container takes care of ordering object creation for me. For example, if the object A, B and C needed to be injected on the object Y, I just have to declare each one of those objects on the configuration file, the container arranges the creation order for me. 

I don't see what is special about this.  You can easily arrange instance creation order with methods on the class-side of your domain classes.
Indeed, the GTTools are set up to work with in-Image sample data.  Look at implementors of #sample and #example.
There was quite some bike-shedding over the naming convention (and I forget the final result), but hopefully it provide the general idea...


 

I started, however, to question DI as a valid mechanisms because of it's complexities and other problems. The article from Fowler provides the service locator as an alternative which seems to me much simpler and completely fine solution for the problem. 

If it seems suitable, then to quote Nike, just do it ;)

 
So, to answer you question "Is it any more complicated than that?": In the DI approach, yes it can be, but I don't think so in the service locator approach.

I am asking here because I wanted to know how people from Smalltalk deal with this problem. As it seems there is no standard approach, nor this is perceived as a problem...


DI or Service Locator are both "implementations" of your need.  Can we take step backward to see what is your need?  To kick off, I hazard a guess at some possible needs...

1.  To switch between configurations to use production data and test data ?
2.  To make this switch during CI testing and production deployment ?
3.  To switch from the command line ?
4.  Want the configuration to editable remotely? e.g. from a text editor?
?
...

 
You think it is enough to do the wiring by hand?

I'm having trouble understanding this "by hand" concept.  
Don't you create the xml configuration file by hand?  
You can just as easily 

 
It is ok to use a service locator approach?  Or wouldn't you care about that?

If it works, its okay.

So very generally, I'd avoid starting with any external test data, so as to not distract myself by that implementation.
I'd copy-paste some test data into the class-side-methods of the domain classes and hack some instance creation code around them.
Build your first tests around those. Then later, consolidate them via an InImageTestData object that you'll later replace with ExternalTestData  

 


but I'll add, it was so much simpler to understand without all that Java typing boiler plate.

Yeah, that's for sure! I am just used to read Java code.

[]s,
Vitor



As an aside, try evaluting "Smalltalk tools inspect" 
and debugging "Smalltalk tools browser open"

cheers -ben
Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Peter Uhnak
> I don't see what is special about this.  You can easily arrange instance
> creation order with methods on the class-side of your domain classes.

I will not use the term "class", but rather a "service" (service can be just a single class, but that is not always the case). The point of inversion of control is provide the class with what is needed instead of the class creating it on it's own.
Sure, you can create class-side helper, however that is very limited, such as the examples/samples as you've demonstrated.

To give you an example, imagine that you have a class PeopleService that manages database of people, so it needs a connection to the database. Implemented in a naive way the class would have hard-coded credentials to a MySQL database and it would execute raw SQL queries. This works for a single class, but it creates a mess and mingles concerns; so instead you inverse the control and you provide PeopleService with e.g. a Persistence instance, which is already connected to the database; note however that you cannot just create the Persistence on the class-side, because you wouldn't even know what to instantiate (as you could e.g. use DbPersistence, FilePersistence, ...). And this is just a basic example. Imagine that the PeopleService also needs other services for it's use, and those services need more services, and you want to keep everything separated as much as possible... instantiation by hand will simply not cut it So the service locator/DI configuration (whether as annotations or in a XML file) keeps the actual classes separated from concrete instances; the service depends on abstract interfaces, not specific classes; only the conf determines the specific ones, and more often than not there will be several different configurations _at the same time_. To continue with the example you could have one config production using e.g. OraclePersistence, another for development using MySQLPersistance, another for test server using MemoryPersistence, etc. (also with different credentials, and whatnot).

Keep in mind however that relates primarily to using application frameworks, where the framework mandates the control, and the framework is the one calling you, and therefore it will also provide you with necessary parts. After all you are not even creating PeopleService class, the framework instantiates it for you and gives it to another services/classes that needed it.

Now I don't feel like there are many application frameworks in Pharo, maybe Seaside has something of this sorts? I guess Spec can be a bit framework-y, as the basic spec widgets do not actually know what Morphic counterparts will be created for them, and Spec looks up the actual class in a hard-coded data table (which might as well be a XML file), but that comes closer to ServiceLocator than DI (as Spec widgets should not actually communicate down to morphic).

I've used dependency injection for five years at my previous work and frankly I cannot imagine living without it there, but I've never felt the need for it in Pharo. This is probably more related to working in Pharo on completely different things and writing small libraries. However I wouldn't be surprised if the liveness of Smalltalk/Pharo environment eliminated some of the problems that DI is trying to solve. But then again, there are many ways to build systems, and not all need or benefit DI/IoC.

Peter

> Indeed, the GTTools are set up to work with in-Image sample data.  Look at
> implementors of #sample and #example.
> There was quite some bike-shedding over the naming convention (and I forget
> the final result), but hopefully it provide the general idea...
>
> http://forum.world.st/a-request-to-change-the-meaning-of-lt-example-gt-pragma-td4927360.html
> http://forum.world.st/lt-example-gt-lt-examplar-gt-td4911728i20.html
> http://forum.world.st/Existing-lt-script-gt-lt-example-gt-pragmas-and-new-GT-needs-td4814903i20.html
>
>
>
> >
> > I started, however, to question DI as a valid mechanisms because of it's
> > complexities and other problems. The article from Fowler provides the
> > service locator as an alternative which seems to me much simpler and
> > completely fine solution for the problem.
> >
>
> If it seems suitable, then to quote Nike, just do it ;)
>
>
>
> > So, to answer you question "Is it any more complicated than that?": In
> > the DI approach, yes it can be, but I don't think so in the service locator
> > approach.
> >
> > I am asking here because I wanted to know how people from Smalltalk deal
> > with this problem. As it seems there is no standard approach, nor this is
> > perceived as a problem...
> >
>
>
> DI or Service Locator are both "implementations" of your need.  Can we take
> step backward to see what is your need?  To kick off, I hazard a guess at
> some possible needs...
>
> 1.  To switch between configurations to use production data and test data ?
> 2.  To make this switch during CI testing and production deployment ?
> 3.  To switch from the command line ?
> 4.  Want the configuration to editable remotely? e.g. from a text editor?
> ?
> ...
>
>
>
> > You think it is enough to do the wiring by hand?
> >
>
> I'm having trouble understanding this "by hand" concept.
> Don't you create the xml configuration file by hand?
> You can just as easily
>
>
>
> > It is ok to use a service locator approach?  Or wouldn't you care about
> > that?
> >
>
> If it works, its okay.
>
> So very generally, I'd avoid starting with any external test data, so as to
> not distract myself by that implementation.
> I'd copy-paste some test data into the class-side-methods of the domain
> classes and hack some instance creation code around them.
> Build your first tests around those. Then later, consolidate them via an
> InImageTestData object that you'll later replace with ExternalTestData
>
>
>
> >
> >
> > but I'll add, it was so much simpler to understand without all that Java
> >> typing boiler plate.
> >
> >
> > Yeah, that's for sure! I am just used to read Java code.
> >
> > []s,
> > Vitor
> >
> >
> >
> As an aside, try evaluting "Smalltalk tools inspect"
> and debugging "Smalltalk tools browser open"
>
> cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Ben Coman
In reply to this post by Attila Magyar


On Tue, Jun 6, 2017 at 11:48 PM, Attila Magyar <[hidden email]> wrote:
I don't think using a DI container worth the effort. They add lots of
complexities and solve very little. For some reason DI containers became
very popular in the Java world, but if you take a look at other programming
communities you'll realize that many people are perfectly happy without
using these containers. Using DI and using a DI container is orthogonal. As
you also said you can just pass dependencies to objects to achieve loose
coupling. Yes, you have to do this manually but what's the big deal? We're
talking about code with cyclomatic complexity of 1. Calling a constructor is
not a problem that need to be solved. Using an external XML configuration to
describe object wiring is the worst idea ever.

Here is an article about using plain old object composition to do DI

http://blog.davidpeterson.co.uk/2011/01/object-oriented-example.html

Some more thoughts about the problems associated with DI containers:

http://www.natpryce.com/articles/000783.html

I liked this...  "the [Dependency Injection] pattern also used to be called "third-party binding" or "third-party connect": some third party is responsible for connecting an object satisfying the service requirements of a component"
This makes the subject seem less esoteric.  It reminds me of hearing that the first (secret) task when doing a PhD is to invent new terms for common ones, and base your writings on that. Perhaps its the same for consultants and framework developers. ;P   Or maybe everything seems esoteric until you have experience with it and I've not done much with Java, certainly not big applications.  

Thx Peter for your example and how you prior experience compares to Pharo. 

cheers -ben 


http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook



--
View this message in context: http://forum.world.st/Wiring-objects-IoC-and-Service-Locator-tp4949280p4949720.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.


Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Vitor Medina Cruz
Thanks for the links Attila, do you have an alternative one to the http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook? It seems to be broken.

I also started to also think containers don't worth the effort, but I am still concerned with problems faced with hand wiring everything as Peter clearly exemplified, thanks for the excellent summary and exemplification Peter!

And this is just a basic example. Imagine that the PeopleService also needs other services for it's use, and those services need more services, and you want to keep everything separated as much as possible... instantiation by hand will simply not cut it 

This is exactly my concern! Sure, for small stuff that is not a problem, but what if you have a big app? Now, my experience with containers and Java may be shadowing my vision: people in Java community tend to use anemic model and to create gazzilions layers for even simple stuff, which make the wiring problem even worse. My experiments with a more OO approach and Smalltalk tells me one would need much less need of containers by using proper OO and a less verbose language, but I am not sure.

Keep in mind however that relates primarily to using application frameworks, where the framework mandates the control, and the framework is the one calling you, and therefore it will also provide you with necessary parts. After all you are not even creating PeopleService class, the framework instantiates it for you and gives it to another services/classes that needed it.

This is true for IoC DI containers, but I don't think it applies for service locator, which, I think, could not be considered a framework approach. Actually, I think being a framework is the big problem of the of the former, since when I start to use an IoC container to create objects I got tied to it in a very basic and pervasive operation of an OO system: object creation. Suddenly everything must be created through the DI container, but that is not true for Service Locator.

However I wouldn't be surprised if the liveness of Smalltalk/Pharo environment eliminated some of the problems that DI is trying to solve. 

That is precisely what I wanted to know. It seems there are no DI counterpart in the Pharo/Smalltalk environment, ok, so what people do to to deal with the above mentioned problem? Hand wiring is suffice? Is there anything in the liveness of Smalltalk/Pharo that eliminates the need for it? People use simple Service Locator, or variations of it?


cheers!
Vitor

On Wed, Jun 7, 2017 at 9:32 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 11:48 PM, Attila Magyar <[hidden email]> wrote:
I don't think using a DI container worth the effort. They add lots of
complexities and solve very little. For some reason DI containers became
very popular in the Java world, but if you take a look at other programming
communities you'll realize that many people are perfectly happy without
using these containers. Using DI and using a DI container is orthogonal. As
you also said you can just pass dependencies to objects to achieve loose
coupling. Yes, you have to do this manually but what's the big deal? We're
talking about code with cyclomatic complexity of 1. Calling a constructor is
not a problem that need to be solved. Using an external XML configuration to
describe object wiring is the worst idea ever.

Here is an article about using plain old object composition to do DI

http://blog.davidpeterson.co.uk/2011/01/object-oriented-example.html

Some more thoughts about the problems associated with DI containers:

http://www.natpryce.com/articles/000783.html

I liked this...  "the [Dependency Injection] pattern also used to be called "third-party binding" or "third-party connect": some third party is responsible for connecting an object satisfying the service requirements of a component"
This makes the subject seem less esoteric.  It reminds me of hearing that the first (secret) task when doing a PhD is to invent new terms for common ones, and base your writings on that. Perhaps its the same for consultants and framework developers. ;P   Or maybe everything seems esoteric until you have experience with it and I've not done much with Java, certainly not big applications.  

Thx Peter for your example and how you prior experience compares to Pharo. 

cheers -ben 


http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook



--
View this message in context: http://forum.world.st/Wiring-objects-IoC-and-Service-Locator-tp4949280p4949720.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.



Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Attila Magyar
It seems to be broken.
Here is an archived version. http://archive.li/GCbEY#selection-755.0-755.38
Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

philippeback
In reply to this post by Vitor Medina Cruz
Also realize the Smalltalk image is a container...

No need for fancy XML externalization because you can do that with code.

I have an app where I wire all kinds of things together in a configuration file which is Smalltalk code and I just compile a method like "wireEverything" that as source has that configuration file. Or just do a Compiler evaluate: aLongConfigurationStringInSmalltalk

Any Dictionary can be a "SpringContext" thing.

Now decorators with specific features like transaction support etc is not something we have and things like Spring do have.

We could take inspiration from Spring Boot.


Best Regards,
Phil







On Thu, Jun 8, 2017 at 1:46 PM, Vitor Medina Cruz <[hidden email]> wrote:
Thanks for the links Attila, do you have an alternative one to the http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook? It seems to be broken.

I also started to also think containers don't worth the effort, but I am still concerned with problems faced with hand wiring everything as Peter clearly exemplified, thanks for the excellent summary and exemplification Peter!

And this is just a basic example. Imagine that the PeopleService also needs other services for it's use, and those services need more services, and you want to keep everything separated as much as possible... instantiation by hand will simply not cut it 

This is exactly my concern! Sure, for small stuff that is not a problem, but what if you have a big app? Now, my experience with containers and Java may be shadowing my vision: people in Java community tend to use anemic model and to create gazzilions layers for even simple stuff, which make the wiring problem even worse. My experiments with a more OO approach and Smalltalk tells me one would need much less need of containers by using proper OO and a less verbose language, but I am not sure.

Keep in mind however that relates primarily to using application frameworks, where the framework mandates the control, and the framework is the one calling you, and therefore it will also provide you with necessary parts. After all you are not even creating PeopleService class, the framework instantiates it for you and gives it to another services/classes that needed it.

This is true for IoC DI containers, but I don't think it applies for service locator, which, I think, could not be considered a framework approach. Actually, I think being a framework is the big problem of the of the former, since when I start to use an IoC container to create objects I got tied to it in a very basic and pervasive operation of an OO system: object creation. Suddenly everything must be created through the DI container, but that is not true for Service Locator.

However I wouldn't be surprised if the liveness of Smalltalk/Pharo environment eliminated some of the problems that DI is trying to solve. 

That is precisely what I wanted to know. It seems there are no DI counterpart in the Pharo/Smalltalk environment, ok, so what people do to to deal with the above mentioned problem? Hand wiring is suffice? Is there anything in the liveness of Smalltalk/Pharo that eliminates the need for it? People use simple Service Locator, or variations of it?


cheers!
Vitor

On Wed, Jun 7, 2017 at 9:32 PM, Ben Coman <[hidden email]> wrote:


On Tue, Jun 6, 2017 at 11:48 PM, Attila Magyar <[hidden email]> wrote:
I don't think using a DI container worth the effort. They add lots of
complexities and solve very little. For some reason DI containers became
very popular in the Java world, but if you take a look at other programming
communities you'll realize that many people are perfectly happy without
using these containers. Using DI and using a DI container is orthogonal. As
you also said you can just pass dependencies to objects to achieve loose
coupling. Yes, you have to do this manually but what's the big deal? We're
talking about code with cyclomatic complexity of 1. Calling a constructor is
not a problem that need to be solved. Using an external XML configuration to
describe object wiring is the worst idea ever.

Here is an article about using plain old object composition to do DI

http://blog.davidpeterson.co.uk/2011/01/object-oriented-example.html

Some more thoughts about the problems associated with DI containers:

http://www.natpryce.com/articles/000783.html

I liked this...  "the [Dependency Injection] pattern also used to be called "third-party binding" or "third-party connect": some third party is responsible for connecting an object satisfying the service requirements of a component"
This makes the subject seem less esoteric.  It reminds me of hearing that the first (secret) task when doing a PhD is to invent new terms for common ones, and base your writings on that. Perhaps its the same for consultants and framework developers. ;P   Or maybe everything seems esoteric until you have experience with it and I've not done much with Java, certainly not big applications.  

Thx Peter for your example and how you prior experience compares to Pharo. 

cheers -ben 


http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook



--
View this message in context: http://forum.world.st/Wiring-objects-IoC-and-Service-Locator-tp4949280p4949720.html
Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.




Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Attila Magyar
In reply to this post by Vitor Medina Cruz
Vitor Medina Cruz wrote
This is exactly my concern! Sure, for small stuff that is not a problem, but what if you have a big app?
I don't think it makes any difference. You have to decide in each case whether an object is an internal (implementation detail) and therefore it must be created from inside the class that uses it, or a dependency (or peer) that should be passed as an argument. In the later case you instantiate the object from the outside and hand it over to the object that requires it.
Most applications have a few major top level abstractions. Let's call them subsystems. I would use more domain specific names in a concrete case but this is a general example. These subsystems are instantiated at the entry point of the application. If there are shared dependencies between them, those are instantiated here as well. Then each subsystem can build up some object graph that is required by the actual subsystem (Not everything needs to know about everything else. There are clusters of objects that represent domain level abstractions). The same things applies here as well. Some dependencies are passed through (peers), others are instantiated (internals) from the inside. This can go on and on further and it will result a fractal like structure. The whole application is one object. It consists of few other objects. Those object consists of further objects. In a typical Spring application there is big blob of object soup with full of equivalent objects, everyone can access to everything else and this fractal structure is missing.
Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Peter Uhnak
In reply to this post by Vitor Medina Cruz
On Thu, Jun 08, 2017 at 08:46:15AM -0300, Vitor Medina Cruz wrote:

> This is true for IoC DI containers, but I don't think it applies for
> service locator, which, I think, could not be considered a framework
> approach. Actually, I think being a framework is the big problem of the of
> the former, since when I start to use an IoC container to create objects I
> got tied to it in a very basic and pervasive operation of an OO system:
> object creation.

Well that is the objective of DI to handle the object creation on your behalf. Of course no class is prohibited from creating instances directly, provided it had the necessary dependencies to give to the instance.

> Suddenly everything must be created through the DI container, but that is not true for Service Locator.

As I've noted above, DI doesn't restrict you from creating instances. Service Locator gives you a more flexible approach, however it follows that it can be also harder to manage, as the services registered in the locator can (and typically do) change at runtime, which inhibits static reasoning about the dependencies, compared to a pre-fixed configuration.

>
> However I wouldn't be surprised if the liveness of Smalltalk/Pharo
> > environment eliminated some of the problems that DI is trying to solve.
>
>
> That is precisely what I wanted to know. It seems there are no DI
> counterpart in the Pharo/Smalltalk environment, ok, so what people do to to
> deal with the above mentioned problem? Hand wiring is suffice? Is there
> anything in the liveness of Smalltalk/Pharo that eliminates the need for
> it? People use simple Service Locator, or variations of it?

In my previous mail I've mentioned Spec doing something of the sorts, but I don't think I've seen it anywhere else. The hand-wiring mostly suffices; sometimes you can see having a method containing the name of the class it will instantiate (and which can be altered in a subclass). My best guess would be that the capabilities of Pharo, such as pluggable closures, and being a live already-running system are more likely to push the programmer towards a different architecture, where incidentally DI's are not such a concern, but I would certainly love to see some deep analysis on this.


Peter

>
>
> cheers!
> Vitor
>
> On Wed, Jun 7, 2017 at 9:32 PM, Ben Coman <[hidden email]> wrote:
>
> >
> >
> > On Tue, Jun 6, 2017 at 11:48 PM, Attila Magyar <[hidden email]>
> > wrote:
> >
> >> I don't think using a DI container worth the effort. They add lots of
> >> complexities and solve very little. For some reason DI containers became
> >> very popular in the Java world, but if you take a look at other
> >> programming
> >> communities you'll realize that many people are perfectly happy without
> >> using these containers. Using DI and using a DI container is orthogonal.
> >> As
> >> you also said you can just pass dependencies to objects to achieve loose
> >> coupling. Yes, you have to do this manually but what's the big deal? We're
> >> talking about code with cyclomatic complexity of 1. Calling a constructor
> >> is
> >> not a problem that need to be solved. Using an external XML configuration
> >> to
> >> describe object wiring is the worst idea ever.
> >>
> >> Here is an article about using plain old object composition to do DI
> >>
> >> http://blog.davidpeterson.co.uk/2011/01/object-oriented-example.html
> >>
> >> Some more thoughts about the problems associated with DI containers:
> >>
> >> http://www.natpryce.com/articles/000783.html
> >
> >
> > I liked this...  "the [Dependency Injection] pattern also used to be
> > called "third-party binding" or "third-party connect": some third party is
> > responsible for connecting an object satisfying the service requirements of
> > a component"
> > This makes the subject seem less esoteric.  It reminds me of hearing that
> > the first (secret) task when doing a PhD is to invent new terms for common
> > ones, and base your writings on that. Perhaps its the same for consultants
> > and framework developers. ;P   Or maybe everything seems esoteric until you
> > have experience with it and I've not done much with Java, certainly not big
> > applications.
> >
> > Thx Peter for your example and how you prior experience compares to Pharo.
> >
> > cheers -ben
> >
> >
> >> http://higherorderlogic.com/2011/07/is-dependency-injection-like-facebook
> >>
> >>
> >>
> >> --
> >> View this message in context: http://forum.world.st/Wiring-o
> >> bjects-IoC-and-Service-Locator-tp4949280p4949720.html
> >> Sent from the Pharo Smalltalk Users mailing list archive at Nabble.com.
> >>
> >>
> >

Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Peter Uhnak
In reply to this post by Attila Magyar
On Thu, Jun 08, 2017 at 08:02:04AM -0700, Attila Magyar wrote:
> Vitor Medina Cruz wrote
> > This is exactly my concern! Sure, for small stuff that is not a problem,
> > but what if you have a big app?
>
> I don't think it makes any difference.

Scale can make all the difference. Imagine the complexity of connecting N elements. If you have just tree objects/classes/systems... you need just two connections, but you if double the number of elements, you need more than seven times more connections (to form a complete graph). Of course in practice that number will be smaller, but certainly more than linear to the number of elements. So what works in small scale doesn't necessarily translate to bigger scale, not to mention that brand new concerns are probably going to arise... just like when you are constructing a taller building, you cannot just slap it twice on each other, because the foundations will collapse, and when you want to build a space elevator, you need technology that hasn't been invented yet.


Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

Attila Magyar
Peter Uhnak wrote
Scale can make all the difference.

I don't think it should. If you have a small cluster of objects where you can manage the dependencies yourself, you can compose larger objects from them and manage the dependencies the same way. By doing so, you'll get an object that is simpler from the outside than it's parts in the inside, and you'll need to solve the smaller problem again. In other words we shouldn't write large software, but compose large software from smaller ones. But the same can be done with objects (that's why I'm not a big fan of microservices despite they solve this problem similarly).
If you have a flat structure (where objects don't form higher level abstractions) and everything needs to know about everything else, then the DI container will make it easier to work with this structure. But I don't think this is the right way to organize a software.
Reply | Threaded
Open this post in threaded view
|

Re: Wiring objects, IoC and Service Locator

aryehof
In reply to this post by Vitor Medina Cruz
In SmallTalk:-

1. Blocks (i.e. anonymous functions) means that one needs not necessarily implement a Class (MovieFinder), in order to vary alternative behavior, unlike Java (before 8).

2. If one does want a number of "finders" (as Classes), then one will typically see one "injected" (constructor or method injection), where each understands some common "find" message.

Is the real question for 2 above, "what (or who) decides" which will be injected?
12