1

Realmをモデル/データベースとして使用してiOSアプリケーションを構築していますが、将来発生する可能性のあるREST-ful APIの変更に容易に対応できるようにクライアントを設計したいと考えています。さまざまなイベントに対応するスポーツ競技団体向けのアプリを開発しようとしています。各イベントには、どのスポーツが行われているかに基づいて、さまざまなタイプのイベントタイプがあります。現在、APIはサッカー、野球、サッカーだけを返しますが、将来はバスケットボールも含むように拡張される可能性があります。後で野球を排除するかもしれない。イベントは、このような多くの関係に一使用してイベントタイプから分離されるように、私は、レルムのオブジェクトを設計しました:REST-ful APIの変更に基づいて、MVC for iOSアプリの動的モデルを作成するにはどうすればよいですか?

class EventTypeGroup: Object { 
    dynamic var name = "" 
    let eventTypes = List<EventType>() 
} 

class EventType: Object { 
    dynamic var name = "" 
    dynamic var descriptionText = "" 
} 

アンEventTypeGroupになります(これはスポーツこの場合は)イベントの種類を記述したクラスです。イベントで演奏。このデザインは、Realmで辞書がサポートされていないため、関連する一連のプロパティでイベントタイプを格納できるため使用しました。

特定の組織のスポーツを追加または削除する場合のAPIの将来の変更に適応できるように、次のような抽象的なファクトリパターンを使用しました。このように、近代的なSwiftの設計原則に従った列挙型を使用せずにイベントを作成することはできません。私が問題を抱えているのは、ユーザーがアプリを開くとAPIのイベントタイプ(スポーツ)に対する変更を一度しかチェックしないと仮定すると、既に開いているアプリケーションでモデルを変更するにはどうすればよいですか?これらのフィールドが変更された場合、データベースを移行する必要がありますか?私は、彼らが定義されます方法がわからない場合は

protocol EventTypeGroupFactory { 

    func createEventTypeGroup(List<EventType>) -> EventTypeGroup 

} 

protocol EventTypeFactory { 

    func createEventTypes() -> List<EventType> 

} 

class SportEventGroupFactory: EventTypeGroupFactory { 
    func createEventTypeGroup(withEventTypes: List<EventType>) -> 
    EventTypeGroup { 
     //implement logic to create an EventTypeGroup for the SportEventGroup 

    } 
} 

class SportEventTypeFactory: EventTypeFactory { 
    EventTypeGroup { 
    func createEventType() -> EventType { 
     //implement logic to create an EventType for the SportEventType 
    } 
} 


class EventTypeGroup: Object { 

    let eventTypes = List<Int> 
    enum EventType { 
    } 
} 

class EventType: Object { 

    var type: Int? 
    name: String? 
    description: String? 
} 

class Event: Object { 

    static enum EventType 
    init(eventTypeWithRawValue:) { 

    } 
} 

はまた、どのように私は今、記述するコード内のクラスの異なるバリエーションを指します。抽象的なファクトリパターンはこれを処理する最善の方法ではないかもしれませんが、APIの変更に基づいてモデル内で簡単に拡張可能な型を作る問題にどのように取り組むべきかを明確にしていません。

答えて

2

あなたはそれを複雑にしている、と私は思う。イベントモデルに "eventType"という文字列プロパティを追加するだけです。

例えば、通常、あなたがこのような何かするかもしれない、ダイナミックなものを維持する必要がなかった場合:

enum EventType { 
    case soccer 
    case baseball 
    case football 
} 

// Your Event model 
struct Event { 
    var date: Date 
    var eventType: EventType // a static type :) 
} 

をしかし、あなたの場合には、代わりに、あなたはこのような何か行うことができます。

// Your Event model without any enums 
struct Event { 
    var date: Date 
    var eventType: String // a dynamic type :(
} 

プロパティeventTypeは、「サッカー」または「野球」または「サッカー」とすることができます。 (しかし、コンパイラは今、エラーを捕捉するのを助けることはできません。)永続的な記憶域については、フィールドにeventTypeというフィールドがあり、その文字列を格納してください。

ダイナミックタイプは、静的なスウィフトがいかに静的であるかを考えると悲しくなりますが、あなたが望むものを得ることができます。エッジケースについて考えてみてください。定義されていない動作にならないようにするには、たとえば、REST APIでサポートされていないイベントタイプがディスクに残った場合など、アプリが何をするべきかを事前に考えてください。

例えば、/eventTypesエンドポイントがあると、アプリのユーザーはイベントを追加してそれに応じて分類することができ、「サッカー」、「野球」、「サッカー」が返され、ユーザーはこれらのタイプを追加していますあなたはそれらをディスク(RealmやCoreDataなど)に格納しています。しかし、ある日、バックエンド(またはバックエンド)の誰かが「フットボール」を「アメリカンフットボール」に改名し、誰も「サッカー」を「フットボール」に改名しないことを願っています。 (そして、名前が変更されたか、削除されたか、別のものが追加されたかどうかは分かりません)。/eventTypesエンドポイントが返すイベントタイプとディスク上のイベントの和集合を取っていますか?ユーザーがディスクにまだ保存されているが、もはやREST APIでサポートされていない古いイベントタイプを追加させたり、それらを表示するだけですか?

アクティブユーザーの場合、バックエンドユーザーがイベントタイプの名前を変更したり、イベントタイプを削除したりすると、このようなエッジケースが発生する可能性があります。どのような行動を取るべきかについては、ステークホルダーと話し合うだけです。

+0

あなたのレスポンスにEventTypeクラスのダイスを追加しませんでしたか?また、クラスではなく構造体を使用してイベントモデルを実装することを選択した特定の理由はありますか? – stonybrooklyn

+1

Re。構造体:構造体は安全です(Swiftでは、参照ではなく値渡しされます)。また、実行時にはより速く(維持するvtableはありません)。しかし、サブクラス化が必要で、プロトコルが十分でない場合は、クラスを使用することに戻ります。 – willtherussian

+1

Re。 EventTypeクラス:はい、他のデータをラップし、文字列(「baseball」や「football」のような値をとる文字列)を配置する必要がある場合は、eventTypeプロパティのクラスまたは構造体を使用できます。要は、列挙型ではなく文字列を使用しているということです。 – willtherussian

関連する問題