java单一原则_Java包和单一责任原则

java单一原则

The S in the famous (or infamous) SOLID acronym stands for the single responsibility principle (which itself has its own acronym, SRP). It means an entity should have only one single responsibility, and no others.

著名(或臭名昭著)的SOLID首字母缩写词中的S代表单一责任原则(其本身有自己的首字母缩写SRP)。 这意味着一个实体应该只承担一个责任,而没有其他责任。

A good and common example of something that does not follow SRP is a function or procedure (“method,” in Java parlance) that does two different things that should obviously be split off to two separate units.

一个不遵循SRP的良好且常见的例子是一个函数或过程(在Java中,为“方法”),它执行两种不同的操作,显然应该将其拆分为两个单独的单元。

Suppose for example that you and I are tasked with writing a function that takes in a postal code (e.g., a ZIP code as an int), consults an online API and returns the corresponding GPS data.

例如,假设您和我的任务是编写一个函数,该函数采用邮政编码(例如,邮政编码为int ),查询在线API并返回相应的GPS数据。

Let’s say our first draft runs a few lines short of sixty lines. It could be an indication that our function is doing too much.

假设我们的初稿少了六十行。 这可能表明我们的职能做得太多。

Let’s also say that the first thirty lines are devoted to validating the postal code, the next ten are to prepare the API call, and the rest are to process the results of the API call.

我们还假设前三十行专用于验证邮政编码,接下来的十行用于准备API调用,其余的行用于处理API调用的结果。

We certainly need to validate the postal code, because we wouldn’t want to waste an API call on an invalid postal code. But the responsibility for validation needs to be somewhere else, like in a separate function.

我们当然需要验证邮政编码,因为我们不想浪费API调用无效的邮政编码。 但是验证的责任需要在其他地方,例如在单独的功能中。

Or better yet, in a separate class, say, PostalCode. Then it’s the responsibility of the PostalCode constructor to construct valid PostalCode instances, rejecting invalid postal codes.

或者更好的是,在一个单独的类中,例如PostalCode 。 然后, PostalCode构造函数负责构造有效的PostalCode实例,拒绝无效的邮政编码。

With a properly developed and tested PostalCode class, we can refactor our function that returns GPS data to take in a PostalCode instance instead of an int. As it would be redundant to validate the postal code twice, we can now delete the validation in our GPS data retrieval function.

使用经过适当开发和测试的PostalCode类,我们可以重构返回GPS数据的函数,以接受PostalCode实例而不是int 。 由于两次验证邮政编码是多余的,因此我们现在可以在GPS数据检索功能中删除验证。

Single responsibility applies to classes, too, as well as packages, modules and even entire programs. Though the larger the entity, the broader the responsibility has to be defined. But not more broadly than necessary.

单一责任也适用于类,以及包,模块甚至整个程序。 尽管实体越大,责任的定义范围就越大。 但没有比必要范围更广泛。

For instance, the single responsibility of iTunes is to organize music tracks. For it to also manage podcasts, movies, ringtones and apps is perhaps defining the single responsibility of the program way too broadly.

例如,iTunes的唯一职责是组织音乐曲目。 对于它来说,它还可以管理播客,电影,铃声和应用程序,因此可能过于广泛地定义了程序的单一职责。

Before we can talk about how the single responsibility principle applies to Java packages and modules, we have to know what packages and modules in Java are.

在讨论单一责任原则如何应用于Java包和模块之前,我们必须知道Java中的包和模块是什么。

Packages are essentially like folders for the interfaces and classes in a Java project or library. And generally that’s reflected in the directory structure of a project in your operating system, and even in the IntelliJ IDEA iconography.

包本质上类似于Java项目或库中用于接口和类的文件夹。 通常,这反映在操作系统中项目的目录结构中,甚至反映在IntelliJ IDEA图标中。

For example, java.util is a very important package in the Java Development Kit (JDK), java.io is another.

