first-class undefined classes for pharo, from alternative designs to a unified practical solution
TRANSCRIPT
First-ClassUndefined Classes
for PharoFrom Alternative Designs to a Unified Practical Solution
Guille Polito, Luc Fabresse, Stéphane Ducasse@guillepolito
Context
Package
Dependency
Object
Platform
workingDirectoryWindows
workingDirectoryPlatform
workingDirectoryUnix
call:library:FFI
Platform >> workingDirectory
^ self subclassResponsibility
Windows >> workingDirectory
^ FFI call: ’_getcwd’ library: LibC
Unix >> workingDirectory
^ FFI call: ’getcwd’ library: LibC
Problem OverviewLoad
Error!
Package
Platform
workingDirectoryWindows
workingDirectoryPlatform
workingDirectoryUnix
Problem Statement• Loading code with unresolved class references
happens when:
• Migrating code to new Pharo versions
• Loading code with unknown or cyclic dependencies
Problem of Tools
Undefined Classes• First-class entity representing non-existing classes to load:
• subclasses with unknown superclasses
• methods extending unknown classes
• Single and uniform mechanism for all tools
Design 1
Object
Class
UndefinedClass
UndefinedClass class
Windows
Windows class
Unix
Unix class
Shared for all non-existent classes (name lost, …)
A unique UndefinedClass class
Design 2One instance of UndefinedClass per undefined class
Object
Class
UndefinedClass
Windows
Windows class
WindowsFFI
WindowsFFI class
Platform
FFI
UndefinedClass class
Class class
Complex and tools issue that must deal with UndefinedClass instances in addition to Classes and Traits
Design 3One subclass of UndefinedClass per undefined class
Object
Class
UndefinedClass
UndefinedClass class
Windows
Windows class
WindowsFFI
WindowsFFI class
Platform
Platform class
FFI
FFI class
UndefinedClass will behave as a normal defined class (can be instantiated? …)
Design selection for Pharo
Ensuring Loading Correctness
• Only one UndefinedClass subclass per missing class (identity)
• UndefinedClass subclass automatic migration, and destruction when loading the actual class
• System uniformity i.e., all code loading mechanism relies on our system
UndefinedClasses MOP• an UndefinedClass cannot be instantiated
• UndefinedClass>>doesNotUnderstand: throws a notifying error • prevent misunderstanding with sub-instances
Tools Integration• Monticello
• create undefined classes at load time if needed • create the extended class as UndefinedClasses if
non-existing
• CodeImporter • parse class definition expressions and create
undefined superclasses if needed • create the extended class as UndefinedClasses if
non-existing
UndefinedClasses
in action
Migrating Old Code• Seaside 2.8 (2011)
• subclasses of PackageInfo (removed in Pharo 4) • extension methods in BlockContext (removed ~Pharo 2)
and ContextPart (renamed Context in Pharo 4)
ConfigurationOfSeaside28 load
• Omni Browser (2015) • subclasses + extension methods of undefined classes • class-side initialize with references to undefined classes
ConfigurationOfOmniBrowser project lastVersion load
Loading Order• Loading Seaside 3 and its 59 monticello packages
dependencies in a random order
Seaside3LoadingTest>> testLoadingSeasidePackagesInRandomOrder | maxNbOfUndefinedClasses | self assert: UndefinedClass allSubclasses isEmpty. maxNbOfUndefinedClasses := self loadSeasidePackagesInRandomOrder. self assert: maxNbOfUndefinedClasses > 0. self assert: UndefinedClass allSubclasses isEmpty. self executeInitializeClassMethodsInCorrectOrder.
self assertAllSeasideUnitTestsAreGreen.
Conclusion• An UndefinedClass
• is a first-class entity representing one missing class • stores all information (name, extension methods, …) • can be subclassed and referenced • is destroyed when loading actual class definition after
introducing all infos in the real class • has a specific MOP • is compliant with tools (MC, CodeImporter)
Future Work
• Integration of Undefined Classes into Pharo 7.0
• Towards a module system: • when loading a module, class references inside a
module may not be resolved until we bound them
Conclusion• An UndefinedClass
• is a first-class entity representing one missing class • stores all information (name, extension methods, …) • can be subclassed and referenced • is destroyed when loading actual class definition after
introducing all infos in the real class • has a specific MOP • is compliant with tools (MC, CodeImporter)