为什么我们需要实体对象?

时间:2020-03-05 18:41:15  来源:igfitidea点击:

我确实需要对当前接受的企业应用程序设计范例的优点进行一些诚实,周到的辩论。

我不认为实体对象应该存在。

实体对象是指我们倾向于为应用程序构建的典型事物,例如"人","帐户","订单"等。

我当前的设计理念是:

  • 所有数据库访问都必须通过存储过程来完成。
  • 每当需要数据时,调用存储过程并遍历SqlDataReader或者DataTable中的行

(注意:我还使用Java EE构建了企业应用程序,java人士请用等价的.NET示例代替)

我不是反OO。我为不同目的编写了很多类,而不仅仅是实体。我将承认我编写的大部分类都是静态帮助器类。

我不是在造玩具。我说的是跨多台机器部署的大批量交易应用程序。 Web应用程序,Windows服务,Web服务,B2B交互,我们可以命名。

我曾经使用过OR Mappers。我写了一些。我已经使用了Java EE堆栈,CSLA和其他一些等效项。我不仅使用了它们,而且还在生产环境中积极开发和维护了这些应用程序。

我得出了经过实战检验的结论,即实体对象正在妨碍我们前进,没有它们,我们的生活将变得更加轻松。

考虑一个简单的示例:我们会收到有关应用程序中某个页面无法正常工作的支持电话,可能其中一个字段没有得到应有的保留。对于我的模型,分配来查找问题的开发人员仅打开了3个文件。一个ASPX,一个ASPX.CS和一个带有存储过程的SQL文件。该问题可能是存储过程调用中缺少的参数,需要几分钟才能解决。但是对于任何实体模型,我们将始终启动调试器,开始逐步执​​行代码,最终可能会在Visual Studio中打开15-20个文件。到栈底时,我们已经忘记了从哪里开始。我们一次只能记住这么多事情。在不添加任何不必要的层的情况下,软件非常复杂。

开发的复杂性和故障排除只是我苦恼的一方面。

现在让我们谈谈可伸缩性。

开发人员是否意识到,每次编写或者修改与数据库交互的任何代码时,都需要对对数据库的确切影响进行彻底的分析?不仅仅是开发副本,我的意思是模仿生产,因此我们可以看到,对象现在需要的添加列刚刚使当前查询计划无效,而在1秒内运行的报告现在将需要2分钟,因为我们在选择列表中添加了单列?事实证明,我们现在需要的索引是如此之大,以至于DBA不得不修改文件的物理布局?

如果我们通过抽象让人们离物理数据存储区太远,那么他们将对需要扩展的应用程序造成破坏。

我不是狂热者。我可以确信,如果我错了,也许我是错的,因为对Linq大力推动了Sql,ADO.NET EF,Hibernate,Java EE等。我真的很想知道它是什么,以及为什么我应该改变自己的想法。

[编辑]

看来这个问题突然又活跃起来了,所以现在有了新的评论功能,我已经直接对几个答案发表了评论。感谢答复,我认为这是一个健康的讨论。

我可能应该更清楚地知道我在谈论企业应用程序。例如,我真的无法评论在某人的台式机或者移动应用程序上运行的游戏。

对于几个类似的答案,我不得不在顶部提出一件事:正交性和关注点分离经常被引用为采用实体/ ORM的原因。对我而言,存储过程是我能想到的分离关注点的最佳示例。如果不允许除通过存储过程之外的所有其他对数据库的访问,则只要我们维护存储过程的输入和输出,理论上就可以重新设计整个数据模型并且不会破坏任何代码。它们是按合同编程的完美示例(只要避免使用" select *"并记录结果集即可)。

问一个已经从事该行业很长时间并且使用了长期应用程序的人:在数据库运行期间,有多少个应用程序和UI层来去了?当有4到5个不同的持久层生成SQL获取数据时,调整和重构数据库有多难?你什么都不能改变! ORM或者生成SQL的任何代码将数据库牢牢锁定。

解决方案

回答

将域模型与数据库模型分开的原因之一。

我要做的是使用测试驱动开发,因此我首先编写了UI和Model层,并且对Data层进行了模拟,因此UI和模型围绕领域特定对象构建,然后将这些对象映射到我正在使用的技术数据层。让数据库结构确定应用程序的设计是一个坏主意。在可能的情况下,首先编写该应用程序,并让它影响数据库的结构,而不是相反。

