Scripted objects migration/fr

Introduction
Les Objets créés par script sont reconstruits à chaque fois qu'un document au format FCStd est ouvert. Pour ce faire, le document conserve une référence au module et à la classe Python qui ont été utilisés pour créer l'objet, ainsi que ses propriétés.

Concentrez-vous particulièrement sur cette partie :

Si la valeur de  ou   n'est pas trouvée sur le système installé, l'objet ne pourra pas être chargé correctement. Cela signifie qu'une fois qu'un objet est créé en utilisant une classe particulière, le module ne doit plus être déplacé ou renommé, car si cela est fait, les objets précédemment enregistrés se briseront.

Toutefois, une raison valable pour déplacer ou renommer le module ou la classe est d'améliorer la structure et la maintenabilité du code d'origine, par exemple, lors de la restructuration d'un atelier entier. Dans ce cas, il existe plusieurs stratégies pour faire migrer les anciens objets vers l'utilisation d'une nouvelle classe. Ceci est fait afin de conserver la compatibilité ascendante, lorsque la rupture pure et simple des anciens documents doit être évitée.

Ancien objet
Un ancien objet est défini dans un module qui se trouve à la racine de l'atelier.

Un objet peut être créé à l'aide de cette classe et il peut être enregistré dans. Si aucun viewprovider particulier n'est attribué au nouvel objet, sa classe proxy est simplement définie sur une valeur différente de, dans ce cas, sur.

Une session de console Python avec les propriétés de base omises.

Nouvel objet
Considérons maintenant que l'atelier est restructuré, de sorte que les classes ne se trouvent pas seulement dans le répertoire racine, mais plutôt dans un répertoire. Les ateliers complexes qui comportent de nombreux types d'objets différents devraient être structurés en répertoires comprenant des objets, des interfaces viewproviders, Commandes Gui, Panneau des tâches, etc.

Cette nouvelle classe fera référence au même type d'objet, mais le nom du module ainsi que le nom de la classe ont été renommés. De plus, les propriétés ont également changé ; une propriété a été renommée et une propriété complètement nouvelle a été ajoutée.

Si nous créons un nouvel objet avec ce nouveau module, nous aurons la session de console suivante.

Méthode 1. Migration en redirigeant la classe
Nous allons migrer l'ancien objet en redirigeant l'ancienne classe. La classe originale est supprimée, et le nom de la classe est simplement redirigé pour pointer vers la nouvelle classe.

Tout document qui tente de charger sera redirigé pour charger  à la place.

Si nous ouvrons le document et inspectons les propriétés de l'objet dans la console Python, nous verrons que les anciennes propriétés sont conservées, mais que l'objet a une nouvelle classe Proxy.

Cependant, dans ce cas, nous ne voyons pas les nouvelles propriétés de la nouvelle classe. La raison en est simplement que l'ancien objet ne possédait pas ces propriétés. Lorsque a été redirigé vers, seule la classe proxy a changé, mais les informations précédentes ont été conservées.

Désormais, si le document est enregistré et rouvert, il recherchera automatiquement et ne nécessitera plus. Le fichier peut être supprimé définitivement du système tant que tous les anciens objets ont été migrés vers le nouveau module. Si l'ancien module est supprimé mais qu'un objet n'a pas été migré, la Vue rapport affichera un message comme celui-ci lors de l'ouverture d'un document contenant cet objet.

S'il n'est pas possible, de manière réaliste, de migrer tous les anciens objets, par exemple parce que l'ancien module a été utilisé dans un atelier pendant de nombreuses années, alors doit être conservé aussi longtemps qu'il est jugé nécessaire pour donner aux utilisateurs la possibilité de migrer leurs objets.

Avantages et inconvénients
Avantages


 * Edit_OK.svg C'est la méthode la plus simple qui nécessite juste de rediriger une ancienne classe vers une nouvelle classe.
 * Edit_OK.svg Les anciennes propriétés sont conservées tant que la nouvelle classe ne les surcharge pas.
 * Edit_OK.svg C'est une bonne chose si l'ancienne et la nouvelle classe ont les mêmes propriétés (gèrent le même type de données) mais que seul leur nom de module ou de classe est différent.

