Original address: http://www.cnblogs.com/lidabo/archive/2012/12/15/2819865.html
Package vs. Namespace
We know that reusability (reusebility) is a very important goal in software engineering. Reuse, not only refers to the software (code, components, etc.) can be reused, more generalized reuse refers to different people, different teams, different companies can use each other's results. In addition, for large software, it is often developed by multiple teams, which are likely to be distributed across different cities, regions, and even countries. For these reasons, name management has become a very important factor.
Since the C language itself does not provide a mechanism for naming management (the static name of the C language solves the problem of visibility, these names are not exported to the outside, but the namespace we are discussing is not exactly the same as the problem), in order to solve the problem of name conflict, we generally choose to prefix the method, and the prefix rule is often : ${project Name}_${name}; More secure naming rules divide the prefixes by more levels: ${project name}_${module Name}_${name}.
This kind of scheme has a lot of similar examples in real life. For example: Many cities in China have Riverside, if you talk to the object of the city you are referring to, you just need to say the riverside, everyone will understand what you mean. But if this is not the case, you need to add a prefix, indicating whether this is the riverside of Leshan, or the riverside of Chengdu. This is most straightforward when you mail a letter.
Therefore, if there is a global management, this scheme of C language should be very effective. But its flaw is that it may cause a very long name, and every time you quote a name you must give the full name.
This is a very troublesome thing. You might as well imagine that you are talking about the Leshan Riverside, but you have to talk about it every time, you have to say "Leshan, Sichuan Province, China", you will be how painful.
In order to solve this kind of problem, and give an effective management plan. Subsequent programming languages, both C++,java and C #, provide their own name-management mechanisms. These schemes have their own unified thinking in essence, but there are some differences in the way of operation.
In the previous C language scheme, it embodies the way of hierarchical management. Hierarchical management is a very natural and effective means. For example, the domain name of the Internet. It guarantees the global uniqueness of a name by hierarchical naming, which is arranged from small to large (this is both because of Western writing habits and also for convenience.) In fact, from this point, we can find that if a person's pre-reading habits from left to right, from small to large arrangement is very convenient to save time, such as "Riverside, Leshan, Sichuan Province, China." We can skip or ignore the following information as we know what we mean from the information on the left. The large-to-small arrangement avoids errors, as we first understand the constraints, and when we finally read the Riverfront road, we have identified what we mean. We can add a name to the front and specify a smaller range. For example: Wsd.wmsg.sps.motorola.com indicates that this is the WSD group of the WMSG Department of Motorola's SPS department.
Java uses this approach to name packages, but instead writes them in the opposite way. This approach can be very effective to ensure the unification of the name. Like what The MMI module package for a project named Mlca can be named: Com.motorola.sps.wmsg.wsd.mlca.mmi, and its engine module package can be named: Com.motorola.sps.wmsg.wsd.mlca.engine.
This way, when the code between different teams and companies is put together for use, we simply need to use it in a case where the name does not conflict. When a conflict is caused, we specify its full name. For example, two of these packages have a class named message, and if one of our other packages uses both, we need to indicate which package it comes from when referencing the message class. As follows:
Import Com.motorola.sps.wmsg.wsd.mlca.mmi;
Import Com.motorola.sps.wmsg.wsd.mlca.engine;
We need to specify which package the class message comes from.
public class Foo extends Com.motorola.sps.wmsg.mlca.mlca.mmi.Message {
...
}
C + + and C # provide the namespace concept to support this approach. You can specify your own namespace in a global space, and then you can create a smaller range of namespace within a namespace. Although C + + and C # itself do not recommend any namespace naming methods (in fact, the way the anti-domain name is Java recommended, not mandatory), but we can also use the above method. For example, the following C # code:
Namespace Com.motorola.sps.wmsg.wsd.mlca.mmi
{
MMI Stuff
...
}
Namespace Com.motorola.sps.wmsg.wsd.mlca.engine
{
Engine Stuff
...
}
When we use these two modules at the same time, if there is a name conflict, it may be indicated by specifying namespace. Like what:
Class Foo:com.motorola.sps.wmsg.wsd.mlca.mmi.Message
{
...
}
The Java package itself does not have the concept of a child bag, and all packages are side-by-side, with no one who has the problem. For example: There is absolutely no packet-to-child relationship between Org.dominoo.action and ORG.DOMINOO.ACTION.ASL. They are separate packages, each with their own set of class/interface. In a Java file in Org.dominoo.action.asl, if you want to refer to a class/interface in org.dominoo.action, you must import org.dominoo.action.
c++/c# namespace scheme is not, a namespace can have their own sub-namespace, we might as well call namespace also called the package, then there may be c++/c# between packages and sub-package relationship. Like what:
Namespace Org.dominoo
{
Namespace action
{
Namespace ASL
{
....
}
}
namespace constraint
{
Namespace OCL
{
....
}
}
}
In this example, both the action and the constraint are Org.dominoo sub-packages, and they each have their own child package ASL and OCL.
Therefore, for a global namespace, the C language cannot be directly separated from the namespace, while Java can separate namespaces from the global namespace, but c++/c# can further separate the namespaces further. Such as:
|------------------|
| Global Namespace |
| |
| |
| |
|------------------|
C language
|-------------------|
| Global Namespace |
| |
| |---| |---| |---| |
| | A | | B | | C | |
| |---| |---| |---| |
|-------------------|
Java language
|----------------------------|
| Global Namespace |
| |
| |-------------| |--------| |
| | A | | B | |
| | |---| |---| | | |---| | |
| | | C | | D | | | | E | | |
| | |---| |---| | | |---| | |
| |-------------| |--------| |
|----------------------------|
c++/c# language
Therefore, the Java package scheme only divides the global namespace once, essentially just provides a naming prefix scheme for the language, but only through the hierarchical management of the naming prefix to guarantee the uniqueness of the name. Its only function is to avoid name collisions.
C++/c#, however, provides the ability to re-partition any space. Between Org.dominoo and ORG.DOMINOO.ASL in Java are separate packages that do not contain relationships at all, but in c++/c#, DOMINOO.ASL is and is obviously a sub-package of Dominoo.
In fact, if a complex scheme like c++/c# is not necessary just to avoid naming conflicts, Java's solution is sufficient. But c++/c# such a scheme can bring other conveniences:
1, the essence of software development is the top-down decomposition, each layer has its own definition, and this definition can be used as the next layer of all subsystems of the public service, multi-level tree structure in line with this logic. The c++/c# scheme satisfies this partitioning relationship in the most natural way. In fact, the idea of such a scheme and document management is the same.
2. Once a program uses which namespace, it can access its sub-packages through it without pointing out the full path. For example, in the above diagram, if a program writes a using namespace a, it only needs to write C::foo when it accesses Class Foo in package C, instead of writing the full path:: A::c::foo. In Java, because A,c is a side-by-side relationship, in order to access the contents of C, you must explicitly point to import c. Then, in the case of a name collision that accesses Foo, you must indicate the full path.
3. When the program is in a package, the definition in the outer package can be accessed directly without creating a name conflict. Since Java packages have only one layer in the hierarchy, Java can only access the definitions in global namespace directly, and any definitions in other packages must be accessible through import.
There is no doubt that C++/c# 's approach is more powerful and flexible, but more complex. and complex things often make it easier for users to make mistakes. If you are inferior, judge yourself.
The "package" in Java and the "Namespaces in C #"