回答

我发现问题真的很有趣。
通常,我需要实体对象来封装应用程序的业务逻辑。将此逻辑推入数据层确实很复杂且不足。
我们将如何避免这些实体对象?我们有什么解决方案?

回答

@丹,对不起,这不是我想要的东西。我知道理论。陈述"是一个非常糟糕的主意"并没有得到一个实际例子的支持。我们正在尝试以更少的时间,更少的人员,更少的错误来开发软件,并且我们希望能够轻松进行更改。根据我的经验,多层模型在上述所有类别中都是负面的。特别是关于使数据模型成为我们最后要做的事情。从第一天起,物理数据模型就必须成为重要的考虑因素。

回答

我还想补充一下Dan的答案,即分离两个模型可以使应用程序可以在不同的数据库服务器甚至数据库模型上运行。

回答

@jdecuyper,我经常对自己重复的一个格言是"如果业务逻辑不在数据库中,那只是一个建议"。我认为保罗·尼尔森(Paul Nielson)在他的一本书中曾说过这一点。应用程序层和UI来来往往,但是数据通常会生存很长时间。

如何避免实体对象?存储过程多为。我也自由地承认,无论我们是否打算,业务逻辑都倾向于遍及应用程序的所有层。一定数量的耦合是固有的,并且是不可避免的。

回答

我认为这取决于应用程序的"逻辑"有多复杂,以及在何处实现它。如果我们所有的逻辑都在存储过程中,而应用程序所要做的只是调用这些过程并显示结果,那么开发实体对象确实是在浪费时间。但是对于一个对象之间具有丰富交互关系且数据库只是一种持久性机制的应用程序而言,拥有这些对象可能会有价值。

因此,我想说的是没有一个"千篇一律"的答案。开发人员确实需要意识到,有时候,过于OO可能导致更多问题,而不是解决的问题。

回答

我认为我们只是习惯于编写特定类型的应用程序并解决特定类型的问题。我们似乎从"数据库优先"的角度进行攻击。有很多开发人员可以将数据持久存储到数据库中,但是性能并不是重中之重。在很多情况下,将抽象放在持久层上可以大大简化代码,而性能成本却不是问题。

无论我们做什么,都不是OOP。没错,这不是面向对象的,将解决方案应用于所有其他问题也没有任何意义。

回答

理论认为,高度凝聚力,松散耦合的实现是前进的道路。

因此,我想我们在质疑这种方法,即分离关注点。

我的aspx.cs文件应该与数据库交互,调用一个sproc并了解IDataReader吗?

在团队环境中,尤其是在我们缺乏技术人员来处理应用程序的aspx部分的情况下,我不需要这些人能够"接触"这些东西。

将域与数据库分开可以保护我免受数据库结构性更改的影响,这肯定是件好事吗?确保数据库的有效性绝对重要,因此,让一位在这方面最出色的人可以在一个地方处理这些东西,并且对系统的其余部分的影响尽可能小。

除非我对方法有误解,否则数据库中的一项结构更改可能会对应用程序的表面产生很大的影响。我看到关注点的分离使我和我的团队能够将其最小化。此外,团队中的任何新成员都应该更好地理解这种方法。

另外,方法似乎主张将应用程序的业务逻辑驻留在数据库中?我觉得这很不对劲,SQL确实擅长查询数据,而恕我直言,不能表达业务逻辑。

尽管有趣的想法,尽管它感觉到与aspx中的SQL相比仅一步之遥,但从我那糟糕的非结构化asp天开始,这让我感到恐惧。

回答

如果我们需要通过负载平衡多个Web服务器来扩展应用程序,该怎么办?我们可以在所有Web服务器上安装完整的应用程序,但是更好的解决方案是让Web服务器与应用程序服务器通信。

但是,如果没有任何实体对象,那么它们就没什么好谈的了。

我并不是说如果它是一个简单的,内部的,寿命短的应用程序,则不应编写整体。但是,一旦它变得相当复杂,或者应该持续相当长的时间,我们确实需要考虑一个好的设计。

这样可以节省维护时间。

通过将应用程序逻辑与表示逻辑和数据访问分开,并在它们之间传递DTO,可以将它们分离。允许他们独立更改。

回答

