【问题标题】:where to put code that operates on an array of structs?在哪里放置对结构数组进行操作的代码?
【发布时间】:2016-11-30 17:56:46
【问题描述】:

如果我有一个结构和一些处理该结构的数组的代码,那么该代码的放置位置在哪里?

struct Thing {
    var id : String
    let type : ThingType
}

things:[Thing]?

我有代码可以从返回100 Thing 数组的服务器检索值。代码应该去哪里?

我目前已将其定义为 Struct 的静态函数,但如果有约定,我想遵循约定。

【问题讨论】:

  • 这完全取决于“过程”的含义。
  • 怎么样,@AlexanderMomchliov,例如我给出的关于服务器调用返回 [Thing] 的示例
  • 一般来说,执行服务器通信的代码应该与你的结构所代表的数据传输对象(DTO)分开。
  • 那肯定不应该是Thing 的成员。最好创建一个声明函数的新协议,并有一个新的符合要求的结构/类来实现它。这样,您只需更换您使用的具体提供程序类即可更改您使用的提供程序(Firebase、Parse、SQLite、CoreData、JSON、CSV 等)
  • 这还有一个好处是它允许您对提供程序进行模拟实现,这使您可以拥有独立于生产后端工作的单元测试。

标签: arrays swift struct


【解决方案1】:

从服务器检索Thing 实例的函数当然不应该是Thing 的成员。

最好创建一个声明函数的新协议,如下所示:

protocol ThingProvider {
    func fetchThings() -> [Thing]
}

和一个符合的类型:

class DataBaseThingProvider: ThingProvider {

    init() {
        // open database connection
    }

    deinit() {
        // close database connection
    }

    func fetchThings() -> [Thing] {
        // fetch Things from database
    }
}

这样,您只需更换您使用的具体提供程序类即可更改您使用的提供程序(Firebase、Parse、SQLite、CoreData、JSON、CSV 等),而所有其他代码都可以保持不变。

它还使您的代码更具可测试性,因为您可以轻松构建一个模拟提供程序,将您的测试与生产后端分离。

class MockThingProvider: ThingProvider {

    func fetchThings() -> [Thing] {
        return [
            Thing(id: "MockThing1", type: thingType1),
            Thing(id: "MockThing2", type: thingType2),
            Thing(id: "MockThing3", type: thingType3)
        ]
    }
}

【讨论】:

  • 感谢@AlexanderMomchliov。您选择 DataBaseThingProvider 的类而不是结构的任何原因? (收到消息说 Swift 可以通过内存泄漏的结构更加健壮)
  • 因为数据库连接(从逻辑上讲)不应该在分配时被复制。你听说过 Swift 中的内存泄漏吗?
  • Swift 闭包正在获得声誉。例如。 “闭包非常棘手,因为它们具有‘捕获语义’”@leojkwan.com/2016/02/memory-leaks
  • 好吧,你必须避免引用循环,在存储闭包中处理self 时尤其如此。这并不意味着你应该完全避免上课。它们有它们的用途。在这种情况下,我希望每个数据库连接有一个对象,所以我选择了一个类
  • @Carl 是的。我会使用单例。但是,单例不能通过结构来实现。只需执行let x = MyStruct.shared,您就可以创建从shared 到x 的副本。您已经有 2 个实例,只需这样做即可。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 2017-11-09
  • 2012-03-08
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多