Upgrade to Pro — share decks privately, control downloads, hide ads and more …

potatotips #36: Translatorのススメ

potatotips #36: Translatorのススメ

Takeshi Ihara

January 17, 2017
Tweet

More Decks by Takeshi Ihara

Other Decks in Programming

Transcript

  1. Entity w/o Translator struct Entity { let title: String let

    description: String let imageUrl: URL let rank: Rank init(title: String, description: String, imageUrl: String, rank: Int) { self.title = title self.description = description self.imageUrl = URL(string: imageUrl)! self.rank = Rank(rank: rank) } }
  2. Entity w/o Translator struct Entity { let title: String let

    description: String let imageUrl: URL let rank: Rank init(title: String, description: String, imageUrl: String, rank: Int) { self.title = title self.description = description self.imageUrl = URL(string: imageUrl)! self.rank = Rank(rank: rank) } } *OJUJBMJ[FSʹ ม׵ϩδοΫؚ͕·ΕͯΔ
  3. ͨͱ͑͹… import Foundation struct Entity { let property1: String let

    property2: Float ... let property15: [String] init(property1: Int, property2: Int, property15: [Int]) { self.property1 = "\(property1)ԁ" self.property2 = Float(property2) * 1.08 ... self.property15 = property15.map { "\($0)ԁ" } } }
  4. ͨͱ͑͹… import Foundation struct Entity { let property1: String let

    property2: Float ... let property15: [String] init(property1: Int, property2: Int, property15: [Int]) { self.property1 = "\(property1)ԁ" self.property2 = Float(property2) * 1.08 ... self.property15 = property15.map { "\($0)ԁ" } } } ཁૉ͕૿͑Δͱ ม׵ϩδοΫ͕ංେԽ͕ͪ͠
  5. class TableViewCell: UITableViewCell { @IBOutlet private weak var label1: UILabel!

    @IBOutlet private weak var label2: UILabel! ... @IBOutlet private weak var label15: UILabel! func configure(entity: Entity) { label1.text = "\(entity.property1)ԁ" label2.text = "\(Float(entity.property2) * 1.08)" ... label15.text = entity.property15.map { "\($0)ԁ" }.reduce("") { $0 != "" ? "\($0), \($1)" : "\($1)" } } } 1. Translate in View
  6. class TableViewCell: UITableViewCell { @IBOutlet private weak var label1: UILabel!

    @IBOutlet private weak var label2: UILabel! ... @IBOutlet private weak var label15: UILabel! func configure(entity: Entity) { label1.text = "\(entity.property1)ԁ" label2.text = "\(Float(entity.property2) * 1.08)" ... label15.text = entity.property15.map { "\($0)ԁ" }.reduce("") { $0 != "" ? "\($0), \($1)" : "\($1)" } } } 1. Translate in View 7JFXʹϩδοΫ͕ છΈग़ͯ͠Δ
  7. struct Entity { let property1: String let property2: Int ...

    let property15: [String] } struct ViewModel { let property1: String let property2: String ... let property15: String } class Translator { static func translate(entity: Entity) -> ViewModel { return ViewModel( property1: "\(entity.property1)ԁ", property2: "\(Float(entity.property2) * 1.08)", ... property15: entity.property15.map { "\($0)ԁ" }.reduce("") { $0 != "" ? "\($0), \($1)" : "\($1)" } ) } } 2. Translator
  8. struct Entity { let property1: String let property2: Int ...

    let property15: [String] } struct ViewModel { let property1: String let property2: String ... let property15: String } class Translator { static func translate(entity: Entity) -> ViewModel { return ViewModel( property1: "\(entity.property1)ԁ", property2: "\(Float(entity.property2) * 1.08)", ... property15: entity.property15.map { "\($0)ԁ" }.reduce("") { $0 != "" ? "\($0), \($1)" : "\($1)" } ) } } 2. Translater 1SFTFOUBUJPO૚ͷͨΊͷ .PEFMΛ༻ҙ͢Δ 5SBOTMBUPS
  9. 2. Translator class Repository { func findAll() -> [Entity] {

    return ... } } class UseCase { let repository: Repository init(repository: Repository) { self.repository = repository } func getAll() -> [ViewModel] { return repository.findAll().map { Translator.translate(entity: $0) } } } UseCaseͰऔಘͨ͠EntityΛPresentation૚ͷͨΊͷModelʹม׵͢Δ
  10. 2. Translater class Repository { func findAll() -> [Entity] {

    return ... } } class UseCase { let repository: Repository init(repository: Repository) { self.repository = repository } func getAll() -> [ViewModel] { return repository.findAll().map { Translator.translate(entity: $0) } } } UseCaseͰऔಘͨ͠EntityΛPresentation૚ͷͨΊͷModelʹม׵͢Δ &OUJUZΛ.PEFMʹม׵͢Δ
  11. ViewController w/o Translator class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private

    let tableView = UITableView(frame: UIScreen.main.bounds) var todos: [Todo] = [] // Entity override func viewDidLoad() { ... } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return todos.count + 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() if indexPath.row < todos.count { cell.textLabel?.text = todos[indexPath.row].title } else { cell.textLabel?.text = "+ ௥Ճ͢Δ" cell.textLabel?.textColor = .gray } return cell } }
  12. ViewController w/o Translator class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private

    let tableView = UITableView(frame: UIScreen.main.bounds) var todos: [Todo] = [] // Entity override func viewDidLoad() { ... } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return todos.count + 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() if indexPath.row < todos.count { cell.textLabel?.text = todos[indexPath.row].title } else { cell.textLabel?.text = "+ ௥Ճ͢Δ" cell.textLabel?.textColor = .gray } return cell } } *OEFY1BUIͰ؅ཧͯͯ͠πϥΠ 3VOUJNFFSSPSͷϦεΫ
  13. Translate from Entity to Model protocol Translator { associatedtype Entity

    associatedtype Model static func translate(entity: Entity) -> Model } struct Todo { let title: String } enum Item { case todo(title: String) case add(title: String) } class TodoTranslator: Translator { typealias Entity = [Todo] typealias ViewModel = [Item] static func translate(entity: Entity) -> ViewModel { return Array( [ entity.map { Item.todo(title: $0.title) }, [ Item.add(title: "+ ௥Ճ͢Δ") ] ].joined() ) } }
  14. Translate from Entity to Model protocol Translator { associatedtype Entity

    associatedtype Model static func translate(entity: Entity) -> Model } struct Todo { let title: String } enum Item { case todo(title: String) case add(title: String) } class TodoTranslator: Translator { typealias Entity = [Todo] typealias ViewModel = [Item] static func translate(entity: Entity) -> ViewModel { return Array( [ entity.map { Item.todo(title: $0.title) }, [ Item.add(title: "+ ௥Ճ͢Δ") ] ].joined() ) } } $FMM༻ͷ.PEFM 5BCMF7JFXදࣔ͢Δ ΞΠςϜΛ͢΂ͯ༻ҙ
  15. ViewController w/ Translator class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private

    let tableView = UITableView(frame: UIScreen.main.bounds) var items: [Item] = [] // Model override func viewDidLoad() { ... } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() switch items[indexPath.row] { case .todo(let title): cell.textLabel?.text = title case .add(let title): cell.textLabel?.text = title cell.textLabel?.textColor = .gray } return cell } }
  16. ViewController w/ Translator class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private

    let tableView = UITableView(frame: UIScreen.main.bounds) var items: [Item] = [] // Model override func viewDidLoad() { ... } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() switch items[indexPath.row] { case .todo(let title): cell.textLabel?.text = title case .add(let title): cell.textLabel?.text = title cell.textLabel?.textColor = .gray } return cell } } ܕͰ؅ཧ͞ΕͯΔͷͰ ҆શʂ