Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!xylogics!merk!alliant!linus!think!barmar From: barmar@think.com (Barry Margolin) Newsgroups: comp.lang.lisp Subject: Re: Using Packages With CLOS Keywords: packages, information hiding, CLOS classes, file naming conventions Message-ID: <41113@think.Think.COM> Date: 30 Jul 90 03:39:45 GMT References: <26B09E74.58E0@wilbur.coyote.trw.com> Sender: news@Think.COM Organization: Thinking Machines Corporation, Cambridge MA, USA Lines: 93 In article <26B09E74.58E0@wilbur.coyote.trw.com> scott@wiley.uucp (Scott Simpson) writes: >How do people use packages with CLOS classes? I don't think there needs to be a particular relationship between classes and packages. The purpose of packages is to prevent inadvertant name collisions between programs written by different groups of people. They can also be used to collect together all the public interfaces to a facility. > The most obvious >solution to me would be to make a separate package for each class. This is probably too extreme. A decent-sized application would probably have dozens of classes, many of which are expected to be mixed together. Related classes would be implemented by the same developer or development team, so name collisions are not likely to be a problem. They'd probably end up using package prefixes excessively. When a method is implemented by several classes, or a normal function is needed by several classes, you'll have to decide arbitrarily which class's package to use. And packages can be pretty confusing, and a large number of small packages is likely to cause more problems than it solves. Implementation of mixins can be tough with this scheme. Frequently, a mixin is designed so that it may be mixed in with any of a number of base classes. It simply requires that the instantiated subclasses implement a given set of generic functions and/or provide a specified set of slots. If each base class is in its own package this can be problematic. > My >office mate objected to this, saying that it would cause problems with >inheritance. He noted that symbols are local to a package Except, of course, for the ones that are exported and inherited or imported into another package. There's nothing special about the symbols used to name slots and methods, so you can import and export them just like any other symbols. However, care must be taken in deciding what symbols to export, since the export list defines the interface to a facility, and slot names are not usually chosen that carefully. > and when you >inherit from another class you would need to know the superclasses >name to access any inherited slot. My retort was that you should >provide accessor functions for superclass slots in your class and >export them if you wish to enable the user of the class to access an >inherited slot. Then if you changed the superclass for any reason the >code behind the package wall would change but the accessor function >used by the user using the class would not change. This is a good point. However, it's often important to distinguish between interfaces intended to be used between related classes and interfaces intended for external users of the class. This can, of course, be done by providing an additional class for external users, and importing/exporting only the public interface from this class. (Some OO languages provide more explicit support for this distinction, such as C++'s "protected" slots and methods.) However, one reason for using function-style accessors rather than SLOT-VALUE is to hide the fact that a value is implemented as a slot of a particular class. However, by using packages this way you force this association to be explicit. See my point above about choosing the package of a generic function implemented by multiple classes. > Another issue is the mapping between file names and CLOS >classes. Do you normally create a different file for each CLOS class? >This seems to me to be simple method for quickly identifying where >classes are stored. If all the files are stored in the same directory, >it regrettably flattens the type hierarchy structure you are trying to >simulate but I think it is the best you can do without some sort of >object-oriented database underneath. One of the features of CLOS is the ability to spread the implementation of a class out. In some cases it's useful to keep the methods of a class together. In other cases, though, it's useful to keep all the methods implementing a particular generic function together. For instance, if you have an optional facility that works by adding functionality to a bunch of classes. In Lisp it is often less necessary to keep source files small than it is in other languages. Most Lisp environments are integrated with an editor, and make it easy to incrementally recompile functions and methods. Therefore, the edit-compile-test cycle time is not usually a function of source file size. Therefore, if you have a number of related, small classes (mixins tend to be pretty small) it may be easier if they are in the same source file. Many good Lisp environments provide automated mechanisms for finding the source file of an identifier, so there's less need for an easy way to guess. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar