客户端上的实体是反模式吗? [英] Is Entities on Client side anti-pattern?

查看:102
本文介绍了客户端上的实体是反模式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前使用过RIA服务,现在正在测试Breeze Sharp.

I have used RIA service before, now testing Breeze Sharp.

RIA和Breeze给人的印象是,在服务器/中间层上看到的就是在客户端上看到的.为了支持这一点,在客户端和服务器上都使用了术语实体".它是一个实体,还是一个客户端上的演示模型或模型?

RIA as well as Breeze give an impression that what you see on the server/middle tier is what you see on the client. To support that, the term Entity is being used on both the client and the server. Is it really an Entity, or it really a Presentation Model or Model on the client?

对于具有一或两个级别实体图的较小系统,认为客户端和服务器相同是正确的.对于图形深入到五个或六个级别的大型系统,需要将实体转换为DTO才能使其变得简单.除非UI拥有一些用于实体的CRUD屏幕,否则大型应用程序最终将拥有更多的DTO和更少的实体.在大多数情况下,这些DTO将代表UI想要的东西,并且等同于表示模型.

For smaller systems having one or two level entity graphs, there may not be wrong in thinking both the client and the server is the same. For larger systems with graphs going deep into five or six levels, the entities need to be converted to a DTO to make it simple. Unless the UI has some CRUD screens for entities, large applications end up with more DTOs and less entities. Most of the time, these DTOs will represent what UI wants and is equivalent to a presentation model.

为什么我们不能将在客户端处理的内容作为展示模型而不是实体?

Why can't we consider what we deal with at the client as presentation models rather than entities?

推荐答案

您可以随意调用客户端实体类:-)

You are free to call the client-side entity class whatever you like :-)

更重要的是,让我们了解一下这是一种反模式这一说法背后的典型原因.

More seriously, let's get at the typical reasoning behind the claim that this is an anti-pattern.

我想对此非常清楚. Breeze是为富Web客户端应用程序而设计的. Breeze客户端不是表示层.它有一个表示层.它还具有自己的业务模型和数据访问层.

I want to be super clear about this. Breeze is designed for rich web client applications. A Breeze client is not a presentation layer; it has a presentation layer. It also has its own business model and data access layers.

术语实体"是指和"DTO"对不同的人意味着不同的事情.我喜欢 Evan的DDD定义用于实体";和 Fowler对"DTO" 的定义.com/amzn/click/com/0321127420"rel =" noreferrer"rel =" nofollow noreferrer> PoEAA .

The terms "entity" and "DTO" mean different things to different people. I like Evan's DDD definition for "entity" and Fowler's definition for "DTO" in PoEAA.

微风客户端实体符合Evans实体的资格:"具有在时间和不同表示形式中运行的独特身份的对象.您还会听到这些称为参考对象"的消息. [福勒].微风的实体不仅仅是财产袋;它们也具有业务逻辑,您可以使用更多自己的逻辑对其进行扩展.

Breeze client entities qualify as Evans entities: "Objects that have a distinct identity that runs through time and different representations. You also hear these called 'reference objects'" [Fowler]. Breeze entities aren't just property bags; they have business logic as well and you can extend them with more of your own.

微风实体不是表示模型" .它们独立于任何特定的UI表示,并且通常不实现表示方面的关注.

Breeze entities are not "presentation models". They are independent of any particular UI representation and typically do not implement presentation concerns.

它们 的设计使其可以直接绑定到可视控件.这是Breeze生产力设计的决定...关于我们如何实现实体的决定.某些人-认为实体属性是反模式的人-会讨厌这一点.埃文斯对这个问题保持沉默. 福勒大便.如果它冒犯了您,您可能不喜欢Breeze.继续前进.

They are designed such that they can be bound directly to visual controls. That's a Breeze productivity design decision ... a decision about how we implement entities. Some people - the people who think entity properties are an anti-pattern - will hate that. Evans is silent on that question. Fowler poo-poos it. If it offends you, you may not like Breeze. Move along.

我将争辩说这是错误的二分法.

I'm about to argue that this is a false dichotomy.

人们经常说""是通过电线发送实体的反模式.始终发送DTO ".这个措辞不佳的法令背后有合理的理由.当客户端和服务器实体类相同时,您已将服务器的实现与客户端的实现耦合在一起.如果模型在服务器上发生更改,则即使在更改仅与某一层相关时,也必须在客户端上进行更改,反之亦然.这可能会干扰您独立开发服务器和客户端代码的能力.我们可以接受,这种耦合只是权宜之计(而权宜之计也很重要!),但没人愿意.

People often say "it's an anti-pattern to send entities over the wire. Always send DTOs". There is sound reasoning behind this poorly worded edict. When a client and server entity class are identical, you've coupled the server's implementation to the client's implementation. If the model changes on the server, it must change on the client and vice-versa even if the change is only relevant on one of the tiers. That can interfere with your ability to evolve the server and client code independently. We may accept that coupling as a matter of expedience (and expedience matters!), but no one wants it.

Breeze client 实体类不必与 server 实体类相同,形状和业务逻辑上都不相同. .当您在Breeze中查询时,将 实体数据 放在网上,然后将其转换为客户实体;保存时,将客户端实体 data 放在网上,然后将其在服务器上转换为服务器实体. DTO可能在任一方向上都参与.重要的事实是类可以不同.

A Breeze client entity class does not have to be the same, neither in shape nor in business logic, as the server entity class. When you query in Breeze, you put entity data on the wire and transform it into client entities; when you save, you put client entity data on the wire and transform it on the server into server entities. DTOs may be involved in either direction. The important fact is that the classes can be different.

它们在概念上当然是相关的.如果Customer实体的含义在两侧大相径庭,那么您将有时间恶魔般地在两种表示形式之间转换数据.有或没有显式DTO都是如此.

They are conceptually related of course. You'll have a devil of a time transforming the data between the two representations if the meaning of the Customer entity diverges widely on the two sides. That's true with or without explicit DTOs.

我们也要承认,当类实际上相同时,在两个方向上转换数据都比较容易.当它们不同时,您需要支付映射税,并且可能会失去在客户端上编写Breeze LINQ查询的能力.您可以根据需要支付税款.微风不在乎.

Let's acknowledge as well that it is easier to transform the data in both directions when the classes are actually the same. You pay a mapping tax when they are different and you may lose the ability to compose Breeze LINQ queries on the client. You can pay the tax if you wish. Breeze doesn't care.

我的倾向是从双方相同的类开始,并在必要时进行更改.对于RIA Services和DevForce中的大部分课程来说,效果很好.最重要的是,当需要出现时,对我来说,重构各个班级从来都不是一件容易的事.

My inclination is to start with the same classes on both sides and change them when and as necessary. That has worked well for a high percentage of classes in RIA Services and DevForce. Most importantly, it has never been difficult for me to re-factor to separate classes when the need arose.

< rant> 烦恼夸大了共享类定义的风险,并低估了映射层的成本,而在应用程序的生命周期中,这种层的收益在实践中很少实现. rant>

<rant> The worrywarts exaggerate the risks of sharing class definitions and understate the cost of mapping layers whose benefits are rarely realized in practice during the lifetime of the application.</rant>

您写道:

对于图形深入到五个或六个级别的大型系统,需要将实体转换为DTO才能使其变得简单. ...在大多数情况下,这些DTO将代表UI想要的东西,并且等同于演示模型

For larger systems with graphs going deep into five or six levels, the entities need to be converted to a DTO to make it simple. ... Most of the time, these DTOs will represent what UI wants and is equivalent to a presentation model

根据我的经验,只有当您假设客户只是将实体粘贴到屏幕上时,这才是正确的.但是我已经规定客户端是应用程序,而不是表示层.

In my experience that is only true if you assume that your client simply pastes entities to the screen. But I have already stipulated that the client is an application, not the presentation layer.

我进一步认为,您需要在客户端上使用域模型的原因与在服务器上需要使用域模型的原因相同:推理域.您可以独立于演示文稿执行此操作.我假设您的实体会按照不同的显示规则以某种方式出现在多个屏幕上.它是同一模型,提供了多种方式.我们称此为"围绕数据旋转".

I further argue that you need a domain model on the client for the same reason that you need one on the server: to reason about the domain. You do this independently of the presentation. I assume that your entities will appear in some fashion on multiple screens subject to differing presentation rules. It's the same model, presented many ways. We call this "pivoting around the data".

无论您在模型上放置多少张面孔,基础模型数据和控制它们的业务规则都应保持不变.这就是使其成为域模型"的原因.而不是演示模型".

