随着我职业生涯的发展,我认为命名约定非常重要。我注意到人们扔掉了控制器、LibraryController
服务LibraryService
和提供者,LibraryProvider
并且在某种程度上可以互换使用它们。是否有任何具体的理由来使用一个与另一个?
如果有网站有更具体的定义,那就太好了。
随着我职业生涯的发展,我认为命名约定非常重要。我注意到人们扔掉了控制器、LibraryController
服务LibraryService
和提供者,LibraryProvider
并且在某种程度上可以互换使用它们。是否有任何具体的理由来使用一个与另一个?
如果有网站有更具体的定义,那就太好了。
根据上下文,这些术语可以彼此同义,这就是为什么每个框架或语言创建者都可以自由地在他们认为合适的时候明确声明它们……想想函数/方法/过程或流程/服务,几乎都是一样的但在不同的上下文中略有不同。
只是脱离正式的英语定义:
这些定义只是为了解释开发人员在定义框架或语言的术语时如何看待常见的英语含义;它并不总是一对一的,术语的相似性实际上为开发人员提供了一种命名非常相似但仍然略有不同的事物的方法。
例如,让我们以 AngularJS 为例。在这里,开发人员决定使用术语 Controller 来表示“HTML Controller”,一个 Service 来表示类似“Quasi Class”的东西,因为它们是用 New 关键字实例化的,而 Provider 实际上是 Service 和 Factory 的超集,它是也类似。您真的可以使用它们中的任何一个来编写任何应用程序,并且真的不会丢失任何东西;尽管在某些情况下一个可能比另一个好一点,但我个人认为这不值得额外的混乱......基本上他们都是提供者。Angular 的人可以将工厂、提供者和服务定义为一个单独的术语“提供者”,然后传入“静态”和“无效”之类的修饰符 像大多数语言一样,可以提供完全相同的功能;这本来是我的偏好,但是我学会了不要与你工作的框架的约定和术语作斗争,无论你多么不同意。
在Java Spring、 Spring Boot 和.NET中,您将拥有:
Repository
:在数据库中持久化数据并执行 SQL 查询。Service
: 包含大部分业务逻辑Controller
:定义 REST 端点,其中包含尽可能少的逻辑。从概念上讲,这意味着WHAT (功能)与HOW(技术)尽可能地分开。这些服务试图保持技术中立。相比之下,控制器只想定义一个外部通信合同。最后,存储库只想方便访问数据库。
以这种方式组织代码可以使业务逻辑保持简短、干净和可维护。不幸的是,将它们分开并不总是那么容易。例如,使用装饰器/注释形式的元数据来污染或丰富您的对象是很诱人的。(例如数据库列名和数据类型)。
一些开发人员没有看到这样做的危害并侥幸逃脱。其他人将他们的对象严格分开并定义多组对象。
拥有多个对象意味着您需要Mappers
将一种类型的对象转换为另一种。一些框架可以为您做到这一点(例如MapStruct
)。
声称严格总是一件好事很容易,但它会减慢你的速度。可以平衡一下。
在Node.js中,控制器和服务的概念是相同的。但是,该术语Repository
并不经常使用。相反,他们会称之为 aProvider
或者有时他们会概括Repositories
为一种Service
。
NestJS 对此有更强烈的看法(这可能是件好事)。NestJS (一个 Node.js 框架)的命名约定受到 Angular 命名约定的强烈影响,Angular 的命名约定当然是一种完全不同的框架(前端)。
(为了完整起见,在 Angular 中, aProvider
实际上只是可以作为依赖项注入的东西。大多数提供程序是Services
,但不一定。(它可能是 aGuard
甚至是 a Module
。AModule
更像是一组工具/驱动程序或连接器。)
PS:无论如何,这个术语Module
的使用有点混乱,因为还有“ES6模块”,这是完全不同的东西。)
ES6 和更现代的 javascript 版本(包括 typescript)在(反)构造对象时非常强大。这使得映射器变得不必要。
话虽如此,如今大多数 Node.js 和 Angular 开发人员更喜欢使用 typescript,它在定义类型方面比 java 或 C# 具有更多功能。
因此,所有这些框架都在相互影响。他们几乎都同意控制器和服务是什么。主要是具有不同含义的 Repository 和 Provider 词。这实际上只是一个约定问题。如果你的框架有约定,那就坚持下去。如果没有,那就自己挑一个。
我也在寻找一个比Provider更有意义的名字:)
并找到了这篇有用的帖子
这里的老开发人员偶然发现了这一点。我的观点以及我在过去 20 年中看到它的使用方式表明它因语言而异,但 Java C# 人群主要使用它们如下。
服务处理业务逻辑并处理域对象。您可以在控制器和其他服务中找到服务。
存储库不处理业务逻辑,而是充当域对象池(具有用于查找或持久化它们的辅助方法。服务通常包含存储库。存储库通常包含上下文并负责从基础设施形式的数据映射到域形式的数据如果定义已经分开。控制器通常还包含用于 crud 端点的存储库。
上下文处理域拥有的基础设施。大多数情况下,这是一个数据库,但上下文意味着任何接触此数据的东西都是通过(在)此上下文中进行的。上下文返回基础设施形状的数据。存储库通常包含上下文。直接在服务中的上下文有时是合适的。控制器中的上下文是一个硬性问题。
提供者提供对其他应用程序拥有的基础设施的访问。大多数情况下,这些是 rest api,但也可以是从其他人读取数据或将数据推送给其他人的 kafka 流或 rpc 类。如果您的某些域对象字段的真实来源发生更改,您可能会在存储库中的上下文旁边看到一个提供程序,并且您的存储库会处理将其余代码与该更改隔离开来。提供 rpc 功能的提供者经常出现在服务中。在微服务或网关或垂直切片架构中,您有时会直接在控制器中看到提供程序。
一位老人的意见,但我希望它有所帮助。