nacho111
nacho111

Reputation: 87

Refactor similar code used by multiple methods

I have a situation like this: there are two methods (that i can't change, because they come from an abstract class) from() and to() that must execute the same code with only a small difference. I created a third method and i used a boolean variable to know which of the two methods called the third. Now, is there a way write this in a cleaner way?

protected from(x: any): any[] {
  return this.convertArray(true, x);
}

protected to(y: any): any[] {
  return this.convertArray(false, y);
}

private convertArray(isFrom: boolean, inArray: any[]): any[] {
  const array = [];
  if (this.types.length === 1) {
      // ... some code here ...
      array.push(isFrom ? adapter.from(value) : adapter.to(value));
  } else {
      // ... some code here ...
      array.push(isFrom ? adapter.from(inArray[i]) : adapter.to(inArray[i]));
  }
  return array;
}

Upvotes: 2

Views: 687

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075745

You have a few other options:

  1. You can use a string for the method name and brackets notation to get the method from adapter:

    private convertArray(isFrom: boolean, inArray: any[]): any[] {
      const array = [];
      const method = isFrom ? "from" : "to";          // ***
      if (this.types.length === 1) {
          // ... some code here ...
          array.push(adapter[method](value));         // ***
      } else {
          // ... some code here ...
          array.push(adapter[method](inArray[i]));    // ***
      }
      return array;
    }
    
  2. You can use a wrapper function created via bind (so that this within the call is adapter):

    private convertArray(isFrom: boolean, inArray: any[]): any[] {
      const array = [];
      const method = (isFrom ? adapter.from : adapter.to).bind(adapter); // ***
      if (this.types.length === 1) {
          // ... some code here ...
          array.push(method(value));         // ***
      } else {
          // ... some code here ...
          array.push(method(inArray[i]));    // ***
      }
      return array;
    }
    

    or (call it "2(b)") via an arrow function:

    private convertArray(isFrom: boolean, inArray: any[]): any[] {
      const array = [];
      const op = isFrom ? value => adapter.from(value) // ***
                        : value => adapter.to(value);  // ***
      if (this.types.length === 1) {
          // ... some code here ...
          array.push(op(value));                       // ***
      } else {
          // ... some code here ...
          array.push(op(inArray[i]));                  // ***
      }
      return array;
    }
    
  3. Or use the method directly via .call:

    private convertArray(isFrom: boolean, inArray: any[]): any[] {
      const array = [];
      const method = isFrom ? adapter.from : adapter.to; // ***
      if (this.types.length === 1) {
          // ... some code here ...
          array.push(method.call(adapter, value));       // ***
      } else {
          // ... some code here ...
          array.push(method.call(adapter, inArray[i]));  // ***
      }
      return array;
    }
    

Upvotes: 1

Related Questions