对我来说,归结为我不希望我的应用程序关心数据的存储方式。我可能会因为这么说而被打耳光...但是应用程序不是数据,数据是应用程序的工件。我希望我的应用程序从客户,订单和物料的角度出发,而不是像DataSets,DataTables和DataRows ... cuz这样的技术来思考,因为他们知道这些数据将持续多久。

我同意总会有一定程度的耦合,但是我更喜欢耦合向上而不是向下。比起改变树干,我可以更容易地调整其四肢和叶子。

我倾向于保留用于报告的存储过程,因为查询的确比应用程序的常规数据访问更难懂。

我也倾向于认为在这种情况下尽早进行适当的单元测试,就像不保留一列很可能不是问题。

回答

最近我一直在想着同样的事情。我曾经是CSLA的重度用户,我很喜欢说"所有业务逻辑(或者至少尽可能合理地封装在业务实体中)"的纯洁性。

我已经看到,在数据库的设计与我们使用数据的方式不同的情况下,业务实体模型可以提供很多价值,在许多业务软件中都是如此。

例如,"客户"的概念可能由"客户"表中的主记录,客户已下达的所有订单以及所有客户的员工及其联系信息以及"客户"的某些属性组成可以从查找表中确定客户及其子级。从开发的角度来看,能够与客户一起作为一个单独的实体工作真的很好,因为从业务角度来看,客户的概念包含所有这些内容,并且关系可以在数据库中执行或者可以不执行。

尽管我赞赏"如果业务规则不在数据库中,这只是一个建议"的说法,但我也相信我们不应该设计数据库来强制执行业务规则,而应该将其设计为高效,快速和规范化。

就是说,正如上面其他人提到的那样,没有"完美的设计",该工具必须适合这项工作。但是,使用业务实体确实可以帮助维护和提高生产率,因为我们知道去哪里修改业务逻辑,并且对象可以以直观的方式对实际概念进行建模。

回答

我想用一个与我们提出的例子类似的例子来回答。

在公司上,我必须为产品构建一个简单的CRUD部分,并建立所有实体和单独的DAL。后来,另一个开发人员不得不更改一个相关的表,他甚至重命名了几个字段。我必须更改以更新表单的唯一文件是该表的DAL。

(在我看来)实体为项目带来的是:

正交性:一层中的更改可能不会影响其他层(当然,如果我们对数据库进行较大的更改,它将在所有层中泛滥,但大多数较小的更改不会)。

可测试性:我们可以在不接触数据库的情况下测试逻辑。这样可以提高测试的性能(允许我们更频繁地运行它们)。

关注点分离:在大型产品中,我们可以将数据库分配给DBA,他可以优化数据库。将模型分配给具有设计所需知识的业务专家。将单独的表单分配给对Web表单等经验更丰富的开发人员。

最后,我想补充一下,大多数ORM映射器都支持存储过程,因为这就是我们所使用的。

干杯。

回答

有趣的问题。一些想法:

  • 如果所有业务逻辑都在数据库中,我们将如何进行单元测试?
  • 更改数据库结构,特别是影响应用程序中多个页面的数据库结构,是否会成为整个应用程序更改的主要麻烦?

回答

埃里克,
你死定了。对于任何真正可伸缩/易于维护/健壮的应用程序,唯一的答案就是省去所有垃圾,并坚持基本操作。

我的职业生涯遵循相似的轨迹,并得出了相同的结论。当然,我们被认为是异端,并且看上去很滑稽。但是我的东西行之有效。

每行代码都应引起怀疑。

回答

实体对象可以促进在应用程序层上的缓存。祝你好运,缓存数据读取器。

回答

好问题!

我更喜欢的一种方法是创建一个迭代器/生成器对象,该对象发出与特定上下文相关的对象实例。通常,此对象包装一些基础数据库访问内容,但使用它时我不需要知道这一点。

例如,

An AnswerIterator object generates AnswerIterator.Answer objects.  Under the hood it's iterating over a SQL Statement to fetch all the answers, and another SQL statement to fetch all related comments.  But when using the iterator I just use the Answer object that has the minimum properties for this context.  With a little bit of skeleton code this becomes almost trivial to do.

我发现,当我有一个庞大的数据集需要处理时,这种方法就很好用,而且如果正确完成,它可以为我提供相对较小的临时对象,这些对象相对易于测试。

从本质上讲,它只是数据库访问方面的薄板,但仍为我提供了在需要时对其进行抽象的灵活性。

