如何使代码模块化?

问题描述 投票:23回答:10

我有一些Java程序,现在我想知道它是否是模块化的,如果它是模块化的,那么在多大程度上,因为模块化永远不能是二进制术语,即0或1.我如何确定特定代码是模块化的在很大程度上。我想知道如何使代码更加模块化?

java module osgi modularity
10个回答
37
投票

模块化的一些基准:

  1. 你有多少次rewriting similar code做特定任务?
  2. 如果您在程序的某个部分更改某些内容,您有多少代码refactor your code
  3. 文件是否更小,更容易浏览?
  4. application modules是否在需要时充分独立地表现?
  5. 你的代码有多糟糕?当你只删除一个函数或变量时,一切都会失败吗?在重新命名课程时,你会得到20多个错误吗? (对于Instance,您可以实现堆栈机制以跟踪应用程序中的所有跃点)
  6. 代码与自然语言的使用有多接近(即模块及其子组件代表更多的真实世界对象,而不必过多关注网络源文件的大小)。

有关check this outsoftware quality的更多想法

至于你担心首先使你的代码更加模块化,你应该问自己上面的问题,获得它们的具体答案,然后看看this

基本原理是将应用程序分解为尽可能小的代码片段,整齐地排列在众多易于理解和可访问的目录布局中。

应用程序中的每个方法都必须不超过所需处理的最小量。将这些方法组合到越来越多的宏级别方法中应该会引导您返回到您的应用程序


0
投票

package-by-feature的想法有助于使代码更加模块化。

在Web上看到的许多示例将应用程序首先划分为多个层,而不是功能

  • 楷模
  • 数据访问
  • 用户界面

但是,使用与功能对齐而不是图层的顶级软件包来划分应用程序似乎更好。

这是一个使用逐个功能的网络应用程序的example。请注意顶级包的名称,它们作为应用程序中实际功能的列表读取。还要注意每个包装如何包含与功能相关的所有项目 - 这些项目不会遍布整个地方;大多数情况下,它们都在一个包/目录中。

通常,删除此类应用程序中的功能可以在单个操作中实现 - 删除单个目录。


25
投票

关键点是

  • 关注点分离
  • 凝聚
  • 封装(通过接口通信)
  • 可替代性
  • 可重用性

这种模块系统的一个很好的例子是标准汽车零件,如盘式制动器和汽车立体声。在制造汽车时,您不希望从头开始构建汽车音响。你宁愿买它并插上它。你也不希望制动系统影响汽车音响 - 或者更糟糕的汽车音响会影响制动系统。

为了回答你的问题,“我如何确定特定代码在很大程度上是模块化的”,我们可以形成问题来测试模块性。您是否可以轻松地用其他东西替换模块而不影响应用程序的其他部分?

XML解析器可能是另一个例子。一旦获得DOM接口,您实际上并不关心在下面使用哪种XML解析器实现(例如Apache Xerces或JAXP)。

在Java中,另一个问题可能是:是否所有功能都可以通过interfaces访问?接口几乎照顾低耦合。

另外,您能用一句话描述系统中的每个模块吗?例如,汽车音响播放音乐和广播。盘式制动器使车辆安全减速。


(这是我写给What is component driven development?的内容)

根据维基百科,基于组件的开发是Component-based software engineering (CBSE)的别名。

[它]是软件工程的一个分支,其优先级是关于整个给定软件系统中可用的广泛功能的关注点的分离。

这有点模糊,让我们来看看更多细节。

单个组件是封装一组相关功能(或数据)的软件包或模块。

所有系统进程都放在单独的组件中,以便每个组件内的所有数据和函数在语义上相关(就像类的内容一样)。由于这个原理,人们常说组件是模块化和内聚的。

因此,根据这个定义,组件可以是任何东西,只要它做的一件事情真的很好而且只有一件事。

关于系统范围的协调,组件通过接口相互通信。 [...]这个原则导致被称为封装的组件。

所以这听起来越来越像我们认为好的API或SOA应该是什么样子。

