Java 如何使代码模块化?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1444221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make code modular?
提问by
I have some Java programs, now I want to find out whether it is modular or not, if it is modular then up to what extent, because modularity can never be binary term i.e. 0 or 1. How do I decide that particular code is modular upto this much extent. I want to know how to make code much more modular?
我有一些 Java 程序,现在我想知道它是否是模块化的,如果它是模块化的,那么到什么程度,因为模块化永远不能是二进制术语,即 0 或 1。我如何确定特定代码是模块化的到这个程度。我想知道如何使代码更加模块化?
回答by Christian
Assuming I understand your question, that you want to know what it is that makes code modular, since code modules will obviously need some dependency between each other to work at all. This is my answer:
假设我理解您的问题,您想知道是什么使代码模块化,因为代码模块显然需要彼此之间存在某种依赖性才能工作。这是我的回答:
If you can break your system down into modules, and you can test those modules in isolation, that is a good indication that a system is modular.
如果您可以将系统分解为模块,并且可以单独测试这些模块,那么这很好地表明系统是模块化的。
回答by Smalltown2k
As you say modularity is not a binary thing so it depends on your relative definition.
正如你所说的模块化不是一个二元的东西,所以它取决于你的相对定义。
I would say: Can you use a given method in any program where you need to perform that function? Is it the "black box" where you wouldn't need to know what it were doing under the hood? If the answer is no, i.e. the method would only work properly in that program then it is not truely modular.
我会说:你能在任何需要执行该功能的程序中使用给定的方法吗?它是一个“黑匣子”,你不需要知道它在做什么?如果答案是否定的,即该方法只能在该程序中正常工作,那么它就不是真正的模块化。
回答by Peter D
Modularity is relative to who ever is developing the code. But I think the general consensus is that modular code is code that has portions that can easily be swapped out without changing most of the original code.
模块化与开发代码的人有关。但我认为普遍的共识是,模块化代码是指可以在不更改大部分原始代码的情况下轻松换出部分的代码。
IMHO, If you have 3 modules A B and C and you want to change or replace module C completely, if it is a SIMPLE task to do so then you have modular code.
恕我直言,如果您有 3 个模块 AB 和 C,并且您想完全更改或替换模块 C,如果这样做是一项简单的任务,那么您就有了模块化代码。
回答by Rich Seller
You can use a code analysis tool such as CAPto analyse the dependencies between types and packages. They'll help you find and remove any cyclic dependencies, which are often a problem when trying to develop modular code. If there are no cyclic dependencies, you can start separating your code into discrete jars.
您可以使用CAP等代码分析工具来分析类型和包之间的依赖关系。它们将帮助您找到并删除任何循环依赖项,这在尝试开发模块化代码时通常是一个问题。如果没有循环依赖,您可以开始将代码分离到离散的 jar 中。
In general it is good practice to code to interfaces if you can, this generally means your code can more easily be refactored and/or used in different contexts.
一般来说,如果可以的话,最好对接口进行编码,这通常意味着您的代码可以更容易地重构和/或在不同的上下文中使用。
Dependency injection frameworks such as Springcan also help with the modularity of your design. As types are injected with their dependencies by some external configuration process they don't need a direct dependency on an implementation.
Spring等依赖注入框架也可以帮助实现设计的模块化。由于类型通过某些外部配置过程注入了它们的依赖项,因此它们不需要直接依赖于实现。
回答by OrangeRind
Some Benchmarks for modularity:
模块化的一些基准:
- How many times are you rewriting similar codefor doing a particular task?
- How much code do you have to refactor your codein case you change something somewhere in a part of your program?
- Are the files smaller and easierto navigate through?
- Are the application modulesperforming adequately and independently as and when required?
- How less disastrousis your code? Does all hell break lose when you delete just one function or variable? Do you get 20-odd errors upon re-naming a class?(For Instance you can implement a stacking mechanismto keep trace of all the hops in your application)
- How near is the code to natural language usage(i.e. modules and their subcomponents represent more real world objects without giving much concern to net source file size).
- 您为完成特定任务而重写了多少次类似的代码?
- 如果您在程序的某个部分更改某些内容,您需要重构多少代码?
- 文件是否更小且更易于浏览?
- 应用模块是否在需要时充分且独立地执行?
- 你的代码的灾难性有多小?当你只删除一个函数或变量时,所有的事情都会失败吗?重命名类时是否会出现 20 多个错误?(例如,您可以实施堆栈机制来跟踪应用程序中的所有跃点)
- 代码与自然语言使用有多接近(即模块及其子组件代表更真实的世界对象,而无需过多关注净源文件大小)。
For more ideas check this outand this one on software quality
As for your concern on making your code more modularfirst you should ask yourself the above questions, obtain specific answers for them and then have a look at this
至于您对让代码更加模块化的担忧,您应该先问自己上述问题,为它们获得具体的答案,然后再看看这个
The basic philosophyis to break down your application into as small a code fragments as possible arranged neatly across a multitude of easily understandable and accessible directory layout.
的基本理念是将您的应用程序分解成尽可能小的代码段尽可能跨容易理解和访问的目录布局的许多排列整齐。
Each method in your application must do no more than the minimum quanta of processing needed. Combining these methods into more and more macro level methods should lead you back to your application
应用程序中的每种方法都不得超过所需的最小处理量。将这些方法组合成越来越多的宏观层面的方法应该会让你回到你的应用程序
回答by Eugene Yokota
Key points are
关键点是
- Separation of concerns
- Cohesion
- Encapsulation (communicates via interface)
- Substitutability
- Reusability
- 关注点分离
- 凝聚
- 封装(通过接口通信)
- 可替代性
- 可重用性
A good example of such module system is standard car parts like disk brakes and car stereo. You don't want to build car stereo from scratch when you are building cars. You'd rather buy it and plug it in. You also don't want the braking system affecting the car stereo —?or worse car stereo affecting the brake system.
这种模块系统的一个很好的例子是标准汽车部件,如盘式制动器和汽车音响。在制造汽车时,您不想从头开始制造汽车音响。您宁愿购买并插入它。您也不希望制动系统影响汽车音响——或者更糟的汽车音响影响制动系统。
To answer your question, "How do I decide that particular code is modular up to this much extent," we can form questions to test the modularity. Can you easily substitute your modules with something else without affecting other parts of your application?
要回答您的问题“我如何确定特定代码的模块化程度如此之高”,我们可以形成问题来测试模块化。你能轻松地用其他东西替换你的模块而不影响应用程序的其他部分吗?
XML parsers could be another example. Once you obtain the DOM interface, you really don't care which implementation of XML parser is used underneath (e.g. Apache Xerces or JAXP).
XML 解析器可能是另一个例子。一旦您获得了 DOM 接口,您就真的不关心下面使用了哪种 XML 解析器实现(例如 Apache Xerces 或 JAXP)。
In Java, another question may be: Are all functionality accessible via interface
s?Interface pretty much takes care of the low coupling.
在 Java 中,另一个问题可能是:所有功能都可以通过interface
s访问吗?接口几乎负责低耦合。
Also, can you describe each module in your system with one sentence?For example, a car stereo plays music and radio. Disk brakes decelerate the vehicle safely.
另外,你能用一句话描述你系统中的每个模块吗?例如,汽车音响播放音乐和收音机。盘式制动器使车辆安全减速。
(Here's what I wrote to What is component driven development?)
(这是我写的什么是组件驱动开发?)
According to Wikipedia, Component-Based Development is an alias for Component-based software engineering (CBSE).
根据维基百科,基于组件的开发是基于组件的软件工程(CBSE)的别名。
[It] is a branch of software engineering, the priority of which is the separation of concernsin respect of the wide-ranging functionality available throughout a given software system.
[它] 是软件工程的一个分支,其优先级是在整个给定软件系统中可用的广泛功能方面的关注点分离。
This is somewhat vague, so let's look at more details.
这有点含糊,所以让我们看看更多细节。
An individual component is a software package, or a module, that encapsulates a set of related functions (or data).
All system processes are placed into separate components so that all of the data and functions inside each component are semantically related (just as with the contents of classes). Because of this principle, it is often said that components are modularand cohesive.
单个组件是封装一组相关功能(或数据)的软件包或模块。
所有系统进程都放置在单独的组件中,以便每个组件内的所有数据和功能在语义上都是相关的(就像类的内容一样)。因为这个原则,人们常说组件是 模块化的、有凝聚力的。
So, according to this definition, a component can be anything as long as it does one thing really well and only one thing.
所以,根据这个定义,一个组件可以是任何东西,只要它真正做好一件事并且只做一件事。
With regards to system-wide co-ordination, components communicate with each other via interfaces. [...] This principle results in components referred to as encapsulated.
关于系统范围的协调,组件通过接口相互通信。[...] 这一原则导致组件被称为封装。
So this is sounding more and more like what we think of good API or SOA should look like.
所以这听起来越来越像我们认为好的 API 或 SOA 应该是什么样子。
The providedinterfaces are represented by a lollipop and requiredinterfaces are represented by an open socket symbol attached to the outer edge of the component in UML.
的提供接口由棒棒糖表示,并且需要接口由附连到在UML组件的外边缘开放的插座符号表示。
Another important attribute of components is that they are substitutable, so that a component could be replaced by another (at design time or run-time), if the requirements of the initial component (expressed via the interfaces) are met by the successor component.
Reusability is an important characteristic of a high quality software component. A software component should be designed and implemented so that it can be reused in many different programs.
组件的另一个重要属性是它们是可 替换的,因此如果后续组件满足初始组件的要求(通过接口表达),则可以将一个组件替换为另一个组件(在设计时或运行时)。
可重用性是高质量软件组件的重要特征。软件组件的设计和实现应该使其可以在许多不同的程序中重用。
Substitutability and reusability is what makes a component a component. So what's the difference between this and Object-Oriented Programming?
可替代性和可重用性使组件成为组件。那么这和面向对象编程有什么区别呢?
The idea in object-oriented programming (OOP) is that software should be written according to a mental model of the actual or imagined objects it represents. [...]
Component-based software engineering, by contrast, makes no such assumptions, and instead states that software should be developed by gluing prefabricated components together much like in the field of electronics or mechanics.
面向对象编程 (OOP) 的思想是,软件应该根据它所代表的实际或想象的对象的心理模型来编写。[...]
相比之下,基于组件的软件工程没有做这样的假设,而是指出应该通过将预制组件粘合在一起来开发软件,就像在电子或机械领域一样。
回答by DVK
To answer your specific question of how to makethe code more modular, a couple of approaches are:
要回答有关如何使代码更加模块化的具体问题,有以下几种方法:
One of best tool for modularization is spotting code re-use. If you find that your code does the same exact (or very similar) thing in more than once place, it's a good candidate for modularizing away.
Determine which pieces of logic can be made independent, in a sense that other logic would use them without needing to know how they are built. This is somewhat similar to what you to in OO design, although module/component does not necessarily need to correspond to a modeled object as in OO.
模块化的最佳工具之一是发现代码重用。如果您发现您的代码在不止一次的地方做了完全相同(或非常相似)的事情,那么它是模块化的一个很好的候选者。
确定哪些逻辑部分可以独立,从某种意义上说,其他逻辑将使用它们而无需知道它们是如何构建的。这有点类似于您在 OO 设计中所做的,尽管模块/组件不一定需要与 OO 中的建模对象相对应。
回答by John O
The package-by-featureidea helps to make code more modular.
该包通过特征想法有助于使代码更模块化。
Many examples seen on the web divide applications first into layers, not features
在网络上看到的许多示例首先将应用程序划分为层,而不是功能
- models
- data access
- user interface
- 楷模
- 数据存取
- 用户界面
It seems better, however, to divide applications up using top-level packages that align with features, not layers.
然而,使用与功能而不是层对齐的顶级包来划分应用程序似乎更好。
Here is an exampleof a web app that uses package-by-feature. Note the names of the top-level packages, which read as a list of actual features in the application. Note as well how each package contains all items related to a feature - the items aren't spread out all over the place; most of the time, they are all in a single package/directory.
以下是使用按功能打包的 Web 应用程序示例。请注意顶级包的名称,它们读取为应用程序中实际功能的列表。还要注意每个包如何包含与功能相关的所有项目 - 这些项目不会散布在所有地方;大多数时候,它们都在一个包/目录中。
Usually, deletion of a feature in such an app can be implemented in a single operation - deletion of a single directory.
通常,删除此类应用程序中的功能可以通过单个操作实现 - 删除单个目录。
回答by AlBlue
Since this has been tagged with 'osgi', I can throw in an OSGi-related perspective.
由于这已被标记为“osgi”,因此我可以提出与 OSGi 相关的观点。
The short answer is that it is possible to go from completely spaghetti code to modular in small steps; it doesn't have to be a big bang. For example, even spaghetti code depends on some kind of bolognaise logging library, so in some sense, it's already modular, just with One Very Big Metball (sorry, module) in it.
简短的回答是,可以通过小步骤从完全意大利面条式代码转变为模块化;它不一定是大爆炸。例如,即使是意大利面条式代码也依赖于某种 bolognaise 日志库,因此从某种意义上说,它已经是模块化的,只是其中包含一个非常大的 Metball(抱歉,模块)。
The trick is to break the big meatball into one smaller chunk and then a slightly less big meatball and then recurse. It doesn't all have to be done in one go either; simply chip off a bit more each time until there is nothing left to remove.
诀窍是将大肉丸分成一个较小的块,然后再将一个稍小的肉丸分成小块,然后递归。也不必一次性完成所有工作;每次只需切掉一点,直到没有任何东西可以去除。
As for OSGi, it's still possible to put an uber-jar into a bundle. In fact, you can do this without changing the bits; either by modifying the Manifest.MF in place, or by wrapping that in another JAR and specify Bundle-ClassPath: metaball.jar in the manifest.
至于 OSGi,仍然可以将 uber-jar 放入一个包中。事实上,你可以在不改变位的情况下做到这一点;通过修改 Manifest.MF 或将其包装在另一个 JAR 中并在清单中指定 Bundle-ClassPath: metaball.jar。
Failing that, tools like BND can help generate the right data you'd need, and then it can be dropped in an OSGi runtime easily enough. But beware of overly coupled code, and stuff that mucks around with classloaders - those will trip you up.
否则,像 BND 这样的工具可以帮助生成您需要的正确数据,然后可以很容易地将其放入 OSGi 运行时中。但要注意过度耦合的代码,以及那些与类加载器混在一起的东西——它们会让你绊倒。
回答by AlBlue
Hej,
嘿嘿
See, "How to encapsulate software (Part 1)," here:
请参阅此处的“如何封装软件(第 1 部分)”:
http://www.edmundkirwan.com/encap/overview/paper7.html
http://www.edmundkirwan.com/encap/overview/paper7.html
Regards,
问候,
Ed.
埃德。