Swift 4で行うDTOとDAOの相互変換

Df8bc8c531e2c5c89c1a007db1cf79a3?s=47 Yu Sugawara
September 23, 2017

Swift 4で行うDTOとDAOの相互変換

Df8bc8c531e2c5c89c1a007db1cf79a3?s=128

Yu Sugawara

September 23, 2017
Tweet

Transcript

  1. Swift 4Ͱߦ͏DTOͱDAOͷ૬ޓม׵ DevSapษڧձ 17/09/23

  2. ੁݪ ༞ @yusuga_

  3. None
  4. VO, DTO, POSO, DAOͱ͸

  5. VO, DTO, POSO, DAOͱ͸ 4 VO (Value Object) 4 getterͷΈ

    4 ෆม VO, DTO, POSO, DAO, Entity ͷҧ͍
  6. VO, DTO, POSO, DAOͱ͸ 4 DTO (Data Transfer Object) 4

    VO + setter 4 Մมɻ֎͔ΒมߋՄೳ 4 ҟͳΔϨΠϠʔؒʢϞσϧ૚ɺϏϡʔ૚ͳͲʣͰσʔλ Λड͚౉͢ͷʹ࢖͏ VO, DTO, POSO, DAO, Entity ͷҧ͍
  7. VO, DTO, POSO, DAOͱ͸ 4 POSO (Plain Old Swift Object)

    4 VO΍DTOͷੑ࣭Λ࣋ͭ 4 Swift struct, enum 4 ໋໊ͷ༝དྷ͸POJO(Plain Old Java Object) VO, DTO, POSO, DAO, Entity ͷҧ͍
  8. VO, DTO, POSO, DAOͱ͸ 4 DAO (Data Access Object) 4

    DBʹΞΫηε͠஋Λߋ৽ͨ͠Γ݁ՌΛฦ͢ VO, DTO, POSO, DAO, Entity ͷҧ͍
  9. ஌͖͔͚ͬͨͬ 4 try! Swift Tokyo 2017 4 σʔλϨΠϠΛ෼཭͢Δ (LT) 4

    ҿΈձͰ΋࿩୊ʹ
  10. ͦ͏͍͑͹ 4 Realm.RLMObject (RealmSwift.Object) 1. ελϯυΞϩʔϯͷRLMObject 2. Realm(σʔλϕʔε)ʹඥ͚ͮΒΕ͍ͯΔRLMObject RealmͰελϯυΞϩʔϯͷRLMObjectΛ׆༻͢Δ

  11. ͦ͏͍͑͹ 4 Realm.RLMObject (RealmSwift.Object) 1. ελϯυΞϩʔϯͷRLMObject 4 DTO 2. Realm(σʔλϕʔε)ʹඥ͚ͮΒΕ͍ͯΔRLMObject

    4 DAO RealmͰελϯυΞϩʔϯͷRLMObjectΛ׆༻͢Δ
  12. ҟͳΔϨΠϠʔؒͰͷσʔλͷड͚౉͠ MVC→MVP→MVVM→Fluxͷ࣮૷ͷҧ͍Λൺֱͯ͠ΈΔ

  13. DAOΛ౉͢΂͖Ͱ͸ͳ͍ 4 Ͳ͜ͰͰ΋σʔλϕʔεͷߋ৽͕Մೳʹͳͬͯ͠·͏

  14. DAOΛ౉͢΂͖Ͱ͸ͳ͍ 4 Ͳ͜ͰͰ΋σʔλϕʔεͷߋ৽͕Մೳʹͳͬͯ͠·͏ 4 Realmʹݶͬͯ͸ɺDBʹඥ͍ͮͨObjectͷߋ৽ʹ͸τϥ ϯβΫγϣϯ͕ඞཁͰ͋ͬͨΓɺεϨουΛ·ͨ͛ͳ͍ͱ ͍͏੍໿͕͋Δ

  15. DAOΛ౉͢΂͖Ͱ͸ͳ͍ 4 Ͳ͜ͰͰ΋σʔλϕʔεͷߋ৽͕Մೳʹͳͬͯ͠·͏ 4 Realmʹݶͬͯ͸ɺDBʹඥ͍ͮͨObjectͷߋ৽ʹ͸τϥ ϯβΫγϣϯ͕ඞཁͰ͋ͬͨΓɺεϨουΛ·ͨ͛ͳ͍ͱ ͍͏੍໿͕͋Δ 4 ͜ΕΒͷ࢓༷ΛͲ͏΍ͬͯप஌ͤ͞Δ͔ʁ

  16. DAOΛ౉͢΂͖Ͱ͸ͳ͍ 4 Ͳ͜ͰͰ΋σʔλϕʔεͷߋ৽͕Մೳʹͳͬͯ͠·͏ 4 Realmʹݶͬͯ͸ɺDBʹඥ͍ͮͨObjectͷߋ৽ʹ͸τϥ ϯβΫγϣϯ͕ඞཁͰ͋ͬͨΓɺεϨουΛ·ͨ͛ͳ͍ͱ ͍͏੍໿͕͋Δ 4 ͜ΕΒͷ࢓༷ΛͲ͏΍ͬͯप஌ͤ͞Δ͔ʁ 4

    ࢓༷ॻ/ӡ༻ϧʔϧ → ❌
  17. DAOΛ౉͢΂͖Ͱ͸ͳ͍ 4 Ͳ͜ͰͰ΋σʔλϕʔεͷߋ৽͕Մೳʹͳͬͯ͠·͏ 4 Realmʹݶͬͯ͸ɺDBʹඥ͍ͮͨObjectͷߋ৽ʹ͸τϥ ϯβΫγϣϯ͕ඞཁͰ͋ͬͨΓɺεϨουΛ·ͨ͛ͳ͍ͱ ͍͏੍໿͕͋Δ 4 ͜ΕΒͷ࢓༷ΛͲ͏΍ͬͯप஌ͤ͞Δ͔ʁ 4

    ࢓༷ॻ/ӡ༻ϧʔϧ → ❌ 4 VO, DTOΛ౉͠ϓϩάϥϜతʹ੍ݶͤ͞Δ΂͖
  18. ࣮૷: Objective-C࣌୅

  19. ࣮૷: Objective-C࣌୅ 4 Realm-JSONͷdeepCopy()Λ࢖༻

  20. ࣮૷: Objective-C࣌୅ 4 Realm-JSONͷdeepCopy()Λ࢖༻ 4 த਎͸Realm.RLMPropertyΛར༻͠ϓϩύςΟΛղੳ ͠ɺ࠶ؼతʹίϐʔ

  21. // 1. ΦϒδΣΫτΛ࡞੒͢Δ Person *author = [[Person alloc] init]; author.name

    = @"David Foster Wallace"; // 2. ΦϒδΣΫτΛRealmʹ௥Ճ͢Δ [realm beginWriteTransaction]; [realm addObject:author]; [realm commitWriteTransaction]; // author͸DAOʹͳΔ // 3. อଘͨ͠authorΛίϐʔ Person *copiedAuthor = [author deepcopy]; XCTAssertNil(copiedAuthor.realm); // true XCTAssertEqualObjects(author, copiedAuthor); // true // 4. τϥϯβΫγϣϯ͕ͳͯ͘΋มߋՄೳ copiedAuthor = @"other name"; // DTO
  22. 4 ৄ͘͠͸ɺRealmͰελϯυΞϩʔϯͷRLMObjectΛ׆༻ ͢ΔΛ͝ཡ͍ͩ͘͞ɻ

  23. Objective-C࣌୅ͷऴᖼ 4 RealmSwiftͷొ৔

  24. Objective-C࣌୅ͷऴᖼ 4 RealmSwiftͷొ৔ 4 RealmSwift.Object͸RLMObjectBaseΛܧঝ

  25. Objective-C࣌୅ͷऴᖼ 4 RealmSwiftͷొ৔ 4 RealmSwift.Object͸RLMObjectBaseΛܧঝ 4 Realm-JSONͷdeepCopy()͕࢖͑ͳ͘ͳΔ

  26. Objective-C࣌୅ͷऴᖼ 4 RealmSwiftͷొ৔ 4 RealmSwift.Object͸RLMObjectBaseΛܧঝ 4 Realm-JSONͷdeepCopy()͕࢖͑ͳ͘ͳΔ 4 ౰࣌͸୅ସͳ͠

  27. ࣮૷: Swift 3࣌୅

  28. ࣮૷: Swift 3࣌୅ 4 ObjectMapperΛ࢖༻

  29. ࣮૷: Swift 3࣌୅ 4 ObjectMapperΛ࢖༻ 4 Object to JSON /

    JSON to Object͕Մೳ
  30. ࣮૷: Swift 3࣌୅ 4 ObjectMapperΛ࢖༻ 4 Object to JSON /

    JSON to Object͕Մೳ 4 SwiftͷStructʹ΋ద༻Ͱ͖Δʂ
  31. ࡞ͬͨ TransformableObject

  32. TransformableObject public protocol TransformableObject { associatedtype TransformedObject } public extension

    TransformableObject where Self: Mappable, TransformedObject: Mappable { func transformToObject() -> TransformedObject? { return TransformedObject(JSON: toJSON()) } }
  33. ڞ௨͢Δgetter/setterͷprotocol protocol ObjectType: Mappable { var bool: Bool { get

    set } var int: Int { get set } var float: Float { get set } var double: Double { get set } var string: String { get set } var date: Date { get set } var data: Data { get set } }
  34. ObjectMapperͷϚοϐϯά extension ObjectType { mutating func mapping(map: Map) { bool

    <- map["bool"] int <- map["int"] float <- map["float"] double <- map["double"] string <- map["string"] date <- (map["date"], DateTransform()) data <- (map["data"], DataTransform()) } }
  35. POSOͷఆٛ struct Struct: ObjectType { var bool = false var

    int = 0 var float: Float = 0 var double: Double = 0 var string = "" var date = Date() var data = Data() init?(map: Map) { } }
  36. DAOͷఆٛ class RealmObject: Object, ObjectType { dynamic var bool =

    false dynamic var int = 0 dynamic var float: Float = 0 dynamic var double: Double = 0 dynamic var string = "" dynamic var date = Date() dynamic var data = Data() required convenience init?(map: Map) { self.init() } }
  37. TransformableObjectʹ४ڌ extension Struct: TransformableObject { typealias TransformedObject = RealmObject }

    extension RealmObject: TransformableObject { typealias TransformedObject = Struct }
  38. Struct → RealmSwift.Object let obj = Struct(JSON: JSONCreator.json())! let realmObj

    = obj.transformToObject()! RealmSwift.Object → Struct let realmObj = RealmObject(JSON: JSONCreator.json())! let obj = obj.transformToObject()!
  39. ར༻γʔϯ let editVC = R.storyboard .ownerEditViewController .instantiateInitialViewController()! editVC.owner = userList.owner!.transformToObject()

    // 1. DAO ! POSO editVC.ownerUpdated .map { $0.transformToObject() } // 2. POSO ! DTO .bind(to: Realm.rx.add(update: true)) .disposed(by: disposeBag)
  40. σϝϦοτ 4 ObjectMapperͷϚοϐϯάΛॻ͘ͷ͕൥ࡶ

  41. σϝϦοτ 4 ObjectMapperͷϚοϐϯάΛॻ͘ͷ͕൥ࡶ 4 RealmSwift.ObjectͱStructͰಉ͡ఆٛΛॻ͘ͷ͕൥ࡶ

  42. σϝϦοτ 4 ObjectMapperͷϚοϐϯάΛॻ͘ͷ͕൥ࡶ 4 RealmSwift.ObjectͱStructͰಉ͡ఆٛΛॻ͘ͷ͕൥ࡶ 4 StructΛ࢖͏ͳΒ͠ΐ͏͕ͳ͍

  43. ࣮૷: Swift 4࣌୅

  44. ࣮૷: Swift 4࣌୅ 4 Codable protocolͷొ৔

  45. ࣮૷: Swift 4࣌୅ 4 Codable protocolͷొ৔ 4 Swift 4ͷFoundationʹCodable͕௥Ճ͞Εͨ

  46. ࣮૷: Swift 4࣌୅ 4 Codable protocolͷొ৔ 4 Swift 4ͷFoundationʹCodable͕௥Ճ͞Εͨ 4

    Codable͸class, struct, enumͷ͢΂ͯͷγϦΞϥΠ ζ/σγϦΞϥΠζΛՄೳʹ͍ͯ͠Δ
  47. ࣮૷: Swift 4࣌୅ 4 Codable protocolͷొ৔ 4 Swift 4ͷFoundationʹCodable͕௥Ճ͞Εͨ 4

    Codable͸class, struct, enumͷ͢΂ͯͷγϦΞϥΠ ζ/σγϦΞϥΠζΛՄೳʹ͍ͯ͠Δ 4 ܕ҆શੑ
  48. Codable public typealias Codable = Decodable & Encodable

  49. ఆٛ public struct Location : Codable { // 1 public

    let latitude: Double public let longitude: Double } public enum Animal : Int, Codable { // 2 case chicken = 1 case dog case turkey case cow } public struct Farm : Codable { // 3 public let name: String public let location: Location public let animals: [Animal] } SE-0166
  50. Encoder / Decoder 4 JSONEncoder / JSONDecoder 4 PropertyListEncoder /

    PropertyListDecoder
  51. ࢖༻ํ๏ let farm = Farm(name: "Old MacDonald's Farm", location: Location(latitude:

    51.621648, longitude: 0.269273), animals: [.chicken, .dog, .cow, .turkey, .dog, .chicken, .cow, .turkey, .dog]) let payload: Data = try JSONEncoder().encode(farm) // 1 do { let farm = try JSONDecoder().decode(Farm.self, from: payload) // 2 // Extracted as user types: let coordinates = "\(farm.location.latitude, farm.location.longitude)" } catch { // Encountered error during deserialization } SE-0166
  52. Codable 4 ObjectMapperͰߦͳ͍ͬͯͨϚοϐϯάΛCodableʹஔ ͖׵͑ΒΕͦ͏

  53. ࡞ͬͨ ObjectConvertible

  54. ObjectConvertible public protocol ObjectConvertible: Encodable {} public extension ObjectConvertible {

    func convert<T: Decodable>() throws -> T { return try JSONDecoder().decode( T.self, from: try JSONEncoder().encode(self)) } }
  55. Ϟσϧڞ௨ͷgetter protocol ObjectType { var bool: Bool { get }

    var int: Int { get } var float: Float { get } var double: Double { get } var string: String { get } }
  56. POSOͷఆٛ struct Object: ObjectType, Codable, ObjectConvertible { var bool: Bool

    var int: Int var float: Float var double: Double var string: String }
  57. DAOͷఆٛ @objcMembers class RealmObject: RealmSwift.Object, ObjectType, Codable, ObjectConvertible { dynamic

    var bool = false dynamic var int = 0 dynamic var float: Float = 0 dynamic var double: Double = 0 dynamic var string = "" }
  58. POSOͷม׵ extension Object { /// 1. POSO ! VO var

    VO: ObjectType { return self } /// 2. POSO ! DAO(DTO) func convertToDAO() throws -> RealmObject { return try convert() } }
  59. DAOͷม׵ extension RealmObject { /// 1. DAO ! POSO func

    convertToPOSO() throws -> Object { return try convert() } /// 2. DAO ! DTO func convertToDTO() throws -> RealmObject { return try convert() } /// 3. DAO ! VO func convertToVO() throws -> ObjectType { return try convertToDTO() } }
  60. ม׵ͷࣦഊ // Swift.DecodingError.keyNotFound let obj: RealmObject = try! Person().convert()

  61. ม׵ͷࣦഊ // Swift.DecodingError.keyNotFound let obj: RealmObject = try! Person().convert() 4

    ΋ͪΖΜఆ͕ٛҰக͠ͳ͍Ϟσϧؒͷม׵͸ɺσίʔυ· ͨ͸Τϯίʔυͷྫ֎͕ൃੜ͢Δ
  62. ม׵ͷࣦഊ // Swift.DecodingError.keyNotFound let obj: RealmObject = try! Person().convert() 4

    ΋ͪΖΜఆ͕ٛҰக͠ͳ͍Ϟσϧؒͷม׵͸ɺσίʔυ· ͨ͸Τϯίʔυͷྫ֎͕ൃੜ͢Δ 4 ݱঢ়ͷҊͰ͸ObjectConvertibleͰdecodeՄೳͳܕ͸੍ ݶͤͣɺϓϩάϥϚͷ੹೚Ͱconvert()Λ࢖༻͢Δͱ͍͏ ํ਑
  63. ·ͱΊ 4 σʔλϨΠϠͷ෼཭͸େࣄ

  64. ·ͱΊ 4 σʔλϨΠϠͷ෼཭͸େࣄ 4 ࢓༷ॻ΍ӡ༻ϧʔϧͰ͸ͳ͘ɺϓϩάϥϜͰ࢓༷ΛറΔ ΂͖ɹ

  65. ·ͱΊ 4 σʔλϨΠϠͷ෼཭͸େࣄ 4 ࢓༷ॻ΍ӡ༻ϧʔϧͰ͸ͳ͘ɺϓϩάϥϜͰ࢓༷ΛറΔ ΂͖ɹ 4 ࣮૷ͷ൥ࡶ͞ͱ͸τϨʔυΦϑ

  66. ·ͱΊ 4 σʔλϨΠϠͷ෼཭͸େࣄ 4 ࢓༷ॻ΍ӡ༻ϧʔϧͰ͸ͳ͘ɺϓϩάϥϜͰ࢓༷ΛറΔ ΂͖ɹ 4 ࣮૷ͷ൥ࡶ͞ͱ͸τϨʔυΦϑ 4 Codableͷ͓͔͛Ͱ֎෦ϥΠϒϥϦʹґଘ͢Δ͜ͱͳ͘Ϛ

    οϐϯά͔Ͱ͖ΔΑ͏ʹͳΓɺDecoder/EncoderΛհ͢ Δ͜ͱͰҟͳΔϞσϧؒͰͷϚοϐϯά΋༰қʹͳͬͨ
  67. ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

  68. ࢀߟ/Ҿ༻ 4 VO, DTO, POSO, DAO, Entity ͷҧ͍ 4 MVC→MVP→MVVM→Fluxͷ࣮૷ͷҧ͍Λൺֱͯ͠ΈΔ

    4 RealmͰελϯυΞϩʔϯͷRLMObjectΛ׆༻͢Δ 4 SE-0166