面向数据编程(DOP)中dbClient的依赖注入实现方法问询
DOP模式下静态类的依赖注入解决方案
《Data-Oriented Programming》(DOP)虽然建议用静态方法组织行为,但并非无法实现依赖注入,硬编码导入dbClient只是最原始的方式,下面提供几种更合理的解决方案:
方案1:将依赖作为参数传入静态方法
这是最贴合DOP"行为无隐藏状态"原则的方式,直接把dbClient作为静态方法的参数传递:
class CatalogDB { static addMember(member, dbClient) { const addMemberQuery = `INSERT INTO members (email, encrypted_password) VALUES ($1, $2)`; dbClient.query( addMemberQuery, _.at(member, ["email", "encryptedPassword"]), ); } } // 使用时传入dbClient实例 CatalogDB.addMember(newMember, myDbClient);
测试时可以轻松传入Mock的dbClient,完全避免硬编码依赖。
方案2:给类设置静态属性注入依赖
如果不想每次调用都传参数,可以在类初始化时通过静态属性注入依赖:
class CatalogDB { static dbClient; static addMember(member) { const addMemberQuery = `INSERT INTO members (email, encrypted_password) VALUES ($1, $2)`; this.dbClient.query( addMemberQuery, _.at(member, ["email", "encryptedPassword"]), ); } } // 应用启动时注入真实实例 CatalogDB.dbClient = myDbClient; // 测试时替换为Mock CatalogDB.dbClient = mockDbClient;
这种方式兼顾了调用简洁性和依赖可替换性,符合DOP对行为组织的要求。
方案3:用闭包封装依赖(更贴合DOP核心思想)
DOP强调"数据是一等公民,行为是操作数据的函数",抛弃类用闭包封装依赖,能彻底分离行为与依赖:
function createCatalogDB(dbClient) { return { addMember: (member) => { const addMemberQuery = `INSERT INTO members (email, encrypted_password) VALUES ($1, $2)`; dbClient.query( addMemberQuery, _.at(member, ["email", "encryptedPassword"]), ); } }; } // 创建实例时注入依赖 const catalogDB = createCatalogDB(myDbClient); // 调用方法 catalogDB.addMember(newMember); // 测试时传入Mock const testCatalogDB = createCatalogDB(mockDbClient);
这种方式没有任何隐藏状态,完全符合DOP的设计哲学,同时完美解决依赖注入问题。
总结
直接导入dbClient的硬编码方式确实会限制扩展性和可测试性,上面三种方案都能解决这个问题,其中闭包方案是最贴合DOP精神的实现方式。
内容的提问来源于stack exchange,提问作者Littlee
相关产品推荐
相关产品推荐

