"Robert I. Eachus" <[log in to unmask]> writes:
Thanks for the comments. I'll think some more about some of these
things, I don't think my way is necessarily better, I'm just giving my
rationale for the decisions I made.
> ( I'm sending this to you directly, but if you want to copy your reply
> to TEAM-ADA, I have no problem with that.)
I will. These are good comments.
> I've started to look at your components. What follows are a couple of
> questions and comments. Much of this is questions of style, I'm not saying
> what you did is wrong, I'm just feeling around for "more right."
> 1) Why is Limited_Object derived from Controlled, not Limited_Controlled?
That's a mistake. Thanks for the info.
> 2) Why have the Baseclass package at all? There seems to be no
> generality gained by not declaring these types in Asgc. Usually this
> structure is chosen to avoid some elaboration order problems, but I don't
> see any currently.
The idea of Baseclass is not really for generality at that level. The
Asgc object could have been its own tagged type and everything would
have worked fine.
However, after using Java for a while and doing work in object-based
fault-tolerance, I find that it is quite convenient to have all
classes in the system derive from one base class. That way containers
of more general objects can be built, all objects can be treated the
same at certain levels, etc. Also, making handling general interfaces
(like Java, a special form of multiple inheritance) more general to be
useful, too. So the expectation is the user would derive from
Baseclass.Object, too, for their tagged types.
So it is not required, but it seems to me to be more convenient.
It's not that big a deal, though.
> 3) Personally, I would find it more appropriate to make the generic type
> Object instead of Contained_Type, and to have the container classes derive
> from a root type Container:
> type List is new Container with private;
> (and in asgc.lists.fixed:)
> type Fixed_List is new List with private;
> 4) My style for doing this would be to have a single non-generic parent
> package, each of the types of container as a non-generic child, and finally
> the "real" packages as generic grandchildren with the Contained_Type
> (renamed ;-) as a generic parameter.
I wanted to push generality as far down the package hierarchy as I
could. So, for instance, you can take any container and search it,
get values from it, etc. Without the genericity pushed all the way
down the package hierarchy, that was not possible except for a very
limited set of operations. Making things as general as possible as
far down the package hierarchy as possible allows the most allows the
most flexibility for replacing containers, too.
If for instance, I am using a fixed doubly linked list and later on I
determine that I need a dynamic list, or that I need to use an
array-based list (AList), etc. I can instantiate the variable with a
different package in one place (if the variable is as generic as
possible) and the job is done. There are other useful ways to
accomplish this, too, such as renaming the packages you want and then
working with those package names exclusively.
My examples currently don't do this, I probably need to add some that
do and add some documentation that this is my intent. The test
routines do take advantage of this. For instance, there is one
routine to test graphs, but nine different types of graphs. The
routine takes a generic graph baseclass and does the tests, it gets
called with nine different types of graphs.
The main disadvantage I have seen so far is that lots of package
instantiation has to be done. It's kind of a pain, but I don't think
it contributes much to executable bloat because all but the "leaf"
packages tend to be very abstract and quite small.
> 5) You have many different access types named Object_Class. This
> creates a painful confusion if you use more than one container type in a
> program. It would be nice to have Container_Class, List_Class,
> Fixed_List_Class, etc. Better might be to name them _Pointer, or _Handle,
> but that is a different discussion.
I have quit following that discussion :-). _Handle might be a better
name, but I really wanted to convey that fact that is is class-wide.
(I use _Ptr for things that are not class-wide). Anyway, I believe
that having everything as an Object and Object_Class makes things less
confusing, not more. I don't like to "use" packages unless they are
very familiar, I like to rename them to what I want and use that name
throughout. So for the the containers, you might take a doubly linked
list (DList) and use it as a queue. You would rename or instantiate
the DList package you wanted to be a Queue package, but wouldn't "use"
the Queue package. Then you would say something like:
package Integer_Base is new Asgc(Contained_Type => Integer);
package Integer_Queue is new Integer_Base.Ordered;
package Integer_Queue_DList is new Integer_Queue.DList;
package Integer_Dynamic_Queue_DList is new Integer_Queue_Dlist.Fixed;
Then later on, instantiate it with:
My_Queue : Integer_Queue.Object_Class
:= new Integer_Dynamic_Queue_Dlist.Object;
Then I would use the methods defined in Integer_Queue to operate on
If it was done the way you suggest, you would end up saying:
My_Queue : Integer_Queue.Dynamic_DList_Ptr
:= new Integer_Queue.Dynamic_DList;
which I don't like as much, personally. However, as threads on
comp.lang.ada show, there are quite a few opinions on this :-).
Corey Minyard Internet: [log in to unmask]
Work: [log in to unmask] UUCP: [log in to unmask]