Por que precisamos de objetos de entidade? [fechadas]


139

Eu realmente preciso assistir a um debate honesto e ponderado sobre os méritos do paradigma de design de aplicativos corporativos atualmente aceito .

Não estou convencido de que objetos de entidade devam existir.

Por objetos de entidade, quero dizer as coisas típicas que costumamos criar para nossos aplicativos, como "Pessoa", "Conta", "Pedido" etc.

Minha filosofia atual de design é a seguinte:

  • Todo acesso ao banco de dados deve ser realizado por meio de procedimentos armazenados.
  • Sempre que você precisar de dados, chame um procedimento armazenado e itere sobre um SqlDataReader ou as linhas em um DataTable

(Nota: Eu também construí aplicativos corporativos com Java EE, pessoal de Java, substitua o equivalente pelos meus exemplos .NET)

Eu não sou anti-OO. Eu escrevo muitas classes para propósitos diferentes, mas não entidades. Admito que grande parte das classes que escrevo são classes auxiliares estáticas.

Eu não estou construindo brinquedos. Estou falando de aplicativos transacionais grandes e de alto volume implantados em várias máquinas. Aplicativos da Web, serviços do Windows, serviços da Web, interação B2B, o nome dele.

Eu usei OR Mappers. Eu escrevi alguns. Eu usei a pilha Java EE, CSLA e alguns outros equivalentes. Eu não apenas os usei, mas desenvolvi e mantive ativamente esses aplicativos em ambientes de produção.

Eu vim à conclusão de batalha-testado que objetos de entidade estão recebendo em nosso caminho, e nossa vida seria assim muito mais fácil sem eles.

Considere este exemplo simples: você recebe uma chamada de suporte sobre uma determinada página em seu aplicativo que não está funcionando corretamente, talvez um dos campos não esteja sendo mantido como deveria. Com o meu modelo, o desenvolvedor designado para encontrar o problema abre exatamente 3 arquivos . Um arquivo ASPX, ASPX.CS e SQL com o procedimento armazenado. O problema, que pode ser um parâmetro ausente para a chamada do procedimento armazenado, leva alguns minutos para ser resolvido. Mas com qualquer modelo de entidade, você invariavelmente inicia o depurador, começa a percorrer o código e pode acabar com 15 a 20 arquivos abertos no Visual Studio. Quando você desce até o final da pilha, você esqueceu onde começou. Só podemos manter tantas coisas em nossas cabeças ao mesmo tempo. O software é incrivelmente complexo sem adicionar camadas desnecessárias.

A complexidade do desenvolvimento e a solução de problemas são apenas um lado da minha queixa.

Agora vamos falar sobre escalabilidade.

Os desenvolvedores percebem que toda vez que escrevem ou modificam qualquer código que interaja com o banco de dados, eles precisam fazer uma análise completa do impacto exato no banco de dados? E não apenas a cópia de desenvolvimento, quero dizer uma imitação da produção, para que você possa ver que a coluna adicional que você precisa agora para o seu objeto invalidou o plano de consulta atual e um relatório que estava sendo executado em 1 segundo agora leva 2 minutos, apenas porque você adicionou uma única coluna à lista de seleção? E acontece que o índice que você precisa agora é tão grande que o DBA precisará modificar o layout físico dos seus arquivos?

Se você permitir que as pessoas se afastem demais do armazenamento de dados físicos com uma abstração, elas criarão estragos no aplicativo que precisa ser dimensionado.

Eu não sou fanático. Posso estar convencido de que estou errado, e talvez esteja, já que existe um forte impulso em direção ao Linq to Sql, ADO.NET EF, Hibernate, Java EE, etc. Por favor, pense nas suas respostas, se estiver faltando algo que eu realmente quero saber o que é e por que devo mudar meu pensamento.

[Editar]

Parece que esta pergunta está subitamente ativa novamente, então agora que temos o novo recurso de comentário que comentei diretamente em várias respostas. Obrigado pelas respostas, acho que é uma discussão saudável.

Eu provavelmente deveria ter sido mais claro que estou falando de aplicativos corporativos. Eu realmente não posso comentar, digamos, sobre um jogo que está sendo executado na área de trabalho de alguém ou em um aplicativo móvel.

Uma coisa que preciso colocar aqui no topo em resposta a várias respostas semelhantes: a ortogonalidade e a separação de preocupações são frequentemente citadas como razões para se tornar uma entidade / ORM. Procedimentos armazenados, para mim, são o melhor exemplo de separação de preocupações em que consigo pensar. Se você não permitir qualquer outro acesso ao banco de dados, exceto por meio de procedimentos armazenados, em teoria, poderá redesenhar todo o seu modelo de dados e não quebrar nenhum código, desde que mantenha as entradas e saídas dos procedimentos armazenados. Eles são um exemplo perfeito de programação por contrato (desde que você evite "selecionar *" e documente os conjuntos de resultados).

Pergunte a alguém que está no setor há muito tempo e já trabalhou com aplicativos de longa duração: quantas camadas de aplicativo e da interface do usuário surgiram e desapareceram enquanto um banco de dados vive? Quão difícil é ajustar e refatorar um banco de dados quando existem 4 ou 5 camadas de persistência diferentes gerando SQL para acessar os dados? Você não pode mudar nada! ORMs ou qualquer código que gera SQL bloqueiam seu banco de dados .


Da leitura sua pergunta, nós somos muito parecidos, e eu quis saber exatamente a mesma coisa há anos (desde ouvir sobre estruturas 3ª entidade partido, e agora da Microsoft)
pearcewg

1
Você está dizendo que a lógica de negócios são os objetos auxiliares ou nos procs armazenados? Estou perguntando quantas pessoas parecem pensar que você está dizendo mais tarde ... mas o que eu acho que você está dizendo é que você ainda tem lógica de negócios nos objetos codificados, está apenas obtendo dados diretamente do banco de dados e usando esses dados , em vez de um ORM ou mapeamento para objetos especializados para armazenar os dados. Costumo me sentir da mesma maneira - mas também estou avaliando o EF4 para ver se vale a pena.
alquimia

