<div>Dear all,<br clear="all"></div><div><br></div><div>I&#39;m using Magma and finding out how transparent it can be. I&#39;m trying Magma to see if the DDD principles can be applied to it. To retrieve, store and save aggegrate root objects a Repository object is used. A &#39;transient&#39; Repository object is nothing more than a wrapper around an OrderedCollection, which contains store save and find methods. The client who is using this Repository object does not know which implementation is behind it. After retrieving the initial root aggegrate the client can manipulate the sub objects of the aggegrate root. </div>
<div><br></div><div>I managed to achieve Read Transparency. I specialised the Repository objects so they use a MagmaCollection instead of an ordinary OrderedCollection.  You just do a findXXX method on the Repository, and that method is delegated to a MagmaCollection which does a read based on some defined index. </div>
<div><br></div><div>To do a Write Transparency, I added a decorator around the store / save methods of the Repository which automatically wraps the original Repository object in a session commit:[] block; enabling Magma to see the changes made to the &#39;saved&#39; object and get them persisted. </div>

<div>AddTransactionAroundMutators&gt;&gt;doesNotUnderstand: aMessage <br>   |result| <br>            (self isMutator: aMessage)          <br>                             ifTrue: [repositoriesController commit:                                         <br>                                       [result := aMessage sendTo: decorated]]<br>

                             ifFalse: [result := aMessage sendTo: decorated]. <br>    ^result.</div><div>In which AddTransactionAroundMutators is a decorator around the Repository object. </div><div><br></div><div>Persisting works, however I noticed that the hash indexes did not get updated this way. On the wiki it is mentioned that MagmaSession&gt;&gt;#noteOldKeysFor: should be called before any change to the object is made. This is off course, using my idiom, impossible to do, since the user using the Repository does not even know that there is a MagmaSession. It just knows the API of the Repository object. The Seaside GUI I&#39;m using is manipulating an object (which it got from a findXXX query on a repository) directly and if it wants to save the changes it calls Repository&gt;&gt;save (which got decorated). The GUI using the Repositories does not know Magma and I tend to keep it that way. </div>

<div><br></div><div>After some searching, I managed to circumvent this by a dirty hack: </div><div>AddTransactionAroundMutators&gt;&gt;doesNotUnderstand: aMessage        <br>   |result| <br>          (self isMutator: aMessage)          <br>                             ifTrue: [<br>

                                        (self isUpdatingMutator: aMessage) &quot;denotes saveXXX methods =&gt; updates to existing objects&quot;<br>                                                  ifTrue: [<br>                                                             |session session2 firstArg oidForFirstArg reReadObject|<br>

                                                              session := repositoriesController session.<br>                                                              session2 := repositoriesController session2.<br>                                                              firstArg := aMessage arguments first.<br>                                                              oidForFirstArg := session oidFor: firstArg.<br>

                                                              reReadObject := session2 realObjectFor: oidForFirstArg.<br>                                              repositoriesController commit:                                                                                 <br>                                                                  [session noteOldKeysFor: firstArg usingHashesFromObject: reReadObject.<br>

                                                                    result := aMessage sendTo: decorated]]<br>           ifFalse: [<br>                                                             repositoriesController commit:                                                                                 <br>                                                              [result := aMessage sendTo: decorated]]]<br>

                             ifFalse: [result := aMessage sendTo: decorated]. <br>        ^result.</div><div><br></div><div><br></div><div>MagmaSession&gt;&gt;noteOldKeysFor: anObject usingHashesFromObject: anOtherObject<br>   guard critical: [ <br>

                  transaction ensureOldHashesCapturedFor: anObject usingHashesFromObject: anOtherObject]<br></div><div><br></div><div>MaTransaction&gt;&gt;ensureOldHashesCapturedFor: anObject usingHashesFromObject: anOtherObject<br>

   (potentialKeysChange includesKey: anObject) ifTrue: [ ^ self ].<br>   self captureOldHashesFor: anObject usingHashesFromObject: anOtherObject<br></div><div><br></div><div>MaTransaction&gt;&gt;captureOldHashesFor: anObject usingHashesFromObject: anOtherObject<br>

   largeCollectionChanges do:<br>            [ :eachChanges |<br>              (eachChanges collection canIndex: anObject)<br>                        ifTrue:<br>                                  [ eachChanges collection indexesDo:<br>                                               [ :eachIndex | | oldKeys oldHashes |<br>

                                                   oldKeys := potentialKeysChange <br>                                                                                 at: anObject ifAbsentPut: [ IdentityDictionary new ].<br>                                                   oldHashes := oldKeys<br>                                                                                 at: eachIndex attribute ifAbsentPut: [ OrderedCollection new ].<br>

                                                   oldHashes<br>                                                                 add: { eachChanges. eachIndex. eachIndex indexHashesFor: anOtherObject } ] ] ].</div><div><br></div><div>So I&#39;m using a second MagmaSession to reload the object I&#39;m about to commit and I&#39;m noting to the first session to noteOldKeysFor: anObject usingHashingFromObject: theJustReloadedObjectFromTheSecondSession. Like this, the first session gets the hashes of the unmodified object in the repository, and the hashes get updated correctly automatically. It is a working solution (at least with my very limited testing), but I find it very complicated. Surely there must be a cleaner way to do an automatic hashkey update. </div>

<div><br></div><div>Other things I already tried is to enable WriteBarrier, but could not get that working.</div><div>I also tried to do readRealObject: oid on the same session; but this always returned a cached version, with the already updated fields in. The only thing that worked was to create a new session and make sure that the object is fresh.</div>

<div><br></div><div>Can anyone help me on this one? I&#39;m finding it a bit strange that Magma can correctly save my changes, but not determine if a hash key update is necessary. </div><div><br></div><div>Thanks for any help.</div>

<div><br></div><div>Kind Regards,</div><div><br>Bart<br></div>
<div><br></div><div>-- <br></div>imagination is more important than knowledge - Albert Einstein<br>Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein<br>Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein<br>



The true sign of intelligence is not knowledge but imagination. - Albert Einstein<br>However beautiful the strategy, you should occasionally look at the results. - Sir Winston Churchill<br>It&#39;s not enough that we do our best; sometimes we have to do what&#39;s required. - Sir Winston Churchill<br>