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 <b...@openinworld.com> wrote:

>
>
> On Tue, Jun 6, 2017 at 5:11 AM, Stephane Ducasse <stepharo.s...@gmail.com>
> 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 <b...@openinworld.com> wrote:
>>
>>>
>>>
>>> On Tue, Jun 6, 2017 at 1:26 AM, Vitor Medina Cruz <vitormc...@gmail.com>
>>> 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:
>>>>
>>>> [image: 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 <
>>>> stepharo.s...@gmail.com> 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 <
>>>>> vitormc...@gmail.com> 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#FormsOfDepe
>>>>> ndencyInjection:
>>>>> >
>>>>> > "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-depen
>>>>> dency-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 via email to