quinta-feira, 29 de julho de 2010

Dificuldades na migração para POO

Quem não está acostumado à POO, ou programou muito tempo de maneira estruturada, orientada a eventos ou de forma sequencial/batch ("linguiçal" ) tem dificuldades para
aprender um novo paradigma, por exemplo a Programação Orientada a Objetos. (Novo? POO é anterior ao meu nascimento.... )

O que gera bastante dúvida e dificuldades para quem que mudar de paradigma é que tem várias "escolas/linhas de pensamento" diferentes. Não adianta, embora programação
tenha uma afinidade e até uma intimidade com a matemática, no lado das exatas, a programação é uma arte. Por mais que se inventem padrões e metodologias, sempre faverá
n+1 maneiras de se chegar à um pensamento abstrato ou uma lógica ou um algoritmo que faça a mesma coisa.

Quem ensina costuma misturar a análise orientada a objeto e a programação orientada a objeto tudo na mesma panela, junto com UML.
"E não é a mesma coisa?" você pode estar se perguntando. Não, não é. Algumas autoridades no assunto podem me crucificar por isso, mas é minha opinião profissional.
Agente sabe que, embora a análise mande criar apenas objetos que possam ser representações de objetos físicos no mundo real, na programação acabam surgindo objetos
artificiais simplesmente para envelopar ou empacotar dados, ou facilitar e automatizar tarefas. É esse que é o meu foco.

Alguns professores de POO pura/análise OO rejeitam os padrões de projeto, porque são classes que não tem representatividade no mundo real
(singleton, builder, Abstract Factory), além de violar conceitos de divisão de responsabilidade e encapsulamento.... anyway....
Depois que eu li o livro Padrões de Projeto, aprendi muito,
e prefiro 1000 vezes criar um programa orientado a objetos usando 80% menos linhas de código e com um acoplamento menor e menor cópia de conceitos abstratos
que violam a Análise OO do que ficar sem saber onde colocar códigos de validação, interface ou persistencia em banco de dados simplesmente porque a Análise OO
não trata desses assuntos, mas lida somente com as classes de negócio. Livros de análise OO enfatizam muito as classes de negócio, mas consideram
que o banco de dados e a interface com o usuário não são objetos "reais", representáveis no mundo físico.

Sempre ouço profissionais das linguagens antigas dizer que não é necessário ter uma linguagem com recursos OO para programar
sob este paradigma. Programadores do antigo C, Pascal e até Clipper podiam simular POO criando estruturas e records escondidos para encapsular dados publicos, funções para
inicializar ou retornar esses dados, simulando construtores, membros de records como ponteiros para funções, simulando métodos. Tudo o que deveria ser privado ou encapsulado
poderia ser precedido de um prefixo, como __ (2 underlines), para que fossem um tanto quanto "invisíveis" por outros programadores ou unidades, e colocando-as na seção de
implementação, se por exemplo estiver usando Pascal.

Na verdade, o fato de você praticar a separação de conceitos, separação de responsabilidades, fragmentar métodos gigantes macarrônicos em pequenos métodos que
fazem pouca coisa, ou que façam algo pouco significativo ou mais abstrato, já é meio caminho andado para chegar a programar orientado a objetos.

Isso mostra que a programação orientada a objetos, e qualquer outro paradigma, está mais relacionada com a maneira de pensar do que com a programação ou ferramenta em si. E POO não é o único
paradigma "novo". Existem ainda outros mais novos e pouco explorados, como a programação orientada a serviços, a programação orientada a aspectos (AOP) e uma nova
febre de programação funcional, que surgiu com novas reciclagens de linguagens funcionais como o F#.

A programação funcional, por exemplo, é muito semelhante à matemática, com suas noções de funções, conjuntos etc... Para um matemático, será muito fácil aprender programação
funcional já que ele já tem afinidade com essa maneira de pensar.

Voltando à POO, o paradigma por si só não é garantia de software de qualidade. Já vi muitos programadores criarem programas com classes, herança, etc... e mesmo assim não ser um programa
orientado a objeto. (estaria mais para programa orientado a classes).
Muita programação (Des)estruturada ou macarrônica se faz em linguagens orientadas a objeto.

O melhor modo de aprender POO é treinar. A qualidade do software, independente do paradigma, vai ser assegurada por:
  1. Nunca use copiar-colar de código
  2. Separe os conceitos
  3. Separe as responsabilidades
  4. Crie estruturas únicas para juntar dados que fazem parte de um mesmo todo
  5. Variáveis de tipos primitivos são permitidas apenas dentro de funções/procedimentos
  6. Cada função/procedimento deve fazer o mínimo possível, porém ter um nome que indique exatamente o que ela faz
  7. Variáveis globais apenas para singletons, e quando realmente forem necessárias no escopo do programa inteiro
  8. Variáveis globais deveriam ser somente leitura, e apenas um único método é que poderia modificá-las
  9. Prefira referenciar indiretamente tudo o que for referenciado. (sempre cabe um intermediário entre duas partes que conversam). Isso pode ajudar a evitar acoplamentos desnecessários, principalmente entre módulos importantes do projeto

Eu tinha dificuldade para entender interfaces, até o dia que eu peguei o Livrão de Delphi (Delphi ### A Bíblia, ou Dominando o Delphi ###. A Bíblia, de Marco Cantù) e todas as revistas que falavam do assunto e li tudo de uma vez, fucei nos exemplos e talz. 

Muitos explicam as interfaces como contratos, mas isso gera muita confusão. E o proprio nome interface gera confusão. Eu prefiro enxergá-las como peças de lego,
roupas, e, a grosso modo, classes que só tem o nome do método, mas não tem implementação.

Você pode fazer um exercício: sempre que precisar fazer uma classe, faça uma interface antes da classe. Todo método público que você gostaria que tivesse na classe deve ter na interface primeiro. Aí você faz a classe implementando a interface. Ela se aproxima muito do diagrama de classes da UML, que não tem implementação, é praticamente um desenho da classe em código. Encare uma interface como uma wish list, ela deve conter os métodos que você deseja que a classe tenha, até porque se a classe implementa a interface, o compilador irá te obrigar a implementar todos os métodos.
Outro treino é o seguinte: sempre que você precisar que duas partes do sistema se comuniquem, sejam trocadas ou que cada um dos programadores desenvolva uma classe respeitando um padrão, para que elas possam se comunicar depois, você cria a interface e manda pros programadores implementarem. Pronto, sempre que precisar trocar um objeto de negócio no programa inteiro, pra mudar um comportamento, você pode escrever outra classe que implemente a interface em questão, sem que tenha nenhum grau de parentesco.

Quem está começando a fazer a verdadeira POO agora (não arrastar e colar componente em formulário) vai encontrar um longo caminho a trilhar. Eu mesmo confesso que só andei por 10% desse caminho. Ainda tenho  formulários com regras de negócio em botões e aquele evendo OnClick que faz tudo.

Desejo boa sorte e boas vindas para quem estiver entrando por esse caminho.

Have Fun ;)

Um comentário:

  1. Bom dia, muito bom seu artigo, gostaria de saber que estratégia você indica para se migrar um sistema todo feito de forma procedural para POO.

    ResponderExcluir

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)