我正在設計一個公開同步和異步操作的C++ API。所有操作可能會失敗並且必須報告失敗。異步操作必須提供完成時執行延續的方法。我正在嘗試以最具可讀性和一致性的方式設計API。設計一個結合了同步和異步操作的C++ API
這說明現在的設計我有一個例子:
#include <memory>
#include <future>
using namespace std;
class Error {
public:
Error(int c, string desc) : code(c), description(desc) {}
int code;
string description;
};
template<typename T>
class Callback {
public:
virtual void completed(const T& result, unique_ptr<Error> error) = 0;
};
template<typename T>
class PrintCallback : public Callback<T> {
public:
void completed(const T& result, unique_ptr<Error> error) override {
if (nullptr != error) {
printf("An error has occured. Code: %d Description: %s\n",
error->code, error->description.c_str());
} else {
printf("Operation completed successfully. Result: %s\n",
to_string(result).c_str());
}
}
};
class API {
public:
void asyncOperation(shared_ptr<Callback<int>> callback) {
thread([callback]() {
callback->completed(5, nullptr);
}).detach();
}
int syncOperation(unique_ptr<Error>& error) {
return 5;
}
void asyncFailedOperation(shared_ptr<Callback<int>> callback) {
thread([callback]() {
callback->completed(-1, unique_ptr<Error>(new Error(222, "Async Error")));
}).detach();
}
int syncFailedOperation(unique_ptr<Error>& error) {
error = unique_ptr<Error>(new Error(111, "Sync Error"));
return -1;
}
};
我不喜歡使用使用錯誤輸出參數進行同步操作和同步和異步簽名之間的不一致的。 我在辯論兩種替代方法:
- 將同步操作視爲異步,並讓它們接受回調以返回其結果/失敗。這種方法在同步和異步操作中更加一致,看起來更乾淨。另一方面,有一個簡單的同步操作與回調工作感覺有點奇怪。
- 使用
std::promise
和std::future
,並使用異常來報告故障。對於異步操作,將返回std::future
,並在發生故障時拋出它的get()
。同步操作只會在發生故障時拋出。這種方法感覺更清晰,因爲錯誤處理不會喧譁方法簽名,而異常是在C++中執行錯誤處理的標準方式。然而,爲了得到結果,我必須調用future::get()
,所以如果我不想阻塞,那麼我必須啓動另一個線程來等待結果。異步操作的繼續在實際上在std::promise
上設置結果的線程上運行也很重要。這種方法是這個問題的公認答案 - Synchronous and ASynchronous APIs。
我想知道:
- 如果能夠避免替代#2額外的線程。
- 如果替代#2的缺點超過它的優點(特別是額外的線程)。
- 如果還有另一種方法,我沒有考慮。
- 哪種方法將被認爲是可讀性和一致性的最佳選擇。
謝謝!
就目前而言,Stack Overflow的問題太廣泛了。你可以寫一本關於API設計的書! :)但是,我確實有一個挑剔:*「異常是在C++中執行錯誤處理的標準方法」* - 不,它們不是。取決於上下文,錯誤代碼或斷言通常更清晰。 –
[codereview.se]網站更適合於改善現有工作代碼的問題。我建議你在諮詢他們的[幫助中心](// codereview.stackexchange.com/help/on-topic)後,在那裏標記你的問題。 –
@ChristianHackl我覺得這應該是一個非常集中的設計問題。我試圖在異步和同步方法之間提出一個關於錯誤處理的一致性問題,在那裏我研究瞭如何解決它(不同的選擇)以及我對它們的擔憂。 – galsh83