Re: Mixing OO and DB

From: Dmitry A. Kazakov <mailbox_at_dmitry-kazakov.de>
Date: Sat, 16 Feb 2008 13:03:07 +0100
Message-ID: <157bhpgm12919.1x4b9mj26302$.dlg_at_40tude.net>


On Fri, 15 Feb 2008 18:52:10 -0800 (PST), David BL wrote:

> On Feb 15, 8:13 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> wrote:

>> On Fri, 15 Feb 2008 01:12:22 -0800 (PST), David BL wrote:
>>> On Feb 15, 1:27 pm, David BL <davi..._at_iinet.net.au> wrote:
>>
>>>> I think when I say "substitutability of values" I mean what you call
>>>> in-substitutability, and when I say "substitutability of variables" I
>>>> mean what you call out-substitutability.
>>
>>> I take back my claim that "substitutability of variables" means out-
>>> substitutability.  I think it should encompass both in-
>>> substitutability and out-substitutability.
>>
>>> Therefore I was wrong to suggest that a pointer to a ColouredRectangle
>>> variable could be implicit cast to a pointer to a Rectangle variable,
>>> because it can lead to subsequent slicing.
>>
>> An important node. Pointer is a data type distinct from the data type of
>> what it is supposed to point to. What you probably meant is that there
>> exists a mapping: f : ColouredRectangle -> Rectangle.

>
> Yes that mapping exists. It is surjective but not injective. Not
> injective means it isn't information preserving (because distinct
> coloured rectangles map to the same rectangle when the colour is
> sliced away). IMO for implicit conversions to be applicable, such a
> mapping must be injective (but not necessarily surjective).
>
>> Which in dreadful C++
>> notation looks like
>>
>>    *(Rectangle *)&
>>
>> (a composition: &, casting and *). In a decent language, which C++ is not,
>> the operation * should not be allowed for all types indiscriminately. That
>> makes optimization quite difficult. What if Rectangle "physically exists"
>> on a different machine in a DB? How can I get its pointer? What is this
>> pointer? etc. Getting rid of data, also eliminates hard-wired data things
>> like pointers. Instead you get behavior of some objects referencing others.

>
> I don't think I follow. Are you saying
>
> *(Rectangle *)&
>
> amounts to slicing and you can blame the pointer indirection - ie
> operator*() ?

I mean that you need not to resort to pointers or more generally to internal representation in order to say that Rectangle value can be obtained from a ColouredRectangle one.

Further the programmer should define the conversion, if that cannot be generated by the compiler or is inappropriate.

>>> In the end it's better
>>> just to say that subtyping ColouredRectangle from Rectangle doesn't
>>> make sense and leave it at that.
>>
>> But there exists a mapping between them, which makes possible for
>> ColouredRectangle to be an extension of Rectangle. In practical terms it
>> means that ColouredRectangle can be out-substitutable for Rectangle:
>>
>>    Give_Me_One : <something> -> Rectangle
>>
>> (this case you considered for circle/ellipse later)

>
> That doesn't change my opinion that sub-typing is inappropriate in
> this case.

Why, it is perfectly OK. Consider a factory of rectangles. There is nothing wrong in generalization. It is just so that generalization is compatible with inheritance of out-operations, while specialization is with inheritance of in-operations.

>> Ah, this is a crucial point. Circle value is not an ellipse value. These
>> have different types. It is only so that there exists a mapping which gives
>> you an ellipse value from any circle value.

>
> It depends on what "is" means. Using the example of the integers and
> reals: As mathematical systems it is reasonable to say the integers
> is not a sub-type of the reals. However it is true that the set of
> integers is a *subset* of the set of reals.

[I answered this in another post. Z is a ring, R is a ring too. One can inherit a ring Z from R]  

> Perhaps the C.Date approach needs a different terminology (ie than
> subtype) to avoid this confusion. When Date says integers is a sub-
> type of reals, he means for example that nonzero integers have
> inherited real-valued multiplicative inverses. In mathematical
> definitions of integers that's inappropriate, but for software
> development I need to see a good reason to disallow it. Can you
> provide one?

No, it is OK. That is a specialization. You constrain a type upon subtyping. The constraining manifests by loosing some operations. There is nothing wrong with that. But also there is nothing wrong with generalization. And also there is nothing wrong with mixed cases.

> I don't think you need the mapping to give an ellipse value from a
> circle value. I would rather say the set of circle values is a subset
> of the set of ellipse values.

Disagree, that would heavily limit the system, and likely make it inconsistent. The only sense in which circle value should ellipse value is to keep the internal representation same. Why should I care?  

>> As for subtyping, to me, it is just a relation between types. I don't
>> expect it to deliver substitutability. It cannot. What it can and should,
>> is to help me to deal with the problem.

>
> Can it? I'm interested to know what you have in mind.

There are many cases where languages could be safer. For example:

  1. multiple dispatching should ensure overriding of all cross variants (dispatch may not fail).
  2. construction model shall be sane, i.e. allowing dispatch from constructors/destructors.
  3. there should be an operation extension model, rather than override-whole only.
  4. no re-dispatch allowed
  5. classes of all types, including small ones of value-semantics (like Boolean and Integer)
  6. dynamically constrained types (light-weight classes)
  7. abstract interfaces for anything, including member variables, arrays, pointers.
  8. interface inheritance from concrete types
  9. supertyping of concrete types
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Received on Sat Feb 16 2008 - 13:03:07 CET

Original text of this message