"Consumidores inovadores geralmente são os que se ferram". - alguém com experiência
Uğur Gümüşhan

Eu herdei um sistema com mais de 2500 SPROCs, em que o aplicativo é visto simplesmente como um meio de ativar SPROCs e entender a saída deles. Cada leitura e gravação de dados tem seu próprio SPROC. Não há pontos centrais de controle. É hediondo e quase tão maleável quanto o granito. Considero otimizar os bancos de dados. Os 2500 SPROCS me colocaram no meu lugar. Comparado a um sistema com camada de domínio bem organizada e código DAL reutilizável, ele parece mal concebido e é um pesadelo de suporte. Tarefas simples levam horas e são destruidoras de almas. Stored Procedures deve ser utilizado para carga elevada ou métodos especiais IMO
trucker_jim

Sobre o seu exemplo de "depuração": com testes de unidade, você saberia muito mais rapidamente onde as coisas dão errado.
MarioDS

Respostas:


59

Eu acho que tudo se resume a quão complicada é a "lógica" do aplicativo e onde você o implementou. Se toda a sua lógica está nos procedimentos armazenados, e tudo o que o seu aplicativo faz é chamar esses procedimentos e exibir os resultados, o desenvolvimento de objetos de entidade é realmente uma perda de tempo. Mas para um aplicativo em que os objetos tenham interações ricas entre si e o banco de dados é apenas um mecanismo de persistência, pode haver valor em ter esses objetos.

Então, eu diria que não há uma resposta única. Os desenvolvedores precisam estar cientes de que, às vezes, tentar ficar com OO demais pode causar mais problemas do que resolve.


Kristopher, parece que você ressuscitou esta questão vinculando-a a outra pergunta. Eu estou querendo saber o que você quer dizer com "interações ricas", e como seria impraticável implementá-las sem objetos?
Eric Z Beard

4
Tudo o que pode ser feito com objetos também pode ser feito sem objetos. Acho que o projeto OO geralmente é muito mais fácil do que os métodos não OO para fazer algo "complicado", mas entendo que ele não funciona para todos.
Kristopher Johnson

Eu concordo - a resposta de "quando usar objetos" depende se as propriedades dos objetos podem ou não exigir ações ou alterar a lógica de negócios. Por exemplo, instâncias de Usuário ou Pessoa podem ter Senha e LoginName -> suas ações de código são alteradas de acordo com os valores dessas. Pelo contrário, se você tivesse um Produto, teria que exibir (nada mais, nenhuma outra ação) do que obter um DataSet do db e criar a GUI.
Yordan Georgiev

5
Existe um equilíbrio. Evite a religião e escolha o que funciona.
Jeff Davis

27

A teoria diz que implementações altamente coesas e pouco acopladas são o caminho a seguir.

Então, suponho que você esteja questionando essa abordagem, ou seja, separando preocupações.

Meu arquivo aspx.cs deve estar interagindo com o banco de dados, chamando um sproc e entendendo o IDataReader?

Em um ambiente de equipe, especialmente onde você tem pessoas menos técnicas que lidam com a parte aspx do aplicativo, não preciso que essas pessoas possam "tocar" essas coisas.

Separar meu domínio do meu banco de dados me protege de alterações estruturais no banco de dados, certamente uma coisa boa? A eficácia do banco de dados é absolutamente importante, portanto, alguém que seja mais excelente nesse ramo lide com ele, em um só lugar, com o menor impacto possível no restante do sistema.

A menos que eu esteja entendendo mal a sua abordagem, uma alteração estrutural no banco de dados pode ter uma grande área de impacto com a superfície do seu aplicativo. Vejo que essa separação de preocupações permite que eu e minha equipe minimizemos isso. Além disso, qualquer novo membro da equipe deve entender melhor essa abordagem.

Além disso, sua abordagem parece defender a lógica comercial do seu aplicativo para residir no seu banco de dados? Isso me parece errado, o SQL é realmente bom em consultar dados, e não em expressar a lógica de negócios.

No entanto, um pensamento interessante, embora pareça um passo longe do SQL no aspx, que nos meus velhos e maus dias não estruturados, me enche de pavor.


Concordo que ter muitas SQL dinâmicas espalhadas por todo o code-behind é ruim. Você deve manter as chamadas Db claras e distintas. O agrupamento de chamadas sproc em métodos auxiliares estáticos alcança uma espécie de separação sem percorrer todo o caminho da rota ORM.
Eric Z Beard

1
Embora eu nunca tenha trabalhado em um ambiente asp, tenho certeza de que algumas das pessoas menos técnicas estariam impressionadas com algum código javascript do lado do cliente, o que resulta em uma bela experiência do usuário, independentemente de qualquer interface ruim para a parte técnica -fim.
crowne

Eu concordo com você aqui e sou conhecido por fazer javascript no lado do cliente também, o que resultou em uma experiência de usuário não muito pobre, mesmo que eu o diga. Eu gostaria de pensar que as interfaces de back-end não são ruins e que nenhum programador do lado do cliente precisa se preocupar com nada disso, porque tentei separar minhas preocupações.
Nachojammers

2
"Isso me parece errado, o SQL é realmente bom em consultar dados, e não em expressar a lógica de negócios." - A menos que você use, digamos, PL / SQL, que adiciona uma linguagem de programação avançada sobre (e totalmente integrada) ao SQL, e seu código é armazenado dentro do banco de dados. Aumenta o desempenho, evitando viagens de ida e volta à rede. E encapsula sua lógica de negócios, independentemente de qual cliente se conecta ao banco de dados.
ObiWanKenobi

25

Um motivo - separando seu modelo de domínio do seu modelo de banco de dados.

O que eu faço é usar o Test Driven Development para escrever primeiro as camadas da interface do usuário e do modelo e a camada de dados ser zombada, para que a interface do usuário e o modelo sejam construídos em torno de objetos específicos do domínio; depois, mapeio esses objetos para qualquer tecnologia que esteja usando a camada de dados. É uma má idéia deixar a estrutura do banco de dados determinar o design do seu aplicativo. Sempre que possível, escreva o aplicativo primeiro e deixe que isso influencie a estrutura do seu banco de dados, e não o contrário.


9
Devo dizer que discordo mesmo, pelo menos em aplicativos corporativos. Os dados são a aplicação.
Eric Z Beard

3
por que você gostaria de ter dois modelos separados dos mesmos dados?
Seun Osewa

3
Porque, para alguns propósitos, uma interpretação do modelo pode ser mais adequada. Alguma lógica funciona muito melhor em objetos do que em linhas.
Wouter Lievens

1
Eu acho que é uma boa ideia implementada mal.
22411 Jeff Davis

21

Para mim, tudo se resume a não querer que meu aplicativo se preocupe com a forma como os dados são armazenados. Provavelmente vou levar um tapa por dizer isso ... mas seu aplicativo não é seus dados, dados são um artefato do aplicativo. Eu quero que meu aplicativo esteja pensando em termos de clientes, pedidos e itens, não uma tecnologia como DataSets, DataTables e DataRows ... porque quem sabe quanto tempo eles estarão por aí.

Concordo que sempre há uma certa quantidade de acoplamento, mas prefiro que o acoplamento alcance mais do que para baixo. Posso ajustar os galhos e folhas de uma árvore mais facilmente do que alterar seu tronco.

Costumo reservar sprocs para relatórios, pois as consultas tendem a ficar um pouco mais desagradáveis ​​do que o acesso geral aos dados dos aplicativos.

Eu também tendem a pensar que, com o teste de unidade adequado no início, esse cenário é como se uma coluna que não estivesse sendo mantida provavelmente não fosse um problema.


3
"seu aplicativo não é seus dados, dados são um artefato do aplicativo." - O aplicativo é inútil sem os dados. Os dados têm grande valor sem o aplicativo. Os aplicativos vêm e vão (são reescritos) o tempo todo, os dados em qualquer aplicativo não trivial são sempre mantidos. E o modelo de dados permanece surpreendentemente estável ao longo do tempo.
Obi-Wan Kenobi

16

Eric, você está morto. Para qualquer aplicação realmente escalonável / de fácil manutenção / robusta, a única resposta real é dispensar todo o lixo e manter o básico.

Eu segui uma trajetória semelhante com minha carreira e cheguei às mesmas conclusões. Claro, somos considerados hereges e parecemos engraçados. Mas minhas coisas funcionam e funcionam bem.

Toda linha de código deve ser vista com desconfiança.


2
certeza, ele faz certamente funciona bem quando você tem toneladas de pessoal anjd recursos, mas eu acho que se você é uma equipe de um homem a pensar técnicas "novos" pode ajudar muito ..
Carl Hörberg

10

Eu gostaria de responder com um exemplo semelhante ao que você propôs.

Na minha empresa, tive que criar uma seção simples de CRUD para produtos, criar todas as minhas entidades e um DAL separado. Mais tarde, outro desenvolvedor teve que alterar uma tabela relacionada e ele até renomeou vários campos. O único arquivo que precisei alterar para atualizar meu formulário foi o DAL para essa tabela.

O que (na minha opinião) as entidades trazem para um projeto é:

Ortogonalidade: alterações em uma camada podem não afetar outras camadas (é claro que, se você fizer uma grande alteração no banco de dados, ela se propagará por todas as camadas, mas a maioria das pequenas alterações não).

Testabilidade: você pode testar sua lógica sem tocar em seu banco de dados. Isso aumenta o desempenho dos seus testes (permitindo que você os execute com mais frequência).

Separação de preocupações: em um grande produto, você pode atribuir o banco de dados a um DBA e ele pode otimizar o inferno. Atribua o modelo a um especialista em negócios que tenha o conhecimento necessário para projetá-lo. Atribua formulários individuais a desenvolvedores com mais experiência em formulários da web etc.

Finalmente, gostaria de acrescentar que a maioria dos mapeadores ORM suporta procedimentos armazenados, pois é isso que você está usando.

Felicidades.


2
Os procedimentos armazenados são provavelmente o melhor exemplo de ortogonalidade e separação de preocupações. Se usados ​​corretamente, eles encapsulam completamente o banco de dados.
Eric Z Beard

1
@ Eric Z Beard: Sim, mas como você pode escrever testes de unidade em torno de procedimentos armazenados enquanto isola apenas a lógica dentro do procedimento armazenado? Os procedimentos armazenados estão fortemente acoplados ao banco de dados, e a maioria de nós não gosta disso. Para escrever um teste de unidade para um procedimento armazenado, você precisa contar com certos dados para estar no banco de dados. e você não pode executar esse teste repetidamente sem essa dependência de dados. O teste que você escreveria não seria mais um teste de unidade, mas um Teste de Integração.
7wp 30/10/09

8

Eu acho que você pode estar "mordendo mais do que pode mastigar" neste tópico. Ted Neward não estava sendo irreverente quando o chamou de " Vietnã da Ciência da Computação ".

Uma coisa que posso garantir absolutamente é que isso não mudará o ponto de vista de ninguém sobre o assunto, como já foi comprovado com frequência em inúmeros outros blogs, fóruns, podcasts etc.

Certamente não há problema em ter uma dissucação aberta e debater sobre um tópico polêmico, é apenas esse que foi feito tantas vezes que os dois "lados" concordaram em discordar e continuaram a escrever software.

Se você quiser ler mais sobre os dois lados, consulte artigos no blog de Ted, Ayende Rahein, Jimmy Nilson, Scott Bellware, Alt.Net, Stephen Forte, Eric Evans etc.


1
Você está certo, a maioria das pessoas não muda de opinião. Sei que o foco do Stack Overflow deve ser perguntas objetivas, mas as subjetivas são muito mais divertidas! Pessoalmente, aprendi muito com essa discussão.
Eric Z Beard

Penso que as várias abordagens são específicas do contexto e que essa discussão pode servir para desambiguar quais cenários se beneficiam ou prejudicam os diferentes modelos de persistência. Especialistas no assunto não mudam de opinião rapidamente, mas esse é um site de perguntas onde as pessoas buscam outras experiências.
TheXenocide 17/09/08

