Boas práticas para o desenvolvimento de software - Parte I

Desenvolvimento de software
Este post faz parte da série Boas práticas para o desenvolvimento de software. Leia também os outros posts da série:

A minha experiência profissional é baseada no desenvolvimento de software básico (firmware) para microprocessadores, microcontroladores de 8 ou 16 bits e DSPs (Digital Signal Processors). Qual o sistema operacional que costumo utilizar? Nenhum desses tradicionais. Na verdade, em geral desenvolvo os sistemas para os meus projetos. Para os tipos de processadores citados dificilmente tem algum sistema operacional que seja enxuto e eficiente.  Afinal, processadores de 8 ou 16  bits são relativamente lentos, possuem pouca memória interna, mas têm grandes vantagens, dependendo da aplicação em que são utilizados: são simples, baratos, diminutos no seu tamanho físico e extremamente eficientes para pequenas aplicações. Tem algumas versões de microcontroladores PIC, por exemplo,  com encapsulamento de 8 pinos.

 

Retornando ao assunto do sistema operacional, no meu caso, de certa forma, um loop infinito é um sistema operacional de alta eficiência se associado a outros recursos dos processadores, tais como temporizações e interrupções por hardware. É uma maneira de se unir as vantagens citadas dos microcontroladores e conseguir um desempenho em tempo real adequado para algumas aplicações.

 

Quando se fala de desenvolvimento de software de tempo real, deve-se lembrar que isso não implica na necessidade de se realizar as tarefas no menor tempo possível, mas sim em que a velocidade de processamento, monitoramento e controle do seu projeto deve ser suficientemente veloz  e compatível com a velocidade de resposta do sistema para o qual ele foi projetado. Existem processos, principalmente os térmicos, que levam horas ou até dias para progredirem ou mudarem de estado. Neste caso, não é necessário que o processador execute todo o seu programa em frações de segundos. Poderia até levar horas para isso, pois não afetaria o desempenho do sistema como um todo e ainda assim seria um sistema de tempo real.

 

Para poder ilustrar o que foi dito até aqui com um resultado prático e real do uso dessas boas práticas, vou apresentar rapidamente algumas características de um projeto que desenvolvi. Trata-se de um equipamento que faz uma varredura periódica em até 32 detectores de vazamento de combustíveis e cuja principal função é a proteção ambiental na medida em que previne a contaminação do solo de postos de combustíveis.

 

Algumas características do equipamento:

  • Permite a  reconfiguração sempre que necessário;
  • É capaz de detectar curto-circuitos ou rompimento dos cabos dos sensores;
  • Sinaliza a varredura por meio de LEDs;
  • Sinaliza falhas por meio de códigos apresentados em displays de 7 segmentos;
  • Gera um registro em memória não volátil a cada evento anormal, gravando a data e hora dessa ocorrência e a data/hora de quando o a ocorrência foi solucionada;
  • Quando solicitado, gera um relatório formatado para uma  impressora;
  • Gerencia um teclado;
  • Gerencia um relógio de tempo real;
  • Conecta-se em rede a um computador ou à internet para permitir um monitoramento remoto.

 

Tudo isso  e algumas coisinhas a mais, sendo executado num microcontrolador de 8 bits da família MCS-51, com clock de 4 MHz, 12 kBytes de memória EEPROM, 256 Bytes de RAM e  que custa em torno de R$ 20,00 no varejo.

 

software foi todo escrito em C. Seu código fonte tem em torno de 8.000 linhas de programa.  É incrível? Mágica? Nem tanto...

 

Vale ressaltar que até hoje, 10 anos depois da primeira versão, tive que realizar apenas uma pequena correção no software e alterações decorrentes do upgrade do microprocessador para versões mais atualizadas.

 

Mas voltemos ao tema. Essas práticas funcionam muito bem se aplicadas a microcontroladores.  Pode ser que não sirva para você, se acaso você trabalha com um software de alto nível, Visual C por exemplo. Desenvolvo meus projetos de software na forma estruturada, aplicando práticas de encapsulamento de entradas e saídas, essas típicas de software orientado a objetos.

 

O que é o desenvolvimento de software estruturado?

 