回答

埃里克,

没有人阻止我们选择我们想要的框架/方法。如果我们要走"以数据驱动/存储过程为动力"的道路,那么一定要走!尤其是,如果确实如此,则确实可以按时按时交付应用程序。

需要注意的是(问题的另一面),所有业务规则都应在存储过程中,而应用程序仅是瘦客户端。

话虽如此,如果我们在OOP中进行申请,则应遵循相同的规则:保持一致。遵循OOP的原则,包括创建实体对象以表示域模型。

唯一真正的规则是一致性一词。没有人阻止我们以数据库为中心。没有人阻止我们进行老式的结构化(又称功能/程序)程序。地狱,没人阻止任何人编写COBOL风格的代码。但是,如果应用程序希望获得任何程度的成功,那么它必须非常一致。

回答

我的应用程序中的对象倾向于与数据库一对一关联,但是我发现使用Linq To Sql而不是sprocs可以使编写复杂查询变得更加容易,尤其是能够使用延迟执行来构建它们。例如从Images.User.Ratings中的r中获取等。这省去了我尝试在sql中计算多个join语句的麻烦,而使用Skip&Take进行分页也简化了代码,而不必嵌入row_number和" over"代码。

回答

除了抽象和松散耦合外,实体对象还有其他很好的理由。我最喜欢的一件事是DataReader或者DataTable无法获得的强类型。另一个原因是,如果做得好,适当的实体类可以通过对特定领域的术语使用一流的构造来使代码更具可维护性,这些领域特定的术语使任何看代码的人都可能理解,而不是使用一堆带有字段名的字符串用于索引DataRow。存储过程实际上与ORM的使用正交,因为许多映射框架使我们能够映射到sproc。

我不会考虑用sprocs + datareader代替好的ORM。使用存储过程时,我们仍然受到过程类型签名的束缚,并与之紧密耦合,该过程使用与调用代码不同的类型系统。存储过程可以进行修改,以适应其他选项和架构更改。在更改架构的情况下,存储过程的替代方法是使用视图-我们可以将对象映射到视图,然后在更改视图时将视图重新映射到基础表。

如果经验主要包括Java EE和CSLA,那么我可以理解我们对ORM的厌恶。我们可能想看一下LINQ to SQL,它是一个非常轻量级的框架,主要是与数据库表的一对一映射,但是通常只需要对它们进行少量扩展即可成为成熟的业务对象。 LINQ to SQL还可以将输入和输出对象映射到存储过程的参数和结果。

ADO.NET实体框架具有添加的优势,即数据库表可以看作是彼此继承的实体类,也可以看作是聚合到单个实体中的多个表的列。如果需要更改架构,则可以更改从概念模型到存储架构的映射,而无需更改实际的应用程序代码。同样,这里可以使用存储过程。

我认为,与代码的可扩展性问题相比,企业中更多的IT项目失败是由于代码的不可维护性或者开发人员生产力低下(例如,在存储过程编写和应用程序编写之间进行上下文切换而导致的)。

回答

我认为我们可能对此话题"咬牙切齿"。泰德·纽亚德(Ted Neward)称其为"越南计算机科学"时,并没有表现出任何轻率。

我绝对可以保证的一件事是,它将改变任何人对此事的观点,这一点已在无数其他博客,论坛,播客等上得到了如此频繁的证明。

对一个有争议的话题进行公开讨论和辩论当然是可以的,只是这一点已经做了很多次,以至于双方都同意不同意并开始编写软件。

如果我们想对双方都做进一步的阅读,请参阅Ted博客上的文章,Ayende Rahein,Jimmy Nilson,Scott Bellware,Alt.Net,Stephen Forte,Eric Evans等。

回答

我们可能会在comp.object上发现这篇文章很有趣。

我并没有声称同意或者不同意,但这很有趣,而且(我认为)与此主题相关。

回答

目前时间不多,但就在我的头顶上。。。

实体模型使我们可以为数据库(和其他可能的系统)提供一致的接口,甚至可以超出存储过程接口可以提供的接口。通过使用企业范围的业务模型,我们可以确保所有应用程序始终如一地影响数据,这是非常重要的。否则,我们将获得错误的数据,这简直就是邪恶。

