3

假设我有一个模型:

public class Thing
{
    public int? identifier { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    ... // arbitrary number of additional properties.
}

以及包含两个关键方法的服务层接口:

public interface IThingService
{
    Thing GetThing(int id);
    Thing AddThing(Thing thing);
}

现在,假设服务层会自动identifier为每个事物生成一个AddThing. 还假设将其公开identifier给表示层很重要,因为它可能会传递给其他服务。

鉴于我必须通过一个Thingto AddThing,这是最好的建模方式Thing吗?表示层的开发者可能认为他们可以指定一个identifer,但这会被 的具体实现忽略IThingService。当然,identifier必须是 public 才能由IThingServicefor设置GetThing

是否可以简单地忽略传入的identifier调用AddThing,或者是否有更好的方法对此进行建模以防止这种情况发生?

4

3 回答 3

2

您的服务应如下所示:

public interface IThingService
{
    Thing GetThing(int id);
    ThingCreationResponse AddThing(ThingCreationRequest request);
}

ThingCreationRequest将拥有创建Thing实体所需的所有数据。它没有标识符。标识符将由AddThing.

AddThing可以简单地返回一个Thingid,但在这种情况下,您应该提供一个有据可查的协议来传达错误(在失败的情况下返回负值,或抛出异常)。

返回 的实例ThingCreationResponse将为您提供更好的灵活性,因为您可以返回 id 或 new 的完整实例Thing,也可以更好地传达失败原因。

于 2013-03-23T19:06:17.047 回答
1

这仅在服务运行在原始Thing实际存在的同一内存上时才有效。如果此服务断开连接,例如在另一台机器上,则更新Thing不会影响原始实例并且identifier永远不会返回到调用代码。

考虑到这一点,有 2 条可能的路径:您打算让此服务始终在本地并在与调用应用程序相同的内存上运行,或者您打算让此服务实际断开连接或最终断开连接。

连接的

如果它已连接,此接口将正常工作,但您可能仍希望隐藏标识符的设置器。如果这样做,您可以将其设为内部并Thing在单独的程序集中定义服务接口和对象,这将使表示层无法访问设置器。好吧,您仍然可以通过反射或其他 hijink 调用它,但对于典型的东西,它将无法访问。

断开连接

这个接口被破坏了,因为您无法以任何方式检索标识符,并且为了检索现在保存的项目是必要的。如果它足够小,这里的典型解决方案会从AddThing方法或整个对象(新内存)返回标识符。

除此之外,不可变的数据项很难推理,无论哪种情况,我都可能更愿意Thing在调用后创建一个新AddThing的。

于 2013-03-23T15:23:44.890 回答
0

我认为在这种情况下,AddThing 的正确签名将是 AddThing(string title, string description),并且该方法的职责是使用生成的标识符构建 Thing 对象。

考虑到您的最后一个规范,我建议创建第二个类,ThingWithId 作为成员标识符和 Thing。AddThing 的签名将更改为 ThingWithId AddThing(Thing thing)

于 2013-03-23T15:21:38.167 回答