[DDD] Specifications são Value Objects?

Gostaria de opiniões sobre minha implementação do padrão Specification, definido no livro de Eric Evans.

Vou usar um exemplo de uma especificacao que define requisitos para criacao de carros:

    public class CarroSpecification {
        private List requisitos;

        public CarroSpecification(List requisitos) {
            this.requisitos = requisitos;
        }

        boolean isSatisfeitaPor(Carro carro) {
            return carro.getCaracteristicas().containsAll(requisitos);
        }
     }

Posteriormente eu refatorei para que além de definir os requisitos a especification criasse um objeto baseado nos requisitos fornecidos e usei o padrão builder. Neste ele lança uma excecao caso os requisitos não sejam suficientes ara a criação de um carro. Ficou algo assim:

    public class CarroSpecification {
        private Map requisitos = null;
        ...

        public CarroSpecification() {
            ...
        }
        
        public CarroSpecification motorizacao(Float valor) {
            this.requisitos.put(MOTORIZACAO, valor);
            return this;
        }
        
        public CarroSpecification cor(Color cor) {
            this.requisitos.put(COR, cor);
            return this;
        }
        
        public CarroSpecification comAr() {
            this.requisitos.put(AR, new Boolean(true));
            return this;
        }
        
        public Carro build() throws IllegalStateException {
            // cria um carro, se possível
        }
        
        public boolean isSatisfeitoPor(ModeloCarro modelo) {
            ...
        }
    }

O que vocês acham? A minha solucao viola o que DDD define como specifications ou é apenas uma specification “um pouco diferente” que perde a caracteristica value object e alem de especificar também cria.

Eu achei essa solucao mais facil para o cliente usar mas gostaria de saber a opiniao dos DDDers de plantao.

[quote=cmoscoso]Gostaria de opiniões sobre minha implementação do padrão Specification
[/quote]

Eu acho que vc está misturando Specification com Builder. São dois padrões diferentes.

Pense em termos reais. Um máquina produz um produto cortado de certa forma. Ela é o builder. Ela constroi o artefacto. Mas ela o faz conforme um conjunto de parametros: a especificação.

Então o seu CarroBuilder é o unico responsável por criar o carro.
Note que o metodo containsAll deixa ao Carro a responsabilidade de verifica a condição e isso não é o objetivo.
A funcionalidade dentro de containsAll deveria estar no specification ou ser um método protegido/de pacote.
O CarroBuilder vai criar um carro. Ele pode fazer isso por ordens directas (interface fluente) ou pela intrepretação de uma especificação. Se vc usa a interface fluente na especificação isso significa que vc não precisa dela, apenas do builder com essa interface.

A ideia é agregar os parametros na especificação, passar ela ao builder, deixar o builder intrepretar a espeficiação.
De tabela deixar a especificação testar se um dado carro atende à especificação. Assim vc pode testar se o builder fez o trabalho como deveria.

Outra coisa, se a especificação é um conjunto de requisitos, eles devem ser objetos tb e não apenas conjuntos num mapa. O seu List requisitos deveria ser List requisitos. Isso é na realidade o padrão Composite, onde vc está montando uma especificação como um conjunto de mini-especificações.

Sergio, obrigado pela resposta.

Foi essa a conclusao que cheguei. Eliminei a specification e mantive apenas o proprio objeto (digamos carro)… Como este é um value object também não é o caso de usar o padrão builder.

Mantive apenas a interface fluente para que os clientes do domain model pudessem criaar esses objetos Carro de uma forma mais, ehhh… “fluente”.

Novamente obrigado.

[quote=sergiotaborda] Outra coisa, se a especificação é um conjunto de requisitos, eles devem ser objetos tb e não apenas conjuntos num mapa. O seu List requisitos deveria ser List requisitos. Isso é na realidade o padrão Composite, onde vc está montando uma especificação como um conjunto de mini-especificações.
[/quote]

Se eu for usar specification eu vou evoluir por esse caminho sim…

Talvez seja util para consultas algo do tipo:

Specification gasolina = new CarroSpecification(GASOLINA);
Specification alcool = new CarroSpecification(ALCOOL);

Specification flex = gasolina.and(alcool);