Princípio da Responsabilidade Única em Firmwares

princípio da responsabilidade única

O princípio da responsabilidade única, do inglês single responsability, defende que cada classe deve ter uma única responsabilidade e que essa responsabilidade deve estar inteiramente encapsulada dentro da classe. É o princípio S da acrônimo mnemônico SOLID que auxilia a programação orientada a objetos (OOP). Embora elaborado para OOP, esse princípio não só pode, mas deve ser aplicado em firmware escrito em C, e a forma de aplicá-lo é através da modularização, onde cada módulo terá a sua única responsabilidade.

 

 

 

Neste artigo é apresentado um template de módulo de firwmare. Se corretamente aplicado, esse template simplifica grandes complexidades em pequenos probleminhas fáceis de solucionar, mas antes de entrar em detalhes sobre a o template em si, é importante enfatizar que a aplicação do princípio da responsabilidade única produz sistemas melhores, pois:

 

  • reduz a complexidade de código;
  • aumenta a legibilidade;
  • evita código espaguete;
  • aumenta a testabilidade;
  • facilita a manutenção e expansão.

 

De fato a lógica é simples, se um módulo foca apenas em resolver um pequeno problema, o código desse módulo está fadado a ser mais robusto e melhor expansível, e, por consequência, o sistema composto por módulos, que obedeçam o princípio da responsabilidade única, também será mais robusto e expansível.

 

Explicando o template  utilizado para o Princípio da Responsabilidade Única 

 

Como em uma classe, o módulo deve ter a parte de alocação de memória, inicialização e desligamento. O gerenciamento de memória fica sob a responsabilidade do usuário (o programador que vai usar seu código). No exemplo abaixo observe que o módulo module_name é usado de duas maneiras, uma onde o objeto é alocado no heap, fazendo uso de malloc e free, e outra na stack, alocando module_name_t diretamente sem usar ponteiro. Entre a inicialização module_name_init e o desligamento module_name_deinit, o exemplo solicita que o objeto efetue uma ação chamando module_name_do. Na verdade, module_name é um módulo vazio que tem o objetivo de ilustrar e fornecer um modelo. Então nenhuma das funções faz algo realmente útil.

 

Exemplo de Uso: main.c

 

 

Interface e Implementação

 

Abaixo encontra-se a interface do module_name e sua implementação, observe que o tipo privado struct s_module_name_private está definido publicamente para que possa ser alocada na stack uma vez que em C não existe uma maneira segura de esconder os membros de estruturas privadas sem impor limitações quanto ao seu uso, entretanto o acesso aos seus membros é proibido, obedecendo assim as regras de abstração.

 

Header: module_name.h

 

 

Source: module_name.c

 

 
 

Aplicando apenas a estrutura de módulo proposta é possível construir sistemas desde os mais simples até os mais complexos.

Implementar uma pequena solução para cada problema simples, fazer isso camada por camada, abstração por abstração, tornar cada módulo facilmente testável, e sempre obedecer o princípio da responsabilidade única até se obter um grande sistema com grande qualidade de código: eis aí uma ótima prática de projeto.

 

Referências

 

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.

2
Deixe um comentário

avatar
 
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Pedro PedruzziMatheus Quick Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Matheus Quick
Visitante
Matheus Quick

Muito bom.

Pedro Pedruzzi
Visitante

Bacana. Isto é OOP em C! Bastante útil quando se quer ter várias instâncias de um módulo ou controlar o ciclo de vida das instâncias. Porém em software embarcado é muito comum que os módulos sejam "singleton" (apenas uma instância global necessária). Nestes casos eu não recomendo seguir este padrão pois seria uma complexidade adicional para pouco ou nenhum benefício. Sobre manter a estrutura privada, pode-se utilizar uma estrutura opaca para alocação em pilha e heap (alocação estática é mais complicado). Você só precisa definir uma função (ou uma constante global se preferir) que retorne o tamanho da estrutura e… Leia mais »