使用流畅的接口重构长方法

eja*_*env 4 java refactoring fluent-interface fluent

我想知道您对使用流畅的界面模式重构一个长方法的看法.

http://en.wikipedia.org/wiki/Fluent_interface

流畅的模式不包括在重构书中.

例如,假设您有这么长的方法(因为它有很多东西,所以有很长的名字)

class TravelClub {

   Receipt buyAndAddPointsAndGetReceipt(long amount, long cardNumber) {
    buy(amount);
    accumulatePoints(cardNumber);
    return generateReceipt();

   }

   void buy(int amount) {...}

   void accumlatePoints(int cardNumber) {...}

   void generateRecepit() {...}

}
Run Code Online (Sandbox Code Playgroud)

称为:

Receipt myReceipt = myTravelClub.buyAndAddPointsAndGetReceipt(543L,12345678L);
Run Code Online (Sandbox Code Playgroud)

这可以重构为:

class TravelClub {

   TravelClub buy(long amount) {
    //buy stuff
    return this;
   }

   TravelClub accumulatePoints(long cardNumber) {
    //accumulate stuff
    return this;
   }

   Receipt generateReceipt() {
    return new Receipt(...);
   }


}
Run Code Online (Sandbox Code Playgroud)

并称为:

Receipt myReceipt = myTravelClub.buy(543L).accumulatePoints(12345678L).generateReceipt();
Run Code Online (Sandbox Code Playgroud)

从我的观点来看,分解long方法并分解其名称是一种非常好的方式.

你怎么看?

gus*_*afc 5

它有一个问题,你必须记住积累点和执行购买(并生成收据,这不是一个问题,因为我认为行动没有副作用).在我看来,点积累应该在执行购买时自动进行.在执行购买时收到收据也很自然,所以在某种程度上,您的初始方法很好,除了它读得不太好.

如果你想要一个流畅的界面,我会引入一个额外的类,轻轻地指导客户端代码做正确的事情(假设所有购买都发生在一张卡片上并以相同的方式积累点数):

class TravelClub {

   OngoingPurchase buyAmount(long amount) {
      return new OngoingPurchase(amount);
   }

   private Receipt buyAndAddPointsAndGetReceipt(long amount, long cardNumber){
      // make stuff happen
   }

   public class OngoingPurchase {
      private final long amount;
      private OngoingPurchase(long amount){
         this.amount = amount;
      }
      public Receipt withCard(long cardNumber){
         return buyAndAddPointsAndGetReceipt(long amount, cardNumber);
      }
   }

}

// Usage:
Receipt receipt = travelClub.buyAmount(543).withCard(1234567890L);
Run Code Online (Sandbox Code Playgroud)

这样,如果你忘了打电话withCard,没有任何反应.发现丢失的交易比不正确的交易更容易,并且如果不执行完整的交易,您将无法获得收据.

编辑:顺便说一句,认为我们完成所有这些工作以使具有许多参数的方法可读时很有趣,例如命名参数会使问题完全消失:

Receipt r = travelClub.makePurchase(forAmount: 123, withCardNumber: 1234567890L);
Run Code Online (Sandbox Code Playgroud)