Skip to content

Métodos de Codificação

wermesonsl edited this page Aug 25, 2022 · 9 revisions

A maior parte das refatorações são dedicadas à codificação mais apropriada de métodos . Em sua maioria, métodos excessivamente longos são a raiz do problema. Os caprichos nesses métodos mascaram a lógica de execução, tornando-os muito difíceis de entender para, então, aplicar mudanças no código-fonte.


Método de Extração

Problema: você tem um fragmento de código que pode ser agrupado.

printOwing(): void {
  printBanner();

  // Print details.
  console.log("name: " + name);
  console.log("amount: " + getOutstanding());
}

Solução: mova esse código para um novo método (ou função) separado e substitua o código antigo por uma chamada ao método.

printOwing(): void {
  printBanner();
  printDetails(getOutstanding());
}

printDetails(outstanding: number): void {
  console.log("name: " + name);
  console.log("amount: " + outstanding);
}

Método de Internalização

Problema: quando um um corpo de método é mais óbvio que o próprio método, use esta técnica.

class PizzaDelivery {
  // ...
  getRating(): number {
    return moreThanFiveLateDeliveries() ? 2 : 1;
  }
  moreThanFiveLateDeliveries(): boolean {
    return numberOfLateDeliveries > 5;
  }
}

Solução: substitua as chamadas para o método pelo conteúdo do método e exclua o próprio método no processo de refatoração.

class PizzaDelivery {
  // ...
  getRating(): number {
    return numberOfLateDeliveries > 5 ? 2 : 1;
  }
}

Extrair Variável

Problema: você tem uma expressão difícil de entender.

renderBanner(): void {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // do something
  }
}

Solução: coloque o resultado da expressão ou de suas partes em variáveis separadas que são auto-explicativas.

renderBanner(): void {
  const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  const isIE = browser.toUpperCase().indexOf("IE") > -1;
  const wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // do something
  }
}

Variável Temporária em Linha

Problema: você tem uma variável temporária à qual é atribuído o resultado de uma expressão simples e nada mais.

hasDiscount(order: Order): boolean {
  let basePrice: number = order.basePrice();
  return basePrice > 1000;
}

Solução: substitua as referências à variável pela própria expressão na refatoração.

hasDiscount(order: Order): boolean {
  return order.basePrice() > 1000;
}

Substituir Variável Temporária por Consulta

Problema: você coloca o resultado de uma expressão em uma variável local para uso posterior no seu código.

 calculateTotal(): number {
  let basePrice = quantity * itemPri###Dividir Variável Temporária Problema: você tem uma variável local usada para armazenar vários valores intermediários dentro de um método (exceto para variáveis de ciclo).

ce;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  }
  else {
    return basePrice * 0.98;
  }
}

Solução: mova a expressão inteira para um método separado e retorne o resultado. Consulte o método em vez de usar uma variável. Incorpore o novo método em outros métodos, se necessário.

calculateTotal(): number {
  if (basePrice() > 1000) {
    return basePrice() * 0.95;
  }
  else {
    return basePrice() * 0.98;
  }
}
basePrice(): number {
  return quantity * itemPrice;
}

Dividir Variável Temporária

Problema: você tem uma variável local usada para armazenar vários valores intermediários dentro de um método (exceto para variáveis de ciclo).

let temp = 2 * (height + width);
console.log(temp);
temp = height * width;
console.log(temp);

Solução: use variáveis diferentes para valores diferentes. Cada variável deve ser responsável por apenas uma coisa em particular.

const perimeter = 2 * (height + width);
console.log(perimeter);
const area = height * width;
console.log(area);

Remover Atribuições a Parâmetros

Problema: algum valor é atribuído a um parâmetro dentro do corpo do método.

discount(inputVal: number, quantity: number): number {
  if (quantity > 50) {
    inputVal -= 2;
  }
  // ...
}

Solução: use uma variável local em vez de um parâmetro na refatoração.

discount(inputVal: number, quantity: number): number {
  let result = inputVal;
  if (quantity > 50) {
    result -= 2;
  }
  // ...
}

Substituir Método por Objeto de Método

Problema: você tem um método longo no qual variáveis locais estão tão entrelaçadas que não é possível aplicar o Método de Extração.

class Order {
  // ...
  price(): number {
    let primaryBasePrice;
    let secondaryBasePrice;
    let tertiaryBasePrice;
    // Perform long computation.
  }
}

Solução: transforme o método em uma classe separada para que as variáveis locais se tornem campos da classe. Em seguida, você pode dividir o método dentro da mesma classe.

class Order {
  // ...
  price(): number {
    return new PriceCalculator(this).compute();
  }
}

class PriceCalculator {
  private _primaryBasePrice: number;
  private _secondaryBasePrice: number;
  private _tertiaryBasePrice: number;
  
  constructor(order: Order) {
    // Copy relevant information from the
    // order object.
  }
  
  compute(): number {
    // Perform long computation.
  }
}

Algoritmo Substituto

Problema: substituir um algoritmo existente por um novo.

foundPerson(people: string[]): string{
  for (let person of people) {
    if (person.equals("Don")){
      return "Don";
    }
    if (person.equals("John")){
      return "John";
    }
    if (person.equals("Kent")){
      return "Kent";
    }
  }
  return "";
}

Solução: substitua o corpo do método que implementa o algoritmo por um novo algoritmo.

foundPerson(people: string[]): string{
  let candidates = ["Don", "John", "Kent"];
  for (let person of people) {
    if (candidates.includes(person)) {
      return person;
    }
  }
  return "";
}