2012-02-19 41 views
2

我有一個關於我的C++類設計的問題。通常我會遇到這樣的小問題,我希望得到一些有關更好接受的建議。基本的C++設計

我有一些類通過UDP監視某些設備的溫度。如果設備收到一個數據包,它將打印「x \ n」給標準輸出以表明它收到了一些東西。然後檢查該數據包中的數據並確認數據未顯示設備溫度過高。如果它太高,我必須調用一些函數。如果不是,我必須調用其他函數。

我不知道我是否應該這樣做:

enum temperature {TEMPERATURE_FINE, TEMPERATURE_EXCEEDED}; 

int main(int argc, char* argv[]) 
{ 
    std::vector<std::string> args(argv+1, argv + argc); 

    if(!args.size()) 
     cout << "No parameters entered.\n"; 
    else 
    { 
     CTemperatureMonitor tempMonitor(args); 

     if(tempMonitor.MonitorTemperature() == TEMPERATURE_EXCEEDED) 
      tempMonitor.ActivateAlarm(); 
     else 
      tempMonitor.DisableAlarm(); 
    } 

    return 0; 
} 

其中tempMonitor.MonitorTemperature()調用std::cout << "x\n"。所以std::cout << "x\n"是內置到課堂上。

或者:其中不包含在類std::cout << "x\n"

enum temperature {TEMPERATURE_FINE, TEMPERATURE_EXCEEDED}; 

int main(int argc, char* argv[]) 
{ 
    std::vector<std::string> args(argv+1, argv + argc); 

    if(!args.size()) 
     cout << "No parameters entered.\n"; 
    else 
    { 
     CTemperatureMonitor tempMonitor(args); 

     temperature tempExceeded = tempMonitor.MonitorTemperature(); 
     std::cout << "x\n"; 
     if(tempExceeded == TEMPERATURE_EXCEEDED) 
      tempMonitor.ActivateAlarm(); 
     else 
      tempMonitor.DisableAlarm(); 
    } 

    return 0; 
} 

std::cout << "x\n"必須在致電CTemperatureMonitor::ActivateAlarm()CTemperatureMonitor::DisableAlarm()之前發生。

我知道這看起來確實輕微的,簡單的,但我常常不知道究竟應該是類的一部分。班級應該輸出到stdout嗎?無論我是做一個還是另一個,這會有什麼區別嗎?我是否對此迂腐?

而且,順便說一句,我知道全局變量被認爲是不良的做法。我使用主體和類中的溫度枚舉。我是否應該在CTemperatureMonitor類中聲明兩次,一次在main中,一次或在全局聲明一次?雖然這個問題看起來很具體,但它確實會爲我清除很多其他問題。

謝謝。

+1

想想單一責任,最小耦合,模塊化和可重用性。 – 2012-02-19 12:21:05

+0

對我來說,它取決於它上面的'x'行是幹什麼的。如果它與溫度狀態有關,它將在CTemperatureMonitor類中。如果它只是針對不同事物的分工,我會把它放在課外。 – 2012-02-19 12:22:23

+0

它只是說,「我收到了一個包」。沒有更多,沒有更多。 – 2012-02-19 12:29:05

回答

1

首先,我想指出,有各種規模的項目,並且這取決於規模(和批評),這些建議實際上會有所不同。所以首先經驗法則:

您放置的「框架」(記錄器,選項解析器等)的大小應該不會超過總程序的10%。在這之後,這只是矯枉過正。除非這是練習的目標!

這就是說,我們可以開始看看你的實際問題。


而且,順便說一句,我知道全局變量被認爲是不良的做法。我使用主體和類中的溫度枚舉。我是否應該在CTemperatureMonitor類中聲明兩次,一次在main中,一次或在全局聲明一次?

你實際上是弄錯變量類型這裏。 溫度是一種(enum類型)。

一般而言,類型用作程序各個部分之間的橋樑,爲此,重要的是所有這些部分共享相同類型的定義。因此,對於類型來說,實際聲明兩次是不好的做法。

此外,並非所有的全局變量都是邪惡的。全球變量都是(共享狀態),但全局常量都很好,並且通常扮演類似於類型的角色。


