javascript如何在NodeJs中应用Java/Spring的分层架构?
我一直在努力学习NodeJS已经有一段时间了。所有的书籍和教程似乎都遵循相似的代码结构模式。范例-
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/', (req, res) =>{
res.render('index');
});
app.get('/getName', (req, res) =>{
// Mock DB call to fetch Name
res.render('displayName');
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
如上所示,/getName控制器正在执行DB调用并返回视图。因此,业务逻辑和CRUD操作是在同一个地方完成的
我来自JAVA
的世界,在那里我们做的略有不同。例如,Spring Boot
应用程序将包含以下结构-
- DTO
- 存储库
- 服务
- 控制器
因此,controller
类是实际的端点,它们不执行任何业务逻辑,而是调用底层的service
类来处理所有这些。service
类实现业务逻辑,并在repository
类的帮助下持久化/获取所需的数据。另一方面,存储库处理CRUD
操作
这似乎是一种开发软件的明智方法。考虑到每个类都有自己定义的角色,处理任何更改都变得非常容易
我知道NodeJs
是一个动态的但-
1。有没有办法像我们在Spring
中那样分离功能?如果没有,则
2。如何构造具有多个端点和DB事务的大型项目强>
问候
编辑-
考虑下面的场景-
我有一个需求,需要从数据库中获取状态为True的用户列表(假设状态是模型中的布尔字段)
在爪哇-
@Service
public class UserService {
@Autowired
UserDetailRepository userDetailRepository;
@Override
public UserDetail getUserDetail (boolean status) {
UserDetail userDetail = UserDetailRepository .findUserDetailByStatus(status);
return userDetail ;
}
控制器。爪哇-
@GetMapping("/getUserDetails")
public ArrayList<UserDetail> getUserDetail(){
return UserService.getUserDetail(true);
}
现在,如果需求发生变化,需要一个新的端点,只返回状态为true的前10个用户详细信息。在这种情况下,我们可以添加一个新的控制器,只需将返回的结果限制为10。我们可以使用相同的业务逻辑/服务类
控制器。爪哇
@GetMapping("/getUserDetailsTop10")
public ArrayList<UserDetail> getUserDetail(){
List<UserDetails> users = UserService.getUserDetail(true);
// Filter the list to send top 10
// return users .
}
如果我必须在NodeJS中实现相同的用例,我必须编写业务逻辑来获取用户两次-
const express = require('express');
const app = express();
app.set('view engine','hbs');
app.get('/getUserDetails', (req, res) =>{
// Call DB and get users whose status is True
res.send(userdetails);
});
app.get('/getUserDetailsTop10', (req, res) =>{
// Call DB and get users whose status is True
// Filter the returned results and limit the result to 10 values only
res.send(userdetails);
});
app.listen(3000, () => {
console.log("Started server on port : 3000");
});
充其量,我可以将这个逻辑抽象为一个函数,它将返回一个状态为True的用户列表,但这种方法的可扩展性不是很强。必须将业务逻辑与控制器完全分离
# 1 楼答案
用户服务。js
用户控制器。js
应用程序。js
我故意“扭曲”我的js代码,使之与java风格相匹配,这样也许你会觉得宾至如归。就我个人而言,我不这样写js,我更喜欢使用函数方式而不是类
我没有包括我使用的两个decorator(
@RouterAdapter, @GetMapping
)的实现,这是一个与讨论无关的细节。我可以向你保证这在js中是可行的。唯一缺少的是js没有运行时方法重载,所以我必须命名2个diff-controller方法我在这里要说的是,设计模式大多与语言无关。如果你熟悉lang,你总能找到一种处理好分离关系的方法
现在我有意在上面的示例中使用类,但作为用户服务的函数并不会降低它的可重用性。我不明白你为什么认为“它不可伸缩”
# 2 楼答案
一个想法:
然后你把你的逻辑写成
function userDetails({ limit, ...rest } = { limit: 0 })
在另一个文件中,即
usersBusinessLogic.js
:之后,您可以调用
GET /userDetails
或GET /userDetails?limit=10
让我知道你的想法
# 3 楼答案
不是一个真正的答案。。。但我有一些想法,因为我来自C#,三年前开始从事NodeJs开发
依赖注入
遗憾的是,在我看到的许多NodeJs项目中,这很少使用。有一些npm模块提供了这一功能,但没有一个模块能让我信服正确的方法和API。依赖注入仍然是完全可能的,只是因为需要编写一些样板代码,所以有点难看。不幸的是,没有简单的方法。所以,是的,你可以像Spring一样进行依赖注入,但不是那么方便。但我的观点并不能阻止你们研究node的依赖注入库
架构
您仍然可以使用DTO、存储库、服务和控制器的概念。只是出于一些(奇怪的)原因,大多数教程和指南都忘记了常识架构,只是把所有东西都放在一个控制器中。不要让它们引诱你忘记你在Java中学到的概念。并不是说OOP和Java没有缺陷,而是“编写JavaScript风格的代码”和“让我们一起忘记正确的体系结构”是有区别的
请注意,您可能会看到更多的“函数式编程”模式出现在NodeJs社区中,这并不坏(但OOP也不坏)
忽略你在那里看到的不好的例子,只需跟随你的直觉,从你的Java体验中了解如何用正确的层、责任和设计模式来构造你的代码。只需记住,你没有接口,没有简单的替代方案。所以你必须学会如何解决这个问题,但是你仍然可以在没有它们的情况下编写优雅的代码
中间件
中间件是NodeJs应用程序的一个常见概念,它们类似于代理/面向方面的编程风格。您可能会发现示例项目中有过多的中间件,也不要让自己受到诱惑。中间件适用于身份验证/序列化/头文件/安全性,但不适用于业务逻辑。我见过中间件地狱和中间件驱动的开发,这并不好看
存储库
许多人直接使用MongoDb/Mongoose/SQL客户机,而不使用存储库之类的适配器模式,从而将MongoDb查询泄漏到他们的解决方案中
我给你的建议是,使用你熟悉的结构和方法,但使用JavaScript提供的工具。我真的很喜欢JavaScript,但当我看到主流资源中缺乏设计和架构时,我会感到畏缩,当然小项目和PoC不需要广泛的设计,但通常当项目增长时,它们不会清理干净。你如何组织一个项目应该与你所使用的语言和框架无关
快乐编码😄