480 likes | 492 Views
Explore a new paradigm focusing on data access in object-oriented programming, bridging the gap between data and OOP principles. Learn about serialization, impedance mismatch, and more concepts vital for modern software development.
E N D
Q: How to create this output? <Stack> <Stack_-Entry obj-name="head" data="Macchiato"> <Stack_-Entry obj-name="next" data="Cappuccino"> <Stack_-Entry obj-name="next" data="Latte"> <null obj-name="next"/> </Stack_-Entry> </Stack_-Entry> </Stack_-Entry> </Stack>
Stack stack = new Stack(); stack.push("Latte"); stack.push("Cappuccino"); stack.push("Macchiato"); new JSX.ObjOut().writeObject(stack); class Stack { private Entry head; private static class Entry { String data; Entry next; } } // push() inserts at head (omitted)
Orthogonal Data Access A new paradigm for object oriented programming
Goals • To import/export data from programs • Simple • Ease of use • Correctness • To test out these ideas on you – comments are most welcome • Generalizing from • Java programming language • XML exchange format
Overview • Part I: Data Access • Importance of data access • OOP • Part II: Instance Evolution • Part III: Back-compatibility • Part IV: Apply to Java
Part I: Data Access • Data is important • Data is the focus of most real-world applications • Oracle made $10.8 billion in bad times
Reasons to access data Export/import data: • Persistence • Communication • across space • across language • across module or subsystem • Data processing • Data input/output
Databases & Data Access • Databases provide data access • For data-processing • For communication between components • For communication between programming languages • To switch operating systems & hardware • Databases provide persistence • CLAIM: not the primary use of databases!
Impedance mismatch problem • Database problem: impedance mismatch • Need to map data between programming languages and the database
Program Environment Database schema store object Database problem
Impedance mismatch • Solutions to impedance mismatch • Object Oriented Databases • O/R mapping • Persistent Programming Languages • O/R is a band-aid solution • OODB and PPL aim at providing persistence, but import/export of data as a secondary goal
Program Environment store object PPL solution
PPL & data access • By getting rid of the schema, PPL also lose the ability to provide data access • The mapping layer is important
Program Environment A Program Environment B object object Distributed computing - RPC
Distributed computing • CORBA and SOAP provide cross-language compatibility • The focus is communication, not persistence • The data is not long-lived, and so evolution is not a primary concern • RPC use marshalling to export/import data – a form of serialization
Serialization example class BankAccount { String name; int accountNumber; int balance; } <?jsx version="1"?> <BankAccount name=“Arthur Weasley" accountNumber="11223344" balance="20000"/>
Program Environment store object object schema schema Serialization
Serialization • Serializing an object graph represents it as a stream of data, which can be deserialized to form a copy of the graph, that could replace the original • It preserves structure • The stream can be saved as a file, transmitted over the network or inspected/manipulated in memory.
Ways of accessing data • Databases, Object DB, O/R mapping • Persistent Programming Languages • RPC: CORBA, SOAP, web services Serialization can be used for all the above
Data Access & OOP • Wait! Doesn’t serialization break the data hiding of objects? • Data is important • But OOP hides data • Orthogonal data access resolves this
OOP and data • Object oriented programming focuses on the behaviour of objects, rather than their state (or data) • This is at odds with the predominate use of computers for dealing with data • Thus, we focus on object state (instances, values), rather than object code
Serialization • Serialization directly accesses the fields of objects, to automatically construct a file format or wire protocol • Must this break encapsulation?
OOP and data hiding • “object oriented = data abstractions + object types + type inheritance” • “It supports objects that are data abstractions with an interface of named operations and a hidden local state.” • Cardelli & Wegner, ACM Survey, 1985
“On the Criteria to Be Used in Decomposing Systems into Modules” • Back to the source: Parnas paper -> ADT -> OO • OO hides data, for modularity • Managerial: Divide the task up • Flexibility: can change modules independently • Comprehensibility: one module at a time • But it only needs to hide information about the implementation of the data to accomplish these aims
Objects • Object = code + data • “Information hiding” is thought to mean to hide the fields of objects, and only allow access through methods (behaviour) • But access to state is still needed: hence, getter and setter methods • But the real purpose is to hide information about the implementation
Expose “data implementation” <Stack> <Stack_-Entry obj-name="head" data="Macchiato"> <Stack_-Entry obj-name="next" data="Cappuccino"> <Stack_-Entry obj-name="next" data="Latte"> <null obj-name="next"/> </Stack_-Entry> </Stack_-Entry> </Stack_-Entry> </Stack>
Hide “data implementation” <Stack_-Memento> <ArrayOf-java.lang.String obj-name="array" length="3"> <java.lang.String valueOf="Macchiato"/> <java.lang.String valueOf="Cappuccino"/> <java.lang.String valueOf="Latte"/> </ArrayOf-java.lang.String> </Stack_-Memento>
Hide “data implementation” private static class Memento { String[] array; private Memento(Stack s) { array = new String[size]; int i = 0; for (Entry e=s.head; e!=null; e=e.next) array[i++] = e.data; } }
Hide “data implementation” private Object writeReplace() throws ObjectStreamException { return new Memento(this); }
Mapping local to the object • Evolution is necessarily tightly coupled with implementation, so that is where the mapping should be • We map from the object’s internal representation, into a “memento”, which is the object’s external representation • Internal representation is implementation • External representation is interface
Does this break encapsulation? • “Information hiding” means (1). data hiding? (2). implementation hiding? • SUBMIT: (2), as this gives the benefits of its raison d'être (Parnas) • It transcends encapsulation
The way was lost… • The real issue is not behaviour vs state, but implementation vs interface • The problem with automatic serialization is not that it records state, but that it records it in terms of the implementation of that state – it should hide this information • We can solve this with a layer, to structure access to state
Memento • The idea is simple • A data object to represent the state of another object • This allows the implementation to evolve, without affecting the interface • …but what if the implementation evolves to augment or diminish its capacity?
Part II: Evolution • Evolution is important • Implementation vs. interface evolution • Evolution of implementation should be local • Forward vs backward propagation of instances • Evolution of interface should be extendable
Context in literature • Instance evolution (not schema/type/class evolution) – Banerjee • Within class evolution (not inheritance or class) – Banerjee • Filtering/screening (not conversion) - Casais
Evolution • Evolution • Implementation evolution • Interface evolution (of external representation) • Terminology • In Databases – “schema evolution” • In Object databases - “class evolution” • In RPC – “type/class evolution” • In PPL – “type/class evolution”
Part III: Back-compatibility • Forward propagation • old -> new (we can read the old version) • Backward propagation • old <- new (we can write to the old version)
Read/write self. Where the interface never changes. Read/write self, and read old. Back compatible read (eg persistence) Read/write self, and write old. Back compatible write(eg publish to old clients) Read/write self, and read/write old. Bi-directional compatibility.
Partial versioning (Roddick survey) • can read old and new, but only write new • Full versioning (Roddick survey) • Can write both old and new versions • Backward and forward compatibility – Monk • Dynamic instance conversion
Back-compatibility • Extending schema • Use inheritance to explicitly extend • We exploit the inheritance of fields/attributes • The semantics work for back-compatibility • The semantics are familiar to developers • CLAIM: using inheritance for back-compatible evolution is novel
Inheritance for back compatibility • Where the evolution is capacity augmenting (or additive), we can “extend” the Memento, and provide a backchain to update and backdate • In the Java data model, inheritance is always additive
Part IV: Apply to Java • Java is • strongly typed • robust • high-level • object oriented • but its evolution mechanisms for serialization are not
Evolution Mechanisms • Custom serial format (write/readObject) • Untyped, unparsed, not named, cannot retrofit • Serializable Field API (Put/GetField) • Runtime type-checking, parsed, named, can retrofit • Memento (writeReplace/readResolve) • Static typing, parsed, named, can retrofit (JSX) + version naming, encapsulation
Memento – external type • The Memento idea is simple • A data object to represent the state of another object • This is an external type, to represent the state (or data) of an internal type
Memento Summary • Memento – external type • Name of the Memento is a version name • Extending a Memento gives back-compatibility semantics (as for method interfaces), for bi-directional instance propagation • Compile-time type checking • Able to retrofit (in JSX) • CLAIM: back-compatible Memento is new
Orthogonal Data Access A new paradigm for object oriented programming?
Goals – comments, please • To import/export data from programs • Simple • Ease of use • Correctness • To test out these ideas on you – comments are most welcome • Generalizing from • Java programming language • XML exchange format • Email: bren@csse.monash.edu.au
Comments so far… • 16 Dec 2002 • Bi-directional (slide 38, rightmost) When an old version reads an extended memento, it discards the data it can’t read. But it’s useful to pass it on when writing, despite not understanding it itself. Useful in a chained pipe/database context. Mail readers do this. COBOL has “filler” for this (thanks John, Michael & Peter) • Implement: store the Memento read in an instance field. Update the fields of this with the new state, instead of creating a new one. • Object identity is an issue for PPL and distributed systems; however, the technique of copying works fine, provided there is no concurrent access. For large databases, with concurrent access, more sophisticated solutions are needed than this. The memento addresses simpler problems that don’t require all that overhead (thanks John)