[c++] ファミリツリーソフトウェアのサイクル数



Answers

あなたの主張をリラックスしてください。

ルールを変更することではなく、顧客の99.9%がデータを入力する際に​​間違いを犯すのに非常に役立ちそうです。

代わりに、「関係を追加できません」というエラーから、「とにかく追加する」という警告に変更します。

Question

私はファミリーツリーソフトウェアの開発者です(C ++とQtで書かれています)。 私の顧客の1人が私にバグレポートを送付するまで問題はなかった。 問題は、顧客が自分の娘を持つ2人の子供を抱えているため、エラーのためにソフトウェアを使用できないということです。

これらのエラーは、家族グラフが処理されていることに関する私のさまざまな主張と不変条件の結果です(例えば、歩行した後、XはYの父と祖父の両方になれないと書かれています)。

すべてのデータアサーションを削除せずにこれらのエラーを解決するにはどうすればよいですか?




いくつかの答えがアサーション/インバリアントを保持する方法を示していますが、これはアサーション/不変の誤用のようです。 アサーションは真実であるべきことが真であることを確かめることであり、不変量は変化してはならないものが変わらないことを確かめることです。

あなたがここに主張しているのは、近親相姦が存在しないということです。 明らかに彼ら存在するので、あなたの主張は無効です。 このアサーションを回避することはできますが、本当のバグはアサーション自体にあります。 アサーションは削除する必要があります。




私はあなたがあなたの小切手の基礎となる人を一意に識別する価値があると思います。

これは難しいことです。 構造体をツリーにしたいと仮定して、私はこれを提案します:

これを仮定します: Aは自分の娘と子供を持っています。

Aは自分自身をABとしてプログラムに追加します。 かつては父親の役割を担い、それをボーイフレンドと呼んでみましょう。

is_same_for_out()関数を追加します。この関数は、プログラムの出力生成部分に、内部的にB向かうすべてのリンクがデータの表示時にAに行くべきであることを伝えます。

これはユーザーのために余分な仕事をするでしょうが、ITを実装し維持するのが比較的簡単だと思います。

これを基にして、矛盾を避けるためにABコードを同期させることができます。

この解決策は必ずしも完璧ではありませんが、最初のアプローチです。




テストケースとして、 Atreidesファミリ(現代、 Atreides 、または古代のOedipus Rexのいずれか)を設定する必要があります。 テストケースとして墨塗りデータを使用することで、バグは見つかりません。




アサーションは現実に生き残れない

通常、アサーションは実世界のデータとの接触から生き残ることはできません。 ソフトウェアエンジニアリングのプロセスの一部で、どのデータを処理したいのか、どのデータを範囲外にするのかを決定することです。

周期的な家族グラフ

家族の "木"(実際にはサイクルを含む完全なグラフです)に関しては、素敵な逸話があります:

私は成長した娘を持つ未亡人と結婚した。 私たちの父親は、しばしば私たちを訪ね、私の娘と恋に落ち、彼女と結婚しました。 その結果、私の父は私の息子になり、私の娘は私の母となりました。 その後しばらくして、私は妻に父の兄弟である息子と私の叔父を与えました。 私の父の妻(私の娘でも母親でもある)は息子を産んだ。 その結果、私は同じ人の兄弟と孫を得ました。 彼女は私の母親の母親なので、私の妻は今私の祖母です。 私は妻の夫であり、同時に私の妻の孫でもあります。 つまり、私は自分のおじいちゃんです。

surrogatesや「ファジーな父親」を考慮に入れると、事態はさらに奇妙になります。

それに対処する方法

サイクルを範囲外として定義する

このようなまれなケースに対処してはならないとあなたは決めることができます。 このような場合は、別の製品を使用する必要があります。 より多くのアサーションとより単純なデータモデルを保つことができるので、より一般的なケースをより堅牢に扱うことができます。

この場合、ソフトウェアにいくつかの優れたインポートおよびエクスポート機能を追加することで、ユーザーは必要に応じて簡単に別の製品に移行できます。

手動リレーションシップを許可する

ユーザーが手動リレーションシップを追加できるようにすることができます。 これらの関係は「ファースト・クラスの市民」ではなく、ソフトウェアは現状のまま使用し、チェックは行わず、メイン・データ・モデルでは処理しません。

ユーザーは、手で稀なケースを処理することができます。 あなたのデータモデルは依然として非常にシンプルで、アサーションは生き残ります。

手動の関係に注意してください。 それらを完全に構成可能にし、したがって完全に構成可能なデータモデルを作成する誘惑があります。 これはうまくいかないでしょう:あなたのソフトウェアはスケールされません、あなたは奇妙なバグを取得し、最終的にユーザーインターフェイスは使用できなくなります。 このアンチパターンは「ソフトコーディング」と呼ばれ、 「毎日のWTF」にはその例がたくさんあります。

データモデルをより柔軟にする、アサーションをスキップする、不変量をテストする

最後の手段は、データモデルをより柔軟にすることです。 ほぼすべてのアサーションをスキップして、データモデルを本格的なグラフにする必要があります。 上の例が示すように、あなた自身の祖父であることは容易に可能であるので、サイクルを持つことさえできます。

この場合、ソフトウェアを広範にテストする必要があります。 ほぼすべてのアサーションをスキップしなければならなかったので、追加のバグの可能性があります。

異常なテストケースをチェックするには、テストデータジェネレータを使用します。 HaskellErlangCクイックチェックライブラリがあります。 Java / ScalaにはScalaCheckNyayaます。 1つのテストアイデアはランダムな母集団をシミュレートし、無作為に交配させてから、ソフトウェアに最初にインポートしてから結果をエクスポートさせることです。 出力のすべての接続も入力とその逆の節にあると予想されます。

あるプロパティが同じままである場合は、不変条件と呼ばれます。 この場合、不変量は、シミュレートされた母集団における個人間の「ロマンチックな関係」の集合である。 できるだけ多くの不変量を見つけて、ランダムに生成されたデータでそれらをテストしてみてください。 インバリアントは機能的であり得る:

  • あなたがもっと「ロマンチックな関係」を加えても、叔父は叔父のままです。
  • すべての子供は親を持っています
  • 2世代の人口には少なくとも1人の祖父母

あるいは、それらは技術的なことができます:

  • あなたのソフトウェアは、最大100億人のメンバーのグラフにクラッシュすることはありません(相互接続数に関係なく)
  • あなたのソフトウェアは、O(ノード数)とO(辺数^ 2)
  • あなたのソフトウェアは、100億人までのメンバーグラフを保存して再ロードできます

シミュレートされたテストを実行すると、奇妙なコーナーケースがたくさんあります。 それらを修正するには多くの時間がかかります。 また、あなたは多くの最適化を失うでしょう、あなたのソフトウェアははるかに遅く実行されます。 それが価値があるかどうか、これがあなたのソフトウェアの範囲内にあるかどうかを判断する必要があります。




系図データは周期的で非巡回グラフには収まらないので、サイクルに対してアサーションがある場合は削除する必要があります。

カスタムビューを作成せずにこのビューを処理する方法は、サイクリック親を「ゴースト」親として扱うことです。 言い換えれば、ある人が同じ人の父と祖父の両方である場合、祖父ノードは正常に表示されますが、父ノードは単純なラベルを持つ「ゴースト」ノードとしてレンダリングされます(「祖父を参照してください」、 )と祖父を指しています。

計算を行うには、サイクルがある場合にノードが複数回訪問されないように、循環グラフを処理するためにロジックを改善する必要があります。




私はこのような状況を批判するのは嫌いですが、あなたの不変量をすべて取り返そうとする最も簡単な方法は、ファインド頂点をグラフの中に作成して、最悪のお父さんの代理として働かせることです。




父親を複製する(またはシンボリックリンク/参照を使用する)。

たとえば、階層データベースを使用している場合は次のようになります。

$ #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



愚かな質問のための別のモック重大な答え:

本当の答えは、適切なデータ構造を使用することです。 人間の系譜は、サイクルのない純粋な木を使って完全に表現することはできません。 何らかのグラフを使用する必要があります。 また、「西洋主義の一部婚姻」という最も単純な場合でも、系譜をモデル化しようとすると、同様の誤りが出る可能性があるため、これ以上進める前に人類学者と話をしてください。

ここで論じたように、ローカルのタブー関係を無視したいとしても、サイクルを家系図に導入するには完全に合法で完全に予期しない方法がたくさんあります。

例: http://en.wikipedia.org/wiki/Cousin_marriage : http://en.wikipedia.org/wiki/Cousin_marriage

基本的に、いとこの結婚は一般的で期待されるだけでなく、人間が何千もの小家族から60億人の世界人口になった理由です。 他の方法では動作しません。

系譜、家系、系統については、実際にはほとんど普遍的ではありません。 叔母が誰であることができるか、または誰と結婚することができるか、または子供が継承の目的で正当化される方法を示唆する規範についてのほとんどの厳格な仮定は、世界または歴史のどこかのある例外を除いて動揺する可能性がある。




Links