处理方法内部过滤与外部过滤

问题描述 投票:0回答:1

在我的应用程序中,我正在处理

IMyInterface
实例列表。不是全部,但其中一些另外也实现了
IAnotherInterface
。请注意,
IAnotherInterface
并非源自
IMyInterface
。遵循单一职责原则,我有一个单独的类,通过
IMyInterfaces
方法处理
Process
实例。现在我正在为设计选择而苦苦挣扎

  1. 签名应该是
    Process(IEnumerable<IMyInterface> items)
    ,我在这个方法中过滤
    IAnotherInterface
  2. 或者签名应该是
    Process(IEnumerable<IAnotherInterface> items)
    ,这意味着过滤必须由“客户端”在处理方法之外完成。

为了更清楚地说明,这些是我正在挣扎的两个代码选项:

// alternative 1:
List<MyInterface> items = GetItems(); // code not shown here
foreach(var item in items)
{
    // do some other processing before, not shown here

    // pass items to Process(IEnumerable<IMyInterface> items)
    myProcessor.Process(items);                
            
    // do some other processing afterwards, not shown here
}

// or alternative 2:
List<MyInterface> items = GetItems(); // code not shown here
foreach (var item in items)
{
    // do some other processing before, not shown here

    // pass items to Process(IEnumerable<IAnotherInterface> items)
    // -> need to filter first
    var filteredItems = filterForIAnotherInterface(items);
    myProcessor.Process(filteredItems);

    // do some other processing afterwards, not shown here
}

选择其中之一有什么好的理由吗?我自己的想法是,替代方案 1 对客户端来说更容易使用,但是

Process
方法必须进行过滤,这除了其主要职责之外还增加了某种额外的职责。另一方面,我认为替代方案 2 在某种程度上使处理管道的可读性降低。

c# oop design-patterns solid-principles single-responsibility-principle
1个回答
0
投票

没有绝对的规则来指导这样的 API 设计决策。一方面,您可能希望尽可能明确。

显式优于隐式。

- Python 之禅

另一种表达方式是应用最小惊喜原则。如果您有一个带有签名

void Process(IEnumerable<IMyInterface> items)
的方法,客户端代码将期望这样的方法来处理
IMyInterface
对象。那么,这样的客户端可能会感到惊讶,如果它传递了一组
IMyInterface
对象,而这些对象也实现了
IAnotherInterface
,然后什么也没有发生。令人惊讶。

另一方面,稳健性原则(波斯特尔定律)可能会认为,如果

Process
可以处理
IMyInterface
对象,那么它也应该接受它们。


因为我不知道OP中的内容,所以听起来Postel定律真的并不适用于此,因为

Process
方法实际上不处理任何
IMyInterface
对象 - 它只是忽略他们。

因此,在不了解更多信息的情况下,听起来 API 应该是

void Process(IEnumerable<IAnotherInterface> items)

另一方面,我认为替代方案 2 在某种程度上使处理管道的可读性较差。

只需使用OfType

myProcessor.Process(items.OfType<IAnotherInterface>());

如果您确实想让管道显式化,您可以通过引入(内部)扩展方法来反转参数:

public static void ProcessWith(
    this IEnumerable<IAnotherInterface> items,
    SomeProcessor processor)
{
    processor.Process(items);
}

这将使您能够像这样编写管道:

items.OfType<IAnotherInterface>().ProcessWith(myProcessor);
© www.soinside.com 2019 - 2024. All rights reserved.