Re: Clean Object Class Design -- Circle/Ellipse

From: Bob Badour <bbadour_at_golden.net>
Date: 8 Sep 2001 15:36:59 -0700
Message-ID: <cd3b3cf.0109081436.20d0685e_at_posting.google.com>


dmitry_at_elros.cbb-automation.de (Dmitry A. Kazakov) wrote in message news:<3b94d133.1837081_at_news.cis.dfn.de>...
> On Tue, 4 Sep 2001 03:14:31 -0400, "Bob Badour" <bbadour_at_golden.net>
> wrote:
>
> >>>If we accept your assumption that no such thing as subtype exists, we can
> >>>end this conversation now. The conversation is, after all, a discussion of
> >>>subtype.
> >>
> >>How the view that any value has a type disallows subtypes?
> >
> >The view that any value has one and only one type disallows inherited type,
> >which then disallows supertypes and subtypes.
> >
> >Any value has a specific type and possibly many inherited supertypes.
>
> That a type inherits means only that methods are inherited.

Type inheritance means that types are inherited. Nothing says that inheritance necessarily means method inheritance.

> >If one properly recognizes the type difference between variables and values,
> >LSP poses no problem. A variable is a reference to a representation of a
> >value, which makes its type different from that of the value whose
> >representation it references.
>
> How it helps in the case of LSP.

Apply LSP to subtype/supertype relationships. While a circle value is a subtype of an ellipse value, a reference to a represented circle value is not a subtype of a reference to a represented ellipse value.

> What happens when a variable of the
> type Circle is resized as if it were an Ellipse?

Since references to represented circle values are not subtypes of references to represented ellipse values, they inherit no operations that allow such resizing. ie. A circle value inherits all operations on ellipse values, but circle variables do not inherit all update operations on ellipse variables.

> >>>This is not the accepted use of the term "class" in OO. The ISO standard
> >>>vocabulary for programming languages equates "class" with data type.
> >>
> >>Nice to have several words for same thing ...
> >
> >The ISO standard vocabulary definition for "class" simply recognizes that
> >the OO crowd invented a new word for an old concept.
> >
> >Your additional definition for "class" overloads the term with a confusing
> >new meaning. I suggest we stick with one meaning, and I further suggest we
> >stick with the general meaning used by OO practitioners.
>
> The term class of types had existed long before.

The OO programming world took existing vocabulary from other disciplines and restricted the meaning -- much as those other disciplines took vocabulary from the english language and restricted the meaning.

Before you can redefine the meaning of the word for the OO programming community, you must establish a consensus among its members. Currently, that community generally equates class with data type as evidenced by the ISO standard vocabulary for programming languages.

If you want to use the ADA syntax, do so in comp.lang.ada and not in comp.object

> It is not my
> invention.

I never claimed it was your invention. I claimed that it was not the meaning generally ascribed by the object oriented programming community. We will never establish a common ground for communication if we indiscriminately insist on word meanings not generally accepted by either the comp.object or comp.databases.theory communities.

> >>>>>"Most-specific type", 'declared type" and "inherited type" have meaning.
> >>>>
> >>>>How many types has the value 1, provided that I can derive from
> >>>>integer?
> >>>
> >>>Integer is rational is real is complex.
> >>
> >>So only 4 types. What if I derive my own type? What if I call my
> >>friends to derive a bit more types?
> >>
> >>>Natural is whole is integer.
> >>>
> >>>Any others you would like to propose?
> >>
> >>Lots. The file descriptor for instance. 1 is stdout.
> >
> >File descriptor is neither a subtype nor a supertype of integer. While it
> >uses similar symbols, the properties of a file descriptor, including defined
> >operations, are neither a subset nor a superset of the properties of
> >integer.
>
> Did I claim that file descriptor is a subtype of integer? I said only
> that it has the literal 1.

You originally posited the value 1 in the context of the integer type. If you originally meant the symbol 1, you should have said that.

> Which means that there are two different
> 1s.

1 is a symbol -- not a value. You previously posited the value 1 in the context of the integer type.

> >For instance, what does it mean to add two file descriptors?
> >Substract? Multiply?
>
> They have no meaning, they are operations of some other unrelated
> types.

And values of those types are different from values of file descriptors even if they use the same symbols for some representation.

> But nothing prevents me from making it a subtype of integer, so
> that 1 + 1 be 2 = stderr.

Nothing prevents you from declaring that pigs are subtypes of integer, but that does not change pigs into integers.

> Of course if your platonic approach is
> applied consequently one should think that there is only one + in the
> universe.

Not true. I have said nothing about restricting the use of symbols for any specific type.

> But it is obviously wrong.

And obviously a straw man.

> >Again, I must point out that your example uses an artifact from a non-object
> >oriented system.
>
> Maybe the artifact is that a particular system is unable to explain
> what appears "artefact"? I wouldn't blaim OO for this.

I never did blame OO for this. I only stated that your non-OO example is inappropriate for a discussion of OO.

> >>Literal can be viewed as a read-only variable. Both literals and
> >>constants might require elaboration (construction) if they have some
> >>complex types.
> >
> >This describes exactly why neither literals nor named constants are values!
> >They are variables constrained to a single value.
>
> Yes and this supports my view that values do not exist without
> variables.

No, it doesn't. Variables do not exist without values, which says nothing about the existence of values.

> >>Value of an ellipse cannot be resized because the result [in most
> >>cases] is another value.
> >
> >One cannot resize an ellipse value because values do not change -- ever. One
> >can resize an ellipse variable because variables do change.
>
> "Resize" means "to call a routine named Resize with an actual
> parameter which value is of ellipse type".

Since "Resize" changes the actual parameter, one must pass a variable -- not a value. Since a circle variable is not an ellipse variable, one cannot pass it.

> >>Surely there would be no problem with LSP if
> >>all operations violating it are removed.
> >
> >We have no need to remove any operations. We need only properly recognize
> >the type of values. The type of a variable is a reference to the
> >representation of a value, and the type of the variable is different from
> >the type of the value.
> >
> >Operations like setFoci operate on variables and not on values.
>
> Is "the type of a variable referencing a circle" a subtype of "the
> type of a variable referencing an ellipse"? Are they same types?

No. As Jan pointed out, "the type of a variable referencing a circle" is a supertype of "the type of a variable referencing an ellipse".

> On which type setFoci is defined? Does it violate LSP?

It is defined on "the type of a variable referencing an ellipse". It does not violate LSP.

> >>>>You pointed the distinction: values are immaterial and enjoy
> >>>>witnessing of the God of programming. Variables are sinful and
> >>>>condemned forever. (:-)) Seriously why in your opinion, say in C++,
> >>>>values and variables are not distinguished?
> >>>
> >>>Update operations necessarily operate only on variables while non-update
> >>>operations necessarily operate only on values, and C++ makes no
> distinction
> >>>between the two. Constraining a variable to a single value or a subset of
> >>>values is a different matter.
> >>
> >>1. Both update and non-update operations operate on variables
> >
> >...in C++... which is why I say that C++ makes insufficient distinction
> >between variable and value.
>
> Is there values in C++?

Yes, there are values in C++, and there are variables in C++. However, C++ makes insufficient distinction between them.

> >>2. void Foo (const X); is Foo an undate or non-update operation?
> >
> >...in C++... it is impossible to say, because C++ makes insufficient
> >distinction between variable and value:
> >
> >1. Foo could update a global or static variable.
> >2. Foo could be a member function that updates the variable referenced by
> >"this".
> >3. Foo could be a non-update operation, in which case it performs little of
> >enduring use.
>
> From this point of view there is no non-update operations, because any
> operation always has side effects [memory mapping, stack use etc].

I disagree. You are again trying to introduce physical implementation irrelevancies into a discussion of the logical concept of type inheritance.

> >>There is no dynamic polymorphism without tags. So being non-existing
> >>it would not work, which should wake up some interest of the user.
> >
> >Try to think out of the box a little. It is possible -- you just haven't
> >imagined all of the possibilities.
>
> Which ones?

Consider that the DBMS might at different times choose different access paths. Such a choice is dynamic. In one path, the DBMS might know that it always uses one representation for a type, and in another path, the DBMS might know that it always uses a different representation. Once the DBMS dynamically chooses a specific access path, it has no need for tags.

Again, tags are an irrelevant implementation detail. Internally the DBMS must somehow represent the meta-data governing which physical representation and type a specific variable has, but this is irrelevant to the discussion of the logical concept of subtype/supertype.

This is the last time that I will discuss tags. I have address that they are irrelevant to the discussion, and I will ignore any mention of them from this point forward.

> >>Very convincing. Give your proof that in a language we both know one
> >>cannot distinguish values of the base type from the values of one of
> >>its subtypes.
> >
> >One can always determine whether a subset contains a given value.
>
> "To determine whether a subset contains a given value" = to determine
> whether a value belongs to the domain of a type = to determine the
> type of a value, ... not knowing the type of that value! If we put
> aside the theory of divine influence then there is nothing that can
> help us.

Both your original challenge and your subsequent histrionics are straw men.

The ability to distinguish a specific type from an inherited type does not change the fact that a given value can have many types.

> >This does
> >not prove whether a conversion is necessary as you claimed. Since a subtype
> >value is also a supertype value, the DBMS can operate on it as the supertype
> >without conversion.
>
> This proves that to do something with a value you shall know its type.

Since the DBMS must internally know both the specific type and the physical representation and since the user must externally know at least one inherited type, the above proof proves little of utility.

> >>>In my language, -1 is a literal of real type also.
> >>
> >>Then they are two different literals overloaded in some given context.
> >
> >Nope. A single literal has multiple types.
> >
> >>One -1 has the type Integer another -1 is Real.
> >
> >Nope. The single literal has both type Integer and type Real.
>
> Now please, explain this:
>
> type MyInteger is new Integer; [Specifies representation for a new type]
> A : Integer := -1; -- Literal of what? [Integer]
> B : MyInteger := -1; -- Literal of what? [MyInteger]
> B:=A; -- Compilation error - why? [Unrelated types]

Using an example that confuses type with representation proves little of utility.

> >In either case, discussing a function from a non-object oriented language
> >like C says nothing about object orientation.
>
> As far as I know the discussion was about C/E problem and subtypes.

It was until you hijacked it with myriad irrelevancies.

> Should your statement mean that any non-polymorphic subroutine is not
> an issue regarding LSP and subtyping.

An operation defined on values of a supertype must operate on values of all subtypes; otherwise, they are not subtypes. If you assume a non-polymorphic operation, you assume no subtypes, which makes the issue irrelevant.

> What makes you think so:
>
> 1. Non-polymorphic subroutines do not exist

They exist for any type with no subtypes.

> 2. Non-polymorphic subroutines cannot be inherited

They would then be polymorphic -- by definition.

> 3. Non-polymorphic subroutines never violate LSP
> 4. Non-polymorphic subroutines always violate LSP

Since there are no subtypes to substitute, they cannot violate LSP. LSP does not apply in this situation.

> >I see where the confusion comes in. ISO equates "internal level" with
> >physical representation of information. Type and representation are both
> >metadata, and the DBMS must internally represent the metadata information
> >somehow.
> >
> >In a DBMS, we have a physical design separate from a logical design and
> >separate from dbms internals. A physical design could involve multiple
> >possible representations for a given type. For instance, one can represent
> >complex numbers in cartesian or polar coordinates. Both physical
> >representations represent the same type, and the DBMS can use either
> >representation interchangeably without any logical consequences to the user.
>
> Now consider that the union of all that possible "representations" is
> also a representation, which never changes.

I do not know what it means to take the union of multiple physical structures. Since they are physical one can overlay them or arrange them in some sequence etc. In any case, the physical representation is irrelevant to the logical issue of subtype/supertype.

Can we get back to something relevant for a change? Do you have anything to say regarding the logical concept of subtype/supertype?

> >The cartesian representation has derived properties for magnitude and angle,
> >while the polar representation has derived properties for real and imaginary
> >parts.
> >
> >A DBA would interact with and manipulate the physical design without always
> >requiring detailed knowledge of internals -- just as a casual user would
> >interact with the logical design without requiring knowledge of the physical
> >design.
>
> It just one of possible solutions in which both cartesian and polar
> view on the complex numbers are implemented using one type and one
> representation [which has some identification of the current view].

Nothing I have said implies that the DBMS or the DBA will implement the complex number type with a single representation. When discussing the logical concept, we must allow the DBMS to use multiple representations of the type regardless whether the DBA declares a single possible representation or multiple possible representations.

> >>So I made the conclusion you argued that the
> >>representation determines the type. Or it is the type that determines
> >>the representation. In any case, to distinguish types by
> >>representation there should be a mapping representation->type. This
> >>excludes multiple type representations.
> >
> >Type does not determine representation. Physical representation does not
> >determine type. Internally, the dbms must represent the metadata information
> >regarding type and representation, but does not expose this internal
> >representation to any user. This allows multiple representations for the
> >same type.
>
> It is exposed in dispatch.

Assuming dispatch -- which I do not.

> >>>I can accept that provided we accept that representation is orthogonal to
> >>>type.
> >>
> >>It is, in the sense that a user/compiler is free to choose a
> >>representation for a type. But the choice shall be made.
> >
> >You assume that a single choice will be made, but the assumption is false.
> >In order to provide physical independence, the dbms must allow multiple
> >representations for a type.
>
> Which union is the actual and single representation of the type.

No. Physical independence requires that we allow multiple alternate representations for a type.

> >>Value is a language term here.
> >
> >What language? What is wrong with the generally accepted definition? How
> >does the definition as a "language term" differ?
>
> Values in a language are not mathematical objects they might
> occasionaly represent.

First, I need to clarify a faulty assumption: Values are not necessarily mathematical.

Again: What language? What is wrong with the generally accepted definition? I do not see how values in a language are any less abstract. Physical representations are physical representations, and values are values. Let's not confuse the two.

> >>>Not my point. My point is: Type does not determine representation and
> >>>representation does not determine type.
> >>
> >>Then you should explain how dispatch can work, if there is not way to
> >>determine the type.
> >
> >Dispatch is ultimately an irrelevant implementation detail when discussing
> >logical type inheritance. A DBMS might derive the type any number of ways
> >just as it might derive the representation any number of ways.
>
> Dispatch = [run-time] selection of an implementation of some
> polymorphic subprogram.

Since the DBMS constructs the physical access path, it might not dispatch anything. It might implement the operation in place with the access path.

> Provided that implementations are written by
> the user, how could it be irrelevant which one is selected?

Here is a fundamental misunderstanding. When one assumes physical independence, one does not assume that the ultimate implementation is written by the user. One assumes quite the opposite.

> >>>Your example does not achieve the desired result. Complex is a single type
> >>>regardless of the physical representation.
> >>
> >>Why? I can use both different complex types interchangeable. It is all
> >>that we need, or?
> >
> >We need a single type. The user must be able to declare variables just by
> >specifying Complex. The user must be able to discover the defined properties
> >and operations from the system catalog by specifying a single type, Complex.
>
> I prefer a system where the user can choose.

You prefer a system where the user must choose, which is entirely different. Most programmers are control freaks. Unfortunately, specifying the level of detail that programming languages customarily require of programmers contravenes the principles and best practices of database management.

In a DBMS, the DBA should have considerable control over the physical implementation. The DBMS should provide considerable flexibility to map a logical design to any conceivable physical implementation. The DBMS should also provide considerable flexibility to map a given user's logical view to any conceivable base logical design.

> It is very doubtful that
> whether to declare a variable DenseMatrix or SparseMatrix is
> irrelevant if the matrix is 100,000x100,000.

Since each will obviously lead to very different performance characteristics, and since those performance characteristics will depend on many potentially unpredictable factors including data distribution and context of use, the DBMS should choose based on which representation will perform the given task better.

> It is also thinkable to
> have some IntelligentMatrix which would try automatically get an
> advantage from the distribution of non-zero elements, but in any case
> those three are different types.

The DBMS has no need for IntelligentMatrix because the DBMS already performs the proposed function of the representation.

> >They have exactly the same values and exactly the same properties, including
> >operations.
>
> Do you really believe that (int) 1 and (double) 1.0 have same
> properties?

Since they are different types, why should they? We were discussing multiple possible representations of a single type and not multiple types.

> >>>>And how do you call the set of all values having exactly one [of that
> >>>>multiple] representation. I would call it a type. And you?
> >>>
> >>>I call it the empty set. All of the values have both representations.
> >>
> >>Simultaneously? So the representations are undistinguishable = same.
> >
> >Yes. At the logical level, the cartesian representation of Complex(0,1) is
> >indistinguishable from polar representation of Complex(1,Degrees(90)).
>
> Which means that there is exactly one representation.

Internally, there are two representations. Externally, there is a single type.

> What cannot be observed does not exist.

The DBMS observes internals. The user observes externals.

> >>>>My proposal to you is
> >>>>to consider the following naming convention (used in Ada). What you
> >>>>call "type" [with multiple representations] is a class-wide type. What
> >>>>you have no name for, is a normal type.
> >>>
> >>>My proposal to you is to consider the generally accepted naming
> >>>conventions. What you call a "class-wide type" is the set of specific types that a
> >>>variable of a declared type can contain -- either directly or through
> >>>inheritance.
>
> [..]
>
> >>>What you claim I have no name for is an abstract data type. (See ISO/IEC
> >>>2382-15.04.02)
> >>
> >>Sorry, but abstact types have no values => representation.
> >
> >Sorry, but the definition for abstract data type only requires us to
> >describe the interface separately from the physical representation. It does
> >not require abstract data types to have no representation. (See ISO/IEC
> >2382-15.04.02)
>
> "An abstract type is a tagged type intended to use as a parent type
> for type extensions, but which is not allowed to have objects of its
> own".

This might be a definition that ADA uses in its implementation, but again this discussion is not posted to comp.lang.ada

In the context of this discussion, I will continue to use the ISO/IEC standard vocabulary for programming languages (ISO/IEC 2382-15), which includes object oriented programming languages.

According to ISO/IEC 2382-15.04.02, abstract data types describe the interface separately from the physical representation but the standard vocabulary does not require abstract data types to have no possible representation.

> I meant the types that are allowed to have objects and those are not
> subject of dispatch.

Again, I do not assume dispatch and one can have multiple possible representations of abstract data types. In fact, by requiring that the DBMS keep logical type independent of physical implementation, the relational model requires that all types are abstract.

> >>>>>>class Circle : public RosaElephant, public Ellipse {...}
> >>>>>>
> >>>>>>You cannot pass such circle to an ellipse method without conversion.
> >>>>>
> >>>>>In the specific implementation of your compiler, perhaps, but that says
> >>>>>nothing about subtypes and supertypes in general.
> >>>>
> >>>>In which compiler it could be possible?
> >>>
> >>>In any compiler that fully supports polymorphism.
> >>
> >>How it supposed to work, provided that according to you values of
> >>Circle are values of RosaElephant and simultaneously of Ellipse?
> >
> >Why would it not work? Variables of RosaElephant can have any value of
> >Circle as well as any other value of RosaElephant. Variables of Ellipse can
> >have any value of Circle as well as any other value of Ellipse. Variables of
> >Circle can have any value of Circle.
>
> Because in this case the domain sets of RosaElephant and Ellipse would
> intersect. But RosaElephant has no axis, it has a big salivous trunk
> and a rose-colored bow with "Rosa" written upon it. You could try to
> resize it, but it will surely take offence.

Hey, it was your example not mine. If you want to criticize it as semantically inappropriate, choose a different example; otherwise, it is only a straw man. Received on Sun Sep 09 2001 - 00:36:59 CEST

Original text of this message