Cycles dans le logiciel d'arbre généalogique

1594

Je suis le développeur d'un logiciel d'arbre généalogique (écrit en C ++ et Qt). Je n'ai eu aucun problème jusqu'à ce qu'un de mes clients m'envoie un rapport de bogue. Le problème est que le client a deux enfants avec leur propre fille et, par conséquent, il ne peut pas utiliser mon logiciel en raison d'erreurs.

Ces erreurs sont le résultat de mes diverses affirmations et invariants concernant le graphique de famille en cours de traitement (par exemple, après avoir parcouru un cycle, le programme déclare que X ne peut pas être à la fois père et grand-père de Y).

Comment puis-je résoudre ces erreurs sans supprimer toutes les assertions de données?

Partick Höse
la source
30
Si vous tracez votre arbre généalogique suffisamment en arrière, vous rencontrerez ce problème beaucoup plus souvent que vous ne le souhaiteriez. L'abandon de la représentation arborescente peut être douloureux mais serait finalement plus correct.
Thomas
55
Vous ne devez pas ajouter d'assertions pour des choses improbables, seulement des choses impossibles. Les cycles sont les choses évidentes qui ne sont pas possibles dans un graphique d'arbre généalogique ... personne ne peut être son propre ancêtre par quelque méthode que ce soit. Ces autres affirmations sont simplement fausses et devraient être supprimées.
pgod
44
Ce n'est pas du tout une question idiote dans le monde de l'élevage d'animaux de compagnie. La fille du père, la mère du fils, la sœur du frère, les petits-enfants des grands-parents y sont une technique standard, et les éleveurs d'animaux ont également besoin d'un logiciel d'arbre généalogique. "Race pure" mon ¤% # &.
kaleissin
31
Épouser des cousins ​​germains était très courant dans l'Angleterre victorienne, en particulier dans les classes supérieures (c'était un excellent moyen de garder de l'argent au sein de la famille). Charles Darwin, par exemple, a épousé sa cousine germaine, Emma Wedgwood. Tout logiciel d'arbre généalogique doit prendre en charge de telles situations.
rtperson

Réponses:

727

Il semble que vous (et / ou votre entreprise) ayez une incompréhension fondamentale de ce qu'est un arbre généalogique.

Permettez-moi de clarifier, je travaille également pour une entreprise qui a (comme l'un de ses produits) un arbre généalogique dans son portefeuille, et nous avons eu des problèmes similaires.

Le problème, dans notre cas, et je suppose que votre cas aussi, vient du format GEDCOM qui est extrêmement avisé sur ce que devrait être une famille. Cependant, ce format contient de graves idées fausses sur l'apparence réelle d'un arbre généalogique.

GEDCOM a de nombreux problèmes, tels que l'incompatibilité avec les relations homosexuelles, l'inceste, etc ... Ce qui se produit dans la vie réelle plus souvent que vous ne l'imaginez (surtout lorsque vous remontez le temps vers le 1700-1800).

Nous avons modelé notre arbre généalogique sur ce qui se passe dans le monde réel: événements (par exemple, naissances, mariages, fiançailles, unions, décès, adoptions, etc.). Nous ne leur imposons aucune restriction, sauf celles logiquement impossibles (par exemple, on ne peut pas être son propre parent, les relations ont besoin de deux personnes, etc.)

L'absence de validations nous donne une solution plus "réelle", plus simple et plus flexible.

Quant à ce cas spécifique, je suggère de supprimer les affirmations car elles ne sont pas universelles.

Pour afficher les problèmes (qui se poseront), je suggère de dessiner le même nœud autant de fois que nécessaire, en faisant allusion à la duplication en allumant toutes les copies lors de la sélection de l'un d'entre eux.

Bert Goethals
la source
32
Cela ressemble à la bonne approche, et il est assez facile à étendre pour détecter des problèmes plus complexes. Vous pouvez établir un ensemble de relations «A s'est produit avant B» entre les événements. Par exemple, qu'une personne est née avant tout autre événement la concernant. Il s'agit d'un graphique orienté. Vous pouvez ensuite vérifier que le graphique ne contient aucun cycle. Voir cette question sur StackOverflow. Cela devrait être acceptable jusqu'à ce que le voyage dans le temps soit inventé.
Paul Harrison
41
@ paul-harrison Si ce n'était que si simple. Dans les enregistrements plus anciens (même les nouveaux), il existe des incohérences de date. Baptême avant la naissance, plusieurs actes de naissance, etc. Dans une certaine mesure, dans les documents officiels, il y a le voyage dans le temps. Nous autorisons ces données incohérentes. Nous permettons aux utilisateurs d'indiquer ce que l'application devrait considérer "le" registre de naissance en cas de doublons. Et nous indiquerons les délais brisés s'ils sont trouvés.
Bert Goethals
38
@ ben-voigt GEDCOM est un format créé par l'Église de Jésus-Christ des Saints des Derniers Jours. La spécification stipule clairement que le mariage (MARR) doit être entre hommes et femmes. Pour le mariage homosexuel ou l'inceste, la balise ASSO doit être utilisée (ASSOCIÉS), également utilisée pour indiquer l'amitié ou le fait d'être voisins. Il est clair que le mariage homosexuel est une relation de deuxième classe dans cette spécification. Une spécification plus neutre n'exigerait pas de relations hommes-femmes.
Bert Goethals
1
@Bert Goethals: Vous confondez GEDCOM avec certains programmes qui ne prennent pas en charge le mariage homosexuel (PAF, Legacy). GEDCOM n'interdit pas les constructions telles que "0 @ F1 @ FAM / 1 HUSB @ I1 @ / 1 HUSB @ I2 @", et prend donc en charge les mariages homosexuels si votre logiciel le souhaite.
Pierre
1
@Pierre Vous pouvez vraiment tromper le système. Ceci provient directement de la documentation 5.5.1: "MARR {MARRIAGE}: = Un événement légal, de droit commun ou coutumier de créer une unité familiale d'un homme et d'une femme comme mari et femme." ( homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gcappa.htm ) Comme vous pouvez le voir, pas de mariage homosexuel ici.
Bert Goethals
563

Détendez vos affirmations.

Pas en modifiant les règles, qui sont généralement très utiles à 99,9% de vos clients pour détecter les erreurs lors de la saisie de leurs données.

Au lieu de cela, remplacez-le par une erreur «impossible d'ajouter une relation» par un avertissement avec un «ajouter quand même».

Ben Voigt
la source
143
Lorsque vous rencontrez une situation très improbable , c'est-à-dire où un utilisateur ne le fait généralement que par erreur, c'est une bonne idée de lui montrer un avertissement. C'est une bonne rétroaction. Mais laissez ensuite l'utilisateur aller de l'avant s'il est vraiment sûr de le vouloir. Je pense donc que c'est une bonne réponse, même si elle ne rentre pas dans les détails.
thomasrutter
15
Bonne réponse! Je me demande simplement comment ce type de logiciel va gérer la situation "Je suis mon propre grand-père" ( youtube.com/watch?v=eYlJH81dSiw )?
Zaur Nasibov
4
Ce n'est pas vraiment une réponse, parce que je pense que le problème vient de la traversée de l'arbre? Cependant, c'est une bonne suggestion.
bdwakefield
3
@bdwakefield: La question était "Comment puis-je résoudre ces erreurs, sans supprimer toutes les assertions de données?" Je pense avoir répondu à cela.
Ben Voigt
2
@Ben Cela dépend à quoi servent les assertions. S'ils empêchent les boucles infinies ou les erreurs fatales de se produire, alors vous proposez effectivement de supprimer les assertions. S'ils sont juste là pour avertir un utilisateur d'une erreur potentielle, alors votre réponse est bonne.
rm999
224

Voici le problème avec les arbres généalogiques: ce ne sont pas des arbres. Ce sont des graphes acycliques ou DAG dirigés. Si je comprends bien les principes de la biologie de la reproduction humaine, il n'y aura pas de cycles.

Pour autant que je sache, même les chrétiens acceptent les mariages (et donc les enfants) entre cousins, ce qui transformera l'arbre généalogique en un DAG familial.

La morale de l'histoire est: choisissez les bonnes structures de données.

exDM69
la source
7
Il faudrait une restriction supplémentaire de chaque nœud ayant 1 ou 2 nœuds maximum pointant vers lui pour la reproduction in vitro et sexuelle. Bien que pour être plus fidèle à la vie réelle, vous pouvez autoriser plusieurs lignes pointillées pour une descendance incertaine du côté du père (il est toujours clair qui est la mère, mais seuls les tests ADN peuvent assurer qui est le père, et cela est rarement fait même aujourd'hui), ou même pour les deux, l'adoption est prise en compte.
manixrock
7
@manixrock - puisque cette question concerne des cas rares, je voudrais affirmer que ce n'est pas toujours clair qui est la mère. les adoptions, les bébés abandonnés, les mères porteuses, etc. peuvent tous compliquer les choses.
Peter Recore
9
Ce n'est pas nécessairement acyclique, n'est-ce pas? Homme-épouse-grand-mère.
Ed Ropple
13
Un homme mariant sa grand-mère ne se fera pas son propre grand-père et n'ajoutera pas de cycle. S'ils ont des enfants, ce sera un bord de graphique régulier non cyclique.
exDM69
11
Il s'agit en fait de deux ADG. Il y a le graphique de filiation et le graphique de relation juridique. Habituellement les mêmes, mais divergentes, on pourrait s'y attendre.
JSacksteder
115

Je suppose que vous avez une valeur qui identifie de manière unique une personne sur laquelle vous pouvez baser vos chèques.

Ceci est délicat. En supposant que vous souhaitiez conserver la structure sous forme d'arbre, je suggère ceci:

Supposons ceci: Aa des enfants avec sa propre fille.

As'ajoute au programme au fur Aet à mesureB . Une fois dans le rôle de père, appelons-le petit ami.

Ajoutez une is_same_for_out()fonction qui indique à la partie génératrice de sortie de votre programme que tous les liens qui vont en Binterne devraient allerA lors de la présentation des données.

Cela fera un travail supplémentaire pour l'utilisateur, mais je suppose que l'informatique serait relativement facile à mettre en œuvre et à maintenir.

À partir de cela, vous pouvez travailler sur la synchronisation du code Aet Béviter les incohérences.

Cette solution n'est sûrement pas parfaite, mais c'est une première approche.

Eduard Thamm
la source
9
De tels nœuds "proxy" sont probablement une solution appropriée. Cependant, je n'ai aucune idée de la façon dont ceux-ci peuvent être mis dans l'interface utilisateur sans choquer l'utilisateur. Je peux vous dire qu'écrire un logiciel qui traite avec de vraies personnes (surtout vos clients) n'est pas facile.
Partick Höse
6
Cela ne finit jamais - le nouveau fils de B sera son propre oncle. Je considérerais un remboursement complet pour le programme!
Bo Persson
3
@Will A: Et puis se rend compte qu'il est aussi sa propre mère et recrute son jeune moi dans l'agence de temps?
Null Set
2
La duplication (et la synchronisation) des données au sein d'un même système est une mauvaise pratique. Cela indique que la solution n'est pas optimale et doit être reconsidérée. Si la création de nœuds supplémentaires (en double) est nécessaire, indiquez-le en tant que proxy et déléguez les données lues et écrites au nœud d'origine.
Bert Goethals
84

Vous devez vous concentrer sur ce qui fait vraiment la valeur de votre logiciel . Le temps consacré à le faire fonctionner pour UN consommateur vaut-il le prix de la licence? Probablement pas.

Je vous conseille de vous excuser auprès de ce client, lui dire que sa situation est hors de portée de votre logiciel et lui rembourser.

christopheml
la source
3
Très vrai. Mais pesez également d'autres problèmes potentiels avec des problèmes similaires que d'autres ont soulevés.
contrat du professeur Falken a été rompu le
2
Bien sûr. Le raisonnement est le suivant: s'il s'agit d'un cas de bord rare sur une application non critique, vous n'êtes pas obligé de corriger ou d'implémenter quoi que ce soit. Si cela blesse vraiment vos utilisateurs, il est utile de travailler dessus.
christopheml
10
Tout le monde a probablement un cas d'inceste quelque part dans son ascendance. Vous allez donc frapper cette bosse si l'on creuse (trop) profondément l'histoire de la famille.
datenwolf
1
Faire un arbre généalogique d'une situation étrange (redevance de consanguinité, Fritzl, etc.) est une utilisation valide du logiciel.
Bulwersator
1
Un logiciel d'arbre généalogique qui ne permettra pas aux cousins ​​germains de se marier est inutile. Presque toutes les familles en ont au moins un cas. C'est pourquoi je pense que l'exemple original est fait pour l'effet.
Fuzzy76
79

Vous devriez avoir configuré la famille Atreides (moderne, Dune ou ancienne, Oedipus Rex ) comme cas de test. Vous ne trouvez pas de bogues en utilisant des données filtrées comme cas de test.

user779752
la source
2
Malheureusement, trop de gens pensent d'abord aux données «ok» au lieu des cas extrêmes qui cassent leurs systèmes.
sjas
59

C'est l'une des raisons pour lesquelles des langues comme "Go" n'ont pas d'assertions. Ils sont utilisés pour gérer des cas auxquels vous n'avez probablement pas pensé, trop souvent. Vous ne devez affirmer que l'impossible, pas simplement l'improbable . Faire ce dernier est ce qui donne aux assertions une mauvaise réputation. Chaque fois que vous tapez assert(, éloignez-vous pendant dix minutes et vraiment réfléchissez-y .

Dans votre cas particulièrement inquiétant, il est à la fois concevable et épouvantable qu'une telle affirmation soit fausse dans des circonstances rares mais possibles. Par conséquent, gérez-le dans votre application, ne serait-ce que pour dire "Ce logiciel n'a pas été conçu pour gérer le scénario que vous avez présenté".

Affirmer que votre arrière-arrière-arrière-grand-père est votre père est impossible est une chose raisonnable à faire.

Si je travaillais pour une société de test embauchée pour tester votre logiciel, j'aurais bien sûr présenté ce scénario. Pourquoi? Chaque «utilisateur» juvénile mais intelligent va faire exactement la même chose et savourer le «rapport de bogue» qui en résulte.

Tim Post
la source
5
D'accord avec l'argument «quand utiliser les assertions»; ne vois pas comment cela se rapporte à «certaines langues ont des affirmations, Go ne le fait pas».
phooji
2
@Red Hue - parfois les compilateurs rendent l'impossible ... possible. Certaines versions de gcc pensent -10 == 10 dans l'implémentation abs ().
Tim Post
2
@Red Hue: Le point essentiel des assertions est de documenter et de tester des conditions qui devraient toujours être vraies (ou fausses). Cela vous empêche (ainsi que d'autres) de "réparer" les choses de telle manière que ces cas impossibles se produisent, car ils casseraient alors explicitement (plutôt que subtilement) l'application. S'il y a une raison valable pour qu'un cas "impossible" apparaisse, alors vous en avez trop affirmé.
cHao
1
@cHao @Tim Post J'essaie simplement de comprendre pourquoi Go ne pas avoir d'assertions est une bonne chose car la plupart d'entre vous conviennent que l'affirmation est importante.
Arlen
5
Avoir des assertions (ou du code de type assertion) n'est pas pertinent. Le code dans des langages comme Go peut et fera des hypothèses sur la structure des données; il ne peut tout simplement pas documenter et appliquer ces hypothèses avec des assertions. Conclusion: l'application a un bug.
Tommy McGuire
41

Je déteste commenter une situation aussi foutue, mais le moyen le plus simple de ne pas relancer tous vos invariants est de créer un sommet fantôme dans votre graphique qui agit comme un proxy pour le père incestueux.

Sean
la source
37

J'ai donc travaillé sur un logiciel d'arbre généalogique. Je pense que le problème que vous essayez de résoudre est que vous devez être en mesure de marcher sur l'arbre sans faire de boucles infinies - en d'autres termes, l'arbre doit être acyclique.

Cependant, il semble que vous affirmiez qu'il n'y a qu'un seul chemin entre une personne et l'un de ses ancêtres. Cela garantira qu'il n'y a pas de cycles, mais c'est trop strict. Biologiquement parlant, la descendance est un graphe acyclique dirigé (DAG). Le cas que vous avez est certainement un cas dégénéré, mais ce genre de chose se produit tout le temps sur des arbres plus gros.

Par exemple, si vous regardez les 2 ^ n ancêtres que vous avez à la génération n, s'il n'y avait pas de chevauchement, alors vous auriez plus d'ancêtres en 1000 AD qu'il n'y avait de personnes vivantes. Donc, il doit y avoir un chevauchement.

Cependant, vous avez également tendance à obtenir des cycles non valides, juste de mauvaises données. Si vous traversez l'arbre, les cycles doivent être traités. Vous pouvez le faire dans chaque algorithme individuel ou en charge. Je l'ai fait en charge.

Trouver de vrais cycles dans un arbre peut se faire de plusieurs manières. La mauvaise façon est de marquer chaque ancêtre d'un individu donné, et lorsque vous traversez, si la personne que vous allez passer à l'étape suivante est déjà marquée, coupez le lien. Cela rompra les relations potentiellement précises. La façon correcte de le faire est de partir de chaque individu et de marquer chaque ancêtre avec le chemin d'accès à cet individu. Si le nouveau chemin contient le chemin actuel en tant que sous-chemin, alors c'est un cycle et doit être interrompu. Vous pouvez stocker des chemins en tant que vecteur <bool> (MFMF, MFFFMF, etc.), ce qui rend la comparaison et le stockage très rapides.

Il existe plusieurs autres façons de détecter les cycles, comme l'envoi de deux itérateurs et la vérification de leur collision avec le test de sous-ensemble, mais j'ai fini par utiliser la méthode de stockage local.

Notez également que vous n'avez pas besoin de couper réellement le lien, vous pouvez simplement le changer d'un lien normal en un lien «faible», qui n'est pas suivi par certains de vos algorithmes. Vous voudrez également faire attention lors du choix du lien à marquer comme faible; Parfois, vous pouvez déterminer où le cycle doit être rompu en consultant les informations de date de naissance, mais souvent vous ne pouvez rien comprendre car il manque tellement de données.

tfinniga
la source
Attention à ces hypothèses; un homme et une femme mère n'est pas donnée quand les gens adaptent ou lesibans qui se considèrent comme les parents, dans un proche avenir , ils peuvent même être en mesure de vraiment être biologiquement parents, atleast des filles. D'ailleurs, si nous appliquons le chariot aux humains, même l'hypothèse «une personne a deux parents distincts» est exclue.
Agrajag
1
@Agrajag, oui c'est pourquoi j'ai spécifié "biologiquement parlant" pour la détection de cycle. Même biologiquement, il y a beaucoup de problèmes possibles, comme les mères porteuses et l'insémination artificielle. Si vous autorisez également les adoptions et d'autres méthodes non biologiques pour définir les parents, il est possible d'avoir un vrai cycle valide dans un arbre - par exemple, peut-être que quelqu'un adopte ses grands-parents quand ils vieillissent et ne sont plus en mesure de prendre soin d'eux-mêmes . Faire des hypothèses sur la vie familiale des gens est toujours compliqué. Mais lors de l'écriture d'un logiciel, vous devez faire quelques hypothèses ..
tfinniga
36

Une autre réponse sérieuse simulée pour une question stupide:

La vraie réponse est d'utiliser une structure de données appropriée. La généalogie humaine ne peut pas être entièrement exprimée en utilisant un arbre pur sans cycles. Vous devez utiliser une sorte de graphique. Parlez également à un anthropologue avant d'aller plus loin, car il existe de nombreux autres endroits où des erreurs similaires pourraient être commises en essayant de modéliser la généalogie, même dans le cas le plus simple du «mariage monogame patriarcal occidental».

Même si nous voulons ignorer les relations taboues locales comme nous le verrons ici, il existe de nombreuses façons parfaitement légales et complètement inattendues d'introduire des cycles dans un arbre généalogique.

Par exemple: http://en.wikipedia.org/wiki/Cousin_marriage

Fondamentalement, le mariage entre cousins ​​n'est pas seulement courant et attendu, c'est la raison pour laquelle les humains sont passés de milliers de petits groupes familiaux à une population mondiale de 6 milliards d'habitants. Cela ne peut pas fonctionner autrement.

Il y a vraiment très peu d'universaux en ce qui concerne la généalogie, la famille et la lignée. Presque toute hypothèse stricte sur les normes suggérant qui peut être une tante, ou qui peut épouser qui, ou comment les enfants sont légitimés à des fins d'héritage, peut être bouleversée par une exception quelque part dans le monde ou dans l'histoire.

clvrmnky
la source
9
Votre commentaire m'a fait penser à la polygamie. Un logiciel de généalogie qui ne modélise que la reproduction sexuelle peut nécessiter un nom attaché au sperme et à l'ovule, mais pas des définitions plus larges de la structure familiale.
Steve Kalemkiewicz
Le logiciel de généalogie permettra souvent plus d'un conjoint dans le modèle. La façon dont vous affichez le modèle dans la vue varie considérablement, même au sein d'un même programme, selon le "mode" fourni.
Todd Hopkinson
20

Hormis les implications juridiques potentielles, il semble certainement que vous devez traiter un `` nœud '' sur un arbre généalogique comme une personne prédécesseur plutôt que de supposer que le nœud peut être la seule et unique personne.

Demandez au nœud d'arbre d'inclure une personne ainsi que les successeurs - et ensuite vous pouvez avoir un autre nœud plus en bas de l'arbre qui comprend la même personne avec différents successeurs.

Will A
la source
13

Quelques réponses ont montré des moyens de conserver les assertions / invariants, mais cela semble être une mauvaise utilisation des assertions / invariants. Les assertions visent à s'assurer que quelque chose qui devrait être vrai est vrai, et les invariants doivent s'assurer que quelque chose qui ne devrait pas changer ne change pas.

Ce que vous affirmez ici, c'est que les relations incestueuses n'existent pas. De toute évidence , ils ne existent, de sorte que votre affirmation est invalide. Vous pouvez contourner cette assertion, mais le vrai bogue se trouve dans l'assertion elle-même. L'affirmation doit être supprimée.

Kerkeslager
la source
8

Votre arbre généalogique doit utiliser des relations dirigées. De cette façon, vous n'aurez pas de cycle.

Patrick Cornelissen
la source
5

Les données généalogiques sont cycliques et ne rentrent pas dans un graphique acyclique, donc si vous avez des affirmations contre les cycles, vous devez les supprimer.

La façon de gérer cela dans une vue sans créer de vue personnalisée consiste à traiter le parent cyclique comme un parent "fantôme". En d'autres termes, lorsqu'une personne est à la fois un père et un grand-père pour la même personne, le nœud de grand-père est affiché normalement, mais le nœud de père est rendu comme un nœud "fantôme" qui a une étiquette simple comme ("voir grand-père" ) et désigne le grand-père.

Afin de faire des calculs, vous devrez peut-être améliorer votre logique pour gérer les graphiques cycliques afin qu'un nœud ne soit pas visité plus d'une fois s'il y a un cycle.

Tyler Durden
la source
4

La chose la plus importante est de avoid creating a problem, donc je crois que vous devez utiliser une relation directe pour éviter d'avoir un cycle.

Comme l'a dit @markmywords, #include "fritzl.h".

Enfin je dois dire recheck your data structure. Peut-être que quelque chose ne va pas là-bas (peut-être qu'une liste chaînée bidirectionnelle résout votre problème).

Nasser Hadjloo
la source
4

Les affirmations ne survivent pas à la réalité

Habituellement, les assertions ne survivent pas au contact avec des données réelles. Cela fait partie du processus de génie logiciel de décider, avec quelles données vous voulez traiter et lesquelles sont hors de portée.

Graphes de famille cycliques

Concernant les "arbres" de famille (en fait ce sont des graphiques à part entière, y compris des cycles), il y a une belle anecdote:

J'ai épousé une veuve qui avait une fille adulte. Mon père, qui nous rendait souvent visite, est tombé amoureux de ma belle-fille et l'a épousée. En conséquence, mon père est devenu mon fils et ma fille est devenue ma mère. Quelque temps plus tard, j'ai donné à ma femme un fils, qui était le frère de mon père et mon oncle. La femme de mon père (qui est aussi ma fille et ma mère) a eu un fils. En conséquence, j'ai eu un frère et un petit-fils dans la même personne. Ma femme est maintenant ma grand-mère, car elle est la mère de ma mère. Je suis donc le mari de ma femme et en même temps le beau-petit-fils de ma femme. En d'autres termes, je suis mon propre grand-père.

Les choses deviennent encore plus étranges lorsque l'on tient compte des substituts ou de la "paternité floue".

Comment y faire face

Définir les cycles comme hors champ

Vous pourriez décider que votre logiciel ne devrait pas traiter de tels cas rares. Si un tel cas se produit, l'utilisateur doit utiliser un produit différent. Cela rend le traitement des cas les plus courants beaucoup plus robuste, car vous pouvez conserver plus d'assertions et un modèle de données plus simple.

Dans ce cas, ajoutez de bonnes fonctionnalités d'importation et d'exportation à votre logiciel, afin que l'utilisateur puisse facilement migrer vers un autre produit si nécessaire.

Autoriser les relations manuelles

Vous pouvez autoriser l'utilisateur à ajouter des relations manuelles. Ces relations ne sont pas des «citoyens de première classe», c'est-à-dire que le logiciel les prend telles quelles, ne les vérifie pas et ne les gère pas dans le modèle de données principal.

L'utilisateur peut alors gérer les rares cas à la main. Votre modèle de données restera assez simple et vos affirmations survivront.

Soyez prudent avec les relations manuelles. Il y a une tentation de les rendre complètement configurables et donc de créer un modèle de données entièrement configurable. Cela ne fonctionnera pas: votre logiciel ne sera pas redimensionné, vous obtiendrez d'étranges bugs et enfin l'interface utilisateur deviendra inutilisable. Cet anti-modèle est appelé "codage logiciel" , et "Le WTF quotidien" est plein d'exemples pour cela.

Rendez votre modèle de données plus flexible, ignorez les assertions, testez les invariants

Le dernier recours consisterait à rendre votre modèle de données plus flexible. Vous devez ignorer presque toutes les assertions et baser votre modèle de données sur un graphique complet. Comme le montre l'exemple ci-dessus, il est facilement possible d'être votre propre grand-père, vous pouvez donc même avoir des cycles.

Dans ce cas, vous devez tester en profondeur votre logiciel. Vous avez dû ignorer presque toutes les assertions, il y a donc de bonnes chances pour des bogues supplémentaires.

Utilisez un générateur de données de test pour vérifier les cas de test inhabituels. Il existe des bibliothèques de vérification rapide pour Haskell , Erlang ou C . Pour Java / Scala, il y a ScalaCheck et Nyaya . Une idée de test serait de simuler une population aléatoire, de la laisser se croiser au hasard, puis de laisser votre logiciel d'abord importer puis exporter le résultat. On s'attendrait à ce que toutes les connexions dans la sortie soient également dans l'entrée et vice versa.

Un cas où une propriété reste la même est appelé invariant. Dans ce cas, l'invariant est l'ensemble des «relations amoureuses» entre les individus de la population simulée. Essayez de trouver autant d'invariants que possible et testez-les avec des données générées aléatoirement. Les invariants peuvent être fonctionnels, par exemple:

  • un oncle reste un oncle, même lorsque vous ajoutez plus de "relations amoureuses"
  • chaque enfant a un parent
  • une population à deux générations a au moins un grand-parent

Ou ils peuvent être techniques:

  • Votre logiciel ne plantera pas sur un graphique jusqu'à 10 milliards de membres (quel que soit le nombre d'interconnexions)
  • Votre logiciel évolue avec O (nombre de nœuds) et O (nombre d'arêtes ^ 2)
  • Votre logiciel peut enregistrer et recharger chaque graphique de famille jusqu'à 10 milliards de membres

En exécutant les tests simulés, vous trouverez de nombreux cas de coins étranges. Les réparer prendra beaucoup de temps. Vous perdrez également beaucoup d'optimisations, votre logiciel fonctionnera beaucoup plus lentement. Vous devez décider si cela en vaut la peine et si cela est dans la portée de votre logiciel.

stefan.schwetschke
la source
3

Au lieu de supprimer toutes les assertions, vous devriez toujours vérifier des choses comme une personne étant son propre parent ou d'autres situations impossibles et présenter une erreur. Peut-être émettre un avertissement si cela est peu probable afin que l'utilisateur puisse toujours détecter les erreurs de saisie courantes, mais cela fonctionnera si tout est correct.

Je voudrais stocker les données dans un vecteur avec un entier permanent pour chaque personne et stocker les parents et les enfants dans des objets personne où ledit int est l'indice du vecteur. Ce serait assez rapide pour passer d'une génération à l'autre (mais lent pour des choses comme les recherches de noms). Les objets seraient dans l'ordre de leur création.

ctype.h
la source
-3

Dupliquez le père (ou utilisez le lien symbolique / la référence).

Par exemple, si vous utilisez une base de données hiérarchique:

$ #each person node has two nodes representing its parents.
$ mkdir Family
$ mkdir Family/Son
$ mkdir Family/Son/Daughter
$ mkdir Family/Son/Father
$ mkdir Family/Son/Daughter/Father
$ ln -s Family/Son/Daughter/Father Family/Son/Father
$ mkdir Family/Son/Daughter/Wife
$ tree Family
Family
└── Son
    ├── Daughter
       ├── Father
       └── Wife
    └── Father -> Family/Son/Daughter/Father

4 directories, 1 file
numérique
la source
3
La ln -scommande ne fonctionne pas de cette façon; la résolution du lien Family/Son/Fathersera recherchée Family/Son/Daughter/Fatherdepuis le dessous Family/Son, où réside le lien, et non d' .où vous avez émis la ln -scommande.
musiphil
48
le clonage est interdit par les conventions de genève
MikeIsrael