* 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 ` Paul Johnson
1998-01-24 0:00 ` Thomas G. McWilliams
1998-01-22 0:00 ` Thomas Beale
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-21 0:00 use eiffel to build a CAM library? Shane Miller
1998-01-22 0:00 ` Paul Johnson
@ 1998-01-22 0:00 ` Thomas Beale
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