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」的字符串屬性添加到您的Event模型。

例如,通常情況下,如果你沒有需要保持動態的東西,你可能會做這樣的事情:

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的字段並存儲字符串。

動態類型讓我很難過,因爲Swift是多麼好的靜態,但它能讓你得到你想要的。只要確保考慮邊緣案例。爲了不結束未定義的行爲,例如,如果最終發現REST API不再支持的磁盤上的事件類型,則可以提前考慮應用程序應該執行的操作。例如,假設您有一個/eventTypes端點,以便您的應用的用戶可以添加事件並對其進行相應的分類,並且它已返回「足球」,「棒球」和「足球」,並且您的用戶已添加這些類型事件,你一直在磁盤上存儲(Realm或CoreData或其他)。但是總有一天,後臺有人(或通過後端)將「足球」改名爲「美式足球」,我們希望沒有人將「足球」改名爲「足球」。 (所以現在你不能分辨一個事物是否被重命名或刪除,而另一個添加。)然後,你接下來的事件類型的聯合,你的終端返回和你在磁盤上找到什麼?您是否允許用戶添加仍舊存在於磁盤上但不再受REST API支持的舊事件類型,或僅顯示它們?

對於活躍的用戶,如果您的後端人員重命名事件類型或刪除事件類型(而不是簡單地添加它們),您可能會遇到這類邊緣情況。只需與你的利益相關者討論行爲應該是什麼。

+0

沒有骰子上的EventType類我添加到您的迴應?此外,您選擇使用結構而不是類來實現Event模型的任何特定原因? – stonybrooklyn

+1

Re。結構:結構更安全(在Swift中,它們是按值傳遞的,而不是通過引用),並且在運行時也更快(無法維護)。但是如果你需要子類和協議不夠,那麼回到使用類。 – willtherussian

+1

Re。 EventType類:是的,如果需要包裝其他數據並將字符串(將採用諸如「棒球」和「足球」之類的值的字符串)放入其中,那麼可以使用類或結構作爲eventType屬性。重點是你仍然在使用字符串而不是枚舉。 – willtherussian