Tim Jansen's blog


2004/01/17
Categorizing Classes without Namespaces or Packages
Categorizing Classes without Namespaces or Packages This time it started with a a thread on kde-core-devel: I wrote about using classes for organizing functions and later wondered why I am using static class methods - that’s what C++ has namespaces for. I think the answer lies somewhere between the way I am using namespaces and the way tools like Doxygen organize the documentation. I am using namespaces in a Java-package-like way. They are a coarse categorization for classes, with 5-50 classes per namespace. That’s what I am used to from Java, and it makes a lot of sense for classes. It would be possible to collect functions in namespaces instead of classes, but then you would have to browse through both the classes and the namespaces in Doxygen-generated documentation. Having two kinds of categorization is just too much, it makes documentation too hard to read and code too hard to find. The C++ syntax does not really help you with organizing your code or reading other people’s code, especially if you are not using an IDE. It’s hard to find out in which file a symbol is declared, and even more difficult to find out where it is implemented. Functions and global variables are the worst, unlike classes they usually do not have their own header. Avoiding these problems requires quite a lot of discipline, you need to keep a consistent naming scheme for all files. This does not help when you work with someone else’s sources though. Another part of C++ that I don’t like is the separation of declarations/headers and implementation. I hate typing more than necessary, syncing headers with the implementation can be annoying and the stupid #ifdef protectors that you need to write in every header are just braindead. Two features in Java that work really well are packages and the source file layout. When you have a class My.Library.Helper you are required to write both implementation and declaration into a file My/Library/Helper.java. This makes it easy to locate the implementation. As everything in Java is in a class there are no problems with locating functions. They are static methods and can only be invoked by specifying the class name (e.g. Math.round()). This is annoying to type, but makes reading someone else’s source code much easier. Unfortunately Sun recommends to use a reverse DNS name as package name, and when you follow it you will have to hide your source code somewhere in a deep directory hierarchy. Unless you are writing a library I would suggest you to ignore Sun’s advice and use a short one-step package name. Java 1.5 shows that Sun recently got hit by a healthy dose of reality, and one of the results are ’static imports’. If you declare static import java.lang.Math; you do not need to write Math.cos() any longer, you can just write cos(). This makes it a little bit more difficult to find the method’s declaration (you need to look out for static imports), but I can understand Sun’s decision. The lack of static imports caused people to do strange things, many people inherited from classes that contained useful static methods only to avoid writing the class prefix for every invocation… it’s a nice compromise between the ease of use of C++’s uncategorized function, and Java’s “everything is a class method"‘ principle. To make it short, I would choose Java’s package system over C++’s header/namespace system any time. But when I thought about it I came to an interesting question: why does Java differentiate between packages and classes? A class with the full path My.Library.Helper could be a class Helper in the package My.Library, or a class Library.Helper in the package My. Inner/sub classes and packages use the same naming scheme, they are identical for the API’s user, so why should there be a difference in the declaration? Isn’t is possible to have only one? I think that with a few tweaks you can get rid of the package mechanism and make everything a class. There are three small problems to be solved: The first problem is how to define a class My.Library.Helper. The traditional Java syntax would be
class My {
	class Library {
		class Helper {
		}
	}
}
But that would be annoying to type (even if not annoying enough to stop the C++ guys to use a similar syntax for namespaces..). So just do the obvious and create an alternative syntax that lets the developer specify the full class name, like C# does:
class My.Library.Helper {
}
Problem one solved. The second issue is that Java allows only one “class Name {}” declaration to specify a class. You can’t do this when the class mechanism is also used for categorization purposes, as you don’t want to specify all sub-classes in a single file. Thus you need to allow more than one declaration for a class, and the compiler needs to merge them like C#’s ‘partial’ class attribute does. This requires that the source file naming scheme needs to be changed: a class with the name My.Library.Helper can be defined in all files that have either the name My/Library/Helper.java or My/Library/Helper/*.java. If a class is a regular class a developer will choose the former scheme. When the class is used like a package, containing only sub-classes, the latter file scheme is used. In some cases it may also make sense to have both. Both schemes allow developer and compiler to easily find all declarations of a class, and certainly not more difficult than with Java’s current package/inner-class mix. Problem two solved. Problem three are imports. So far Java allowed you to import either a single class (’import My.Library.Helper’) or to import a whole package (’import My.Library.*’). Exactly the same syntax can be kept for sub-classes. A simple name imports a single class, an appended ‘*’ imports all sub-classes. Problem three solved. To make it short, there should be no need for packages or namespaces. With a few small changes in the language the class is sufficient as a single way of organizing methods, variables and other classes.


 

This blog is my dumping ground for thoughts and ideas about Eek. Someday Eek will be a programming language and system, somewhat comparable to Java in scope. It is my attempt to bring sanity to the world of computing.
At least I hope so. Right now it is far from being finished and I can't guarantee that it ever will be. I am still working on the specification, but I won't release anything before I got my first prototype running. The world does not need more vapourware and unusable beta-software. All publicly available information about Eek is contained in this blog. You can find the latest summary here.
This page is powered by Blogger. Isn't yours? Creative Commons License
This work is licensed under a Creative Commons License.