UUID est un standard qui permet d'être sûr que les chaà®nes générées sont uniques dans la galaxie tout entière. (après c'est sûr que je ne me suis jamais penché sur le moteur qui les génère).
Par exemple dans le cas de muqaddar, il lui faut des identifiants qui soient uniques pour identifier les différents éléments de sa base, base qui est synchronisée entre plusieurs iPhones. Donc il faut que chaque iPhone génère pour chaque fiche de sa base, non seulement un identifiant qui va être unique localement, mais aussi mondialement, pour que si 2 iPhones différents génèrent chacun une fiche différente dans leur coin, il soit sur que ces deux fiches, malgré qu'elles aient été générées sur des devices qui n'ont rien à voir l'un avec l'autre, aient un identifiant différent l'une de l'autre. Comme ça quand il synchronise tout et fusionne les bases des différents utilisateurs, il n'y a pas conflit.
Mais bon les UUID peuvent servir à bien d'autres choses. Dans mon framework JSON-RPC pour iPhone/Cocoa, je les utilise pour générer des identifiants uniques pour les requêtes JSON que j'envoie, car cet identifiant est ensuite utilisé pour faire correspondre chaque requête et sa réponse, donc il ne faut pas que j'utilise 2x le même, idéalement même si j'utilise plusieurs instances de ma classe JSONRPCService (donc je ne peux pas gérer une sorte de compteur interne qui va s'incrémenter à chaque requête car une autre instance risquerait de générer exactement les mêmes numéros)
1) En tout cas, je me pose toujours la question de savoir si je passe mes clés étrangères en mode UUID également.
Par exemple, dans la table wines, on ajoute à :
- id<br />- productor_id
- uuid<br />- productor_uuid
qui permet de ne plus avoir de soucis sur les clés étrangères à long terme et lors des sync. Mais du coup, je dois modifier tous mes modèles.
2) L'autre solution est de dealer chaque clé secondaire lors des synchros, ce qui veut dire : - vérifier la nouvelle valeur de la clé primaire après sync, mettre à jour la clé secondaire en conséquence... et tout ça à chaque fois. Je trouve cela dangereux.
Bah en même temps je crois que t'as pas trop le choix : idéalement tu aurais dû penser à cet aspect unique des ID au moment de ta conception d'origine, donc vu que ça n'était pas à l'ordre du jour à l'époque et que tu vas donc devoir refactorer, bah il va falloir adapter ton modèle (normal, c'est bien ton modèle et ta base que tu changes, là )...
Bah en même temps je crois que t'as pas trop le choix : idéalement tu aurais dû penser à cet aspect unique des ID au moment de ta conception d'origine, donc vu que ça n'était pas à l'ordre du jour à l'époque et que tu vas donc devoir refactorer, bah il va falloir adapter ton modèle (normal, c'est bien ton modèle et ta base que tu changes, là )...
Je savais que je ferai une synchro un jour, mais tu crois que j'avais pensé au coup des clés primaires uniques sur chaque device qui entrent en collision ? 8--) Faut être tombé dedans pour s'en rendre compte.
Bon j'ai déjà écrit le code SQL qui va mettre à jour toute la base. Donc il me faut réécrire mes modèles maintenant (et aussi un peu de contrôleur).
Par exemple dans le cas de muqaddar, il lui faut des identifiants qui soient uniques pour identifier les différents éléments de sa base, base qui est synchronisée entre plusieurs iPhones. Donc il faut que chaque iPhone génère pour chaque fiche de sa base, non seulement un identifiant qui va être unique localement, mais aussi mondialement, pour que si 2 iPhones différents génèrent chacun une fiche différente dans leur coin, il soit sur que ces deux fiches, malgré qu'elles aient été générées sur des devices qui n'ont rien à voir l'un avec l'autre, aient un identifiant différent l'une de l'autre. Comme ça quand il synchronise tout et fusionne les bases des différents utilisateurs, il n'y a pas conflit.
Mais bon les UUID peuvent servir à bien d'autres choses. Dans mon framework JSON-RPC pour iPhone/Cocoa, je les utilise pour générer des identifiants uniques pour les requêtes JSON que j'envoie, car cet identifiant est ensuite utilisé pour faire correspondre chaque requête et sa réponse, donc il ne faut pas que j'utilise 2x le même, idéalement même si j'utilise plusieurs instances de ma classe JSONRPCService (donc je ne peux pas gérer une sorte de compteur interne qui va s'incrémenter à chaque requête car une autre instance risquerait de générer exactement les mêmes numéros)
Puisqu'on parle d'iPhone, on peut supposer CoreData : et pour rappel, en CoreData les NSManagedObject ont une méthode objectID qui renvoit un NSManagedObjectID :
"An NSManagedObjectID object is a compact, universal, identifier for a managed object. This forms the basis for uniquing in the Core Data Framework. A managed object ID uniquely identifies the same managed object both between managed object contexts in a single application, and in multiple applications (as in distributed systems). Identifiers contain the information needed to exactly describe an object in a persistent store (like the primary key in the database), although the detailed information is not exposed. The framework completely encapsulates the “external†information and presents a clean object oriented interface."
Donc utiliser des UUID n'apporte pas grand chose dans le contexte CoreData, sauf à vouloir simplifier l'éventuel portage pour un autre SGDB... et il vaut mieux connaà®tre un minimum du pour et du contre à l'utilisation des UUIDs dans un SGBD :
- tous les SGBDs n'ont pas un type UUID natif (128 bits) et une clé unique de 32 caractères minimum peut avoir un impact sur les performances car les UUIDs étant lexicographiquement parlant aléatoires (contrairement à une SEQUENCE), cela a un impact sur l'allocation des pages d'indexation (les index prendront plus de place sur disque...) : on se retrouve avec beaucoup de pages d'index presque vides... ce qui a un impact sur les performances... - en situation client-serveur, attention à où la clé est générée car si plusieurs types de clients différents accèdent à la même DB si l'UUID est stocké sous forme de chaà®ne (case sensitivity) - par rapport à une SEQUENCE, on perd l'ordre d'insertion des records : il peut être nécessaire d'ajouter un champ si cette information est pertinente pour l'application - ...
même si plusieurs de remarques ne sont pertinentes que pour des très grosses bases... mieux vaut le savoir...
Reste la question : dans le cadre d'un application iPhone : pourquoi dupliquer la fonctionnalité de -objectID ?
Je n'ai pas vérifié depuis mais sur 10.5 les uuid Core data étaient changé lors du premier enregistrement dans le moc, avant il y en a un temporaire, ce qui peut poser problème...
Réponses
Par exemple dans le cas de muqaddar, il lui faut des identifiants qui soient uniques pour identifier les différents éléments de sa base, base qui est synchronisée entre plusieurs iPhones. Donc il faut que chaque iPhone génère pour chaque fiche de sa base, non seulement un identifiant qui va être unique localement, mais aussi mondialement, pour que si 2 iPhones différents génèrent chacun une fiche différente dans leur coin, il soit sur que ces deux fiches, malgré qu'elles aient été générées sur des devices qui n'ont rien à voir l'un avec l'autre, aient un identifiant différent l'une de l'autre. Comme ça quand il synchronise tout et fusionne les bases des différents utilisateurs, il n'y a pas conflit.
Mais bon les UUID peuvent servir à bien d'autres choses. Dans mon framework JSON-RPC pour iPhone/Cocoa, je les utilise pour générer des identifiants uniques pour les requêtes JSON que j'envoie, car cet identifiant est ensuite utilisé pour faire correspondre chaque requête et sa réponse, donc il ne faut pas que j'utilise 2x le même, idéalement même si j'utilise plusieurs instances de ma classe JSONRPCService (donc je ne peux pas gérer une sorte de compteur interne qui va s'incrémenter à chaque requête car une autre instance risquerait de générer exactement les mêmes numéros)
Par exemple, dans la table wines, on ajoute à :
qui permet de ne plus avoir de soucis sur les clés étrangères à long terme et lors des sync.
Mais du coup, je dois modifier tous mes modèles.
2) L'autre solution est de dealer chaque clé secondaire lors des synchros, ce qui veut dire :
- vérifier la nouvelle valeur de la clé primaire après sync, mettre à jour la clé secondaire en conséquence... et tout ça à chaque fois.
Je trouve cela dangereux.
Je savais que je ferai une synchro un jour, mais tu crois que j'avais pensé au coup des clés primaires uniques sur chaque device qui entrent en collision ? 8--) Faut être tombé dedans pour s'en rendre compte.
Bon j'ai déjà écrit le code SQL qui va mettre à jour toute la base. Donc il me faut réécrire mes modèles maintenant (et aussi un peu de contrôleur).
Bon, j'ai 11 tables concernées sur 45, ça devrait aller. :-)
Le pire, c'est que tout tourne du premier coup après les modifs ! ;D
Vive la couche modèle.
Bon, je vais pouvoir m'atteler à la partie intéressante maintenant. :P
Je sais pas si elle est bonne, mais elle ne doit pas être mauvaise en tout cas. :-)
Puisqu'on parle d'iPhone, on peut supposer CoreData :
et pour rappel, en CoreData les NSManagedObject ont une méthode objectID qui renvoit un NSManagedObjectID :
"An NSManagedObjectID object is a compact, universal, identifier for a managed object. This forms the basis for uniquing in the Core Data Framework. A managed object ID uniquely identifies the same managed object both between managed object contexts in a single application, and in multiple applications (as in distributed systems). Identifiers contain the information needed to exactly describe an object in a persistent store (like the primary key in the database), although the detailed information is not exposed. The framework completely encapsulates the “external†information and presents a clean object oriented interface."
Donc utiliser des UUID n'apporte pas grand chose dans le contexte CoreData, sauf à vouloir simplifier l'éventuel portage pour un autre SGDB...
et il vaut mieux connaà®tre un minimum du pour et du contre à l'utilisation des UUIDs dans un SGBD :
- tous les SGBDs n'ont pas un type UUID natif (128 bits) et une clé unique de 32 caractères minimum peut avoir un impact sur les performances
car les UUIDs étant lexicographiquement parlant aléatoires (contrairement à une SEQUENCE), cela a un impact sur l'allocation des pages d'indexation (les index prendront plus de place sur disque...) : on se retrouve avec beaucoup de pages d'index presque vides... ce qui a un impact sur les performances...
- en situation client-serveur, attention à où la clé est générée car si plusieurs types de clients différents accèdent à la même DB si l'UUID est stocké sous forme de chaà®ne (case sensitivity)
- par rapport à une SEQUENCE, on perd l'ordre d'insertion des records : il peut être nécessaire d'ajouter un champ si cette information est pertinente pour l'application
- ...
même si plusieurs de remarques ne sont pertinentes que pour des très grosses bases... mieux vaut le savoir...
Reste la question : dans le cadre d'un application iPhone : pourquoi dupliquer la fonctionnalité de -objectID ?
Faudrait déjà utiliser CoreData...
EDIT : grilled by Ali.