例如, java.util是Java开发工具包(JDK)中非常重要的软件包,而java.io是另一个。

Ignoring comments and whitespace, the package declaration should be the very first thing in a Java source file. For example, the source for the Locale class in java.util should have the following line close to the top:

忽略注释和空格,包声明应该是Java源文件中的第一件事。 例如, java.util Locale类的源代码应在最接近顶部的位置包含以下行:

package java.util;

Note that the package name is followed by a semicolon, not an opening curly brace. There can only be one package declaration in a Java source file.

请注意,程序包名称后跟一个分号,而不是一个花括号。 Java源文件中只能有一个包声明。

In Scala, you could use an opening curly brace at this point, but that only makes sense if you’re including two or more packages in a one source file — a cool but perhaps not too useful feature.

在Scala中,此时您可以使用左花括号,但这仅在您在一个源文件中包含两个或多个软件包的情况下才有意义-这是一个很酷的功能,但可能不太有用。

To use java.util.Locale in our own packages, we could refer to it as such, or we could use an Import statement to save ourselves from having to type “java.util.” each time we want to use Locale.

要在我们自己的程序包中使用java.util.Locale ,我们可以这样称呼它,或者可以使用Import语句来避免自己输入“ java.util.java.util. 每次我们要使用Locale

For example, our first draft of ZIPCode might look something like this:

例如,我们的ZIPCode可能看起来像这样:

package postal;import java.util.Locale;public class ZIPCode extends PostalCode {    // TODO: Override toString()    // TODO: Add constructor for ZIP code without ZIP+4    public ZIPCode(int zip5, int zip4) {
super(zip5 * 10000 + zip4, Locale.US);
// TODO: Add ZIP code validation
}
}

Okay, so maybe the Import statement doesn’t save us any typing if we’re only going to refer to Locale once.

好的,所以如果我们仅要引用一次Locale ,那么Import语句可能不会为我们节省任何输入。

More importantly, however, the package name “postal” might clash with a package name in another library our teammates or our clients might use. This potential problem worried the earliest Java programmers.

但是,更重要的是,程序包名称“ postal ”可能与我们的队友或客户可能使用的另一个库中的程序包名称冲突。 这个潜在的问题使最早的Java程序员感到担忧。

For the most part, you can name a package anything you like, but you shouldn’t start it with “java.” or “javax.”, unless maybe you’re working on a proposal for a JDK.

在大多数情况下,您可以根据自己的喜好为程序包命名,但不应该以“ java. ”开头java. ”或“ javax. ”,除非您正在为JDK制定提案。

I would also strongly advise against starting package names with either “scala.” or “kotlin.”, even if you don’t program in either Scala or Kotlin.

我也强烈建议不要以“ scala. ”开头软件包名称scala. ”或“ kotlin. ”,即使您既不在Scala或Kotlin中也不编程。

However, there is nothing to actually forbid you from starting a package name with “java.” or “javax.” for non-JDK purposes, other than good taste and not wanting to create unnecessary problems for yourself and others.

但是,实际上没有什么可以禁止您使用“ java. ”或“ javax. 出于非JDK的目的,除了具有良好的品味之外,并且不想为自己和他人带来不必要的问题。

Package names of course must not contain reserved Java keywords like “int” or “class.” Uppercase letters may be used in package names, but, by tradition, are generally not used.

程序包名称当然不能包含保留的Java关键字,例如“ int ”或“ class 。 包名称中可以使用大写字母,但传统上通常不使用大写字母。

Package names can’t contain dashes either, but underscores are allowed (underscores have special significance in Scala, so I’m not quire sure on this point, but generally what works in Java should also work in Scala).

程序包名称也不能包含破折号,但允许使用下划线(下划线在Scala中具有特殊的意义,因此我不确定在这一点上是否正确,但是通常在Java中有效的内容在Scala中也应适用)。

Underscores can be used to substitute for spaces or punctuation, but generally words should be run together in lowercase. For example, NetBeans usually suggests “newpackage” as the name for a new package.

下划线可以用来代替空格或标点符号,但是通常单词应以小写形式一起使用。 例如,NetBeans通常建议使用“ newpackage ”作为新软件包的名称。

Digits are allowed in package names, subject to some restrictions, which can be circumvented with an underscore. For example, “4winds” would be invalid, but “_4winds” would be valid; “fourwinds” would be preferable.

软件包名称中允许使用数字,但有一些限制,可以在下划线处加以规避。 例如,“ 4winds ”将无效,而“ _4winds ”将有效; “ fourwinds ”将是更可取的。

We can’t use operators (+, -, *, /, etc., but not counting the period) in package names either, nor any punctuation (aside from the period). The asterisk has special significance for Import statements as a wildcard (e.g., java.util.* to import several classes from that package at once).

我们既不能在包名称中使用运算符( +-*/等,但不计算句点),也不能使用任何标点符号(句点除外)。 星号对于Import语句作为通配符具有特殊的意义(例如, java.util.*一次从该包中导入多个类)。

Accented letters can be used, but preferably lowercase. Hiragana, katakana and probably all kanji can also be used.

可以使用重音字母,但最好使用小写字母。 平假名,片假名和可能的所有汉字也可以使用。

Other than that, neither the Java compiler nor the integrated development environments (IDEs) give much guidance as to how to name packages.

除此之外,Java编译器和集成开发环境(IDE)都没有提供有关如何命名包的大量指导。

It didn’t take programmers long to see that between the JDK, their own packages and third-party libraries, package naming conflicts were very likely to happen.

不久之后,程序员就发现JDK,他们自己的程序包和第三方库之间很可能发生程序包命名冲突。

In the example project described above, we might want to have a postal package for the PostalCode class and related interfaces and classes, and a gps package for the classes dealing specifically with GPS.

在上面描述的示例项目中,我们可能希望为PostalCode类以及相关的接口和类提供一个postal包,并为专门处理GPS的类提供一个gps包。

I doubt either of these would cause a package naming clash today, but, in the early days of Java, I would not have been able to say that with any certainty.

我怀疑上述任何一种都会导致今天的软件包命名冲突,但是,在Java的早期,我无法确定地说出这一点。

I don’t know who came up with using reverse domain names to start off package names, but now it’s practically an informal standard. It was endorsed by Sun and now it’s endorsed by Oracle.

我不知道是谁提出使用反向域名来开始使用软件包名称,但是现在这实际上是一个非正式标准。 它得到了Sun的认可,现在又得到了Oracle的认可。

What we do is that we take our domain name and reverse it. First “com.” or “org.” or whatever the top level domain is, then our domain name, then a dot and then the pertinent package name.

我们要做的是获取域名并将其反向。 第一“ com. ”或“ org. ”或其他顶级域名,然后是我们的域名,然后是一个点,然后是相关的软件包名称。

So Google probably uses “com.google.*,” Microsoft definitely uses “com.microsoft.*,” and 1-800-flowers.com can use something like “com._1_800_flowers.”

因此Google可能会使用“ com.google.* ”,微软肯定会使用“ com.microsoft.* ”,并且1-800-flowers.com可以使用类似“ com._1_800_flowers ”的com._1_800_flowers

For example, let’s say that we work for Example Corporation LLC and our domain name is example.com. Then we would start all of our package names with “com.example.

例如,假设我们为Example Corporation LLC工作,我们的域名为example.com 。 然后,我们将以“ com.example. ”开头所有包名称com.example.

So, our postal package would be com.example.postal and our GPS package would be com.example.gps.

因此,我们的邮政包裹将为com.example.postal而我们的GPS包裹将为com.example.gps

In the old days of Visual J++ (Microsoft’s early take on Java), Microsoft might have had a com.microsoft.visualjpp package (plus signs are not allowed in package names). Now I can tell you for sure that they have a com.microsoft.azure package.

