Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
potatotips #36: Translatorのススメ
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Takeshi Ihara
January 17, 2017
Programming
580
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
potatotips #36: Translatorのススメ
potatotips #36
https://potatotips.connpass.com/event/46832/
Takeshi Ihara
January 17, 2017
More Decks by Takeshi Ihara
See All by Takeshi Ihara
iOSDC20200921: Feature Flagを適切に分類することでA/Bテストの運用コストを下げる
nonchalant
3
1.4k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装
nonchalant
3
6.5k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装 with 発表ノート
nonchalant
2
650
Sign In with Apple
nonchalant
1
2.5k
iOSDC RejectCon 20180915: Factoryの自動生成によりテストを書きやすくする
nonchalant
1
770
iOSDC 20180902: 小さくはじめる端末管理
nonchalant
2
1k
devsap 20180728: コード生成のススメ
nonchalant
0
150
potatotips #50: iOSは自動生成の夢を見るか?
nonchalant
0
2k
try! Swift Tokyo 2018: Best Docker Container in Swift
nonchalant
1
1.4k
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
480
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
390
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.1k
速習iPhone Duo対応
yuukiw00w
2
960
すこし踏み込む CancellationToken
htkym
2
1.6k
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
260
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
480
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
350
R8 の設定見直しでアプリサイズ削減
andpad
0
190
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
480
Are APIs Still Relevant in the AI Era?
soyuka
0
430
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
140
Featured
See All Featured
Code Review Best Practice
trishagee
74
20k
Tell your own story through comics
letsgokoyo
1
1.1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
Prompt Engineering for Job Search
mfonobong
0
490
Being A Developer After 40
akosma
91
590k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
1k
How to build a perfect <img>
jonoalderson
1
6.1k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
The Curious Case for Waylosing
cassininazir
1
560
Building AI with AI
inesmontani
PRO
1
1.3k
Transcript
Translatorͷεεϝ potatotips #36 / @nonchalant0303
Profile • Takeshi Ihara / @nonchalant0303 • Recruit Marketing Partners
• iOS Engineer
Translator • UseCaseͰऔಘͨ͠EntityΛPresentationͷ ͨΊͷModelʹม͢Δ 1SFTFOUBUJPO %PNBJO *OGSBTUSVDUVSF 6TF$BTF 5SBOTMBUPS 7JFX.PEFM
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) } }
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ʹ มϩδοΫؚ͕·ΕͯΔ
ผʹ͍͍ͷͰʁ
ͨͱ͑… 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)ԁ" } } }
ͨͱ͑… 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)ԁ" } } } ཁૉ͕૿͑Δͱ มϩδοΫ͕ංେԽ͕ͪ͠
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
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ʹϩδοΫ͕ છΈग़ͯ͠Δ
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
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
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ʹม͢Δ
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ʹม͢Δ
View, Entity͔Β มϩδοΫΛͰ͖ͨʂ
Pros/Cons of Translator • Pros • มϩδοΫΛͰ͖Δ • Cons •
ʹͳΓ͔Ͷͳ͍
ඞཁʹԠͯ͡TranslatorΛ ಋೖ͠Α͏ʂ
Translator͕༗ޮͩͱࢥ͏ྫ • UITableViewʹ දࣔ͢ΔΞΠςϜ͕ ʮEntityͷ+1ʯ
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 } }
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ͷϦεΫ
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() ) } }
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දࣔ͢Δ ΞΠςϜΛͯ͢༻ҙ
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 } }
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 } } ܕͰཧ͞ΕͯΔͷͰ ҆શʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