让DDD为你的JavaScript混乱带来秩序。
我不会把自己当作JavaScript开发人员,我总是开玩笑说这是一种我从未打算学习的语言。它现在如此普遍,它刚刚发生。我经历了享受它和鄙视它的阶段。但是通过爱的高峰和低谷并不是很讨厌。一个问题仍然存在:如果我要成为一名优秀的JS开发人员并编写函数性JavaScript,那么我如何以使用一种合适的领域模型的方式编写代码?
在传统的OO语言中,例如Java,C#,甚至Go实际上,编写围绕领域设计构建的代码很容易。你有Class类,这些类很大并且能做很多事情。当然,你通常在JavaScript中会像躲避瘟疫一样避免这种情况。
但是,我的代码似乎总是看起来像这样:
const { getUser, removeUser } = require('services/user'); const { sendEmail } = require('helpers/email'); const { pushNotification } = require('helpers/notifications'); const { removeFilesByUserId } = require('services/files'); const removeUserHandler = await (userId) => { const message = 'Your account has been deleted'; try { const user = await getUser(userId); await removeUser(userId); await sendEmail(userId, message); await pushNotification(userId, message); } catch (e) { console.error(e); sendLogs('removeUserHandler', e); }; return true; };
|
看起来没问题吧?当然!这里设计没有大问题。但是,如果你有一个完全由这样的文件构成的大型代码库,换句话说,目录中充满了模糊分组的“服务”,单独导出和导入单个函数,通常含糊不清,并且在阅读时通常不属于某个域代码,它可以很快地感觉到你正在处理一个大泥球,而不是一个架构良好的软件应用程序。
我不想回到类和传统的封装。在学习'functional way 之后,这感觉就像退后一步。但是,越来越多,我发现JavaScript项目难以阅读,支离破碎。我到处都看到了这个!看起来JS项目几乎没有设计或架构似乎很常见。我已经准备好把JS扔进垃圾桶并转投到Golang。
直到我的一位工程师将一个新功能放入我们最嘈杂的代码库之一,这引起了我的注意。
ScheduledJobs.run(jobId); const job = await ScheduledJobs.get(jobId);
|
这要做成一个类吗?当然不是:
const run = (jobId) => {}; const stop = (jobId) => {}; const pause = (jobId) => {}; const get = (jobId) => {}; module.exports = { run, stop, pause, get, };
|
整个代码非琐碎,其实没有javascript更重要概念,模块,模块其实类似“类"或聚合,是一种相似功能的聚合而已。重构代码如下,加入模块概念:
const UserModel = require('models/user'); const EmailService = require('services/email'); const NotificationService = require('services/notification'); const FileModel = require('models/file'); const Logger = require('services/logger'); const removeUserHandler = await (userId) => { const message = 'Your account has been deleted'; try { const user = await UserModel.getUser(userId); await UserModel.removeUser(userId); await EmailService.send(userId, message); await NotificationService.push(userId, message); return true; } catch (e) { console.error(e); Logger.send('removeUserHandler', e); }; return true; };
|
将函数进行分组形成对象,以对象为中心编码,这种模式比处理大量一个个未分组的函数调用能更好地传达了目的。我发现它让代码更容易理解,这段代码适合指明大局的指标。