簡體   English   中英

什么進入主要功能?

[英]What goes into main function?

我正在尋找使用c ++進入程序主要功能的最佳實踐技巧。 目前我認為有兩種方法可行。 (盡管這些方法的“邊緣”可以任意地彼此接近)

1:編寫一個“Master”類,接收傳遞給main函數的參數並處理“Master”類中的完整程序(當然你也使用其他類)。 因此,主要功能將減少到最小的線。

#include "MasterClass.h"
int main(int args, char* argv[])
{
MasterClass MC(args, argv);
}

2:在主函數中編寫“完整”程序,當然利用用戶定義的對象! 但是,還涉及全局功能,主要功能可能會有所增加。

我正在尋找一些關於如何用c ++編寫程序主要功能的一般指導原則。 我通過嘗試為第一種方法編寫一些單元測試來遇到這個問題,這有點困難,因為大多數方法都是私有的。

為什么你會有一個大師班? 它的單一責任范圍是什么?

“主人”或“應用程序”類往往會變成一個大塊,可以做太多不同的事情。 最終,重點是什么? 它給你帶來了什么?

為什么不使用main函數來提供這個主要功能? main定義高級應用程序生命周期。 它需要一些命令行參數並解析它們(最好通過將其委托給另一個函數或類),然后它調用一些設置功能,然后它可能會在進行一些清理之前進入某種主循環。 總而言之,這可能會給你一個大概10-15行的主要功能,但可能不會超過這個。 它應該盡可能地委托給其他類和函數。 因此main本身保持簡短和甜美,但仍然有目的。

將這種超高級流量放在main意味着很容易找到,因為無論如何main是你的起點。 如果您想了解代碼,那么您將開始尋找它。 因此,在嘗試理解代碼時,讀者想要了解的內容。

當然,你可以把所有這些都放在一個“主要課堂”中,除了滿足所有那些覺得“一切都必須在課堂上”的Java-luddites之外你什么都沒有獲得。

您正在描述兩種“極端”方法,這些方法對我來說都不合適。 既沒有單一的上帝階級 ,也沒有單一的上帝功能是實施任何旨在實際使用的重要程序的正確方法。

main()單獨調用MasterClass可以的(盡管我更喜歡分區功能,例如在main()執行任何命令行特定處理,以將MasterClass與命令行參數的細節分離)。 但是,如果該類難以進行單元測試,則表明存在設計問題,通常解決方案是將部分或全部可測試功能委托給其他類,通過公共接口可以輕松地對其進行單元測試。 。

您的第二種方法可能再次成為單元測試的問題,因此您應該努力從中提取方法 (然后最好將它們移動到單獨的類中 )以使細粒度單元測試成為可能。

因此,您想要的最佳位置介於兩個極端之間,受到使您的代碼可測試的要求的限制。

值得思考如何一般地構建程序,而不僅僅是在main()上下文中。 基本思想是將其划分為“塊”(類和方法)

  • 足夠小,易於理解,測試和維護,
  • 邏輯上有凝聚力。

我將在主例程中分析進程的參數,然后通過傳遞比argc和argv更可讀的參數來創建類實例。

您的第一種方法很常見,雖然該類通常被命名為“應用程序”(或至少包含“應用程序”一詞),所以這樣做。

第一個:我很少使用C ++,但我認為這不是一個特定於語言的問題。
嗯,我想這可歸結為除了一些實用性問題之外的味道。 我個人傾向於使用布局#1,但不要將命令行解析例程放在MasterClass中 對我來說,這顯然屬於主要的。 MasterClass應該獲得解析的參數(整數,FileStream,等等)。

通常我在應用程序的命名空間中調用一個main函數(具有相同的簽名):

namespace current_application {
    int main( int argc, char **argv ) {
        // ...
    }
}
int main( int argc, char **argv ) {
    return current_application::main( argc, argv );
}

然后我通常使用我的實際main(命名空間中的那個)初始化應用程序明智的東西:

  • 在標准輸入/輸出/錯誤上設置區域設置)

  • 解析應用程序參數

  • 實例化我的主類的對象,如果存在(相當於像QApplication這樣的東西)

  • 調用main函數,如果存在(相當於像QApplication::run這樣的東西)

並且通常更喜歡在那里添加try catch塊,以便在崩潰時打印更多調試信息。


然而,所有這些都是非常主觀的; 它是你編碼風格的一部分。

如果異常沒有處理程序,則未指定是否在std::terminate之前調用本地對象的析構函數。

如果你想讓這個行為可以預測,那么main是一個擁有最頂層異常處理程序的好地方,有一些報告。

通常這就是我放在main中的所有內容,否則只會調用cppMain ... ;-)

干杯&hth。,

通常,我執行必要的特定於平台的設置操作,然后委托給對象。 對象優於函數沒有什么優勢,但是對象可以從接口繼承,如果你說平台無關的庫使用接口實現回調,這是很好的。

您給出的示例只是將主函數移動到命名空間中。 我沒有看到這里的優勢。 道路中間的方法略顯傾向於使用Master Class模型。 Master Class對象通常很大,最好在堆上創建。 我有main函數創建對象並處理可能在此處發生的任何錯誤。

class MasterClass {
public:
static MasterClass* CreateInstance( int argc, char **argv );
    // ...
}

int main(int argc, char** argv)
{
    try
    {
         MasterClass mc = MC::CreateInstance(argc, argv);
    }
    catch(...)
    {
        // ...
    }
}

這還具有以下優點:任何與實際程序邏輯無關的處理(例如,讀取環境等)都不必放在MasterClass中。 他們可以進入main()。 一個很好的例子是Lotus Domino系統的服務器加載項任務。 這里的任務只應在Domino調度程序任務將控制權移交給它時運行。 這里的主要內容可能如下所示:

STATUS LNPUBLIC AddInMain(HMODULE hModule, int argc, char far *argv[])
{
     MasterClass mc = MC::CreateInstance(argc, argv);
     while(/* wait for scheduler to give control */)
     {
          STATUS s = mc->RunForTimeSlice();
          if (s != SUCCESS)
               break;
     }
     // clean up
}

因此,與調度程序交互的所有邏輯都是主要的,程序的其余部分不必處理任何邏輯。

我更喜歡IOC(Inversion of Control)方法來實現我的程序。

因此,我的“main”使用命令參數來確定程序的“選項”和“配置”。 通過選項我的意思是解釋在命令行中傳遞的某些標志,並且通過配置我的意思是加載配置文件。

它用於加載配置文件的對象有一個“運行”命令,但運行的內容(如果有的話)也取決於命令行參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM