(太多)复杂对象的宁静架构问题
好吧,我负责这个 RESTful 架构的服务器和客户端(内部使用)部分。 (使用restlet)。
我们有一个公开 Post 操作的资源。这是一个简化版本:
public class UserResource {
@Post
public Representation create(UserRegistration registration) {
SomeService.getInstance().createUser(registration);
return new XstreamRepresentation(new RegistrationResponse(registration.getUniqueCode()););
}
几个月来,我们是唯一使用这些服务的人,因此域对象在客户端和服务器端之间共享......并且它一直工作得很好。
现在我们必须记录这些资源并让其他客户端使用它们,但出现了一些“问题”,这让我认为这个 API 可能有点太复杂了。
以邮政服务为例。 内部方法接受复杂类型UserRegistration
public class UserRegistration implements Serializable {
private Profile profile;
private Boolean someBooleanProperty;
public UserRegistration(Profile profile) {
this(profile, true);
}
public Profile getProfile() {
return profile;
}
public boolean isSomeBooleanProperty() {
return someBooleanProperty;
}
}
,而后者又使用另一个复杂对象(Profile)
public class Profile {
private String nickname;
private String email;
private String password;
private String firstname;
private String lastname;
private Date birthDate;
private String phone;
private Address address;
private GenderType gender;
private String subscriptionSite;
private Date privacyAcceptanceDate;
private Date subscriptionDate;
private String activationCode;
private String socialSecurityNumber;
...
,该对象使用大量复杂类型等等。
这种复杂类型的使用才是真正让我烦恼的地方。 我要么不知道如何记录这一点(除了列出这些复杂对象内部属性的长长列表),要么我只是迷失了。
我的问题是: 我必须简化吗? 这个架构设计得很糟糕吗? 一些构建器方法可以解决问题吗?
Alright, I've been put in charge of both the server and client (used internally) part of this RESTful architecture. (using restlet).
We've got a resource that exposes the Post operation. Here's a simplified version:
public class UserResource {
@Post
public Representation create(UserRegistration registration) {
SomeService.getInstance().createUser(registration);
return new XstreamRepresentation(new RegistrationResponse(registration.getUniqueCode()););
}
For a few months, we've been the only ones using these services, so domain objects were shared across client and server sides... and it's been working just fine.
Now that we have to document these resources and let other clients use them some "issues" have been arising that made me think this API might be a little too complicated.
This Post service, for example.
The internal method accepts complex type UserRegistration
public class UserRegistration implements Serializable {
private Profile profile;
private Boolean someBooleanProperty;
public UserRegistration(Profile profile) {
this(profile, true);
}
public Profile getProfile() {
return profile;
}
public boolean isSomeBooleanProperty() {
return someBooleanProperty;
}
}
which, in turn, uses another complex object (Profile)
public class Profile {
private String nickname;
private String email;
private String password;
private String firstname;
private String lastname;
private Date birthDate;
private String phone;
private Address address;
private GenderType gender;
private String subscriptionSite;
private Date privacyAcceptanceDate;
private Date subscriptionDate;
private String activationCode;
private String socialSecurityNumber;
...
which is using a lot of complex types and so on.
This use of complex types is what really bugs me.
I either don't know how to document this (apart from making a long long list of these complex objects inner properties) or I'm just lost.
My questions are:
Do I have to simplify?
Is this architecture very bad-designed?
Would a few builder methods do the trick?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过在客户端和服务器之间共享域实体类型,您(没有具体说您)已经完全击败了 REST 的要点。 RESTful 系统应该只共享媒体类型和链接关系。使用 SOAP 共享类型要容易得多,因为 WSDL 允许工具包处理保持客户端和服务器类型同步的细节。
REST 的目的就是减少客户端和服务器之间的耦合,使它们能够独立发展。显然,如果您有大量共享类型,那将会很困难,这就是为什么您目前有这种不好的感觉。
我针对这个问题采取的解决方案是定义两种媒体类型。一种是通用实体数据容器。我们将其称为 BusinessDocument,另一个称为 BusinessLayout。客户端使用 BusinessDocument 从服务器检索所有数据,并且 BusinessLayout 提供“数据绑定”信息,以便客户端知道在 UI 中的何处显示不同的业务数据。
通过这样做,我能够构建一个客户端,它实际上不理解它正在处理的数据的细节,它只知道如何在 UI 上显示它以供用户交互。通过这样做,我能够使用单一媒体类型来描述数百个不同的业务实体。
By sharing domain entity types between the client and the server, you (not saying you specifically) have completely defeated the point of REST. RESTful systems are supposed to share only media types and link relations. Sharing types like you are doing is much easier with SOAP because WSDL allows toolkits to take care of the details of keeping the client and server types in sync.
REST is all about reducing the coupling between client and server to allow them to evolve independently. Obviously, if you have a large set of shared types, that is going to be difficult, which why you currently have this bad feeling.
The solution I have taken to this problem is to define two media types. One is sort of a generic entity data container. Let's call it BusinessDocument, and the other is called BusinessLayout. The client uses the BusinessDocument to retrieve all the data from the server and the BusinessLayout provides "data binding" information so the client knows where in my UI to display the different pieces of business data.
By doing this I am able to build a client that really doesn't understand the specifics of the data it is dealing with, it just knows how to display it on the UI for the user to interact with. By doing this, I am able to use a single media type, to describe hundreds of different business entities.
无需将 java 客户端提供给外部消费者。您的 API 应该能够响应任何 Http 客户端。事实上,有一个共享对象的 Java 客户端可能取决于不同的因素,但不应影响您向第三方消费者公开 REST API 的方式。
因此,我建议开始使用 apache commons HTTP 编写一个纯 HTTP 客户端,以查看 REST API 的行为方式。
服务器对象很复杂这一事实也不应该引起 API 的任何兴趣。如果旧系统是围绕数据建模对象而设计的(我认为这是一个坏主意),那么这是您必须处理的事情。
从 REST API,您始终只接收文本、XML 或 JSON,并且最终必须将其解析为 Java 对象(如果您有 ORM + RDBMS 支持的系统)。如果您可以像在文档数据库上一样存储 Json,则不会遇到此问题,但同样,这与 REST API 本身无关,但您需要一个将 JSON 转换为 Java 对象的层。
Restlet 可以帮助你做到这一点,当然如此复杂的对象并不是一个容易自动转换的对象。
There's no need to give the java client to external consumers. Your API should be able to answer to any Http client. The fact that there is a java client that shares the object can depend on different factors but should not influence how you expose your REST API to third party consumer.
So I'd suggest to start writing a pure HTTP client, using apache commons HTTP, to see how your REST API behaves.
The fact that the server objects are complex also should not be of any interest of the API. If the old system was designed modeling object around data, which I consider a bad idea, that's something you have to deal with.
From the REST API you always receive just text, XML or JSON, and you have eventually to parse it into your Java Object, if you have for example and ORM + RDBMS backed system. If you could store Json, like on a a document DB, you do not have this problem but, again, this is of no concern of the REST API per se, but you need a layer that transform JSON to Java Object.
Restlet helps you with this, of course such complicated object is not an easy one to be automagically converted.