Interfaces on different logic layers假设您有一个分为3层的应用程序:GUI,业务逻辑和数据访问。在您的业务逻辑层中,您已经描述了您的业务对象:getter,setter,accessors等……您就明白了。与业务逻辑层的接口保证了业务逻辑的安全使用,因此您调用的所有方法和访问器都将验证输入。 这是您第一次编写UI代码时的绝佳选择,因为您拥有一个可以信任的简洁定义的界面。 但这是棘手的部分,当您开始编写数据访问层时,业务逻辑的接口无法满足您的需求。您需要有更多的访问器和获取器来设置/曾经被隐藏的字段。现在,您被迫侵蚀您的业务逻辑接口。现在可以从UI层设置字段,而UI层没有业务设置。 由于数据访问层所需的更改,与业务逻辑的接口已经侵蚀到可能甚至用无效数据设置业务逻辑的地步。因此,该接口不再保证安全使用。 我希望我已经足够清楚地解释了这个问题。如何防止接口腐蚀,保持信息隐藏和封装,同时又适应不同层之间的不同接口需求? 如果我正确理解了这个问题,则说明您已经创建了一个域模型,并且希望编写一个对象关系映射器来映射数据库中的记录与域对象之间的映射。但是,您担心要使用"管道"代码来污染域模型,而这对于读取和写入对象的字段是必不可少的。 退后一步,您基本上有两种选择,可以将数据映射代码放置在何处-在域类本身内还是在外部映射类内。 例如
在此示例中,我们有一个对象,该对象代表一个具有名称和AccountStatus的用户。我们不想直接设置状态,也许是因为我们要检查更改是否是有效的状态转换,所以我们没有设置器。幸运的是,GetById和Save静态方法中的映射代码可以完全访问对象的名称和状态字段。 第二个选项是拥有第二个类,该类负责映射。这样做的好处是可以分离出业务逻辑和持久性的不同方面,这可以使您的设计更具可测试性和灵活性。这种方法的挑战在于如何将名称和状态字段公开给外部类。一些选项是: 中使用好友功能 有关更多信息,我推荐Martin Fowler的经典著作《企业体系结构模式》 不过,警告一下,在继续编写自己的映射器之前,我强烈建议您考虑使用第三方对象关系映射器(ORM)工具,例如nHibernate或Microsoft的Entity框架。我从事过四个不同的项目,由于各种原因,我们编写了自己的mapper,很容易浪费很多时间来维护和扩展mapper,而不是编写提供最终用户价值的代码。到目前为止,我已经在一个项目上使用了nHibernate,尽管最初它的学习曲线相当陡峭,但您早期投入的投资却能获得可观的回报。 这是一个经典问题-将域模型与数据库模型分离。有几种方法可以攻击它,我认为这实际上取决于项目的大小。您可以像其他人所说的那样使用存储库模式。如果您使用的是.net或Java,则可以使用NHibernate或Hibernate。 我要做的是使用测试驱动开发,因此我首先编写了UI和Model层,并且对Data层进行了模拟,因此UI和Model围绕领域特定对象构建,然后将这些对象映射到我所使用的任何技术上\\正在使用数据层。让数据库确定您的应用程序的设计,先编写应用程序,然后再考虑数据是一个非常糟糕的主意。 ps问题标题有点误导人 @冰^^热度:
UI向业务层中的ServiceClass寻求服务,即获取由具有所需参数数据的对象过滤的对象列表。 然后,UI想要编辑项目X。它将项目(或业务对象)发送到业务层中的服务。业务层将验证对象,如果可以,则将其发送到数据层进行存储。 UI知道业务层中的服务,而业务层又知道数据层。 UI负责将用户输入的数据与对象进行映射,数据层负责将db中的数据与对象进行映射。业务层保持纯粹的业务。 :) 我将继续我的习惯,违背常规,说您应该质疑为什么要构建所有这些极其复杂的对象层。 我认为许多开发人员将数据库视为对象的简单持久层,并且只关心那些对象所需的CRUD操作。对象模型和关系模型之间的"阻抗不匹配"花费了很多精力。这是一个主意:停止尝试。 编写存储过程以封装数据。根据需要使用代码中的结果集,DataSet,DataTable,SqlCommand(或等效的java / php /任何形式)与数据库进行交互。您不需要那些对象。一个很好的例子是将SqlDataSource嵌入到.ASPX页中。 您不应尝试向任何人隐藏您的数据。开发人员需要准确了解与物理数据存储进行交互的方式和时间。 对象关系映射器是魔鬼。停止使用它们。 构建企业应用程序通常是管理复杂性的一种练习。您必须使事情尽可能简单,否则您将拥有一个绝对无法维护的系统。如果您愿意允许某种耦合(无论如何在任何应用程序中都是固有的),则可以消除业务逻辑层和数据访问层(用存储过程代替它们),并且您不需要任何这些接口。 您可能希望将接口分为两种类型:
可以继承和实现两组接口,例如:
这样,在您的数据层中,您仅需要查看IData的接口实现,而在您的UI中,您仅需要查看IView的接口实现。 您可能要使用的另一种策略是在UI或Data层中组合对象,以使它们仅被这些层消耗,例如,
这又使您的业务对象对UI / View层和数据层均一无所知。 因此问题在于业务层需要向数据层公开更多功能,而添加此功能意味着向UI层公开太多功能?如果我正确地理解了您的问题,这听起来像是您在尝试通过单个界面满足太多的要求,这只会使它变得混乱。为什么没有两个接口连接到业务层?一个可能是用于UI层的简单,安全的界面。另一个将是数据层的较低级接口。 您也可以将这种两接口方法应用于需要同时传递到UI和数据层的任何对象。
这是什么意思,即数据层不应该知道业务逻辑层?您如何用数据填充业务对象? 我经常这样做:
这可能是一个解决方案,因为它不会侵蚀接口。我想你可能会有这样的课:
我总是创建一个单独的程序集,其中包含:
顺便说一句。为什么要在业务逻辑层中定义方法以容纳数据层? |