在Visual J ++的早期(Microsoft早期使用Java)中,Microsoft可能有com.microsoft.visualjpp程序包(程序包名称中不允许加号)。 现在,我可以肯定地告诉您它们具有com.microsoft.azure程序包。

Suppose our Example Corporation also has an Azure product, distinct enough from Microsoft’s Azure to merit its own separate trademark, despite stern warnings from Microsoft’s lawyers.

假设我们的示例公司也有一个Azure产品,与Microsoft的Azure截然不同,尽管微软律师严厉警告,但也值得拥有自己的商标。

With reverse domain name package naming, this presents no problem: our Azure is in a package called com.example.azure and theirs is in a package called com.microsoft.azure.

使用反向域名程序包命名,这不会出现问题:我们的Azure在一个名为com.example.azure的程序包中,而他们的Azure在一个名为com.microsoft.azure的程序包中。

As long as the classes in these two packages have different names, there would be no clash whatsoever. A class in another package could easily import from both com.example.azure and com.microsoft.azure.

只要这两个包中的类具有不同的名称,就不会发生冲突。 另一个包中的类可以轻松地从com.example.azurecom.microsoft.azure导入。

JUnit is a good example of a *.org domain. JUnit 4 is in the org.junit package and JUnit 5 is in the org.junit.jupiter package. Theoretically, you could use JUnit 4 and JUnit 5 simultaneously, though I don’t think there’s much practical need for that aside from gradual migration.

JUnit是* .org域的一个很好的例子。 JUnit 4位于org.junit包中,而JUnit 5位于org.junit.jupiter包中。 从理论上讲,您可以同时使用JUnit 4和JUnit 5,尽管我认为除了逐步迁移外,没有太多实际需要。

Since JUnit feels almost like a standard part of Java, the JUnit team could probably use the “junit” package name (without the “org.” part) without clashing with anything else. It might be an option for JUnit 6.

由于JUnit几乎感觉像Java的标准部分,因此JUnit团队可以使用“ junit ”程序包名称(不包含“ org. ”部分),而不会发生任何其他冲突。 它可能是JUnit 6的一个选项。

Our “postal” and “gps” package names, without the “com.example.” part, are perhaps much likelier to clash with other packages we might need to use than “junit” if reverse domain package naming wasn’t so prevalent.

我们的“ postal ”和“ gps ”软件包名称,不含“ com.example. ”部分,如果反向域软件包命名不是那么普遍,那么与“ junit ”相比,可能更可能与我们可能需要使用的其他软件包发生冲突。

It’s all well and good to have globally unique package names, but, except in the simplest projects, it’s not good to have one package for all of the classes and interfaces you write. Even if you’re not at a big company like Microsoft.

具有全局唯一的包名称是一件好事,但是,除了在最简单的项目中,对于您编写的所有类和接口都只有一个包是不好的。 即使您不是像Microsoft这样的大公司。

But how do you decide how to split up your packages? This is where the single responsibility principle comes in. The single responsibility of a package is to group together classes and interfaces that each have their own single responsibilities that are reasonably similar.

但是,您如何决定如何拆分包裹? 这就是引入单一责任原则的地方。包的单一责任是将类和接口组合在一起,每个类和接口都有各自的合理相似的单一责任。

So the single responsibility of our com.example.postal package is to group together classes and interfaces directly pertaining to mailing letters and packages, while the single responsibility of our com.example.gps package is to group together classes and interfaces directly pertaining to GPS.

因此, com.example.postal包的唯一职责是将与邮寄信件和包裹直接相关的类和接口分组在一起,而com.example.gps包的唯一责任是将与GPS直接相关的类和接口分组在一起。

Packages can be thought to contain other packages. For example, java.util, which contains very useful classes like ArrayList, HashMap and TreeSet, can be thought to also contain the java.util.concurrent package, and a few other packages.

