Lively Kernel canvas LivelyStories-DraftStoringTasksSoftwareArchitectureGroup(HPI)2010-http://www.hpi.uni-potsdam.de/swa/lively_tasksmanypagescontainlittlenotesandTODOitems...Wehavelotsofthem.Andwehaveforgottenthemandwewillforgetthemunlesssomeoneorsomethingwillrememberusthattheyarethereandthattheywon'tgoawayonitself.Atleastnotallofthem.task2={title:'testtask',description:'thisisnodescription2'}db.save(task2)task3={title:'testtask3yeah',description:'thisisnodescription3...',type:'task'}db.save(task3)allObjs[4]db=newCouchDB('lively_tasks')docs=db.allDocs()docs.rows[0].valueallObjs=docs.rows.collect(function(ea){returndb.open(ea.id)})allTasks=allObjs.select(function(ea){returnea.type=='task'})pane=newRealListPane(newRectangle(0,0,300,300))pane.openInWorld(this.getPosition().addPt(pt(0,300)),"taskListMorph")pane.setFill(Color.gray)list=pane.innerMorph()list.updateList(allTasks)list.itemPrinter=function(task){returntask.title}newtasktesttask3yeahnewtasknewtasktesttask//UISetupconnect($morph('taskList'),'selection',$morph('taskIdLabel'),'setTextString',{converter:function(task){returntask._id}})connect($morph('taskList'),'selection',$morph('titleTextField'),'setTextString',{converter:function(task){returntask.title}})connect($morph('taskList'),'selection',$morph('titleTextField'),'setTextString',{converter:function(task){returntask.title}})connect($morph('taskList'),'selection',$morph('descriptionTextField'),'setTextString',{converter:function(task){returntask.description}})30f3c39862c74a09b6667573d799dbd5idtesttask3yeahtitledescriptionthisisnodescription3...updatetasksnewtaskdeletetaskTODO:makelocalupdatecycle...after"newtask"thetaskisaddedtotheDBbutnotdisplayedlocallyyet...TODO:whenthefieldsareeditedthetasksshouldbeupdated....ResearchQuestion:Weknowourwaywithlocalobjectsnow....whathappenswhendatabasesandthereforforeignobjectscomeintoplay.Tostartsimple,letsuseCouchDB.Ishasanotionofdocumentsbutdoesnotsupportautomaticobjectreferences....CouchDBLivelyLivelynewtaskTasksupdatetitledescriptionidTaskListselectionTaskEditordeletetask1.SimpleDocumentBasedTaskEditor2.ObjectBasedTasksObject.subclass("LivelyStories.Task",{initialize:function(title){this.title=title||'NoTitle';this.description='NoDescription';this.type='Task'},toString:function(){return"Task["+this.title+"]"}});Object.subclass("LivelyStories.Story",{initialize:function(title){this.title=title||'NoTitle';this.description='NoDescription';this.tasks=[];this.type='Story'},toString:function(){return"Story["+this.title+"]"},addTask:function(task){if(this.tasks.include(task))return;this.tasks.push(task)}});task1=newLivelyStories.Task('Dosomething')task2=newLivelyStories.Task('Dosomethingelse')story=newLivelyStories.Story('GetStarted');story.addTask(task1)story.addTask(task2)serializer=ObjectGraphLinearizer.forLively();obj=serializer.serialize(story)objlively.persistence.Debugging.Helper.prettyPrintJSON(obj){id:6,registry:{0:{registeredObject:{title:GetStarted,description:NoDescription,tasks:{0:{__isSmartRef__:true,id:1,},1:{__isSmartRef__:true,id:2,},},__LivelyClassName__:LivelyStories.Story,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:0,},},1:{registeredObject:{title:Dosomething,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:1,},},2:{registeredObject:{title:Dosomethingelse,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:2,},},3:{registeredObject:{title:GetStarted,description:NoDescription,tasks:{0:{__isSmartRef__:true,id:4,},1:{__isSmartRef__:true,id:5,},},__LivelyClassName__:LivelyStories.Story,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:3,},},4:{registeredObject:{title:Dosomething,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:4,},},5:{registeredObject:{title:Dosomethingelse,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:5,},},6:{registeredObject:{title:GetStarted,description:NoDescription,tasks:{0:{__isSmartRef__:true,id:7,},1:{__isSmartRef__:true,id:8,},},__LivelyClassName__:LivelyStories.Story,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:6,},},7:{registeredObject:{title:Dosomething,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:7,},},8:{registeredObject:{title:Dosomethingelse,description:NoDescription,__LivelyClassName__:LivelyStories.Task,__SourceModuleName__:Global,},ref:{__isSmartRef__:true,id:8,},},},}4.ObjectGraphasDataModel3.StoreStoriesandTasksintoDocuments...eachTaskandeachStoryshouldbeindividualdocumentsandshouldbeabletoreferenceeachother....sincethereisnoconceptofreferencesinJSON,wehavetodealmanuallywithitotherwisetheJSONserializemakesabigtreeoutofitasinthecaseofserializingtheStory.-Robert'sObjectGraphserializerknowsaboutreferencesanddealswiththemautomatically.-ItfurtherhandlesClassescorrectly.-Problems:-TheserializedStoriesandTasksendupinonebigBLOB.-Theidsarenotpersistent(externalentitiescannotreferencethem)-NonLivelyCodecannoteaslyreadandwritetheformatwithoutimplementingsomethingliketheGraphSerilazer/Deserializer-Example:ShellScriptthatgrepssourcecodeandgeneratestasks-Updatingmaynotscale-deserializeallobjects-add/deletethetask-serializeallobjects-NointerfaceforCollaboration-addinganddeletingoneobjectisinconflictwitheveryotherobjectCanwecombineCouchDBstoriesandtasksIdeaswiththeGraphSerialzier?-TheGraphSerializershouldnotproduceonebigdocument-TheGraphSerializercantreatoneCouchDBdatabaseasitsplayground...-Class/TypeinformationshouldbepersistedArewetalkingaboutObjectDatabases?5.Task/StoryDocumentswithReferencesandClassesSolutionIdea:-everyobjectthatwouldgetangeneratedidgetsacouchdbUUID-programmerscancontrolwhatisanownobjectandwhatisonlyavalueobjectthatdoesnotneeditsownid-oneCouchDBbecomeonebigimagewithpersistentobjects!-weneedmanualgarbagecollectioninsuchabigimage-itisnotnessessarytoloadallobjectstochangeoneobjectProblems:-Howdowesyncronizelocalwithremoteobjects?-Howdowedealwithconflicts?varobj1={a:3},obj2={a:4},obj3={a:5};obj1.o=obj2,obj3.o=obj3;varserializer=ObjectGraphCouchDBLinearizer.forLively();varstring=serializer.serialize(obj1);obj1._idtask1=newLivelyStories.Task('Dosomething')task2=newLivelyStories.Task('Dosomethingelse')story=newLivelyStories.Story('GetStarted');story.addTask(task1)story.addTask(task2)db=newCouchDB('lively_tasks')db.save(task1)task1_id=task1._idpersistedTask1=db.open(task1_id)db.save(task2)task2_id=task2._idpersistedTask2=db.open(task2_id)db.save(story)story_id=story._idpersistedStory=db.open(story_id)lively.persistence.Debugging.Helper.prettyPrintJSON(persistedTask1){_id:679aa96fd282f2ecae889b14d988c32b,_rev:1-f8d4f0789b7d4c2427b20e4dd2ecc0bd,title:Dosomething,description:NoDescription,type:Task,}lively.persistence.Debugging.Helper.prettyPrintJSON(persistedTask2){_id:1d082c1b749c95e1f2144ae101cb6106,_rev:2-c3dfa25a80babcd9545c6befb46c098f,title:Dosomethingelse,description:NoDescription,type:Task,}lively.persistence.Debugging.Helper.prettyPrintJSON(persistedStory){_id:be7e8836853fc8be57bdbdc8f64f85ce,_rev:1-a7313f9a58922bfacee81e93bcf4d403,title:GetStarted,description:NoDescription,tasks:{0:{title:Dosomething,description:NoDescription,type:Task,_id:679aa96fd282f2ecae889b14d988c32b,_rev:1-f8d4f0789b7d4c2427b20e4dd2ecc0bd,},1:{title:Dosomethingelse,description:NoDescription,type:Task,_id:1d082c1b749c95e1f2144ae101cb6106,_rev:2-c3dfa25a80babcd9545c6befb46c098f,},},type:Story,}task1=newLivelyStories.Task('Dosomething'),task2=newLivelyStories.Task('Dosomethingelse')story=newLivelyStories.Story('GetStarted');story.addTask(task1)story.addTask(task2)varserializer=ObjectGraphCouchDBLinearizer.forLively();varregistry=serializer.flatten(story);varobjList=Object.values(registry).pluck('registeredObject')objList[0]registrythis__LivelyClassName____SourceModuleName____proto__descriptiontaskstitletype-----doitsherehavethis===selectedinspecteeStoryXMObjectGraphCouchDBLinearizerTestRunTestCaseRunAllTestCasesRefreshTestsrun:2--Testsfailed:2--Time:0.013sObjectGraphCouchDBLinearizerTest.testFalttenfailed:ReferenceError:Can'tfindvariable:story(undefined)inTaskDB.js(Line83)ObjectGraphCouchDBLinearizerTest.testSerializeTasksAndStoriesfailed:(registeredobjecthasnocouchdbid)(undefined)inTestFramework.js(Line181)TestRunnerXMWikicontrol// this script is evaluated on world load