1 2 Previous Next 17 Replies Latest reply: Mar 15, 2011 7:49 PM by YoungWinston RSS

    Classic accessors vs chained setters

    baftos
      I am in the process of designing an API. My first thought is to use conventional, JavaBeans-like setters and getters.
      But there are some classes in the Java API that take a different approach. ProcessBuilder comes to my mind.
      Look at this:
      File directory() 
                Returns this process builder's working directory. 
      ProcessBuilder directory(File directory) 
                Sets this process builder's working directory. 
      
      boolean redirectErrorStream() 
                Tells whether this process builder merges standard error and standard output. 
      ProcessBuilder redirectErrorStream(boolean redirectErrorStream) 
                Sets this process builder's redirectErrorStream property. 
      Those are essentially setters and getters with a twist: the setters return the object on which they are called and the naming convention is different.
      The only advantage I can see for this approach is that we can write code such as:
      ProcessBuilder pb = new ProcessBuilder(...).redirectErrorStream(true).directory(...);
      which is syntactic sugar, I think.
      We can also write code such as:
      pb.redirectErrorStream(); // It does not do what the name implies, it does nothing!
      The last mistake is the result of losing the absolute certainty that the old naming convention provided: getters get and setters set.
      Not to mention that this smells like an abuse of overloading.
      I can see a compromise: use the old naming convention, but return the object from setters.
      What I dislike about this is that I am trying to be 'clever' and how comes others did not think about it. Maybe they had good reasons.

      My question: is the ProcessBuilder approach some kind of a pattern? Where can I read about it, when to use it and when not?
      Any thoughts appreciated.

      Edited by: baftos on Mar 12, 2011 10:25 AM
        • 1. Re: Classic accessors vs chained setters
          jduprez
          My question: is the ProcessBuilder approach some kind of a pattern?
          Yes, that is known under the name of method chaining (EDIT or read the following to know better, sorry)
          See e.g. http://firstclassthoughts.co.uk/java/method_chaining.html (not a very impressive reference, but this style is used in some other APIs (Joda-time comes to mind).

          EDIT: adding Wikipedia link: http://en.wikipedia.org/wiki/Method_chaining
          Indeed browsing the Wikipedia article led to a better description of your tempting design, known under the term Fluent Interface, a term coined partly by Martin Fowler, who is a great source of inspiration in OOD, and a frequent promoter of accurate and expressive naming: http://en.wikipedia.org/wiki/Fluent_interface
          • 2. Re: Classic accessors vs chained setters
            jduprez
            Although I find this style elegant in general, I do agree with you that the porr naming and "abuse of overloading" in ProcessBuilder's usage are awkward and error-prone.
            which is syntactic sugar, I think.
            Maybe. What I like in this style is that it helps writing code that reads closer to plain english (EDIT Fowler's more reasonably refers to Domain-Specific Language - a pet subject of his).

            See for example Joda-time's API (citing from memory, but bear with me):
            /**
             * Ship the following tuesday, 1 hour later than the order's time
             */
            public Date computeDeliveryDate(Date orderDate) {
                return new DateTime(orderDate).plusWeek(1).withDay(TUESDAY).toDate();
            }
            I realize though, that Joda-time, although encouraging a case of method chaining , is not strictly a FluentInterface : the chained methods indeed operate on different instances (the DateTime instances are immutable, and the "mutator" methods indeed return a different instance each time (so not what you described in your OP).
            when to use it and when not?
            Based on this latest remark, one beneficial side-effect could be that the client code could be used unchanged if at some point you turn your mutable object into an immutable one. But I wouldn't count on it, because that's impossible to guarantee, and probably hard to verify, whether all client code consistently leveraged the "fluent" style.

            See Martin Fowler's Fluent Interface article for a discussionof pros and cons: http://martinfowler.com/bliki/FluentInterface.html
            • 3. Re: Classic accessors vs chained setters
              YoungWinston
              baftos wrote:
              My question: is the ProcessBuilder approach some kind of a pattern? Where can I read about it, when to use it and when not?
              I believe it's based on the [url http://en.wikipedia.org/wiki/Builder_pattern]Builder pattern, which first came to my attention in "Effective Java" v2. The example on the Wiki page doesn't use chained setters, but Josh Bloch's does.

              For a builder class, I can definitely see the advantages; but I'm not so sure about regular setters. I'd be a little worried that it's inviting clients to write horrendous chains of calls. But then again, I'm not too wild about setters in general.

              Winston
              • 4. Re: Classic accessors vs chained setters
                baftos
                Thanks guys! Martin Fowler's sentence "Coming up with a nice fluent API requires a good bit of thought." convinced me to stay with classic accessors:)
                • 5. Re: Classic accessors vs chained setters
                  YoungWinston
                  baftos wrote:
                  Thanks guys! Martin Fowler's sentence "Coming up with a nice fluent API requires a good bit of thought." convinced me to stay with classic accessors:)
                  Just FYI, The Wiki page does contain a link to the [url http://drdobbs.com/java/208403883?pgno=2]relevant section of EJv2. Personally, I rather like them for the scenario Joshua Bloch suggests.

                  Winston
                  • 6. Re: Classic accessors vs chained setters
                    baftos
                    Thanks for the link. I read this some time ago. I was aware of the builder pattern, but I did not remember at all that he talks about chained setters in this context.
                    After re-reading, my understanding is that the builder pattern is there to fix the 'telescopic constructors' problem. It can be used with or without chained setters.
                    And chained setters may be used outside the builder pattern. Anyway, I don't have telescopic constructors and I don't have lots of properties.
                    I decided to stay away from chained setters because:

                    Maybe I would use them internally (they are fun), but mine being a published API, I don't want to give up on the ability of IDE's to identify my properties and allow some 'visual' programmimg.
                    I am not a fan of visual programming, but this is an API for others to use the way they like.

                    But you or someone else may still convince me:)
                    • 7. Re: Classic accessors vs chained setters
                      jschellSomeoneStoleMyAlias
                      YoungWinston wrote:
                      baftos wrote:
                      Thanks guys! Martin Fowler's sentence "Coming up with a nice fluent API requires a good bit of thought." convinced me to stay with classic accessors:)
                      Just FYI, The Wiki page does contain a link to the [url http://drdobbs.com/java/208403883?pgno=2]relevant section of EJv2. Personally, I rather like them for the scenario Joshua Bloch suggests.
                      Useless fluff.

                      If you have a lot of constructors that take a lot of parameters then there is something wrong with your design.

                      Conversely if you have 1 or 2 out of 10,000 and you use this odd pattern than a maintainer is going to need to puzzle out exactly what is going on the first time they see this.

                      And the alternative (which this idiom is supposed to improve on) is no worse for the fact that one is dealing with an odd object in the first place - specifically because it requires a large number of values to construct.

                      Further as to the point of immutable and leaving construction in an indeterminate state - exactly how many objects out of the 10,000 is that a real concern? Again if a lot of objects are like that then there is something seriously wrong with the design and very likely the architecture of the application.
                      • 8. Re: Classic accessors vs chained setters
                        YoungWinston
                        jschell wrote:
                        Conversely if you have 1 or 2 out of 10,000 and you use this odd pattern than a maintainer is going to need to puzzle out exactly what is going on the first time they see this.
                        You're the one who loves to ask for supporting evidence. What brought you to the figure 2 out of 10,000?
                        And the alternative (which this idiom is supposed to improve on) is no worse for the fact that one is dealing with an odd object in the first place - specifically because it requires a large number of values to construct.
                        Says who? Maybe others who have worked in different fields find this sort of thing commonplace. Bloch clearly thought it was worthy of mention, and I haven't seen any evidence to suggest that he's someone to waste words. I also suspect you haven't read the whole piece, because he also suggests other scenarios in which a Builder might be useful.
                        Further as to the point of immutable and leaving construction in an indeterminate state - exactly how many objects out of the 10,000 is that a real concern?
                        There we go, throwing statistics around again.
                        Again if a lot of objects are like that then there is something seriously wrong with the design and very likely the architecture of the application.
                        Rubbish. I've been a programmer and data modeller for a long time, and if there's one thing I know it's that some entities have lots of attributes and others don't. Rules of normalization are a far better guide as to how good the design is than some arbitrary dictum of yours.

                        Winston
                        • 9. Re: Classic accessors vs chained setters
                          jschellSomeoneStoleMyAlias
                          YoungWinston wrote:
                          jschell wrote:
                          Conversely if you have 1 or 2 out of 10,000 and you use this odd pattern than a maintainer is going to need to puzzle out exactly what is going on the first time they see this.
                          You're the one who loves to ask for supporting evidence. What brought you to the figure 2 out of 10,000?
                          Because I have written a lot of classes.

                          And per the given link it provided a specific set of circumstances that were required to make this useful.

                          Only average what percentage of classes that you write require, for example, 10 or more parameters to the constructor?
                          And the alternative (which this idiom is supposed to improve on) is no worse for the fact that one is dealing with an odd object in the first place - specifically because it requires a large number of values to construct.
                          Says who? Maybe others who have worked in different fields find this sort of thing commonplace. Bloch clearly thought it was worthy of mention, and I haven't seen any evidence to suggest that he's someone to waste words. I also suspect you haven't read the whole piece, because he also suggests other scenarios in which a Builder might be useful.
                          I have worked in medical, telephony and financial fields. I certainly never saw a need for that.

                          Also read a lot one what people consider 'good' OO. I certainly can't recall anyone claiming that that was needed. Pretty sure that I have seen more than a few writers that either explicitly or implicitly claimed doing that is wrong.
                          Further as to the point of immutable and leaving construction in an indeterminate state - exactly how many objects out of the 10,000 is that a real concern?
                          There we go, throwing statistics around again.
                          And again - provide what you think your average is for constructors that take more than 10 parameters.
                          Again if a lot of objects are like that then there is something seriously wrong with the design and very likely the architecture of the application.
                          Rubbish. I've been a programmer and data modeller for a long time, and if there's one thing I know it's that some entities have lots of attributes and others don't. Rules of normalization are a far better guide as to how good the design is than some arbitrary dictum of yours.
                          That however has nothing to do with what I said.

                          I didn't say it was zero. I said it was small.

                          And thus to use a different idiom for the very small number of cases versus the much larger set (but still waiting on what you think your stats are) makes no sense.
                          • 10. Re: Classic accessors vs chained setters
                            YoungWinston
                            jschell wrote:
                            Only average what percentage of classes that you write require, for example, 10 or more parameters to the constructor?
                            I've got no idea (and I've no idea where you plucked the number 10 from either), but I've found three good uses for the idiom since I first read about it 18 months ago. Furthermore, far from what you claim, it's very clear and easy to document. I just wish JB had put it in version 1, so I'd known about it earlier.
                            And thus to use a different idiom for the very small number of cases versus the much larger set (but still waiting on what you think your stats are) makes no sense.
                            I don't believe it. You're the one making the claim for 2 in 10,000, but it's me that has to come up with the stats?

                            I don't think there's much to be gained from continuing this. I'll carry on enjoying using the pattern; you keep doing whatever it is you do instead.

                            Winston
                            • 11. Re: Classic accessors vs chained setters
                              baftos
                              Whenever you think you know it all, something comes up and you marvel at the complexity of our profession:
                              GridBagConstraints(int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty, int anchor, int fill, Insets insets, int ipadx, int ipady) 
                                        Creates a GridBagConstraints object with all of its fields set to the passed-in arguments.
                              Eleven (or maybe fourteen, depending how you look at insets)!
                              • 12. Re: Classic accessors vs chained setters
                                YoungWinston
                                baftos wrote:
                                Whenever you think you know it all, something comes up and you marvel at the complexity of our profession:
                                GridBagConstraints(int gridx, int gridy, int gridwidth, int gridheight, ...
                                Eleven (or maybe fourteen, depending how you look at insets)!
                                Oh God yes. I remember mucking about with that for days, trying to learn how to get shapes to expand and contract the way I wanted them to when you resize the whole frame. I'm sooo glad I don't have to muck about with GUI stuff too much; I'd probably have to start from scratch again :-).
                                Plus, I'm a complete duffer at it.

                                Winston
                                • 13. Re: Classic accessors vs chained setters
                                  gimbal2
                                  YoungWinston wrote:
                                  baftos wrote:
                                  Whenever you think you know it all, something comes up and you marvel at the complexity of our profession:
                                  GridBagConstraints(int gridx, int gridy, int gridwidth, int gridheight, ...
                                  Eleven (or maybe fourteen, depending how you look at insets)!
                                  Oh God yes. I remember mucking about with that for days, trying to learn how to get shapes to expand and contract the way I wanted them to when you resize the whole frame. I'm sooo glad I don't have to muck about with GUI stuff too much; I'd probably have to start from scratch again :-).
                                  Plus, I'm a complete duffer at it.

                                  Winston
                                  Its easy: forget GridbagLayout exists and be happy.
                                  • 14. Re: Classic accessors vs chained setters
                                    jschellSomeoneStoleMyAlias
                                    YoungWinston wrote:
                                    jschell wrote:
                                    Only average what percentage of classes that you write require, for example, 10 or more parameters to the constructor?
                                    I've got no idea (and I've no idea where you plucked the number 10 from either), but I've found three good uses for the idiom since I first read about it 18 months ago. Furthermore, far from what you claim, it's very clear and easy to document. I just wish JB had put it in version 1, so I'd known about it earlier.
                                    You are the one that claims it is "clear and easy to document", so want to provide proof for that?

                                    Myself I know that I found a number of "good" uses for operator overloading in C++ a number of years ago. I documented them as well. Didn't realize how problematic it was in terms of maintenance until quite a long time after that when I had to look at others code. Hopefully those that follow you will have a different experience with your code.
                                    And thus to use a different idiom for the very small number of cases versus the much larger set (but still waiting on what you think your stats are) makes no sense.
                                    I don't believe it. You're the one making the claim for 2 in 10,000, but it's me that has to come up with the stats?
                                    Again...
                                    1. My code has always had few cases like that. I have and do code in C++, C# and Java. And in different industries.
                                    2. I have read numerous other sources that would suggest that they too do not have a large number of cases. And in fact specifically suggest that such cases are badly designed (and numerous posts on this site have suggested large number of parameters are problematic in a single class.)

                                    And far as I can tell you are not claiming that you actually have a large number like that but rather that someone might.
                                    Certainly if you only have "three" cases then either you write far fewer classes than I do or you do in fact have very few cases that do that.
                                    1 2 Previous Next