工厂应该设置模型属性

本文关键字:模型 属性 设置 工厂 | 更新日期: 2023-09-27 17:50:37

作为整个soa编程工作的一部分,我创建了一个工厂接口&基本框架API中的抽象工厂。

人们已经开始使工厂的Create方法过载。问题是人们用模型属性重载了Create方法(从而期望工厂填充它们)。

我认为属性设置不应该由工厂来完成。我错了吗?

public interface IFactory
{
    I Create<C, I>();
    I Create<C, I>(long id); //<--- I feel doing this is incorrect
    IFactoryTransformer Transformer { get; }
    IFactoryDataAccessor DataAccessor { get; }
    IFactoryValidator Validator { get; }
}

更新-对于那些不熟悉SOLID原则的人,这里有一些:

单一责任原则
它指出每个对象都应该有一个单独的职责,并且这个职责应该完全被类

封装起来。

打开/关闭原则
这个原则的含义是,当你收到一个需要添加到你的应用程序中的特性的请求时,你应该能够在不修改旧类的情况下处理它,只需要添加子类和新的实现。

依赖倒置原则
它说你应该解耦你的软件模块。要实现这一点,您需要隔离依赖项。

整体:


我有90%的把握知道答案。但是,我希望已经在使用SOLID的人能够进行一些好的讨论。谢谢你提出的宝贵意见。

UPDATE -那么我认为一个SOLID工厂应该做什么?

IMHO一个SOLID工厂提供适当的对象实例…但是这样做的方式隐藏了对象实例化的复杂性。例如,如果您有一个Employee模型…你可以让工厂给你弄一个合适的。DataAccessorFactory会给你正确的数据访问对象,ValidatorFactory会给你正确的验证对象等等。

例如:

var employee = Factory.Create<ExxonMobilEmployee, IEmployee>();
var dataAccessorLdap = Factory.DataAccessor.Create<LDAP, IEmployee>();
var dataAccessorSqlServer = Factory.DataAccessor.Create<SqlServer, IEmployee>();
var validator = Factory.Validator.Create<ExxonMobilEmployee, IEmployee>();

更进一步,我们将…

var audit = new Framework.Audit(); // Or have the factory hand it to you
var result = new Framework.Result(); // Or have the factory hand it to you
// Save your AuditInfo
audit.username = 'prisonerzero';
// Get from LDAP (example only)
employee.Id = 10;
result = dataAccessorLdap.Get(employee, audit);
employee = result.Instance; // All operations use the same Result object
// Update model    
employee.FirstName = 'Scooby'
employee.LastName = 'Doo'
// Validate
result = validator.Validate(employee);
// Save to SQL
if(result.HasErrors)
     dataAccessorSqlServer.Add(employee, audit);

UPDATE -那么为什么我坚持这种分离?

我觉得责任分离可以实现更小的对象,更小的单元测试,并且增强了可靠性& &;维护。我承认这样做的代价是创造更多的对象……但这就是固体工厂保护我的…它隐藏了收集和实例化上述对象的复杂性。

工厂应该设置模型属性

我想说这是坚持DRY原则,只要它是简单的值布线我不认为这是问题/违反。而不是用

var model = this.factory.Create();
model.Id = 10;
model.Name = "X20";

分散在你的代码库中,把它们放在一个地方总是更好。未来的合同变更、重构或新需求将更容易处理。

值得注意的是,如果这样的对象创建和立即属性设置是常见的,那么这就是您的团队已经开发的模式,开发人员添加重载只是对这一事实的响应(值得注意的是,这是一个很好的响应)。应该引入一个API来简化这个过程。

同样,如果它缩小到简单的赋值(就像你的例子),我会毫不犹豫地保留重载,特别是如果它是你经常注意到的东西。当事情变得更复杂时,这将是发现新模式的标志,也许这时您应该求助于其他标准解决方案(例如构建器模式)。

假设您的工厂接口是从应用程序代码中使用的(与基础结构组合根相反),它实际上代表了一个服务定位器,可以将其视为依赖注入方面的反模式。参见Service Locator: roles vs. mechanics。

注意下面的代码:

var employee = Factory.Create<ExxonMobilEmployee, IEmployee>();

只是语法糖。它不能消除对具体ExxonMobilEmployee实现的依赖。

您可能还对弱类型与强类型消息通道和没有服务位置的消息调度(它们说明了这些接口如何违反SRP)以及Mark Seemann的其他出版物感兴趣。

经过6个月的依赖注入经验,我只发现工厂应该设置属性的情况很少:

  1. 如果设置器标记为internal,并且该属性仅由工厂设置一次。这通常发生在只有get - ter属性的接口上,其实现预计将通过工厂创建。

  2. 当模型使用属性注入时。我很少看到使用属性注入的类(我也尽量避免构建这些类),但是当我确实看到一个类,并且所需的服务只在其他地方可用时,这是您别无选择的情况。

对于底线,将public set排除在工厂之外。只设置标记为internal的属性。如果允许,让客户端决定需要设置哪些属性。这将使您的工厂清除不必要的功能。