Uau. +1 no link para o artigo "Vietnã da Ciência da Computação", que apresenta uma excelente introdução ao tópico ORM vs. ORM não.
lambacck

7

@ Dan, desculpe, esse não é o tipo de coisa que estou procurando. Eu conheço a teoria. Sua afirmação "é uma péssima idéia" não é apoiada por um exemplo real. Estamos tentando desenvolver software em menos tempo, com menos pessoas, com menos erros, e queremos a capacidade de fazer alterações facilmente. Seu modelo de várias camadas, na minha experiência, é negativo em todas as categorias acima. Especialmente no que diz respeito a tornar o modelo de dados a última coisa que você faz. O modelo de dados físicos deve ser uma consideração importante a partir do dia 1.


uau, alguém que pensa como eu nisto ... meus aplicativos são quase sempre sobre manipulação de dados, é isso que eles realmente fazem.
alquimia

Isso seria melhor como comentário agora que esses recursos estão disponíveis
Casebash

1
Perdoe-me por ser pedante, mas como essa é uma pergunta popular, e o erro que você cometeu é comum, senti que deveria apontar. "Menos tempo" está correto, mas "menos pessoas" e "menos erros" devem ser "menos pessoas" e "menos erros". Se você tiver menos farinha, poderá fazer menos biscoitos. (Além disso, se você usar muita farinha, fará muitos biscoitos - uma distinção menos esquecida.) Mais uma vez, minhas desculpas; Apenas Tentando Ser útil.
precisa saber é o seguinte

4

Achei sua pergunta realmente interessante.
Normalmente, eu preciso de objetos de entidades para encapsular a lógica de negócios de um aplicativo. Seria realmente complicado e inadequado empurrar essa lógica para a camada de dados.
O que você faria para evitar esses objetos de entidade? Que solução você tem em mente?


Isso seria melhor como comentário
Casebash

4

Objetos de entidade podem facilitar o cache na camada do aplicativo. Boa sorte em cache de um datareader.


4

Também devemos falar sobre a noção de que entidades são realmente. Quando leio essa discussão, tenho a impressão de que a maioria das pessoas aqui está olhando para entidades no sentido de um Modelo de Domínio Anêmico . Muitas pessoas estão considerando o Modelo de Domínio Anêmico como um antipadrão!

Há valor nos modelos de domínio avançado. É disso que se trata o Domain Driven Design . Pessoalmente, acredito que o OO é uma maneira de conquistar a complexidade. Isso significa não apenas complexidade técnica (como acesso a dados, ligação à interface do usuário, segurança ...), mas também complexidade no domínio comercial !

Se podemos aplicar técnicas de OO para analisar, modelar, projetar e implementar nossos problemas de negócios, essa é uma enorme vantagem para a manutenção e extensibilidade de aplicativos não triviais!

Existem diferenças entre suas entidades e suas tabelas. As entidades devem representar seu modelo, as tabelas representam apenas o aspecto de dados do seu modelo!

É verdade que os dados duram mais que os aplicativos, mas considere esta citação de David Laribee : Os modelos são eternos ... os dados são um efeito colateral feliz.

Mais alguns links sobre este tópico:


1
Francamente, estou começando a acreditar que os dados duram mais do que o software ao seu redor, porque muitas vezes pouca atenção está sendo prestada ao design do software, a partir de uma verdadeira compreensão dos negócios.
Flq 04/03/09

4

Pergunta realmente interessante. Honestamente, não posso provar por que as entidades são boas. Mas posso compartilhar minha opinião por que gosto deles. Código como

void exportOrder(Order order, String fileName){...};

não se preocupa de onde veio a ordem - do banco de dados, da solicitação da web, do teste de unidade etc. Isso torna esse método mais explicitamente declarar o que exatamente é necessário, em vez de pegar o DataRow e documentar quais colunas ele espera ter e quais tipos devem estar. O mesmo se aplica se você implementá-lo de alguma forma como procedimento armazenado - você ainda precisa enviar o ID do registro, embora ele não seja necessário no DB.

A implementação desse método seria feita com base na abstração do pedido, não com base em como exatamente ele é apresentado no DB. A maioria dessas operações que implementei realmente não depende de como esses dados são armazenados. Entendo que algumas operações exigem acoplamento à estrutura do banco de dados para fins de desempenho e escalabilidade, apenas na minha experiência, não há muitas delas. Na minha experiência, muitas vezes é suficiente saber que Person tem .getFirstName () retornando String, e .getAddress () retornando Address e endereço tem .getZipCode (), etc - e não se importa com quais tabelas são involidas para armazenar esses dados .

Se você tiver que lidar com os problemas que você descreveu, como quando quebras de colunas adicionais relatam desempenho, para as tarefas, o DB é uma parte crítica e você deve estar o mais próximo possível dele. Embora as entidades possam fornecer algumas abstrações convenientes, elas também podem ocultar alguns detalhes importantes.

A escalabilidade é um ponto interessante aqui - a maioria dos sites que exigem uma escalabilidade enorme (como facebook, livejournal, flickr) tendem a usar a abordagem ascética do DB, quando o DB é usado o mais raro possível e os problemas de escalabilidade são resolvidos pelo cache, especialmente pelo uso da RAM. http://highscalability.com/ tem alguns artigos interessantes.


2
A escalabilidade em aplicativos corporativos geralmente não pode ser solucionada pelo armazenamento em cache, uma vez que grande parte deles frequentemente altera dados transacionais em tabelas com milhões de linhas. Eu vejo o facebook et. al. como sites de alto volume, onde a parte mais difícil é atender a tantas solicitações da web.
Eric Z Beard

4

Há outras boas razões para objetos de entidade além da abstração e do acoplamento solto. Uma das coisas que mais gosto é a digitação forte que você não pode obter com um DataReader ou um DataTable. Outro motivo é que, quando bem executadas, as classes de entidade adequadas podem tornar o código mais fácil de usar, usando construções de primeira classe para termos específicos de domínio que qualquer pessoa que esteja olhando para o código provavelmente entenda, em vez de um monte de strings com nomes de campos usados para indexar um DataRow. Os procedimentos armazenados são realmente ortogonais ao uso de um ORM, pois muitas estruturas de mapeamento permitem mapear para sprocs.

