10 Junho, 2012 0 Comentários AUTOR: elemarjr CATEGORIAS: Sem categoria Etiquetas:, ,

SNIPPET: Pensando na melhor maneira de relacionar os 10 métodos com maior CC usando FluentCodeMetrics

Tempo de leitura: Menos de um minuto

Olá pessoal. Tudo certo?!

Posts “snippet” vão mostrar apenas trechos curtos de código com algumas questões (dúvidas) relacionadas. A idéia é “parear” mais com vocês.

Considerem:

var topComplexMethods =
   (from type in Assembly.GetExecutingAssembly().GetTypes()
    from m in type.GetMethods()
    where m.IsPublic && !m.IsAbstract
    let entry = new {Method = m, Cc = Cc.For(m)}
    orderby entry.Cc descending
    select entry).Take(10);

O Snippet relaciona os 10 métodos com maior complexidade ciclomática em meu código usando LINQ e FluentCodeMetrics.

Do que eu não gosto?!

  • as três primeiras linhas (da consulta) servem apenas determinar um escopo – parece código demais e tenho sensação que “escopo de consulta” deveria ser algo “built-in” na FluentCodeMetrics;
  • a quarta linha é uma construção para um retorno “refinado” – pela frequência de uso, também me parece que deveria ser built-in;

Enfim, FluentCodeMetrics está sendo desenvolvida “aos poucos”. Em cada entrega, refino o design.  Por isso, me diga:

  1. o que você não gosta nesse código?
  2. concorda com minhas observações?

Era isso.

Let’s design. Let’s code. Let’s rock.

0 Comentários

  1. oenning 4 anos ago says:

    Olá Elemar,

    Uma das características que mais gosto no TDD é que o design do SUT é modelado do ponto de vista do usuário (o teste neste caso). Isso normalmente resulta em um design bem limpo.

    Partindo desta ideia, eu, como usuário, gostaria de escrever algo assim:

    (from t in CurrentAssembly.Types
    from m in t.Methods
    where m.Cc > 5
    orderby m.Cc descending
    select m).Take(10);

    Agora respondendo aos seus questionamentos:

    1) Não gosto do CC.For(). O usuário teria que ler uma documentação para conhecer todas as possíveis métricas de um método, tipo ou assembly. Do modo que se o próprio método tivesse uma propriedade/método para cada métrica, tornaria a utilização do FCM muito mais fácil para quem está começando.

    Também não gostei da utilização cláusula let em conjunto com a classe anônima. Acredito que alterando o tipo de dado retornado no IQueryable vai remover a necessidade desta instrução e deixar a utilização mais fluente. Este item complementa o outro ponto que citei acima. Penso em um "wrapper" para o MethodInfo/Type onde haveriam estas propriedades, algo específico para a API de consulta.

    2) Com o primeiro eu concordo, afinal foi o que eu comentei acima. Agora com o segundo ponto eu não tenho tanta certeza. Se o filtro padrão fosse ignorar métodos não-públicos e abstratos, ao tentarmos fazer algo como t.Methods.Count estaríamos retornando um valor incorreto. Penso que retornar tudo e deixar o usuário filtrar seja a melhor opção mesmo. Ou talvez definir alguns "shortcuts" como t.PublicMethods.

    Responder
    • elemarjr 4 anos ago says:

      Concordo com todas as observações.

      Pelo que eu notei, você defende a criação de um modelo de objetos alternativo (independente de Reflection e Cecil) para representar as primitivas de trabalho (classes, métodos, namespaces, whatever?!) .. Estava pensando nisso outro dia..

      Entendi certo?!

      Responder
  2. oenning 4 anos ago says:

    Isso mesmo. Este é a primeira vez que uso o Cecil, mas pelo que eu percebi é o que ele faz com o TypeDefinition, MethodDefinition e AssemblyDefinition.

    Com um modelo de objetos próprio é possível construir uma interface limpa sem ter que poluir os tipos padrões com métodos de extensão.

    Responder
    • elemarjr 4 anos ago says:

      Cecil vai um pouco mais longe. Ele lê/salva IL direto de arquivos .EXE/.DLL

      Entendi o que você está indicando e começo a pensar da mesma maneira.

      Responder