Pergunta

Onde eu trabalho, voltamos e voltamos sobre esse assunto várias vezes e estamos procurando uma verificação de sanidade. Aqui está a pergunta: os objetos de negócios devem ser contêineres de dados (mais parecidos com DTOs) ou também devem conter a lógica que pode executar alguma funcionalidade nesse objeto.

Exemplo - Pegue um objeto de cliente, provavelmente contém algumas propriedades comuns (nome, ID, etc.), esse objeto do cliente também inclui funções (salvar, calc, etc.)?

Uma linha de raciocínio diz separar o objeto da funcionalidade (principal de responsabilidade única) e colocar a funcionalidade em uma camada ou objeto lógica de negócios.

A outra linha de raciocínio diz, não, se eu tiver um objeto de cliente, eu só quero ligar para o cliente.Save e terminar com ele. Por que preciso saber como salvar um cliente se estou consumindo o objeto?

Nossos dois últimos projetos tiveram os objetos separados da funcionalidade, mas o debate foi levantado novamente em um novo projeto. O que faz mais sentido?

EDITAR

Esses resultados são muito semelhantes aos nossos debates. Um voto para um lado ou outro muda completamente a direção. Alguém mais quer adicionar seus 2 centavos?

EDITAR

Embora a amostragem de resposta seja pequena, parece que a maioria acredita que a funcionalidade em um objeto de negócios é aceitável, desde que seja simples, mas a persistência é melhor colocada em uma classe/camada separada. Vamos tentar isso. Obrigado pela contribuição de todos ...

Foi útil?

Solução

Objetos são estado e comportamento juntos. Se um objeto tiver um comportamento sensato (por exemplo, calcular a idade de uma pessoa a partir da data de nascimento ou um imposto total para uma fatura), adicione -o. Objetos de negócios que nada mais são do que DTOs são denominados "modelo de domínio anêmico". Eu não acho que seja um requisito de design.

A persistência é um tipo especial de comportamento. O que estou chamando de "sensato" é o comportamento dos negócios. Um objeto de negócios não precisa saber que é persistente. Eu diria que um DAO pode manter a persistência separada do comportamento comercial. Não coloco "salvar" na categoria "sensível".

Outras dicas

Objetos de negócios Podem ter funcionalidade comercial.

Persistência não é uma funcionalidade comercial , mas é implementação técnica.

Longa história curta:

  1. Salvar/atualizar/excluir/encontrar etc - mantenha -se longe dos objetos de negócios em uma camada de persistência.
  2. Calculações, ApplyDiscount etc são métodos relacionados a negócios e podem ser:
    1. Métodos dos objetos de negócios (Então Bo é representação independente da entidade) ou;
    2. serviços separados Implementando funcionalidade específica (então as Bos estão agindo mais como DTOs).

Quanto ao ponto 2.
Devo mencionar que a abordagem 2.1 tende a tornar os bos muito inchados e Violar SRP. Enquanto 2.2 apresenta mais manutenção complexidade.

Eu geralmente Saldo Entre 2.1 e 2.2, para que eu coloque coisas triviais relacionadas aos dados em objetos de negócios e crie serviços para um cenário um pouco mais complexo (se houver mais de 4 linhas de código - faça dele um serviço).

Isso muda o paradigma dos objetos de negócios para serem mais objetos de transferência de dados.

Mas tudo isso facilita o desenvolvimento do projeto, teste e manutenção.

A resposta é a mesma, independentemente da plataforma ou idioma. A chave para esta questão é se um objeto deve ser capaz de ser Autônomo ou se é melhor que um determinado comportamento seja espalhado entre objetos com mais responsabilidade focada.

Para cada classe, a resposta pode ser diferente. Acabamos com um espectro ao longo do qual podemos colocar classes com base no Densidade de responsabilidade.

                          (Level of responsibility for behavior)
         Autonomy - - - - - - - - - - - - - - - - - - - Dependence  
      High
  C      -   <<GOD object>>                            <<Spaghetti code>>
  l      -
  a      -  
  s      -                                      
  s      -                 
         -                        
  s      -  
  i      -  
  z      -
  e      -  <<Template>>                                <<Framework>>
       low  

