Benefits and drawbacks of method chaining and a possibility to replace all void return parameters by the object itself

前端 未结 9 1685
隐瞒了意图╮
隐瞒了意图╮ 2020-11-29 06:58

I am mostly interested in Java, but I think it\'s a general question. Recently I\'ve been working with Arquillian framework (ShrinkWrap) that uses a lot of meth

相关标签:
9条回答
  • 2020-11-29 07:24

    Personally I think that it is a very useful pattern, but it should not be used everywhere. Consider the situation where you have a copyTo(T other) method. Normally you would expect it to not return anything, but if it were to return an object of the same type, which object would you expect? This sort of issue can be cleared up with documentation, but it is still ambiguous on the method signiature.

    public class MyObject {
    
        // ... my data
    
        public MyObject copyTo(MyObject other) {
    
            //... copy data
    
    
            // what should I return?
            return this;
        }
    }
    
    0 讨论(0)
  • 2020-11-29 07:25

    Drawbacks

    • Principally it confuses the signature, if something returns a new instance I don’t expect it to also be a mutator method. For example if a vector has a scale method then if it has a return I would presume it returns a new vector scaled by the input, if it doesn't then I would expect it to scale internally.
    • Plus of course you get problems if the class is extended, where partway through your chaining your object gets cast to a supertype. This occurs when a chaining method is declared in the parent class, but used on an instance of the child class.

    Benefits

    • It allows mathematical equation style code to be written as full equations without the need for multiple intermediate objects (leading to unnecessary overhead), for example without method chaining the vector triple cross product (as a random example) would have to be written either as

      MyVector3d tripleCrossProduct=(vector1.multiply(vector2)).multiply(vector3);
      

      which has the disadvantage of creating an intermediate object which must be created and garbage collected, or

      MyVector3d tripleCrossProduct=vector1;
      tripleCrossProduct.multiplyLocal(vec2);
      tripleCrossProduct.multiplyLocal(vec3);
      

      which avoids the creation of intermediate objects but is deeply unclear, the variable name tripleCrossProduct is in fact a lie until line 3. However, if you have method chaining this can be written concisely in a normal mathematical way without creating unnecessary intermediate objects.

      MyVector3d tripleCrossProduct=vector1.multiplyLocal(vector2).multiplyLocal(vector3);
      

      All of this assumes that vector1 is sacrificial and will never need to be used again

    • And of course the obvious benefit; brevity. Even if your operations aren't linked in the manor of my above example you can still avoid unnecessary references to the object

      SomeObject someObject=new SomeObject();
      someObject
        .someOperation()
        .someOtherOperation();
      

    NB MyVector3d is not being used as a real class of Java, but is assumed to perform the cross product when .multiply() methods are called. .cross() is not used so that the 'intention' is clearer to those not familiar with vector calculus
    NB Amit's solution was the first answer to use multiline method chaining, I include it as part of the forth bullet point for completeness

    0 讨论(0)
  • 2020-11-29 07:30

    This pattern is useful when there is series of update needs to be done on the same object and the update operations don't need to return any status of updation. For example I used this pattern in some api I wrote for database layer. For fetching some rows based on many criteria many conditions needs to be added to where clause. Using this pattern the criteria can be added as follows.

    CriteriaCollection().instance()
        .addSelect(Criteria.equalTo(XyzCriteria.COLUMN_1, value1))
        .addSelect(Criteria.equalTo(XyzCriteria.COLUMN_2, value2))
        .addSelect(Criteria.isIn(XyzCriteria.COLUMN_3, values3))
        .addOrder(OrderCriteria.desc(XyzCriteria.Order.COLUMN_1));
    

    Ultimately it improves the readability of the code.

    0 讨论(0)
提交回复
热议问题