DI/wiring

Discussion in 'Java' started by Stefan Ram, Apr 18, 2013.

  1. Stefan Ram

    Stefan Ram Guest

    I have »invented« myself something that also seems to be
    known as »dependency injection« or »wiring«. I am doing it
    in pure Java SE without any framework, for example:

    component0.acceptPrinter( printer0 );
    component0.acceptEngine( engine0 );
    component1.acceptPrinter( printer0 );
    component1.acceptEngine( engine0 );
    component2.acceptPrinter( printer0 );
    component2.acceptEngine( engine0 );

    . Now, however, every component needs to have all that
    boilerplate code like an implementation of »acceptPrinter«
    and so.

    The whole project would need much less boilerplate, if
    I would just do:

    Globals.printer = printer0;
    Globals.engine = engine0;

    and every component that needs the printer or the engine
    would just use »Globals.printer« or »Globals.engine«, just
    as we use the »global« »java.lang.System.out«.

    Some people, however, frown upon such globals. But would
    it be that bad?
     
    Stefan Ram, Apr 18, 2013
    #1
    1. Advertising

  2. Stefan Ram

    Daniel Pitts Guest

    On 4/18/13 9:03 AM, Stefan Ram wrote:
    > I have »invented« myself something that also seems to be
    > known as »dependency injection« or »wiring«. I am doing it
    > in pure Java SE without any framework, for example:

    I think "invented" is the wrong word here. Discovered? Uncovered?
    Migrated toward? Maybe reinvented.
    >
    > component0.acceptPrinter( printer0 );
    > component0.acceptEngine( engine0 );
    > component1.acceptPrinter( printer0 );
    > component1.acceptEngine( engine0 );
    > component2.acceptPrinter( printer0 );
    > component2.acceptEngine( engine0 );

    Why aren't those simply setters? Must you go against all convention in
    every possible way?
    >
    > . Now, however, every component needs to have all that
    > boilerplate code like an implementation of »acceptPrinter«
    > and so.

    Most IDE's will generate getters/setters for you automatically. Yes, it
    is boilerplate, but it is useful to have such explicit declarations.
    >
    > The whole project would need much less boilerplate, if
    > I would just do:
    >
    > Globals.printer = printer0;
    > Globals.engine = engine0;
    >
    > and every component that needs the printer or the engine
    > would just use »Globals.printer« or »Globals.engine«, just
    > as we use the »global« »java.lang.System.out«.
    >
    > Some people, however, frown upon such globals. But would
    > it be that bad?

    It depends on the scope of your project, the size of your team, and the
    expected lifespan of the product.

    For a small project with a one person team for a product which will last
    a week, that's absolutely fine.

    For any other combination, it *will* cause problems at some point. A
    new feature will require component0 to use a different printer than
    component2, and component1 uses a different engine. Or, someone will
    unwittingly change the value of a Global value, and effect more than
    they intended. Especially if this ends up being concurrent code.

    java.lang.System.out is global accessible because it truly is a global
    entity. It isn't just "an output", it is *the* system's output. I
    wouldn't want to use it in most code directly, but instead pass around a
    PrintWriter, PrintStream, or even an OutputStream. That way, if the
    main program wants to redirect the output of the library, it can do so
    with no hoops to jump through.
     
    Daniel Pitts, Apr 18, 2013
    #2
    1. Advertising

  3. Stefan Ram

    Joerg Meier Guest

    On 18 Apr 2013 16:03:21 GMT, Stefan Ram wrote:

    > I have »invented« myself something that also seems to be
    > known as »dependency injection« or »wiring«. I am doing it
    > in pure Java SE without any framework, for example:


    > component0.acceptPrinter( printer0 );
    > component0.acceptEngine( engine0 );
    > component1.acceptPrinter( printer0 );
    > component1.acceptEngine( engine0 );
    > component2.acceptPrinter( printer0 );
    > component2.acceptEngine( engine0 );


    > . Now, however, every component needs to have all that
    > boilerplate code like an implementation of »acceptPrinter«
    > and so.


    Change the methods to setPrinter and setEngine instead, and use Lombok. And
    just like that, your boilerplate is reduced to

    @Data class Bla {
    private Engine engine;
    private Printer printer;
    }

    Liebe Gruesse,
    Joerg

    --
    Ich lese meine Emails nicht, replies to Email bleiben also leider
    ungelesen.
     
    Joerg Meier, Apr 18, 2013
    #3
  4. Stefan Ram

    Daniel Pitts Guest

    On 4/18/13 11:56 AM, Joerg Meier wrote:
    > On 18 Apr 2013 16:03:21 GMT, Stefan Ram wrote:
    >
    >> I have »invented« myself something that also seems to be
    >> known as »dependency injection« or »wiring«. I am doing it
    >> in pure Java SE without any framework, for example:

    >
    >> component0.acceptPrinter( printer0 );
    >> component0.acceptEngine( engine0 );
    >> component1.acceptPrinter( printer0 );
    >> component1.acceptEngine( engine0 );
    >> component2.acceptPrinter( printer0 );
    >> component2.acceptEngine( engine0 );

    >
    >> . Now, however, every component needs to have all that
    >> boilerplate code like an implementation of »acceptPrinter«
    >> and so.

    >
    > Change the methods to setPrinter and setEngine instead, and use Lombok. And
    > just like that, your boilerplate is reduced to
    >
    > @Data class Bla {
    > private Engine engine;
    > private Printer printer;
    > }
    >
    > Liebe Gruesse,
    > Joerg
    >


    Thanks for the pointer to Lombok!

    If only I was still programming in Java professionally, this would come
    in very handy! Too bad my company is switching to PHP. No flames
    please, all the arguments have been made and vetoed already ;-(.
     
    Daniel Pitts, Apr 18, 2013
    #4
  5. Stefan Ram

    Joerg Meier Guest

    On 18 Apr 2013 16:03:21 GMT, Stefan Ram wrote:

    > I have »invented« myself something that also seems to be
    > known as »dependency injection« or »wiring«. I am doing it
    > in pure Java SE without any framework, for example:


    On second thought, what you've "invented" here is not dependency injection,
    it's the problem that DI intends to solve. If you want a solution (other
    than the low tech one I posted): get Google Guice, Weld, Spring or any
    other injection framework, and it becomes (almost) as easy as:

    class Bla {
    @Inject private Engine engine;
    @Inject private Printer printer;
    }

    That's literally what those things are made for. The reason why those
    solutions are preferred over "globals" or the Singleton anti-pattern is
    because with common DI frameworks, it is easy to change the implementation
    of one (or many) of the injected components. For example (slightly
    paraphrased):

    if (developmentMode)
    guiceInjector.bind(Printer.class)
    .to(DebugPrinter.class);
    else
    guiceInjector.bind(Printer.class)
    .to(LogFilePrinter.class);

    And without ever touching any of your classes, you have changed all of them
    to use either one of the Printer classes. Especially useful for testing.

    There are of course a lot of other ways to change or adjust the behaviour
    of the injection provider to inject whichever component you prefer.

    Guice is probably the most light weight DI framework around. Note that
    retrofitting existing applications to use a DI framework can be a bit
    messy, as injection generally won't work on objects instantiated with the
    "new" keyword instead of being injected.

    Liebe Gruesse,
    Joerg

    --
    Ich lese meine Emails nicht, replies to Email bleiben also leider
    ungelesen.
     
    Joerg Meier, Apr 18, 2013
    #5
  6. Stefan Ram

    Joerg Meier Guest

    On Thu, 18 Apr 2013 12:08:25 -0700, Daniel Pitts wrote:

    > If only I was still programming in Java professionally, this would come
    > in very handy! Too bad my company is switching to PHP. No flames
    > please, all the arguments have been made and vetoed already ;-(.


    You have my condolences. Being forced to work in PHP infuriatingly often
    myself, I feel your pain. I think what hits me the most with PHP is the
    lack of a proper IDE-level AST and the lack of refactoring coming even
    remotely close to what's available in any modern Java IDE.

    I think the problem with the PHP ecosystem can be summarized by my PHP-only
    friends comment when I told him about how awesome the various Java IDEs
    were: "My text editor has line numbers and syntax highlighting now, it's
    probably better than your IDE."

    Liebe Gruesse,
    Joerg

    --
    Ich lese meine Emails nicht, replies to Email bleiben also leider
    ungelesen.
     
    Joerg Meier, Apr 18, 2013
    #6
  7. Stefan Ram

    markspace Guest

    On 4/18/2013 9:03 AM, Stefan Ram wrote:
    > I have »invented« myself something that also seems to be
    > known as »dependency injection« or »wiring«. I am doing it


    I should have a look at Joerg's answer myself, but here's another idea.

    Make an app context object that holds the state of your app.

    class Context {
    Engine getEngine()....
    Printer getPrinter()...
    }

    Inject that into submodules in the code. Submodules are larger than
    classes and can treat the context as immutable. The context then
    becomes global but only for that module. The idea is that you still get
    dependency injecting, but you can still test reasonably as well.

    class SomeConfig {
    Context context;
    public SomeConfig( Context c ) { context = c; }

    public init() {
    Component c0 = new Component( context );

    ....
    }
    }

    class Component {
    Context context;...
    public printIt() {
    context.getPrinter().do something...
    }
    }

    This reduces boilerplate but doesn't eliminate it. For some projects it
    might be better to get a real dependency injection framework.
     
    markspace, Apr 18, 2013
    #7
  8. Stefan Ram

    Roedy Green Guest

    On 18 Apr 2013 16:03:21 GMT, -berlin.de (Stefan Ram)
    wrote, quoted or indirectly quoted someone who said :

    > I have »invented« myself something that also seems to be
    > known as »dependency injection« or »wiring«. I am doing it
    > in pure Java SE without any framework, for example:


    you might think about specifying the corrections is some simple
    grammar, and having a Stomper crank out Java source code.

    That way you may be able to hide much of the bubblegum.
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    Computer programming is the best remedy for pain (physical or emotional)
    I have encountered. It requires so much concentration there is nothing left
    over to pay attention to the pain. They should teach this in AA.
     
    Roedy Green, Apr 18, 2013
    #8
  9. On 18/04/2013 21:16, markspace allegedly wrote:
    > On 4/18/2013 9:03 AM, Stefan Ram wrote:
    >> I have »invented« myself something that also seems to be
    >> known as »dependency injection« or »wiring«. I am doing it

    >
    > I should have a look at Joerg's answer myself, but here's another idea.
    >
    > Make an app context object that holds the state of your app.
    >
    > class Context {
    > Engine getEngine()....
    > Printer getPrinter()...
    > }
    >
    > Inject that into submodules in the code. Submodules are larger than
    > classes and can treat the context as immutable. The context then
    > becomes global but only for that module. The idea is that you still get
    > dependency injecting, but you can still test reasonably as well.
    >
    > class SomeConfig {
    > Context context;
    > public SomeConfig( Context c ) { context = c; }
    >
    > public init() {
    > Component c0 = new Component( context );
    >
    > ....
    > }
    > }
    >
    > class Component {
    > Context context;...
    > public printIt() {
    > context.getPrinter().do something...
    > }
    > }
    >
    > This reduces boilerplate but doesn't eliminate it. For some projects it
    > might be better to get a real dependency injection framework.


    As a side note, since this approach has the drawback of requiring
    additional constructor or method parameters (and hence targeted
    factoring), I have in such cases often found it useful to provide the
    context object via the threadlocal functionality.

    In code terms, instead of:
    class Actor {
    void act( Context c ){ doSomethingWith( c.getXXX() ); }
    }
    You'd have:
    class Actor {
    void act(){
    doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
    }
    }

    --
    DF.
     
    Daniele Futtorovic, Apr 22, 2013
    #9
  10. Stefan Ram

    markspace Guest

    On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
    >
    > In code terms, instead of:
    > class Actor {
    > void act( Context c ){ doSomethingWith( c.getXXX() ); }
    > }


    Just to be clear, I was advocating using constructors, not method
    parameters:

    public class Actor {
    private Context c;
    public Actor( Context c ) {this.c = c}
    public void act() { doSomethingWith( c.getXXX() ); }
    }

    This is really really different:

    > You'd have:
    > class Actor {
    > void act(){
    > doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
    > }
    > }


    Now actor does something different depending on what thread is invoking
    a method. My class was invariant with respect to the thread invoking its
    method. No matter who calls "act()" the result will always be the same.

    Since modern systems often use thread pools and the worker threads are
    supposed to be generic and often randomly assigned, I can't see too many
    cases where your thread local context is going to be useful. Worse, if
    an generic worker thread has a context and then is assigned to another
    task... the results could be random and unpredictable, and really hard
    to debug as well.

    I'm sure you must have some use case in mind where a thread local is
    useful, but I'm having a hard time seeing it. It feels like you push
    the context/initialization problem into the threading system, where it's
    actually going to be harder to manage. In a system that was designed
    from the ground up to support contexts attached to threads, OK it might
    work, but in many existing systems it seems difficult to add.
     
    markspace, Apr 22, 2013
    #10
  11. Stefan Ram

    Stefan Ram Guest

    Daniel Pitts <> writes:
    >Why aren't those simply setters? Must you go against all convention in
    >every possible way?


    I just had to remember that remark, when I read a method
    name of mine that made me smile myself, it was the name

    acceptReportAcceptor

    . Here is some more context:

    public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    { this.reportAcceptor = reportAcceptor; }

    . But now, honestly, when one sees a hungry man, and gives
    him some bread and says:

    »Sir, please accept this bread!«

    this sound fine to me, while

    »Sir, please set this bread!«

    sounds strange. In

    object.acceptNumber( 2 )

    I tell the object to accept the number, but what is

    object.setNumber( 2 )

    supposed to mean? How can the object set the number 2?
    This makes no sense!

    But I am not a native English speaker. May be I am missing
    something here.

    Imagine I would have called the reportAcceptor
    »reportSetter«. This would have made no sense to me! This
    object is supposed to accept a report, not to set a report!
    The report is already »set« by the caller, the callee is
    just asked to kindly consider accepting it!

    >Why aren't those simply setters?


    Actually I do not know the definition of »setter« that you
    take as basis for your question. When do you call something
    a setter?
     
    Stefan Ram, Apr 24, 2013
    #11
  12. On 22/04/2013 19:59, markspace allegedly wrote:
    > On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
    >>
    >> In code terms, instead of:
    >> class Actor {
    >> void act( Context c ){ doSomethingWith( c.getXXX() ); }
    >> }

    >
    > Just to be clear, I was advocating using constructors, not method
    > parameters:
    >
    > public class Actor {
    > private Context c;
    > public Actor( Context c ) {this.c = c}
    > public void act() { doSomethingWith( c.getXXX() ); }
    > }


    Yes; this is why I spoke of "constructor or method parameters".

    See, the problem, or issue, with this approach is that you make the
    context part of the actor's state. Meaning the actor is bound to the
    context, rather than being context-independent. For instance, the
    component wouldn't be reusable for a different context.

    Now, there may be situations where that would be the right thing to do.
    Yet, because of that, this approach to me is inferior to passing the
    context to the main actor method (the method that encapsulates the unit
    of work).

    > This is really really different:
    >
    >> You'd have:
    >> class Actor {
    >> void act(){
    >> doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
    >> }
    >> }

    >
    > Now actor does something different depending on what thread is invoking
    > a method. My class was invariant with respect to the thread invoking its
    > method. No matter who calls "act()" the result will always be the same.
    >
    > Since modern systems often use thread pools and the worker threads are
    > supposed to be generic and often randomly assigned, I can't see too many
    > cases where your thread local context is going to be useful. Worse, if
    > an generic worker thread has a context and then is assigned to another
    > task... the results could be random and unpredictable, and really hard
    > to debug as well.


    I'll have to disagree with you here. All systems that use thread pools
    will involve some sort of dispatch mechanism that consumes a queue of
    work units. I do not believe it is far fetched to imagine that the
    dispatch mechanism would run as exemplified in the following:

    while take-from-queue
    set-up-context
    try {
    execute-task
    } finally {
    clean-up-context
    }

    The only situation, then, where the ThreadLocal wouldn't work is when
    the work units are executed on multiple threads. I may be wrong, but I
    do not see this as being the majority of cases -- to the contrary.

    > I'm sure you must have some use case in mind where a thread local is
    > useful, but I'm having a hard time seeing it. It feels like you push
    > the context/initialization problem into the threading system, where it's
    > actually going to be harder to manage. In a system that was designed
    > from the ground up to support contexts attached to threads, OK it might
    > work, but in many existing systems it seems difficult to add.


    It is true that it is more fragile, and for that reason alone may be
    legitimately rejected, I'll grant you that. But it is not difficult to
    add; quite the contrary, it is much easier to add to an existing system
    than the one you suggested, because it does not involve any change in
    the API (only to the implementation).

    Now, don't get me wrong, I'm not trying to suggest this is anywhere the
    be-all and end-all of programming techniques. Indeed, because it is
    fragile and less explicit (and hence more difficult to grasp) than the
    other way (passing a context to the actor's method), the latter is my
    preferred and indeed the standard approach I opt for when designing a
    piece of code that involves a dispatch mechanism (which is most of
    them). I merely intended to mention that other possibility for the record.

    --
    DF.
     
    Daniele Futtorovic, Apr 24, 2013
    #12
  13. Stefan Ram

    Lew Guest

    Stefan Ram wrote:
    > Daniel Pitts writes:
    >> Why aren't those simply setters? Must you go against all convention in
    >> every possible way?

    >
    > I just had to remember that remark, when I read a method
    > name of mine that made me smile myself, it was the name
    >
    > acceptReportAcceptor
    >
    > . Here is some more context:
    >
    > public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    > { this.reportAcceptor = reportAcceptor; }
    >
    > . But now, honestly, when one sees a hungry man, and gives
    > him some bread and says:
    >
    > »Sir, please accept this bread!«
    >
    > this sound fine to me, while
    >
    > »Sir, please set this bread!«
    >
    > sounds strange. In
    >
    > object.acceptNumber( 2 )
    >
    > I tell the object to accept the number, but what is
    >
    > object.setNumber( 2 )
    >
    > supposed to mean? How can the object set the number 2?
    > This makes no sense!


    It makes perfect sense, assuming you don't reject the convention.

    > But I am not a native English speaker. May be I am missing
    > something here.


    This really doesn't have anything to do with native English, or really
    English at all except as a basis for technical terminology.

    What you are missing, deliberately at a guess, is the convention set
    recommended for all serious Java programmers.

    Every profession has its argot. The meaning of 'setXyz()' and 'getXyz()' in
    Java is a matter of domain-specific terminology.

    Your analysis is utterly correct modeling methods as actions, or messages,
    depending on the methodology by which you describe programs. In a word,
    behaviors. So yes, in that sense you tell the object to accept an argument.

    In UML you model behaviors, or methods, below the line below attributes.

    In Java, unlike C# and some other languages, there is not a direct
    implementation of attributes, modeled differently from behavioral methods.
    One could use elevated-visibility member variables, 'public Xyz xyz;', but
    this practice is decried. Instead, by nearly universal convention in Java, one
    uses specific JavaBean-compliant names for methods that wrap these
    members and provide attribute characteristics.

    This convention has been around since the Java equivalent of the Paleolithic Age.
    It was established by Sun's attempt to promote JavaBeans. It's the part that really
    stuck, as it turns out Java really needed a good implementation for attributes.
    What we got are getters (accessor methods) and setters (mutator methods), so
    named for the conventional 'getXyz()' and 'setXyz()' patterns for naming the
    wrapper methods for the 'xyz' attribute.

    .... [snip] ...

    >> Why aren't those simply setters?

    >
    > Actually I do not know the definition of »setter« that you
    > take as basis for your question. When do you call something
    > a setter?


    Aye, therein lies the rub. It is a vocabulary issue.

    A setter is a mutator method taking a single argument corresponding to
    a type attribute, named in the JavaBean pattern of 'setXyz(Xyz xyz)' for
    a hypothetical attribute 'xyz' of type 'Xyz'. It is one of a pair of methods
    used to give Java full power to express a type attribute, the other being
    the 'getXyz()' accessor method.

    There are advantages to following the convention, not least of which is
    the ability to communicate in full bandwidth with knowledgeable Java
    programmers. Many tools (IDEs, rich-application platforms, etc.) take
    advantage of this convention and other JavaBean conventions to provide
    robust, component-based, rapidly-developed functionality.

    It's really not such a bad thing to follow Java conventions. Really it's not.

    --
    Lew
     
    Lew, Apr 24, 2013
    #13
  14. On 24/04/2013 06:34, Stefan Ram allegedly wrote:
    > Daniel Pitts <> writes:
    >> Why aren't those simply setters? Must you go against all convention in
    >> every possible way?

    >
    > I just had to remember that remark, when I read a method
    > name of mine that made me smile myself, it was the name
    >
    > acceptReportAcceptor
    >
    > . Here is some more context:
    >
    > public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    > { this.reportAcceptor = reportAcceptor; }
    >
    > . But now, honestly, when one sees a hungry man, and gives
    > him some bread and says:
    >
    > »Sir, please accept this bread!«
    >
    > this sound fine to me, while
    >
    > »Sir, please set this bread!«
    >
    > sounds strange. In
    >
    > object.acceptNumber( 2 )
    >
    > I tell the object to accept the number, but what is
    >
    > object.setNumber( 2 )
    >
    > supposed to mean? How can the object set the number 2?
    > This makes no sense!
    >
    > But I am not a native English speaker. May be I am missing
    > something here.
    >
    > Imagine I would have called the reportAcceptor
    > »reportSetter«. This would have made no sense to me! This
    > object is supposed to accept a report, not to set a report!
    > The report is already »set« by the caller, the callee is
    > just asked to kindly consider accepting it!
    >
    >> Why aren't those simply setters?

    >
    > Actually I do not know the definition of »setter« that you
    > take as basis for your question. When do you call something
    > a setter?
    >


    You give that bread to the hungry man to be his property; yet bread is
    not a property of a hungry man (except perhaps a boolean one). Or again
    without the wordplay: you give that bread to the hungry man to be his
    possession; yet bread is not a quality of a hungry man. The closest
    equivalent in engineering terms is that you give it to him for
    /processing/, to do something with, to consume. If he's hungry enough,
    he'll eat it; if he's gluten sensitive, he won't; if he's a Goldman
    Sachs banker, he'll short the bread and long the Yen. In either case,
    "bread" is not a quality of any man, hungry or not. Hungriness, however,
    is. And while on an object whose purpose would be to re-form the
    Austro-Hungarian empire, you might define a method call "acceptHungary",
    you wouldn't call a method "acceptHungry" if you wanted to determine
    whether not that object was hungry or not, would you? Or, to put it
    differently, imagine you had your own Goldman-Sachs banker to play with,
    and could resist the urge to arrange his timely and painful demise (it's
    a stretch, but bear with me). There might be numerous qualities of his
    you might want to alter: his hairdo, his clothing, his level of naked
    short selling... In each case, you'd use a setter: "setHairdo",
    "setClothing", "setLevelOfNakedShortSelling". It would be totally
    pointless to say, for instance, "acceptLevelOfShortSelling". Why, he'd
    probably double down on whatever you specify on his own anyway!

    HTH,

    --
    DF.
     
    Daniele Futtorovic, Apr 24, 2013
    #14
  15. On 04/24/2013 01:34 AM, Stefan Ram wrote:
    > Daniel Pitts <> writes:
    >> Why aren't those simply setters? Must you go against all convention in
    >> every possible way?

    >
    > I just had to remember that remark, when I read a method
    > name of mine that made me smile myself, it was the name
    >
    > acceptReportAcceptor
    >
    > . Here is some more context:
    >
    > public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    > { this.reportAcceptor = reportAcceptor; }
    >
    > . But now, honestly, when one sees a hungry man, and gives
    > him some bread and says:
    >
    > »Sir, please accept this bread!«
    >
    > this sound fine to me, while
    >
    > »Sir, please set this bread!«
    >
    > sounds strange. In
    >
    > object.acceptNumber( 2 )
    >
    > I tell the object to accept the number, but what is
    >
    > object.setNumber( 2 )
    >
    > supposed to mean? How can the object set the number 2?
    > This makes no sense!
    >
    > But I am not a native English speaker. May be I am missing
    > something here.
    >
    > Imagine I would have called the reportAcceptor
    > »reportSetter«. This would have made no sense to me! This
    > object is supposed to accept a report, not to set a report!
    > The report is already »set« by the caller, the callee is
    > just asked to kindly consider accepting it!
    >
    >> Why aren't those simply setters?

    >
    > Actually I do not know the definition of »setter« that you
    > take as basis for your question. When do you call something
    > a setter?
    >

    Others have provided good responses. Here's my take.

    You certainly know the getX/setX convention, and you also certainly know
    that this convention is sometimes required by frameworks. So I won't
    belabour that point.

    You're already making one valuable point, which is that if getX and setX
    don't sound quite right, that maybe the X is not really a "property" of
    the object being modelled by the Java class.

    From a natural language standpoint, perhaps it would help to translate
    getX and setX to "get value of (my) X" and "set value of (my) X",
    because that's really what the accessor naming shorthand means. If
    phrased this way you'll see that there is a reasonable interpretation of
    what the callee is doing, not the caller. Although the getter sounds
    even better in natural English as "get and provide value of (my) X".

    If after this mental translation the natural language meaning of the
    getter/setter is still not sensible, then maybe you really don't have an
    object property.

    That's really the OO definition of accessor methods: the operations for
    retrieving or modifying the value of the property of an object. The
    naming conventions do interfere somewhat with the options we've then got
    available for methods that describe behaviour, but they had to call them
    something.

    AHS
     
    Arved Sandstrom, Apr 24, 2013
    #15
  16. On 04/22/2013 02:59 PM, markspace wrote:
    > On 4/22/2013 12:03 AM, Daniele Futtorovic wrote:
    >>
    >> In code terms, instead of:
    >> class Actor {
    >> void act( Context c ){ doSomethingWith( c.getXXX() ); }
    >> }

    >
    > Just to be clear, I was advocating using constructors, not method
    > parameters:
    >
    > public class Actor {
    > private Context c;
    > public Actor( Context c ) {this.c = c}
    > public void act() { doSomethingWith( c.getXXX() ); }
    > }
    >
    > This is really really different:
    >
    >> You'd have:
    >> class Actor {
    >> void act(){
    >> doSomethingWith( ContextHelper.getThreadLocalContext().getXXX() );
    >> }
    >> }

    >
    > Now actor does something different depending on what thread is invoking
    > a method. My class was invariant with respect to the thread invoking its
    > method. No matter who calls "act()" the result will always be the same.
    >
    > Since modern systems often use thread pools and the worker threads are
    > supposed to be generic and often randomly assigned, I can't see too many
    > cases where your thread local context is going to be useful. Worse, if
    > an generic worker thread has a context and then is assigned to another
    > task... the results could be random and unpredictable, and really hard
    > to debug as well.
    >
    > I'm sure you must have some use case in mind where a thread local is
    > useful, but I'm having a hard time seeing it. It feels like you push
    > the context/initialization problem into the threading system, where it's
    > actually going to be harder to manage. In a system that was designed
    > from the ground up to support contexts attached to threads, OK it might
    > work, but in many existing systems it seems difficult to add.
    >

    I can think of one right now, one that is in production in a fairly
    major J2EE/JEE system I am familiar with.

    The idea was/is to implement a persistent conversation, and this
    implementation goes back about 7 years, in the context of JSF 1.x and
    JPA. Basically an application-managed entity manager needs to kept
    around, one for each application user, from a defined EM-creation
    checkpoint to a defined EM-commit/rollback checkpoint. This is needed
    because money is involved and the real-world scenario demands it. It is
    not possible to commit per-request, for much of the business state.

    Between HTTP requests it's reasonable to keep a user's EM in their HTTP
    session. *During* requests the specific conversational EM assigned to
    that user must be made available wherever it's required in code - a very
    convenient way of doing that is to place the user EM into a ThreadLocal
    in the 1st JSF phase, in a helper class, and provide a getter to allow
    the user's HTTP request thread to retrieve that "special" EM as needed
    in any method.

    I think you'll realize that something like an ApplicationScoped JSF
    managed bean would not work here. It's technically possible for B.L. or
    datalayer code to access a JSF managed bean, if you assume that that top
    layer is there, but it's an unpleasant picture. Much better to have the
    user EM's kept in a ThreadLocal in a data layer helper class, since that
    makes architectural sense.

    I might add, this described implementation is pre-Servlet 3 and no async
    processing is involved.

    AHS
     
    Arved Sandstrom, Apr 24, 2013
    #16
  17. Stefan Ram

    Daniel Pitts Guest

    On 4/23/13 9:34 PM, Stefan Ram wrote:
    > Daniel Pitts <> writes:
    >> Why aren't those simply setters? Must you go against all convention in
    >> every possible way?

    >
    > I just had to remember that remark, when I read a method
    > name of mine that made me smile myself, it was the name
    >
    > acceptReportAcceptor
    >
    > . Here is some more context:
    >
    > public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    > { this.reportAcceptor = reportAcceptor; }
    >
    > . But now, honestly, when one sees a hungry man, and gives
    > him some bread and says:
    >
    > »Sir, please accept this bread!«
    >
    > this sound fine to me, while
    >
    > »Sir, please set this bread!«
    >
    > sounds strange. In
    >
    > object.acceptNumber( 2 )
    >
    > I tell the object to accept the number, but what is
    >
    > object.setNumber( 2 )

    The word "accept" has a different connotation in programming. It is
    often used for the visitor pattern. The "get" and "set" words are
    referring to "the value of a property."

    >
    > supposed to mean? How can the object set the number 2?
    > This makes no sense!

    Translating "setNumber" becomes "Set your property called 'number' to
    the value '2'"
    >
    > But I am not a native English speaker. May be I am missing
    > something here.

    Besides the fact that "set" and "get" are convention, they are actually
    an integral part of the JavaBean concept, which is far more than just a
    convention. Introspector expects get, is, and set prefixes on property
    names.
    >
    > Imagine I would have called the reportAcceptor
    > »reportSetter«. This would have made no sense to me! This
    > object is supposed to accept a report, not to set a report!
    > The report is already »set« by the caller, the callee is
    > just asked to kindly consider accepting it!
    >
    >> Why aren't those simply setters?

    >
    > Actually I do not know the definition of »setter« that you
    > take as basis for your question. When do you call something
    > a setter?

    A setter is a method which sets the value of a property. A setter method
    starts with the literal "set", and ends with the capitalized camel-case
    name of the property. The property *may* be backed by a field, but that
    isn't a requirement.


    Usually "accept" is an object that can be visited (in the Visitor
    Pattern). Generally, classes which can be visited will implement an
    abstract "void accept(Visitor visitor)" method, and visitor will
    implement an interface with many "visit(???)" methods. One for each
    static type of visitable. The accept/visit is needed in languages which
    only have single-dispatch polymorphism.

    The point is, your use of the word "accept" may cause less confusion to
    an English major, but will cause more confusion to the average computer
    programmer. You are writing in Java, not in English.

    Thanks,
    Daniel.
     
    Daniel Pitts, Apr 24, 2013
    #17
  18. Stefan Ram

    Stefan Ram Guest

    Daniel Pitts <> writes:
    >A setter is a method which sets the value of a property. A setter method
    >starts with the literal "set", and ends with the capitalized camel-case
    >name of the property. The property *may* be backed by a field, but that
    >isn't a requirement.


    Thanks for your helpful answer! I might still continue to
    use »accept« sometimes, but I see your point.

    >The point is, your use of the word "accept" may cause less confusion to
    >an English major, but will cause more confusion to the average computer
    >programmer. You are writing in Java, not in English.


    You have triggered a boilerplate quotation of mine
    (not intended to contradict your paragraph!):

    »I've found that some of the best [Software ]developers
    of all are English majors. They'll often graduate with
    no programming experience at all, and certainly without
    a clue about the difference between DRAM and EPROM.

    But they can write. That's the art of conveying
    information concisely and clearly. Software development
    and writing are both the art of knowing what you're going
    to do, and then lucidly expressing your ideas.«

    http://praisecurseandrecurse.blogspot.com/2007/03/english-majors-as-programmers.html
     
    Stefan Ram, Apr 24, 2013
    #18
  19. On 04/24/2013 12:47 PM, Stefan Ram wrote:
    > Daniel Pitts <> writes:
    >> A setter is a method which sets the value of a property. A setter method
    >> starts with the literal "set", and ends with the capitalized camel-case
    >> name of the property. The property *may* be backed by a field, but that
    >> isn't a requirement.

    >
    > Thanks for your helpful answer! I might still continue to
    > use »accept« sometimes, but I see your point.
    >
    >> The point is, your use of the word "accept" may cause less confusion to
    >> an English major, but will cause more confusion to the average computer
    >> programmer. You are writing in Java, not in English.

    >
    > You have triggered a boilerplate quotation of mine
    > (not intended to contradict your paragraph!):
    >
    > »I've found that some of the best [Software ]developers
    > of all are English majors. They'll often graduate with
    > no programming experience at all, and certainly without
    > a clue about the difference between DRAM and EPROM.
    >
    > But they can write. That's the art of conveying
    > information concisely and clearly. Software development
    > and writing are both the art of knowing what you're going
    > to do, and then lucidly expressing your ideas.«
    >
    > http://praisecurseandrecurse.blogspot.com/2007/03/english-majors-as-programmers.html
    >

    That's been my experience too, English and history majors notably.
    PoliSci also not bad, basically anyone who has been called upon to do
    research, express themselves well and clearly.

    Strikes me that the people who design languages - albeit smart - don't
    always have that background. And I wish they didn't artificially choose
    keywords or syntax just to be different from another language...which
    they damned well do.

    AHS
     
    Arved Sandstrom, Apr 24, 2013
    #19
  20. Stefan Ram

    Joerg Meier Guest

    On 24 Apr 2013 04:34:21 GMT, Stefan Ram wrote:

    > I just had to remember that remark, when I read a method
    > name of mine that made me smile myself, it was the name


    > acceptReportAcceptor


    > . Here is some more context:


    > public void acceptReportAcceptor( final ReportAcceptor reportAcceptor )
    > { this.reportAcceptor = reportAcceptor; }


    > . But now, honestly, when one sees a hungry man, and gives
    > him some bread and says:


    > »Sir, please accept this bread!«


    > this sound fine to me, while


    > »Sir, please set this bread!«


    > sounds strange. In


    To add to all the excellent replies: a better example would be changing
    channels on your TV - you don't use your remote to ask your TV to "accept"
    channel 1, you tell it to "set" the channel to 1. Various other words with
    basically the same meaning would work as well - switchChannel(Channel c),
    changeChannel, but as said, they mean the same as "set", and "set" is the
    one the general public has settled on (likely due to its similarity to its
    logical counterpart: "get").

    Liebe Gruesse,
    Joerg

    --
    Ich lese meine Emails nicht, replies to Email bleiben also leider
    ungelesen.
     
    Joerg Meier, Apr 24, 2013
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Oisin Grehan
    Replies:
    3
    Views:
    494
    Natty Gur
    Jul 15, 2003
  2. =?Utf-8?B?RWxkb24gRmVycmFuIGRlIFBvbA==?=

    Wiring up events nightmare

    =?Utf-8?B?RWxkb24gRmVycmFuIGRlIFBvbA==?=, Dec 17, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    318
    Rajagopal Pasupuleti
    Dec 17, 2004
  3. =?Utf-8?B?RWxkb24gRmVycmFuIGRlIFBvbA==?=

    Wiring Up Events Nightmare

    =?Utf-8?B?RWxkb24gRmVycmFuIGRlIFBvbA==?=, Dec 17, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    417
    John Saunders
    Dec 17, 2004
  4. =?Utf-8?B?SG9tYW0=?=

    Dynamic controls and event wiring

    =?Utf-8?B?SG9tYW0=?=, Feb 16, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    372
    =?Utf-8?B?SG9tYW0=?=
    Feb 16, 2005
  5. Jordan
    Replies:
    4
    Views:
    628
    Bruce Barker
    Sep 1, 2005
Loading...

Share This Page