如果只有一个应用程序,那么无论该应用程序或者数据有多大,我们实际上都没有"企业"系统。在这种情况下,我们可以使用与我们所谈论的方法类似的方法。请注意,如果我们决定将来扩展系统,则需要做的工作。

不过,我们应该牢记以下几点(IMO):

  • 生成的SQL代码不好(要遵循的例外)。抱歉,我知道很多人认为这可以节省大量时间,但是我从来没有发现能够产生比我编写的代码更有效的代码的系统,并且通常这些代码简直太恐怖了。我们通常还会最终生成大量从未使用过的SQL代码。这里的例外是非常简单的模式,例如查找表。虽然很多人对此感到迷惑。
  • 实体<>表(甚至必须是逻辑数据模型实体)。数据模型通常具有应与数据库尽可能紧密地实施的数据规则,其中可以包括有关表行如何相互关联的规则,或者对于声明性RI而言过于复杂的其他类似规则。这些应在存储过程中处理。如果我们所有的存储过程都是简单的CRUD proc,那么我们将无法做到这一点。最重要的是,CRUD模型通常会造成性能问题,因为它无法最大程度地减少网络与数据库之间的往返路程。这通常是企业应用程序中的最大瓶颈。

回答

为什么停在实体对象上?如果我们在企业级应用程序中看不到实体对象的价值,则只需使用纯功能/过程语言进行数据访问并将其连接到UI。为什么不切掉所有的OO"绒毛"呢?

回答

我们还应该讨论实体实际上是什么的概念。
当我阅读完该讨论时,我会觉得这里的大多数人都在从"贫血域模型"的角度看待实体。
许多人正在考虑将"贫血域模型"用作反模式!

丰富的领域模型具有价值。这就是域驱动设计的全部意义。
我个人认为OO是征服复杂性的一种方法。这不仅意味着技术复杂性(例如数据访问,UI绑定,安全性...),还意味着业务领域中的复杂性!

如果我们可以应用面向对象技术来分析,建模,设计和实现我们的业务问题,那么对于非平凡应用程序的可维护性和可扩展性来说,这是一个巨大的优势!

实体和表之间存在差异。实体应代表模型,表仅代表模型的数据方面!

数据的寿命确实比应用程序长,但是请考虑一下大卫·拉里比(David Laribee)的这句话:模型永远存在……数据是一种快乐的副作用。

有关此主题的更多链接:

  • 为什么二传手和吸气者是邪恶的
  • 纯OO的回报
  • POJO vs.NOJO
  • 超级模特第2部分
  • TDD,模拟和设计

回答

我一直在猜测,由SQL驱动的关系数据库是否与使用ActiveRecord范式的这些框架有所交叉。一个基本的问题是,AR(以及良好的OO设计)驱使我们分解逻辑。 SQL根本不适合语句分解。

我想知道对于数据库使用isam持久性模型是否会更好?与OO更好的阻抗匹配;在表中数据的基本概念上达成更多共识;与OO持久性的常规工件更加一致。一个很好的例子是FK及其关联可以更加明确。

RoR表示自己是数据库专家,我怀疑这个问题在很大程度上是原因。

有没有人试图将isam数据库用于ActiveRecord实现?

回答

我真的不确定我们认为"企业应用程序"是什么。但是我给印象是,我们将其定义为内部应用程序,其中RDBMS可以固定使用,并且该系统不必与任何其他系统(内部或者外部)都可以互操作。

但是,如果我们有一个数据库,其中包含100个表,而这些表仅相当于基本CRUD操作的每个表的4个存储过程,则该400个存储过程需要维护并且不是强类型的,因此容易出现拼写错误,也不能进行单元测试。当我们获得一位新的CTO(即一位开源传道者)并想要将RDBMS从SQL Server更改为MySql时,会发生什么?

如今,无论企业应用程序还是产品,许多软件都在使用SOA,并且对公开Web服务有一些要求,至少我本人并且曾经参与其中。
使用方法,最终会暴露出序列化的DataTable或者DataRows。现在,如果保证客户端是.NET并在内部网络上,则这可以视为可接受。但是,如果不知道客户端,那么我们应该努力设计一种直观的API,并且在大多数情况下,我们都不想公开完整数据库模式。
我当然不想向Java开发人员解释DataTable是什么以及如何使用它。还需要考虑带宽和有效负载大小以及序列化的数据表,因此数据集非常繁重。

