在Xcode中组织大型Cocoa应用程序源代码的最佳方法是什么?

Mar*_*ark 5 xcode cocoa modularity objective-c

这是我正在寻找的:

我想将各种功能分成某些模块或组件,以限制其他类的可见性,以防止每个类都可以访问其他类,这些随着时间的推移会产生意大利面条代码.

例如,在Java和Eclipse中,我将使用包并将每个包放入一个具有明确定义的依赖结构的单独项目中.

我考虑过的事情:

  1. 为源文件使用单独的文件夹并在Xcode中使用Groups:
    • 优点:操作简单,几乎不需要Xcode配置
    • 缺点:没有编译时功能分离,即访问所有内容只是一个#import声明
  2. 使用框架:
    • 优点:框架代码无法访问框架之外的访问类.这会强制执行封装并将事物分开
    • 缺点:如果您同时处理多个框架,则代码管理很麻烦.每个Framework都是一个单独的Xcode项目,带有一个单独的窗口
  3. 使用插件:
    • 优点:与Frameworks类似,插件代码无法访问其他插件的代码.在编译时清除分离.插件源可以是同一个Xcode项目的一部分.
    • 缺点:不确定.这可能是要走的路......

根据您的经验,在能够编辑同一项目中的所有来源时,您会选择将内容分开?

编辑:

  • 我的目标是Mac OS X.
  • 我真的在寻找一种在编译时强制分离的解决方案
  • 通过插件我的意思是Cocoa捆绑(http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingCode/Concepts/Plugins.html)

Rob*_*ier 9

我曾经参与过一些大小合适的Mac项目(在我的最后一个90 xcodeproj文件中,> 2M SLOC)以下是我对管理它们的想法:

  • 除非您实际在组之间共享二进制文件,否则请避免使用Frameworks,Bundles或dylib之类的动态加载.这些往往会产生比我在经验中解决的更多的复杂性.另外,它们不容易移植到iOS,这意味着要保持多种方法.最糟糕的是,拥有大量动态库会增加两次包含相同符号的可能性,从而导致各种疯狂的错误.当您直接在多个库中直接包含一些"helper"类时会发生这种情况.如果它包含一个全局变量,那么错误很棒,因为不同的线程使用不同的全局实例.

  • 静态库是许多(如果不是大多数情况下)的最佳选择.它们在构建时解决所有问题,允许在C/C++中进行代码剥离以及动态库中不可能实现的其他优化.他们摆脱了"嘿,它加载到我的系统而不是客户的"(当你使用错误的值框架路径时).从崩溃堆栈计算行号时无需处理幻灯片.它们在构建时捕获重复的符号,从而节省了数小时的调试痛苦.

  • 将主要组件分离为单独的xcodeproj.但是,真的想想这里的"主要"意味着什么.我的90个项目产品太多了.只是进行依赖性检查可能会成为一项非常重要的工作.(Xcode 4可以改进这一点,但是在我们能够让Xcode 4可靠地构建它之前我离开了项目,所以我不知道它到底有多好.)

  • 将公共标题与私有标题分开.您可以使用静态库来完成此操作,就像使用Frameworks一样.将公共标头放在不同的目录中.include为此,我建议每个组件都有自己的公共目录.

  • 不要复制标题.直接从include组件的公共目录中包含它们.在您执行此操作之前,将标头复制到共享树中似乎是一个好主意.然后你会发现你正在编辑副本而不是真正的副本,或者你正在编辑真实副本,而不是实际复制副本.无论如何,它使开发成为头痛的问题.

  • 使用xcconfig文件,而不是构建窗格.构建窗格会让你在这些大项目中疯狂.我倾向于有这样的线:


common="../../common"
foo="$(common)/foo"
HEADER_SEARCH_PATHS = $(inherited) $(foo)/include
Run Code Online (Sandbox Code Playgroud)
  • 在公共标头路径中,包含您自己的包名称.在上面的示例中,主标头的路径是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"
Run Code Online (Sandbox Code Playgroud)
  • 如果你有几个项目之间共享的稳定代码,并且在开发这些项目时你永远不会搞乱这些代码(并且不希望源代码可用),那么框架可以是一种合理的方法.如果您需要插件以避免加载大量不必要的代码(并且在大多数情况下您实际上不会加载该代码),那么捆绑可能是合理的.但在应用程序开发人员的大多数情况下,从静态库链接在一起的一个大型可执行文件是IMO的最佳方法.共享库和框架只有在运行时实际共享时才有意义.