No matter how many faces you put on the model, the underlying model data and the business rules that govern them should stay the same. That's what makes it a "Domain Model" and not a "Presentation Model."

FWIW,我一直都有一个演示模型", (又称为"ViewModel"),以协调View的活动.因此,我不会问自己"PM还是模型?".相反,我选择将数据控件直接绑定到我通过VM的api 公开的模型实体,或者我将它们绑定到中间的"Item Presentation Model". (又称项目ViewModel"),用于包装某些实体.我走哪条路是应用程序的决定.在实践中,我首先直接绑定到实体,然后重构为"Item ViewModel".何时以及何时需要.

FWIW, I always have a "Presentation Model" (AKA "ViewModel") in my apps to orchestrate the activities of a View. So I don't ask myself "PM or Model?". Rather I choose either to data bind visual controls directly to model entities that I expose through the VM's api or I bind them instead to an intermediate "Item Presentation Model" (AKA "Item ViewModel") that wraps some entities. Which way I go is an application decision. In practice, I start by binding directly to the entities and refactor to an "Item ViewModel" when and as needed.

无论哪种情况,我都会在客户端上构建所需的PM(VM).如果我需要"Item ViewModel",那么我也会在客户端上创建它. 我不要求服务器准备DTO供客户端显示.对我来说这是一种反模式,因为它将服务器与客户端耦合在一起.

In either case, I will construct the PMs (VMs) that I need on the client. If I need an "Item ViewModel", I create that on the client too. I do not ask my server to prepare DTOs for my client to display. To me that is an anti-pattern because it couples the server to the client.

如何?如果开发人员需要更改客户端上的屏幕,则她可能必须等待有人提供支持服务器端点和DTO.现在,即使更改的推动力是客户要求,而不是服务器要求,我们也必须协调服务器和客户端的发布计划.

How? If the developer needs to change a screen on the client, she may have to wait for someone to provide the supporting server endpoint and DTO. Now we have to coordinate the release schedules of the server and client even though the impetus for the change was a client requirement, not a server requirement.

实际上比那更糟.一些服务器端开发人员必须停止正在做的事情,并添加新的服务方法以满足客户的需求.那不是她的要求之一……但是现在.随着时间的流逝,服务API会迅速扩展,并且很快便充满了看起来相似的成员,这些成员显然以略有不同的方式完成相同的工作.

It's actually worse than that. Some server-side developer has to stop what she's doing and add a new service method to satisfy a client requirement. That wasn't one of her requirements ... but it is now. Over time the service API expands enormously and soon it is full of look-a-like members that do apparently the same job in slightly different ways.

最终,我们忘记了谁在使用哪种方法以及用于什么方法.没有人敢改变现有的方法,以免破坏未知的客户.因此,开发人员复制了某种看起来正确的东西,使其有所不同,然后将其命名为其他东西.对于使用企业应用程序的任何人来说,这种服务API污染模式应该听起来很熟悉.

Eventually we forget who is using which method and what for. No one dares change an existing method for fear of breaking an unknown client. So the dev copies something that kind of looks right, make it a little different, and calls it something else. This pattern of service API pollution should sound familiar to anyone who has worked with enterprise applications.

每个看似规则"的地方意味着要被打破.当然,有时让服务器准备要显示的数据既方便又有效.这种情况最常见于大量的只读数据,这些数据汇总了数据层上甚至更大个复杂数据.当我走这条路线时,通常会受到性能方面的考虑.否则,我会忠实于面向实体的体系结构.

Every seeming "rule" is meant to be broken. Of course there are occasions when it is both expedient and efficient to let the server prepare data for display. This happens most frequently with high volume, read-only data that summarize an even larger volume of complex data on the Data Tier. When I go this route, I'm typically motivated by performance considerations. Otherwise, I stay true to the entity-oriented architecture.

当我的应用程序中的 everything 看上去都符合例外条件时,我得出结论:我为此特定应用程序使用了错误的体系结构 ...,因此不应不是微风应用程序.我不知道这是否是你的情况.

When it looks like everything in my app conforms to the exception, I conclude that I've got the wrong architecture for this particular application ... and this shouldn't be a Breeze app. I don't know if this is your case or not.

希望这会有所帮助.

这篇关于客户端上的实体是反模式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