Pergunta

Eu acredito em OO, mas não ao ponto onde os projetos inadequados / implementações deve ser usado apenas para ser "OO Compliant".

Então, como lidar com o Serlvet / EJB / DataContainer arquitetura em camadas:

  • Servlets receber pedidos e chamar uma "camada de negócios" (por exemplo, EJBs de sessão)
  • A camada de negócios localiza DataContainers do banco de dados e manipula-los para implementar a lógica do negócio
  • DataContainers conter nenhum código real, apenas get / set correspondente ao banco de dados.

Esta abordagem tem um apelo; os DataContainers são claras no que fazem e é muito fácil saber onde os dados vem.

Além de não ser OO, isso leva a classes de camada de negócios pouco claros que podem ser difíceis para nomear e difícil de organizar.

Mesmo que foram tentando ser mais "OO" (por exemplo, colocar alguns desses métodos nas DataConatiners), algumas destas operações operar em mais de um conjunto de dados.

Como você mantém a sua camada de negócio de ficar confusa processual, mas sem poluir seus DataContainers com lógica de negócios?

Exemplo

class UserServlet {
  handleRequest() {
    String id = request.get("id");
    String name = request.get("name");
    if (UserBizLayer.updateUserName(id,name))
      response.setStatus(OK);
    else
      response.setStatus(BAD_REQUEST);
  }
}

class UseBizLayer {
    updateUserName(String id, String name) {
        long key = toLong(id);
        user = userDAO.find(key);
        if user == null
            return false;
        if (!validateUserName(name))
            return false;
        user.setName(name);
        userDAO.update(user);
        return true;
    }

    validateUserName(String name) {
        // do some validations and return
    }
}

class User {
    long key;
    String name;
    String email;

    // imagine getters/setters here
}
  • Não queremos validateUserName no usuário, uma vez que só opera em um nome; Eu acho que ele poderia ir para outra classe, mas depois temos outra processual "uti" class tipo
  • Não queremos persistência métodos no usuário, uma vez que há valor no desacoplamento estruturas de dados a partir de sua estratégia de persistência
  • Não queremos a lógica de negócios em nossa Servlet, uma vez que pode precisar de re-uso que a lógica em outros lugares
  • Não queremos que nossa lógica de negócios no nosso usuário, pois isso atrai demais para a classe de usuário, fazendo re-uso da lógica de negócios difícil e acoplar o usuário com a sua estratégia de persistência

Eu percebo este exemplo não é tão ruim, mas imagine 10 DataContainers e 20 BizLayer objetos com vários métodos cada. Imagine que algumas dessas operações não são "centrada" em um contêiner de dados particular.

Como podemos manter este de ser uma confusão processual?

Foi útil?

Solução

Então, eu vou resolver meus pensamentos sobre isso em alguns pontos:

  1. Parece em um sistema Java EE em algum momento você tem que lidar com o encanamento de Java EE, o encanamento nem sempre beneficiam de conceitos OO, mas certamente pode com um pouco de criatividade e trabalho. Por exemplo, você poderia poderia tirar proveito de coisas como AbstractFactory, etc a ajuda commonize tanto desta infra-estrutura possível.
  2. Um monte do que você está olhando para é discutido em Eric Evans excelente livro chamado Domain Driven projeto. Eu altamente recomendo que você olhar para ele como ele faz resolver o problema de expressar o conhecimento do domínio e lidar com a infra-estrutura técnica para apoiá-lo.
  3. Depois de ler e GROKD alguns dos DDD, gostaria de encapsular a minha infra-estrutura técnica em repositórios. Os repositórios todos seriam escrito para usar uma estratégia de persistência que é baseado em suas EJBs de sessão. Você poderia escrever uma implementação padrão para que sabe como falar com seus EJBs de sessão. Para fazer este trabalho, você precisa adicionar um pouco de convenções e especificar que convenção / contrato em suas interfaces. Os repositórios de fazer todo o CRUD e só deve fazer mais do que se for absolutamente necessário. Se você disse "Meus DAOS são meus repositórios", então eu concordaria.
  4. Assim, para continuar com isso. Você precisa de algo para encapsular a unidade de trabalho que se expressa na UseBizLayer. A este nível, eu acho que a natureza do que é que você está escrevendo código preso que tudo está indo ser roteiro transação. Você está criando uma separação de responsabilidade e de Estado. Isto é tipicamente como eu já vi isso feito dentro dos sistemas Java EE como uma espécie padrão de arquitetura. Mas não é Object Oriented. Gostaria de tentar explorar o modelo e ver se eu poderia pelo menos tentar commonize alguns dos comportamentos que estão escritas nas BizClasses.
  5. Outra abordagem que eu usei antes é livrar-se das classes BizLayer e depois de proxy as chamadas a partir do domínio para os Repositórios reais / DAO de fazer a operação. No entanto, este pode exigir algum investimento na construção de infra-estrutura. Mas você poderia fazer muito com um quadro como Spring e usando algum do conceito AOP para fazer este trabalho bem e reduzir a quantidade de infra-estrutura personalizada que é necessário.

Outras dicas

desde que você está implementando classes e objetos, a solução vai ser OO independentemente de como você camada coisas - ele só não pode ser muito bem estruturada dependendo da sua situação / necessidades! ; -)

Quanto à sua pergunta específica, seria em alguns casos, faz sentido para validateUserName pertencer à classe de usuário, uma vez que cada usuário gostaria de ter um nome válido. Ou você pode ter uma classe de utilitário de validação assumindo que outras coisas têm nomes que usam as mesmas regras de validação. O mesmo vale para e-mail. Você pode dividir estes em classes NameValidator e EmailValidator, o que seria uma solução bem se eles serão usados ??muito. Você também pode ainda fornecer uma função validateUserName no objeto do usuário que simplesmente chamado de método de classe de utilitário. Todos estes são soluções válidas.

Uma das grandes alegrias sobre OOD / OOP é que quando o projeto é certo, você sei que é certo, porque um monte de coisas simplesmente cair do modelo que você pode fazer isso você não podia fazer antes.

Neste caso, eu faria aulas NameValidator e EmailValidator, porque parece provável que outras entidades terão nomes e endereços de e-mail no futuro, mas eu gostaria de fornecer funções validateName e validateEmailAddress na classe de usuário, porque isso faz para uma interface mais conveniente para a biz objetos de uso.

o resto do 'nós-não-quero' balas estão corretas; eles não só são necessárias para camadas adequada, mas eles também são necessários para um projeto OO limpo.

camadas e OO ir mão-na-luva baseado em uma separação de interesses entre as camadas. Eu acho que você tem a idéia certa, mas vai precisar de algumas classes de utilitários para validações comuns como apresentado

Pense em como essas tarefas seria feito se não houvesse computador e modelar o seu sistema dessa forma.

Um exemplo simples ... preenchimentos de cliente de um formulário para solicitar um widget, entrega a um empregado, o empregado verifica a identidade do cliente, processa o formulário, obtém um widget, dá o widget e um registro da transação para o cliente e mantém um registro da transação em algum lugar para a empresa.

O cliente armazenar seus dados? Não, o empregado faz. Que papel é o funcionário tomar quando ele está armazenando os dados do cliente? Cliente Registros Keeper.

O formulário verificar se ele foi preenchido corretamente? Não, o empregado faz. Que papel é a tomada empregado quando ele está fazendo isso? Form Processor.

Quem dá ao cliente o widget? O funcionário que atua como Distribuidor Widget

E assim por diante ...

Para empurrar isso em uma aplicação Java EE ...

O Servlet está agindo em nome do cliente, preenchendo o formulário (puxando dados da solicitação HTTP e fazer o objeto Java apropriado) e passá-la para o funcionário apropriado (EJB), que então faz com a forma que as necessidades a ser feito. Durante o processamento do pedido, o EJB ser necessário passá-lo para outro EJB que se especializa em tarefas diferentes, parte do qual seria incluir o acesso a / colocar informações de / para armazenamento (a sua camada de dados). A única coisa que não deve mapear diretamente para a analogia devem ser os detalhes sobre como os objetos se comunicam uns com os outros, e como seus dados comunica camada com o seu armazenamento.

Eu tive os mesmos pensamentos me.

No tradicional MVC a coisa mais importante é separar a vista do porções de modelo e controlador. Parece ser uma boa idéia para separar o controlador e o modelo, simplesmente porque você pode acabar com objetos do modelo inchado:


public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating {
  // member fields
  // getters and setters
  // 100 interface methods
}

Considerando que você pode ter controladores separados (ou padrões inteiros) para muitas das interfaces acima, e sim, é um pouco de natureza processual, mas eu acho que é como as coisas funcionam nos dias de hoje. Alternativamente, você pode perceber que algumas das interfaces estão fazendo a mesma coisa (fétido - armazenamento de dados e recuperação, Serializable - o mesmo para um formato binário, XMLable, o mesmo para XML) para que você deve criar um único sistema para lidar com isso, com cada backend potencial de ser uma aplicação separada que as alças de sistema. Deus, que é muito mal escrita.

Talvez haja algo como "co-classes" que permitem que você tenha arquivos de origem separadas para a execução do controlador que agir como se eles são um membro da classe de modelo que eles agir.

Quanto a regras de negócio, que muitas vezes o trabalho em vários modelos ao mesmo tempo, e, portanto, eles devem ser separados.

Eu acho que essa é uma questão sobre a "separação de interesses". Você parece ser um longo caminho no caminho certo com a sua arquitetura em camadas, mas talvez você precisa fazer mais do mesmo? - ou seja, criar camadas de arquitetura dentro de suas camadas Java EE

A DataContainer se parece muito com a transferência de dados Objects (DTO) padrão.

Um projeto OO moderna tem um monte de pequenas turmas, cada uma relacionada a um pequeno número de "amigos", por exemplo, composição através de. Isso pode produzir muito mais classes e Java caldeira-plate do que você está realmente confortável com, mas deve levar a um projeto que é melhor em camadas e mais fácil de teste de unidade e manter.

(+ 1 para a questão, um para a resposta sobre quando você sabe que tem o direito de camadas)

Grosseiramente, o "Nós não queremos" seção tem que ir. Ou você quer que seja certo, ou você quer que ele fique como está. Não há nenhum ponto em não criação de uma classe quando você precisa de um. "Temos muitos" é uma má desculpa.

Na verdade, é mal a expor todas as classes internas, mas na minha experiência, criando uma classe por conceito (ou seja, um usuário, um ID, um conceito de banco de dados ...) sempre ajuda.

Junto a isso, não é um padrão algo Fachada para resolver a existência de cargas de aulas BizRules, escondido atrás de uma interface bem organizada e limpa?

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