2-2UML - Department of Computer Science

advertisement
OBJECT MODELS,
CONSTRAINTS, AND PROLOG
UML2-1
More than Class Diagrams
• Often you need to show instances of models
• use object diagrams or database tables
• You need constraints, when class diagrams are insufficient and they almost always are
• Object Constraint Language (OCL) is the proposed standard
• I don’t like it – few do
• I use Prolog instead – why?
» it is a fundamental language in CS, not one that is hacked
» it is declarative also like OCL
» you can learn OCL when you need to – a small subset of Prolog
is sufficient for our use
UML2-2
when we want to see more…
OBJECT MODELS
UML2-3
Object Models
• Object Models are are instances of class diagrams
• Nodes are individual objects and links are relationships. Ex:
e1 : Employee
age : Integer = 33
d1 : Department
minAge : Integer = 30
e2 : Employee
Employee
*
1
+age : Integer
Department
+minAge : Integer
-employs
-worksIn
Class Diagram
ED
age : Integer = 35
e3 : Employee
age : Integer = 54
e4 : Employee
d2 : Department
age : Integer = 24
minAge : Integer = 20
e5 : Employee
age : Integer = 29
Object Model that conforms
to class diagram ED
• An Object Model shows instance, type, attribute information
• There are LOTS of different kinds of object models
you’ll see
UML2-4
Class Diagram → Schema Mapping
• Schema – set of table definitions
• 1 table per UML class
• 1 row per table for each object
• 1 column per attribute
• 1 extra column (#) for internal identifier
this is where a
wee bit of databases
would help you
• Each association is encoded by a 1 or 0..1 attribute
• name is role name
• no set valued attributes
• For each class, the number of columns =
1 for object identifier + number of attributes listed
+ 1 for every 1 or 0..1 association end of the class
Employee
*
1
Department
+minAge : Integer
+age : Integer
-employs
-worksIn
# of columns/table?
UML2-5
Example
Employee
*
1
+age : Integer
+minAge : Integer
-employs
Employee
Employee#
Department
-worksIn
Department
age
worksin
Department#
minAge
of type
Department#
• Remember: each association turns into a single attribute of a 1 or 0..1 end
• This works because each association is a 2-way inverse relationship. One attribute
is sufficient. The “Remember” rule eliminates redundancy
UML2-6
Object Models Encoded as Tables
Department Table
e1 : Employee
age : Integer = 33
d1 : Department
#
minAge
d1
30
minAge : Integer = 30
e2 : Employee
age : Integer = 35
Employee Table
e3 : Employee
age : Integer = 54
#
age
worksIn
e1
33
d1
e2
35
d1
e3
54
d1
UML2-7
Database Tables
for those of you who are database savvy
• Use normalized Relational Tables – they don’t have set-valued attributes
• Null values are OK a null is a scalar!
So instead of:
Employee Objects
Employee Table
#
age
worksIn
#
age
worksIn
e1
33
d1
e1
33
d1
e2
35
d1
e2
35
d1
e3
54
d1
e3
54
d1
columns for both ends of
an association
Department Objects
database
tables
Q: why does this xform
lose no info?
Department Table
#
minAge
employs
#
minAge
d1
30
{e1, e2, e3}
d1
30
UML2-8
Here’s the Rule (Reason):
or
UML2-9
What Does This Require?
• All associations must be of the form 1. . š‘› or (0 − 1). . š‘›, never ∗. .∗
• This is where the association class transformation rewrite is used
• Recall this slide from the last lecture:
Association Classes
•
Links can have an attached class
called an Association Class
•
Gives association “attributes” and
“methods”
•
Above diagram can be transformed
to the equivalent diagram below
•
Hint: always use the bottom
notation, never the top
*
Student
*
Course
Enroll
+student : Student
+course : Course
Student
Course
1
1
Enroll
*
*
UML1-34
UML2-10
Example #1
• Instead of:
Student
Student
Course
*
…
*
Student#
…
1
*
Enroll#
s1
{c1,c2}
s2
{c2}
…
Enroll
1
*
Student#
Course#
Course
Enroll#
c1
{s1}
c2
{s1,s2}
s1
equivalent
s2
but always use
right side as
the answer
Enroll#
Student#
Course#
e1
s1
c1
e2
s1
c2
e3
s2
c2
Course#
…
c1
c2
UML2-11
Example #2
• Start with:
ParentOrGuardian
Child
2..*
1..*
rewrite to
• Rewrite to:
PersonOrGuardian
• Now create tables
Child
1
1
Assoc
2..*
1..*
UML2-12
Inheritance in Tables
• Lots of ways: here is the simplest
• Create a table for each non-abstract class
• Objects that belong only to that class are listed as rows;
infer objects rows that belong to subclasses, just as in Java
crewman
crewman
-fname
-lname
commander
commander
-rank
lieutenant
-specialty
lieutenant
#
fname
lname
c1
mr
spock
#
fname
lname
rank
c2
james
kirk
captain
c3
christopher
pike
captain
#
fname
lname
specialty
c4
hikaru
sulu
navigation
c5
leonard
mccoy
physician
UML2-13
ocl and prolog
CONSTRAINTS
UML2-14
Consider the Model
Person
-ownedByPerson
-owns
-name : String
Kontract
-owns
-ownedByCompany
-value : Integer
0..1
*
Company
-name : String
*
0..1
• A kontract must be owned by a person or by a company BUT NOT BOTH
• Further: the value of a kontract depends on the owner:
• if Company has kontract: value > 500K
• if Person has kontract: value < 100K
• How can these constraints be expressed?
UML2-15
Could Rewrite Original Diagram
• To use an abstract class to solve only the ownerkontract problem
• that’s not so good because the diagram is
more complex
• Still cannot express constraints on values without
diagram distortion – for just a few constraints –
imagine what would happen if there are lots of
constraints!
Kontract
-value : Integer
-owns
*
-ownedBy
1
KontractOwner
Person
Company
• This isn’t the right way to go…
UML2-16
Constraints!
• When UML diagrams are insufficient they almost always are write constraints
• Formal languages are hard for typical programmers to use and understand
• So the Object Constraint Language (OCL) was invented to make constraints hard
for everyone to write and understand ļŠ
• note the intent of the designers, but…
• Lessons from databases were not learned. OCL is very much tied to the navigability
of the class structure. This forces you as a designer to write your OCL constraints in
terms of navigability. Database people learned decades ago this was a bad idea
• Tools are inconsistent
although there are “standards”
and may even be useable
UML2-17
Forget OCL! Use Prolog!
• OCL is an engineer-crafted functional language
• declarative
• documentation is awful
• implementations are worse
• language is to me a hack
• Prolog solved a similar problem long ago
• declarative
• documentation is decent
• implementations are very good
• language is fundamental to Computer Science
UML2-18
need a language to write constraints – use prolog!
TUTORIAL ON PROLOG
UML2-19
Prolog Atoms
• Very popular in 1980s – has evolved to datalog in database area for dealing with
large fact bases
• Excellent for reasoning; awful at complex input-output or string manipulation
• Atom – lowercase name, single-quoted text, or a number
• also can be double-quoted text, which we won’t use
batory
‘batory’
45
3.52
Note: unquoted atom and quoted
atom are different
equal(batory, ‘batory’) is false!
Note: unquoted names MUST begin with
a lowercase letter!!!!
UML2-20
Prolog Lists – Likely Won’t Need
• Lists are one of the two basic data structures in Prolog
[ a, b, c, d, e, f ]
• Typically, you want to design your program with lists of atoms that are of the same
type – lowercase names, single-quoted strings, or numbers:
[ ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ ]
[ 1, 2, 3, 4, 5, 6 ]
• Prolog is an untyped language, so you can have lists of lists, lists of a mixture of
atoms, etc. By programming discipline, you enforce lists of atoms of the same type
• Very likely you will won’t use lists at all as this is where Prolog becomes complex
UML2-21
Prolog Tuples
• Other basic data structure in Prolog is tuple – this is how Prolog represents facts
• Here is how we will represent tables in Prolog:
a tuple defining the schema of the table, followed by the tuples of the table
parent
father
child
a0
a1
a1
a2
a2
a3
a2
a4
list
table(parent,[father,child]).
equivalent
parent(a0,a1).
parent(a1,a2).
parent(a2,a3).
parent(a2,a4).
1st line declares parent table always starts with a LOWER-CASE letter! with
list of 2 attributes: father and child – both attributes are atomic names
next 4 lines are rows of a table – all facts end in period (.)
UML2-22
Prolog Queries
• Uses pattern matching – unbound variables to be matched are UPPERCASE
• Query: Who are the children of a2?
?- parent(a2,C).
• Query: Who are the parents of a2?
?- parent(P,a2).
UML2-23
Prolog Rules
• Based on unification pattern matching – free or unbound variables are names starting
with UPPER case to distinguish them from atomic values
• Rules of the form HEAD :- BODY.
See wikibooks
click here
% parent(X,Y)
– X is a parent of Y
% descendant(X,Y) - a descendant of X is Y
% ancestor(X,Y)
- an ancestor of X is Y
“,” = and
descendant(X,Y) :- parent(X,Y).
descendant(X,Y) :- parent(X,Z),descendant(Z,Y).
ancestor(X,Y) :- descendant(Y,X).
UML2-24
Prolog Rule Execution
• Match the initial definition first, if it fails, go to the next definition, until no definition
exists, at which point, failure execution halt occurs
% a descendant of X is Y; X is a parent of Y
table(parent,[father,child]).
descendant(X,Y) :- parent(X,Y).
descendant(X,Y) :- parent(X,Z),descendant(Z,Y).
parent(a0,a1).
parent(a1,a2).
parent(a2,a3).
parent(a2,a4).
ancestor(X,Y) :- descendant(Y,X).
descendant(a2,Y) succeeds
with Y=a3,a4. go onto next rule
• Try this:
descendant(a2,Y).
a3
a0
a1
a2
descendant(a2,Y) succeeds
with parent(a2,Z) Z=a3,a4
descendant(a3,Y) fails
descendant(a4,Y) fails
go onto next rule
a4
no more rules – done!
UML2-25
Prolog Rule Execution
• I use SWI-Prolog – works on Windows and Mac OS X platforms, even Eclipse
• Watch Video:
UML2-26
BACK TO UML
CONSTRAINTS
UML2-27
Example Database in Prolog
-ownedByPerson
Person
-owns
-name : String
Kontract
-owns
-ownedByCompany
-value : Integer
0..1
p#
name
p1
Batory
p2
Lin
p3
Browne
k#
value
c#
k1
740
c1
k2
220
k3
330
k4
47
*
p#
p2
c1
Ace Plumbing
c2
Rudys BBQ
c4
Os Cafeteria
*
0..1
table(company,[cid,"name"]).
table(kontract,[kid,value,cid,pid]).
table(person,[pid,"name"]).
c2
name
-name : String
kontract.pl
p1
c#
Company
equivalent
person(p1,'Batory').
person(p2,'Lin').
person(p3,'Browne').
kontract(k1,740,c1,null).
kontract(k2,220,null,p1).
kontract(k3,330,c2,null).
kontract(k4,47,null,p2).
company(c1,'Ace Plumbing').
company(c2,'Rudys BBQ').
company(c4,'Os Cafeteria')
UML2-28
Watch Video
• Facts or rules always start with a lowercase letter: kontract, person, company
• Unbound variables always start with an uppercase letter: Company, Person
• Type <space> after each binding to get the next binding
UML2-29
Prolog Constraints
• A kontract must be
owned by a person or
by a company,
NOT BOTH
• If Company has
kontract: value > 500K
• If Person has kontract:
value < 100K
% kontract constraint – precisely 1 is nonnull
one(C,P):- C==null, not(P==null).
one(C,P):- not(C==null), P==null.
kontractConstraint :forall(kontract(_,_,C,P),one(C,P)).
% company constraint
companyConstraint :forall(kontract(_,V,C,null),cc(V,C)).
cc(V,C) :- V>500,company(C,_).
% person constraint
personConstraint :forall(kontract(_,V,null,P),pc(V,P)).
pc(V,P) :- V<100,person(P,_).
run:-companyConstraint,
personConstraint,
kontractConstraint.
question: is there a better kontract constraint?
UML2-30
Or A More Compact Way
• A kontract must be
owned by a person or
by a company, NOT
BOTH
% all 3 constraints
• If Company has
kontract: value > 500K
run:-all3Constraints.
all3(V,C,P):-V>500,not(C==null),P==null,company(C,_).
all3(V,C,P):-V<100,not(P==null),C==null,person(P,_).
all3Constraints:forall(kontract(_,V,C,P),all3(V,C,P)).
• If Person has kontract:
value < 100K
UML2-31
Watch Video
• Prolog hints:
• When you build your constraints, always test them individually
k#
value
c#
k1
740
c1
k2
220
k3
330
k4
47
p#
p1
c2
p2
UML2-32
constraint violations tell us nothing
ERROR MESSAGES SUCK
SOMETHING AWFUL…
UML2-33
Want Better Error Messages
• Identify rows of tables that are offensive
• Simple fix – add extra rules
isError(S,N) :- tell(user_error),write(S),writeln(N),told.
% kontract database constraints
% kontract constraint
notBoth(_,C,P) :- C==null,not(P==null),person(P,_).
notBoth(_,C,P) :- not(C==null),P==null,company(C,_).
notBoth(K,_,_) :- isError('kontract fails constraint ',K).
kontractConstraint :- forall(kontract(K,_,C,P),notBoth(K,C,P)).
% company constraint
companyConstraint :- forall(kontract(K,V,C,null),cc(K,V,C)).
cc(_,V,C) :- company(C,_),V>500.
cc(K,_,_) :- isError('company fails kontract constraint ',K).
% person constraint
% virtually same as company constraint
run :- kontractConstraint, companyConstraint, personConstraint.
UML2-34
Beware!
• Try to write your constraints in the form:
foreach( findAnError(X), isError(‘violation ’,X)).
• where findAnError(X) defines a predicate that binds to an error X
• Do NOT write constraints as:
foreach( tuple(X), checkError(X) ).
checkError(X) :- ErrorCondition(X),
IsError(‘violation ‘,X)).
• Why?: if checkError fails just once, foreach stops and fails.
Make sure you understand this!
UML2-35
Watch Video
• Better error reporting
UML2-36
PERSPECTIVES
UML2-37
OCL
as of today
is Likely Insufficient
• Suppose we define a UML model whose instances are rings of 3Ī‡k nodes (kļ‚³1)
1
Node
-next
1
conforms
ļƒ˜ conforms
• I have no idea on how to write this constraint and many others in OCL
• may need to add more “basic” operations to OCL
• OCL cannot update values – it is a read-only language
• need a Turing-complete language like Prolog, perhaps?
• Solving this problem took me hours because I didn’t know prolog very well
The solution is simple – but you have to work hard at it to make it so
UML2-38
Even Simpler Example
richEmployee
-Salary : Integer
reConstraint:-forall(richEmployee(_,S),S>500).
• A richEmployee has a salary in excess of 500K
• Can not check this constraint statically
• Must check it at run-time, but when…?
– at epochs – points in time when consistency must be guaranteed
– in MDE, you create an instance of a model by drag and drop like Visio
You then push a “validate” button that tells you if the instance satisfies
constraints
UML2-39
Recap
• Almost all class diagrams need constraints
• to eliminate incorrect or unwanted instances
• Standard today is to use Object Constraint Language (OCL)
• I prefer Prolog
• Why?
• represent object models as database tables
• Prolog was designed with tables in mind
• Prolog can also be used to map databases to other databases
which we won’t cover in this class
UML2-40
Download