Inconvénients


 * Edit_Cancel.svg La nouvelle classe conserve les anciennes propriétés de l'objet, ce qui n'est pas toujours souhaité.
 * Edit_Cancel.svg Les nouvelles propriétés ou les propriétés renommées ne sont pas gérées, donc l'objet sera chargé mais il peut ne pas montrer le comportement correct de la nouvelle classe.
 * Edit_Cancel.svg L'ancien module peut devoir être conservé indéfiniment pour migrer tous les anciens objets créés dans le passé.

Méthode 2. Migration lors de la restauration du document
Nous allons migrer l'ancien objet en modifiant l'ancienne classe. La majorité de la classe d'origine est supprimée et à la place la méthode est implémentée. Lorsque cette méthode existe, elle s'exécute lorsque le document tente de restaurer un objet qui utilise la classe. C'est donc l'occasion pour nous d'attribuer une nouvelle classe, de manipuler les informations ou d'imprimer des messages.

Dans ce cas, nous supposons que nous avons également défini un nouveau viewprovider dans le module. Si nous ne voulons pas migrer cette classe, nous pouvons omettre tout ce qui se trouve après la vérification.

Un exemple plus complexe vérifie d'abord que la classe proxy est du type que nous recherchons, et ne procède à la migration que si c'est le bon type.

En supposant que nous avons déjà modifié l'ancien module de cette manière, si nous ouvrons un document avec un ancien objet, nous verrons les messages mentionnant l'utilisation des nouvelles classes.

En inspectant l'objet depuis la console Python, nous verrons que les anciennes propriétés sont conservées, et qu'en plus, de nouvelles propriétés ont été ajoutées avec la nouvelle classe Proxy.

Les anciennes propriétés étaient et  ; les nouvelles propriétés sont,  et. L'objet migré conserve les deux propriétés d'origine et acquiert trois nouvelles propriétés. Cependant, comme la nouvelle a le même nom que l'ancienne propriété, la nouvelle propriété est renommée avec un numéro incrémental. Ce n'est sans doute pas ce que nous voulons. Nous pouvons améliorer la situation en suivant l'addendum 2.1 ci-dessous.

Étant donné que les classes sont censées gérer le même type d'objet, nous aimerions une migration dans laquelle se transforme en, et  est simplement affecté au nouveau , et il n'y a pas de propriétés en double.

Avantages et inconvénients
Avantages


 * Edit_OK.svg Cette méthode nous permet de vérifier que la classe que nous migrons est la bonne, au lieu de simplement rediriger vers une classe plus récente.
 * Edit_OK.svg Similaire à la méthode 1, les anciennes propriétés sont conservées tant que la nouvelle classe ne les surcharge pas.
 * Edit_OK.svg Contrairement à la méthode 1, les nouvelles propriétés sont toujours ajoutées, cependant si elles ont le même nom, elles seront renommées.
 * Edit_OK.svg La migration n'est pas immédiate, on peut encore manipuler les informations, ou imprimer des messages pendant que l'objet se charge.

Inconvénients


 * Edit_Cancel.svg Elle est plus verbeuse que la méthode 1 car nous devons implémenter la méthode pour migrer l'objet.
 * Edit_Cancel.svg Il ajoute toujours les nouvelles propriétés, donc il peut créer des propriétés dupliquées dans le cas où les nouvelles propriétés ont le même nom que les anciennes propriétés. Ceci doit être géré manuellement.

Méthode 3. Migration lors de la restauration du document, manipulation manuelle des propriétés
Il s'agit d'une extension de la méthode 2. Dans la méthode, nous devons enregistrer les valeurs des propriétés que nous voulons, puis nous pouvons supprimer ces propriétés originales. Ainsi, lorsque la nouvelle classe sera utilisée, elle attribuera les nouvelles propriétés sans risquer de collision de noms avec les anciennes propriétés.

Comme dans la méthode 2, si nous le souhaitons, nous pouvons également ajouter le morceau de code qui vérifie que la classe Proxy est la bonne. Dans cet exemple, nous supposons une fois de plus que nous utilisons un viewprovider personnalisé, avec au moins une propriété personnalisée.

