Quando Utilizar Orientação a Objetos e Quando NÃO Utilizar
Um tema bastante discutido tanto na área de desenvolvimento quanto na área de infra-estrutura é “performance”.
Muito comum também nas mesas de ping-pong da vida:
Desenvolvedor: “O problema é o servidor que não está aguentando a carga. Precisa fazer um upgrade”;
Adminstrador do Servidor: “O problema é a programação que está muito pesada e consumindo todo o processamento do servidor”.
A verdade é que este assunto deve ser muito bem trabalhado nas duas áreas.
Se tanto Desenvolvedores quanto Administradores de Rede fizerem a sua parte, a aplicação certamente terá vida longa (pelo menos do ponto de vista técnico) e poderá suportar um bom crescimento.
Este assunto de crescimento, escalabilidade e performance é algo bastante amplo e envolve várias áreas e técnicas. Não pretendo me aprofundar em todas as variantes do tema, mas gostaria de falar sobre algumas regras que costumo utilizar para garantir uma performance melhor da aplicação.
A Programação Orientada a Objetos (POO) é algo maravilhoso para o desenvolvedor.
A clareza, legibilidade e manutenibilidade que esta técnica traz para o código algo excelente e necessário nos dias atuais.
O problema é que, em alguns casos, uma aplicação corretamente desenvolvida numa Arquitetura de Software Orientada a Objetos pode trazer impactos negativos à performance da aplicação.
Por outro lado, uma aplicação de média complexidade desenvolvida de forma estruturada poderá, também, trazer impactos negativos na manutenibilidade e crescimento da aplicação e do negócio.
Para falar sobre este assunto, iremos organiza-lo em dois tipos de aplicações:
APLICAÇÕES COM POUCOS ACESSOS SIMULTÂNEOS OU BAIXA CRITICIDADE DE PERFORMANCE
Estes costumam ser os projetos menos críticos e a minha sugestão é para usar e abusar da Orientação a Objetos e dos Design Patterns.
Neste caso você terá uma grande oportunidade de aprendizado e aperfeiçoamento técnico, a aplicação tende a ter um código mais limpo, reutilizável e de fácil manutenção, sem incorrer em riscos de sobrecarga do sistema (devido à baixa quantidade de acessos).
APLICAÇÕES COM MUITOS ACESSOS SIMULTÂNEOS OU DE PERFORMANCE CRÍTICA
Estes são os projetos mais “delicados”. E a minha sugestão é que nestes casos, seja buscado o melhor balanceamento entre a manutenibilidade do código e a performance da aplicação.
Para alcançar isto faz-se necessário identificar quando utilizar a Orientação a Objetos e quando NÃO utilizar a Orientação a Objetos.
Isto não é algo tão fácil de se conseguir, porque em muitos momentos será preciso optar entre manter o código legível e de fácil manutenção “ou” manter a boa performance.
Ou seja, em alguns momentos será necessário sacrificar ou a legibilidade e manutenibilidade, ou a performance.
De qualquer forma existem algumas dicas que podem ajudar nesta decisão.
Algumas vezes eu costumo utilizar uma solução híbrida, utilizando POO onde não há maiores impactos na performance ou onde o benefício da clareza e reutilização do código superam a perda de performance, e utilizando programação estruturada onde é preciso garantir a boa performance.
Por exemplo:
1) Páginas muito acessadas
As páginas mais acessadas normalmente são as mais críticas, carregam mais informações e demandam melhor otimização.
Se você está programando a Front Page de um site, e esta contém muita programação, você poderá optar por trabalhar com cache.
Se cache for algo possível (do ponto de visto do negócio) na sua aplicação, ótimo, você poderá fortalecer sua estrutura de cache e caprichar na Orientação a Objetos, sem maiores impactos em performance.
Se cache não for uma alternativa viável para esta página, talvez seja melhor buscar uma arquitetura mais híbrida e evitar muitos instanciamentos em cascata nos objetos mais complexos, trabalhar com menos requisições SQL e caprichar na otimização da programação.
O problema é que na POO, os objetos mais complexos costumam carregar uma série de dependências (que normalmente são outros objetos), e, ficar carregando um caminhão de objetos para cada requisição, pode ser algo prejudicial a performance.
Para simplificar, vou chamar estes objetos de “cegonhas” (aquele caminhão que carrega vários outros carros).
Se a sua aplicação possuir várias “cegonhas”, existem alguns Design Patterns que podem ajudar, como a Factory e objetos Singleton (que lhe permitirão reutilizar objetos persistentes e evitar loads desnecessários) e o Lazy Load (que lhe permitirá carregar apenas as dependências necessárias para a requisição).
Porém, ainda assim, em alguns casos, estas técnicas serão insuficientes.
E estes são os casos que quero chamar a atenção.
A minha grande dica é: Sempre que você estiver programando, tente imaginar como aquele pedaço de código irá rodar em nível de máquina:
- A quantidade de recursos que será exigido do servidor e o quanto estes recursos são pesados em nível de servidor;
- Quantos loops serão necessários e o quanto estes loops são pesados em nível de processamento, I/O de disco, memória e etc;
- Quantas requisições (banco de dados, HTTP, I/O de disco e etc) serão necessárias (imagine os casos mais comuns, os mais complexos, os mais pesados) e o quanto elas poderão impactar na performance ou até mesmo criar um gargalo.
Com base nisso, pense em maneiras mais eficientes de se fazer a mesma coisa.
Quais os prós e contras de cada alternativa.
Como elas se comportariam com o crescimento da aplicação e dos servidores?
Eleja a melhor alternativa para a sua realidade.
De modo geral, sempre que você perceber que a execução da página poderá gerar pontos de sobrecarga, repense a otimização do código.
2) Páginas pouco acessadas
As páginas pouco acessadas costumam ser menos preocupantes. Normalmente elas não oferecem risco de sobrecarga ao sistema, justamente por receberem pouquíssimos acessos simultâneos.
Ainda assim, é preciso ter em mente que, se esta página tiver uma programação “pesada” que exija muitos recursos do servidor, ela passará a ser um ponto de falha da aplicação. Isto porque, se algum usuário mal intencionado perceber este impacto, poderá utilizá-la para um ataque DoS e tirar a aplicação do ar.
Por via de dúvida eu costumo utilizar as mesmas regras do item 1, também nestes casos.
A diferença é que no caso das páginas pouco acessadas eu costumo ser um pouco mais tolerante.
3) Páginas leves
As páginas mais leves costumam dispensar maiores comentários.
Neste caso a preocupação maior é com a segurança, visto que na parte de performance elas não costumam ser impactantes.
Novamente, a dica fica para considerar a possibilidade de um ataque DoS.
Tente imaginar (e se possível, testar na prática) como ela se comportaria diante de um ataque DoS, apenas para certificar-se que a página é realmente leve e dispensa maiores otimizações.
CONSIDERAÇÕES FINAIS
Para não deixar dúvidas, eu gostaria de deixar claro que não estou afirmando que a Programação Orientada a Objetos é mais pesada que a Programação Estruturada.
Normalmente ela não é.
Em determinados casos (ou padrões) ela é até mais leve.
E em outros casos a ela costuma ser mais pesada.
O que precisamos é aprender quais são estes casos, prever estas situações e trabalhar nas otimizações antecipadamente.
RESUMINDO
Problemas conhecidos com o uso correto da Orientação a Objetos
Objetos com muitas dependências, especializações ou regras poderão exigir load de outros objetos e requisições SQL, que poderá impactar negativamente na performance da aplicação.
Problemas conhecidos com o uso da Programação Estruturada
Blocos de código duplicados, pior intuitividade e legibilidade do código, resultando em maior dificuldade de manutenção da aplicação.
Quando usar Orientação a Objetos e quando não usar Orientação a Objetos?
Usar sempre que possível e os recursos exigidos em nível de hardware não trouxerem impactos negativos para a performance da aplicação.
Quando a página for muito acessada e o bloco de código exigir carga excessiva de componentes ou requisições extras (banco de dados, HTTP, I/O e etc), otimizar o código, mesmo que isto indique a utilização de outras técnicas em conjunto (cache, informações sumarizadas, Programação Estruturada e etc).
Ronan Lucio Pereira
