私は現在、鶏または卵の最初の状況の問題に取り組んでいます。基本的に、私はこのようなソリューションを設計しています:
World
は国のコレクションです。Country
には、名前、フラグ、および社長(すべて文字列)があります。いつでも私は次のような要求を処理する必要があるかもしれません:誰が究極のリーダー国であるか(最大の支持者や友人などがいる)、誰が究極のリーダー国の支持者であるか、または特定のリーダー国の支持者である、など。ここでのトリックは、友達やリーダーの基本的なプロパティが同じであるということです(すべてのCountry
には名前、フラグ、社長がいるように)
この問題ステートメントの基本的なサービス要件に対処するための優れたスケルトン構造が必要です。しかし、後継者、子孫、判決の期間、大統領の家族など、将来の拡張を処理できるデザインが必要です。
従うべきアプローチを決定する際に混乱しています。作成する必要があるか(アプローチ1)、定義する必要があるか(アプローチ2)。
Country
はWorld
の一部ですclass World
{
class country *country_list // not taking array , so that i need not to limit the list
};
Country
が最初に定義され、World
はそれから継承しますCountry
は小さなエンティティであり、World
は大きなエンティティであるため、これは奇妙に見えます。そして、それから世界の内容は何でしょうか、再び国のリストです。
class World : Inherit class country
{
// not sure what should be the content here
// can getcounty();
// add_country_to_world();
//
};
//not sure wether to make this abstract or normal.
//no duplicates countries are allowed.
class country
{
string countryname;
string flag;
string president;
};
次に、キー(国名で作成)と値がその詳細であるマッパーを作成します。国は友達またはリーダーであり、友達はないので、最終的なリーダーが誰であるかを直接確認できます。
私は、WorldとCountryにどのような形式の継承も使用しません。世界は国ではなく、国は世界ではありません。
代わりに、世界は多くの国を含む「バッグ」です。 「バッグ」とは、選択したある種のコンテナクラス(リンクリスト、セット、辞書/マップなど)を意味します。最も効率的に国を見つけることができるコンテナタイプを選択してください。
ここに1つか2つの考えがあります:
World
をモデル化する必要があると確信していますか?あなたの説明によると、それは何の効果もないようです。はい、それはあなたのCountries
をカプセル化しますが、それがすべてのプログラムがそうするなら、プログラムのカプセル化はうまくいくはずです。Relationsクラス(簡略化された疑似コード)
class CountryRelation
{
Country FirstCountry { get; set; }
Country SecondCountry { get; set; }
RelationshipType Relationship { get; set; }
}
enum RelationshipType {
Friends,
Enemies,
Neutral
};
私はあなたの最初の要件が最もわかりやすいと思います:
世界は国の集まりです
残りの要件は、国、リーダー、およびアライアンスについて話します。私が確信していることが1つあります。動作がなければ、World
はクラスではありません。せいぜい、それは一般的なコレクションです。
var world = new Collection<Country>();
国とアライアンスの要件がどの程度詳細であるかを考えると、Country
オブジェクトのコレクションは必要ないかもしれません。このモデルの主なエンティティはCountry
(お伝えしたとおり)とAlliance
(複数の国間の関係)のようです。
var world = new Collection<Country>();
world.Add(new Country("United States of America"));
world.Add(new Country("Portugal"));
world.Add(new Country("Saudi Arabia"));
var natoAllianceTypes = new AllianceType[] { AllianceType.Military, AllianceType.Political };
var nato = new Alliance("North Atlantic Treaty Organization", natoAllianceTypes);
nato.AddMemberNation(world.Single(c => c.Name == "United States of America"));
nato.AddMemberNation(world.Single(c => c.Name == "Portugal"));
var opecAllianceTypes = new AllianceType[] { AllianceType.Economic };
var opec = new Alliance("Organization of the Petroleum Exporting Countries", opecAllianceTypes);
opec.AddMemberNation(world.Single(c => c.Name == "Saudi Arabia"));
// so on, and so forth...
ここでの鍵は、国を結びつけるAlliance
クラスです。これにより、希望する関係をモデル化できます。国固有の属性はCountry
クラスに属します。 2つ以上の国間の関係に固有の属性は、Alliance
クラスに属します。 「リード」国を特定することは、Alliance
クラス、またはこの計算を抽象化する必要がある場合は戦略オブジェクトの懸念事項のように聞こえます。たとえば、NATOは政治的および軍事的同盟です。 「政治的」指導者は必ずしも「軍事的」指導者ではないかもしれない。
world
?まあ、このオブジェクトについて言うことはあまりありません。これは、存在する国の正規の情報源です(ただし、国際社会によって必ずしも「公式に認識されている」とは限りません。これは、another同盟:国連、誰かですか?)。
最も基本的なエンティティはCountry
です。 World
は、すべての国の aggregation です( nited Nations によると、193の加盟国)。明らかに、World
には大統領も旗もありません。したがって、これはCountry
ではなく、継承しないものとします。
それにもかかわらず、問題にとって重要な何かを見逃しました。国によっては、関係によってはより大きなGroup
を形成するように集約できます。そして、すべての質問は基本的にこれらのグループの特性についてです。
World
がGroup
(またはそのインスタンス)になるかどうかは哲学的な問題であり、モデルの決定はお客様にお任せします。
Group
はCountry
よりも多くを提供します:加盟国があり、リーダー国がある場合があります(必ずしもそうである必要はありません)。独自の政治的代表であり、正式な資本または非公式の資本などがある場合があります。ユニオン、フェデレーション、ブロックなど、さまざまな種類のGroup
が存在する可能性があります。関係。グループは、将来の拡張のための完全な柔軟性と、その部分に基づいて全体がどのように反応するかについてのより微妙なルールを保証します。
設計の核となる問題は、Country
とGroups
を同じように使用したいかどうかです。
Country
インターフェイスに基づいてGroup
とPower
を設計できます=(以下を参照)。非常に大まかに言えば、すべての問題は、いくつかのメンバーシップ規則による sets 、 subsets 、および partitions に関するものです。グループの機能を簡単に拡張して、それらすべてを処理できます。また、新しいまたは更新された関係に基づいて経済グループを修正できる関係マネージャーを設計できます。
追記:地球上のすべての州に大統領がいるわけではありません。より適切な一般的な用語は 国家元首 。です。
専門用語に集中しすぎているようです。
World
とCountry
はどちらもテリトリーです。実際、すべてがTerritory
です。テリトリーにはテリトリーが含まれているので、私があなたである場合、それをテリトリーの再帰的なコレクションに減らし、ユースケースのテリトリーを定義するために必要なプロパティの最小数を決定します。
たとえば、政府の場合、Person
、Role
、およびResponsibility
をすべての関連する人々の基本型として持つことができます。人は多くの役割を持つことができ、役割は多くの責任を持つことができます。継承と階層を使用すると、政府やその他のエンティティを形成する人々の複雑なネットワークを計画できます。
テリトリーの場合、テリトリーには多数の小さなテリトリーが含まれ、各テリトリーにはRelationship
sのコレクションが含まれ、TradeRelationship
およびPoliticalRelationship
などを使用してサブタイプを指定できます。
各個人と地域は別個のエンティティであり、それらを接続してネットワークを形成し、必要に応じてプロパティと新しいサブタイプを追加します。
それを最も基本的な構成要素に分解することは、将来的に完全に拡張可能にする最良の方法ですが、それを非常に複雑にする方法でもあるため、将来達成する必要があることによって異なります。
擬似コードの例:
var world = new Territory {
Name = "World",
Children = []
};
var china = new Territory {
Name = "People's Republic of China",
Parents = [world],
Children = []
};
var eu = new Union {
Name = "European Union",
Members = [],
Relationships = [],
Purposes = [UnionPurpose.Trade, UnionPurpose.Political]
};
var euChinaRelationship = new TradeRelationship {
Participants = [eu, china]
};
eu.Relationships.Add(euChinaRelationship);
china.Relationships.Add(euChinaRelationship);
var europe = new Territory {
Name = "Europe",
Parents = [world],
Children = []
};
var britain = new Territory {
Name = "Britain",
Parents = [europe],
Children = []
};
var conservatives = new Union {
Name = "Conservative Party",
Members = [],
Purposes = [UnionPurpose.Political]
};
var ukPrimeMinisterRole = new Role {
Name = "Prime Minister",
Responsibilities = ["Leading the government", "Causing trouble :P"],
BeganAt = "24 July 2019",
EndedAt = "12 December 2019"
};
var bojo = new Person {
Name = "Alexander Boris de Pfeffel Johnson",
Roles = [ukPrimeMinisterRole]
};
conservatives.Members.Add(bojo);
britain.Government = conservatives;
europe.Children.Add(britain);
eu.Members.Add(britain);
以下のスキーマの場合:
abstract Entity {
Name: string;
}
Person : Entity {
DOB: DateTime;
DOD: DateTime;
Roles: Role[];
Relationships: Relationship[];
}
Role {
Name: string;
Responsibilities: string[];
BeganAt: DateTime;
EndedAt: DateTime;
}
Relationship {
Reciprocal: boolean;
Participants: Entity[];
}
TradeRelationship : Relationship {
Reciprocal = true;
override Participants: Territory[];
}
Territory : Entity {
Parents: Territory[];
Children: Territory[];
Relationships: Relationship[];
Government: Union;
}
Union : Entity {
Members: Entity[];
Purposes: UnionPurpose[];
Relationships: Relationship[];
}
enum UnionPurpose {
Political,
Military,
Trade
}
これを計画するには長い時間がかかるかもしれませんが、世界はかなり複雑です。
私は「ワールド」クラスを国のコンテナではなく国のコンテナとして見ています。国のためにそれを継承することは正しく聞こえません。
国については、国名とそのフラグがほとんど変わらないことを考えると、それを列挙型として持つことができます。
Enum Country{
ABC("abc", "abc_flag")
private final String name;
private final String flag;
public String getName() {
return name;
}
public String getFlag() {
return flag;
}
}
国の大統領は変更することができ、1対1のマッピングがあるため、このための簡単なEnumMapを使用できます。
EnumMap<Country, String> countryPresident
。
@Noceoが言及したように、関係タイプとマッピングは列挙型にすることができます。
enum RelationshipType {
Friends,
Enemies,
Neutral
};
ソフトウェアエンジニアリングStackexchangeへようこそ!
いつでも私は次のような要求を処理する必要があるかもしれません:誰が究極のリーダー国であるか(最大の支持者や友人などがいる)、誰が究極のリーダー国の支持者であるか、または特定のリーダー国の支持者である、ここでの秘訣は、友人や指導者の基本的な特性が同じであることです(すべての国に名前、旗、大統領があるように)。
国間の関係は輸出情報に基づいているように思えます。これは、各ノードが国であり、国AからBへの各リンクが、国Aが国Bに輸出する量の情報を運ぶ、有向グラフとしてモデル化できると思います。実装に関しては、いくつかの方法で実装できます。 、2つのマップを持つそれぞれの国のクラスのように、1つはエクスポート用、もう1つはインポート用で、キーは他の国で、値は金額です。
国間の関係ではなく単一の国(フラグなど)に関連するプロパティは、このクラスの単純なプロパティにすることができます。
この問題ステートメントの基本的なサービス要件に対処するための優れたスケルトン構造が必要です。しかし、後継者、子孫、判決の期間、大統領の家族など、将来の拡張を処理できるデザインが必要です。
拡張可能な構造を持つことは良いことですが、あまり多くするべきではありません。あなたが作成するこれらの例は、必要になった場合にリファクタリングを検討するのに十分な大きさであると思われるため、最初は検討しません。私の以前のアイデアに基づくと、将来性のある適切な選択の例は、単純な数値ではなくクラスでエクスポートとインポートの関係を表すことです。そのため、関係に情報を追加する必要が生じた場合、次のことができます。それは単に。