Eu não consideraria sprocs + datareaders um substituto para uma boa ORM. Com os procedimentos armazenados, você ainda é limitado e fortemente associado à assinatura de tipo do procedimento, que usa um sistema de tipos diferente do código de chamada. Os procedimentos armazenados podem estar sujeitos a modificações para acomodar opções adicionais e alterações de esquema. Uma alternativa aos procedimentos armazenados no caso em que o esquema está sujeito a alterações é usar visualizações - você pode mapear objetos para visualizações e, em seguida, mapear novamente as visualizações para as tabelas subjacentes ao alterá-las.

Entendo sua aversão aos ORMs se sua experiência consistir principalmente em Java EE e CSLA. Você pode querer dar uma olhada no LINQ to SQL, que é uma estrutura muito leve e é principalmente um mapeamento individual com as tabelas do banco de dados, mas geralmente precisa apenas de uma extensão menor para que eles sejam objetos de negócios completos. O LINQ to SQL também pode mapear objetos de entrada e saída para os parâmetros e resultados dos procedimentos armazenados.

A estrutura de entidade do ADO.NET possui a vantagem adicional de que suas tabelas de banco de dados podem ser exibidas como classes de entidades herdadas umas das outras ou como colunas de várias tabelas agregadas em uma única entidade. Se você precisar alterar o esquema, poderá alterar o mapeamento do modelo conceitual para o esquema de armazenamento sem alterar o código do aplicativo real. E, novamente, os procedimentos armazenados podem ser usados ​​aqui.

Eu acho que mais projetos de TI nas empresas falham por causa da manutenção do código ou da baixa produtividade do desenvolvedor (o que pode acontecer, por exemplo, na alternância de contexto entre gravação de sproc e gravação de aplicativo) do que problemas de escalabilidade de um aplicativo.


Eu acho que um bom compromisso seria mapear um ORM para procedimentos armazenados, exceto que isso pode ser facilmente feito mal: se você apenas criar os 4 procs CRUD para cada tabela, não terá conseguido nada. Você pode mapear procs grandes e de granulação grossa para entidades, ou isso realmente não leva a lugar algum?
Eric Z Beard

Além das operações CRUD, os ORMs da Microsoft permitem adicionar métodos às classes de entidade que são mapeadas diretamente para qualquer processo armazenado que você deseja lançar (desde que todos os tipos de entrada / saída sejam mapeáveis).
Mark Cidade

3

Também gostaria de acrescentar à resposta de Dan que a separação dos dois modelos pode permitir que seu aplicativo seja executado em diferentes servidores de banco de dados ou mesmo modelos de banco de dados.


3

E se você precisar dimensionar seu aplicativo equilibrando mais de um servidor da Web? Você pode instalar o aplicativo completo em todos os servidores da Web, mas uma solução melhor é fazer com que os servidores da Web conversem com um servidor de aplicativos.

Mas se não houver objetos de entidade, eles não terão muito o que falar.

Não estou dizendo que você não deve escrever monólitos se for uma aplicação simples, interna e de vida curta. Mas assim que ficar moderadamente complexo ou durar uma quantidade significativa de tempo, você realmente precisará pensar em um bom design.

Isso economiza tempo quando se trata de mantê-lo.

Ao dividir a lógica do aplicativo da lógica de apresentação e do acesso a dados e passando DTOs entre eles, você os dissocia. Permitindo que eles mudem independentemente.


3
Muitas pessoas estão criando o desacoplamento e permitindo que uma camada mude sem afetar a outra. Procedimentos armazenados fazem isso melhor do que qualquer ORM! Posso alterar radicalmente o modelo de dados e, desde que os procedimentos retornem os mesmos dados, nada será interrompido.
Eric Z Beard

2
Na minha opinião, os procedimentos armazenados E um modelo de entidade não são mutuamente exclusivos. Os procedimentos armazenados podem fornecer um mecanismo para armazenar seu modelo de entidade. A pergunta é: sua lógica de negócios funciona com as entidades ou acessa diretamente os procedimentos armazenados?
jbandi

3

Você pode encontrar este post no comp.object interessante.

Não estou afirmando concordar ou discordar, mas é interessante e (acho) relevante para este tópico.


Esse é um ótimo post. Resume meus pensamentos sobre ORMs quase perfeitamente.
Eric Z Beard

3

Uma pergunta: como você lida com aplicativos desconectados se toda a sua lógica de negócios está presa no banco de dados?

No tipo de aplicativo corporativo em que estou interessado, precisamos lidar com vários sites, alguns deles devem poder funcionar em um estado desconectado.
Se sua lógica de negócios estiver encapsulada em uma camada de Domínio simples de incorporar em vários tipos de aplicativos - diga, como dll-, eu posso criar aplicativos que estejam cientes das regras de negócios e que, quando necessário, possam aplicá-las localmente.

Para manter a camada Domínio nos procedimentos armazenados no banco de dados, você precisa se ater a um único tipo de aplicativo que precisa de uma linha de visão permanente para o banco de dados.

Tudo bem para uma certa classe de ambientes, mas certamente não cobre todo o espectro de aplicativos corporativos .


2

@jdecuyper, uma máxima que repito para mim mesmo com frequência é "se sua lógica de negócios não está no seu banco de dados, é apenas uma recomendação". Eu acho que Paul Nielson disse isso em um de seus livros. As camadas de aplicativo e a interface do usuário vêm e vão, mas os dados geralmente duram muito tempo.

Como evito objetos de entidade? Procedimentos armazenados principalmente. Também admito livremente que a lógica de negócios tende a atingir todas as camadas de um aplicativo, independentemente de você pretender ou não. Uma certa quantidade de acoplamento é inerente e inevitável.