软件设计没有灵丹妙药,它实际上取决于优先级在哪里,对我而言,它在单元可测试代码和松散耦合的组件中,任何客户端都可以轻松使用。

只是我的2美分

回答

真有趣的问题。老实说,我不能证明实体为什么好。但是我可以分享我为什么喜欢他们的观点。像这样的代码

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

无需担心来自数据库,Web请求,单元测试等的顺序。它使此方法更明确地声明其确切要求,而不是采用DataRow并记录其期望具有的列以及应具有的类型。如果我们以某种方式将其实现为存储过程,则同样适用,我们仍然需要将记录id推入存储过程,而数据库中不必存在该ID。

该方法的实现将基于订单抽象,而不是基于数据库中的精确程度。我执行的大多数此类操作实际上并不取决于如何存储此数据。我确实了解到,出于性能和可伸缩性的目的,某些操作需要与数据库结构耦合,仅以我的经验来看,其中并没有太多。以我的经验,经常知道Person具有.getFirstName()返回String以及.getAddress()返回Address以及address具有.getZipCode()等就足够了,并且不必关心哪些表涉及存储该数据。

如果我们必须处理所描述的问题,例如当其他列中断报告性能时,则DB对于任务至关重要,我们确实应该尽可能地接近它。虽然实体可以提供一些方便的抽象,但是它们也可以隐藏一些重要的细节。

可伸缩性是一个有趣的问题,在大多数需要巨大可伸缩性的网站(例如facebook,livejournal,flickr)中,它们倾向于使用DB-ascetic方法,这是因为尽可能少地使用DB,并且可缓存性(尤其是RAM的使用)解决了可伸缩性问题。 http://highscalability.com/上有一些有趣的文章。

回答

我为支持存储过程而对"将数据库锁定在石头上"的说法感到困惑。我可以采用ActiveRecord模型,并将其从MySQL迁移到Postgres再迁移到SQLite,非常感谢。除非我想全部重写它们,否则我无法使用任何基于proc的存储方式来做到这一点。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

我以为意思是我们将数据库模式牢牢地锁定在石头上。这种说法更有趣。从某种程度上讲,我认为这是从具有最小的单元测试和代码覆盖率的应用程序的角度出发的,这些应用程序是出于我们担心会破坏"某些东西"而不会更改代码的应用程序。

我对基于存储过程的系统的经验很少。我很好奇,在大型应用程序中,我们如何管理所有数据关系?在一页上,我显示带有图片的产品。在另一页上,我显示了产品和创建该产品的用户。在另一页上,我显示了产品及其评论。在另一页上,我需要显示没有图片的产品,并附有关于它的规格表……等等。我有一个具有很多关系的数据模型。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。我假设我们不为每种组合都编写一个存储的proc程序吗?不会。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。我担心的是DRY原则。我在重新左连接(有效地重新编码)我的关系的地方写了几个查询?而且,当我们谈论锁定模式时,我需要重写多少个存储过程?

回答

我想为OO和RDB之间的距离问题提供另一个角度:历史。

任何软件都具有现实模型,在某种程度上,它是现实的抽象。没有计算机程序可以捕获现实的所有复杂性,而编写程序只是为了解决现实中的一系列问题。因此,任何软件模型都是现实的缩影。有时,软件模型会迫使现实降低自己。就像我们想让汽车租赁公司为我们保留任何一辆汽车,只要它是蓝色且有合金的汽车一样,但由于要求不适合计算机,操作员无法遵守。

RDB源自将信息放入表格的一种非常古老的传统,称为会计。记帐是在纸上,然后在打孔卡上,再在计算机上完成的。但是会计已经成为现实。会计一直迫使人们遵循其系统,直到它已成为公认的现实。这就是为什么制作用于会计的计算机软件相对容易的原因,会计早在计算机问世之前就已经具有其信息模型。

鉴于良好的会计系统的重要性以及我们得到任何业务经理的认可,这些系统已经变得非常先进。现在,数据库的基础非常牢固,并且毫不犹豫地将重要数据保存在如此值得信赖的环境中。

我猜想,当人们发现现实的其他方面比会计(已经是模型)更难建模时,OO一定会出现。 OO已经成为一个非常成功的想法,但是OO数据的持久性却相对欠发达。 RDB / Accounting取得了轻松的胜利,但是OO是一个更大的领域(基本上所有不会计的领域)。