包可以被认为包含其他包。 例如, java.util包含非常有用的类,例如ArrayListHashMapTreeSet ,可以认为还包含java.util.concurrent包和其他一些包。

And in turn the java.util.concurrent package can be thought to contain the packages java.util.concurrent.atomic and java.util.concurrent.locks.

反过来,可以认为java.util.concurrent包包含java.util.concurrent.atomicjava.util.concurrent.locks包。

The java.util.concurrent package contains classes and interfaces that pertain to concurrent programming, and the sub-packages that it can be thought to contain deal with more granular aspects of concurrency.

java.util.concurrent包包含与并发编程相关的类和接口,并且可以认为其中包含的子包可以处理更精细的并发方面。

However, the Java compiler does not hold this view of packages containing other packages, and neither does the Java runtime. Nor does either one of those require the necessary files to be in any particularly named folder, as long as the necessary file locations are “in the classpath.”

但是,Java编译器不包含包含其他软件包的软件包的此视图,Java运行时也没有。 只要必要的文件位置在“类路径”中,这些文件中的任何一个都不需要将必要的文件放在任何特别命名的文件夹中。

So java.util and java.util.concurrent, for example, are two distinct packages, and if an interface or class from one package needs to refer to something from the other package, the programmer must either write an Import statement or use the “fully qualified” name of the necessary item.

因此,例如java.utiljava.util.concurrent是两个不同的程序包,并且如果一个程序包中的接口或类需要引用另一程序包中的内容,则程序员必须编写Import语句或使用“完全必要的名称”。

For example, in java.util.concurrent.atomic, there is the abstract class AtomicIntegerFieldUpdater<T>, which imports Objects from java.util just to use it once in a private function to check whether two classes come from the same package.

例如,在java.util.concurrent.atomic ,有一个抽象类AtomicIntegerFieldUpdater<T> ,该类从java.util导入Objects ,仅在私有函数中使用它一次,以检查两个类是否来自同一包。

This also means that a “java.util.*” Import does not bring in anything at all fromjava.util.concurrent, a separate Import statement is needed.

这也意味着“ java.util.* ”导入根本不会从java.util.concurrent引入任何内容,需要单独的Import语句。

For the most part, however, it is convenient for us to visualize package containment, and the project overview in IntelliJ reinforces this visualization, showing us packages as if they were nested folders.

但是,在大多数情况下,这对我们来说很方便地可视化软件包的包含,而IntelliJ中的项目概述加强了这种可视化,向我们显示了软件包就像是嵌套文件夹一样。

Example of a project overview in IntelliJ IDEA.
Example of a project overview in IntelliJ IDEA.
IntelliJ IDEA中的项目概述示例。

This screenshot actually shows a Scala project, but it makes my point for Java projects just the same.

该屏幕截图实际上显示了一个Scala项目,但对于Java项目,我的观点也是如此。

The source for ElectronicsItem is in src\retail\items\electronics (if we’re working on this under Windows), and likewise the bytecode file, the source for ElectronicsItemTest and its corresponding bytecode file are at different but very similar paths.

ElectronicsItem的源位于src \ retail \ items \ electronics(如果我们在Windows下进行此工作),同样,字节码文件, ElectronicsItemTest的源及其对应的字节码文件位于不同但非常相似的路径中。

Occasionally NetBeans will show a similar nesting, but usually it does not.

有时NetBeans会显示类似的嵌套,但通常不会。

Example of NetBeans project overview
Example of NetBeans project overview
NetBeans项目概述示例

Although NetBeans makes a folder structure much like IntelliJ’s, in its project overview it shows us something closer to the way that the Java compiler and the runtime see these packages.

尽管NetBeans的文件夹结构与IntelliJ非常相似,但在项目概述中,它向我们展示了更接近Java编译器和运行时查看这些软件包的方式。