我知道這看起來確實輕微的,簡單的,但我常常不知道究竟應該是類的一部分。班級應該輸出到stdout嗎?無論我是做一個還是另一個,這會有什麼區別嗎?我是否對此迂腐?

有兩種輸出:

  • 記錄輸出,這是用來診斷問題時,他們遇到
  • 真正輸出,這是程序做什麼

根據程序的不同,您可能有兩種或兩種。

從迂腐的角度來看,你通常更喜歡不要混合這些。例如,您可以完美地將日誌記錄發送到文件,或者在嚴重時將stderr發送給「有用」的東西,並使用stdout

這實際上是在某種程度上推動了設計,因爲那時您需要兩個接收器:每個接收器一個接收器。

因爲你有一個相當簡單的程序,最簡單的方法可能是簡單地通過兩個不同的std::ostream&到你的班級建設。或者,甚至更簡單,只需要兩個泛型函數並使用(邪惡)全局變量。

在較大的程序中,您可能會設計一個Logger類,該類具有各種日誌級別並提供特定的宏來自動註冊日誌行的函數名稱,文件名和行號。您也可能有一個輕量級日誌記錄機制,允許您禁用發佈版本中的日誌記錄DEBUG/DEV級別跟蹤。

+0

謝謝你的回答,這是相當豐富的。我的程序沒有記錄形式,cout <<「x \ n」是實際輸出。我知道可能看起來很奇怪......因爲我只有一個輸出,而且它是真實的,它必須始終是標準輸出,這將是首選? – 2012-02-19 13:04:46

+0

@ user968243:我會建議不要過度使用它。 'std :: cout'現在可以工作,所以就保留它。即使你有一天想要登錄一個文件,你仍然可以重定向輸出(甚至使用'tie'來登錄文件和控制檯)。如果您需要其他功能(例如可以啓用/禁用的日誌記錄級別),則只引入一個記錄器類,並在此刻*重構您的應用程序。 – 2012-02-19 14:18:33

1

The single level of abstraction principle將有利於做的所有I/O相同的方法,而不是做一些在較高的水平,並在一些抽象的低水平。

換句話說,如果你相信這個原則,通過CIN/COUT相同的方法保持輸入和輸出,而不是呈現出一些和隱藏一些是個好主意。它傾向於在每個類中提供更少的依賴關係的可讀代碼。

1

根據Single responsibility principle,第二個選項是首選(任何類應該只有一個責任,它監視您的情況下的溫度,不輸出結果),但您可能想要設置另一個類來處理溫度監測結果(例如,將結果寫入某個日誌文件或某物)。

+0

這很難劃清界線。例如,也許監視溫度的一部分是做std :: cout <<「x \ n」;說你實際上正在監測溫度並且正在工作。 – 2012-02-19 12:52:07

+0

當然,我在這裏討論的是真正的系統設計,因爲這個問題是一個普遍的問題,溫度監控只是一個例子(並沒有考慮調試日誌記錄)。 – 2012-02-19 13:06:23

+0

是的,我很難找出在哪裏畫線,何時決定什麼不應該在課堂上。似乎有一些確定的灰色地帶! – 2012-02-19 13:10:56

0

在我在這種情況下,你不應該包括COUT到類的意見,因爲有時也許以後你將需要輸出的文件或不輸出的。所以如果cout沒有放到課堂上,您將有機會重複使用您的課程代碼而不做任何更改。

1

這是很正常的記錄有關的節目信息的一些方法。
這種方式也是正常的,也是全球性的。

否則在調用方法時,事情會變得太複雜。
你應該做些什麼來改善這種情況的唯一的事情就是:

有一個記錄器類(或使用現有的),可以有它的輸出流設置,無論你選擇(包括標準::出來,一個空的流,其不打印任何東西)。
最終,有一個記錄器可以隱藏在#define後面,以便它不會減慢在發佈模式下運行的代碼。

0

也沒有。 main的責任是使用命令行參數啓動應用程序並提供返回值。其他一切都不應該在那裏。你可能想看一本像「對象設計,角色,責任和合作」的書