2011-07-08 40 views
5

以下是我在尋找:在Xcode中組織大型Cocoa應用程序的源代碼的最佳方式是什麼?

我想的功能件分成模塊或某種其他類別的限制可視性部件,以防止每個類可以訪問所有其他類隨着時間的推移會產生意大利麪代碼。例如,在Eclipse中,我將使用包,並將每個包放入一個具有明確定義的依賴關係結構的獨立項目中。

事情我已經考慮:

  1. 使用單獨的文件夾源文件並在Xcode使用羣組:
    • 優點:簡單的事情,配置幾乎不需要的Xcode
    • 缺點:沒有編譯時功能的分離,即訪問所有內容只有一個#import聲明
  2. 使用框架
    • 優點:框架代碼無法訪問框架之外訪問類。這強制封裝並保持獨立
    • 缺點:如果您同時在多個Frameworks上工作,則代碼管理非常麻煩。每個框架是一個獨立的Xcode項目有一個單獨的窗口
  3. 使用插件
    • 優點:以框架類似,插件代碼不能訪問其他插件的代碼。在編譯時清理分離。插件源可以是同一個Xcode項目的一部分。
    • 缺點:不確定。這可能是要走的路......根據你的經驗

,你會選擇什麼讓事情分開,同時能夠編輯所有資源在同一個項目?

編輯:

  • 我針對Mac OS X的
  • 我真的尋找一個解決方案在編譯時
  • 強制分離到的插件我的意思是可可束(HTTP: //developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingCode/Concepts/Plugins.html)
+2

重要的插件:它們在iOS下無效。希望你的目標是OS X.在Xcode 4中,在同一個窗口中管理多個目標和項目 - 包括框架 - 非常簡單,你只需要去File> New Workspace。 –

回答

9

我有一些很好的大小的Mac項目的經驗(> 2M SLOC在我的最後一個90個xcodeproj文件),這裏是我的管理他們的想法:

  • 避免像框架,捆綁動態負載,或者dylibs,除非你實際上共享組之間的二進制文件。這些往往會創造出比我的經驗更復雜的解決方案。另外,它們不會輕鬆移植到iOS,這意味着需要維護多種方法。最糟糕的是,擁有大量動態庫會增加兩次包含相同符號的可能性,從而導致各種瘋狂的錯誤。當你直接在一個以上的庫中直接包含一些「助手」類時會發生這種情況。如果它包含一個全局變量,那麼這個錯誤很棒,因爲不同的線程使用全局的不同實例。

  • 靜態庫是許多情況下的最佳選擇,如果不是大多數情況下。他們在構建時解決所有問題,允許在C/C++中進行代碼剝離以及其他優化在動態庫中不可行。他們擺脫了「嘿,它加載在我的系統上,而不是客戶的」(當你使用框架路徑的錯誤值時)。計算崩潰堆棧中的行號時無需處理幻燈片。它們在構建時捕獲重複的符號,節省了許多小時的調試難度。

  • 將主要組件分離爲單獨的xcodeproj。不過,真的想想這裏的「主要」意味着什麼。我的90項目產品太多了。只要進行依賴性檢查就可以成爲非常不平凡的練習。 (Xcode 4可以改善這一點,但是在我們讓Xcode 4能夠可靠地構建它之前我就離開了這個項目,所以我不知道它到底有多好。)

  • Private to Private頭。您可以像使用Frameworks一樣使用靜態庫來執行此操作。將公共標題放在不同的目錄中。爲此,我建議每個組件都有自己的公開include目錄。

  • 請勿複製標題。直接從組件的公共include目錄中加入它們。複製標題到共享樹似乎是一個好主意,直​​到你做到這一點。然後你發現你正在編輯副本而不是真正的副本,或者你正在編輯真正的副本,但實際上並沒有複製它。無論如何,這使得開發令人頭疼。

  • Use xcconfig files, not the build pane.構建面板會讓你在這些大項目中瘋狂。礦往往有線路是這樣的:


common="../../common" 
foo="$(common)/foo" 
HEADER_SEARCH_PATHS = $(inherited) $(foo)/include 

  • 在你的公開頭的路徑,包括您自己的包名稱。在上面的例子中,主標題的路徑是common/foo/include/foo/foo.h。額外的水平看起來很痛苦,但是當你導入時它是一個真正的勝利。然後你總是這樣導入:#import <foo/foo.h>。保持一切非常乾淨。不要使用雙引號導入公共標題。只能使用雙引號導入您自己的組件中的私有頭文件。

  • 我還沒有確定Xcode 4的最佳方式,但在Xcode 3中,您應該始終鏈接自己的靜態庫,方法是將該項目添加爲子項目並將「.a」目標拖入鏈接步驟。這樣做可以確保您將鏈接爲當前平臺和配置構建的鏈接。我真的很大的項目還沒有能夠轉換到Xcode 4,所以我沒有強烈的意見,但最好的方式。

  • 避免搜索自定義庫(鏈接步驟中的-L-l標誌)。如果您將庫作爲項目的一部分構建,請使用上述建議。如果您預先構建它,請在LD_FLAGS中添加完整路徑。搜索庫包括一些令人驚訝的算法,並使整個事情很難理解。千萬不要將預建的庫放入鏈接步驟。如果將預製的libssl.a放入鏈接步驟中,它實際上會爲該路徑添加-L參數,然後添加-lssl。在默認搜索規則下,即使您在構建窗格中顯示libssl.a,也會鏈接到系統libssl.so。刪除庫將刪除-l,但不會刪除-L,這樣就可以結束奇怪的搜索路徑。 (我討厭構建窗格。)這樣來做,而不是在xcconfig:


LD_FLAGS = "$(openssl)/lib/libssl.a" 

  • 如果您有幾個項目之間共享穩定的代碼,並同時開發者項目你永遠不會混淆這個代碼(並且不希望源代碼可用),那麼框架可以是一個合理的方法。如果您需要插件來避免加載大量不必要的代碼(並且在大多數情況下您確實不會加載該代碼),那麼捆綁包可能是合理的。但在大多數應用程序開發人員的情況下,從靜態庫鏈接在一起的一個大型可執行文件是IMO的最佳方法。共享庫和框架只有在運行時實際共享共享纔有意義。
+0

非常有趣。我沒有想過靜態庫。這可能很適合我。我有兩個應用程序共享的代碼,但我不介意將每個代碼分別鏈接到一個二進制文件中。謝謝! – Mark

+0

我發現了一個很好的教程,展示瞭如何實現您在Xcode中提出的建議:http://www.clintharris。net/2009/iphone-app-shared-libraries/ – Mark

+0

要回答關於框架的一些觀點,可以通過使用「命名空間」前綴,像蘋果在其自己的框架中所做的那樣,輕鬆避免命名衝突。這就是爲什麼'CoreAnimation'中的每個類都以「CA」開頭,「UIKit」中的所有內容都以「UI」開頭。如果您願意,您可以靜態鏈接到框架。沒有什麼規定框架必須使用動態鏈接。實際上,對於iOS,它們只能靜態鏈接。由於Karl Stenerud的努力,他們將iOS移植到iOS上(https://github.com/kstenerud/iOS-Universal-Framework)。 – aroth

4

我的建議是:

  1. 使用框架。它們是您列出的選項中最容易重複使用的構建工件,您描述您嘗試實現的結構的方式聽起來非常像創建一組框架。

  2. 爲每個框架使用一個單獨的項目。如果所有內容都被轉儲到單個項目中,您將永遠無法讓編譯器強制執行所需的訪問限制。如果你不能讓編譯器執行它,那麼祝你的開發人員能夠這樣做。

  3. 升級到XCode4(如果您還沒有的話)。這將允許您在單個窗口中處理多個項目(很像Eclipse的工作方式),而不會混淆項目。這幾乎消除了您在「框架」選項下列出的缺點。

如果你是針對iOS的,我強烈建議你建立real frameworks,而不是假的,你通過維管束破解方法得到的,如果你沒有真正的建立已經框架。

+0

我的目標是Mac OS X.也許現在是時候升級到Xcode 4並使用框架... – Mark

+0

奇怪的是,我真的很希望看到這個答案在2015年爲Xcode 7.x詳細闡述。我面臨同樣的規模問題,我發現無法管理測試應用程序目標以及單元測試目標,而無需將我的應用程序項目拆分爲許多較小的項目。問題是,你怎麼會分享內部代碼,以及如何管理外部依賴。 – fatuhoku

0

這很大程度上取決於您的情況和您自己的具體偏好。

如果您正在編寫「正確的」面向對象的類,那麼您將擁有一個類結構,並在必要時隱藏其他類的方法和變量。除非你的項目非常龐大,並且由數百個不同的可區分模塊構成,否則它可能足以將類和資源分組到XCode中的文件夾/組中,並以這種方式進行工作。

如果你真的有一個容易區分模塊的huuge項目,那麼通過一切手段創建一個框架。我會建議,但只有在不同的應用程序中使用相同的代碼時,纔會真正需要這種情況,在這種情況下,創建框架/額外項目將是在項目之間有效複製代碼的好方法。在幾乎所有其他情況下,它可能只是矯枉過正,而且比需要複雜得多。

你最後的想法似乎是前兩個的混合。插件(據我所知,你正在描述 - 告訴我,如果我錯了)在同一個項目中只是分開的類?這可能是最好的方式,無論如何都應該(在一定程度上)完成。如果您正在創建繪製圖形的功能(例如),則應該將一個新的文件夾/組分開,並在其中啓動您的類和功能,並在必要時將這些類包括到主應用程序中。

讓我這樣說吧。沒有理由超越頂端......但是,即使只是爲了您自己的理智 - 或者您的代碼的可維護性 - 您應該始終努力將所有內容分組爲描述性組/文件夾。

+0

感謝您的建議。我今天使用的是組和麪向對象的方法,但是依賴於我自己的規則不包含頭並引入不應該存在的依賴。通過插件我的意思是實際的可可捆綁:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingCode/Concepts/Plugins.html – Mark

2

通過強迫自己實踐模型 - 視圖 - 控制(MVC),加上一個健康的數量,我設法保持我的理智在我的項目上工作,這個項目在過去幾個月已經發展到相當大的數量的評論,和不可或缺的源代碼控制(顛覆,然後混帳)。

一般來說,我觀察到以下內容:串行化數據

「模型」類(不從那裏關係,並且包括應用程序的「狀態」)在從NSObject的或定製的子類一個Objective-C 1類從NSObject繼承的「模型」類。爲了兼容性,我選擇了更多的Objective-C 1.0版本,因爲它是最低的通用分母,我不想因爲Objective-C 2.0特性的依賴性而從頭開始編寫「模型」類。

視圖類在XIB中,XIB版本被設置爲支持我需要支持的最老的工具鏈(所以我可以使用除Xcode 4之外的先前版本的Xode 3)。我傾向於從Apple提供的Cocoa Touch API和框架開始,從Apple隨着這些API的發展而引入的任何優化/增強中受益。

控制器類包含管理視圖的顯示/動畫(以編程方式以及來自XIB)和通過「模型」類數據的數據序列化的常用代碼。

如果我發現自己多次重複使用一個類,我會探索重構代碼並優化(使用Instruments進行測量)到我所謂的「實用程序」類或協議中。

希望這會有所幫助,祝你好運。

相關問題