it-swarm.cn

在C ++中使用名称空间的最佳做法

几个月前,我已经读过Bob叔叔的 Clean Code ,它对我编写代码的方式产生了深远的影响。即使看起来他在重复每个程序员都应该知道的事情,将它们放在一起并付诸实践确实可以使代码更简洁。特别是,我发现将大型函数分解为许多微型函数,并将大型类分解为许多微型类非常有用。

现在问这个问题。本书的示例全部使用Java,而过去几年我一直在C++中工作。 Clean Code中的思想如何扩展到Java中不存在的名称空间的使用? (是的,我知道Java软件包,但实际上并不相同。)

将创建许多微小实体(每个都有明确定义的责任)的想法应用于命名空间是否有意义?一小部分相关类是否应该始终包装在命名空间中?这是管理拥有许多小类的复杂性的方法,还是管理大量名称空间的成本过高?

编辑:我的问题在 关于包装原则的维基百科条目 中得到了回答。

39
Dima

(我还没看过Clean Code并且不太了解Java。)

将创建许多微小实体(每个都有明确定义的责任)的想法应用于命名空间是否有意义?

是的,就像重构为多个类和多个函数一样。

一小部分相关类是否应该始终包装在命名空间中?

无需实际回答:是的,您至少应使用一个顶级名称空间。这可以基于项目,组织或您喜欢的任何对象,但是使用很少的全局名称将减少名称冲突。用于将其下所有其他内容分组的单个名称空间仅引入一个全局名称。 (除了外部“ C”功能,但这是由于C的互操作性,并且仅影响其他外部“ C”功能。)

是否应该将一小类相关类包装在专用于它们的名称空间中。特别是如果您发现自己在这些类上使用公共前缀– FrobberThing,FrobberThang,FrobberDoohickey –您应考虑使用名称空间– frobber :: Thing等。如果它们是较大项目的一部分,则它仍将位于您的根名称空间或其他名称空间下。

这是管理拥有许多小类的复杂性的方法,还是管理大量名称空间的成本过高?

以上面的前缀名称为例,管理frobber :: Thing比FrobberThing更加容易。使用某些工具,例如文档和代码完成,甚至可能更容易。 ADL有所不同,但这可以使您满意:关联名称空间中的名称较少,使得ADL更易于理解,您可以使用声明将特定名称注入一个或另一个名称空间。

命名空间别名使您可以在特定的上下文中将较短的名称用于较长的命名空间,这又使更容易使用:

void f() {
  namespace CWVLN = Company_with_very_long_name;  // Example from the standard.
  // In this scope, use CWVLN::name instead of Company_with_very_long_name::name.
  namespace fs = boost::filesystem;  // Commonly used.
}

考虑一下Boost,它有一个根根名称空间,boost和随后的许多子命名空间-boost :: asio,boost :: io,boost ::文件系统,boost :: tuples等,用于各种库。 某些名称被“提升” 到根名称空间:

所有定义都在命名空间:: boost :: tuples中,但是最常见的名称通过使用声明提升为命名空间:: boost。这些名称是:Tuple,make_Tuple,tie和get。此外,ref和cref直接在:: boost命名空间下定义。

与带有“实际”模块的语言的最大区别是使用扁平结构的普遍性,这种情况通常发生是因为这是它的工作方式,除非您花费额外的精力来定义嵌套名称。

23
Fred Nurk

您应该为所有代码使用一个主命名空间。就命名空间而言,这与外部代码有所区别。

在主命名空间中,根据大小和复杂性,您可以打开子命名空间。这是名称在上下文中明确表示某些含义的地方,而相同的名称可能在不同的上下文中使用。

特别是,如果您有一个通用的名称,例如FileInfo,这意味着在上下文中有特定的含义,请将其放在名称空间中。

您也可以为此使用类,尽管类是不可扩展的,因此您不能在不修改其标题的情况下向该类添加新的声明。

9
CashCow

命名空间不是模块的概念,因此我仅在可能发生名称冲突的地方使用它们。

3
Brainlag

我喜欢深名称空间(通常意味着三个级别)。

  • 我有公司名.
  • app/util/lib/etc
  • 专案名称/或包装

根据情况,我可能还会再上一层

  • 详细信息(特定于平台的实现详细信息)
  • utils(尚未移动到通用实用程序的实用程序对象)。
  • 无论我需要什么.
1
Martin York

Java有名称空间,只是没有真正使用它们。在javax.swing.*javax是命名空间,而swing是子命名空间。我还没有读过这本书,不知道它对Java)软件包说了什么),但是相同的原理几乎可以直接应用于任何语言的名称空间。

一个很好的启发式方法是,当您发现自己想一遍又一遍地为类键入相同的前缀时,就使用名称空间。例如,我最近编写了一些名为OmciAttribute,OmciAlarm,OmciMe等的类,并意识到我需要将Omci分解为自己的命名空间。

1
Karl Bielefeldt