如何在MVC架构中防止上帝模型class?
How to prevent a God model class in an MVC architecture?
如何防止他们的模型 类 变得太大或依赖于与他们没有直接关系的对象?
例子
想象一个用户注册表,一旦成功注册,用户就会收到一封电子邮件来验证他们的电子邮件地址。
示例代码1
免责声明 - 这是演示代码
// route.js
app.post('/register', (req, res) => {
container.get('UserController').postRegisterUser(req, res);
});
选项 1 - 在用户模型中添加 emailSender 依赖项
// userController.js
class UserController {
public constructor(model) {
this.model = model;
}
public postRegisterUser(req, res) {
const {email, password, repeatPassword} = req.body;
const user = this.model.registerUser({email, password, repeatPassword});
return res.render('/', user);
}
}
// UserModel.ts
class UserModel {
constructor(repository, validator, emailSender) {
this.repository = repository;
this.validator = validator;
this.emailSender = emailSender; // <--- emailSender injected in to model
}
public registerUser(user) {
if (this.validator.isValid(user)) {
this.repository.save(user);
this.emailSender.sendVerificationEmail(user.email); // <---- emailSender called here
return user;
}
}
}
选项 2 - 在控制器中添加 emailSender 依赖项
// userController.js
class UserController {
public constructor(model, emailSender) {
this.model = model;
this.emailSender = emailSender; // <--- Injected in constructor
}
public postRegisterUser(req, res) {
const {email, password, repeatPassword} = req.body;
const user = this.model.registerUser({email, password, repeatPassword});
this.emailSender.sendVerificationEmail(email); // <--- emailSender called here
return res.render('/', user);
}
}
// UserModel.ts
// no EmailSender injected
class UserModel {
constructor(repository, validator) {
this.repository = repository;
this.validator = validator;
}
public registerUser(user) {
if (this.validator.isValid(user)) {
this.repository.save(user);
return user;
}
}
}
可以看到当涉及其他系统时这些依赖性会变得有多大——例如将数据发送到 S3 存储桶、生成 csv 文件等。理想情况下我不希望我的控制器或模型具有这些依赖性,但他们去哪儿了?
我想理想的解决方案是介于上述两个选项之间的东西。我只是对如何实施我的 Web 应用程序有困难。
您可以构建另一个组件 UserProcessor
或 UserRegistrationProcessor
,其中包含对其他服务的所有外部调用,并将该组件注入 UserController
。
如何防止他们的模型 类 变得太大或依赖于与他们没有直接关系的对象?
例子
想象一个用户注册表,一旦成功注册,用户就会收到一封电子邮件来验证他们的电子邮件地址。
示例代码1
免责声明 - 这是演示代码
// route.js
app.post('/register', (req, res) => {
container.get('UserController').postRegisterUser(req, res);
});
选项 1 - 在用户模型中添加 emailSender 依赖项
// userController.js
class UserController {
public constructor(model) {
this.model = model;
}
public postRegisterUser(req, res) {
const {email, password, repeatPassword} = req.body;
const user = this.model.registerUser({email, password, repeatPassword});
return res.render('/', user);
}
}
// UserModel.ts
class UserModel {
constructor(repository, validator, emailSender) {
this.repository = repository;
this.validator = validator;
this.emailSender = emailSender; // <--- emailSender injected in to model
}
public registerUser(user) {
if (this.validator.isValid(user)) {
this.repository.save(user);
this.emailSender.sendVerificationEmail(user.email); // <---- emailSender called here
return user;
}
}
}
选项 2 - 在控制器中添加 emailSender 依赖项
// userController.js
class UserController {
public constructor(model, emailSender) {
this.model = model;
this.emailSender = emailSender; // <--- Injected in constructor
}
public postRegisterUser(req, res) {
const {email, password, repeatPassword} = req.body;
const user = this.model.registerUser({email, password, repeatPassword});
this.emailSender.sendVerificationEmail(email); // <--- emailSender called here
return res.render('/', user);
}
}
// UserModel.ts
// no EmailSender injected
class UserModel {
constructor(repository, validator) {
this.repository = repository;
this.validator = validator;
}
public registerUser(user) {
if (this.validator.isValid(user)) {
this.repository.save(user);
return user;
}
}
}
可以看到当涉及其他系统时这些依赖性会变得有多大——例如将数据发送到 S3 存储桶、生成 csv 文件等。理想情况下我不希望我的控制器或模型具有这些依赖性,但他们去哪儿了?
我想理想的解决方案是介于上述两个选项之间的东西。我只是对如何实施我的 Web 应用程序有困难。
您可以构建另一个组件 UserProcessor
或 UserRegistrationProcessor
,其中包含对其他服务的所有外部调用,并将该组件注入 UserController
。