Send the link below via email or IMCopy
Present to your audienceStart remote presentation
- Invited audience members will follow you as you navigate and present
- People invited to a presentation do not need a Prezi account
- This link expires 10 minutes after you close the presentation
- A maximum of 30 users can follow your presentation
- Learn more about this feature in our knowledge base article
Do you really want to delete this prezi?
Neither you, nor the coeditors you shared it with will be able to recover it again.
Make your likes visible on Facebook?
Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.
Saving and retrieving objects in a changing environment
Transcript of Saving and retrieving objects in a changing environment
are pretty much the same ...since our code ARE objects Classes, metaclasses,
inside method dictionaries And inside methods, literal references global references
(including classes) unique objects
(true, false, nil) To save an arbitrary group of objects
even starting from a well-defined root
(as a ProjectSession)
we need to do several cleaning operations This is useful not only for saving
(economy of space and time)
but for retrieving also
(no need to rebuild unnecessary structures) Basically, we should clean
all instance variables
referencing temporary values
or global values.
Also, some references could be
sythesized using names or identifiers Tradition separates two scenarios Time passes, and
life goes on... And your objects,
and your environment,
CHANGE Saving code ...and what you expect to be already
present when you retrieve You have
Constant Pools You expect to find
Pool constants ...and you can have
collisions on all of it ...and you should
solve them Saving model objects You have
Instances of model classes
Instances of common library classes
References to globals You expect to find
Common library classes
Globals You cannot have name conflicts, but
you could not find the referenced
classes or globals Most likely, you cannot
solve this automatically Besides, everything can be in place
all names could be resolved
no apparent conflict detected
...and nevertheless be wrong! Classes could be in different hierarchies Globals & constants
unexpected values Classes could have changed name Most of this can be fixed
using mappings. Parcels
Tanker (Fuel packages)
Monticello In the basement, we have... ObjectDumper
ObjectLoader An object serialization tool,
inspired in BOSS Hooks #afterReadActivate #dumpingSurrogate before exporting
can answer a different object Bitmap>>dumpingSurrogate self saveBitmap.
^self copy clearSurrogate In Java serialization
you can declare transient
instance variables after loading
adapts receiver instance variables
can return a different object Transient variables must use
lazy initialization to fix useful to clean transient variables
but also to encode objects by id
or expression FacilitySpec>>afterReadActivate super afterReadActivate.
maxConnectedWells isNil ifTrue: [self initializeMaxConnectedWells].
minWellsRequired isNil ifTrue: [self initializeMinWellsRequired] It has no warranted order
It is individual, object per object
It gets complex when several versions pass
and changes go on and on You need a unique and consistent
source of version number PVRApplication class>>currentVersion ^10.201 PetroVR suite includes several different
tools, with different model objects PVRReader>>readFrom: aStream self
model notNil ifTrue: [self migrateToCurrentVersion].
^model PVRReader>>migrateToCurrentVersion objectFiler saveMissingVariables.
model := self migrator migrate: model fromVersion: version.
objectFiler releaseMissingVariables We work with many
incremental migrations PVRReader>>readModel self initializeMappings; loadRequiredLibraries.
model := objectReader loadFrom: stream loadMaps: mappings We had to add logic for composing the maps Class A Class B Class C renamed renamed ProjectMigrator>>migrateTo519 Specific cases and examples FML Expressions and model names
model allVariablesDo: [:var |
(var hasFmlFunction and: [var functionString includesString: 'Start date'])
ifTrue: [| exp |
exp := var calcFunction fmlExpression.
exp variableNamesDo: [:v |
(v refersToJob and: [v lastName = 'Start date']) ifTrue: [
v lastName: 'Expected Start Date'.
var calcFunction fromFmlExpression: exp]]]].
model allJobs do: [:j |
(j instVarNamed: 'startGuess') name: 'Expected Start Date'] ProjectMigrator>>migrateTo9102 | oldNames names |
oldNames := OrderedCollection new.
names := OrderedCollection new.
model excessActions select: [:e | e isExpansion] thenDo: [:e | | v |
v := e threshold.
v name = 'Unused capacity' ifFalse: [
oldNames add: v modelName.
v name: 'Unused capacity'.
names add: v modelName]].
names notEmpty ifTrue: [self renameVarsNamed: oldNames to: names]. evolved into general
services Note that methods should be idempotent! ProjectMigrator>>migrateTo10107 | aux |
select: [:r | r isGasReservoir]
thenDo: [:r | r oil solutionGOR deactivate].
aux := FacilityModelMigrator new.
model facilities do: [:f | aux migrate: f structure fromVersion: version] Bussiness modeling change Forced initialization of new variables ProjectMigrator>>migrateTo91 model simpleReservoirs do: [:r | | plan pattern |
plan := r depletionPlan.
plan wellReservesThreshold isNil
ifTrue: [plan initializeWellReservesThreshold].
(plan instVarNamed: 'batch') isNil ifTrue: [plan batch: false]] Changes in representation Internal changes in selectors ProjectMigrator>>migrateTo9301 | percentages wrong |
percentages := model percentageSensitivitySpec percentages.
wrong := percentages columnSpecOf: #baseValue.
wrong notNil ifTrue: [wrong selector: #displayValue] Changes in codification ProjectMigrator>>migrateTo8107 model wells
select: [:w | w recompletionPolicy == #autoDrillCompletions]
thenDo: [:w | w recompletionPolicy: #autoComplete] ProjectMigrator>>migrateTo8109 model heatingWells do: [:h | | decline |
decline := InjectorPerformanceSpec new.
decline fluid: h injectionFluid; owner: h.
h instVarNamed: 'decline' put: decline] Adding ranges to variables ProjectMigrator>>migrateTo8302 model declines
select: [:d | d decline class == GasDeliverabilityDeclineSpec]
thenDo: [:d |
d decline flowExponent range: (Range open: 0.0 close: 10.0).
d decline flowCoefficient range: Range positive] Changes of classes ProjectMigrator>>migrateTo7206 model facilities
select: [:f | f isPowerPlant and: [f isCogenerator]]
thenDo: [:f |
f changeClassTo: SteamPlantSpec.
f structure: (f structure copyTo: SteamPlantModel new).
f structure initializeConverter] Adding description to variables ProjectMigrator>>migrateTo7207 model allJobs do: [:job |
job isInfillDrilling ifTrue: [
job cost opEx
description: 'Calculated as Number of Wells * the prototype''s OpEx.'].
job isRigMobilization ifTrue: [
job cost opEx
description: 'Calculated from mobilization/demobilization costs defined for the rig type']] We added support for missingVariables
so we can extract data from discarded
or renamed instance variables ProjectMigrator>>migrateTo7303 model wells do: [:w | | missing location point |
location := w location.
missing := location propertyAt: #missingVariables.
missing notNil ifTrue: [
point := missing at: 'logical' ifAbsent: nil.
point notNil ifTrue: [location x: point x y: point y z: 0.0]]] Because, sometimes, we let user decide
We have built Migration Issues ProjectMigrator>>migrateTo62 model facilities do: [:f | | issue |
(f hasDowntimeDefined and: [f usesSequentialAllocation]) ifTrue: [
issue := self
addMigrationIssueBecause: f modelName
, ' has Downtime defined which is currently unsupported with sequential choking'.
addOption: 'Disable downtime'
receiver: f maintenanceProgram downtime
description: 'Turn off the Downtime defined at ' , f name;
addOption: 'Use proportional choke distribution'
description: 'Change to proportional choking all facilities up and down-stream '
, f name;
addEmptyOption]] We can move variables to different objects ProjectMigrator>>migrateTo6214 model reservoirs do: [:r | | missingVariables oil gas |
missingVariables := r propertyAt: #missingVariables.
missingVariables notNil ifTrue: [
oil := missingVariables at: 'oil'.
gas := missingVariables at: 'gas'.
instVarNamed: 'oil' put: oil;
instVarNamed: 'gas' put: gas]] Sometimes, objects must be fixed
BEFORE we start the migration,
because base services would not work otherwise.
We introduced the fixBrokenObjects mechanism ProjectMigrator>>fixBrokenObjectsIn8303 model connections
do: [:c | c capacity isNil ifTrue: [c reinitializeCapacity]] Project Migrator>>fixBrokenObjectsBeforeMigration PVRApplication current allVersions do: [:v | | selector |
(PVRApplication isVersion: version pre: v) ifTrue: [
selector := ('fixBrokenObjectsIn'
, (v printString reject: [:c | #($. $,) includes: c]))
(self respondsTo: selector) ifTrue: [self perform: selector]]] A common problem:
tracking the version number THIS kind of mappings Missing variables Migration Issues Two stages and fixing broken objects Variables and Fml According to what you
have when you save Saving Code Saving Model Objects Globals could have unexpected values Classes could have changed shape
renaming variables Variable semantics or business
rules could change DepletionPlan instanceVariableNames: .... threshold batch ... initialize
.. .. ..
batch := false. aHeatingWell aVariable anInjector
Spec decline decline FacilitySpec PowerPlantSpec Cogenerator SteamPlantSpec aLocation x y aPoint logical nil physical aLocation x y z A medium-size project from a client
contains 8248 objects (2950 literals)
of 164 classes. A tiny demo project contains 4086 objects
(1844 literals) of 175 classes Class A oil gas aReservoir oil gas aReservoir aReservoirFluids