node.js - 面向对象编程的表达
问题描述
作者提出 OOP express 应用程序的地方。我发现它很有趣,并使用他的一些想法创建了一个后端,以便更好地组织我的代码并防止 ctrl+c + ctrl+v。
我的想法是:我的许多实体:用户、客户、产品、菜单(是的,我正在创建一个管理餐厅订单的程序)将有一些基本路线,例如:创建 / FindOne / UpdateOne / DeleteOne / 等等。 ..而且,每个查询都将基本相同,所以...考虑到这一点并试图防止重复代码,我创建了这个结构:
基本控制器 将接收它的服务和模型,并将有一个名为 setRouter 的方法,该方法将基于每个路由“自动”创建该路由,应用它需要的所有中间件,其相关控制器将调用它的服务。
class BaseController {
constructor(basePath, service, routes) {
this.router = new Router();
this.basePath = basePath;
this.service = service;
this.routes = routes;
}
setRouter() {
Object.values(this.routes).forEach((route) => {
route.localMiddleware.forEach((middleWare) => {
this.router.use(route.endpoint, errorCatcher(middleWare));
});
switch (route.method) {
case 'GET':
this.router.get(route.endpoint, errorCatcher(route.handler(this.service)));
break;
case 'POST':
this.router.post(route.endpoint, errorCatcher(route.handler(this.service)));
break;
case 'PUT':
this.router.put(route.endpoint, errorCatcher(route.handler(this.service)));
break;
case 'DELETE':
this.router.delete(route.endpoint, errorCatcher(route.handler(this.service)));
break;
default:
// Throw exception
}
});
return this.router;
}
}
Base Routes 每个路由都将由一个对象表示,该对象包含:它的端点、方法、处理程序(将调用服务的控制器函数)以及数组中的所有中间件
class BaseRoutes {
constructor(routes) {
this.routes = {
activate: {
endpoint: '/activate/:id',
method: METHODS.PUT,
handler: (service) => async (req, res) => {
const { id } = req.params;
const data = await service.activate(id);
res.status(status.ok).json({ data });
},
localMiddleware: [],
},
基础服务 将与路由类似,具有相同的方法。并调用它的各自模型来查询数据库
class BaseService {
constructor(model, queries) {
this.model = model;
this.queries = queries;
}
// Endpoint Methods
async create(payload) {
const insertedEntity = await this.model.create(payload);
return insertedEntity;
}
async findAll() {
const data = await this.model.findAll(this.queries.findAll());
return data;
}
async findByPk(id) {
const data = await this.model.findByPk(id);
return data;
}
async findOne(query) {
const data = await this.model.findOne(this.queries.findOne(query));
return data;
}
async updateOne(id, payload) {
const updatedEntity = await this.model.update(
this.queries.updateOne(payload), { where: { id } },
);
if (!updatedEntity[0]) throw new FireError(status.notFound, errorMessages.notFound);
return updatedEntity;
}
async deleteOne(id) {
const deletedEntity = await this.model.destroy(this.queries.deleteOne(id));
return deletedEntity;
}
async activate(id) {
const updatedEntity = await this.model.update(this.queries.activate(), { where: { id } });
return updatedEntity;
}
async deActivate(id) {
const updatedEntity = await this.model.update(this.queries.deActivate(), { where: { id } });
return updatedEntity;
}
}
module.exports = BaseService;
最后但同样重要的是: 查询接口 默认情况下,每条路由都会有一个类似的查询来对数据库执行某些操作,如果需要,我可以扩展这个类并更改其中一个方法
/* eslint-disable class-methods-use-this */
class QueryInterface {
constructor({
create,
findAll,
deleteOne,
updateOne,
findOne,
findByPk,
activate,
deActivate,
}) {
this.create = create || this.noQuery;
this.findAll = findAll || this.noQuery;
this.findByPk = findByPk || this.noQuery;
this.findOne = findOne || this.findOne;
this.updateOne = updateOne || this.updateOne;
this.deleteOne = deleteOne || this.delete;
this.activate = activate || this.activate;
this.deActivate = deActivate || this.deActivate;
}
noQuery() {
return {};
}
findOne(query) {
return { where: query, attributes: { exclude: ['createdAt', 'updatedAt'] } };
}
updateOne(payload) {
return { ...payload };
}
delete(id) {
return { where: { id } };
}
activate() {
return { isActive: true };
}
deActivate() {
return { isActive: false };
}
}
module.exports = QueryInterface;
所以......我的问题是......你有没有见过或创建一个使用OOP范式表达的后端,如果是这样,与功能相比有什么优点和缺点?
解决方案
推荐阅读
- reactjs - 工作箱与 React js 的集成
- javascript - 与 SurveyJS 自定义渲染的 NextJS 问题?
- javascript - 如何让我的循环从零而不是一开始?
- c++ - 使用表达式列表在 C++ 20 中初始化多维数组
- swift - 错误:调用中缺少参数“from”的参数
- mysql - 通过使用 SQL 中的相关表进行分组来求和
- firebase - 实时数据库中是否有 startBefore() 函数?
- javascript - 如何使仅添加到 DOM 的 1 个 img 在双击时消失?
- docker - 无法在 docker 之间建立连接
- javascript - 如何从表单提交中捕获 GET 请求 url