Obviously there are people who are enthusiastic and people that
aren't. The work expressed in the PDF is excellent but something
doesn't sound right, in particular when they talk about the scope, not
the idea of the scope that is good, but how this idea is applied to
code. In general what I don't like is the use of the name and the
explicit use of a class called scope. In example of the GOOS these
concepts are present but are implicit and there isn't a class called
scope that manages the scope of the object or there aren't any classes
called *inject. I would appreciate your opinion about this technique.
Thank you very much
Gianluca
P.S.
The GOOS is a fantastic book as every page is gold. For me it was
fantastic because it was the practical implementation of a lot of
theoretical study that I had made, in particular the role of the mock
object to discover the role between objects, the use of the Acceptance
Test to design the software, the non-use of a framework of DI, etc ...
I can't wait for your next book :-)
I read through half of it before giving up. I really can't imagine how this tedious, ugly and uncommon framework could be seen as better, or less intrusive, than Guice.
Especially considering that in Guice 3 you can use the standard @Inject or even go annotation-less by binding directly to a constructor.
Moandji
Sent from my Android
--Nat
If you're looking into framework-less DI, you might also consider this
approach:
http://sonymathew.blogspot.com/2009/11/context-ioc-revisited-i-wrote-about.html
Although I consider both somewhat verbose. DIY-DI's static factory
methods do seem a bit excessive, and Context IoC's per-class interfaces
also seem like more work than necessary.
Personally, I've had success passing scope classes directly to
constructors, e.g.:
public interface ApplicationScope {
DepA getA();
}
public class MyService {
private final DepA a;
public MyService(ApplicationScope s) {
this.a = s.getA();
}
}
It is not as conceptually clean as either DIY-DI or Context IoC, both of
which avoid MyService depending on the outside ApplicationScope
interface. And it also hides the real dependencies (a in this case)
inside of the MyService's cstr, instead of in the cstr argument list.
The trade off is that wiring becomes a lot simpler, because you just
pass ApplicationScope around and let objects use what they need. In
practice, it has worked well for me but YRMV.
Though I'm sure the GOOS authors would take me to task for having
non-domain language terms like "scope" and "service" floating around the
codebase. Fair enough. :-)
- Stephen
S.
On 1 Dec 2010, at 20:39, Stephen Haberman wrote:
>
> Personally, I've had success passing scope classes directly to
> constructors, e.g.:
>
> public interface ApplicationScope {
> DepA getA();
> }
>
> public class MyService {
> private final DepA a;
> public MyService(ApplicationScope s) {
> this.a = s.getA();
> }
> }
>
> It is not as conceptually clean as either DIY-DI or Context IoC, both of
> which avoid MyService depending on the outside ApplicationScope
> interface. And it also hides the real dependencies (a in this case)
> inside of the MyService's cstr, instead of in the cstr argument list.
> The trade off is that wiring becomes a lot simpler, because you just
> pass ApplicationScope around and let objects use what they need. In
> practice, it has worked well for me but YRMV.
>
> Though I'm sure the GOOS authors would take me to task for having
> non-domain language terms like "scope" and "service" floating around the
> codebase. Fair enough. :-)
>
> - Stephen
>
Steve Freeman
Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com
+44 (0) 797 179 4105
M3P Limited. http://www.m3p.co.uk
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 03689627
Do you have an example of going "annotation-less" construction with guice?
Hi,
in my team there is a discussion about this technique to apply the
DI.The technique is described in these two links:
http://blacksheep.parry.org/archives/diy-di
http://blacksheep.parry.org/wp-content/uploads/2010/03/DIY-DI.pdf
Do you have an example of going "annotation-less" construction with guice?
Hi Nat,
probably I don't express well what I think, I retry. In this document
there is a suggestion to create class named *Scope, and the
responsability of this type of class is to manage the different life
cycle of other object.
In the example of the GOOS there isn't anything like this and the
scope of the variables is "implicit" in the class, method, block where
the variables are defined. Do I understand correct?
In the Sniper application, for example, when you press the join
button, you create a AuctionSniper through the SniperLauncher, the
scope of the AuctionSniper start when the button is pressed, but the
sniper use object that have application scope (connection for
example). To manage this situation using the DIY-DI technique I should
create something like AuctionScope and pass it to SniperLauncher.
In the example of the pdf (BatchLineReader pag 11) the author want
process a file and for every line they want create a new
TradeProcessor and use the object tradeScopeEntrance to create
TradeProcessor. How you can manage this situation without the use of
the scope object?
Thanks in advance
Gianluca
I "feel" that this way is not good but I can't transmit these
sensation to my team, any suggestions? :-)
bye
Gianluca
That is NOT implicit! Java is a block structured language with lexical
scoping. IT ALREADY IMPLEMENTS SCOPES with well defined semantics. So
we are VERY EXPLICIT in our use of scopes and did not waste time
reimplementing something that is already provided by the language.
> In the example of the pdf (BatchLineReader pag 11) the author want
> process a file and for every line they want create a new
> TradeProcessor and use the object tradeScopeEntrance to create
> TradeProcessor. How you can manage this situation without the use of
> the scope object?
Why not create a new object for every line and pass the line to it to
be processed? You can do that with a callback or "by hand" in a for-
loop, depending whether the processing is push- or pull-driven. The
object defines the instance variables it needs to do its work, so it
already is a scope. If you use an inner class, it can refer to the
variables in the scope in which it is defined (it's a closure). Or you
can pass its constructor references to the objects it needs, and it
can store those references in instance variables.
--Nat
>
I think I'm using the word "implicit" wrong, sorry. I'm agree with you
that Java already implements the scopes with a well defined semantics
and it's better than a reinvented one. This concept (semantic) is
already presented in Java and we shouldn't reinvent it.
> Why not create a new object for every line and pass the line to it to
> be processed? You can do that with a callback or "by hand" in a for-
> loop, depending whether the processing is push- or pull-driven. The
> object defines the instance variables it needs to do its work, so it
> already is a scope. ...
Thank you for your suggestion
bye
Gianluca
I'm not sure what you intend for "without the principles", I think it
don't express what the software should do in term of domain and
"force" the developer to create a lot of *inject and *scope class
without think about the role of the class in the domain. My fear is
that if we apply this technique for a month we full our code base of
injector and scope class but our code will not became more clear or
more easy to change.
I've always injected stuff through constructors without knowing what
"injection" or "scopes" meant. I mean, it is kind of common sense.
IMO trying to figure out what happens in, for example, a thoroughly
injection dependent Spring FW project is a nightmare.
(disclaimer: I'm not a Spring expert, just haven't seen clean code done with it)
--
"Progress doesn't come from early risers — progress is made by lazy
men looking for easier ways to do things." - Robert. A. Heinlein
>
> In the Sniper application, for example, when you press the join
> button, you create a AuctionSniper through the SniperLauncher, the
> scope of the AuctionSniper start when the button is pressed, but the
> sniper use object that have application scope (connection for
> example). To manage this situation using the DIY-DI technique I should
> create something like AuctionScope and pass it to SniperLauncher.
Is there confusion between 'scope' (which is lexical in Java and refers to variables) and 'extent', which refers to the duration of the objects existence?
> I don't know about *inject and *scope classes, because I've done dependencyI've always injected stuff through constructors without knowing what
> injection for years without knowing what those things mean.
"injection" or "scopes" meant. I mean, it is kind of common sense.
IMO trying to figure out what happens in, for example, a thoroughly
injection dependent Spring FW project is a nightmare.
I don't know about services in the DDD sense, but in the general
OO-design case I might amend that advice to say push all decisions
about which objects to create up as far as possible, but no further:
"Composite Simpler than the Sum of its Parts", "Outside-In", etc.
--Nat
I have to admit that I just never find the need to explicitly
represent scopes/lifetimes the way you describe or squirrel them away
in thread-local variables or AOP gubbins. I create an object that
needs to do something, giving it references to the objects that it
needs to do its job. I pass its reference to the sources of events
that will trigger its behaviour. When an event source will no longer
feed it events, the source "forgets" the reference. Eventually there
will be no references to the object and it gets garbage collected.
That, in turn, may cause the collection of the objects that it depends
on, and so on...
--Nat
S.
Steve Freeman
http://www.m3p.co.uk/blog
Written on a phone, so please allow for typos and short content.
Following on from Nat, the problem with annotating a class with its scope is that an object shouldn't really control its own lifecycle. That should be the job of its context.
the implementation of a singleton needs to be thread-safe, but it doesn't need to know if it's the only instance. And anything but read-only singletons are a bad idea anyway, so best not to encourage them... :)
S.
_very_ true (GUICE considered harmful).
I've seen too many instances of novices spraying Guice DI annotations throughout a codebase.
I've seen too many instances of novices spraying Guice DI annotations throughout a codebase. Agree that you learn by doing it by hand first, but I don't see many people doing that. Not just Guice/DI, of course (nothing makes you appreciate ORM, session management etc more than building your own first).
No, but if they don't learn the principles behind improving the design, then they'll never stop being novices.
On Thu, Dec 9, 2010 at 1:21 AM, J. B. Rainsberger <m...@jbrains.ca> wrote:No, but if they don't learn the principles behind improving the design, then they'll never stop being novices.Agreed. I just don't want them writing their framework on my project. So we'll use Spring/Guice/etc.
If you're absolutely determined to use a DI framework,
then I recommend you take a look at Newie (http://github.com/guilhermesilveira/newie); it's written in Ruby, but I believe there is a underway to Java. I'd say it was ideal for novices who need to learn the principles behind dependency injection without having to learn the ins and outs of a complex framework.
> A web application typically has request scope, session scope and
> application scope (also known as singleton scope). Other common ones
> are conversation scope (for example filling a form; conversation
> consists of multiple related requests, but is smaller than session
> scope), thread scope, transaction scope
Exactly, you have clearly explained what I want to say
Thank you Esko!!
P.S.
I don't Like this technique and I'm trying to understand how to
resolve the problem raised in the PDF in another way.
On Thu, Dec 9, 2010 at 1:21 AM, J. B. Rainsberger <m...@jbrains.ca> wrote:No, but if they don't learn the principles behind improving the design, then they'll never stop being novices.Agreed. I just don't want them writing their framework on my project. So we'll use Spring/Guice/etc.
Arguably, though, a small framework like Guice can aid in learning the design principles, since you can concentrate on collaborators, scopes and constructors without getting muddled up in the plumbing. In my experience, Spring is too complex to be a good learning tool.
Hi Joe,
I don't understand what you suggested, let me try to recap:
- Don't use DI framework if you are a novice.
- Use DI framework only if you know the principle behind the framework
Is it correct?
I think the discussion is not only about the PDF that I sent but also
about the use of framework for DI.
The PDF, I think, suggests to use some principles/ideas (the scope and
the injector class) that could be used instead of a framework.
Isn't that what you are suggesting Joe?
bye
Gianluca
So you want the people on your project to learn these principles, but not while they're on your project?
Arguably, though, a small framework like Guice can aid in learning the design principles, since you can concentrate on collaborators, scopes and constructors without getting muddled up in the plumbing. In my experience, Spring is too complex to be a good learning tool.
I believe you can do the same simple things with both, if you restrict yourself to those features.
On Thu, Dec 9, 2010 at 12:16 PM, J. B. Rainsberger <m...@jbrains.ca> wrote:So you want the people on your project to learn these principles, but not while they're on your project?No, I don't want them writing the framework (I'd rather not write my own framework on my project). I'm happy for people to learn principles while on a project (I do so all the time). Then, I'd rather use a well-known and robust implementation of those principles than a buggy and perpetually half-finished one. As a side benefit, you might run into that framework again on another project.
2010/12/9 J. B. Rainsberger <m...@jbrains.ca>:
> I believe you can do the same simple things with both, if you restrictHi Joe,
> yourself to those features.
I don't understand what you suggested, let me try to recap:
- Don't use DI framework if you are a novice.
- Use DI framework only if you know the principle behind the framework
Is it correct?
I think the discussion is not only about the PDF that I sent but also
about the use of framework for DI.
The PDF, I think, suggests to use some principles/ideas (the scope and
the injector class) that could be used instead of a framework.
Isn't that what you are suggesting Joe?
On Thu, Dec 9, 2010 at 12:16 PM, J. B. Rainsberger <m...@jbrains.ca> wrote:So you want the people on your project to learn these principles, but not while they're on your project?No, I don't want them writing the framework (I'd rather not write my own framework on my project). I'm happy for people to learn principles while on a project (I do so all the time). Then, I'd rather use a well-known and robust implementation of those principles than a buggy and perpetually half-finished one. As a side benefit, you might run into that framework again on another project.
I just came across this, which is close to my own feelings: http://www.jonarcher.com/2010/12/perils-of-rolling-your-own.html
I believe you can do the same simple things with both, if you restrict yourself to those features.Of course, but in my experience of teaching people, getting up and running in Spring has always been a little complex, while doing so in Guice is trivial.
1. Tell your client to give you the dependencies you need.
2. Depend on abstractions instead of details.
I have the opposite experience. In 2002-2003 (...)
>> @ImplementedBy(SomeClass.class)I've spent a happy afternoon getting rid of this from a large codebase. Mysterious defaults, scattered around all your interface files: not good, IMHO, and one of the bits of Guice that I wish people would stay away from.
it is sorta amusing/odd/weird/annoying to me how java started out
with, i think, a very "be clear and explicit and just live with the
boilerplate" and then has been shoved over time ever more towards
"sprinkle some magic on".
it is sorta amusing/odd/weird/annoying to me how java started out
with, i think, a very "be clear and explicit and just live with the
boilerplate" and then has been shoved over time ever more towards
"sprinkle some magic on".
I read your last couple of mails this morning and let them sink in for the rest of the day before responding. I found them really valuable, so wanted to respond in kind.
I love the concise way you've expressed this. I like to think that I apply (or at least try to apply) these principles, but I'd never boiled them down so well.
Thanks for that story. I'm kind of biased here because I've written my own little MVC framework based on Guice. After reading your emails, I thought a little more about 1) Could I write it without Guice? and 2) Why am I using Guice?Thinking about the first question, I guess I could, fairly easily. Annotations aside, there's nothing that fundamentally necessitates a framework: I have interfaces and implementations broken down according to fairly logical, self-contained chunks of functionality. For example, a Responder is an interface for something that knows how to write some data to the HTTP response. One implementation is the JsonResponder, that takes a JSONObject in its constructor. Other interfaces handle looking up the correct request handler, convert request parameters, etc. Were I to rip Guice out, I guess I'd have to move the wiring and knowledge of scopes into the servlet that receives and dispatches all requests (or a collaborator). That wouldn't be too difficult, but it would stop being a framework.To answer the second question, I like that Guice avoids my having to write out all the wiring, I continue to find it more logical to put scope requirements on the class itself and finally it makes it easier for people to integrate with and extend the framework. For example, I can get sensible defaults by putting @ImplementedBy(SomeClass.class) on an interface to get default behaviour, which can then be overridden by the user if necessary.
Thanks for the thought-provoking conversation,
About the sensible defaults, doesn't it make sense in a framework, though? Like how rails or grails provide a default persistence mechanism, which you can change if you wish. Imagine if instead you had to specify the implementation of every single module the framework used. It would be a nightmare.
In my case, I don't see the value, from a usability/friendliness point of view, of forcing the user to choose a routing mechansim every single time. Yes, it's impure from a DI standpoint, but makes frameworks easier to use.
Perhaps an alternative could be to bundle up a set of bindings and make that a "one-stop" configuration.
Moandji
Sent from my phone
About the sensible defaults, doesn't it make sense in a framework, though? Like how rails or grails provide a default persistence mechanism, which you can change if you wish.
Imagine if instead you had to specify the implementation of every single module the framework used. It would be a nightmare.
In my case, I don't see the value, from a usability/friendliness point of view, of forcing the user to choose a routing mechansim every single time. Yes, it's impure from a DI standpoint, but makes frameworks easier to use.
Perhaps an alternative could be to bundle up a set of bindings and make that a "one-stop" configuration.