Dicas valiosas de programação – Parte 01

Introdução

Ao longo do tempo, cada analista de sistemas e programador adquire experiência e proeficiência em algoritmos e soluções de software para atender a necessidade de seus clientes. Normalmente cada linguagem têm os seus “pulos do gato”, muitos são conhecidos e são independentes da linguagem de programação. Neste post vamos abordar os mais conhecidos, e que sempre devem ser lembrados, com ênfase no “porquê” é melhor fazer assim do que assado.

Separe o Processamento da Interface

Basicamente, você escreve um pouco mais de código, visando criar no mínimo duas etapas de processamento em códigos distintos. O primeiro código, responsável pela camada de interface, deve criar para o usuário uma interativa de fornecer os dados e parâmetros para um processamento.

Por exemplo, uma inclusão de novo cliente, ou a emissão de um relatório. Você constrói uma interface onde o usuário possa preencher os campos de cadastro ou os parâmetros a serem considerados na emissão do relatório.

O segundo código é responsável pela realização efetiva do processamento. Porém, este código não deve ter acesso a interface. Ele deve receber os dados para serem processados como argumento da função, e o retorno de sua execução deve indicar se o processamento foi executado com sucesso, e em caso de falha, os detalhes pertinentes da falha — como por exemplo parametrização inválida, tentativa de incluir cliente já existente, etc…

Por que fazer dessa forma ?

  1. Uma rotina escrita para não depender de interface pode ser executada SEM interface, em processamentos do tipo “JOB”. Isso torna possível, por exemplo, a criação de JOBs dedicados para realizar várias inclusões ao mesmo tempo, ou por exemplo a execução do relatório através de um programa do tipo “Agendador de Tarefas” (ou Scheduler) sem a dependência de ser iniciado pelo usuário.
  2. A rotina responsável pelo processamento deve possuir as validações adequadas da parametrização envolvida na sua execução, assim você escreve uma única função de processamento, e pode fazer a chamada dela a partir de várias interfaces ( SmartClient, Telnet, WebService, HTML, REST, etc ), onde a regra de negócio é mantida em apenas um código.
  3. As interfaces de chamada da função de processamento não necessariamente precisam apresentar uma tela ao usuário. Por exemplo, a sua função de processamento recebe parâmetros em array, no formato chave=valor. Com algumas linhas de código é possível escrever uma classe de Web Services Server, responsável por publicar uma funcionalidade e tratar os parâmetros (SOAP ou REST) recebidos, converter em array para a chamada da função, e retornar o status da tarefa.
  4. Mesmo utilizando uma arquitetura Client-Server, como o caso do AdvPL, o contexto de execução de um processo de interface — SmartClient por exemplo — somente é mantido no ar enquanto a aplicação Client está sendo executada. Logo, se durante um processamento de código AdvPL no servidor, sendo executado em um contexto (ou Thread) iniciada a partir de um SmartClient, se o APPlication Server perder o contato com o SmartClient — normalmente por instabilidade na rede ou mesmo um problema na máquina onde o Smartclient está sendo executado ), o processo em execução no servidor é encerrado imediatamente — afinal sua existência é baseada na premissa da interface gráfica com o usuário.
  5. Justamente em processamentos mais longos, como por exemplo processos em lote — ou a emissão de um relatório que demora duas horas … Não vale a pena deixar a interface aberta e travada com uma tela de “aguarde”, e rodar o relatório neste processo. Imagine que falta 10 minutos pro relatório efetivamente ser emitido, e a energia “piscou” no terminal, e o terminal perdeu por um instante a conexão de rede .. lá se foi uma hora e 50 minutos de trabalho jogados fora, em uma infra-estrutura onde o servidor de aplicação normalmente está em um ambiente com rede redundante, alimentação de energia redundante, alta disponibilidade e afins .. o relatório teve que ser emitido novamente, e iniciar “do zero” por que a energia “piscou” na sala onde estava o terminal do sistema.

Então, vamos mudar tudo pra JOB ?

Não, não é assim que funciona. Chamar um processo separado do processo atual para realizar uma tarefa têm custo, exige mais controle(s), tratamento(s) de erro, normalmente exige um algoritmo de gerenciamento de processos, para não deixar o sistema subir mais processos do que ele “aguenta” processar. Um erro de lógica neste mecanismo ou a ausência dele pode levar um sistema a um estado de esgotamento de recursos.

O que colocar em JOB ?

Via de regra, normalmente é recomendável colocar em JOB os seguintes tipos de processamento:

  1. Emissões de relatórios pesados e/ou demorados. Aquele resumo financeiro do dia anterior, que só pode ser executado depois da meia note, que demora pelo menos meia hora para ser emitido, e que você precisa ver no dia seguinte as 8 horas da manhã … coloque em um agendador de tarefas (Scheduler)  para rodar as 5 ou 6 da manhã. Quando você entrar no sistema e abrir o Spool de Impressão,  seu relatório deve estar lá. Se não estiver, o Scheduler deve ter registrado alguma falha.
  2. Tarefas complementares de processamentos, onde não existe a necessidade imediata do resultado para a continuidade do processo. Por exemplo, um envio de e-mail informativo de uma determinada operação. Quando utilizadas em pequenas quantidades, subir um jobs adicional na execução do programa é suficiente. Agora, caso múltiplas rotinas de envio de email sejam chamadas ao mesmo tempo, sob pena de haver um esgotamento de recursos, é prudente criar uma fila de envio de emails — por exemplo uma tabela na aplicação contendo os emails pendentes de envio, e um ou mais JOBS dedicados ao envio de email. Assim, enquanto os processos vão inserindo os emails a serem enviados em uma tabela do banco de dados, um ou mais processos dedicados vão enviando esses emails, um a um, sem sobrecarregar o servidor atual com muitos jobs, e sem sobrecarregar o próprio provedor de email.
  3. Tarefas especializadas concorrentes, onde múltiplos processos concorrem pelo mesmo recurso, que só pode ser usado por um processo por vez. Normalmente estes casos são exemplificados por rotinas de atualização que exigem o bloqueio temporário de um registro. Neste caso, seria mais elegante criar um e apenas um JOB dedicado para fazer esta atualização, e este JOB pegar os dados que devem ser atualizados de uma fila. Assim, outros processos que precisem fazer esta tarefa não precisam esperar o processo dedicado terminar de rodar a requisição.

Conclusão

Escrever a rotina de processamento sem depender de interface, além de naturalmente permitir a execução dessa rotina dentro de um processo de interface, lhe abre a oportunidade de executá-la em um processo separado, mas não o obriga a fazer isso. Se uma rotina já existe, e foi escrita para depender de uma interface, você deve decidir se usar um JOB é a melhor alternativa para as suas necessidades, e avaliar o custo de fazer essa separação. Em linhas gerais, para não sofrer amanhã, comece a separar processamento da interface hoje, nas novas funcionalidades que você implementa, assim a utilização delas em Job, se assim conveniente ou necessário for, será menos traumático.

Desejo a todos(as)  TERABYTES de SUCESSO 😀

 

2 comentários sobre “Dicas valiosas de programação – Parte 01

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s