Executando verificação de segurança...
1

SOLID - SRP (Single Responsability Principle)

Descrição histórica:

  • Um módulo deve ter uma, e apenas uma, razão para mudar.
  • Um módulo deve ser responsável por um, e apenas um, ator.

Problema:
Imagine a classe Employee que calcula o salário do funcionário comum com base nas horas trabalhadas:

class Employee {
  constructor(
    private id: string,
    private hourPayment: number,
    private workedHours: number,
  ) {}

  get payment(): number {
    return this.calculatePayment();
  }

  private calculatePayment() {
    return this.hourPayment * this.workedHours;
  }
}

Agora imagine o caso do funcionário que recebe adicional de insalubridade. Como obrigatoriamente tem o cálculo do adicional, teríamos de modificar a classe existente para que aceitasse o cálculo - mudando assim o foco da classe base - e agora ela atenderia a dois atores diferentes: o funcionário comum e o que recebe o adicional.

Solução:
Manter a estrutura do funcionário comum como uma classe abstrata e criar duas novas classes para representar o funcionário comum e outra que receba os adicionais de insalubridade.

abstract class EmployeeAbastract {
  constructor(
    protected id: string,
    protected hourPayment: number,
    protected workedHours: number,
  ) {}

  get payment(): number {
    return this.calculatePayment();
  }

  protected calculatePayment() {
    return this.hourPayment * this.workedHours;
  }
}

class EmployeeA extends EmployeeAbastract {
  constructor(id: string, hourPayment: number, workedHours: number) {
    super(id, hourPayment, workedHours);
  }
}

enum EmployeeRiskLevel {
  LOW = 10,
  MEDIUM = 20,
  HIGH = 40,
}
class EmployeeB extends EmployeeAbastract {
  constructor(
    id: string,
    hourPayment: number,
    workedHours: number,
    private riskLevel: EmployeeRiskLevel,
  ) {
    super(id, hourPayment, workedHours);
  }

  protected calculatePayment() {
    const riskLevelInDecimal = this.riskLevel / 100;
    const basePayment = this.hourPayment * this.workedHours;
    const additional = basePayment * riskLevelInDecimal;
    return basePayment + additional;
  }
}

A classe do funcionário básico manteve-se inalterada quanto às implementações da classe abstrata, já a classe que recebe os adicionais de insalubridade, houve o method overriding para modificar o comportamento da função de cálculo do pagamento e entregar o valor atualizado com os adicionais.

Conclusão:
Trata-se da possibilidade de modificação de uma classe/módulo sem que interfira no funcionamento geral ou de outras que utilizem métodos compartilhados.
No exemplo de solução, pode-se modificar ambas as classes livremente que uma não interferirá no funcionamento da outra, bem como caso haja a necessidade de adicionar/modificar um comportamento comum, basta faze-lo na classe abstrata que ambas irão compartilhar a adição/modificação.

Referências:

  • MARTIN, Robert C. Arquitetura Limpa: O Guia do Artesão para Estrutura e Design de Software. Rio de Janeiro: Alta Books, 2019.
Carregando publicação patrocinada...