As you can see from the screenshots, both NetBeans and IntelliJ segregate Source Packages and Test Packages. And so does Eclipse, with some prodding. This makes it easy to separate what goes into a production release or deployment from the tests, which are only needed in a development context.

从屏幕截图中可以看到,NetBeans和IntelliJ都将源程序包和测试程序包分开。 Eclipse也是如此,但有一些建议。 这样可以轻松地将生产版本或部署中的内容与测试分开,这仅在开发环境中才需要。

When running the tests, these IDEs take care of putting all the relevant folders in the classpath, so that by the time the necessary classes are loaded by the Java Virtual Machine (JVM), it doesn’t matter where the files came from.

在运行测试时,这些IDE负责将所有相关文件夹放在类路径中,以便在Java虚拟机(JVM)加载必要的类时,文件的来源无关紧要。

For example, when running the tests, it doesn’t matter to the JVM that ElectronicsItem is in src\retail\items\electronics and ElectronicsItemTest is in test\retail\items\electronics, it only matters that they’re both in the retail.items.electronics package.

例如,在运行测试时,对于JVM来说, ElectronicsItem位于src \ retail \ items \ electronics中,而ElectronicsItemTest位于test \ retail \ items \ electronics中无关紧要,只要它们都在retail.items.electronics软件包。

Although someone working on a JDK could very well place all the files in a single directory named by an irrelevant or nonsense word, it makes much more sense to organize the files in a directory structure that reflects the convenient fiction of nested packages.

尽管使用JDK的人可以将所有文件很好地放在一个不相关或无用的单词命名的目录中,但将文件组织成反映嵌套包的方便用法的目录结构更为有意义。

For example, the source for AtomicIntegerFieldUpdater<T> could quite sensibly be placed in src\java\util\concurrent\atomic, to give a Windows example of this.

例如,可以很合理地将AtomicIntegerFieldUpdater<T>的源放置在src \ java \ util \ concurrent \ atomic中,以给出Windows的示例。

So, just as neither the compiler nor the runtime sees java.util as containing java.util.concurrent, they don’t see java as containing java.util, and in fact there’s no java package at all.

因此,就像编译器和运行时都没有将java.util视为包含java.util.concurrent ,他们也没有将java视为包含java.util ,并且实际上根本没有java包。

Nor is there generally a com or org package, even if the project has two or more package names starting with “com.” or “org.,” as far as the compiler and the runtime are concerned.

即使项目有两个或多个以com.开头的软件包名称,通常也不会提供comorg软件包com. ”或“ org. ”,就编译器和运行时而言。

But a strict interpretation of the dots in the package name as indicating separate folder levels would mean a com folder or an org folder in your computer’s file system.

但是,如果将软件包名称中的点严格解释为表示单独的文件夹级别,则意味着计算机文件系统中的com文件夹或org文件夹。

And how do you define the single responsibility of a com or org folder in a worthwhile and meaningful way?

以及如何以有意义和有意义的方式定义com或org文件夹的单一职责?

For example, it does not really matter to the Java compiler nor to the Java runtime whether or not the Example Corporation provided the initial endowment for the Example Foundation (the domain name of the latter being, hypothetically, example.org).

例如,对于示例编译器是否提供了示例基金会的初始捐赠(假设后者的域名假设为example.org ),对于Java编译器或Java运行时都没有关系。

Maybe there’s a way to define this distinction meaningfully for the purposes of programming for the JVM, but I think it’s far more important to properly partition the packages under your domain.

也许有一种方法可以有意义地定义这种区别,以便为JVM进行编程,但是我认为在您的域下正确地划分软件包更为重要。

And the JDK itself is a generally good example of how to do that according to the single responsibility principle, and so is JUnit.

而且,JDK本身是按照单一职责原则执行此操作的一个很好的示例,JUnit也是如此。

The java.util package, however, is actually not the best example of the single responsibility principle. It is actually a hodgepodge of very useful interfaces and classes that we now see should’ve been placed in three or four different packages in the early days of Java.

