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
570
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.4k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装 with 発表ノート
nonchalant
2
650
Sign In with Apple
nonchalant
1
2.5k
iOSDC RejectCon 20180915: Factoryの自動生成によりテストを書きやすくする
nonchalant
1
760
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
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
220
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
370
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
140
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
150
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
150
Jetpack Compose メカニズム
skydoves
0
140
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
700
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
330
Laravelのアプリケーションをどこにデプロイするか #ツナギメオフライン.9
akase244
0
130
Heart of Swift Concurrency
koher
0
330
Intent as Code
shoppingjaws
6
970
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
140
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
96
14k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
700
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
300
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Discover your Explorer Soul
emna__ayadi
2
1.3k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
480
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
Why Our Code Smells
bkeepers
PRO
340
58k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
540
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
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 } } ܕͰཧ͞ΕͯΔͷͰ ҆શʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