提供的接口由棒棒糖表示,并且所需的接口由以UML连接到组件外边缘的开放套接字符号表示。

alt text

组件的另一个重要属性是它们是可替代的,因此如果后续组件满足初始组件的要求(通过接口表示),则组件可以被另一个组件(在设计时或运行时)替换。

可重用性是高质量软件组件的重要特征。应该设计和实现软件组件,以便可以在许多不同的程序中重用它。

可替代性和可重用性是使组件成为组件的原因。那么这与面向对象编程有什么区别?

面向对象编程(OOP)中的思想是软件应该根据它所代表的实际或想象的对象的心理模型来编写。 [...]

相比之下,基于组件的软件工程没有做出这样的假设,而是声明应该通过将预制组件粘合在一起来开发软件,就像在电子或机械领域一样。


3
投票

要回答有关如何使代码更加模块化的具体问题,可以采用以下几种方法:

  • 模块化的最佳工具之一是发现代码重用。如果您发现您的代码在多个地方完成相同的(或非常相似的)事物,那么它就是模块化的好选择。
  • 确定哪些逻辑片段可以独立,在某种意义上,其他逻辑将使用它们而不需要知道它们是如何构建的。这有点类似于OO设计中的内容,尽管模块/组件不一定需要与OO中的建模对象相对应。

2
投票

你好,

请参阅“如何封装软件(第1部分)”,此处:

http://www.edmundkirwan.com/encap/overview/paper7.html

问候,

埃德。


1
投票

由于这已被'osgi'标记,我可以引入与OSGi相关的视角。

简短的回答是,可以从完全意大利面条代码到模块化的小步骤;它不一定是大爆炸。例如,即使意大利面条代码依赖于某种bolognaise日志库,所以在某种意义上,它已经是模块化的,只有One Very Big Metball(抱歉,模块)。

诀窍是将大肉丸打成一个较小的块,然后是一个稍微不那么大的肉丸然后递归。它并非都必须一气呵成;每次只需更多地切断,直到没有任何东西可以移除。

至于OSGi,它仍然可以将超级jar放入一个包中。实际上,你可以在不改变位的情况下做到这一点;或者通过修改Manifest.MF,或者将其包装在另一个JAR中并在清单中指定Bundle-ClassPath:metaball.jar。

如果做不到这一点,像BND这样的工具可以帮助您生成所需的正确数据,然后可以轻松地将其放入OSGi运行时。但是要注意过度耦合的代码,以及那些与类加载器混在一起的东西 - 那些会让你失望。


0
投票

假设我理解你的问题,你想知道什么使代码模块化,因为代码模块显然需要彼此之间的依赖才能工作。这是我的答案:

如果您可以将系统分解为模块,并且可以单独测试这些模块,则表明系统是模块化的。


0
投票

正如你所说,模块化不是二元的东西,所以它取决于你的相对定义。

我想说:你能在任何需要执行该功能的程序中使用给定的方法吗?它是“黑匣子”,你不需要知道它在引擎盖下做了什么?如果答案是否定的,即该方法只能在该程序中正常工作,那么它不是真正的模块化。


0
投票

模块化与开发代码的人有关。但我认为普遍的共识是模块化代码是代码,其中包含可以轻松交换的部分,而无需更改大部分原始代码。

恕我直言,如果您有3个模块A B和C,并且您想要完全更改或更换模块C,如果执行此操作是SIMPLE任务,那么您将拥有模块化代码。


0
投票

您可以使用代码分析工具(如CAP)来分析类型和包之间的依赖关系。它们将帮助您查找和删除任何循环依赖项,这在尝试开发模块化代码时通常是个问题。如果没有循环依赖关系,您可以开始将代码分离为离散的jar。

一般来说,如果可以的话,最好对接口进行编码,这通常意味着您的代码可以更容易地在不同的上下文中重构和/或使用。

依赖注入框架(如Spring)也可以帮助您设计的模块化。当类型通过某些外部配置过程注入其依赖项时,它们不需要直接依赖于实现。

© www.soinside.com 2019 - 2024. All rights reserved.