comp.lang.ada
 help / color / mirror / Atom feed
* use eiffel to build a CAM library?
@ 1998-01-21  0:00 Shane Miller
  1998-01-22  0:00 ` Thomas Beale
  1998-01-22  0:00 ` Paul Johnson
  0 siblings, 2 replies; 5+ messages in thread
From: Shane Miller @ 1998-01-21  0:00 UTC (permalink / raw)



hi:

i was considering using C++ to develop a library for use
within electronic manufacturing.  in short, we wanted the
library to do for CAM systems what other C++ libraries
have done for database systems: one API works on informix,
sysbase, oracle.

the bug was put in my ear about eiffel.  i am curious to
hear from people who have used eiffel to develop a library
(and, even, better those who have done libraries in C++ too)
to comment on the following.  but also ADA-95 people.  i
think i made a mistake but not examining ADA-95 and eiffel
and their respective tools and third-party libs as solutions.
i only looked at C++:

* what did you do for GUI?  if you did not want to use eiffels
WEL/MEL libs but wanted to use another lib (such as Roguewave's
ZIP/ZAPP) how did you get eiffel's runtime system to work with
an external package's event-loop?

* what about database support, in particular, informix, oracle,
and sysbase?

(note: a library does not count unless you used with your 
language be it ADA-95 or eiffel.  i am trying to make a 
decision based upon experience not on-paper options. C++
has database and GUI libs down 7 ways from sunday.)

* is this short form nonsense?  who actually comitted to giving
the user or client programmer nothin' but what you generated
in short form?  ISE says it can output that to HTML, ps, ect.
eg. what other things did you do to provide documentation?

* are BON diagrams useful for teaching and/or communicating or
documenting the library so that others may use it?

* with respect to memory management and object sharing/ownership,
how does eiffel impact the following two (similar) scenarios:
(a) you have a object containing 50 values.  the user asks to
display values in a form.  you use a "table" or "spreadsheet"
like UI object to edit those fifty values.  say 10 are modified.
Q: what do you do if the user clicks on cancel?  those 10 values
cannot be commited.  how does eiffel deal with copy semantics? 
reference vrs deep-copy?

(b) your library maintains a list of objects.  each object is
real big.  Q: what do you do if a client programmer who's using your
lib wants to inspect the list?  on the library side, you cannot
allow the client programmer to modify the list or the state of
any object in the list.  how can you share the list without doing
a deep copy?  ok, now the client programmer *needs* a copy of the
list because he needs it for a computation but also wants to
change the state of the objects in the list.  what's the least
painful way of giving a copy to the client from the libraries
perspective?

(hint in C++ you use const functions and reference-counting with
copy-on-write.  how, really, does garabge collection make this
easier?  i don't eiffel makes this any easier than any other 
language "makes it harder" relative to eiffel.  i am really
curious on this point).

* is there such an aminal as callbacks in eiffel?  suppose
i have a complex business system containing 200 objects how do
i handle each of the following scenarios: (a) object A wants
to change the state of object B.  but object B knows that it
first must ask permission from objects C and D.  the only 
reason B knows this is because, dynamically during runtime,
C and D found out about B and registered themselves with B
saying "look, if anybody tries to change you, consult me 
first: i may allow or disallow it".  so again, A tries to
change the state of B; B contacts C and D and says "ok here
is the proposed change, is it ok?".  if both C and D say
yes then B proceeds with A requests else nothing happens.

(b) simlarly, C and D may register themselves with B and
say "only notify me if your state changes; tell me what
changed but i don't care to stop the change".

(hint: in C++ you use function ptrs or functors, and either
pointers or references for the objects A,B,C,D)

any thoughts or ideas or experience is greatly appreciated.
i have ordered two of myers' books and hope it discusses these
very tricky questions of object ownership and copy-semantics.
lazy-evaluation and copy-on-write are neat ways to similuate
copy-semantics with only reference-sematics until the user
really tries to change the object.

in the above example, if the list of big objects contains
100 entries and the user (after he obtains his "copy")
only modifies 35 objects, then copy-on-write saved 65% 
of the maximum amount of work (eg. if you deep-copied every
one of the 100 objects that would 100% work).  these issues
are consisently *NOT* talked about in eiffel literature.

shane miller
geferan systems

-- 
--------------------------------------------------------------------
shanem@netcom.com | Remember: know where you're going and then who's 
804.673.4966      | going with you.  Never get the order mixed up.
--------------------------------------------------------------------
Beware of the software trap: because I can do x, I should be doing x
--------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: use eiffel to build a CAM library?
  1998-01-21  0:00 use eiffel to build a CAM library? Shane Miller
@ 1998-01-22  0:00 ` Thomas Beale
  1998-01-22  0:00 ` Paul Johnson
  1 sibling, 0 replies; 5+ messages in thread
From: Thomas Beale @ 1998-01-22  0:00 UTC (permalink / raw)



Shane Miller wrote:

> in the above example, if the list of big objects contains
> 100 entries and the user (after he obtains his "copy")
> only modifies 35 objects, then copy-on-write saved 65%
> of the maximum amount of work (eg. if you deep-copied every
> one of the 100 objects that would 100% work).  these issues
> are consisently *NOT* talked about in eiffel literature.
> 
> shane miller
> geferan systems

This is a good question. A solution is not completely obvious.
What I have done is:

- add mark_for_store and marked_for_store features to a class
  from which all storable business objects must inherit. Note
  that with ISE's EiffelStore, only the root object of a 
  logical "business" object has to do this inheritance, e.g.
  you might have PERSON, with all kinds of bits and pieces
  e.g. ADDRESS, PERSON_NAME, etc, etc. Only PERSON need inherit
  from the storable ancestor.

- when you call modifier routines, they have to set 
  mark_for_store to True. This sounds tedious, but in reality
  I have not found it a problem. Again this only relates to 
  business objects, not the bits and pieces.

As an overall approach, I have come up with the following,
for complex objects. 

0. It is essential to understand the  difference between a 
business (or "domain") object such as PERSON, VEHICLE, 
NET_NODE etc, and the actual network of instances which will 
make up any of these objects. When you are talking about 
storing "objects" you have to actually think about networks
of instances, right down to the LINKABLE instances making
up a LINKED_LIST.

1. I call a business or domain object a "composition" of
instances. A composition is the smallest unit that can be
read from or written to the database, since modifications
and reading require the whole logical object.

2. Complex business objects (investments, vehicles, SCADA
control systems) tend to be "parts explosions" of informational
business objects. E.g. VEHICLE might be a business object
containing ENGINE and GEAR_TRAIN, each of which is also a
business object. I use the word "aggregation" to mean
aggregation of business objects. A "sub-aggregation" is
a partial "tree" from an intermediate point down. This is
very useful where the aggregations are trees of software 
objects in a CM system for example; a sub-aggregation
could correspond to a component, a subsystem, a project etc.

3. Now you are in a position to attach sensible semantics
to the read and write of a) compositions, aggregations (of
compositions), and sub-aggregations. Semantics include
granularity of modification, locking, version control and
so on. A typical example would be to enforce locking of
entire sub-aggregations when a modification was requested.

4. Once these basics are in place, you can implement intelligent
storage schemes. For example, if a business object composition
is altered, write the whole thing. You can't do otherwise - 
think about what happens at the instance level if the contents 
of PERSON.addresses: LINKED_LIST[ADDRESS] changes. Mark-for_store
can be implemented on a per-composition basis. Now it can be
seen that if an object like INVESTMENT has a LIST of PORTFOLIO,
and both INVESTMENT and PORTFOLIO are programmed as business
objects, a write on INVESTMENT will traverse into all PORTFOLIO
objects, writing only those marked-for-store.

This type of approach gets out of mindlessly traversing 
entire networks of objects connected by reachability. You
rarely want to do that. Instead, you want to traverse 
business objects and aggregations, and stop when you hit
a new aggregation, and simply update association references
to it. The aggregation relationship (as described above)
is the relationship type which determines the scope of
traversals for writing and reading.

Another area of complexity is business object validity.
When is a PERSON valid; particularly, while constructing a
PERSON object from its parts, when is it ok to call it
valid? Simple Eiffel invariants for valdity don't work,
since many operations may be needed on an object before it
is fully built (e.g. if consturcting it from RDBMS records).
When the composition is viewed as the unit of construction,
compositions are also the place to put basic validity
functions, as well as a marker of some kind saying when
an object has been built for the first time, and it is now
sensible to call my_obj.is_valid.

