简体   繁体   English

如何基于REST-ful API中的更改使MVC for iOS应用中的模型动态化?

[英]How do I make model in MVC for iOS app dynamic based on changes in REST-ful API?

We're building an iOS app using Realm as our model / database but we want to design the client so it can easily accommodate changes in the REST-ful API that may occur in the future. 我们正在使用Realm作为模型/数据库来构建iOS应用程序,但我们希望设计客户端,以便它可以轻松适应将来可能发生的REST-ful API中的更改。 Lets say we're developing an app for sports competition organizations that accommodates different events. 可以说,我们正在为体育比赛组织开发一款可容纳各种赛事的应用程序。 Each event has different types of event types based on what sports are being played. 每个事件都有不同类型的事件类型,具体取决于所进行的体育运动。 Right now the API only returns Soccer, Baseball, and Football but in the future it might expand to include Basketball too. 目前,API仅返回“足球”,“棒球”和“足球”,但将来可能会扩展到包括“篮球”。 Later it might eliminate Baseball. 以后可能会消除棒球。 I've designed the Realm objects so that Events are decoupled from Event Types using a one-to many relationship like this: 我已经设计了Realm对象,以便使用如下所示的一对多关系将事件与事件类型分离:

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

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

An EventTypeGroup is the class describing the event types (in this case which sports) will be played at the event. EventTypeGroup是描述事件类型(在本例中为哪种体育项目)的类,将在该事件中播放。 I used this design because dictionaries aren't supported in Realm where we could store an event type with an associated set of properties. 我之所以使用这种设计,是因为Realm不支持字典,在Realm中我们可以存储带有相关属性集的事件类型。

In order to make the model adaptable to future changes in the API in case sports for a particular organization are added or removed, I used an abstract factory pattern like below. 为了使模型适应API将来的更改,以防添加或删除特定组织的运动,我使用了如下的抽象工厂模式。 This way an event cannot be created without using an enum in keeping with modern Swift design principles. 这样,如果不使用符合现代Swift设计原则的枚举就无法创建事件。 The problem I'm having is, assuming we only check for changes in the API to the event types (sports) once upon the user opening the app, how do we change the model with the app already open? 我遇到的问题是,假设我们仅在用户打开应用程序后才检查事件类型(体育)的API中的更改,我们如何在已打开应用程序的情况下更改模型? Will the database need to be migrated if these fields change? 如果这些字段更改,是否需要迁移数据库?

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:) {

    }
}

Also, how will I refer to the different variations of the classes in the code I write now if I don't know how they'll be defined. 另外,如果我不知道如何定义它们,我将如何在我现在编写的代码中引用这些类的不同变体。 I'm guessing the abstract factory pattern may not be the best way to deal with this but am not sure what other options I should consider or how to approach the issue of making types easily extensible in a model based on API changes. 我猜想抽象工厂模式可能不是解决此问题的最佳方法,但是不确定我应该考虑哪些其他选项,或者不确定如何解决基于API更改的类型在模型中易于扩展的问题。

You are overcomplicating it, I think. 我认为您太复杂了。 Just add a string property called "eventType" to your Event model. 只需在事件模型中添加一个名为“ eventType”的字符串属性即可。

For example, normally, if you didn't need to keep things dynamic, you might do something like this: 例如,通常,如果不需要保持动态变化,则可以执行以下操作:

enum EventType {
    case soccer
    case baseball
    case football
}

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

But in your case, instead you can do something like this: 但就您而言,您可以执行以下操作:

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

Property eventType can then be "soccer" or "baseball" or "football". 然后,属性eventType可以是“足球”或“棒球”或“足球”。 (But the compiler cannot help you catch errors now.) As for your persistent storage, just have a field there of type eventType and store the string. (但是编译器现在无法帮助您捕获错误。)至于持久性存储,只需在其中有一个eventType类型的字段并存储字符串即可。

Dynamic types make me sad given how nicely static Swift is, but it gets you what you want. 考虑到静态Swift的出色表现,动态类型让我很伤心,但它可以满足您的需求。 Just make sure to think about edge cases. 只要确保考虑一些极端情况即可。 To not end up with undefined behavior, think ahead about what your app is supposed to do if, for example, you end up with event types on disk that are no longer being supported by your REST API. 为了避免出现不确定的行为,例如,如果您遇到磁盘上的事件类型不再受REST API支持的情况,请考虑一下应用程序应该做什么。

For example, say you have an /eventTypes endpoint, so that your app's users can add events and categorize them accordingly, and it's been returning "soccer", "baseball" and "football" and your users have been adding these types of events and you have been storing them on disk (in Realm or CoreData or whatever). 例如,假设您有一个/eventTypes端点,以便您的应用程序的用户可以添加事件并进行相应的分类,并且它一直在返回“足球”,“棒球”和“足球”,并且您的用户一直在添加这些事件类型,您已将它们存储在磁盘上(在Realm或CoreData中或其他任何形式)。 But then one day someone on the backend (or through the backend) renames "football" to "american football", and let's hope no one renames "soccer" to "football" too. 但是有一天,后端(或通过后端)上的某人将“足球”重命名为“美国足球”,我们希望没有人也将“足球”重命名为“足球”。 (And so now you can't tell if a thing was renamed or removed and another added.) Do you then take the union of the event types your /eventTypes endpoint returns and what you find on disk? (因此,现在您无法确定某个事物是否已重命名或删除,以及是否添加了另一个事物。)然后,您是否将/eventTypes端点返回的事件类型与在磁盘上找到的内容进行并集? Do you let users add old event types that still live on disk but are not longer supported by your REST API or only display them? 您是否允许用户添加仍在磁盘上但REST API不再支持的旧事件类型,或者仅显示它们?

With active users, you will likely end up with these kinds of edge cases if your backend folks rename event types or remove event types (as opposed to simply adding them). 对于活跃的用户,如果后端人员重命名事件类型或删除事件类型(而不是简单地添加事件类型),则可能会遇到这种极端情况。 Just discuss with your stakeholders what the behavior should be. 只需与您的涉众讨论行为应该是什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM