domingo, 29 de junho de 2008

Uma conversa sobre boas práticas de desenvolvimento

Quando começamos a desenvolver, a principal meta é obter uma aplicação que funcione. E com o tempo vamos melhorando nossas práticas, facilitando e polindo nosso código - claro que estou me referindo aos verdadeiros profissionais.

Mas mesmo assim, na enorme maioria das vezes os desenvolvedores não vão tão a fundo sobre o funcionamento da aplicação, sendo que isto muitas vezes pode ser muito útil. Seja por falta de informação, ou na dificuldade de encontrar e entender a mesma.

Por exemplo, quantos de vocês já pararam para pensar sobre o processo de requisição de uma simples página de internet? Vamos fazer uma pequena viagem neste processo (acredite, isso é a forma simplificada!).

Ao clicar num link para uma página, o seu navegador pede ao sistema operacional que envie um pacote de requisição pela interface de rede. Este pacote contém os request headers, ou seja informações sobre o destino solicitado (o SO é que acrescenta o endereço de origem), informações sobre o navegador, quais linguagens e encodings ele aceita, etc.. Essa solicitação é resolvida num servidor DNS, que converte o nome para um endereço IP, e a saga do pacote continua de roteador em roteador até que o IP da página requisitada seja encontrado. Chegando lá, o SO do servidor, vai direcioná-lo para o servidor HTTP (geralmente o Apache), onde será enfim processado.

O servidor é responsável por localizar qual arquivo está sendo solicitado, checar regras e políticas de segurança junto ao SO, formatá-lo, codíficá-lo se for o caso, e por fim, enviar de volta o arquivo em pacotes, fazendo o caminho inverso. Se o seu navegador, ao reconstruir os pacotes, identificar que existem outros arquivo sendo solicitados na própria página, como folhas de estilo externas (CSS), arquivos javascript, imagens, arquivos flash, ou mesmo frames, ele irá enviar novas solicitações ao servidor para que este envie os arquivos necessários.

Com tudo recebido, o seu navegador monta a página, rederiza o CSS sobre os elementos, e carrega os javascripts para execução.

Bastante coisa não? Vamos deixar um pouco de lado a parte do seu navegador e vamos focar em duas coisas: o processamento do lado do servidor, e o tráfego de rede.

O servidor tem que alocar memória para cada requisição feita. Este processo também demanda processamento, tanto do servidor HTTP, quanto do SO. Ele tem que gerenciar muitas coisas, ainda mais quando se tem várias requisições chegando ao mesmo tempo.

Agora quando uma página dinâmica é solicitada, o trabalho do lado do servidor acaba aumentando bastante. Ao identificar que se trata de uma página PHP ou Python, por exemplo, o servidor HTTP precisa ler o arquivo e passá-lo ao engine responsável pelo processamento. Isso faz com que o SO reserve mais memória e consuma mais processamento, pois há mais um aplicativo participando da bricadeira. Pelo amor de Deus, eu não estou falando para criar apenas páginas estáticas, mas estou dando uma visão geral para que vocês entendam a importância de uma polida no código no sentido de otimização quando forem fazer um sistema.

Bem, vamos lá... temos um SO gerenciando vários processos e alocando memória para o Apache e para o engine do PHP. Até aí nenhum problema, os softwares são bem escritos e as máquinas de hoje dão conta do recado sem precisar fazer muita força. Mas o mundo não é feito só de hello world's, e de scripts para mostrar que horas são em Estocolmo.

Então, não raro o seu script PHP vai precisar acessar um banco de dados ou arquivos. E aí é onde a coisa pode começar a complicar. Quando acessa um banco de dados, o PHP carrega um módulo, com uma API para o banco de dados, e então ele abre uma conexão para o banco de dados. O processo é muito parecido com a requisição de uma página (exceto, geralmente, o que diz respeito a ficar passando de roteador em roteador para encontrar o banco de dados). E o servidor de banco de dados trabalha de forma muito parecida (guardando-se as devidas proporções) com o servidor HTTP. Ele válida a sessão, reserva memória e começa a processar prioridades de acesso - em outras palavras, mais memória alocada, mais processamento consumido.

Aí voltamos ao seu script. Ele se conectou no banco de dados. Hora de enviar as queries. Para cada query enviada, uma nova requisição é enviada ao banco de dados, através da conexão que você abriu (sim, isto é tráfego de rede). Ao receber a requisição, o engine do banco de dados realiza primeiro o que é chamado de execution plan. Ele estima algumas formas de como pode executar sua requisição, e executa aquela que ele julga ser a mais apropriada (com menor custo ao sistema). Isso é assunto pra tese de doutorado, então não vou me ater a explicações profundas sobre isso. Mas só para constar, triggers, rules, reconstrução de índices, validação de constraints e outros recursos também entram nas contas das estimativas do execution plan, daí você imagina o trabalho do servidor de banco de dados ao decodificar cada query ANTES de executá-la.

Executar a query, envolve além de consumo de processamento e memória, acesso a discos, e possivelmente gravação neles (o que nos trás de volta ao SO, que é o responsável por essa parte de acesso e gravação em discos).

Terminada a maratona da execução, o banco de dados retorna o resultado disso para o PHP (através daquela conexão que ele tem, lembra?). Para daí em diante o PHP continuar o seu processamento. Lembre-se que tudo o que foi descrito acima vale para CADA QUERY enviada. Chegando ao fim do script, o PHP fornece o seu produto ao Apache, que o formata, codifica, etc... e envia em gentis pacotes ao cliente através da rede.

Agora, o que aconteceria se enviássemos menos queries? Conseguem ver a vantagem? Este é o motivo pelo qual é muito importante usar de forma eficiente e inteligente os recursos que os servidores de bancos de dados oferecem. Isso deixa os códigos mais elegantes e limpos, o sistema gerlamente fica mais seguro, mais fácil de fazer manutenção, e otimizado (sem contar que dá pra cobrar uma grana a mais pelo serviço mais profissional).

Dou o artigo como encerrado por aqui. Em breve escrevo mais sobre otimização e segurança no lado dos BDs, e no PHP em si.

See ya.
-----------
keepReading