Obviously there are many details to a scheme like this, but
these are the essentials.

One last note: how do you decide what is a business object and
what is not? Does an ADDRESS need to be a business object? My
answer is: only if its existence is meaningful on its own.
If you want a repository of ADDRESS objects, then yes; if 
ADDRESS will only ever mean anything when building PERSON 
objects, then no.


- thomas beale




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: use eiffel to build a CAM library?
  1998-01-21  0:00 use eiffel to build a CAM library? Shane Miller
  1998-01-22  0:00 ` Thomas Beale
@ 1998-01-22  0:00 ` Paul Johnson
  1998-01-24  0:00   ` Thomas G. McWilliams
  1 sibling, 1 reply; 5+ messages in thread
From: Paul Johnson @ 1998-01-22  0:00 UTC (permalink / raw)



In article <shanemEn5Ju8.2z6@netcom.com>, Shane Miller
<shanem@netcom.com> writes

>the bug was put in my ear about eiffel.  i am curious to
>hear from people who have used eiffel to develop a library
>(and, even, better those who have done libraries in C++ too)

I've written libraries in C++, and done a data structure library in
Eiffel for my own interest.

>* what did you do for GUI?  if you did not want to use eiffels
>WEL/MEL libs but wanted to use another lib (such as Roguewave's
>ZIP/ZAPP) how did you get eiffel's runtime system to work with
>an external package's event-loop?

I've used WEL.  Basically, its not a run-time issue at present.  When we
have concurrent Eiffel compilers (real soon now :-) then you will need a
non-blocking approach to GUI events.  For now, just call the
get_next_event routine or whatever, or just go into the event loop
routine that does this.

Its a pity that the run-time cannot use the time spent waiting for an
event to do a quick bit of GC.

Eiffel has good C and C++ linkage, but wrapping a 3rd-party library in
Eiffel classes is tedious.

Object Tools (used to be called Sig) do a neat GUI-builder called
Display Machine.  Take a look at it.

>* what about database support, in particular, informix, oracle,
>and sysbase?

ISE produce an add-on with ODBC connectivity.  You just dump your
objects into it.  I don't know about performance, but I suspect you
would be better off with an object database instead.  Relational DBs
were designed for table-wide batch operations, not individual row gets
and puts.  I've never used these.

Or you can write an interface to embed SQL in Eiffel yourself.  Eiffel
has excellent interfaces to C and C++.

>* is this short form nonsense?  who actually comitted to giving
>the user or client programmer nothin' but what you generated
>in short form?  ISE says it can output that to HTML, ps, ect.
>eg. what other things did you do to provide documentation?

Short-flat-form is one of the key arguments for Eiffel.  It acts as the
reference manual for the library.  Of course you still need natural-
language documents to introduce the library, show examples of use and so
on.  But they are much less sensitive to changes in the code than the
reference documents.

>* are BON diagrams useful for teaching and/or communicating or
>documenting the library so that others may use it?

Never used BON, so I can't comment.  Like all graphical notations, I
suspect it requires the others to be conversant with the notation.  You
may be better off with one of the Eiffel-UML tools instead.

>* with respect to memory management and object sharing/ownership,
>how does eiffel impact the following two (similar) scenarios:
>(a) you have a object containing 50 values.  the user asks to
>display values in a form.  you use a "table" or "spreadsheet"
>like UI object to edit those fifty values.  say 10 are modified.
>Q: what do you do if the user clicks on cancel?  those 10 values
>cannot be commited.  how does eiffel deal with copy semantics? 
>reference vrs deep-copy?

Depends on the GUI.  Eiffel has both shallow-copy and deep-copy built
in.  Also compound objects such as arrays and lists generally redefine
the shallow copy routine to do the "right thing" in their case.  So in
this case I would say you edit a shallow copy of the object, and then
copy it back onto your original when "OK" is clicked.

>(b) your library maintains a list of objects.  each object is
>real big.  Q: what do you do if a client programmer who's using your
>lib wants to inspect the list?  on the library side, you cannot
>allow the client programmer to modify the list or the state of
>any object in the list.  how can you share the list without doing
>a deep copy?

Define "read-only" ancestors to your classes, and export those using
polymorphism.  That way the type system prevents the programmer using
the modification routines, but they are available internally.  See my
paper on "Re-use through fine grain inheritance" in S-P&E Dec 92 for
more details.

>  ok, now the client programmer *needs* a copy of the
>list because he needs it for a computation but also wants to
>change the state of the objects in the list.  what's the least
>painful way of giving a copy to the client from the libraries
>perspective?

Give him a copy of the list.  Either deep or shallow, depending on what
you want.

Actually, these questions rather suggest a poor OO design.  A good OO
design should preserve the "object identity principle", which states
that for anything out there in the "real world" that you are modelling,
there should be exactly one corresponding object in your system.

>(hint in C++ you use const functions and reference-counting with
>copy-on-write.  how, really, does garabge collection make this
>easier? 

It means that if you only want to pass a reference to the list (in
accordance with the object identity principle) you don't have to keep
track of who is using the reference in order to determine when you can
deallocate the memory used for the list, or any other object.  Also, the
data required for GC is also used to do deep copy operations.

>* is there such an aminal as callbacks in eiffel?

OO designs don't use callbacks in the C way: you should use inheritance
and polymorphism instead.  These play similar tricks with function
pointers behind the scenes, but you don't need to worry about that.

>  suppose
>i have a complex business system containing 200 objects how do
>i handle each of the following scenarios: 

See the Gang of Four "observer" pattern.

>any thoughts or ideas or experience is greatly appreciated.
>i have ordered two of myers' books and hope it discusses these
>very tricky questions of object ownership and copy-semantics.

Object ownership is simply not an issue in Eiffel systems.  GC does this
for you.

Paul.
--------------------------------+---------------------------------
Paul Johnson                    | You are lost in a maze of twisty
Email: Paul@treetop.demon.co.uk | little standards, all different.
       paul.johnson@gecm.com    |




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: use eiffel to build a CAM library?
  1998-01-22  0:00 ` Paul Johnson