Concordo que a lógica de negócios que está no aplicativo muitas vezes falha em levar em conta as outras maneiras pelas quais os dados podem ser inseridos, excluídos ou alterados. Isso geralmente causa problemas de integridade de dados no caminho.
HLGEM 3/08/08

E por que você sempre deve usar uma camada de serviço para lidar com a incompatibilidade entre o mundo dos objetos e o mundo relacional. A lógica de negócios que atravessa todas as camadas certamente NÃO é inevitável.
Cdaq 14/05

2

Ultimamente tenho pensado muito nessa mesma coisa; Eu era um usuário pesado do CSLA por um tempo e adoro a pureza de dizer que "toda a sua lógica de negócios (ou pelo menos o quanto for razoavelmente possível) está encapsulada em entidades de negócios".

Vi o modelo de entidade comercial fornecer muito valor nos casos em que o design do banco de dados é diferente da maneira como você trabalha com os dados, o que ocorre em muitos softwares comerciais.

Por exemplo, a idéia de um "cliente" pode consistir em um registro principal em uma tabela do Cliente, combinado com todos os pedidos que o cliente fez, além de todos os funcionários do cliente, suas informações de contato e algumas das propriedades de um cliente e seus filhos podem ser determinados a partir de tabelas de pesquisa. É muito bom do ponto de vista do desenvolvimento poder trabalhar com o Cliente como uma entidade única, pois, do ponto de vista comercial, o conceito de Cliente contém todas essas coisas e os relacionamentos podem ou não ser impostos no banco de dados.

Embora aprecie a citação de que "se sua regra de negócios não estiver no seu banco de dados, é apenas uma sugestão", também acredito que você não deve projetar o banco de dados para impor regras de negócios, mas sim projetá-lo para ser eficiente, rápido e normalizado .

Dito isto, como outros observaram acima, não existe um "design perfeito", a ferramenta precisa se adequar ao trabalho. Mas o uso de entidades de negócios pode realmente ajudar com manutenção e produtividade, já que você sabe para onde modificar a lógica de negócios, e os objetos podem modelar conceitos do mundo real de maneira intuitiva.


2

Eric,

Ninguém o impede de escolher a estrutura / abordagem que você deseja. Se você estiver indo para o caminho "alimentado por procedimento controlado por dados / armazenado", então vá em frente! Especialmente se realmente ajudar realmente a fornecer seus aplicativos dentro das especificações e dentro do prazo.

Sendo a ressalva (um lado oposto à sua pergunta), TODAS as suas regras de negócios devem estar em procedimentos armazenados, e seu aplicativo não passa de um thin client.

Dito isto, as mesmas regras se aplicam se você fizer seu pedido no OOP: seja consistente. Siga os princípios do OOP, e isso inclui a criação de objetos de entidade para representar seus modelos de domínio.

A única regra real aqui é a consistência da palavra . Ninguém está impedindo você de se concentrar no DB. Ninguém está impedindo você de executar programas estruturados da velha escola (também conhecidos como funcionais / processuais). Inferno, ninguém está impedindo ninguém de fazer código no estilo COBOL. MAS um aplicativo precisa ser muito, muito consistente depois de seguir esse caminho, se desejar obter algum grau de sucesso.


Eu concordo com a consistência em todo o aplicativo. Para ser sincero, mudei de direção no meu projeto atual há um tempo e nunca consegui consertar 100% do modelo original, o que torna as coisas confusas. As melhores decisões são tomadas com antecedência.
Eric Z Beard

Eric, verdade mesmo. Uma vez eu era um fanático por OOP (da mesma forma que outras pessoas neste segmento), mas conheci um cara que é dono de uma empresa que é muito bem-sucedida na venda de aplicativos orientados a banco de dados. Isso abalou o meu mundo. Ainda sou um fã de OOP / TDD, mas não desaprovo mais o DB-centric.
Jon Limjap

O problema é que, às vezes, as pessoas vendem demais sua ideologia, você poderia ganhar a vida vendendo sites apenas em html e javascript, se tivesse uma boa metodologia para implementá-los.
Mark Rogers

2

Eu realmente não tenho certeza do que você considera "Aplicativos Corporativos". Mas estou tendo a impressão de que você o está definindo como um Aplicativo Interno, onde o RDBMS seria gravado em pedra e o sistema não precisaria ser interoperável com outros sistemas, internos ou externos.

Mas e se você tivesse um banco de dados com 100 tabelas que equivale a 4 procedimentos armazenados para cada tabela apenas para operações básicas de CRUD, são 400 procedimentos armazenados que precisam ser mantidos e não são fortemente tipados, por isso são suscetíveis a erros de digitação e não podem ser testados por unidade . O que acontece quando você obtém um novo CTO que é um evangelista de código aberto e deseja alterar o RDBMS do SQL Server para o MySql?

Atualmente, existe um monte de software, se os Aplicativos ou Produtos Corporativos estão usando SOA e têm alguns requisitos para expor os Serviços da Web, pelo menos o software que eu sou e com o qual estou envolvido. Usando sua abordagem, você acabaria expondo uma Serialized DataTable ou DataRows. Agora, isso pode ser considerado aceitável se for garantido que o Cliente é .NET e em uma rede interna. Mas quando o Cliente não é conhecido, você deve se esforçar para criar uma API que seja intuitiva e, na maioria dos casos, não queira expor o esquema de banco de dados completo. Eu certamente não gostaria de explicar a um desenvolvedor Java o que é um DataTable e como usá-lo. Há também a consideração do tamanho da largura de banda e da carga útil e das DataTables serializadas, os DataSets são muito pesados.

Não existe uma bala de prata no design de software e depende realmente de onde estão as prioridades, para mim está no código Unit Testable e nos componentes fracamente acoplados que podem ser facilmente consumidos por qualquer cliente.

apenas meus 2 centavos


Não, minha definição de aplicativo corporativo é o oposto. O esquema muda frequentemente, e há muitos aplicativos que usam o banco de dados e interopera com muitos parceiros externos. Em um aplicativo corporativo real , você nunca mudará para um RDBMS diferente. Isso simplesmente não acontece.
Eric Z Beard

E criar 4 procs para cada tabela é uma prática ruim. Ele o acopla firmemente ao modelo de dados, como o sql gerado a partir de um ORM, de modo que você não compra nada. Os procs precisam ser operações de negócios de granulação grossa, não apenas CRUD em cada tabela.
Eric Z Beard

Mas não é essa a resposta ?: quanto mais código você precisa escrever, mais recursos para suporte à programação em larga escala: encapsulamento, digitação de string, refatoração, estilo sofisticado e verificação de erros, etc .; Java e .NET têm um amplo suporte nessa área, as linguagens de procedimento armazenado não.
Reinierpost 01/04/09

2

Gostaria de oferecer outro ângulo para o problema da distância entre OO e RDB: história.

Qualquer software possui um modelo de realidade que é, até certo ponto, uma abstração da realidade. Nenhum programa de computador pode capturar todas as complexidades da realidade, e os programas são escritos apenas para resolver um conjunto de problemas da realidade. Portanto, qualquer modelo de software é uma redução da realidade. Às vezes, o modelo de software força a realidade a se reduzir. Como quando você deseja que a empresa de aluguel de carros reserve qualquer carro para você, desde que seja azul e tenha ligas, mas o operador não pode atender porque sua solicitação não cabe no computador.

RDB vem de uma tradição muito antiga de colocar informações em tabelas, chamada contabilidade. A contabilidade era feita no papel, depois nos cartões perfurados e depois nos computadores. Mas a contabilidade já é uma redução da realidade. A contabilidade forçou as pessoas a seguirem seu sistema por tanto tempo que se tornou realidade aceita. É por isso que é relativamente fácil criar software de contabilidade para contabilidade, a contabilidade teve seu modelo de informação muito antes de o computador aparecer.

Dada a importância de bons sistemas contábeis e a aceitação que você obtém de qualquer gerente de negócios, esses sistemas se tornaram muito avançados. As bases de dados agora são muito sólidas e ninguém hesita em manter os dados vitais em algo tão confiável.

Eu acho que o OO deve ter surgido quando as pessoas descobriram que outros aspectos da realidade são mais difíceis de modelar do que a contabilidade (que já é um modelo). OO tornou-se uma idéia muito bem-sucedida, mas a persistência dos dados OO é relativamente subdesenvolvida. O RDB / Contabilidade obteve vitórias fáceis, mas o OO é um campo muito maior (basicamente tudo o que não é contábil).

Muitos de nós queriam usar o OO, mas ainda queremos um armazenamento seguro de nossos dados. O que pode ser mais seguro do que armazenar nossos dados da mesma forma que o estimado sistema contábil? É uma perspectiva atraente, mas todos corremos para as mesmas armadilhas. Muito poucos se deram ao trabalho de pensar na persistência de OO em comparação com os esforços maciços da indústria de RDB, que teve o benefício da tradição e posição da contabilidade.

Prevayler e db4o são algumas sugestões, tenho certeza de que há outras de que não ouvi falar, mas nenhuma pareceu ter metade da imprensa como, por exemplo, hibernação.

Armazenar seus objetos em bons arquivos antigos nem parece ser levado a sério para aplicativos multiusuário e especialmente aplicativos da web.

Na minha luta cotidiana para fechar o abismo entre OO e RDB, uso OO o máximo possível, mas tento manter a herança no mínimo. Não costumo usar SPs. Usarei o material de consulta avançada apenas em aspectos que parecem contabilidade.

Ficarei feliz em surpreender quando o abismo for fechado para sempre. Eu acho que a solução virá quando a Oracle lançar algo como "Oracle Object Instance Base". Para realmente entender, terá que ter um nome tranquilizador.


Não acho que você precise que o ORM para OO seja considerado útil. Uso procs armazenados e escrevo muitas classes auxiliares estáticas no meu código, mas essas classes são construídas no enorme framework .NET, que é uma coleção fantástica de objetos.
Eric Z Beard

Sua lógica faz sentido, mas não acho que a premissa seja sólida. Eu nunca ouvi falar de nada que não possa ser mapeado com RDB.
Jeff Davis

1

Não há muito tempo no momento, mas apenas em cima da minha cabeça ...

O modelo de entidade permite fornecer uma interface consistente ao banco de dados (e outros sistemas possíveis), mesmo além do que uma interface de procedimento armazenado pode fazer. Ao usar modelos de negócios em toda a empresa, você pode garantir que todos os aplicativos afetem os dados de maneira consistente, o que é MUITO importante. Caso contrário, você terá dados ruins, o que é simplesmente um mal.

Se você possui apenas um aplicativo, não possui um sistema "corporativo", independentemente do tamanho do aplicativo ou dos seus dados. Nesse caso, você pode usar uma abordagem semelhante à que você fala. Esteja ciente do trabalho que será necessário se você decidir expandir seus sistemas no futuro.

Aqui estão algumas coisas que você deve ter em mente (IMO):

  1. O código SQL gerado é inválido (exceções a seguir). Desculpe, eu sei que muitas pessoas pensam que é uma enorme economia de tempo, mas nunca encontrei um sistema que pudesse gerar código mais eficiente do que o que eu poderia escrever e, muitas vezes, o código é simplesmente horrível. Você também acaba gerando uma tonelada de código SQL que nunca é usado. A exceção aqui são padrões muito simples, como talvez tabelas de pesquisa. Muitas pessoas se empolgam com isso.
  2. Tabelas de entidades <> (ou mesmo entidades de modelo de dados lógicos necessariamente). Um modelo de dados geralmente possui regras de dados que devem ser aplicadas o mais próximo possível do banco de dados, o que pode incluir regras sobre como as linhas da tabela se relacionam entre si ou outras regras semelhantes muito complexas para a RI declarativa. Estes devem ser tratados em procedimentos armazenados. Se todos os seus procedimentos armazenados forem simples procs CRUD, você não poderá fazer isso. Além disso, o modelo CRUD geralmente cria problemas de desempenho porque não minimiza as viagens de ida e volta pela rede ao banco de dados. Esse costuma ser o maior gargalo de um aplicativo corporativo.

Concordou em SQL gerado. Sempre causa mais problemas do que resolve. E sou contra a simples criação de uma camada CRUD com procs armazenados. Os procs devem ser o mais grosseiros possível. Não sabe ao certo como você define "um aplicativo".
Eric Z Beard

Por um aplicativo, quero dizer um único aplicativo escrito por um único grupo na organização. Onde estou consultando agora, eles têm um banco de dados corporativo que é acessado por pelo menos três grupos separados, trabalhando em três aplicativos diferentes, com comunicação limitada entre eles.
Tom H

1

Às vezes, seu aplicativo e sua camada de dados não são tão fortemente acoplados. Por exemplo, você pode ter um aplicativo de cobrança por telefone. Mais tarde, você cria um aplicativo separado que monitora o uso do telefone para: a) anunciar melhor para você; b) otimizar seu plano de telefone.

Esses aplicativos têm preocupações e requisitos de dados diferentes (mesmo que os dados saiam do mesmo banco de dados), eles direcionariam projetos diferentes. Sua base de código pode acabar com uma bagunça absoluta (em qualquer aplicativo) e um pesadelo para manter, se você deixar o banco de dados conduzir o código.


1

Os aplicativos que possuem lógica de domínio separada da lógica de armazenamento de dados são adaptáveis ​​a qualquer tipo de fonte de dados (banco de dados ou outro) ou aplicativo de interface do usuário (web ou windows (ou linux etc.)).

Você está praticamente preso no seu banco de dados, o que não é ruim se você estiver com uma empresa satisfeita com o sistema de banco de dados atual que está usando. No entanto, como os bancos de dados evoluem ao longo do tempo, pode haver um novo sistema de banco de dados realmente limpo e novo que sua empresa deseja usar. E se eles quisessem mudar para um método de acesso a dados de serviços da Web (como a arquitetura Orientada a Serviços em algum momento). Pode ser necessário portar os procedimentos armazenados em todo o lugar.

Além disso, a lógica do domínio abstrai a interface do usuário, o que pode ser mais importante em grandes sistemas complexos que sempre evoluíram (especialmente quando estão constantemente procurando por mais clientes).

Além disso, embora eu concorde que não há resposta definitiva para a questão de procedimentos armazenados versus lógica de domínio. Estou no campo de lógica de domínio (e acho que eles estão ganhando com o tempo), porque acredito que procedimentos armazenados elaborados são mais difíceis de manter do que lógica de domínio elaborada. Mas esse é outro debate


0

Eu acho que você está acostumado a escrever um tipo específico de aplicativo e resolver um certo tipo de problema. Você parece estar atacando isso da perspectiva do "banco de dados primeiro". Existem muitos desenvolvedores por aí onde os dados são mantidos em um banco de dados, mas o desempenho não é uma prioridade. Em muitos casos, colocar uma abstração sobre a camada de persistência simplifica bastante o código e o custo de desempenho não é um problema.

O que quer que você esteja fazendo, não é POO. Não está errado, apenas não é POO, e não faz sentido aplicar suas soluções a todos os problemas existentes.


Os dados sempre vêm em primeiro lugar. É a razão pela qual você tem o programa de computador em primeiro lugar. Portanto, "primeiro banco de dados" é possivelmente a única abordagem válida para o design de aplicativos.
Gbjbaanb

0

Pergunta interessante. Algumas reflexões:

  1. Como você testaria unitariamente se toda a sua lógica de negócios estava no seu banco de dados?
  2. As alterações na estrutura do banco de dados, especificamente as que afetam várias páginas do seu aplicativo, não seriam um grande problema para mudar em todo o aplicativo?

0

Boa pergunta!

Uma abordagem que eu mais gosto é criar um objeto iterador / gerador que emita instâncias de objetos relevantes para um contexto específico. Normalmente, esse objeto envolve algumas coisas de acesso ao banco de dados subjacentes, mas não preciso saber disso ao usá-lo.

Por exemplo,

Um objeto AnswerIterator gera objetos AnswerIterator.Answer. Nos bastidores, ele está repetindo uma instrução SQL para buscar todas as respostas e outra instrução SQL para buscar todos os comentários relacionados. Mas, ao usar o iterador, apenas uso o objeto Answer, que possui as propriedades mínimas para esse contexto. Com um pouco de código esquelético, isso se torna quase trivial.

Descobri que isso funciona bem quando tenho um grande conjunto de dados para trabalhar e, quando bem feito, fornece objetos pequenos e transitórios que são relativamente fáceis de testar.

É basicamente uma camada fina sobre o material de Acesso ao Banco de Dados, mas ainda me dá a flexibilidade de abstraí-lo quando preciso.


0

Os objetos nos meus aplicativos tendem a se relacionar individualmente ao banco de dados, mas estou achando que usar o Linq To Sql em vez de sprocs facilita muito a escrita de consultas complicadas, especialmente a capacidade de construí-las usando a execução adiada. por exemplo, a partir de r em Images.User.Ratings onde etc. Isso me poupa ao tentar elaborar várias instruções de junção no sql, e ter o Skip & Take para paginação também simplifica o código, em vez de incorporar o número da linha e o código 'over'.


Há um grande perigo em fazer as coisas dessa maneira. As consultas mais complexas acabam precisando ser reescritas inteiramente por um DBA para que elas sejam dimensionadas. Nenhuma quantidade de ajuste de índice pode fazer o que alterar uma consulta às vezes pode fazer. Este tipo de Linq2Sql é um acoplamento extremamente apertado.
Eric Z Beard

0

Por que parar nos objetos de entidade? Se você não vir o valor com objetos de entidade em um aplicativo de nível empresarial, basta acessar os dados em uma linguagem puramente funcional / processual e conectá-lo a uma interface do usuário. Por que não cortar todo o "cotão" de OO?


Não vejo OO como "cotão". Só que, na última década, MSFT, Sun, etc, escreveram 99% dos objetos de que precisaremos. Só porque eu escrevo muitas classes estáticas no topo da estrutura, não significa que não estou usando OO.
Eric Z Beard
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.