Para quem não conhece, discorrendo resumidamente sobre o assunto, um software estruturado é organizado em blocos, o fluxo é muito bem definido e tem regras rígidas para a recursão. Em princípio cada bloco tem uma entrada e uma saída e não se utiliza o recurso do "GOTO" em hipótese alguma, pois ele destrói e corrompe qualquer organização que se tenha realizado no software. A linguagem C, por exemplo, é na sua essência uma linguagem computacional com características de software estruturado. Difícil, não é? A seguir vou explicar e fundamentar porque se deve dar preferência à programação estruturada no caso de microcontroladores e alguns DSPs.

 
desenvolvimento de software estruturado
Figura 1 - Desenvolviemento de software estruturado
 
 

Porque não usar programação orientada a objeto?

 

O principal motivo para não usar programação orientada a objeto é o tamanho do código gerado. Outro motivo é o fato de se  perder um pouco o controle de como o código é gerado e de como a memória é utilizada. Isso complica muito quando é necessário otimizar o código principalmente quando a velocidade de processamento é crítica. Quando se utiliza a linguagem C, depois de algum tempo você aprende a escrever seu código de forma a favorecer a sua otimização. Na hora do aperto, dá até para inserir inline pequenos trechos de código em Assembly (Não é recomendado, mas às vezes não há alternativa...).  Isso te dá o controle quase total sobre o que vai ser gerado no final, o quanto de memória vai ser utilizado, como vai ser utilizada essa memória, etc.

 

Reconheço as qualidades do software orientado a objetos, tais como a portabilidade, velocidade de desenvolvimento de código, encapsulamento de dados e facilidade de manutenção, até porque aproveitei o encapsulamento de dados, típico de programação orientada a objetos,  para melhorar o software estruturado. Apenas afirmo que para o uso em microprocessadores de 8 e 16 bits, frequentemente não é a melhor alternativa. Acredito também, que com o avanço das tecnologias dos compiladores de linguagens orientadas a objeto, pode ser apenas uma questão de tempo para que esses compiladores se tornem mais eficientes e produzam resultados melhores que os compiladores de linguagens estruturadas.

 

O que é encapsulamento de entradas e saídas?

 

É um método  de organização do software que determina regras rígidas para o acesso aos parâmetros ou recursos de um determinado periférico. O acesso tem que ser realizado sempre por meio de um mesmo conjunto de rotinas. Por exemplo: suponhamos que você tenha previsto a utilização de um canal de comunicação serial no seu projeto e que haja a necessidade de se utilizar uma rotina para transmitir dados e outra para receber dados. Se o canal de comunicação for organizado de forma encapsulada, qualquer acesso ao canal serial deverá obrigatoriamente se dar por meio dessas mesmas rotinas de qualquer ponto do seu programa. Assemelha-se muito ao conceito de objeto e métodos associados, conforme definido na programação orientada a objetos, não é mesmo? A diferença é que esse objeto e os métodos associados não são genéricos, mas feitos sob medida para essa aplicação. Por isso que ela tem todas as vantagens decorrentes dessa forma de organização aliada às vantagens de ser específica: enxuta, veloz entre outras.

 

Vale ressaltar que a aplicação desse método a um programa estruturado deve ser realizada por iniciativa e disciplina do desenvolvedor, uma vez que os compiladores de linguagens estruturadas não oferecem ferramentas ou facilidades para fazê-lo.

 

Qual a vantagem dessa forma de organização?

 

Uma vez depuradas as rotinas que administram o seu periférico, você não precisa mais se preocupar com elas ou com o funcionamento dele. Se acaso for detectada alguma falha nesse conjunto, você corrige essas rotinas e todo o seu programa volta a funcionar corretamente.

 

Talvez o jovem profissional, já habituado a utilizar ferramentas de produção de software orientadas a objeto ou de alto nível, não perceba a diferença. Isso porque as ferramentas orientadas a objeto já encapsulam os dados naturalmente. É que é muito comum o programador de software básico ou firmware, por pressa ou preguiça, não organizar o programa desse jeito e acessar diretamente o seu periférico de diversos pontos do seu programa.  É uma grande tentação fazer isso e confesso, que se o programa é pequeno, talvez até seja uma solução rápida. Quando funciona bem, que maravilha!!!!! Mas quando dá "pau" .... É um inferno!!! Fica quase impossível encontrar o problema no código e evitar que a correção do problema eventualmente mal planejada se propague de forma negativa e gere  outros defeitos imprevistos em outras partes do código.

 

No próximo artigo são abordadas algumas sugestões de como proceder para dar nomes a rotinas, variáveis e constantes de forma a aumentar a sua eficiência na produção e manutenção do seu software . Vou comentar um pouco sobre a notação húngara. Parece grego?

 

Se você tiver sugestões e críticas, por favor faça-as que serão muito bem vindas.

Outros artigos da série

<< Boas práticas para o desenvolvimento de software – IntroduçãoBoas práticas para o desenvolvimento de software - Parte II >>
Este post faz da série Boas práticas para o desenvolvimento de software. Leia também os outros posts da série:
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

9
Deixe um comentário

avatar
 
6 Comment threads
3 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
Fabiano SchincariolFelipe LavrattiErisson SiqueiraHenrique Frank Werner PuhlmannMateus Oliveira Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Fabiano Schincariol
Visitante
Fabiano Schincariol

Muito bom o artigo! No caso de microcontroladores STM32 poderia pensar em programação orientada a objeto pela velocidade de processamento? ou também no ESP32?

Mateus Oliveira
Visitante
Mateus Oliveira

Gostei do artigo, vou analisar as ideias para melhorar meu material de aula para o proximo semestre! Mas discordo de um ponto: "O principal motivo para não usar programação orientada a objeto é o tamanho do código gerado. Outro motivo é o fato de se perder um pouco o controle de como o código é gerado e de como a memória é utilizada." Neste caso, esse problema é oriundo da implementação de objetos utilizando o modelo de classes e, principalmente, com alocação dinamica (praticamente um tiro no pé em certos sistemas embarcados) Eu utilizo a orientação a objetos desde muito… Leia mais »

Henrique Frank Werner Puhlmann
Visitante

Caro Mateus, fico feliz que o artigo tenha te inspirado a melhorar o seu material de aula. Talvez tenha faltado de minha parte situar no artigo o contexto da minha afirmação. Eu trabalhei sempre com "firmware" e "bare metal", programando do zero. Quando escrevi o artigo, havia saído uma pesquisa numa das revistas de eletrônica, que leio de vez em quando, exatamente sobre isso. Não é só uma preferência pessoal minha. Muitos profissionais que trabalham com firmware têm essa preferência. Pode ser uma questão de hábito até. Quanto à programação de "middleware" ou de alto nível, aí certamente as preferências… Leia mais »

Mateus Oliveira
Visitante
Mateus Oliveira

Ola Henrique,

Muito grato pela contribuição. Espero, eu, em breve poder tambem contribuir com minhas experiencias. Conheci o site embarcados a pouco tempo, e tenho lido bastante material aqui!

[]s
Mateus

trackback

[…] Boas práticas para o desenvolvimento de software - Parte I […]

trackback

[…] a produtividade na geração e manutenção de software e de qualidade desse software gerado e a primeira parte, onde é abordada a idéia de se desenvolver o software de forma estruturada, porém utilizando […]

trackback

[…] Boas práticas para o desenvolvimento de software - Parte I - É abordada a ideia de desenvolver seu software de forma estruturada, porém utilizando alguns métodos de encapsulamento de dados. […]

Erisson Siqueira
Visitante
Erisson Siqueira

Gostei do artigo, mas discordo com o trecho que diz que GOTO não pode ser utilizado em hipótese alguma pois, pelo menos quando falamos em microcontroladores, o GOTO é utilizado nas principais bibliotecas dos fabricantes como no caso abaixo: [Trecho retirado da biblioteca em_i2c.c da Energy Micro] ... /***********************************/ /* Wait for STOP to have been sent */ /***********************************/ case i2cStateWFStopSent: if (pending & I2C_IF_MSTOP) { i2c->IFC = I2C_IFC_MSTOP; transfer->state = i2cStateDone; } goto done; /******************************/ /* Unexpected state, SW fault */ /******************************/ default: transfer->result = i2cTransferSwFault; transfer->state = i2cStateDone; goto done; } } done: ... Obviamente, seu código é… Leia mais »

Felipe Lavratti
Visitante
Felipe Lavratti

Na minha opinião, GOTO é perdoado se usado apenas em formatos bem estruturados. São geralmente encontrados em códigos baixo nível, por exemplo, em device drivers de linux, onde é usado para fazer retorno com desinicialização condicional da função em caso de erro. Ainda assim, nas camadas longe do hardware, GOTO é péssimo.