Há muitas respostas na minha pergunta anterior sobre simplicidade relacionada à legibilidade que me ajudaram a ver que minha definição e compreensão da simplicidade no código eram, possivelmente, incorretas.
Como posso definir simplicidade no código? Quais medidas e métricas de software estão disponíveis para medir a simplicidade do código?
code-quality
Richard
fonte
fonte
Respostas:
As métricas mais comuns para medir a complexidade (ou simplicidade, se você considerar a simplicidade o oposto da complexidade) são a Complexidade Ciclomática de McCabe e a Métrica da Complexidade de Halstead .
A complexidade ciclomática mede o número de caminhos distintos através de uma determinada unidade, geralmente um método ou função, embora também possa ser calculado em uma classe. À medida que o número de caminhos aumenta, fica mais difícil lembrar o fluxo de dados através de um determinado módulo, que está relacionado ao conceito de memória de trabalho . A alta complexidade ciclomática tende a indicar dificuldade na capacidade de testar um módulo - são necessários mais casos de teste para cobrir os vários caminhos do sistema. Também houve estudos que associaram alta complexidade ciclomática a altas taxas de defeitos. Normalmente, uma complexidade ciclomática de 10 indica que uma unidade deve ser revisada e possivelmente refatorada.
As medidas de complexidade de Halstead usam as entradas de operadores e operandos totais e distintos para calcular o volume, a dificuldade e o esforço de um pedaço de código. A dificuldade, que é o (número de operadores únicos / 2) * (número total de operandos / número de operandos únicos), está ligada à capacidade de ler e entender o código para tarefas como aprender o sistema ou executar uma revisão de código. Novamente, você pode contar isso no nível do sistema, no nível da classe ou no nível do método / função. Existem algumas publicações sobre o cálculo dessas medidas aqui e aqui .
Simplesmente contar linhas de código também pode lhe dar uma idéia da complexidade. Mais linhas de código significa que há mais para ler e entender em um módulo. Eu hesitaria em usar isso como uma medida independente. Em vez disso, eu o usaria com outras medidas, como o número de defeitos em um determinado módulo para obter a densidade do defeito. Uma alta densidade de defeitos pode indicar problemas ao escrever testes e executar revisões de código, que podem ou não ser causadas por códigos complexos.
Fan-in e fan-out são outras duas métricas, relacionadas ao fluxo de dados. Conforme definido aqui , fan in é a soma dos procedimentos chamados, parâmetros lidos e variáveis globais lidas e fan out é a soma dos procedimentos que chamam um determinado procedimento, parâmetros gravados (expostos a usuários externos, passados por referência), e variáveis globais gravadas em. Novamente, a alta entrada e saída de ventiladores pode ser um indicativo de um módulo que pode ser difícil de entender.
Em paradigmas específicos, pode haver outras medidas ou métricas também úteis. Por exemplo, no mundo orientado a objetos, o monitoramento do acoplamento (desejo baixo), coesão (desejo alto) e profundidade da herança (desejo baixo) pode ser usado para avaliar o quão simples ou complicado é um sistema.
Obviamente, é importante perceber que muitas medidas e métricas são simplesmente indicadores. Você precisa usar seu julgamento para determinar se é necessário refatorar para aumentar a simplicidade ou se não vale a pena o esforço para fazê-lo. Você pode fazer as medições, calcular as métricas e aprender sobre seu código, mas não deseja projetar seu sistema pelos números. Por fim, faça o que faz sentido.
fonte
Em vez de olhar para um modo formal de definir simplicidade, eu gostaria de definir a simplicidade como um atributo da qualidade da escrita de código.
Não estou colocando um pouco de simplicidade, mas quando você chama algo simples ou não.
1. Code Traversal:
como é fácil navegar pelo código? É fácil identificar onde as funções da API estão gravadas? É fácil entender os fluxos de chamadas, por exemplo, quais métodos estão chamando outras pessoas (e por que) - existem boas máquinas de estado implementadas ou algoritmos identificados de maneira limpa?
Quando a passagem do código é fácil, é fácil seguir o código .
2. Nomeação
Embora outros padrões de codificação ajudem a tornar o código mais limpo - o mais importante é a nomeação de classes / instâncias de objetos / Variáveis / métodos. O uso de nomes claros e inequívocos tem claramente um grande impacto na simplicidade do código. Quando é difícil identificar um nome simples, é um sinal de que você pode repensar a ideia de ser essa variável / método.
3. Interpretação e referências
Cada um dos seus métodos tem um papel claro a desempenhar. Cada variável / atributo é fácil de determinar o papel que está desempenhando? Quando um pedaço de código faz algo que implica suposições ou afeta um conjunto de variáveis não relacionadas, pode se tornar um pesadelo de manutenção.
4. Dependência ou acoplamento
É difícil julgar apenas olhando o código, mas fica muito evidente se alguém tentar corrigir seus erros. Quando algumas outras coisas mudam em outro objeto, a operação aqui muda? Essas mudanças são óbvias? Você precisa alterar a API com tanta frequência para acomodar coisas. Isso sugere que as relações entre módulos não são simples
5. Insere usuário ou aplicativos
Finalmente, quão simples são as entradas de usuário ou aplicativo são aceitas na API / UI? Quando vários usuários / aplicativos possíveis (para diferentes propósitos) precisam fornecer a você - eles são óbvios? Existem estados / detalhes que não estão relacionados à abstração mais alta, mas ainda vão e voltam à interface?
Uma pergunta simples que eu geralmente faria é a seguinte: Se em vez de um programa, se eu pedisse a mesma função a ser desempenhada por um humano, eu teria preenchido essas informações em um formulário em papel ? Caso contrário, não sou simples o suficiente aqui.
Não direi que esta lista é completa, mas acho que critérios são o quão fácil ou difícil é usar e modificar o software. Isso é simples.
fonte
Não conheço nenhuma boa métrica existente para simplicidade de código (isso não significa que elas não existem - apenas que eu não as conheço). Eu poderia propor alguns, talvez alguns ajudem:
Simplicidade dos recursos de idioma utilizados: se o idioma tiver recursos que possam ser considerados "avançados" e "simples", você poderá contar o número de ocorrências dos recursos avançados. Como você define "avançado" pode ser um pouco mais subjetivo. Suponho que alguns possam dizer que isso também é como medir a "inteligência" de um programa. Um exemplo comum: alguns podem dizer que o
?:
operador deve ser um recurso "avançado", outros podem discordar. Não sei como seria fácil escrever uma ferramenta que possa testar isso.Simplicidade de construções no programa: Você pode medir o número de parâmetros que uma função aceitará. Se você tiver> n % de todas as funções com parâmetros > m , poderá optar por considerá-lo como não simples, dependendo de como definir n e m (talvez n = 3 e m = 6?). Acho que existem algumas ferramentas de análise estática que podem medir isso - acho que o JTest simplesmente mediu funções com parâmetros > m .
Você pode tentar contar o número de loops aninhados ou estruturas de controle. Na verdade, acho que isso não é uma métrica ruim e acho que existe um nome para ela (não me lembro bem). Mais uma vez, acho que existem ferramentas (mais uma vez, como o JTest) que podem medir isso, até certo ponto.
Você pode tentar medir a "refatorabilidade". Se o seu código contiver muitos trechos de código que poderiam ser refatorados, mas não são , talvez isso não fosse simples. Também me lembro, desde o tempo em que trabalhei com o JTest, que ele também tentava medir isso, mas lembro que não concordei com isso nesse caso, então YMMV.
Você pode tentar medir o número de camadas entre diferentes partes do seu sistema. Por exemplo: quantas partes de código diferentes tocam nos dados provenientes de um formulário da Web antes de serem armazenados no banco de dados? Pode ser complicado medir adequadamente ...
fonte
?:
são um problema quando estão aninhadas a 5 profundidade. Quanto às camadas, as camadas separadas de maneira limpa são melhores que uma camada complicada. Mas 7 camadas principalmente redundantes, quando apenas 2 ou 3 eram necessárias, é uma coisa ruim.