我们中的许多人都想使用OO,但我们仍然希望安全地存储数据。还有什么比像受人尊敬的会计系统一样存储我们的数据更安全的呢?这是一个诱人的前景,但我们都遇到了同样的陷阱。与RDB行业进行了大量努力相比,很少有人会想到OO持久性,RDB行业已经受益于会计的传统和职位。

Prevayler和db4o是一些建议,我敢肯定还有其他一些我没听说过的建议,但是似乎没有什么能像冬眠一样吸引媒体的一半。

对于多用户应用程序,尤其是Web应用程序,似乎甚至没有认真考虑将对象存储在良好的旧文件中。

在我为消除OO和RDB之间的鸿沟所做的日常努力中,我尽可能地使用OO,但要尽量减少继承。我不经常使用SP。我只会在看起来像会计的方面使用高级查询内容。

当鸿沟永久关闭时,我会感到惊讶。我认为,当Oracle启动" Oracle对象实例库"之类的解决方案时,解决方案便会出现。要真正流行起来,它必须有一个令人放心的名称。

回答

我认为,如今在企业解决方案中,实体对象已被过分强调。它们不能包含业务层功能,因为它们属于服务层的服务或者UI特定功能的UI层等。实体对象的确可以使设计人员在设计应用程序方面进行更好的思考,但不一定必须在其中包含所有应用程序逻辑。它们可以是遵循某些规则和接口的哑对象,并且可以用于在它们之上构建其他层,并充当层之间的数据载体。

回答

一个问题:如果所有业务逻辑都被困在数据库中,那么如何处理断开连接的应用程序?

在我感兴趣的企业应用程序类型中,我们必须处理多个站点,其中一些站点必须能够在断开状态下运行。

如果业务逻辑封装在可以轻松集成到各种应用程序类型的域层中-例如,作为一个dll,那么我可以构建了解业务规则并能够在必要时将其本地应用的应用。

为了将域层保留在数据库的存储过程中,我们必须坚持需要对数据库具有永久视线的单一类型的应用程序。

回答

可以在特定类别的环境中使用,但肯定不能涵盖企业应用程序的全部范围。

有时,应用程序和数据层并不是那么紧密地耦合在一起。例如,我们可能有一个电话计费应用程序。稍后,我们将创建一个单独的应用程序,该应用程序监视电话使用情况,以便a)更好地向我们宣传b)优化电话计划。

回答

这些应用程序有不同的关注点和数据要求(即使数据来自同一数据库),它们也会驱动不同的设计。如果让数据库来驱动代码,代码库可能会导致绝对混乱(在任何一个应用程序中),并且将是一场噩梦。

具有与数据存储逻辑分离的域逻辑的应用程序适用于任何种类的数据源(数据库或者其他)或者UI(Web或者Windows(或者Linux等))应用程序。

我们几乎陷在数据库中,如果我们对对当前数据库系统感到满意的公司,这也不错。但是,由于数据库会随着时间的推移而发展,因此可能会出现一个新的数据库系统,公司想使用它确实很新。如果他们想切换到Web服务的数据访问方法(如有时面向服务的体系结构会这样做),该怎么办。我们可能必须在各处移植存储过程。

此外,域逻辑还会抽象出UI,这在具有不断发展的UI的大型复杂系统中(尤其是当他们不断寻找更多客户时)尤其重要。

回答

同样,尽管我同意对存储过程和域逻辑的问题没有明确的答案。我正处于领域逻辑阵营中(并且我认为它们会随着时间的流逝而获胜),因为我认为,精心设计的存储过程比精心设计的领域逻辑更难维护。但这是另一场辩论

我看不到实体对象与可伸缩性有什么关系,我们可能正在谈论使用ORM工具,在这种情况下,我同意观点。

我对可伸缩性非常感兴趣。实体对象永远不会以方式构建高度可扩展的应用程序,但我们必须以正确的方式进行操作,换句话说,我们需要手写的DAL,而不是使用某些ORM生成的DAL。实际上,这就是为什么我不喜欢ORM的原因,没有比手写DAL更胜一筹的了,因为在许多地方我读到LINQ开销很大,所以我也不使用LINQ。我调整应用程序中的每个查询并创建所需的索引,我不让某些ORM为我生成代码。

