From: konstan@elmer-fudd.cs.berkeley.edu (Joe Konstan)
Newsgroups: comp.lang.clos
Subject: Re: CLOS Stylistic Questions -- Program Structuring
Date: 18 Aug 1992 00:53:38 GMT
Organization: Picasso Research Group, UCB Computer Science Division
Distribution: world
NNTP-Posting-Host: elmer-fudd.cs.berkeley.edu

In article <DOUG.92Aug17094109@monet.ads.com>, doug@monet.ads.com (Doug Morgan) writes:
|> In article <4948.9208171124@subnode.aiai.ed.ac.uk> jeff@aiai.edinburgh.ac.uk (Jeff Dalton) writes:
|> 
|> Defsystem is great and would be hard to live without.  I use defsystem
|> and the second alternative (below).  The problem with the above
|> solution by itself is just that defclasses and defmethods appear in
|> the same file.  When this happens, each addition of a method
|> specialized to a new or different class to any file can cause the
|> developer(s) to have to manually rearrange the defsystem dependencies.
....

From my original posting, I have no qualms about combining defsystem (or 
any PORTABLE code to handle compilation dependencies) with a carefully
designed style that avoids excessive dependencies and circular dependencies.

When we first wrote the Picasso graphical UI system, we also wrote a parser
that would take in files and generate defsystem specifications.  Eventually,
we found that it was far too complicated (for instance, a setf method could
be defined anywhere a :writer or :accessor existed, but only one had to be 
defined for the macro to exist) and went to a style where only header files
had load and compile order dependencies.  From what I've read so far, others
are either adding the dependencies to the defsystem when they are discovered
(not great for large systems) and are handling cyclical dependencies when
they occur, or they are adopting a similar header-based approach.

|> > > >2.  Subclasses in new packages 
|>   ...
|> > >        d)  Specifically import the desired symbols into the
|> > >            SPECIAL-AGENT packages either as an import-from clause in
|> > >            the defpackage or with an import call
|> > >     	   This seems like the best solution I've found.  I
|> > >     	   imagine it would also be pretty easy to design
|> > >     	   standard :import-from clauses for packages so all
|> > >     	   children of AGENT in other packages would use the same
|> > >     	   clause.
|>   ...
|> > I don't think it works very well to have a separate package for
|> > each class.  A separtate package for a group of related classes
|> > would usually work better, because otherwise the package structure
|> > gets too complex.  You also tend to start referring to internal
|> > names (by using "::" or by importing them), which violates the
|> > modularity of your packages, or else exporting names that should
|> > really be internal, thus violating the modularity of your class
|> > definitions.
|> > 
|> > The problem is that you want some names to be available only to
|> > certain packages (the ones that define subclasses) but Common Lisp
|> > provides only "available to everyone" (exported) and "available to no
|> > one" (not exported).  I'm not sure there is a very good solution to
|> > this in general, but the problem can be avoided when there is a group
|> > of related classes that can be considered as a single "service".  (Eg,
|> > if you want to provide a graphics service, you might have several
|> > class definitions in the "GRAPHICS" package.)
|> 
|> I completely agree with your comments.  A package per class is almost
|> never a good idea.  Classes almost always form systems of related
|> classes that are a much more natural target for a package.  I thought
|> of the original question more as "what do you do when you want a
|> subclass to be outside of the natural package of the superclass?"  I
|> suspect that this would hardly ever be a desireable thing to do, but
|> if you ever do want to do it, d) still seems the way to go.

Perhaps my example is a poor one (that's what you get for trying to
simplify), but I never intended to have a "package per class."  I do have a
lot of core classes, however, whose subclasses naturally belong in other
semantic units.  In the code I'm working with now, which is roughly a system
where "agents" (which are semantic units that encapsulate code) communicate
via "events" (which are messages without a designated recipient), it makes
much more sense to define a package for each major agent type that includes
the class for the agent, all the events it can generate, and all of the
handlers for the events it can receive (average of perhaps 20 classes or so).  

It does seem that these packages (which really should stay as packages
because they define units that can be loaded separately, have small
well-defined interfaces, and can benefit from a separate namespace) really
only have three choices for dealing with the core package that defines
the base classes for all agents and events:

	1.  Use the :: notation - which I think is poor programming

	2.  Use :IMPORT-FROM, perhaps by defining a special import-from 
	    line that is to be used by any "friend" of the package being
	    imported from, or
	
	3.  Define an extra interface package BASE-EXPORTS-FOR-INHERITANCE
	    that is used by the subclasses. This package could use #2 to
	    import symbols from the right packages and could export them.

I hadn't thought of #3 until reading some of the replies, but now it seems
like a close call between #2 and #3.  #2 would work better, I think, when 
there are several different chunks each of which might or might not
need to be imported whereas #3 would work better when there was a large, 
well-defined set of extra imports that might even come from several
packages.

More comments?

Joe Konstan
Newsgroups: comp.lang.clos