Nous pouvons voir que les anciennes valeurs sont stockées dans un dictionnaire auxiliaire, puis les anciennes propriétés sont supprimées, puis nous ajoutons la nouvelle classe, et enfin nous assignons les valeurs précédemment sauvegardées aux nouvelles propriétés. À ce moment, nous pouvons transformer les valeurs sauvegardées comme il se doit pour la nouvelle classe. Par exemple, le est fixé à 3 fois l'ancien, et le nouveau  reçoit simplement la valeur de l'ancien. Comme nous savons comment l'ancienne et la nouvelle classe sont censées se comporter, nous avons la liberté de manipuler les données pour faire migrer l'objet comme nous le souhaitons.

Nous ne pouvons supprimer que les propriétés qui ont été ajoutées par les classes Python lorsque nous avons construit l'Objet créé par script. Les autres attributs appartiennent à l'objet C++ de base et ne peuvent pas être supprimés.

En supposant que nous avons déjà modifié l'ancien module de cette manière, si nous ouvrons un document avec un ancien objet, nous verrons les messages mentionnant l'utilisation des nouvelles classes. En inspectant l'objet depuis la console Python, nous voyons que les anciennes propriétés ont été supprimées et que seules les nouvelles propriétés existent.

Comme la propriété n'existait pas dans l'ancienne classe, rien n'a été fait avec elle. Elle a simplement été créée par la nouvelle classe.

Avantages et inconvénients
Avantages


 * Edit_OK.svg Similaire à la méthode 2, cette méthode nous permet de vérifier que la classe que nous migrons est la bonne.
 * Edit_OK.svg Nous avons le contrôle total de ce qu'il faut faire avec les anciennes propriétés. Typiquement, elles seront supprimées afin qu'il n'y ait pas de collision de noms avec les nouvelles propriétés ajoutées. Ainsi nous évitons les propriétés dupliquées.
 * Edit_OK.svg En sauvegardant les anciennes valeurs, nous pouvons manipuler les informations de l'étape de restauration comme nous le souhaitons, et affecter les valeurs correspondantes aux nouvelles propriétés.

Inconvénients


 * Edit_Cancel.svg Cette méthode est très verbeuse par rapport aux précédentes, car nous devons implémenter la méthode, et traiter chacune des propriétés individuellement (enregistrer la valeur, supprimer la propriété, réassigner la valeur). Ceci est problématique si l'objet que nous voulons migrer possède de nombreuses propriétés, ou si leurs valeurs doivent être transformées de manière très spéciale.

Addendum A. Créer les propriétés uniquement si elles n'existent pas déjà
L'un des inconvénients de la méthode 2 est qu'elle essaiera toujours d'ajouter les nouvelles propriétés. Si les anciennes propriétés ont le même nom que les nouvelles, elles seront dupliquées avec un numéro incrémental, ainsi donnera, puis , et ainsi de suite. Cela fait de la méthode 2 une option irréaliste dans la plupart des cas, car la nouvelle classe n'utilisera de toute façon qu'une seule propriété.

Pour améliorer cette méthode, la nouvelle classe peut également être modifiée pour n'ajouter les propriétés que si elles n'existent pas déjà sous le même nom.

Dans ce cas, puisque existe déjà, elle ne sera pas ajoutée à nouveau ;  et  n'existent pas, elles seront donc ajoutées. Et comme précédemment, sera conservé car il n'est pas explicitement supprimé, bien qu'il ne soit peut-être plus utilisé dans la nouvelle classe.

La même chose peut être faite pour la classe du viewprovider.

En utilisant cette méthode 2 + A, le résultat est similaire à la méthode 1 en ce sens que l'objet conservera toutes les propriétés précédentes, mais en plus il gagnera les nouvelles propriétés fournies par la nouvelle classe.

La méthode 3 n'a pas besoin de cet addendum à la nouvelle classe car les anciennes propriétés sont explicitement supprimées, il n'y aura donc aucun conflit lors de l'installation des nouvelles propriétés. Néanmoins, c'est toujours une bonne pratique que chaque classe ajoute ses propriétés requises seulement si celles-ci n'existent pas déjà. Ceci est utile à la fois dans le cas de la création de nouveaux Objets créés par script ou de leur migration.

Avantages et inconvénients
Avantages


 * Edit_OK.svg The object will retain all previous properties, but in addition it will gain new properties without repetition.

