SOLID Aplicado

Na teoria, teoria e prática são a mesma coisa.

Na prática, não.

SOLID mão na massa

30 minutos

60 minutos

O que é S.O.L.I.D.?

Como surgiu esse acrônimo?

Orientada a que!?

Programação orientada a objetos...

O que é Programação Orientada a Objetos?

Este paradigma permite

Abstração de um objeto do mundo real para o código.

1.

Abstração

2.

Encapsulamento

Embrulha propriedades de uma classe.

3.

Adaptabilidade.

Na biologia, plantas e animais tem com o intuito de sobrevivência.

Polimorfismo

4.

Herança

Extremamente utilizada para a diminuição de código.

SRP

Single Responsibility Principle

OCP

Open-Closed Principle

LSP

Liskov Substitution Principle

DIP

Dependency Inversion Principle

ISP

Interface Segregation Principle

S

O

L

I

D

Qual a vantagem?

Single Responsibility Principle

Princípio da responsabilidade única

export class Pagamento {
  nome = 'Rafael'
  salario = 4000
  horas = 40

  pagar() {
    const salario = this.salario * this.horas
    return (`Pagando ${salario} para ${this.nome}`)
  }
}

const pagamento = new Pagamento()
pagamento.pagar()

Violando o Princípio

class Estagiario {
  nome = 'Estudante'
  salario = 2000
  horas = 20
}


export class Pagamento {
  pagar(funcionario: Estagiario) {
    const salario = funcionario.salario * funcionario.horas
    console.log(`Pagando ${salario} para ${funcionario.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())

Cumprindo o Princípio

Open-Closed Principle

Princípio Aberto-Fechado

class Estagiario {
  nome = 'Dev Junior'
  salario = 2000
  horas = 20
}

export class Pagamento {
  pagar(funcionario: Estagiario) {
    const salario = funcionario.salario * funcionario.horas
    console.log(`Pagando ${salario} para ${funcionario.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())

Violando o Princípio

class Estagiario {
  nome = 'Estudante'
  salario = 20000
  horas = 20
}

class Junior extends Estagiario {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40
}

export class Pagamento {
  pagar(funcionario: Estagiario | Junior) {
    const salario = funcionario.salario * funcionario.horas
    return (`Pagando ${salario} para ${funcionario.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())

Cumprindo o Princípio

Liskov Substitution Principle

Princípio da substituição de liskov

class Estagiario {
  nome = 'Estudante'
  salario = 20000
  horas = 20
}

class Junior extends Estagiario {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40
}

export class Pagamento {
  pagar(funcionario: Estagiario | Junior) {
    const salario = funcionario.salario * funcionario.horas
    return (`Pagando ${salario} para ${funcionario.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())

Violando o Princípio

interface Pessoa {
  nome: string
  salario: number
  horas: number
}

class Estagiario implements Pessoa {
  nome = 'Estudante'
  salario = 20000
  horas = 20
}

class Junior implements Pessoa {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40
}

export class Pagamento {
  pagar(pessoa: Pessoa) {
    const salario = pessoa.salario * pessoa.horas
    console.log(`Pagando ${salario} para ${pessoa.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())
pagamento.pagar(new Junior())

Cumprindo o Princípio

Interface Segregation Principle

Princípio da segregação de interface

interface Pessoa {
  nome: string
  salario: number
  horas: number
}

class Estagiario implements Pessoa {
  nome = 'Estudante'
  salario = 20000
  horas = 20
}

class Junior implements Pessoa {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40
}

export class Pagamento {
  pagar(pessoa: Pessoa) {
    const salario = pessoa.salario * pessoa.horas
    return (`Pagando ${salario} para ${pessoa.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())
pagamento.pagar(new Junior())

Violando o Princípio

abstract class Pessoa {
  abstract nome: string
  abstract salario: number
  abstract horas: number

  abstract calculaSalario(): number
}

class Estagiario implements Pessoa {
  nome = 'Estudante'
  salario = 20000
  horas = 20

  calculaSalario() {
    return this.salario * this.horas
  }
}

class Junior implements Pessoa {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40

  calculaSalario() {
    return this.salario * this.horas
  }
}

class Pleno implements Pessoa {
  nome = 'Dev Pleno'
  salario = 100000
  horas = 40

  calculaSalario() {
    const bonus = this.salario * this.horas * 0.1
    return (this.salario * this.horas) + bonus
  }
}

export class Pagamento {
  pagar(pessoa: Pessoa) {
    const salario = pessoa.calculaSalario()
    return (`Pagando ${salario} para ${pessoa.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())
pagamento.pagar(new Junior())
pagamento.pagar(new Pleno())

Cumprindo o Princípio

Dependency Inversion Principle

Princípio da inversão de dependência

abstract class Pessoa {
  abstract nome: string
  abstract salario: number
  abstract horas: number

  abstract calculaSalario(): number
}

class Estagiario implements Pessoa {
  nome = 'Estudante'
  salario = 20000
  horas = 20

  calculaSalario() {
    return this.salario * this.horas
  }
}

class Junior implements Pessoa {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40

  calculaSalario() {
    return this.salario * this.horas
  }
}

class Pleno implements Pessoa {
  nome = 'Dev Pleno'
  salario = 100000
  horas = 40

  calculaSalario() {
    const bonus = this.salario * this.horas * 0.1
    return (this.salario * this.horas) + bonus
  }
}

export class Pagamento {
  pagar(pessoa: Pessoa) {
    const salario = pessoa.calculaSalario()
    return (`Pagando ${salario} para ${pessoa.nome}`)
  }
}


const pagamento = new Pagamento()
pagamento.pagar(new Estagiario())
pagamento.pagar(new Junior())
pagamento.pagar(new Pleno())

Violando o Princípio

import { setDependency, useDependency } from "../ic"

abstract class Pessoa {
  abstract nome: string
  abstract salario: number
  abstract horas: number

  abstract calculaSalario(): number
}

abstract class Desenvolvedor extends Pessoa {
  abstract nome: string
  abstract salario: number
  abstract horas: number

  abstract calculaSalario(): number
  
  abstract resolveProblema(): boolean
}

class Estagiario implements Desenvolvedor {
  nome = 'Estudante'
  salario = 20000
  horas = 20

  calculaSalario() {
    return this.salario * this.horas
  }

  resolveProblema() {
    return false
  }
}

class Junior implements Desenvolvedor {
  nome = 'Dev Junior'
  salario = 50000
  horas = 40

  calculaSalario() {
    return this.salario * this.horas
  }

  resolveProblema() {
    return false
  }
}

class Pleno implements Desenvolvedor {
  nome = 'Dev Pleno'
  salario = 100000
  horas = 40

  calculaSalario() {
    const bonus = this.salario * this.horas * 0.1
    return (this.salario * this.horas) + bonus
  }

  resolveProblema() {
    return true
  }
}


class Pagamento {
  pagar(pessoa: Pessoa) {
    const salario = pessoa.calculaSalario()
    return (`Pagando ${salario} para ${pessoa.nome}`)
  }
}


const devs: Record<string, Desenvolvedor> = {
  estagiario: new Estagiario(),
  junior: new Junior(),
  pleno: new Pleno(),
}

setDependency(Desenvolvedor, Junior)

app.get('/devs', (req, res) => {
  const dev = useDependency(Desenvolvedor)
  res.json(dev)
})

app.get(`/pagamento/:dev`, (req, res) => {
  const dev = devs[req.params.dev]

  const pagamento = new Pagamento()

  res.json({ message: pagamento.pagar(dev) })
})

Cumprindo o Princípio

Princípios Solid com TypeScript

By Guilherme Siquinelli

Princípios Solid com TypeScript

  • 296