Pergunta

Esta é uma daquelas situações em que "paralisia por análise" parece ter tomado conta tão conselho por favor!

O projeto

Uma lista bastante simples de produtos automotivos que incluem detalhes como referência da peça, que veículos eles se encaixam etc.

A extremidade dianteira é uma aplicação MVC asp.net.

A infra-estrutura é SQL, usando Subsonic para projetar os produtos em objetos de domínio.

Funcionalidade

Uma das nossas telas é uma tela de detalhes do produto. Um ASP.NET MVC controlador chama o repositório do produto para recuperar os detalhes do produto, retorna esses detalhes (através de algum mapeamento automático a um ViewModel) à vista.

Agora, o detalhe assassino é que temos dois ou três canais na web site, dependendo do canal, o usuário precisa ver diferentes números de peça.

Vamos dizer, por exemplo, se é o canal de varejo, em seguida, os números de peça são como são no banco de dados, mas se o usuário chegou ao site através do canal do Comércio, o início da referência da peça é substituído com números alternativos.

por exemplo. 0900876 se visto através do canal de Trade torna-se 1.700.876.

Onde eu estou lutando é para decidir onde para encapsular as "regras do Canal" em relação a referências de peças (e outros detalhes que podem alterar).

Eu considerei essas alternativas.

Escrever a lógica diretamente no objeto de domínio

No produtos classe poderíamos ter um método / propriedade para obter a referência da peça traduzido.

public string TranslatedPartRef()
    {
        if (this.Channel == "Trade")
        {
            return PartRef.Replace("0900", "1700");
        }
        else
        {
            return PartRef;
        }
    }      

Neste cenário, a instância do produto deve saber sobre o canal, o que parece errado para mim.

encapsular a lógica em outro objeto

Poderíamos escrever uma classe para lidar com esta tradução referência da peça, ou criar um Canal classe que contém essa lógica.

O que eu não entendo, porém, é como se, em seguida, coordenar as duas classes.

Se o controlador chama o repositório para recuperar o Produto, deve-o, em seguida, descobrir o que canal foi utilizado e traduzir a referência da peça? Se assim como eu, em seguida, enviar o produto com ele é traduzido de volta referência parte à vista?

Também é importante notar que esta referência parte tem que aparecer nos resultados de busca e outros cenários, bem como, por essa razão eu acho que precisa ser ordenadamente contido dentro do lugar de domínio.

Foi útil?

Solução

Eu não sou um cara de C #, mas eu iria atacar isso com um Decorator em Java, eu acho.

Supondo que você tenha uma interface para o produto, então você pode criar um decorador que administra a questão número da peça.

class Product implements IProduct {
    public String getProductCode();
    // etc
}

class ProductChannelDecorator implements IProduct
{
    // constructor, like this in C#?
    public ProductChannelDecorator(IProduct product, Channel channel) { 
        this.product = product;
        this.channel = channel;
    }
    public String getProductCode() {
        switch (this.channel) {
            case Channel.RETAIL:
                return this.decorated.getProductCode();
            case Channel.TRADE:
                return retailToTradeTransformer(this.product.getProductCode());
            // etc
        }
    }
    // etc
}

Outras dicas

A primeira pergunta que você precisa perguntar é se o conceito de um canal é um conceito de domínio ou não. Sua pergunta parece indicar que não é, mas por outro lado, eu não acho que soa específico do aplicativo também.

Uma questão adicional que você poderia fazer é: se, no futuro, eu preciso construir um outro aplicativo sobre este modelo de domínio (por exemplo, um serviço web ou um cliente rico), eu ainda precisa lidar com o conceito de um canal?

Meu palpite é que a resposta pode ser Sim .

Tanto quanto eu entendi sua pergunta, o Canal está relacionado com o contexto de solicitação de alguma forma. Talvez seja realmente um atributo do usuário. Ou talvez em um atributo da própria configuração do aplicativo.

Em qualquer caso, eu iria pensar muito sobre se ele não é realmente um conceito de domínio depois de tudo. Se for, então ele poderia pertencer muito bem em um objeto de domínio.

Se não, a implementação Decorator sugerido por sons ptomli como uma boa abordagem.

Como muitos varients diferentes de número de peça haveria. Se é apenas Trade v Retail eu ficaria muito tentado a simplesmente ter ambos os números no objeto de Produto, e ter a interface do usuário decidir qual exibir. Ao deliberar sobre produto a identidade pode ser "tipo {Trade, Varejo}, number".

Para o modo algo flexível eu acho que é a sua ideia Canal está bem. Mas se ele tinha responsabilidades bi-direcionais, mapeamento de varejo de e para o comércio, isto parece trabalho. O objecto con Canal ser visto como um adaptador, capaz de outras transformações e enriquecimentos.

Como uma implementação eu estaria criando um objeto Canal separado para cada canal, tentando evitar declarações de caso e se a lógica outra pessoa. Para Retail o objeto Canal poderia ser um objeto NOOP do Comércio que pode fazer teh mapeamentos. A fábrica pode creat o objeto Canal approporaye.

E se o mapeamento número de peça poderia mudar? Agora é um prefixo que muda, mas poderia haver outros tipos de mudanças que você tem que atender a? Talvez você não precisa disso, mas:

Ao nível empresarial, você está dizendo que um produto pode ter diferentes números de peça, dependendo do canal (que é, afinal, um conceito de negócio fundamental). Assim que sugere que, no nível de banco de dados, poderia haver uma em algum lugar da tabela PartNumber que tem colunas ProductID, channelId e partNumber. Isso certamente vai cobrir o caso em que mais canais aparecem ao longo do tempo (hoje de varejo ou Trade, amanhã eles podem adicionar Web, Mail-Order etc. tudo o que concebivelmente poderia querer diferentes números de peça).

Ao nível do objeto, este mapas para uma instância Product tendo um Dictionary<Channel, PartNumber> que pode ser usado para obter o número de peça apropriada dado um Channel.

Agora, o detalhe assassino é que temos dois ou três canais na web site, dependendo do canal, o usuário precisa ver diferentes números de peça.

Uma solução para a frente:

public interface IChannel
    function GetNumber(Part as IPart) as String
end interface

Não decoradores, sem opções, nenhuma inversão de controle.

Cada vez que você precisar de número de peça para um canal específico você chamar esse método.

dim Channel as IChannel = ...
dim Part as IPart = ...
dim PartNumber = Channel.GetNumber(Part)

Cada vez que você precisa de um método número da peça cálculo diferente você simplesmente implementar essa interface.

public class TradeChannel
    implements IChannel

    public function GetNumber(Part as IPart) as String implements IChannel.GetNumber
        return Part.Number.Replace("0900", "1700")
    end function
end class
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top