我不同意Entity对象会使代码难以维护,实际上,此体系结构的整个目的是使维护和修改代码更容易,而这就是我在实践中看到的,我为很长时间(没有使用3层或者n层架构),所以我知道我在说什么。

回答

缓存还需要实体对象,我想知道如果不使用实体对象,如何使用数据集或者数据表,如何在应用程序中缓存数据?

老实说,我想如果我们能摆脱表单中的数据,那就去吧!但是,当事情变得棘手时,我们将明智地学习如何构造事物来获得一些简单性。

  • 代码重复越野车,代码不稳定
  • 加载了静态类的巨大类
  • 逻辑无处不在(aspx,静态方法,sql,triggers)
  • 与多个对象交互,共享共同的特征将困难重重

我还没有阅读所有答案,但是常见的问题很棘手:

至于域与数据。我认为数据将永远取胜,功能是所有与客户息息相关的事情。它必须工作。我支持重构,只要我们违反原则就可以按时交付有效的东西,就可以进行重构。

也是有关调试器,复杂域的快速介绍。我似乎很多人都害怕,因为他们碰到了界面,不了解非常高级的OOP /多态代码中可能出现的所有杂技。我完全理解,有时候我们会迷路和震慑。这就是为什么他们制造工具的原因。与一千行的繁琐方法相比,与一千个文件的解决方案相比,我不惧怕这种解决方案。我见过都信不信由你。

回答

如果我们愿意编写测试,也不必担心调试器和通过代码逐步调试,那么这里也有一个不错的选择。如果我们拥有良好的工具并找到平衡点,则可以解决上述所有问题,并使事情简单到可以解决的程度。

好吧,我想感谢我们进行的有趣的讨论。我正在通过Stephen Walther的ASP.NET MVC Framework Unleashed进行工作,并且我喜欢将其作为一种哲学练习,但是对于他的方法需要大量的代码,我感到有些震惊。现在,这并不是使用ORM所固有的-Rails以将我们从此类整理工作中解放出来而感到自豪,但是我真的在为是否必须编写和维护一个可以由应用程序使用的Record类而感到困惑。一个EntityRecord类,该实体将Record类映射到数据库。

他的好处在于,我们最终会得到一个可测试的应用程序,其中的测试可以快速运行,但是坦率地说,我宁愿以某种测试速度来执行应用程序中实际存在的代码。我认为,当我们花费一天时间进行跟踪并复制属性以使测试可以快速运行时,测试尾巴已经开始摇摇程序员的狗了-他们宁愿追赶兔子或者小睡一下火。

引用的第二个好处是我们可以使用应用程序并在其他数据库上运行它。是的,好的,也许如果我们正在编写诸如SalesForce的转售之类的东西,那可能是一个目标,但是对于90%或者更多的应用程序来说,那又如何呢?我想起了《这是美好的生活》中的邻居,那人给了乔治一罐钱,他说:"万一我有了丈夫,我会把这钱存起来以备离婚。"直到需要时才写它。

回答

另一方面,我确实对存储过程有异议。它的使用不一定是固有的,而是我工作过的一些脑力衰竭商店的功能:他们有时将DBA放在我要编写的代码中。我想以为我不是牛仔,但相反,我不想召集联合国委员会在表格中添加字段。

一个问题:如果数据源是Web服务,该怎么办?我只通过Web服务使用分布式数据编写应用程序。我是否希望使用与我的数据源是RDBMS时不同的范例来编写?

我不是问我们从RDBMS切换到Web服务时该怎么做(因为在内部商店中这不太可能),我问的是从一开始数据就来自Web服务时该怎么办?

回答

编程模型与RDBMS相比是否大不相同?如果是这样,则需要考虑可维护性。如果他们跳入的每个应用程序都使用不同的范例进行编程,那么我的开发人员将度过一个糟糕的时光。

诸如与集合相关的操作之类的某些逻辑倾向于在存储过程中更好地表示。然而,有时在编程代码中最好地表示具有许多分支和条件的算法。存储过程中无法实现用于解析支持脚本操作的运行时功能的命令的语法。

我在存储过程中看到的一个弱点是,我们倾向于为应用程序中的新列表或者网格获得一个新的存储过程。或者更糟糕的是,一个存储的proc可以将它们全部规则化,另外还有10个参数和case语句来进一步定义它们。此外,存储的proc变得非常庞大,甚至更加难以调试。

段落数量不匹配