但是, java.util包实际上不是单一职责原则的最佳示例。 实际上,它是一个非常有用的接口和类的杂物箱,我们现在看到,在Java的早期,它们应该放在三个或四个不同的程序包中。

Besides classes like ArrayList, HashMap and TreeSet, the java.util package also includes classes like Currency and Locale, which are only tenuously related to the data structure classes.

除了ArrayListHashMapTreeSet类的类之外, java.util包还包括CurrencyLocale类的类,它们仅与数据结构类紧密相关。

It would have made more sense to put the various list, map and set classes and interfaces in a package called java.collections or java.datastructures. In fact, the Scala equivalents to the Java collections are in a package quite appropriately named scala.collections.mutable in the Scala software development kit.

将各种列表,映射以及设置类和接口放在名为java.collectionsjava.datastructures的包中会java.collections java.datastructures 。 实际上,与Java集合等效的Scala在Scala软件开发工具包中的一个相当恰当的名称为scala.collections.mutable的程序包中。

Thus the single responsibility of the scala.collections.mutable package is to hold together classes and traits (interfaces) for mutable collections. The single responsibility of the scala.collections.immutable package can be described quite similarly.

因此, scala.collections.mutable包的唯一职责是将可变集合的类和特征(接口)保持在一起。 scala.collections.immutable包的单一职责可以非常相似地描述。

And we can describe the single responsibility of the scala.collections package as holding together classes and traits for collections.

我们可以将scala.collections包的单一职责描述为将集合的类和特征组合在一起。

Although some classes have been moved around in the JDK (e.g., SecureRandom used to be in javax.crypto but now it’s in java.security), I seriously doubt anyone would want to move ArrayList out of java.util; such a change would break many existing programs and libraries.

尽管在JDK中已经移动了一些类(例如, SecureRandom以前在javax.crypto但现在在java.security ),但我严重怀疑有人会想将ArrayListjava.util移出; 这样的更改将破坏许多现有程序和库。

Moving a class or interface to a different source package is quite easy in an IDE. In NetBeans, for example, you can just edit the package declaration, then NetBeans will offer to move the class or interface to the correct package, along the way taking care of editing the Imports and moving the source file and the bytecode file to the appropriate folder.

在IDE中,将类或接口移动到其他源包非常容易。 例如,在NetBeans中,您可以只编辑包声明,然后NetBeans将提供将类或接口移动到正确包的过程,同时还要注意编辑Imports并将源文件和字节码文件移动到适当的位置。夹。

However, you need to make the corresponding changes to the Test Packages in two or more separate steps, ultimately ending by removing Imports from the same package.

但是,您需要在两个或多个单独的步骤中对测试包进行相应的更改,最终要从同一包中删除导入。

Java 9 added modules, which are like super-packages. The idea of modules is that they are supposed to make it easier to break up a large system into independent components for stand-alone public distribution.

Java 9添加了模块,就像超级包一样。 模块的思想是使它们更容易将大型系统分解为独立的组件,以进行独立的公共发行。

However, it seems that most professional Java programmers are still using Java 8, and that beginners who are starting out with the most recent version of Java (as of this writing Java 14; Java 15 is due out next month) are not learning about packages, much less modules.

但是,似乎大多数专业的Java程序员仍在使用Java 8,而开始使用最新版本的Java(撰写本文时为Java 14; Java 15将于下个月发布)的初学者尚未了解软件包。 ,更少的模块。

Though to be fair, it would be information overload to expect an absolute beginner to declare both a module and a package for a simple Hello World at the beginning of the course.

公平地说,期望一个绝对的初学者在课程开始时同时声明一个简单的Hello World的模块和程序包将使信息过载。

So the typical Hello World program is given without either a package declaration or a module declaration. Then, in Java 8 or earlier, the HelloWorld class is understood to be in the default unnamed package, and in Java 9 or later it is also understood to be in the default unnamed module.

