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
Self-Documenting のススメ
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
580
@Environment(\.keyPath)那么好我不允许你们不知道! / atEnvironment keyPath is so good and you should know it!
lovee
0
570
ゼロから始めるPreferenceの実装 / Let's implement Preferences from scratch
lovee
0
160
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
410
個人アプリを2年ぶりにアプデしたから褒めて / I just updated my personal app, praise me!
lovee
0
790
How did I build an Open-Source SwiftUI Toast Library
lovee
1
190
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
390
Observation のあれこれ / A brief introduction about Observation
lovee
3
460
Other Decks in Programming
See All in Programming
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
Event is what happens
moro
2
1.2k
気持ちぃ〜角丸 Squircle
ryu1013
0
320
Workers Cache を知る
syumai
0
370
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
190
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
200
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
830
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
200
Web Framework Benchmark Battle 2026, Any%
a_matsuda
2
2.7k
Seven New Principles of Software Engineering
yegor256
0
190
Rでドレミ/Do-Re-Mi_with_R
florets1
0
130
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
180
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
Technical Leadership for Architectural Decision Making
baasie
3
610
Facilitating Awesome Meetings
lara
57
7.2k
Paper Plane
katiecoart
PRO
5
54k
Building Applications with DynamoDB
mza
96
7.2k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
810
The Language of Interfaces
destraynor
162
27k
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
Embracing the Ebb and Flow
colly
88
5.2k
Producing Creativity
orderedlist
PRO
348
41k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
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Ͱ ফͷগͳ͍։ൃϥΠϑΛ