如何区分';角色';来自';结果';接口

本文关键字:结果 接口 来自 角色 何区 | 更新日期: 2023-09-27 18:26:51

这个问题在我的编码中经常出现,我很惊讶我能找到这么少的参考,并且会重视别人的想法和想法。

我为我工作的框架定义了很多API,并在我想要分解的大型领域模型中定义了很多。这些API几乎完全由接口组成(在我的例子中,这意味着C#接口)。我一次又一次地发现,我想区分两种接口。在没有找到任何更广泛使用的术语的情况下,我将这两个术语定义如下:

  • "Role"接口旨在由API外部的对象实现,以便这些对象可以用作API上定义的方法的参数。

  • "结果"接口由API内部的对象实现,并通过API提供给系统的其他部分。定义结果接口而不是公开实现它的对象的目的是将对象的视图限制在外部世界。

举一个例子,支付子系统可以将IPayableItem定义为角色接口,由应用程序其他部分的许多类型实现,以便为它们生成支付。这些生成的支付对象可以通过API检索,但由结果接口IPayment定义。

我目前唯一能区分这些的方法是命名约定和/或注释。理想情况下,我希望该语言强制执行区别,并让它强制执行规则:你不能在API之外实现Result接口,只能使用它。但C#没有提供任何这样的机制。(有人能给我一种可以的语言吗?)。我可以定义一个属性,但这仍然不能强制执行任何操作。

区别的另一个重要意义在于API的语义版本化。如果我向角色接口添加一个新成员,那么这应该被视为一个突破性的更改(因此也是一个一级版本),因为任何现有的外部实现都需要添加该成员。但是,如果我将一个成员添加到我认为是"Result"接口中,那么应该只有我自己的代码受到影响——这只是其他人的一个新功能(二级版本)。但是,如果这两种类型之间没有强制的区别,那么人们在实现Result接口时会有一些风险,因此他们的代码会被破坏。

其他人遇到过这种困境吗?如果是,你是如何处理的?我期待着你的回答。

但请不要同时用以下任何一个论点来回应(我经常听到):

  • My Result接口应该是抽象类,而不是接口。这并不能解决问题,而且可能会使问题变得更糟,因为外部代码可以对它们进行子类。

  • 我应该返回具体类型,并确保我不想在API外部访问的任何内容都标记为"内部"。在很多情况下,我需要API内部的东西是公共的,例如可以访问其他框架(而不是通过API)。

如何区分';角色';来自';结果';接口

我想您要问的是,是否可以公开一个接口,但确定给定的实例就是您创建的实例?

如果是这样,您还可以创建一个内部私有接口,并将所有实现标记为也实现了私有接口。然后,当从外部世界获得一个对象时,验证它是否也具有内部接口实现。

public interface IPublic
{
    ...
}
internal interface ISecret { }
public class PublicImplementation : IPublic, ISecret
{
    ...
}

只有你才能实现ISecret,所以即使有人实现了IPublic并将其传递给你,它也会通过ISecret测试。