包和命名空间代表着什么?

概念封装

我觉得如果我们的项目结构能以某种方式既体现出架构也体现出领域的话,我们的代码库的可维护性可以得到极大地提升。实际上现在我敢笃定这也是唯一可行的方式(当我们面对大中型企业应用时)。

代码库如果组织得当,特定代码单元只有一处位置可供它存放。我们可能并不知道到具体的位置,但一定只有一条逻辑路径可以让我们顺藤摸瓜找到它。

包的定义

将类划分成包可以让我们在更高的抽象级别来思考设计。其目标是将你的应用中的类按照某种条件进行分片,然后将这些分片分配到包中。这些包之间的关系表达出了应用高级别的组织方式。—— Robert C. Martin 1996, Granularity pp. 3

将概念上相关的代码定义成包,我们需要达成的目标。这些包十分重要,因为它们定义了概念上相关且独立于其它包的代码单元,还有这些包之间的关系。

这样做的目的是:

  • 理解代码单元之间的关系
  • 维护代码单元之间的逻辑关系
  • 实现高内聚低耦合的代码包
  • 在不影响/极少影响应用的情况下重构代码包
  • 在不影响/极少影响应用的情况下替换代码包的实现

分包的原则

我们要遵循 Robert C. Martin 在 1996 年和 1997 年提出的包划分原则以及其他的一些原则来达成目标,主要有 CCP (Common Closure Principle,共同封闭原则), the CRP (Common Reuse Principle,共同重用原则) 和 SDP (Stable Dependencies Principle,稳定依赖原则)。

Robert C. Martin 提出的包划分原则:

包内聚原则

  • REP – 重用发布等价原则:重用的粒度等价于发布的粒度
  • CCP – 共同封闭原则:一起被修改的类应该放在一个包里
  • CRP – 共同重用原则:一起被重用的类应该放在一个包里

包耦合原则

  • ADP – 无环依赖原则:包的依赖图中不能出现循环
  • SDP – 稳定依赖原则:依赖应该朝着稳定的方向前进
  • SAP – 稳定抽象原则:抽象的级别越高,稳定性就越高

要想合理地运用 SDP,我们应该定义出代码的概念单元(组件)和组件的分层,这样我们才能搞清楚那些组件应该了解(依赖)其它组件。

然而,如果这些组件的边界不够清晰,我们就会把本该互不相干的代码代码单元混在一起,让它们耦合在一起变成意大利面式代码,最后将无法维护。

要让这些边界能清楚地呈现出来,我们需要把概念上相关的类放在同一个包中,就像我们把概念上相关的方法放在同一个类中一样。在包这个级别,我们只能用一些名字在领域中有一定含义(例如,UserManagement、Orders、Payments 等)的文件夹来区分它们。在最底层的级别,即包内的叶子节点,我们才会在必要时按照功能作用区分类(例如,Entity、Factory、Repository 等)。

下面这个问题可以帮助我们反思如何设计出低耦合的组件:

“如果我想去掉一个业务概念,是不是删除掉它的组件根目录就能把这个业务概念的所有代码删除而且应用的剩余部分还不会被破坏?”

如果答案是肯定的,那么我们就有了一个解耦得不错的组件。

例如,在命令总线架构中,命令和处理器离开对方就无法工作,它们在概念上和功能上都绑定在一起,因此,如果我们需要去掉该逻辑就要将它们一起去掉。如果它们在同一个位置,我们只用删除一个文件夹就好(我们并非真的要删除代码,只是借助这种思维方式来帮我们得到解耦和内聚的代码)。所以,遵循 CCP 和 CRP 原则,命令应该和它的处理器放在同一个文件夹中。

任何代码只能存在于一个逻辑上的位置,即使对项目中的新手和初级开发者来说,这个位置也是十分明了的。这能避免自相矛盾、令人费解、重复的代码和开发者的挫败感。如果因为无法在代码本该在的位置找到它,和/或难以理解哪些代码和手头上正在处理的代码有关,而导致我们需要去搜寻这些代码…那么我们的项目结构就很糟糕,甚至是更坏的情况,架构很糟糕。

尖叫架构

尖叫架构是 Robert C. Martin 的想法,它基本上表明了这样一个观点,架构应该清楚地告诉我们系统是做什么的:即它的主要领域。那么源代码文件夹里出现的第一级目录自然就应该和领域概念有关,即最顶层的限界上下文(例如,患者、医生、预约等)。它们应该和系统使用的工具(例如,Doctrine、MySQL、Symfony、Redis 等)无关,和系统的功能块(例如,资源库、制图、控制器等)无关,和传达机制无关(HTTP、控制台等)。

你的架构应该呈现给人的应该是系统,而不是系统使用的框架。如果你构建的是一个医疗保健系统,那么新程序员看到源代码仓库后的第一映像应该是:“哦,这是一个医疗保健系统”。—— Robert C. Martin 2011, Screaming Architecture

这实际上是一种更简单地理解他十五年前发表的包划分原则的方法,这些原则之前我已经阐述过了。这种分包的风格又叫做“按特性分包”。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章