Namespaces - Importing versus Explicit Naming (was Re: [Modules] Upper case message names for accessing modules])

Doug Way dway at riskmetrics.com
Wed Feb 20 06:53:28 UTC 2002


Henrik Gedenryd wrote:
> 
> Doug Way wrote:
> >
> > This would require that your module imports ("uses") the Morphic-Core-Basic
> > module.  I tend to think that this is probably the best practice of the
> > three... assuming there's some sort of reasonable UI for easily making modules
> > import other modules, etc, in as automated a fashion as possible.
> >
> > In fact, I'd go as far to say that I would always import modules (like example
> > 3) when writing code, and never use explicit paths in my code, the *only*
> > exception being when there's an actual class name clash in my imported
> > modules, and then of course I would need an explicit path in the code.  (I'd
> > be curious to hear other opinions on this, though.)
> 
> - Importing all names has many problems of its own, and indeed you still
> would need the ability to disambiguate somehow. But it is generally
> considered better practice to be explicit about where a name comes from,
> than to import a name. E.g. when creating Oberon, Wirth removed the ability
> to import names like you could in Modula-2.
> 
> But like I said above, what do you suggest instead?

I don't think there's necessarily a problem with the current situation... both importing and explicit naming is supported, which is good.

I am interested in the pros and cons of explicit naming versus importing names, though, and which would be considered better practice.  I'm not necessarily convinced that importing names is always better, but my experience (as a user, not an implementor) has been that it's mostly better.

(Are there any articles out there describing why explicit naming (vs. importing) might be considered better practice?  I tried to look up info on Google, and didn't come up with much, but this was sort of interesting, even though it's about XML namespaces:  http://lists.xml.org/archives/xml-dev/200009/msg00171.html )


Here's my list of pros and cons...

1. Advantages to always importing names (except for direct name clashes):

  a. Readability/Less Code.  With imported names, class names in source code appear as a single word (e.g. EllipseMorph).  With explicit naming you need either ~5 words (e.g. Squeak Morphic Core Basic EllipseMorph) plus the overhead of getting used to the upper-case message name convention, or ~10 words (e.g. (Module path: #(Squeak Morphic Core Basic) class: #EllipseMorph)).

  b. Refactoring.  You might reference EllipseMorph several times in your module, so you could have the same module name repeated several times in your source code, or have it appear just once in an import.  With importing, if the imported module name changes, you only need to change your code in one place.

  c. Code looks more like classic Smalltalk, which people are familiar with. (We should try not to be too obsessed with this factor, but it's a nice bonus.)

  d. It's probably easier to automatically determine prerequisite modules from import statements (or perhaps they are one and the same), than it is to determine them from looking for explicit module names in the source code.  Although this may not be a big deal.  (Hmm, need to look at exactly how this is currently handled.)

  e. Others?


2. Advantages to always using explicit path names in source code:

  a. Module name information could provide extra meaning in source code.  In some cases, it might help the readability of the source code to know which module a class is from.  E.g. when creating an EllipseMorph instance, it might be handy to know that it's from the Squeak-Morphic-Core-Basic module.  Hmm, bad example, that seems not very useful.  I'd say it's probably only very occasionally useful at best... the meaning of the class should really be in the class name anyway.

  b. Over time, unneeded crufty import statements can accumulate.  You might have required Squeak-Morphic-Core-Basic as a prerequisite to your module at one point, and after much rewriting, you no longer require it, but you still have the original import statement left.  (I realize "import statement" is probably not the right term.)  This should be solvable with good tools, though... a tool should be able to automatically remove name imports which aren't used.

  c. It's conceptually simpler to have only one way to deal with names (explicit naming) than to have two ways (importing and explicit naming), since with importing you may still (rarely) need explicit names.

  d. When new name clashes are introduced in newer versions of imported modules, they would have to be addressed, but they wouldn't be a problem with explicit naming.

  e. Others?


So, I guess I listed four advantages for each, so it might seem like a close call. :)  I consider #1a and #1b to be the most important issues, though, which is why I'd tend to favor namespace importing as a better practice.  #2a-b-c actually don't seem too important.  Problems like #2d are worth considering, though.

I suppose one advantage of using explicit names is that you wouldn't have to rely as much on tools to take care of things (like #2b).  But Smalltalk is good at tool support!

The problem of readability (#1a) might be reduced quite a bit if you had non-hierarchical namespaces. e.g. "UniqueModuleName ClassName" instead of "ClassName".  This would only be two words instead of one word, a relatively incosequential difference.  Was Oberon like this?  (Of course, hierarchical namespaces are useful.)

I'm also thinking of how namespaces work in other languages like Java and Python, not that we need to follow their example, but the importing versus explicit naming thing is still relevant.  I'm doing some work on a large Java project, and we always import names rather than use explicit naming, and it does make the code generally more readable and there haven't been any serious consequences.  (Well, actually crufty import statements (#2b) are a minor problem, but in Squeak a tool could be written to take care of it, whereas in Java we're powerless to do much about it.)

However, I suppose #1a and #1b are even bigger problems in a statically-typed language like Java, where you have static type declarations everywhere.  In Smalltalk you don't have *that* many class names in the code, relatively speaking, so maybe it's not as big a deal.

This reminds me of a different point.  It seems that there are two different approaches to namespaces:

A.  Duplicate class names not discouraged, some classname meaning can be derived from the module name.  (Collection-Ordered, Collection-Sorted might be extreme examples, where "Collection" could be the module name and "Ordered" the class name.)  IMHO I tend to think this is the less practical approach, especially with longish hierarchical module names.

B.  Duplicate class names discouraged, little or no meaning derived from the module name.  Namespaces are pretty much only there to handle unintended name clashes.  More practical?  (Er, I should say, more practical for Smalltalkers used to one large namespace?)


The Java project I'm working on strictly uses approach B.  There are *no* duplicate classnames among 1000 or so classes across many packages in the app.  A few imported classnames from other frameworks conflict, but very rarely.  (Two different external packages each had their own implementation of a Date object, which was confusing.)

Overall, I tend to think that approach B, and hierarchical namespaces, might favor using imported names as a better practice.  Approach A and/or flat namespaces might favor explicit naming.  (For readability reasons.)

Anyway, enough rambling for now.  Mostly I'm just trying to get my head around the real advantages & disadvantages of various approaches...

- Doug Way
  dway at riskmetrics.com



More information about the Squeak-dev mailing list