Disadvantages


 * Edit_Cancel.svg Like method 2, it still doesn't deal with renamed properties. The old properties should be manually removed.

Addendum B. Migrating different versions of the old object
Method 3 is the most complex method because the properties are handled individually. However, in this method we also have full flexibility in how we manipulate the data, and this is an advantage if we want to do complex operations.

If from the beginning we create a property that holds the version number of our object, we can use this number in the future to perform specific migration from that version to any other. We set the property to be read-only, so that we cannot overwrite it in the property editor, although it is still accessible from the Python console.

Then, when we want to migrate the object, we implement the method, and test for this version.

We don't save the value as we will set a new  number when doing the migration. As shown in the example, we can implement various functions for each corresponding version of the object that we intend to migrate. We omit the migration of the viewprovider properties but it follows the same pattern.

Advantages and disadvantages
Advantages


 * Edit_OK.svg We have complete control of what to do with the old properties, and how to perform the migration.
 * Edit_OK.svg We can implement a particular method to migrate a particular version of the old object.

Disadvantages


 * Edit_Cancel.svg This method is very verbose because we must have a clear idea on how to handle each of the properties of each "version" that we want to migrate. If our object has many different versions created over the years, we may have to prepare a long list of methods to migrate them to the newest object.

Addendum B2. Using internal class attributes instead of properties
Instead of using a property of the object to hold the version information, we can use an attribute of the class. In this way we "hide" the version information, because properties are normally public, and visible in the property editor, while class attributes can only be manipulated from the Python console. Class attributes can be saved and restored as explained in Scripted objects saving attributes.

This attribute is inspected by looking at the attribute.

Then the file is modified to migrate the object.

When we install the new class, this new class should set the new value of the version attribute, for example,.

Addendum C. Method 3 without removing old properties that are named the same
Like in Addendum A, we can write the new class to create properties only if they aren't already present. Using method 3, we save the values of the older properties, and subsequently delete the older properties. However, if the new properties are named the same as the older ones, we don't need to delete the older ones, we can just reuse the same property, as we know the property won't be duplicated. If we are using Addendum B, we have a way to query the version as well.

As we see in the example, the old property is deleted and migrated to the new  property as usual. We do not need to delete nor  because in the new class they are still used with the same name, and they won't be created again (addendum A). As we don't want to modify, this property is not touched at all; it is migrated to the new class silently. However, we do update to the new value. We omit the migration of the viewprovider properties but it follows the same pattern.

This should work like method 3, meaning that the old properties are removed and only the new properties remain in the new object. The only difference is that we omit removing and recreating the properties that are named the same. This process should work as long as the old property and the new property have the same type (for example, or ), so the old property can pass its value directly. However, if the new property has a different type than the old property, then the old property should be removed, otherwise the old property will completely overwrite the new property, which is probably not what we want because the new class will be expecting the new type and not the old type.

Advantages and disadvantages
Advantages


 * Edit_OK.svg Like method 3, this method allows us complete control of the migration of the old information.
 * Edit_OK.svg We avoid writing code that removes and recreates properties that are named the same.

Disadvantages


 * Edit_Cancel.svg Like method 3, this method is still very verbose because we have to handle the properties carefully.
 * Edit_Cancel.svg If a new property and an old property share the same name, the new property will be overwritten, which may be undesired behavior, especially if the two properties have different types. In this case, removing the old property, and migrating its value manually is still necessary.

Summary
Each of the methods has a recommended use:
 * Method 1. The module is moved or renamed but the properties are the same. Simple redirection of classes because the properties don't need to be modified at all.
 * Method 2+A. Simple migration scenarios. Display a message when the object is migrated from one class to another. The properties are of the same type and don't need to be modified at all.
 * Method 3, 3+A, or 3+B. Complex migration scenarios. Full control of the properties, deleting the old properties, and adding new properties. An identifier to know the version of the object is useful to choose the right function to perform the migration (Addendum B or B2).

Preferably avoid the following:
 * Method 2. The properties will be duplicated if the new class doesn't check for existing properties (Addendum A).
 * Method 3+C. Use only when the old properties and the new properties are of the same type. Otherwise use method 3 or 3+B to remove older properties, and handle them exactly as needed.

Links

 * Migrating and upgrading old scripted objects
 * Migrate old scripted objects