=Paper=
{{Paper
|id=Vol-3089/ttc20_paper_Hinkel
|storemode=property
|title=An NMF solution to the TTC 2020 roundtrip engineering case
|pdfUrl=https://ceur-ws.org/Vol-3089/ttc20_paper4_Hinkel.pdf
|volume=Vol-3089
|authors=Georg Hinkel
|dblpUrl=https://dblp.org/rec/conf/ttc/Hinkel21
}}
==An NMF solution to the TTC 2020 roundtrip engineering case==
An NMF solution to the TTC 2020 roundtrip engineering case Georg Hinkel1 1 Am Rathaus 4b, 65207 Wiesbaden, Germany Abstract This paper presents a solution to the Roundtrip Engineering case at the Transformation Tool Contest (TTC) 2020. I demon- strate how synchronization blocks can be easily used to specify the relationships in a bidirectional manner. Through a superimposition concept, the migrations can concentrate on those parts of the metamodel that have actually changed. The performance results on the provided model shows that the solution has a very good performance on the provided input models, although these are very small. Keywords Model Migration, Roundtrip, BX, Transformation 1. Introduction 2. Synchronization blocks and Just like every software artifact, metamodels are also sub- NMF Synchronizations ject to evolution. However, in large entities, metamodel Synchronization blocks are a formal tool to run model change do not take place immediately but rather, one transformations in an incremental (and bidirectional) has to accept a period where both the old and the new way [2]. They combine a slightly modified notion of schema version are used throughout the organization. lenses [3] with incrementalization systems. Model prop- During this period, changes can occur either in the new erties and methods are considered morphisms between or in the old form of a model, which leads to a problem objects of a category that are set-theoretic products of a that models have to be maintained both in the new and type (a set of instances) and a global state space β¦. in the old schema. A (well-behaved) in-model lens π : π΄ Λβ π΅ between In the TTC 2020 Roundtrip benchmark [1], the task types π΄ and π΅ consists of a side-effect free Get mor- was to synchronize instances of evolving metamodels in phism π ββ π ππ(π΄, π΅) (that does not change the a range of minimal example evolution scenarios. global state) and a morphism π ββ π ππ(π΄ Γ π΅, π΄) In this paper, I present a solution to this benchmark called the Put function that satisfy the following condi- using synchronization blocks and their implementation tions for all π β π΄, π β π΅ and π β β¦: in NMF Synchronizations [2]. NMF Synchronizations allows us to create very declarative and fully bidirec- π β (π, π β (π)) = (π, π) tional specifications of commonalities between two ver- π β (π β (π, π, π)) = (π, π Λ β β¦. Λ ) for some π sions of a metamodel. Furthermore, because NMF Syn- chronizations is implemented as an internal DSL, it al- The first condition is a direct translation of the original lows to shorten the specification of commonalities such PutGet law. Meanwhile, the second line is a bit weaker that developers of roundtrip migrations can focus on than the original GetPut because the global state may the actual differences between the two versions of a have changed. In particular, we allow the Put function metamodel. The solution is available on GitHub: https: to change the global state. //github.com/georghinkel/ttc2020-roundtrips. A (single-valued) synchronization block π is an oc- tuple (π΄, π΅, πΆ, π·, Ξ¦π΄βπΆ , Ξ¦π΅βπ· , π, π) that declares a synchronization action given a pair (π, π) β Ξ¦π΄βπΆ : π΄ βΌ = πΆ of corresponding elements in a base isomor- phism Ξ¦π΄βπΆ . For each such a tuple in states (ππΏ , ππ ), the synchronization block specifies that the elements TTCβ20: Transformation Tool Contest, Part of the Software (π (π, ππΏ ), π β (π, ππ )) β π΅ Γ π· gained by the lenses Technologies: Applications and Foundations (STAF) federated π and π are isomorphic with regard to Ξ¦π΅βπ· . conferences, Eds. A. Boronat, A. GarcΓa-DomΓnguez, and G. Hinkel, A schematic overview of a synchronization block is 17 July 2020, Bergen, Norway (online). depicted in Figure 1. The usage of lenses allows these " georg.hinkel@gmail.com (G. Hinkel) declarations to be enforced automatically and in both Β© 2021 Copyright for this paper by its authors. Use permitted under Creative Commons License Attribution 4.0 International (CC BY 4.0). CEUR Workshop http://ceur-ws.org ISSN 1613-0073 CEUR Workshop Proceedings (CEUR-WS.org) directions. The engine simply computes the value that Proceedings Ξ¦π΄βπΆ 1 public class Person2Person : SynchronizationRule{ π π 2 public override void DeclareSynchronization() { 3 Synchronize(p => p.Name, p => p.Name); 4 Synchronize(p => p.Age, p => 2020 - p.Ybirth); π΅ π· Ξ¦π΅βπ· 5 } 6 public override bool ShouldCorrespond(V1Person left, V2Person right, ISynchronizationContext context) { Figure 1: Schematic overview of unidirectional synchroniza- 7 return left.Name == right.Name; tion blocks 8 } 9 } Listing 1: The synchronization block to specify the the right selector should have and enforces it using the semantic overlap between the Person classes Put operation. Similarly, a multi-valued synchronization in scenario 1 block is a synchronization block where the lenses π and π are typed with collections of π΅ and π·, for example π : π΄ Λβ π΅* and π : πΆ Λβ π·* where stars denote Kleene closures. 3.1. Specific solution Synchronization blocks have been implemented in The idea of synchronization blocks is to specify the se- NMF Synchronizations, an internal DSL hosted by C# mantic overlap between two metamodels, not their dif- [4, 2]. For the incrementalization, it uses the extensible ference. For scenario 1, this overlap consists of the name, incrementalization system NMF Expressions [5]. This which is still the same, and the overlap that the age can DSL is able to lift the specification of a model transfor- be computed from the year of birth or vice versa. This is mation/synchronization in three orthogonal dimensions: depicted in Listing 1. In particular, both aspects of the semantic overlap can β’ Direction: A client may choose between trans- be specified with just one line of code each. Here, the formation from left to right, right to left or in calculation of the age from the year of birth (and vice check-only mode versa which NMF is able to automatically infer) is very β’ Change Propagation: A client may choose simple because the inversion of a subtraction is already whether changes to the input model should be built into NMF. However, NMF also allows to specify a propagated to the output model, also vice versa custom conversion operation and an appropriate lens or not at all to put back the value, in case a metamodel evolution β’ Synchronization: A client may execute the requires more sophisticated adaptions. transformation in synchronization mode between As a very simple example, such a conversion is used a left and a right model. In that case, the engine in scenario 3, because the coalescing operator is not re- finds differences between the models and han- versible in NMF by default. The implementation of the dles them according to the given strategy (only custom conversion is shown in Listing 2. add missing elements to either side, also delete superfluous elements on the other or full duplex 1 public V2Person> class Person2Person : SynchronizationRule p.Name, p => Coalesce(p.Name)); 4 } This flexibility makes it possible to reuse the specifi- 5 } cation of a transformation in a broad range of different 6 [LensPut(typeof(Scenario3Solution), nameof(CoalesceBack))] 7 public static string Coalesce(string value) { use cases. Furthermore, the fact that NMF Synchroniza- 8 return value ?? ""; tions is an internal language means that a wide range 9 } 10 public static string CoalesceBack(string value, string of advantages from mainstream languages, most notably coalesced) modularity and tool support, can be inherited [6]. 11 { 12 return coalesced; 13 } 3. Solution Listing 2: The synchronization blocks to specify the semantic overlap between the Person classes Our solution consists of two parts: At first, I describe the in scenario 3 solutions to all four of the scenarios using vanilla NMF Synchronizations, that is, using explicit coding. After- In particular, one only needs to annotate a given con- wards, I explain the necessary steps to turn this into a version method with a lens put annotation in order to generic solution. tell NMF how to invert this function call. In order to run these synchronization blocks, I instruct NMF to enforce the consistency relations specified using 1 var repository = new ModelRepository(); 1 foreach (var att in oldModelClass.Attributes) { 2 var input = LoadModel (repository) 2 var newAtt = newModelClass.Attributes.FirstOrDefault(a => ; a.Name == att.Name); 3 3 if (newAtt != null && att.Type == newAtt.Type && newAtt. 4 var transformation = new Scenario1Solution(); LowerBound == att.LowerBound) { 5 transformation.Initialize(); 4 // Create Synchronize call 6 5 var lambda = CreateLambdaFor (att); 7 Scenario1.V2.Model.Person result = null; 6 singleAttribute 8 // this call is the migrate step 7 .MakeGenericMethod(lambda.ReturnType) 9 transformation.Synchronize(ref input, ref result, 8 .Invoke(this, new object[] { lambda, SynchronizationDirection.LeftToRightForced, CreateLambdaFor (newAtt) }); ChangePropagationMode.None); 9 } 10 // this call is the migrate back step 10 } 11 transformation.Synchronize(ref input, ref result, 11 foreach (var oldReference in oldModelClass.References) { SynchronizationDirection.RightToLeftForced, 12 var newReference = newModelClass.References. ChangePropagationMode.None); FirstOrDefault(r => r.Name == oldReference.Name); 12 13 if (newReference != null && newReference.LowerBound == 13 repository.Save(input, Output); oldReference.LowerBound) { 14 // Create Synchronize call var oldLambda = CreateLambdaFor (oldReference); Listing 3: Running the transformation: Migrate and 15 16 var newLambda = CreateLambdaFor (newReference); migrate back 17 var rule = Synchronization. GetSynchronizationRuleForSignature(oldLambda. ReturnType, newLambda.ReturnType); 18 singleReference 19 .MakeGenericMethod(oldLambda.ReturnType, newLambda. ReturnType) synchronization blocks either from left to right or from 20 .Invoke(this, new object[] { rule, oldLambda, right to left. In the context of this solution, left means V1 newLambda, null }); } (because I always noted the V1 type on the left) and right 21 22 } means V2. Migrate and Migrate back therefore translate to simply calling the transformation with direction left to Listing 4: Generating a synchronization block for each right forced and right to left forced. Here, forced means unchanged attribute and reference that also null values are propagated. The execution of the synchronization is depicted in Listing 3. I first create a model repository in which I load the input model (lines 1 and 2), then create and Listing 4. For brevity, we do not handle inheritance, multi- initialize the transformation (lines 4/5). Then, I create a valued attributes or references and only check whether new and empty variable that I use to hold the migrated an attribute or reference with the same name exists and V2 model in line 7. In line 9, I force NMF to override this whether the lower bound is the same (in order to account variable and put the migrated Person model element. for the difference between null values and empty strings Then, I immediately migrate the model back, using the in scenario 3). same pattern. As the last parameter suggests, NMF is also able to obtain an incremental change propagation 1 foreach (var oldClass in oldModel.Descendants().OfType< IClass>()) { in case the models are to be used in-memory, but offline 2 var newClass = newModel.Descendants().OfType (). synchronization is also supported (by just disabling the FirstOrDefault(c => c.Name == oldClass.Name); 3 if (newClass != null) { change propagation). 4 var oldMapping = oldClass.GetExtension (); A new information as in scenario 2 simply can be im- 5 var newMapping = newClass.GetExtension (); 6 plemented by not synchronizing this attribute. Multiple 7 if (oldMapping?.SystemType != null && newMapping?. edit operations as in scenario 4 simply means to combine SystemType != null) { 8 var rule = (SynchronizationRuleBase)Activator. the necessary synchronization blocks. CreateInstance(typeof(MigrationRule<,>). MakeGenericType(oldMapping.SystemType, newMapping.SystemType)); 3.2. Generic solution 9 yield return rule; 10 } } The biggest problem that I see with the specific solution 11 12 } is that the identical parts of the metamodel have to be specified over and over again. While of course not a Listing 5: Generating synchronization rules problem for very small metamodels such as the ones in the benchmark, this can become a problem once the idea is applied to big metamodels with hundreds of classes as What we need to do is to generate synchronization one has to create a separate synchronization rule for each rules to house the generated synchronization blocks. For metaclass and a synchronization block for every feature. this, we simply iterate over the classes of the metamodel The code for generating such synchronization blocks and check whether there is a corresponding class in the for single-valued attributes and references is depicted in new metamodel. 1 public class Scenario4Solution : Migration { 2 [OverrideRule] Scenario 3 public class Person2Person : MigrationRule { Scenario1Forward 4 public override void DeclareSynchronization() { Scenario2Backward base.DeclareSynchronization(); Scenario2Forward 5 Scenario3Backward 6 Synchronize(p => p.Age, p => 2020 - p.Ybirth); 1000 Scenario3Forward } Scenario4Backward Time [ms] 7 8 } Scenario4Forward 9 } Listing 6: Superimposition of the migration for person 100 elements 10 1 10 100 1000 10000 100000 1000000 Repetitions With these two artifacts, we get a model synchroniza- tion that automatically synchronizes all classes and fea- Figure 2: Performance results for running the Transforma- tures that have not changed (meaning that a feature with tion step of the solution multiple times. the same name exists), but we still need to specify the semantic overlap that is contained in different attributes such as the corespondence between age and year of birth. To do that, we use the superimposition concept that 5. Conclusion is available in NMF Synchronizations, depicted in List- I think that the NMF solution highlights the advantages ing 6. That is, we inherit from our new migration class model transformations based on synchronization blocks that spawns the synchronization rules to synchronize can offer in terms of flexibility. A single specification of the unchanged bits and then superimpose this rule by consistency relationships between the evolution steps a more detailed rule that inherits the synchronization of a metamodel suffices to transform instances forwards of unchanged attributes and references (line 5) and add and backwards. Boilerplate rules can be calculated au- the synchronization of the age with the year of birth by tomatically while the essential differences between two subtracting from 2020. evolution steps (the actual migration) is specified manu- ally with the full flexibility. 4. Evaluation One may think that the generic solution and the reflec- tion it performs must lead to a slow solution. However, I ran performance measurements of the solution on a Intel this is not true because NMF uses the .NET expression Core i7-8550U CPU on a system with 8GB RAM running compiler under the hood to compile the expressions that Windows 10. The results are depicted in Figure 2. The are built through reflection. Therefore, the reflection figure shows the required time to synchronize the model only affects the initialization of such a transformation, changes forward and backward. The suffix indicates the the runtime is completely identical. direction that is executed first, i.e. Scenario1Backward means that the V2 version of scenario 1 is migrated back to V1 and then migrated to V2 again, Scenario1Forward References means that the V1 version of scenario 1 is migrated to [1] L. Beurer-Kellner, J. von Pilgrim, T. Kehrer, Round- V2 and back to V1 again. Trip Migration of Object-Oriented Data Model In- As the figure shows, the solution is generally very stances, http://www.transformation-tool-contest.eu/ fast. If the synchronization is only called once, the ef- 2020_roundtrip.pdf, 2020. fects of just-in-time compilation and assembly loading [2] G. Hinkel, E. Burger, Change Propagation and Bidi- cause an average of little more than 10ms but if the syn- rectionality in Internal Transformation DSLs, Soft- chronization is repeated often, the runtime anneals to ware & Systems Modeling (2017). URL: http://rdcu. roughly 10ns per iteration. However, the input model be/u9PT. doi:10.1007/s10270-017-0617-6. size is also trivially small and therefore, the results are [3] J. N. Foster, M. B. Greenwald, J. T. Moore, B. C. Pierce, hardly meaningful. A thourough performance evaluation A. Schmitt, Combinators for bidirectional tree trans- would require larger models that the benchmark did not formations: A linguistic approach to the view-update provide. problem, ACM Transactions on Programming Languages and Systems (TOPLAS) 29 (2007). URL: http://doi.acm.org/10.1145/1232420.1232424. doi:10. 1145/1232420.1232424. [4] G. Hinkel, Change Propagation in an Internal Model Transformation Language, in: D. Kolovos, M. Wim- mer (Eds.), Theory and Practice of Model Trans- formations: 8th International Conference, ICMT 2015, Held as Part of STAF 2015, LβAquila, Italy, July 20-21, 2015. Proceedings, Springer Interna- tional Publishing, Cham, 2015, pp. 3β17. URL: http: //dx.doi.org/10.1007/978-3-319-21155-8_1. doi:10. 1007/978-3-319-21155-8_1. [5] G. Hinkel, R. Heinrich, R. Reussner, An extensible approach to implicit incremental model analyses, Software & Systems Modeling (2019). URL: https:// doi.org/10.1007/s10270-019-00719-y. doi:10.1007/ s10270-019-00719-y. [6] G. Hinkel, T. Goldschmidt, E. Burger, R. Reuss- ner, Using Internal Domain-Specific Languages to Inherit Tool Support and Modularity for Model Transformations, Software & Systems Model- ing (2017) 1β27. URL: http://rdcu.be/oTED. doi:10. 1007/s10270-017-0578-9.