Sintaxe e Semântica
Tudo na vida possui forma e conteúdo. Mas um bom conteúdo com forma ruim é problema, e uma forma bacana com conteúdo ruim, pior ainda.
Projetar software é lidar com isso toda hora. Modelos, especificações, código: precisam de uma boa forma (sintaxe) e um bom conteúdo (semântica). Entender como ter qualidade na sintaxe e na semântica é fundamental!
Na Engenharia de Software quando falamos de sintaxe geralmente nos referimos à forma de escrever código fonte (palavras reservadas, comandos, recursos diversos).
Aprendemos na escola que sintaxe é algo sobre regras para escrever em linguagem natural na produção de textos, então é natural tal “analogia”; mas é pobre.
No mundo escrevemos de vários “jeitos”, seja em linguagem natural numa redação, em linguagem matemática na física, em linguagem de símbolos na química, em linguagem de programação na engenharia de software etc.
No contexto de “textos” (analisando filosoficamente) sintaxe (com suas regras, premissas e restrições) é a forma, a estrutura, a estética do texto. Idem para código fonte no contexto de uma linguagem de programação, idem para um diagrama da UML no projeto de um sistema.
Quando ampliamos a visão sobre sintaxe na Engenharia de Software deixamos de aplica-la somente em modelos de código fonte, pois outros modelos também possuem formas, estruturas etc.
E para os outros modelos (requisitos, casos de uso por exemplo), também existem regras, premissas e restrições para o que é produzido.
Quanto à semântica, de um modo geral é o estudo do significado das coisas (do conteúdo das “formas”). Na Engenharia de Software, quando falamos de semântica nos referimos ao significado dos modelos, ao nível de entendimento (clareza, objetividade, detalhamento, coesão etc.) de alguma coisa.
Por exemplo: uma redação bem escrita (sem erros de concordância, gramática etc.), mas com um texto ruim (sem contexto, sem início/meio/fim, com uma estória confusa) possui boa “sintaxe”, mas uma “semântica” ruim.
Exemplificando
Consideremos três frases: 1) um mais um é igual a dois, 2) one plus one equals two, 3) 1 + 1 = 2. Temos três frases escritas de formas diferentes, mas três frases que dizem a mesma coisa.
A seguir, três exemplos do famoso “Hello World”, escrito em três linguagens de programação diferentes (C#, Object Pascal e Haskell):
/* C# */
class HelloWorld
{ static void Main() { System.Console.WriteLine(“Hello, World!”); } }
// Object Pascal
program HelloWorld(output);
begin WriteLn(‘Hello World!’); end
— Haskell
main = putStrLn “Hello World”
Os três algoritmos realizam a mesma coisa, que é exibir um “Hello World” na tela, mas estão escritos de formas diferentes.
Nos exemplos das frases o significado do que foi descrito de três formas diferentes é: ao somar um mais um, o resultado é dois. Nos exemplos do código fonte o significado do que foi descrito em C#, Object Pascal e Haskell é: exibir na tela um “Hello World”. O significado é a semântica e a forma é a sintaxe.
/* em tudo, sintaxe não existe sem semântica, nem semântica existe sem sintaxe. Em qualquer área de conhecimento é necessário dar forma a um conteúdo, pois uma forma sem conteúdo é um contrassenso pois o vazio não existe; e um conteúdo sem forma é um abstrato absoluto, também sendo um contrassenso pois qualquer tipo de matéria está no espaço. É filosófico, mas se aplica no contexto que estamos discutindo, basta quebrar um pouco a cabeça (para os que não entenderam facilmente) */
Em projetos de software é fundamental entender a diferença entre os dois conceitos. Um artefato com sintaxe ótima, mas com semântica péssima não serve para nada (até serve, para causar estragos no projeto).
É como um profissional que se expressa muito bem, tem excelente oratória, mas não sabe do que fala, usando do talento “no verbo”, mas pecando forte no conteúdo que está verbalizando.
Ou seja, um excelente formato com um péssimo conteúdo não gera valor, apenas subtrai valor. É como um sistema com um lindo front-end (interface do usuário), mas cheio de bugs em suas funcionalidades.
Na mesma linha de pensamento, um artefato com semântica ótima e sintaxe péssima geralmente serve para deixar o analista maluco, pois este sabe que o conteúdo deve estar certo, mas se perde na bagunça especificada.
É como o profissional que entende muito de algo, mas não sabe se expressar com fluência, acaba querendo dizer uma coisa, mas dando a entender outra. Ou seja, um excelente conteúdo com um péssimo formato, gera pouco valor, e também subtrai valor.
Mais alguns exemplos
Vejamos um exemplo de código fonte.
Temos um método, que possui o objetivo de somar dois valores e retornar o resultado desta soma. Este método foi criado para somar o resultado de vendas de uma quinzena, e recebe como parâmetros de entrada o resultado da semana anterior, e o resultado da semana atual.
A seguir, o método escrito e funcional, mas com uma sintaxe terrível, e uma semântica boa (pois deixa claro que realiza a soma, e faz o que tem que ser feito).
public int M0998_Sma(int M0998_1, int M0998_2)
{
return M0998_1 + M0998_2;
}
O método acima realizará a soma, e retornará o resultado esperado. Mas é possível entender o que este método quer dizer? Se o programador que o escreveu sair da empresa, imaginem a dificuldade que a equipe terá para entender o que um método escrito assim faz, e dar manutenção no código!
Vejamos agora um outro método, que atende ao mesmo objetivo, mas tando do ponto de vista de forma e conteúdo (sintaxe e semântica) está bem escrito:
public int somaResultadoQuinzena (int aValorSemanaAnterior, int avalorSemanaAtual)
{
int resultadoQuinzena = aValorSemanaAnterior + avalorSemanaAtual;
return resultadoQuinzena;
}
É outra coisa não?
Vejamos agora a sintaxe e a semântica aplicadas a um requisito não funcional.
Requisito Não funcional com sintaxe boa e semântica ruim
O requisito não funcional a seguir possui uma boa sintaxe: está bem escrito, bem organizado. Mas seu conteúdo demanda revisão, sua semântica não está boa.
O nome do requisito é “Gravação de log de operações”. Entende-se que operações realizadas no sistema deverão ser logadas. Mas logadas para qual fim? Quais os tipos de operações deverão ser logadas? Estas perguntas demonstram que o nome utilizado não está bom, porque não deixa claro o que realmente o RNF deve realizar.
No nosso contexto, as operações que deverão ser logadas são operações de Inclusão, Alteração e Exclusão de registro apenas, e o log deve ter finalidade de prover dados para auditoria. E quanto ao formato do log, qual será? Logs podem ser gravados em várias saídas diferentes: banco de dados, logs de eventos de sistema operacional (como o Event Viewer do Windows), arquivo texto, arquivo XML etc. Ainda no nosso contexto, vamos considerar que o log será gravado em banco de dados, apenas.
Considerando a reflexão acima, o nome adequado do RNF005 é: “Gravação de log de operações de inserção/alteração/exclusão de registro em banco de dados”.
Com este nome, ao ver este RNF numa lista de requisitos não funcionais fica claro do que ele se trata de fato.
Quanto à descrição do requisito – “Deverão ser gravados logs de todas as operações efetuadas no sistema” – as mesmas perguntas aplicadas ao nome também se aplicam.
A descrição também demanda a mesma reflexão. Mas somente as respostas às dúvidas colocadas não são suficientes; já ficou claro que apenas logs de operações de inserção/alteração/exclusão de registros deverão ser logadas, e logadas em banco de dados. Mas como serão logadas? E quais dados destas operações precisam de ser logados? E haverá auditoria automática, através de mágica ou do atendimento a alguma funcionalidade ou novo requisito não funcional?
/* uma premissa para avaliação da qualidade de um artefato de especificação é, ao analisa-lo, perceber se existem dúvidas acerca do seu propósito e conteúdo. Se houver dúvidas tem algo que precisa ser revisado. Requisitos Funcionais, Requisitos Não funcionais e Regras de Negócio não podem gerar dúvidas, pois se assim o for, o sistema terá defeito. Claro que na prática sabemos que muita coisa “passa batido” e ao longo do ciclo de vida do projeto o ajuste de escopo é feito, mas se um bom trabalho for realizado em “tempo de especificação”, a quantidade de ajustes posteriores diminui muito, muito mesmo. */
Precisamos esclarecer tudo isso na especificação do RNF. Considerando o resultado da reflexão, a descrição adequada do requisito segue abaixo:
Para todas as operações de Inserção, Alteração e Exclusão de registros no sistema, o sistema deverá gravar um log em banco de dados contendo as informações abaixo:
– Usuário logado no sistema, que efetuou a operação.
– Versão do sistema.
– Data/hora que a operação foi efetuada.Todas as tabelas do banco de dados do sistema deverão possui três campos, para atender à necessidade apresentada. Abaixo segue o formato de cada um dos três campos (descrição, nome do campo/coluna, tipo de dado, obrigatoriedade):
– Usuário logado/USUARIO_LOGADO/varchar(30)/obrigatório.
– Versão do sistema/VERSÃO_SISTEMA/varchar(10)/obrigatório.
– Data hora operação/DATA_HORA_OPERACAO /Datetime/obrigatório.Obs.: o objetivo é que as informações gravadas possam ser utilizadas para auditoria. Não está no escopo deste requisito a forma como as informações gravadas serão consultadas, apenas a gravação delas.
Considerando a revisão do nome e da descrição do RNF005, temos então uma nova versão deste RNF com a especificação abaixo:
Concluindo
É fundamental termos modelos no projeto do software com boa sintaxe e boa semântica. É importante sempre lembrarmos que fazemos software para outros manterem, e outros usarem.
Em função disso, buscar qualidade na produção dos artefatos é uma questão até mesmo de ética.
Se você gostou do conteúdo deste post, deixe seus comentários, para ajudar outras pessoas a encontrarem este material! 🙂
Abraço!