=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== https://ceur-ws.org/Vol-3089/ttc20_paper4_Hinkel.pdf
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.