@ 1998-01-24  0:00   ` Thomas G. McWilliams
  1998-01-25  0:00     ` Rob Heyes
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas G. McWilliams @ 1998-01-24  0:00 UTC (permalink / raw)



Paul Johnson <Paul@treetop.demon.co.uk> wrote:
: OO designs don't use callbacks in the C way: you should use inheritance
: and polymorphism instead.  These play similar tricks with function
: pointers behind the scenes, but you don't need to worry about that.

I disagree. If one's OO design operates purely in a synthetic domain,
then callbacks may not be needed. But the real world is composed of
data representations that must be cajoled into a format acceptable
to OO techniques. Callbacks are most useful when attempting to parse
non-OO streams in an OO fashion. Callbacks can be dispatched on some
discriminant retrieved from the stream, rather than using ugly "if-then",
"inspect", or "case" type techniques. The weakness of all OO languages
seems to be the lack of a general high-level way to describe the mapping of
non-OO stream data into objects. Ada is better than most in this respect,
but it is still has a long way to go.






^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: use eiffel to build a CAM library?
  1998-01-24  0:00   ` Thomas G. McWilliams
@ 1998-01-25  0:00     ` Rob Heyes
  0 siblings, 0 replies; 5+ messages in thread
From: Rob Heyes @ 1998-01-25  0:00 UTC (permalink / raw)



In article <tgmEnAEI4.G6J@netcom.com>, tgm@netcom.com says...
> I disagree. If one's OO design operates purely in a synthetic domain,
> then callbacks may not be needed. But the real world is composed of
> data representations that must be cajoled into a format acceptable
> to OO techniques. Callbacks are most useful when attempting to parse
> non-OO streams in an OO fashion. Callbacks can be dispatched on some
> discriminant retrieved from the stream, rather than using ugly "if-then",
> "inspect", or "case" type techniques. 

What stops you using an object instead of a function pointer? Provide an 
abstract class that supplies the 'callback function' (and often 
encapsulates other relevant data) then create descendant classes that 
implement the 'callback' as appropriate.  Or am I missing your point, 
e.g. are you thinking of an OS routine that calls your code?

Rob Heyes




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1998-01-25  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-01-21  0:00 use eiffel to build a CAM library? Shane Miller
1998-01-22  0:00 ` Thomas Beale
1998-01-22  0:00 ` Paul Johnson
1998-01-24  0:00   ` Thomas G. McWilliams
1998-01-25  0:00     ` Rob Heyes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox