Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Self-Documenting のススメ
Search
Elvis Shi
September 20, 2018
Programming
1.1k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Self-Documenting のススメ
Elvis Shi
September 20, 2018
More Decks by Elvis Shi
See All by Elvis Shi
@Environment(\.keyPath)那么好我不允许你们不知道! / atEnvironment keyPath is so good and you should know it!
lovee
0
450
ゼロから始めるPreferenceの実装 / Let's implement Preferences from scratch
lovee
0
150
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
390
個人アプリを2年ぶりにアプデしたから褒めて / I just updated my personal app, praise me!
lovee
0
730
How did I build an Open-Source SwiftUI Toast Library
lovee
1
170
SwiftUIで使いやすいToastの作り方 / How to build a Toast system which is easy to use in SwiftUI
lovee
3
1.3k
SwiftUIで二重スクロール作ってみた / When I tried to make a dual-scroll-ish view in SwiftUI
lovee
1
380
Observation のあれこれ / A brief introduction about Observation
lovee
3
440
ChatGPT 時代の勉強 / Learning under ChatGPT era
lovee
27
9k
Other Decks in Programming
See All in Programming
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
550
AI 輔助遺留系統現代化的經驗分享
jame2408
1
800
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
350
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
200
A2UI という光を覗いてみる
satohjohn
1
140
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
260
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
360
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
370
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.3k
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
14
5.6k
Vite+ Unified Toolchain for the Web
naokihaba
0
320
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
190
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
220
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Mind Mapping
helmedeiros
PRO
1
250
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
200
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.5k
We Have a Design System, Now What?
morganepeng
55
8.2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
AI: The stuff that nobody shows you
jnunemaker
PRO
8
720
How to build a perfect <img>
jonoalderson
1
5.7k
New Earth Scene 8
popppiees
3
2.3k
Transcript
4FMG%PDVNFOUJOH$PEF ͷεεϝ forJ04%$3FKFDU$POGFSFODFEBZT
rܙྤ lզʑΤϯδχΞେͬݏ͍ͳ͜ͱ͕Cͭ͋Δ CͭυΩϡϝϯτΛॻ͘͜ͱɻ CͭυΩϡϝϯτͷͳ͍ଞਓ͕ॻ͍ͨ ίʔυΛอक͢Δ͜ͱͩɻz
rܙྤ lզʑΤϯδχΞେͬݏ͍ͳ͜ͱ͕Cͭ͋Δ CͭυΩϡϝϯτΛॻ͘͜ͱɻ CͭυΩϡϝϯτͷͳ͍ଞਓ͕ॻ͍ͨ ίʔυΛอक͢Δ͜ͱͩɻz
rܙྤ lզʑΤϯδχΞେͬݏ͍ͳ͜ͱ͕Cͭ͋Δ CͭυΩϡϝϯτΛॻ͘͜ͱɻ CͭυΩϡϝϯτͷͳ͍ଞਓ͕ॻ͍ͨ ίʔυΛอक͢Δ͜ͱͩɻz ʊਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓਓʊ ʼɹͩͬͨΒ࠷ॳ͔ΒυΩϡϝϯτͱͯ͠ɹʻ ʼɹ͑ΔίʔυΛॻ͚ສࣄղܾͳͷͰ
ɹʻ ʉ:?:?:?:?:?:?:?:?::?:?:?:?:?:?:?:?:ʉ
} var employedBy = "YUMEMI Inc." var job = "iOS
Developer" var favoriteLanguage = "Swift" var twitter = "@lovee" var qiita = "lovee" var github = "el-hoshino" var additionalInfo = """ iOSDC 2018 CfP શ෦མͪͨਏ͍ """ class Me: Developable, Talkable {
໔આ໌ w "͜ͷτʔΫίʔσΟϯάνοϓεతͳͰ͋Δ w #͜ͷτʔΫυΩϡϝϯτࣗಈੜͷͰͳ͍
rӳࣙ l4FMGEPDVNFOUJOHDPEFɿࣗݾจॻԽίʔυz
let s = (0 ..< 50) .map({ _ in Int.random(in:
0 ... 100) }) .filter({ $0 >= 60 }) .reduce(0, +)
let s = (0 ..< 50) .map({ _ in Int.random(in:
0 ... 100) }) .filter({ $0 >= 60 }) .reduce(0, +)
private extension Int { var isPassed: Bool { return self
>= 60 } } let numberOfStudents = 50 let studentsScoreList = (0 ..< numberOfStudents) .map({ _ -> Int in let score = Int.random(in: 0 ... 100) return score }) let passedStudentsScoreList = studentsScoreList .filter({ $0.isPassed }) let totalScoreOfAllPassedStudents = passedStudentsScoreList .reduce(0, +) ͳΔ΄Ͳɺςετʹ߹֨ͨ͠ੜెͷ ͷ߹ܭͶʂ
rܙྤ l4FMGEPDVNFOUJOHDPEFɿࣗࣗͷҙຯΛ ͖ͪΜͱઆ໌Ͱ͖͍ͯΔίʔυz
ͳͥ4FMG%PDVNFOUJOH$PEFʁ w ಉ͜͡ͱΛʮίʔυʯͱʮυΩϡϝϯτʯ྆ํͰॻ͘ ͱ͍͏ೋख͕ؒݮΔɻ w w w w w w
w w ίʔυϨϏϡʔ͕ΑΓ͘͢͠ͳΔɻ w ίϛολʔͷҙਤ͕ಡΈऔΓ͘͢ͳΔ w w w w w w w w w w w อक͢Δ࣌ʹՕॴΛಛఆ͘͢͠ͳΔ w w w w w w
4FMG%PDVNFOUJOH$PEFͷΞϓϩʔν w ՄಡੑʹؾΛ͚ͭΔ w Λࡉ͔͘நԽ w ҉ͳલఏΛͳ͘͢
ՄಡੑʹؾΛ͚ͭΔ
ՄಡੑʹؾΛ͚ͭΔʢʣ ͳΜͷ 63-ͩΖʁ let url = URL(string: "https://iosdc.jp/2018/")!
ՄಡੑʹؾΛ͚ͭΔʢʣ let apiBaseURL = URL(string: "https://iosdc.jp/2018/")! "1*ͷ ϕʔε63-ͩͶʂ
r୭͔ l؆ܿ͞ΑΓɺΘ͔Γ͢͞z
ՄಡੑʹؾΛ͚ͭΔʢʣ class Player { // ... var allowsMagic: Bool {
return // ຐ๏͕͑Δ͔Ͳ͏͔ͷఆ } } ຐ๏Λ ڐՄʜʁ
ՄಡੑʹؾΛ͚ͭΔʢʣ class Player { // ... var canUseMagic: Bool {
return // ຐ๏͕͑Δ͔Ͳ͏͔ͷఆ } } ຐ๏͕ ͑Δ͔Ͳ͏͔͔ʂ
r୭͔ lޡղͷͳ͍දݱʹؾΛ͚ͭΑ͏z
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(_ subview: UIView, _ baseView: UIView) { baseView.addSubview(subview)
} addSubview(avatarView, contentView) Ͳ͕ͬͪͲͬͪʹ Ճ͞ΕΔͷʜʁ
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(subview: UIView, baseView: UIView) { baseView.addSubview(subview) } addSubview(subview:
avatarView, baseView: contentView) ଟavatarView͕ࢠϏϡʔͰ contentView͕Ϗϡʔʁ
ՄಡੑʹؾΛ͚ͭΔʢʣ avatarViewΛ contentViewͷ্ʹՃͩͶʂ func addSubview(_ subview: UIView, onto baseView: UIView)
{ baseView.addSubview(subview) } addSubview(avatarView, onto: contentView)
r୭͔ lҾϥϕϧΛ͏·͘׆༻͠Α͏z
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(_ subview: UIView, onto baseView: UIView) { baseView.addSubview(subview)
} addSubview(avatarView, onto: contentView)
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(_ subview: UIView, onto baseView: UIView, ifNeeded) {
if !baseView.subviews.contains(where: { $0 === subview }) { baseView.addSubview(subview) } } addSubview(avatarView, onto: contentView, ifNeeded) ಡΈ͍͕͢ จ๏ΤϥʔͰ͋Δ
rܙྤ l4XJGUͷจ๏ʹ།Ұʹͯ͠࠷େͷෆຬ ޙஔϥϕϧ͕ͳ͍͜ͱz
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(_ subview: UIView, onto baseView: UIView, ifNeeded) {
if !baseView.subviews.contains(where: { $0 === subview }) { baseView.addSubview(subview) } } addSubview(avatarView, onto: contentView, ifNeeded)
ՄಡੑʹؾΛ͚ͭΔʢʣ enum AddSubviewPostLabel { case ifNeeded } func addSubview(_ subview:
UIView, onto baseView: UIView, _ label: AddSubviewPostLabel) { if !baseView.subviews.contains(where: { $0 === subview }) { baseView.addSubview(subview) } } addSubview(avatarView, onto: contentView, .ifNeeded) ߈ུ"ɿޙஔϥϕϧ༻ͷenumҾΛ͑ͯ࡞Δ ɿར༻෦ΛಡΉͱ͔ͳΓಡΈ͍͢ ɿenumΛΘ͟Θ͟ఆٛ͠ͳ͍ͱ͍͚ͳ͍ɺ໘ष͍ɺ໊લিಥ͍͢͠
ՄಡੑʹؾΛ͚ͭΔʢʣ func addSubview(_ subview: UIView, onto baseView: UIView, ifNeeded: ())
{ if !baseView.subviews.contains(where: { $0 === subview }) { baseView.addSubview(subview) } } addSubview(avatarView, onto: contentView, ifNeeded: ()) ߈ུ#ɿޙஔϥϕϧ༻ͷμϛʔҾΛ࡞Δ ɿԿՃͰఆٛ͢Δඞཁ͕ͳ͍ɺָ ɿར༻෦ΛಡΉ࣌ඍົʹͳͥ͜ͷҾͯ͠Δͷ͔Λߟ͑ͯ͠·͍ͦ͏
ՄಡੑʹؾΛ͚ͭΔʢʣ ߈ུ$ɿ࠷ॳ͔ΒޙஔϥϕϧΛ࡞Βͳ͍ ɿճΓ͘Ͳ͍ϫʔΫΞϥϯυ͕ཁΒͳ͍ ɿӳจ๏ͱͯͪ͠ΐͬͱඍົͳͷͰ͏ͪΐͬͱ໊લͷ͕ඞཁ͔ func addSubviewIfNeeded(_ subview: UIView, onto baseView:
UIView) { if !baseView.subviews.contains(where: { $0 === subview }) { baseView.addSubview(subview) } } addSubviewIfNeeded(avatarView, onto: contentView)
rܙྤ l݁ɿޙஔϥϕϧཉ͍͠ɻz
ՄಡੑʹؾΛ͚ͭΔʢʣ class SomeSequence { private var numbers: [Int] = [3,
2, 1] private var isSorted: Bool = false // ... func getSorted() -> [Int] { self.numbers = self.numbers.sorted(by: <) self.isSorted = true return self.numbers } } let sequence = SomeSequence() // Կ͔ॲཧ... let sorted = sequence.getSorted() ฒͼସ͑ΒΕͨྻΛऔΖ͏ͱͨ͠ ͚ͩͳͷʹsequenceͷঢ়ଶ͕มΘͬͨ
ՄಡੑʹؾΛ͚ͭΔʢʣ class SomeSequence { private var numbers: [Int] = [3,
2, 1] private var isSorted: Bool = false // ... @discardableResult func sort() -> [Int] { self.numbers = self.numbers.sorted(by: <) self.isSorted = true return self.numbers } } let sequence = SomeSequence() // Կ͔ॲཧ... let sorted = sequence.sort() ͜ͷϝιουΓ͕͋Δ͕ ෭࡞༻͋Δϝιουͩʂ
r୭͔ l෭࡞༻͕͋Δ͔Ͳ͏͔Λ໌ࣔ͠Α͏z
IUUQTTXJGUPSHEPDVNFOUBUJPOBQJEFTJHOHVJEFMJOFTTUSJWFGPSqVFOUVTBHF
ՄಡੑʹؾΛ͚ͭΔ w ؆ܿ͞ΑΓɺΘ͔Γ͢͞ w ޡղͷͳ͍දݱʹؾΛ͚ͭΑ͏ w ҾϥϕϧΛ͏·͘׆༻͠Α͏ w ෭࡞༻͕͋Δ͔Ͳ͏͔Λ໌ࣔ͠Α͏
クイズ:象さんを冷蔵庫に入れる手順は? 1.冷蔵庫のドアを開ける 2.象さんを冷蔵庫の中に入れる 3.冷蔵庫のドアを閉める
ࡉ͔͘நԽ
ࡉ͔͘நԽ class SomeScreen { func presentWebPage() { // ΞυϨεόʔΛ... //
ΔϘλϯΛ... // ... // จࣈྻΛ URL ʹ... // URL ͔ΒϦΫΤετΛ... // ... // จࣈίʔυΛ... // ༰ͷϨΠΞτΛ... // ... // } }
ࡉ͔͘நԽ class SomeScreen { func presentWebPage() { // ॳظ WebPage
ը໘Λ࡞Δ // ࡞ͬͨ WebPage ը໘ʹભҠ͢Δ // ભҠ͕ऴΘͬͨΒ WebPage ը໘ͰಡΈࠐΉ } }
ࡉ͔͘நԽ class SomeScreen { func presentWebPage() { let screen =
WebPageScreen() self.present(screen, completion: { screen.loadAddress("user_defined") }) } }
ࡉ͔͘நԽ class SomeScreen { // presentWebPage private func present(_ screen:
WebPageScreen, completion: () -> Void) { // ભҠॲཧʹઐ೦ } } class WebPageScreen { // ը໘ߏʹઐ೦ func loadAddress(_ address: String) { // ಡΈࠐΈॲཧʹઐ೦ } }
Λࡉ͔͘நԽ͢Δ w ͍͖ͳΓ۩ମతͳ࣮Λߟ͑ͳ͍ w ෳࡶͳͦͦߟ͑Δͷ͍͠ w ؆୯ͳͰ͋Δఔͬ͘͟ΓͳΠϝʔδ͕͍͍ w ෳࡶͳػೳ΄Ͳɺͪΐͬͱׂͣͭ͢Δ w
Ұʹߟ͑ΔΛߜΕΔ w 5%%ʹ௨͡Δߟ͑ํ w ςετॻ͖͘͢ͳΔͱ͍͏خ͍͠෭࡞༻ w ෦ͷʹઐ೦͢Δ w ඞཁʹԠͯ͡%FMFHBUF$MPTVSFʹؙ͛
҉ͳલఏΛͳ͘͢
҉ͳલఏΛͳ͘͢ class SomeContainerView: UIScrollView { var childViews: [UIView] = []
// ... func scrollToView(at index: Int) { self.contentOffset.x = self.bounds.width * CGFloat(index) } } தಡΜͰΈͨΒ ͜Ε֤childViewͷ෯͕ࣗͷ෯ͱಉ͡ ͱ͍͏લఏͰಈ͍ͯΔॲཧͩ
҉ͳલఏΛͳ͘͢ class SomeContainerView: UIScrollView { var childViews: [UIView] = []
// ... func scrollToView(at index: Int) { self.contentOffset = self.childViews[index].frame.origin } } ͍ͭͲ͜Ͱ୭ʹݺΕΑ͏ͱඞͣ ֘childView͕දࣔ͞ΕΔॲཧͰ͋Δ ʢchildViewͷϨΠΞτͱ͍͏҉ͳલఏʹ ґଘ͠ͳ͍ʣ
҉ͳલఏΛͳ͘͢ class SomeContainerView: UIScrollView { private var childViews: [UIView] =
[] // ... func scrollToChildView(at index: Int) { let childView = self.childViews[index] assert(childView.superview === self) self.contentOffset = childView.frame.origin } } Ͳ͏ͯ͠֎ͤͳ͍લఏ ඞͣ໌ࣔ͢Δ
҉ͳલఏΛͳ͘͢ w ͍ͭͲ͜Ͱ୭ʹݺΕͯಉ݁͡ՌʹͳΔΑ͏ʹ࡞Δ w Ͳ͏ͯ͠ඞཁͳલఏΛ໌ࣔ͢Δ w લఏΛҾʹͰ͖ΕҾʹ͢Δ w લఏΛҾʹͰ͖ͳ͚Ε໊લʹΈࠐΉ w
໊લʹΈࠐΉʹ͍͠߹࣮ͰΞαʔτ
4FMG%PDVNFOUJOH$PEFͷΞϓϩʔν w ՄಡੑʹؾΛ͚ͭΔ w Λࡉ͔͘நԽ w ҉ͳલఏΛͳ͘͢
͡Ό͋4FMG%PDVNFOUJOH$PEFͰॻ͍ͨϓϩάϥϜ ίϝϯτυΩϡϝϯτ͕શ͘ཁΒͳ͘ͳΔͷʁ
4FMG%PDVNFOUJOH$PEF͚ͩͰΓͳ͍ w $PEFʮ8IBUʯͱʮ)PXʯ͚͔ͩ͠આ໌Ͱ͖ͳ͍ w ϓϩάϥϜϓϩδΣΫτΛཧղ͢ΔͨΊʹ ʮ8IZʯඞཁʢΠϨΪϡϥʔͳ༷આ໌ͳͲʣ w υΩϡϝϯτίϝϯτͰ8IBUͱ)PXΛઆ໌͠ͳ ͯ͘ࡁΉΘΓʹɺ8IZͷઆ໌ʹઐ೦Ͱ͖Δ w
݁Ռͱͯ͠ඞཁՕॴϘϦϡʔϜ͕ݮΔʂ
4FMG%PDVNFOUJOH$PEFͰ ফͷগͳ͍։ൃϥΠϑΛ