Professional Documents
Culture Documents
Taxonomic Modeling in C Based Object Ori
Taxonomic Modeling in C Based Object Ori
Taxonomic Modeling in C Based Object Ori
Abstract
1
1 Introduction
Object-oriented database systems (OODBS) exhibit several well-accepted virtues,
combining the strength of databases technology with the power and flexibility of
the object-oriented paradigm of programming languages like C++ or Smalltalk.
In particular, the rich type system of an OODBS, supporting the natural model-
ing of complex attributes, is one feature that attracted the attention of database
application builders. Object-orientation with its inheritance mechanism also sup-
ports software reuse ([Kim90, RBP+ 91, Boo94]), which is of major concern in soft-
ware engineering. It is conspicuous, however, that this capability has received
less attention in the OODBS community than other popular features. Indeed
this is not a coincidence, rather it is rooted in two different mentalities joining
together when C++ meets the OODBS-world: C++ programmers tend to have
an implementational view of the data modeling process leading to implementation
hierarchies ([ZM90]), whereas database folks tend to think in terms of extensions
or taxonomic modeling.
Let us give a motivating example to highlight the differences (cp. [LP91]).
Example 1.1 (Triangle World) Suppose that three kinds of triangles are to be
modeled: general triangles, right triangles, and equilateral triangles. In Figure 1
two different modeling views are expressed in OMT-notation ([RBP+91]). For
simplicity we only treat the shape of triangles but not their spatial location. On
the right side there is the C++ view that puts Triangle as subclass of Right-
Triangle. On the left side this model is turned upside down by defining Right-
Triangle and EquilateralTriangle as disjoint subclasses of Triangle, which reflects
a taxonomic, viz. extensional or database view. Expressions like A = B denote
integrity constraints.
What are the benefits and drawbacks of each view of the world?
The C++ view: The structurally most simple class, EquilateralTriangle, is
placed at the top of the hierarchy. Attribute A represents all three sides of
such triangles. RightTriangle and Triangle are put below as subclasses according
to their additional attributes B and C.
This approach is guided by implementational considerations interpreting ISA-
links as structural inheritance. But this contradicts intuition, since it does not
capture that in reality the sets of right and equilateral triangles are disjoint.
Moreover, it is not possible to reuse the implementations of query method Circum-
ference and of update method Scale in subclasses: Circumference is implemented
as {return 3∗A} in√ EquilateralTriangle, but in RightTriangle it must be redefined
to {return A+B+ A2 + B2 }, and in Triangle to {return A+B+C}. On the other
hand, we have a very frugal use of storage. For each class only those attributes
2
Which view of the triangle world?
EquilateralTriangle
A: double
Circumference: double
ResizeA(double)
Scale(double)
Triangle
A,B,C: double
Circumference: double RightTriangle
ResizeA(double) B: double
ResizeB(double)
ResizeC(double) ResizeB(double)
Scale(double)
Triangle
RightTriangle EquilateralTriangle C: double
{C = A2+ B2} {A = B, B = C} ResizeC(double)
are defined that are “necessary” from an implementational point of view. More-
over, it is not possible to use update methods in a way causing anomalies, that
is, the implementation hierarchy can be considered as subtyping relationship in
the sense of [LP91]. For instance, it is not possible to construct an equilateral
triangle with different side lengths.
The database view: A different kind of object-oriented modeling is strictly
based on class taxonomies that correspond to classification hierarchies ([ZM90])
with a set inclusion semantics among class extents. We will denote this kind of
modeling by taxonomic modeling.
The taxonomy at the left side of Figure 1 represents a view that has been ac-
cepted by non-programmers for at least 2000 years: right and equilateral triangles
are special triangles, and there are no triangles which are both right and equi-
lateral. Class Triangle possesses the same methods as in the C++ hierarchy.
These methods are inherited by subclasses RightTriangle and EquilateralTriangle,
which in addition are restricted by functional constraints. The method Circum-
ference of class Triangle—implementable as {return A+B+C}—can be reused by
all subclasses without modification; overriding is, of course, possible.
Clearly, taxonomic modeling has a lot of conceptual advantages. But as the
trend is to couple C++ with OODBS technology, a new kind of impedance mis-
match might arise if this is not handled carefully. Technically this gap is man-
ifested by the fact that the class model in C++ ([Str91]) has no notion of an
extension, it only caters for types (“object factory” view, [ABD+ 89]), whereas
3
on the OODBS side there is the notion of types and extensions (“object ware-
house” view). Characteristically though, this is not even unanimously agreed
upon within the OODBS community itself; e.g., Versant ([VER94]) supports the
strict taxonomic view, whereas ObjectStore ([OSt94]) offers extensions decou-
pled from types. Even the ODMG-93 proposal ([Cat94]) supports both classes
with or without extensions. Since, as a matter of fact, a great deal of OODBS
applications are or will be written by C++-programmers, the storage efficiency
argument behind the implementational view of data modeling must be defeated.
In other words, the conceptual advantages of taxonomic modeling in C++ based
OODBS have to be provided without storage penalties.
The rest of the paper is organized as follows. In Section 2 we will promote more
thoroughly the case for taxonomic modeling. Section 3 presents our automatic
storage optimization algorithm based on the functional constraints used in tax-
onomic modeling. Thereafter, Section 4 deals with inheritance and automatic
adaptation of update methods. Section 5 describes how taxonomic modeling can
be implemented on top of a C++ based OODBS. Finally, Section 6 summarizes
our results and outlines areas of future work.
2 Taxonomic Modeling
4
Physical data independence has proved successful in the relational data model
separating the logical and physical database organization. It is likewise important
for object-oriented view definition ([AB91]).
The kind of integrity constraints √
we concentrate on here are functional constraints
between attributes, (e.g., C = A2 + B2 ), which have to be inherited just as
attributes and methods, and are used by our storage optimizer. Different kinds
of integrity constraints for object-oriented models, such as range constraints,
enumeration constraints, relational constraints, have been proposed (see, e.g.
[BCV91]).
Example 2.1 (CAD modeling) The left part of Figure 2 shows a part of the
taxonomy of a CAD application, which models ellipse arcs and specializations
(update and many query methods are left out for shortnes, see Figure 3 for
parameters of ellipse arcs).
The classes NonRotatedEllipseArc, Ellipse, and CircleArc are specified by functional
constraints. Moreover, Ellipse has an additional query method Area which only
makes sense for “closed” arcs. This method is inherited by NonRotatedEllipse and
Circle, which are non-disjoint subclasses of EllipseArc. In addition, Circle has an
attribute Radius used as an alias for the two coinciding semi-axes.
This taxonomy as a natural model of the application domain promotes the reuse
of query and update methods; both method signatures and their implementations
can be reused (see methods ArcLength and Area). In some cases, however, it makes
sense to override inherited code; e.g., a complex and time consuming algorithm
is needed to implement ArcLength in class EllipseArc. Although this algorithm is
applicable to circle arcs as well, it should be overridden by the faster algorithm
{return 2 ∗ SemiMajorAxis ∗ π ∗ DeltaAngle} in class CircleArc.
The right part of Figure 2 depicts an implementation hierarchy for the CAD
classes introduced above. It was developed by an experienced C++ program-
mer as part of a large-scale CAD system. The main reason for this model is to
5
Taxonomic model C++ based model
EllipseArc
Center: Point
SemiMajorAxis: double Circle
SemiMinorAxis: double
StartAngle: double Center: Point
DeltaAngle: double Radius: double
RotateAngle: double Area: double
ArcLength: double ArcLength: double
Circle EllipseArc
Remark 2.2 Let us assume the following storage requirements: double requires
8 Byte, Point 16 Byte, and the OID 8 Byte. Then in the C++ based model of Fig-
ure 2 a Circle object occupies 32 Byte, in contrast to 72 Byte in the unoptimized
taxonomic model if all attributes were physically stored.
We will demonstrate subsequently that the same storage efficiency can be gained
automatically for the taxonomic model. The implementation hierarchy, however,
has several severe drawbacks, e.g.:
• Method Area is inherited, e.g., by CircleArc, which does not make any sense.
6
SemiMajorAxis
SemiMinorAxis StartAngle
RotateAngle
X Axis
DeltaAngle
3 Storage Optimization
7
Note that in implementation hierarchies only type constraints on method signa-
tures are inherited. The functional constraints needed for taxonomic modeling
are defined as follows.
Definition 3.2 (Functional Constraints) Let C be a class with attributes
A, let A, A1, . . . , An ∈ A be different attributes, and let fA be an n-ary function.
1. An equation fc ≡ A = fA (A1, . . . , An ) is called functional constraint (FC).
A is called head of fc (head(fc)), {A1, . . . , An } is the body of fc (body(fc)).
fA is called FC-function of fc (funct(fc)).
Let F be a set of FCs over A.
2. Let A, B ∈ A be two attributes. Then A directly depends on B, A ←d B, iff
there is an FC A = fA (X1 , B, X2 ) ∈ F , where X1 , X2 ⊆ A. The transitive
+
closure of this relation is denoted by ←d .
+
3. F is called acyclic, if ←d is an irreflexive partial ordering.
Note that FCs with an empty body (n = 0) cover constant constraints like
RotateAngle = 0.
8
2. Acomp := A \ Astore;
Proof
9
+
Fcomp ∪ {fc} is done by computing the transitive closure ←d successively. If
+
←d is represented by an n × n matrix, then adding one A ←d B to the current
closure and computing the resulting transitive dependencies can be done with
time complexity O(n2 ). Moreover, restoring the original transitive closure, in
case of a cycle, can be done by copying and has complexity O(n2 ), too. Thus,
the algorithm has a worst case complexity of O(m · n3).
+
2. Fcomp is by construction acyclic, hence ←d is an irreflexive and finite partial
+
ordering. We perform a Noether induction on ←d : by construction, for each
A ∈ A there is exactly one functional constraint A = fA (YA ) ∈ Fcomp . By
inductive hypothesis for all attributes B ∈ YA ∩ Acomp there exists a unique
computation function cB (XB ), XB ⊆ Astore. Then cA (XA ) of attribute A is
constructed from the FC-function fA and cB (XB ).
The computation functions will be used to compute the values of computed at-
tributes from the stored ones. They are constructed by the following recursive
algorithm:
Note that the recursion terminates since Fcomp is acyclic. Its worst case com-
plexity is polynomial. We demonstrate the storage optimization performed by
Algorithm 3.3 for two classes of Example 1.1.
A = {A, B, C},
F = {A = B, B = A, B = C, C = B} .
10
When the elements of F are ordered as above, then step 1 of Algorithm 3.3
computes Astore and Fcomp as follows:
2. Astore and Fcomp are not modified since insertion of B = A into Fcomp would
cause a cycle.
4. Astore and Fcomp are not modified since insertion of C = B into Fcomp would
cause a cycle.
In step 2 we get Acomp = {A, B}. The computation functions are constructed as
cA (C) = fA (fB (C)) = C and cB (C) = fB(C) = C by Algorithm 3.5.
Example 3.7 (CAD continued) For the CAD hierarchy of Figure 2, Algo-
rithm 3.3 yields the desired storage optimizations as well.
For class Circle, e.g., the attributes Center and Radius may be stored. Assuming
the prerequisites of Remark 2.2 a circle object of the storage-optimized taxonomy
consumes 32 Byte, and is thus as storage-efficient as the C++ based model!
11
4 Taxonomic Inheritance and Adaptation
In this section we focus on taxonomic inheritance of query and update methods
and on how to adapt update methods in order to enforce integrity w.r.t. the
functional constraints (cp. [STSW93, CFPT94]). It is essential to note that the
following discussions are independent of our storage optimization.
We assume that updates are performed by update methods only since the system
has to ensure the FCs by integrity checks.4 As a consequence no direct update
access to the attributes is possible.
12
for method overriding ([KA90]) is applied to u. Note that taxonomic modeling
entails a coexistence of both the contravariance rule for query methods and the
covariance rule for update methods, contrary to the broad discussion on this topic
for non-taxonomic modeling approaches (see e.g. [Sha94]).
Example 4.2 (Inheritance of Scale) Let update method Scale of class Triangle
be defined as:
Scale(K: double) begin A := K∗A; B := K∗B; C := K∗C; check() end
This method is, e.g., inherited by class EquilateralTriangle and rewritten to:
Scale(K: double) begin A := K∗A; B := K∗B; C := K∗C; check(A=B,B=C) end
It is a property of equilateral triangles that the integrity check of this method
will never fail.
13
3. u is called adaptable, iff DEP(u) = ADAPT(u).
DEP(u) denotes those attributes that must be modified because of the functional
dependencies between them and the update attributes Xu . ADAPT(u) con-
tains those attributes that can actually be adapted by means of the FCs. Both
DEP(u) and ADAPT(u) can be determined in polynomial time. As noted for the
storage optimization, more functional constraints imply the adaptibility of more
attributes. Adaptation functions aA are constructed by the following recursive
algorithm (with polynomial worst case complexity):
14
Then u defined as
update u(<parameters>) begin <body>; check(F ) end
is adapted as follows:
update u(<parameters>)
begin <body>; <A := aA (XA ), A ∈ DEP(u)>; check(F ) end
The update method is rewritten in such a way that all attributes depending on
the updated attributes are consistently modified, too.
ResizeC(K: double)
begin C := K+C; /* original body */
B := C; A := C; /* adaptation of dependent attributes */
check(A=B,B=C)
end
The adapted method resizes all three sides of the equilateral triangle.
15
C++ source program
with embedded ODL/OML
preprocessor
database
executable application
methods, update methods (that are already adapted according to Section 4), and
create methods do:
1. Astore and Acomp are computed by Algorithm 3.3. For all attributes A ∈ Astore
the computation functions cA are constructed by Algorithm 3.5.
2. Two classes are defined: an abstract class C (without extent) and a leaf class
Cext as a direct subclass of C.
3. For each non-inherited but newly defined attribute A ∈ A two virtual member
functions get A() and set A(x) are declared in class C.
5. For each attribute A ∈ Astore in Cext , get A() is overridden by a read access
to store A, and for each A ∈ Acomp, get A() in Cext is overridden by a call of
computation function cA .
6. For each A ∈ Astore, set A(x) is overridden in Cext by writing value x to store A.
16
8. For each update method defined in C a virtual member function is declared
in C.
10. For each create method defined in class C a constructor is defined in class Cext
as follows: For each A ∈ A, the declaration of a (not initialized) local variable
A is inserted in front of the method body. After the constraint check on the
local variables succeeds, set A(A) is called for A ∈ Astore.
ResizeC(K: double)
begin var A: double = get A(),
B: double = get B(),
C: double = get C();
C := K+C; B := C; A := C;
check(A=B,B=C);
set C(C)
end
17
Triangle_Ext Triangle
store_A, store_B, store_C virtual get_A(), get_B(), get_C()
get_A(), get_B(), get_C() virtual set_A(x), set_B(x), set_C(x)
set_A(x), set_B(x), set_C(x) Circumference()
ResizeA(K) virtual ResizeA(K)
ResizeB(K) virtual ResizeB(K)
ResizeC(K) virtual ResizeC(K)
Scale(K) virtual Scale(K)
RightTriangle EquilateralTriangle
RightTriangle_Ext EquilateralTriangle_Ext
store_A, store_B store_C
get_A(), get_B(), get_C() get_A(), get_B(), get_C()
set_A(x), set_B(x) set_C(x)
ResizeA(K) ResizeA(K)
ResizeB(K) ResizeB(K)
ResizeC(K) ResizeC(K)
Scale(K) Scale(K)
18
method inheritance.
For rapid availability of taxonomic modeling within a C++-based OODBS we
have shown how to write a preprocessor integrated into the C++-environment
of ODMG. To promote taxonomic modeling on a larger scale, however, requires
the extension of the ODMG object model by functional constraints, and towards
more general integrity constraints beyond. Currently we are also investigating the
extension of OODBS by more powerful taxonomical constraints, even including
probabilistic constraints ([KLKG94]). In summary, we think that taxonomic
modeling has a broad range of applicability. In addition to the CAD domain
covered here we expect great benefits in the domains of CASE and multimedia
databases, where complex and large class attributes demand a natural semantic
modeling in combination with a good storage optimization.
Acknowledgment: We like to thank Felix Dutkowski, civil engineer from Nemetschek
Programmsystem GmbH, for providing us with insights into the mentality of C++
programmers as part of the OCAD project.5 Likewise we thank Jutta Seidel, chief
architect from U.T.M. Ingenieurgesellschaft für Hochbau GmbH, Regensburg,
for insights into architectural CAD applications. Furthermore, we thank Hans
Kempe and Robert Hitzelberger from FORWISS for fruitful discussions and Ver-
sant support.
5
“OCAD: Object-Oriented Databases and CAD” is a joint project of Nemetschek Programm-
system GmbH, Munich (a large CAD tool manufacturer in Europe) and the Bavarian Research
Center for Knowledge-Based Systems (FORWISS) under the direction of W. Kießling.
19
References
[AB91] S. Abiteboul and A. Bonner. Objects and views. In Proc. ACM SIGMOD
Conf., pages 238–247, Denver, CO, May 1991.
[BCV91] A.P. Buchmann, R.S. Carrera, and M.A. Vazquez-Galindo. Handling con-
straints and their exceptions: An attached constraint handler for object-
oriented CAD databases. In Dittrich, Dayal, and Buchmann, editors,
Object-Oriented Database Systems, chapter II 6., pages 65–86. Springer,
Berlin, 1991.
[Cat94] R.G.G. Cattel, editor. The Object Database Standard: ODMG–93. Morgan
Kaufmann Publishers, San Mateo, California, 1994.
[GSUW94] A. Gupta, Y. Sagiv, J.D. Ullman, and J. Widom. Constraint checking with
partial information. In Proc. ACM SIGACT-SIGMOD-SIGART Symp. on
Principles of Database Systems., pages 45–55, Minneapolis, 1994.
20
[LS91] J.A. Larson and A.S. Sheth. Updating relational views using knowledge at
view definition and view update time. Inf. Sys., 16(2):145–168, 1991.
[MP92] D.E. Monarchi and G.I. Puhr. A research typology for object-oriented
analysis and design. Communications of the ACM, 35(9):35–47, September
1992.
[OSt94] ObjectStore technical overview, release 3.0. Object Design Inc., One New
England Executive Park, Burlington, 01803, 1994.
[VER94] System manual, release 3.0. Versant Object Technology Corporation, Park,
CA 94025, 1994.
[Wil91] M.J. Willshire. How spacey can they get? Space overhead for storage and
indexing with object-oriented databases. In Proc. IEEE Conf. on Data
Eng., pages 14–22, Kobe, Japan, Apr. 1991.
21
Appendix A
// Triangle.h
//===============================================================
// Standard includes
//===============================================================
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <iostream.h>
//===============================================================
// Triangle Taxonomy
//===============================================================
//---------------------------------------------------------------
// class Triangle
//---------------------------------------------------------------
create:
Triangle(double a, double b, double c) {A=a; B=b; C=c};
query:
double circumference();
virtual void print();
22
update:
void ResizeA(double K);
void ResizeB(double K);
void ResizeC(double K);
};
//---------------------------------------------------------------
// class RightTriangle
//---------------------------------------------------------------
query:
void print(); // override print
constraints:
C=sqrt(A*A+B*B)
};
//---------------------------------------------------------------
// class EquilateralTriangle
//---------------------------------------------------------------
query:
void print(); // override print
constraints:
A=B, B=C
};
23
// Triangle.C
#include "Triangle.h"
//===============================================================
// Definition of query methods
//===============================================================
double Triangle::circumference()
{return A + B + C;};
void Triangle::print()
{cout <<"Triangle: "<<A<<" "<<B<<" "<<C<<"\n";}
void RightTriangle::print()
{cout <<"RightTriangle: "<<A<<" "<<B<<" "<<C<<"\n";}
void EquilateralTriangle::print()
{cout <<"EquilateralTriangle: "<<A<<" "<<B<<" "<<C<<"\n";}
//===============================================================
// Definition of update methods
//===============================================================
24
A.2 Versant C++ Code of the Triangle Taxonomy
The triangle taxonomy is transformed into Versant C++ code ([VER94]) by
means of Algorithm 5.1. For the sake of simplicity, update method aborting is
realized by doing nothing but printing a warning message.
// Triangle.transform.h
//===============================================================
// Versant includes
//===============================================================
#include <cxxcls/pobject.h>
#include <cxxcls/vstring.h>
#include <cxxcls/vlist.h>
//===============================================================
// Standard includes
//===============================================================
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <iostream.h>
//===============================================================
// Triangle Taxonomy
//===============================================================
//---------------------------------------------------------------
// class Triangle
//---------------------------------------------------------------
25
virtual void set_A(double X) = 0;
virtual void set_B(double X) = 0;
virtual void set_C(double X) = 0;
double circumference();
virtual void print() = 0;
public:
virtual ~Triangle_Ext(); // needed by Versant
Triangle_Ext(double a, double b, double c)
{double A; double B; double C;
A=a; B=b; C=c;
set_A(A); set_B(B); set_C(C);};
void print();
26
//---------------------------------------------------------------
// class RightTriangle
//---------------------------------------------------------------
public:
virtual ~RightTriangle_Ext(); // needed by Versant
RightTriangle_Ext(double a, double b)
{double A; double B; double C;
A=a; B=b; C=sqrt(a*a+b*b);
if (C=sqrt(A*A+B*B))
{set_A(A); set_B(B);}
else
{cout << "RightTriangle Warning: create failed\n";};
};
void print();
27
//---------------------------------------------------------------
// class EquilateralTriangle
//---------------------------------------------------------------
public:
virtual ~EquilateralTriangle_Ext(); // needed by Versant
EquilateralTriangle_Ext(double a)
{double A; double B; double C;
A=a; B=a; C=a;
if ((A=B) && (B=C))
{set_C(C);}
else
{cout << "EquilateralTriangle Warning: create failed\n";};
};
void print();
#endif
28
// Triangle.transform.C
#include "Triangle.transform.h"
//===============================================================
// Versant specific definitions
//===============================================================
Implement PClassObj<Triangle>;
Implement PClassObj<RightTriangle>;
Implement PClassObj<EquilateralTriangle>;
Implement PClassObj<Triangle_Ext>;
Implement PClassObj<RightTriangle_Ext>;
Implement PClassObj<EquilateralTriangle_Ext>;
Triangle::~Triangle(){};
Triangle_Ext::~Triangle_Ext(){};
RightTriangle::~RightTriangle(){};
RightTriangle_Ext::~RightTriangle_Ext(){};
EquilateralTriangle::~EquilateralTriangle(){};
EquilateralTriangle_Ext::~EquilateralTriangle_Ext(){};
//===============================================================
// Definition of query methods
//===============================================================
double Triangle::circumference()
{return get_A() + get_B() + get_C();};
void Triangle_Ext::print()
{cout <<"Triangle: "
<<get_A()<<" "<<get_B()<<" "<<get_C()<<"\n";}
void RightTriangle_Ext::print()
{cout <<"RightTriangle: "
<<get_A()<<" "<<get_B()<<" "<<get_C()<<"\n";}
void EquilateralTriangle_Ext::print()
{cout <<"EquilateralTriangle: "
<<get_A()<<" "<<get_B()<<" "<<get_C()<<"\n";}
29
//===============================================================
// Definition of adapted update methods
//===============================================================
void Triangle_Ext::ResizeA(double K)
{double A = get_A(); A = A + K; set_A(A);};
void Triangle_Ext::ResizeB(double K)
{double B = get_B(); B = B + K; set_B(B);};
void Triangle_Ext::ResizeC(double K)
{double C = get_C(); C = C + K; set_C(C);};
void RightTriangle_Ext::ResizeA(double K)
{cout << "RightTriangle Warning: ResizeA not adaptable\n";};
void RightTriangle_Ext::ResizeB(double K)
{cout << "RightTriangle Warning: ResizeB not adaptable\n";};
void RightTriangle_Ext::ResizeC(double K)
{cout << "RightTriangle Warning: ResizeC not adaptable\n";};
void EquilateralTriangle_Ext::ResizeA(double K)
{double A = get_A(); double B = get_B(); double C = get_C();
A = A+K; B = A; C = A;
if ((A=B) && (B=C))
{set_C(C);}
else
{cout << "EquilateralTriangle Warning: ResizeA failed\n";};
};
void EquilateralTriangle_Ext::ResizeB(double K)
{double A = get_A(); double B = get_B(); double C = get_C();
B = B+K; A = B; C = B;
if ((A=B) && (B=C))
{set_C(C);}
else
{cout << "EquilateralTriangle Warning: ResizeB failed\n";};
};
void EquilateralTriangle_Ext::ResizeC(double K)
{double A = get_A(); double B = get_B(); double C = get_C();
C = C+K; A = C; B = C;
if ((A=B) && (B=C))
{set_C(C);}
else
{cout << "EquilateralTriangle Warning: ResizeC failed\n";};
};
30
A.3 Two Simple Applications
Let us give two simple applications of the triangle taxonomy. The first one inserts
three new triangle objects into the database and prints the database content.
// InsertTriangle.C
// insert three new triangle objects into the class
#include "Triangle.h"
#define DBNAME "TriangleDB" //database used
#define SESSION "TriDB"
main()
{
::dom = new PDOM;
::dom->beginsession(DBNAME,SESSION);
::dom->commit();
::dom->exit(0);
}
31
The second application calls ResizeC(10) for each triangle object in the database
and prints the updated database content.
// UpdateTriangle.C
// call ResizeC(10) for each triangle in the database
#include "Triangle.h"
main()
{
::dom = new PDOM;
::dom->beginsession(DBNAME,SESSION);
::dom->commit();
::dom->exit(0);
}
32
A.4 Versant C++ Code of the Applications
The applications are transformed as well. The modifications are, however, very
simple. Thus, the user can easily interpret compiler error messages of the trans-
formed code.
// InsertTriangle.transform.C
// insert three new triangle objects into the class
main()
{
::dom = new PDOM;
::dom->beginsession(DBNAME,SESSION);
::dom->commit();
::dom->exit(0);
}
33
// UpdateTriangle.transform.C
// call ResizeC(10) for each triangle in the database
main()
{
::dom = new PDOM;
::dom->beginsession(DBNAME,SESSION);
::dom->commit();
::dom->exit(0);
}
34