如何将客户端与服务器端解耦?
How is decoupling client side from server side possible?
当涉及到 SPA 客户端应用程序和 API/REST 后端时,我一直在努力解决松散耦合的概念。每个人似乎都在说将前后端代码紧密耦合是一种不好的做法,我明白为什么。
但我的问题是,在服务器和客户端应用程序都需要相同模型并且可以对这些模型进行更改的情况下,如何让它们保持松散耦合?我想你将不得不为模型声明复制代码(这也是不好的做法)或者让客户端代码知道后端的模型结构。
例如,假设我正在客户端上编写类似 object.someprop = 'some value'
的代码,但 someprop
不再是 属性 或已在服务器上更新。然后我还必须更新客户端,据我所知,这属于紧密耦合的范畴。
看来在客户端写object.someprop
之类的东西也是不对的。但如果我不这样做,我怎么能让用户与数据交互?[=13=]
有人能告诉我一些关于这里应该发生什么的信息吗?
客户端会对服务端提供的接口产生依赖,比如REST接口、graphql、flatbuffer等。这个接口可以看作是服务端和客户端约定的契约。这确实暗示了所提供的数据结构,并且是一种 耦合 的形式。因此需要清楚地描述/定义 APIs 并制定版本控制和废弃它们的策略 - 至少如果有多个客户端使用 API 并且客户端和服务器不能同时发布。对于只有服务器生成的 html 客户端的基本 Web 应用程序,您可以跳过 API 版本控制。
所以乍一看这似乎是紧密耦合,但不一定如此。客户端和服务器可能会或可能不会使用相同的语言/数据表示。他们所同意的只是访问方式和传输格式。通常有额外的转换 to/from 传输格式,例如 JSON 到 javascript 对象。在这个例子中,客户端可以自由地使用 JSON 做任何它想做的事情。它可以使用所有数据或仅使用一个属性。所有这些都与服务器无关。同样,客户端不关心服务器如何创建此 JSON 字符串。它可以在 golang 中实现并具有完全不同的内部表示——客户不会知道。由于服务契约仅描述接口和由此产生的服务器/客户端实现的自由度,耦合可以被认为是松散的(足够)。
在您的具体示例中,您似乎描述了在服务器和客户端上都使用 javascript 的场景,并且您想知道是否可以使用相同的代码库(至少代表对象)。您可以为接口部分执行此操作(查看 graphql approach),但通常最好在服务器上使用单独的内部对象类型,因为通常您会发现需要添加额外的属性、内部处理的引用提供给客户的目的或不安全的目的(想想密码、隐私相关数据、秘密等)。
你必须在更广泛的意义上区分 松散耦合 和 继承 而不仅仅是子类化。当您需要完全相同的模型被客户端和服务器重复使用时 - 这完全没问题,而且 正常 要做的事情。您只需引入 Shared 程序集(有时也称为 Core)并定义通用的东西(包括抽象 类,它们假设有不同的实现关于 client/server 必需品)那里。这并不意味着紧密耦合 除非您不费心将接口与实现分开 ,好吗?松散耦合完全取决于 interfaces/adtract 类而不是具体的实现:您可以共享一些通用的实现,但即使这样,一般来说,客户端和服务器也不应该依赖它们; inputs/outputs 的所有函数必须是实现未知的。
当涉及到 SPA 客户端应用程序和 API/REST 后端时,我一直在努力解决松散耦合的概念。每个人似乎都在说将前后端代码紧密耦合是一种不好的做法,我明白为什么。
但我的问题是,在服务器和客户端应用程序都需要相同模型并且可以对这些模型进行更改的情况下,如何让它们保持松散耦合?我想你将不得不为模型声明复制代码(这也是不好的做法)或者让客户端代码知道后端的模型结构。
例如,假设我正在客户端上编写类似 object.someprop = 'some value'
的代码,但 someprop
不再是 属性 或已在服务器上更新。然后我还必须更新客户端,据我所知,这属于紧密耦合的范畴。
看来在客户端写object.someprop
之类的东西也是不对的。但如果我不这样做,我怎么能让用户与数据交互?[=13=]
有人能告诉我一些关于这里应该发生什么的信息吗?
客户端会对服务端提供的接口产生依赖,比如REST接口、graphql、flatbuffer等。这个接口可以看作是服务端和客户端约定的契约。这确实暗示了所提供的数据结构,并且是一种 耦合 的形式。因此需要清楚地描述/定义 APIs 并制定版本控制和废弃它们的策略 - 至少如果有多个客户端使用 API 并且客户端和服务器不能同时发布。对于只有服务器生成的 html 客户端的基本 Web 应用程序,您可以跳过 API 版本控制。
所以乍一看这似乎是紧密耦合,但不一定如此。客户端和服务器可能会或可能不会使用相同的语言/数据表示。他们所同意的只是访问方式和传输格式。通常有额外的转换 to/from 传输格式,例如 JSON 到 javascript 对象。在这个例子中,客户端可以自由地使用 JSON 做任何它想做的事情。它可以使用所有数据或仅使用一个属性。所有这些都与服务器无关。同样,客户端不关心服务器如何创建此 JSON 字符串。它可以在 golang 中实现并具有完全不同的内部表示——客户不会知道。由于服务契约仅描述接口和由此产生的服务器/客户端实现的自由度,耦合可以被认为是松散的(足够)。
在您的具体示例中,您似乎描述了在服务器和客户端上都使用 javascript 的场景,并且您想知道是否可以使用相同的代码库(至少代表对象)。您可以为接口部分执行此操作(查看 graphql approach),但通常最好在服务器上使用单独的内部对象类型,因为通常您会发现需要添加额外的属性、内部处理的引用提供给客户的目的或不安全的目的(想想密码、隐私相关数据、秘密等)。
你必须在更广泛的意义上区分 松散耦合 和 继承 而不仅仅是子类化。当您需要完全相同的模型被客户端和服务器重复使用时 - 这完全没问题,而且 正常 要做的事情。您只需引入 Shared 程序集(有时也称为 Core)并定义通用的东西(包括抽象 类,它们假设有不同的实现关于 client/server 必需品)那里。这并不意味着紧密耦合 除非您不费心将接口与实现分开 ,好吗?松散耦合完全取决于 interfaces/adtract 类而不是具体的实现:您可以共享一些通用的实现,但即使这样,一般来说,客户端和服务器也不应该依赖它们; inputs/outputs 的所有函数必须是实现未知的。