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 <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#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" http://www.weizhishi.tech/questions/296612/smalltalk-and-ioc 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'." http://randycoulman.com/blog/2013/06/04/affordances-dependency-injection/ 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." https://gbracha.blogspot.com.au/2007/06/constructors-considered-harmful.html 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... https://www.youtube.com/watch?v=ymITEeAOtEA https://www.youtube.com/watch?v=XxqZVAOomfM 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') > 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 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 > > > >