digitalmars.D - On packages and naming them
- Bill Baxter (65/65) May 14 2008 This was going to be a proposal, but then I realized that D actually
- terranium (3/6) May 15 2008 One more option:
- Yigal Chripun (28/36) May 15 2008 I'll also add something I read in this NG in the past about python's
- terranium (2/7) May 22 2008 Who cares whether private symbols are imported or not? What can this aff...
- Robert Fraser (8/17) May 22 2008 You can't have multiply-defined symbols, even if some of them are
This was going to be a proposal, but then I realized that D actually already has a nice way to deal with the issue. So consider this an essay about how to use packages effectively in D. Hopefully someone will find it informative. Problem: D code tends to work best when placed in a package [1], but a good package name is not always obvious. I observe a few of strategies in use: [Strategy 1] Just use a generic name like "utils" or "tools". This makes the D compiler happy, but only until someone else decides to name their package the same thing. [Strategy 2] Just use a random made-up name, like "cashew", "schooner", "tango", or "derelict". This is fine except these packages often become huge, containing lots of disparate libraries and no one user is likely to want them all. For instance a dev might want cashew.utils.Array but couldn't care less about cashew.cgi.*. The granularity is bad. You end up with a lib that is a monolithic assortment of eclectic rubbish. [Stragegy 3] (from Java) Put modules inside net-derived package names like "com.sun.java". That eliminates clashes but it's just ugly. Chances are there's only going to be *one* SWT out there, so saying "org.eclipse.swt" every time you import an SWT module is a little tedious. And sometimes affiliations change, companies get acquired, or you're just a hobby dev and don't actually *have* your own domain name to use. [Strategy 4] For an individual developer, use your initials or some form of your name. This is ok if you intend to make this project "yours" forever, but if you're starting an open source project, I think putting any form of your own name on it is a bad practice. It discourages others from joining the project. Plus it has similarities to Strategy 2, in that your name has nothing to do with the contents of the package, so the contents will end up being a random grab-bag. POSSIBLE REMEDIES: Here I was about to propose a few new ways to handle this, but realized that one of my proposals is actually possible, and indeed already in use. So I'll just point out the solution: The idea is just to split a single package across multiple locations. This is actually possible now, and is in fact used by Derelict to organize its various sub-projects. So this means you can happily use a random-name package (Strategy 2) for everything you do without forcing everyone who uses one part of that package to download/install all of it. If you use dsss for building/distribution you need to specify different names for the different components, but it's straightforward, just see derelict/DerelictAL/dsss.conf for instance. (http://www.dsource.org/projects/derelict/browser/trunk/DerelictAL/dsss.conf) Still I think maybe D and supporting tools could do more to support this very nice paradigm. For instance the Derelict source tree is kind of a mess because all the separate sub-libraries are in sub-directories. So there is much redundancy in the directory layout: derelictFoo/derelict/foo/Foo.d, derelictBar/derelict/bar/Bar.d It would be nicer if the derelict source tree could just be under a single top-level derelict/ directory. There are probably issues with SVN involved there too in the decision to organize that way. So I'm not sure what could be done to make that easier. However there is one thing that I think D could do to make using pacakges easier, and that is Package aliases But I think I'll put it in a separate message because it switches gears from an essay on how to do things now, to a proposal for a change. [1] As an example I recently ran into a conflict where my module called just "memory" clashed with a module in Tango called "tango.something.something.memory". So a package-less module can clash even with a deeply nested module in a package. There are troubles with installation, too, (with DSSS) since all package-less modules are copied to the same DSSS include directory. --bb
May 14 2008
Bill Baxter Wrote:[Strategy 1] Just use a generic name like "utils" or "tools". This makes the D compiler happy, but only until someone else decides to name their package the same thing.One more option: import projectname.all;
May 15 2008
terranium wrote:Bill Baxter Wrote:I'll also add something I read in this NG in the past about python's package system: you can define a file called __this__.py with imports. this is a reserved python symbol so you cannot import it directly. the idea is that you can write import package.subpackage; //replace with the python syntax for this and since you asked for a package and not a module, the compiler will rewrite it to mean: import package.subpackage.__this__; in the D version this would mean to define a special this.d file for packages. also, in the exciting D system it can be done in tango as well due to the naming convention: tango packages are all lowercase, while modules are CamelCase. this mean you can use the following: import package.subpackage.Module; import package.Subpackage; this works because d is case sensitive. so even if you try this on windows (where FSs are case insensitive) it will work cause the compiler will recognize them as different symbols, and will know to look for the right file in the file system. at least, this is what I read in the NG. I prefer something in this line more than .all since .all implies the D equivalent of import stuff.*; in Java. the two approaches above can be used when you want to import some sort of Public API (user defined) instead of all the symbols (including the internal ones)[Strategy 1] Just use a generic name like "utils" or "tools". This makes the D compiler happy, but only until someone else decides to name their package the same thing.One more option: import projectname.all;
May 15 2008
Yigal Chripun Wrote:I prefer something in this line more than .all since .all implies the D equivalent of import stuff.*; in Java. the two approaches above can be used when you want to import some sort of Public API (user defined) instead of all the symbols (including the internal ones)Who cares whether private symbols are imported or not? What can this affect?
May 22 2008
terranium wrote:Yigal Chripun Wrote:You can't have multiply-defined symbols, even if some of them are private. i.e. I have a 3-module program. I want two of the modules to work independently but want to use the alias "string" in all 3 modules if it hasn't been defined. No way to do this -- the two modules that need to be independent would define "string" separately, and the module that import them both fails to compile, even when the alias is private in one or both of them.I prefer something in this line more than .all since .all implies the D equivalent of import stuff.*; in Java. the two approaches above can be used when you want to import some sort of Public API (user defined) instead of all the symbols (including the internal ones)Who cares whether private symbols are imported or not? What can this affect?
May 22 2008