Patent Publication Number: US-8996349-B2

Title: Synchronizing an abstract model and source code

Description:
BACKGROUND 
     A popular way of creating software is using abstract models. An abstract model defines various aspects of a system&#39;s behavior at a design level before a developer writes any source code. For example, the abstract model may define the major components of the design and the interfaces between components. Abstract models can also define finer details of software, such as the names of each class that will be in the design, the variables associated with each class, function names and parameters, and so forth. A recent movement called Model-Driven Engineering (MDE) is the systematic use of models as primary engineering artifacts throughout the engineering life cycle. Engineers can apply MDE to software, system, and data engineering. As it pertains to software development, MDE refers to a range of development approaches that are based on the use of software modeling as a primary form of expression. With the introduction of the Unified Modeling Language (UML), MDE has become very popular with a wide body of practitioners and there are many available supporting tools. More advanced types of MDE have expanded to permit industry standards that allow for consistent application and results. The continued evolution of MDE has added an increased focus on the use of models and their role in software development. 
     Modeling is not useful without a relationship to the eventual building of software code. Therefore, modeling tools are often capable of generating source code from the model. Model-generated source code gives a developer a head start in developing a software system and reduces the chance for errors since the generated code is a close reflection of the model. However, models are insufficient to completely implement the software system, so the developer must often modify the generated code or add additional code to complete the implementation of the system. Often the product is built in two distinct stages: (1) designing and modeling with a modeling tool that ultimately generates a coding framework, and (2) implementing the product based on the generated code. 
     Unfortunately, the model and source code can quickly become out of sync. If the developer makes changes to the model, then regenerating the generated code based on the model changes may overwrite changes to the generated code made by the developer or may cause developer-added code to fail to interoperate with the regenerated code. As the developer changes a declaration in his abstract model, he is required to (1) manually change all uses of that declaration in other parts of the model, (2) manually trigger a re-generation of all of the generated source code, and (3) manually update all of the additional source code to reflect the change. If the developer makes changes to the code first, then to keep the model in sync he is required to (1) manually perform the same change in the model that corresponds to the change he made in the developer code, (2) manually change all uses of that declaration in other parts of the model, (3) manually trigger a regeneration of all of the generated source code, and (4) manually update all of the developer source code to reflect the change. The large number of manual steps can lead to errors and consume valuable development time. 
     SUMMARY 
     A software synchronization system is provided that maintains the association between an abstract software model and source code based on the model. The software synchronization system receives a change that modifies an element of the abstract model. The software synchronization system globally modifies references to the element throughout the abstract model. Then the software synchronization system automatically determines elements of the source code that are dependent on the changed model element. The software synchronization system modifies the determined elements of the source code. Thus, the software synchronization system synchronizes the abstract model and the source code, regardless of the one to which the developer makes changes. 
     This Summary is provided to introduce a selection of concepts in a simplified form that are further described below in the Detailed Description. This Summary is not intended to identify key features or essential features of the claimed subject matter, nor is it intended to be used to limit the scope of the claimed subject matter. 
    
    
     
       BRIEF DESCRIPTION OF THE DRAWINGS 
         FIG. 1  illustrates an example environment in which the software synchronization system may be used. 
         FIG. 2  is a block diagram that illustrates the components of the software synchronization system in one embodiment. 
         FIG. 3  is a flow diagram that illustrates the processing of the detect change component at load time in one embodiment. 
         FIG. 4  is a flow diagram that illustrates the processing of the detect change component when a model change is detected in one embodiment. 
         FIG. 5  is a flow diagram that illustrates the processing of the detect change component when a code change is detected in one embodiment. 
     
    
    
     DETAILED DESCRIPTION 
     Overview 
     A software synchronization system is provided that maintains the association between an abstract software model and source code based on the model. The software synchronization system receives a change that modifies an element of the abstract model. For example, a developer may change the name of a class. The software synchronization system globally modifies references to the element throughout the abstract model. For example, parent and child classes may reference the name of the class, and the software synchronization system renames these references. Then, the software synchronization system automatically determines elements of the source code that are dependent on the changed model element. For example, the source code may contain an implementation of the class, various instantiations of the class, and so forth. The software synchronization system modifies the determined elements of the source code. For example, the software synchronization system may globally rename references to the class name in the source code based on the new name given to the model element by the developer. Thus, the software synchronization system synchronizes the abstract model and the source code, regardless of the one to which the developer makes changes. 
     In some embodiments, the software synchronization system synchronizes the abstract model and the source code for a variety of types of changes. For example, the developer may rename a variable in the source code that he defined in the model, and the software synchronization system will propagate the renamed variable into the model and throughout the rest of the source code. The developer may also change the return type of a function, a parameter type of a function, add or remove parameters, change the type of a field, change the hierarchical relationship of classes, and so on. In addition, the developer may change the cardinality of a relationship in the model (e.g., from “one” to “many”). In this case, the software synchronization system changes the developer source code accordingly, such as by replacing a single variable with a collection type (e.g., an ICollection derived class when using .NET). Changes can originate in either the abstract model or the source code. For each type of change, the software synchronization system modifies the appropriate elements of both the abstract model and the source code to keep the two in sync. 
     In some embodiments, the software synchronization system performs changes within a transaction scope. If many parts of the software need to change because of a modification made by a developer, then the developer may want the software synchronization system to make all of the changes or none of the changes. Otherwise, the system could leave the software in a nonworking state. Therefore, the software synchronization system can enforce transaction semantics such that each change is attempted, and if any of the changes fail, the system rolls back all of the previous changes. The software synchronization system commits the transaction when all of the changes in both the abstract model and the source code succeed. 
     In some embodiments, the software synchronization system uses partial classes to separate generated source code from developer-added source code. A partial class is a class that is divided into two or more parts (e.g., split over multiple files), making it easier to deal with large quantities of code. At compile time, the compiler groups the elements from each part of the partial class together, thus logically making the output the same as if the class were defined in one place. Partial classes can make automatically generated code easier to interpret by separating the generated code from developer-added code. Version 2.0 of the Microsoft .NET Framework introduced partial class support in both C# and Visual Basic.NET. By using partial classes, the software synchronization system can modify the model and regenerate the generated code without interfering with code that the developer has added. The software synchronization system can then separately propagate a change to the developer-added source code. 
     Example Environment 
       FIG. 1  illustrates an example environment in which the software synchronization system may be used. A developer uses a model tool  110  to create an abstract model of the software. For example, the developer may create a model that outlines the major logical objects (e.g., classes) that the software project will contain. The model tool  110  stores the model created by the developer in a model store  120 . For example, the model store  120  may be a file on a disk, a database, or another storage device. When the developer is satisfied with the model, the developer instructs the model tool  110  to generate code in accordance with the model. For example, the model tool  110  may create C++ header and source files that define each of the classes and contain placeholders where the developer can fill in additional implementation details. When the code is generated, the model tool  110  passes control to a development environment  130  where the developer can edit the generated code, add additional code, and so forth. The generated code and the code the developer writes are stored in a code store  140 . 
     A software synchronization system  150  introduces the ability to keep the model and code in sync when either the model or the code is changed. When the model changes, the synchronization system  150  detects that an elements has changed in the model tool  110 , for example, by receiving an event from the model tool  110 . The software synchronization system  150  then instructs the development environment  130  to update the corresponding elements in the code. For example, if the developer renamed a model element IFoo to IBar, then the software synchronization system  150  instructs the development environment  130  to rename instances of IFoo to IBar in the code. 
     The other direction, reflecting changes to the code in the model, uses an association between the model and code for each element, called a NamingManager, that is generated by the model tool  110  when the code is generated. For example, the NamingManager may be defined in a C++ attribute within the code that does not affect the compiled software but is accessible during development. When a user loads a project, the development environment  130  informs the software synchronization system  150  through a load event. At that time, the software synchronization system  150  loads each NamingManager to track later changes to code elements. For example, the software synchronization system  150  can use reflection to identify each NamingManager attribute and instantiate a corresponding class that registers with the development environment  130  to receive element change events. When an element with a NamingManager changes, the development environment  130  informs the software synchronization system  150  through an element change event. Then the software synchronization system  150  informs the model tool  110 . 
     Mapping Between Model Elements and Code Elements 
     The software synchronization system consists of three major components: a component that provides a mapping between model elements and corresponding code elements, a component that listens for changes in the model and triggers updates in the associated code, and a component that performs source code updates. This section describes the operation of the first of these components in further detail. 
     In some embodiments, an INamingManager interface provides the means to obtain the full name of a code element through a method GetFullName. This interface is defined in part as follows: 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 interface INamingManager 
               
               
                   
                 { 
               
               
                   
                  string GetFullName (string namingToken, ModelElement mel, 
               
               
                   
                  CodeGenerationLanguage codeGenerationLanguage) 
               
               
                   
                 } 
               
               
                   
                   
               
            
           
         
       
     
     To consistently modify elements of the source code, the software synchronization system determines both the old and the new states of the code element. For example, if the change is a rename, then the software synchronization system uses the old name to find elements that need to be modified and uses the new name to modify the found elements. The GetFullName method helps to calculate both old and new names of a given code element. GetFullName takes the following parameters: namingToken—the model element attribute defining the part of the code element name that changed; mel—the model element that is being modified, that defines rules for constructing the code element name, and that contains namespace information; and codeGenerationLanguage—the target language for the code generation. The target language affects how the element name is constructed. For example, in C#, the name of a property and the name of the field backing it differ only in their casing, but in VB.NET, the field name is also suffixed with “Value.” 
     In some embodiments, a NamingManager abstract base class partially implements INamingManager. Each model element with generated code has an implementation of INamingManager. A given model element need only derive from this class and implement the CalculateFullName method. GetFullName calls CalculateFullName to perform steps specific to a given model element. This abstract class is defined as: 
     
       
         
           
               
             
               
                   
               
             
            
               
                 internal abstract class NamingManager&lt;T&gt; : INamingManager where T : 
               
               
                 ModelElement 
               
               
                 { 
               
               
                  // Implementation of INamingManager interface 
               
               
                  public string GetFullName (string namingToken, T mel, 
               
               
                  CodeGenerationLanguage codeGenerationLanguage); 
               
               
                  // implemented by each concrete NamingManager 
               
               
                  abstract protected string CalculateFullName(string 
               
               
                  namingToken, ModelElement mel, CodeGenerationLanguage 
               
               
                  codeGenerationLanguage) {...} 
               
               
                 } 
               
               
                   
               
            
           
         
       
     
     In some embodiments, each model element with corresponding generated code has a derivative of NamingManager for each type of element for which the software synchronization system handles changes. For example, the software synchronization system creates an EntityNamingManager for handling changes to the element itself or related class code, a PropertyNamingManager for handling changes to properties, and a FieldPropertyNamingManager for handling changes to fields. Each class corresponds to exactly one code element generated from the model element. The following is an example of a FieldPropertyNamingManager class. 
     
       
         
           
               
               
             
               
                   
                   
               
             
            
               
                   
                 [NamingManagerFor(typeof(DesignTimeMetaModel.PropertyInfo), 
               
               
                   
                 NamedElement.NameMetaAttributeGuidString, ElementKind.Field)] 
               
               
                   
                 internal class FieldPropertyNamingManager : 
               
               
                   
                 NamingManager&lt;DesignTimeMetaModel.PropertyInfo&gt; 
               
               
                   
                 { 
               
               
                   
                    ... 
               
               
                   
                 } 
               
               
                   
                   
               
            
           
         
       
     
     In some embodiments, the software synchronization system implements CalculateFullName by concatenating the values of several attributes and special prefixes or suffixes (e.g., “Destination”) for a property produced from an associated model element. The software synchronization system can use the resulting string to detect multiple types of changes to the corresponding code element. 
     In some embodiments, each derivative of NamingManager has the NamingManagerFor attribute applied to it. This attribute specifies the model element corresponding to the NamingManager instance, which model element&#39;s property causes the change of a corresponding code element (e.g., Name), and the kind of code element. The information in this attribute enables the software synchronization system to generically listen for changes in the abstract model and trigger the corresponding changes in the source code. For example, Visual Studio provides an event interface that receives an indication when changes occur to any element with this attribute. 
     Detecting Changes 
     As discussed above, the software synchronization system consists of three major components: a component that provides a mapping between model elements and corresponding code elements, a component that listens for changes in the model and triggers updates in the associated code, and a component that performs source code updates. This section describes the operation of the second of these components in further detail. 
     In some embodiments, the software synchronization system inspects each code assembly using .NET reflection when the development environment loads, discovers all NamingManagerFor attributes, and uses the discovered attributes to subscribe to relevant change events in the model. Visual Studio, for example, provides the ability to register for changes to an abstract model. For example, the NamingManagerFor attribute on PropertyNamingManager indicates that an event listener can be registered to detect property change events so that code can be regenerated when a property changes. Thus, when the development environment is loaded, the software synchronization system can register to receive notification of any changes in the model. 
     When the development environment passes a change in the model to a registered event handler, the software synchronization system looks at the list of discovered NamingManager classes to find ones correlated to the changed model element type. If the software synchronization system discovers a match for the changed model element, then the system uses the NamingManager class to calculate the old and new names of the code element. The NamingManager then executes code updates accordingly. 
     In some embodiments, if the developer changes the code first, such that the model needs to be updated, then the software synchronization system locates the model element through the mapping of the model element to the code element name collected when the development environment loaded the software project. As described above, the software synchronization system can use reflection when a project is loaded to create an initial association between model and code elements. Then the software synchronization system can extract the model element name from the code element name or from other stored information. After locating the model element, the software synchronization system performs the change on the model element, and then the system proceeds as described above when a model change occurs. The system may prompt the developer to ask if it is okay to proceed with the model element change to ensure that the developer did not accidentally cause the change. 
     Updating Source Code 
     As discussed above, the software synchronization system consists of three major components: a component that provides a mapping between model elements and corresponding code elements, a component that listens for changes in the model and triggers updates in the associated code, and a component that performs source code updates. This section describes the operation of the third component in further detail. 
     In some embodiments, the software synchronization system invokes an existing tool to propagate a change. For example, many popular development environments (e.g., Visual Studio) provide a global rename operation (also known as rename refactoring) for renaming variables or other definitions in source code. If a developer makes a change to one part of the model or the source code, the software synchronization system can invoke an appropriate operation of the existing tool. For example, the software synchronization system may propagate the change throughout the abstract model and invoke the global rename function of Visual Studio to propagate the change throughout the source code. 
     In some embodiments, the software synchronization system uses the Microsoft Visual Studio Code Model Application Programming Interface (API) to find the existing declaration of the code element based on the calculated old code element name. The Visual Studio code model offers automation clients the ability to discover code definitions in a project and modify those code elements. The code model automatically updates all referenced objects when a developer makes modifications in the code editor. The code model allows automation clients to avoid implementing a parser for Visual Studio languages in order to discover the high-level definitions in a project, such as classes, interfaces, structures, methods, properties, and so on. After the software synchronization system finds the correct declaration using the code model API, the system invokes the Microsoft Visual Studio rename refactoring API as described above to update the code with the new code element name. 
     Figures 
     The following figures illustrate some embodiments of the features of the software synchronization system described above. 
       FIG. 2  is a block diagram that illustrates the components of the software synchronization system in one embodiment. A software synchronization system  200  contains a model store component  210 , a code store component  220 , a generate code component  230 , a map elements component  240 , a detect change component  250 , an update model component  260 , and an update code component  270 . The model store component  210  stores a persistent version of the abstract model. The code store component  220  stores a persistent version of the source code. The generate code component  230  generates part of the source code using the information in the abstract model. The map elements component  240  identifies source code elements associated with a given model element and vice versa. The detect change component  250  detects when a developer changes a model element or a source code element and notifies other components. The update model component  260  updates the model based on changes detected to the source code. The update code component  270  updates the source code based on changes detected to the model. 
     The computing device on which the system is implemented may include a central processing unit, memory, input devices (e.g., keyboard and pointing devices), output devices (e.g., display devices), and storage devices (e.g., disk drives). The memory and storage devices are computer-readable media that may be encoded with computer-executable instructions that implement the system, which means a computer-readable medium that contains the instructions. In addition, the data structures and message structures may be stored or transmitted via a data transmission medium, such as a signal on a communication link. Various communication links may be used, such as the Internet, a local area network, a wide area network, a point-to-point dial-up connection, a cell phone network, and so on. 
     Embodiments of the system may be implemented in various operating environments that include personal computers, server computers, handheld or laptop devices, multiprocessor systems, microprocessor-based systems, programmable consumer electronics, digital cameras, network PCs, minicomputers, mainframe computers, distributed computing environments that include any of the above systems or devices, and so on. The computer systems may be cell phones, personal digital assistants, smart phones, personal computers, programmable consumer electronics, digital cameras, and so on. 
     The system may be described in the general context of computer-executable instructions, such as program modules, executed by one or more computers or other devices. Generally, program modules include routines, programs, objects, components, data structures, and so on that perform particular tasks or implement particular abstract data types. Typically, the functionality of the program modules may be combined or distributed as desired in various embodiments. 
       FIG. 3  is a flow diagram that illustrates the processing of the detect change component at load time in one embodiment. The component is initially invoked when a development environment that uses the software synchronization system loads a software project. In block  310 , the component determines the elements to be monitored for changes. For example, the component may use reflection to identify model or code elements flagged with an attribute that indicates that the component should propagate changes to that element throughout the project. In block  320 , the component registers a handler for events indicating that one of the determined elements changed. For example, the component may use an interface provided by the development environment for detecting code or model changes. In decision block  330 , if the component receives an event notification, then the component continues at block  340 , else the component loops to block  330  and waits for receipt of an event. 
     In block  340 , the component updates the model based on the detected change. For example, if the developer renamed a class, then the component renames all references to that class in the model. In block  350 , the component prompts the generate code component to regenerate code based on the updated model. In block  360 , the component updates the added source code (e.g., the code that is not generated) based on the change. After block  360 , these steps conclude. 
       FIG. 4  is a flow diagram that illustrates the processing of the detect change component when a model change is detected in one embodiment. In block  410 , the component identifies the model element that changed. In block  420 , the component updates references to the changed element throughout the model. In block  430 , the component determines code elements that depend on the changed model element. In block  440 , the component updates the determined code elements. For example, if a variable is renamed, the software synchronization system updates the name first in the model and then in the source code. After block  440 , these steps conclude. 
       FIG. 5  is a flow diagram that illustrates the processing of the detect change component when a code change is detected in one embodiment. In block  510 , the component identifies the code element that changed. For example, the component may receive a name of the changed element from an event interface and then query the elements of the software project to find a matching name. In block  520 , the component identifies a related model element. For example, the component may inspect the identified code element to determine whether an association exists with a particular model element. In block  530 , the component modifies the identified related model element. In block  540 , the component invokes the process described in  FIG. 4  to propagate the detected change throughout the project. After block  540 , these steps conclude. 
     From the foregoing, it will be appreciated that specific embodiments of the software synchronization system have been described herein for purposes of illustration, but that various modifications may be made without deviating from the spirit and scope of the invention. For example, although software has been described, other fields where a model and a document are closely related could also use the methods described. UML in particular is a modeling language suitable for modeling many systems and is often used in fields other than software. Accordingly, the invention is not limited except as by the appended claims.