Por que eu devo ler este artigo:Neste artigo serão apresentados alguns dos erros mais comuns realizados por desenvolvedores Java, principalmente por não compreenderem perfeitamente os fundamentos da própria Orientação a Objetos.

Exemplos mostram como identificar trechos de código com alto acoplamento e como isso prejudica a manutenção e a extensão de um sistema OO.

Além disso, os propósitos de conceitos como Encapsulamento, Herança e Polimorfismo, bem como o padrão Modelo-Visão-Controle, são revisitados, mostrando como utilizá-los corretamente para deixar o projeto mais rico e facilitar o reuso de classes.

Quando ouvimos falar em Java como linguagem de programação, a expressão “Orientação a Objetos” logo vem à cabeça. Apesar de ser um dos primeiros temas a estudar quando aprende-se a programar em Java, muitas pessoas o negligenciam achando, por exemplo, que Encapsulamento se reduz a utilizar métodos do tipo getXXX() e setXXX() em suas classes quando, na verdade, estes tipos de métodos devem ser evitados a qualquer custo justamente por ferir este princípio fundamental.

Outros exibem orgulhosos a “árvore genealógica” das classes que compõem o seu sistema, sem saber que o esforço para estender e manter o código funcionando corretamente aumenta proporcionalmente com o tamanho da “árvore”.

Diante deste cenário, este artigo tem como objetivo principal revisitar os conceitos fundamentais da Orientação a Objetos: Encapsulamento, Herança e Polimorfismo.

Ao mesmo tempo, alguns padrões GRASP (General Responsibility Assignment Software Patterns) são introduzidos. Estes padrões, ao contrário dos Padrões de Projeto escritos pela “Gangue dos Quatro”, possuem o objetivo de facilitar o entendimento sobre quais são as responsabilidades de cada classe em um sistema.

Apesar de muitos desenvolvedores considerarem estes padrões mais básicos, sua importância é enorme e não deve ser menosprezada pois, nem mesmo uma abordagem ágil com todas as suas técnicas que preveem suporte a alterações frequentes no código, é capaz de diminuir os impactos negativos de um código mal escrito.

Nota: Durante o desenvolvimento de softwares orientados a objetos, existem alguns problemas que são recorrentes, ou seja, aparecem várias vezes e em diferentes situações, às vezes até “mascarados” como problemas diferentes. Desta forma, há algum tempo, quatro dos grandes nomes da comunidade de orientação a objetos (Erich Gamma, John Vlissides, Ralph Johnson e Richard Helm) perceberam esse padrão e começaram a catalogar as soluções utilizadas para resolver estes problemas, dando nomes a elas e descrevendo como e quando utilizá-las.

Posteriormente, estas soluções foram compartilhadas através do livro “Padrões de Projeto: soluções reutilizáveis de softwares orientados a objetos” e seus autores passaram a ser conhecidos como a “Gangue dos Quatro”. O livro é uma referência até hoje para aqueles que querem se aprofundar no estudo da orientação a objetos.

Como exemplo, considere as Listagens 1, 2 e 3, onde são exibidas as classes de um sistema bancário simples que permite a criação de agências. O código foi propositalmente escrito com a classe que representa o domínio (AgenciaBancaria) contendo somente métodos getXXX() e setXXX(), funcionando como um recipiente de dados.

O padrão arquitetural Modelo-Visão-Controle (outro conceito mal compreendido por muitos desenvolvedores) foi utilizado como forma de separar as responsabilidades envolvidas em cada classe. A Figura 1 mostra o diagrama de classes deste sistema.

Listagem 1. Classe que representa o domínio do problema no sistema bancário.

  01 public class AgenciaBancaria {
  02    private String codigo;
  03    private List<ContaBancaria> contas = new LinkedList<>();
  04    public List<ContaBancaria> getContas() {
  05          return contas;
  06    }
  07    public void setContas(List<ContaBancaria> contas) {
  08          this.contas = contas;
  09    }
  10    public String getCodigo() {
  11          return codigo;
  12    }
  13    public void setCodigo(String codigo) {
  14          this.codigo = codigo;
  15    }
  16 }

Listagem 2. Classe que representa a lógica de negócio no sistema bancário.

  01 public class ControladorAgencia {
  02    private List<AgenciaBancaria> agencias = new LinkedList<>();
  03    public void adicionaAgencia(AgenciaBancaria agencia) {
  04          agencias.add(agencia);
  05    }
  06    public AgenciaBancaria buscarAgencia(String codigo) {
  07                 for (AgenciaBancaria agenciaBancaria : agencias) {
  08                 if(agenciaBancaria.getCodigo().equals(codigo)){
  09                        return agenciaBancaria;
  10                 }
  11          }
  12          return null;
  13    }
  14 }

Listagem 3. Classe que representa a interface com o usuário do sistema bancário.

  01 public class VistaAgencia {
  02    private int codigoAgencia = 1; 
  03    private ControladorAgencia controlador = new ControladorAgencia();
  04    public void exibir(){
  05          Scanner scan = new Scanner (System.in);
  06          String opcao = "";
  07          while(opcao != null){
  08                 System.out.println ("Digite : ");
  09                 System.out.println("[1] Para criar nova agencia");
  10                 System.out.println("[2] Para buscar uma agencia");
  11                 System.out.println("[3] Para sair.");
  12                 opcao = scan.nextLine();
  13                 if(opcao.equals("1")){
  14                        String codigo = String.valueOf(codigoAgencia);
  15                        codigoAgencia = codigoAgencia + 1;
  16                        AgenciaBancaria agencia = new AgenciaBancaria();
  17                        agencia.setCodigo(codigo);
  18                        controlador.adicionaAgencia(agencia);
  19                        System.out.println(“Agencia criada com sucesso. Códi ... 

Quer ler esse conteúdo completo? Seja um assinante e descubra as vantagens.
  • 473 Cursos
  • 10K Artigos
  • 100 DevCasts
  • 30 Projetos
  • 80 Guias
Tenha acesso completo