Product Engineer 西 悠作 @jrsaruo_tech
後夜祭 iOSDC Japan 2023 登壇資料
コードを読みやすく・挙動を予測しやすくするために、 Swift の API Design Guidelines を活用しましょう。
本トークでは実際のコード例をもとに
- ガイドラインの示す API の理想像とは? - API 設計における大事な観点とは?
を解説します。 API の構成要素すべてを洗練させ、簡潔明瞭で美しいAPIをデザインしましょう!
$PQZSJHIU1SFTFOU"/%1"%*OD5IJTJOGPSNBUJPOJTDPOGJEFOUJBMBOEXBTQSFQBSFECZ"/%1"%*ODGPSUIFVTFPGPVSDMJFOU*UJTOPUUPCFSFMJFEPOCZBOESEQBSUZ1SPQSJFUBSZ$POGJEFOUJBMແஅసࡌɾແஅෳͷېࢭ࣮ફʂSwift API Design Guidelinesʹج͍ͮͨ؆ܿ໌ྎͳAPIͷ࡞Γํ ༔࡞
View Slide
༔࡞ @jrsaruo_techΞχϝɹອըɹήʔϜɹSwift199612݄21ੜגࣜձࣾΞϯυύουେࡕग़ ੜ
SwiftͷAPI Design GuidelinesͱAPIɿApplication Programming InterfaceSwiftʹ͓͚Δʰྑ͍APIʱͷ࡞ΓํΛࣔͨ͠ͷϝιουϓϩύςΟͱ͍ͬͨΠϯλʔϑΣΠεhttps://www.swift.org/documentation/api-design-guidelines/
API Design Guidelinesͷࣔ͢ʰྑ͍APIʱͱʁͦΕΛ࡞Δʹʁຊ͢͜ͱ͜Μͳ͔ͨͬͨ͠Ͱ͕͢ຊׂѪɿmove(destination:)ΑΓmove(to:)ʂbookId͡Όͳͯ͘bookIDʂ shopUrl͡Όͳͯ͘shopURLʂ
let string = input.message.trim()let mail = try await Mailer.sendMail(string, to: "Taro")mailBox.update(mail: mail, bottom: false)ԿΛτϦϛϯά͍ͯ͠Δʁinput.messageࣗମΛՃ͍ͯ͠ΔʁԿΛ͍ͯ͠Δʁbottom: falseͱʁtrueʹ͢ΔͱͲ͏ͳΔʁϝʔϧΞυϨεͰͳ͘ਓ໊ʁ🤔
let message = input.message.trimmingWhitespaces()let sentMail = try await Mailer.send(message, toAddress: "Taro")mailBox.insert(sentMail, at: .top)🙂Ҿؒҧ͑ͯΔʂ
એݴଆҎ্ʹར༻ଆͰͷ໌շ͕͞࠷ॏཁAPI Design Guidelines - Fundamentals؆ܿ͞ΑΓ໌շ͞ͷํ͕େࣄϝιουϓϩύςΟͷએݴ1Օॴ͕ͩར༻ෳՕॴ؆ܿ͞SwiftͷݴޠػೳʹΑΔ෭࣍ޮՌɻΰʔϧͰͳ͍υΩϡϝϯτίϝϯτॻ͜͏Ͷ
໌շͱʁ
ڍಈΛ༧ଌ͍͢͠໌շͳAPIͱ͍ؒҧ͑ʹ͍͘ɺؒҧ͍ͬͨํ͕Ͱ͖ͳ͍ʮݺͿͱԿ͕ى͖Δͷ͔ʯ͕͖ͬΓ͔Δ͍ํ͕͔Γ͍͢
ใΛෆͤ͞ͳ͍໌շͳAPIΛઃܭ͢ΔʹใΛͤ͞ͳ͍ใ͕ଟ͗͢Δͱೝෛՙ্͕͕Δใ͕গͳ͗͢ΔͱᐆດʹͳΔ
͞ͳ͍͔ʁAPIͷׂʁ໌շͳAPIΛઃܭ͢ΔͨΊͷ4ͭͷ͍ใΓ͍ͯΔ͔ʁ෭࡞༻͋Δ͔ʁࣗΛมߋ͢Δ͔ʁ
let mail = try await Mailer.sendMail(string, to: "...")mailBox.update(mail: mail, bottom: false)let string = input.message.trim()
let string = input.message.trim()func trim() -> StringQ. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁ༨നΛτϦϛϯάͨ͠จࣈྻΛฦ͢Q. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁ
let string = input.message.trimWhitespaces()func trimWhitespaces() -> StringQ. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁ༨നΛτϦϛϯάͨ͠จࣈྻΛฦ͢͠ͳ͍Q. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁFEɺJOHܗʹ͢Δ
let string = input.message.trimmingWhitespaces()func trimmingWhitespaces() -> StringQ. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁ ͠ͳ͍Q. ͞ͳ͍͔ʁ 0,Q. ใΓ͍ͯΔ͔ʁ 0,FEɺJOHܗʹ͢Δ༨നΛτϦϛϯάͨ͠จࣈྻΛฦ͢
let mail = try await Mailer.sendMail(string, to: "...")mailBox.update(mail: mail, bottom: false)let string = input.message.trimmingWhitespaces()
let mail = try await Mailer.sendMail(string, to: "...")func sendMail(_ message: String,to destinationAddress: String) async throws -> MailQ. APIͷׂʁQ. ෭࡞༻͋Δ͔ʁࢦఆͷѼઌʹϝʔϧΛૹ৴͢Δ͋ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁ to͚ͩͰͲΜͳจࣈྻͳͷ͔ར༻ଆͰ͔Γʹ໋͍͘ྩܗʹ͢Δ ܕใ͕ऑ͍ͱى͖͕ͪAny, Int, String, ...
func sendMail(_ message: String,toAddress destinationAddress: String) async throws -> MailQ. APIͷׂʁQ. ෭࡞༻͋Δ͔ʁࢦఆͷѼઌʹϝʔϧΛૹ৴͢Δ͋ΔQ. ͞ͳ͍͔ʁ Mailແͯ͘ΘΔʢMailer͔ΒਪଌͰ͖ΔʣQ. ใΓ͍ͯΔ͔ʁlet mail = try await Mailer.sendMail(string, toAddress: "...")໋ྩܗʹ͢Δ ܕใ͕ऑ͍ͱى͖͕ͪAny, Int, String, ...to͚ͩͰͲΜͳจࣈྻͳͷ͔ར༻ଆͰ͔Γʹ͍͘
func send(_ message: String,toAddress destinationAddress: String) async throws -> MailQ. APIͷׂʁQ. ෭࡞༻͋Δ͔ʁࢦఆͷѼઌʹϝʔϧΛૹ৴͢Δ͋ΔQ. ͞ͳ͍͔ʁ Mailແͯ͘ΘΔʢMailer͔ΒਪଌͰ͖ΔʣQ. ใΓ͍ͯΔ͔ʁlet mail = try await Mailer.send(string, toAddress: "...")໋ྩܗʹ͢Δ ܕใ͕ऑ͍ͱى͖͕ͪAny, Int, String, ...to͚ͩͰͲΜͳจࣈྻͳͷ͔ར༻ଆͰ͔Γʹ͍͘
let string = input.message.trimmingWhitespaces()mailBox.update(mail: mail, bottom: false)let mail = try await Mailer.send(string, toAddress: "...")
func update(mail: Mail, bottom: Bool)Q. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁϝʔϧΛϝʔϧϘοΫεͷτοϓʹૠೖ͢ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁmailBox.update(mail: mail, bottom: false)
func insert(mail: Mail, bottom: Bool)Q. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁϝʔϧΛϝʔϧϘοΫεͷτοϓʹૠೖ͢ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁmailBox.insert(mail: mail, bottom: false)తޠ
func insertMail(_ mail: Mail, bottom: Bool)Q. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁϝʔϧΛϝʔϧϘοΫεͷτοϓʹૠೖ͢Δ͢ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁ bottom: falseᐆດmailBox.insertMail(mail, bottom: false)໋ྩܗʹ͢Δenumʹͯ͠ΈΔ
func insertMail(_ mail: Mail, at position: InsertPosition)Q. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁϝʔϧΛϝʔϧϘοΫεͷτοϓʹૠೖ͢Δ͢ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁMailແͯ͘ΘΔbottom: falseᐆດmailBox.insertMail(mail, at: .top)໋ྩܗʹ͢Δenumʹͯ͠ΈΔ
func insert(_ mail: Mail, at position: InsertPosition)Q. APIͷׂʁQ. ࣗΛมߋ͢Δ͔ʁϝʔϧΛϝʔϧϘοΫεͷτοϓʹૠೖ͢Δ͢ΔQ. ͞ͳ͍͔ʁQ. ใΓ͍ͯΔ͔ʁMailແͯ͘ΘΔbottom: falseᐆດmailBox.insert(mail, at: .top)໋ྩܗʹ͢Δenumʹͯ͠ΈΔ
string = input.message.trimmingWhitespaces()string, toAddress: "...")mail = try await Mailer.send(letletmailBox.insert(mail, at: .top)
message = input.message.trimmingWhitespaces()message, toAddress: "...")mail = try await Mailer.send(letletmailBox.insert(mail, at: .top)mailBox.insert(mail, at: .top)
sentMail = try await Mailer.send(message, toAddress: "...")message = input.message.trimmingWhitespaces()letletmailBox.insert(sentMail, at: .top)
sentMail = try await Mailer.send(message, toAddress: "...")message = input.message.trimmingWhitespaces()letletlet string = input.message.trimString()let mail = try await Mailer.sendMail(string, to: "...")mailBox.update(mail: mail, bottom: false) 🤔🙂mailBox.insert(sentMail, at: .top)
API Design GuidelinesΛಡ͏ར༻ଆͰͷ໌շ͞Λॏࢹ͠Α͏·ͱΊ໌շͳAPIΛઃܭ͢ΔͨΊͷ4ͭͷ͍APIͷׂɺ෭࡞༻͋Δ͔ɺใΓ͍ͯΔ͔ɺ͞ͳ͍͔
We are Hiring !!IUUQTFOHJOFFSBOEQBEDPKQΤϯδχΞ࠾༻
͋Γ͕ͱ͏͍͟͝·ͨ͠@jrsaruo_tech'PMMPXNF𝕏