我想使用REST来创建一个API,该API与数据库中的数据进行交互(存储)。
当我阅读一些设计模式时,我遇到了远程外观,而我读的书中提到该外观的作用是将过程方法从远程调用转换为精细的本地调用,并且< strong>它不应有任何多余的逻辑。作为说明,它说该程序在没有这种外观的情况下仍应该可以运行。
但是我有两个问题:
考虑到我也有一个数据库,将常规调用分为每个属性的特定调用是否有意义?仅具有一个通用的“获取数据”方法对数据库运行一个查询并将其转换为可用的对象以减少数据库调用的数量,是否更有意义?因此,与其拆分获取地址来获取街道,获取城市,获取邮政编码,还不如通过数据库调用获取所有这些信息。
牢记所有这些,在我使用golang的情况下,应如何根据文件和功能来构造项目?
假设所有问题都是肯定的,那么以下结构有意义吗?
答案 0 :(得分:0)
首先,如Mike Amundsen所述
您的数据模型不是您的对象模型不是您的资源模型不是您的负担能力模型
Jim Webber确实说过something very similar,即通过实现REST体系结构,您将拥有一个Web形式的集成模型,该模型由HTTP控制,另一个由域模型控制。尽管您的数据库中的数据与您发送的表示形式之间没有1:1的映射,但是资源会熟练地将您的领域模型推向世界。一个典型的REST系统确实比域模型中具有数据库条目的资源更多。
话虽如此,很难就如何构造项目提供具体建议,尤其是在要使用的特定框架方面。关于Robert“ Uncle Bob” C. Martin在研究代码结构时,它应该告诉您有关应用程序意图的信息,而不是您使用的框架¹。据他Architecture is about intent说。尽管您通常会看到由Maven,Ruby on Rails等框架强加的默认结构,但对于golang
,您可能应该通读某些文档或blogs,它们可能会或可能不会给您你有一些想法。
就访问数据库而言,您可以尝试遵循一种微服务体系结构,其中每个服务都维护自己的数据库,或者您可以尝试像充当整体系统并在其所有部分之间共享数据库的分布式整体式架构。如果要扩展到广泛的范围,并且有几个并行服务使用数据,即在使用消息代理的情况下,则可能需要分布式锁和/或队列,以确保多个实例不能同时使用数据。
但是,您应该做的是以能够很好扩展的方式设计数据层。许多开发人员经常忘记或低估的是他们从缓存中可以获得的好处。链接基本上是在Web上用于从一种资源引用到另一种资源,并通过使用定义明确的链接关系名称为关系提供某种语义上下文。链接关系还允许服务器控制其自己的名称空间并根据需要更改URI。但是URI不仅是客户端可以调用的资源的指针,还是缓存的键。缓存可以在多个位置进行。在服务器端,避免进行昂贵的计算或在客户端进行查询,以避免一般或在中间跃点上发送请求,从而避免了来自大量请求服务器的压力。菲尔丁提出caching even a constraint,需要予以尊重。
关于应为哪些属性创建查询的属性完全取决于您尝试描绘的用例。在给出地址示例的情况下,一次返回所有地址信息确实很有意义,因为很少会自己查询街道或邮政编码。如果该地址是某些用户或雇员数据的一部分,则是将该信息作为用户或雇员数据的一部分还是作为应作为进一步请求的一部分而应自行查询的链接来返回则更加含糊。您返回的内容还可能取决于媒体类型客户端的功能以及您的服务是否同意(内容类型协商)。
如果您为某些足球运动员和他们所属的某些类别(例如,他们的球队以及他们是进攻还是防守球员)实施了grouping之类的内容,则您可能拥有Team A
资源包括所有播放器作为嵌入式数据。在数据库中,您可以拥有自己的球队表并引用各自的球员,或者球队可以只是球员表中的一列。我们不知道,客户通常也不会打扰。但是,从设计角度来看,您应该意识到在同时提供所有玩家方面的好处和后果,以提供与各个玩家的链接,或者使用呈现某些基础数据和链接的混合方法来了解更多详细信息。
后一种方法可能是最明智的方法,因为它为客户提供了足够的信息来确定是否需要更详细的数据。如果需要,对提供的URI进行简单的GET请求就足够了,该请求可能由缓存提供服务,因此根本无法到达实际的服务器。第一种方法肯定具有缺点,即无法最佳地重用缓存,并且可能返回比实际需要更多的数据。仅包含链接的方法可能无法提供足够的信息,无法迫使客户执行跟进请求以了解有关团队成员的数据。但是如前所述,您作为服务设计者可以决定将哪些URI或查询返回给客户端,从而可以相应地设计系统和数据模型。
通常,您在REST体系结构中所做的就是为客户提供选择。优良作法是将整个交互流程设计为a state machine,通过接收请求和返回响应来遍历。由于REST使用与Web相同的交互模型,因此设计整个系统似乎更自然,就像您要为Web实现该模型,然后将设计应用于您的REST系统一样。
控制器是否应该包含业务逻辑主要是一个自以为是的问题。正如Jim Webber正确指出的那样,HTTP是REST的事实上的传输层,是
应用协议,其应用域是通过网络传输文档。这就是HTTP所做的。它移动文档。 ... HTTP是一个应用程序协议,但不是您的应用程序协议。
他进一步指出,您必须将HTTP缩小为域应用程序协议,并触发业务活动,这是在网络上移动文档的副作用。因此,触发文档通过网络移动文档的副作用。没有明确的规则是否在控制器中包含业务逻辑,但是通常您会尝试将业务逻辑保留在它们自己的层中,即作为您仅从控制器内部调用的服务。这样就可以测试业务逻辑,而无需控制器,因此也不需要真实的HTTP请求。
尽管此答案不能提供更详细的信息,部分是由于问题本身的广泛性,我希望我能阐明您应该考虑哪些方面,并且您的数据模型不一定是您的资源或收费模型。