Digamos que você seja a favor de deixar a classe executar todos os comportamentos em si, ou o máximo possível. Começando no lado esquerdo deste gráfico, quando você torna sua classe mais autônoma, o tamanho da classe crescerá, a menos que você o refatore continuamente para torná -lo mais genérico. Isso leva a um modelo. Se nenhuma refatoração estiver feita, a temperatura é que a classe se torne mais "como Deus"Porque se houver algum comportamento necessário, ele tem um método para isso. O número de campos e métodos cresce e logo se torna incontrolável e inevitável. Como a classe já faz muito, os codificadores preferem aumentar a monstruosidade do que tentar tentar separe -o e corte o nó Gordiano.

O lado direito do gráfico tem classes que dependem de outras classes em grande parte. Se o nível de dependência for alto, mas a classe individual é pequena, isso é um sinal de um estrutura; Cada classe não faz muito e requer muitas classes dependentes para cumprir alguma função. Por outro lado, uma classe altamente dependente que também tem uma grande quantidade de código é um sinal de que a classe está cheia de Espaguete.

A chave para esta questão é determinar onde você se sente mais confortável no gráfico. De qualquer forma, as classes individuais acabarão se espalhando no gráfico, a menos que algum princípio organizacional seja aplicado, e é assim que você pode alcançar os resultados de Modelo ou Estrutura.

Tendo acabado de escrever isso, eu diria que há uma correlação entre o tamanho da classe e o grau de organização. Robert C. Martin (ou "tio Bob") cobre um terreno semelhante com dependências de pacotes em seu artigo muito completo sobre Princípios de design e padrões de design. JDepend é uma implementação das idéias por trás do gráfico na página 26 e complementos Ferramentas de análise estática tal como Checkstyle e PMD.

Eu acho que faz mais sentido para os objetos de negócios saber como "lidar com" a si mesmos, depois ter que colocar esse fardo em outras partes do sistema. No seu exemplo, o local mais lógico para lidar com como "salvar" os dados do cliente seria, para mim, no objeto do cliente.

Isso pode ser porque considero o banco de dados o "contêiner de dados", por isso sou a favor de "objetos de negócios" sendo o nível superior que protege o contêiner de dados do acesso direto e aplica "regras de negócios" padrão sobre como esses dados é acessado/manipulado.

Usamos a estrutura CSLA da Rocky Lhotka há anos e amamos a maneira como ela foi projetada. Nessa estrutura, toda a funcionalidade está contida nos objetos. Embora eu possa ver o valor de separar a lógica, acho que não mudaremos dessa filosofia em breve.

Os objetos de negócios devem ser sobre a encapsulação de dados e comportamentos associados da entidade comercial modelada por esse objeto. Pense assim: um dos principais princípios da programação orientada a objetos é encapsular dados e comportamentos associados nesses dados.

A persistência não é um comportamento do objeto modelado. Acho que o desenvolvimento progride mais suavemente se os objetos de negócios são ignorados. O desenvolvimento de novos código e teste de unidade novo código acontece mais rápido e mais suave se os objetos de negócios não estiverem especificamente ligados ao encanamento subjacente. Isso ocorre porque posso zombar desses aspectos e esquecer de ter que passar por aros para chegar ao banco de dados, etc. Meus testes de unidade serão executados mais rapidamente (uma enorme vantagem se você tiver milhares de testes automatizados que correm com cada compilação) e eu terá menos estresse, porque não terei testes falhando devido a problemas de conexão do banco de dados (ótimo se você costuma trabalhar offline ou remotamente e nem sempre pode acessar seu banco de dados e, a propósito, esses aspectos (conectividade do banco de dados etc.) devem ser testado em outro lugar!).

A outra linha de raciocínio diz: não, se eu tiver um objeto de cliente que eu só quero ligar Customer.Save e ser feito com isso. Por que preciso saber como salvar um cliente se estou consumindo o objeto?

Sabendo que Customer tem um Save O método já está sabendo como salvar um objeto de cliente. Você não evitou o problema incorporando essa lógica em seu objeto de negócios. Em vez disso, você tornou sua base de código mais fortemente acoplada e, portanto, mais difícil de manter e testar. Empurre a responsabilidade de persistir no objeto para outra pessoa.

Os objetos de negócios, como são nomeados, devem obviamente coutain sua própria lógica de negócios, a dinâmica da lógica de negócios entre o domínio que está na camada de serviço.

Por outro lado, o BO poderia ser uma composição e métodos de contêiner de dados (DTO?); Significando bo são pura funcionais? Isso pode evitar todas as conversões entre BO e DTO.

Em uma arquitetura MVC,

Podemos dizer que o modelo contém objetos de negócios.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top