Se você gerar um diagrama no Entity Framework, ele vai gerar as classes para você. Estas classes são geradas automaticamente pela ferramenta. Se você alterá-las diretamente, não vai poder regerar ou alterar o diagrama, porque isso alteraria o código gerado. Ou seja, não pode mais alterar o diagrama em nada. Esse é o motivo que impede o EF de funcionar com os atributos do Validation Application Block do Enterprise Library: atributos alterariam o código e você perderia tudo se fizesse qualquer alteração no modelo do EF.

Esse padrão é comum em qualquer código gerado por ferramenta: se você alterar o código gerado não pode mais usar a ferrramenta para atualizar o código, ou vai perder tudo. Nos datasets tipados já era assim. Por isso a Microsoft inventou o conceito de partial classes, que é bem legal e ajudou bastante. Elas oferecem hooks, ganchos, para você se plugar nelas de fora. Assim, você tem uma classe para o designer, e outra para você trabalhar e estender.

Só que com classes parciais não dá para aplicar atributos em propriedades ou métodos. Aí eles inventaram as buddy classes, que apareceram pela primeira vez no ADO.Net Dynamic Data, e agora estão aparecendo no RIA Services, conforme fiquei sabendo neste blog.

Buddy classes são o seguinte: já que você não pode alterar o atributo de uma propriedade, nós te arranjamos uma outra classe, que é “amiga” daquela que você queria alterar. Lá você aplica seus atributos, e depois o framework junta tudo, entendendo que o atributo que você aplicou na classe amiga (buddy), era na verdade para aplicar na classe auto-gerada. A classe amiga não serve para nada além de ser a classe a que você vai decorar com seus atributos, já que a classe principal é gerada por uma ferramenta.

Um exemplo, esta seria sua classe auto-gerada:

    public partial class MyClass
    {
      public int MyProperty { get; set; }
    }

Como aplicar um atributo sobre esta propriedade “MyProperty”?

São dois passos: primeiro você aplica um atributo em uma classe parcial, que indica quem é sua classe “amiga”, o tal MetadataClass:

    [MetadataClass(typeof(MyMetadataClass))]
    public partial class MyClass { }

E depois basta criar a propriedade igualzinha à da classe original e aplicar o atributo nesta outra classe:

    public class MyMetadataClass
    {
      [RangeValidator(1,100)]
      public int MyProperty{ get; set; }
    }

Simples, não é?

Agora faça isso 10 vezes para cada uma das suas 30 classes de negócio. Dá umas 300 vezes. Depois refatore tudo. Parece divertido, não é?

Na prática, este esforço quase elimina o fato de você ter um designer visual para te ajudar. Se eu estou utilizando um designer visual, eu quero que ele me ajude a fazer o código, não quero que eu precise recodificar tudo de novo. Além disso, se eu mudar o nome de uma propriedade, vou ter que alterar também na classe amiga. O mesmo vale para qualquer outra refatoração, como mover propriedades entre classes.

Isso viola violentamente o pricípio DRY, que diz que você não deve se repetir. E está na cara que com buddy classes vamos nos repetir bastante, não é?

A grande questão é: como ter o melhor dos dois mundos, ou seja, ter a geração de código funcionando bem, mas ainda assim permitir estensibilidade matendo bons princípios, como o DRY. Isso é algo muito difícil de fazer, e acredito que é um dos motivos que frameworks como o NHibernate até hoje não fizeram designers visuais: eles teriam que gerar código, e isso sempre é complicado, porque qualquer código gerado seria muito criticado.

Ainda há a possibilidade de colocar a validação de forma externa, utilizando XMLs de configuração por exemplo. Mas isso é separar responsabilidades que deveriam estar na classe. Está longe do ideal…

Eu tenho um certo pós-conceito com código gerado por ferramentas. Já fui impactado diretamente mais de uma vez, onde o projeto engessava por causa deste tipo de “ajuda”. O que vocês acham? Esse problema tem solução?

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.