5

As an example, suppose I have the following class:

public class FruitBasket {
    private List<Apple> apples;
    private List<Orange> oranges;
    // getters and setters...
}

Now suppose I also have a method somewhere which gets the FruitBasket.

public FruitBasket getFruitBasket() {
    //...
}

Now further suppose that the getFruitBasket method aggregates data from two different sources, which are accessed via a proxy. For example, there is a server AppleTree to get objects of type Apple, and a server OrangeTree to get objects of type Orange, and both are accessed via a proxy called OrchardGate. This is the reason why I want to write a single getFruitBasket method rather than getApples and getOranges, to minimise the latency when calling from my application to the OrchardGate.

In the case where Apple objects and Orange objects were retrieved successfully, there is no problem, I can just return the FruitBasket. In the case where there was a problem accessing or inside the OrchardGate, or in both the AppleTree and OrangeTree, I can also handle this by throwing a descendant of RuntimeException (or even Exception, if I add it to the getFruitBasket throws clause as appropriate).

However, what happens in the partial success case? What happens if I can access the AppleTree server fine, but I can't access the OrangeTree server due to some transport issue between the OrchardGate and OrangeTree?

As far as I can see there are only four options, and all are absolutely horrible:

  • I could throw an exception, meaning that even though the Apple objects were received successfully, the FruitBasket would not be returned due to the lack of Orange objects.
  • I could ignore the error and just return an empty list of Orange objects. This would mean that the client would not be able to see an error when looking for the Orange objects, instead it would just look as if no Orange objects existed on the OrangeTree server.
  • I could add a field to FruitBasket called errorCodes which contained a list of the errors encountered when accessing the FruitBasket. Then I could add an error code to that list called PATH_FLOODED to signify the error I had encountered. However, this field errorCodes does not belong on the FruitBasket domain object at all. This field is not relevant to a FruitBasket, but only in the transaction to retrieve the FruitBasket.
  • I could throw an exception, but attach the incomplete FruitBasket to the exception. This is also horrible because exceptions should only contain error information - they should not contain any fruit baskets.

I have described this problem in Java but I imagine this problem extends to multiple languages. I was quite surprised to not find a discussion of it already. Is there any standard pattern for writing methods which can return a partial success? Or anything I have missed?

4

3 回答 3

1

我认为这种方法没有任何问题。

我可以向 FruitBasket 添加一个名为 errorCodes 的字段,其中包含访问 FruitBasket 时遇到的错误列表。然后我可以在名为 PATH_FLOODED 的列表中添加一个错误代码来表示我遇到的错误。但是,这个字段 errorCodes 根本不属于 FruitBasket 域对象。此字段与 FruitBasket 无关,但仅在检索 FruitBasket 的事务中

FruitBasketTransaction {
  FruitBasket fruitBasket;
  List<Error> errorCodes;

  // ... constructor and getters
}

public FruitBasketTransaction getFruitBasket() {
  // ...
}

// In your application somewhere
FruitBasketTransaction transaction = getFruitBasketTransaction();
if contains(transaction.errorCodes, APPLE_ERROR) {
  // ... tell the user
}
if contains(transaction.errorCodes, ORANGE_ERROR) {
  // ... tell the user
}

giveFruitToUser(transaction.getFruitBasket());
于 2015-08-11T08:06:10.960 回答
1

我认为您可能需要另一种方法 loadFruitBasket()来从服务器加载 Apple 和 Orange 对象。因为您必须访问服务器才能获得苹果和橙子,您可以将boolean权限设置true为访问成功的时间或访问false失败的时间。然后在使用之前,getFruitBasket()您可以询问已加载 FruitBasket 的类是它hasApples()还是hasOranges(). 这样您就不必多次访问服务器并且可以显示不同的错误。

于 2015-09-18T13:28:25.853 回答
0

部分结果,及时的快照。对于收集各种在线词典和服务的翻译系统也是如此,这些在线词典和服务可能可用也可能不可用。通常使用控件“进一步搜索/中止”。

通常,您提供结果的最小阈值,例如一个代理提供其贡献的结果。

模式不是结果的模式,而是管理正在进行的搜索任务,提供结果的模式。也需要进行一些变更管理。当使用部分结果制作水果篮时,稍后您可能想要重复制作具有更多变化的水果篮。

Aservice提供了一个时间线data packages[]

`Service A:   (start) [pack 0] (t1) [pack 1] (t2) [pack 2] (t3) {running}
`Service B:   (start) (t1) [pack 3] (t2) (t3) [pack 4] (t4) {ended}

使用哪个比喻取决于:例如项目管理,或者在您的情况下是生产。

于 2015-08-11T08:34:22.967 回答