因此,给出的典型Hello World程序没有包声明或模块声明。 然后,在Java 8或更早版本中, HelloWorld类应理解为位于默认的未命名包中,而在Java 9或更高版本中,它也可以理解为在默认的未命名模块中。

This enables backwards compatibility for programs and libraries that have not been updated to use the Java 9 module system.

这样可以向后兼容尚未更新为使用Java 9模块系统的程序和库。

This means that you can use a library written for Java 8 or earlier in a project for Java 9 or later without the compiler bothering you with the fact that the library doesn’t declare any modules.

这意味着您可以在Java 9或更高版本的项目中使用为Java 8或更早版本编写的库,而编译器不会因为该库未声明任何模块而困扰您。

And hopefully those classes that get placed in the default unnamed module don’t also get placed in the default unnamed package, because hopefully the programmer knew better than that.

并希望将那些放置在默认未命名模块中的类也不要放置在默认未命名包中,因为希望程序员对此有所了解。

Technically, a package can contain a lot more classes and interfaces than there is any practical need for, hundreds if not thousands.

从技术上讲,一个包可以包含比实际需要更多的类和接口,数百甚至不是数千。

As a very rough guideline, a source package should not contain more than three or four interfaces or abstract classes, and no more than twelve classes and interfaces total (enumerated types are just classes that extend the Enum<E> abstract class, as far as the JVM is concerned).

作为一个非常粗糙的准则,源包不应包含多于三个或四个接口或抽象类,和不超过12级的类和接口合计(枚举类型是扩展的只是类Enum<E>抽象类, 只要有关JVM的信息 )。

This rough guideline is not meant to be taken literally. When a package seems to be too large, the decision to break it up into smaller packages should be based on an understanding of the single responsibilities of the constituent classes, not an effort to get below some arbitrary threshold.

这个粗略的指导原则并不是从字面上理解的。 当一揽子计划似乎太大时,决定将其拆分为较小的计划,应基于对组成类的单一职责的理解,而不是努力低于某个任意阈值。

Maybe a more helpful guideline would be that if you can’t honestly describe a source package using specific terms, but without using the word “and,” then it needs to be split up. For example:

也许更有用的准则是,如果您不能诚实地使用特定术语来描述源程序包,而没有使用“和”一词,则需要对其进行拆分。 例如:

TOO VAGUE: The com.example.location package consists of classes that represent locations.

太多提示: com.example.location包由代表位置的类组成。

BETTER: The com.example.location package consists of classes that represent mailing addresses and GPS coordinates.

更好: com.example.location包由代表邮件地址和GPS坐标的类组成。

The use of the word “and” in the better description suggests that maybe thecom.example.location package should be broken up into the smaller com.example.location.postal and com.example.location.gps packages.

在更好的描述中,单词“和”的使用表明com.example.location程序包应分解为较小的com.example.location.postalcom.example.location.gps程序包。

The single responsibility of a test package is quite obvious: to test the classes in the correspondingly named source package. For example, com.example.gps in test\com\example\gps tests the classes of com.example.gps in src\com\example\gps.

测试包的单一职责非常明显:测试相应命名的源包中的类。 例如, com.example.gps在测试\ COM \示例\ GPS测试的类com.example.gps在SRC \ COM \示例\ GPS。

With that in mind, it is acceptable for a test package to have more files than the corresponding source package (e.g., the source package has eight classes but the test package has ten classes).

考虑到这一点,测试包比相应的源包具有更多的文件是可以接受的(例如,源包具有八个类,而测试包具有十个类)。

But if you don’t like that being the case, but need certain additional classes to test a class (such as an implementation of an abstract class or interface), you can probably use nested classes.

但是,如果您不喜欢这种情况,但是需要某些其他类来测试类(例如抽象类或接口的实现),则可以使用嵌套类。

翻译自: https://medium.com/swlh/java-packages-and-the-single-responsibility-principle-a23e151719d1

java单一原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值