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
iOS アプリエラー監視の設計とその効果
Search
Kuniwak
PRO
November 20, 2017
Programming
9k
33
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOS アプリエラー監視の設計とその効果
Kuniwak
PRO
November 20, 2017
More Decks by Kuniwak
See All by Kuniwak
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
8
3k
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
16
11k
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
40
24k
DeNA での思い出 / Memories at DeNA
orgachem
PRO
8
3.7k
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
18
4.8k
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
4
810
テストケースの名前はどうつけるべきか?
orgachem
PRO
2
1k
欠陥を早期に発見するための Software Engineer in Test とその重要性 / What is Software Engineer in Test and How they works
orgachem
PRO
22
5.1k
住宅を WebXR で評価しよう / Evaluating My Home by WebXR
orgachem
PRO
0
260
Other Decks in Programming
See All in Programming
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
250
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
330
巨大モノリシックアプリ モダン化大作戦
ktcryomm
0
1k
AIエージェント時代のコードレビューを設計する
nogu66
6
2.7k
Intent as Code
shoppingjaws
6
1k
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
210
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
170
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
620
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
200
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
110
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
120
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
390
Featured
See All Featured
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
330
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
420
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Designing for Timeless Needs
cassininazir
1
480
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.2k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
700
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.6k
New Earth Scene 8
popppiees
4
2.6k
The Spectacular Lies of Maps
axbom
PRO
1
990
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Transcript
J04ΞϓϦΤϥʔࢹͷ ઃܭͱͦͷޮՌ
"CPVUNF
,VOJXBL גࣜձࣾ%JWFSTFͷJ04ςοΫϦʔυɻ ͱ͋ΔΞϓϦͷϦχϡʔΞϧϓϩδΣΫτʹ ్த͔ΒՃΘͬͨͷͷɺςετࠔͳઃܭΛ ͷͨΓʹͨͨ͠ΊɺཪϦχϡʔΞϧΛ։࢝ɻ ࠷ऴతʹςετΛಋೖ͠ɺ։ൃΛഒʹͨ͠ɻ झຯ5%%ɻ
Τϥʔࢹͱ
w ΞϓϦͰൃੜͨ͠ΤϥʔΛαʔόʹૹΔͳͲͯ͠ ΤϥʔͷൃੜͳͲΛࢹ͢Δٕज़ w ྫ͑ɺΞϓϦ͕Ϋϥογϡͨ͠ΒϨϙʔτΛ ඈ͢ΫϥογϡϨϙʔτ͜ͷҰछ w ΫϥογϡϨϙʔτղੳαʔϏεͰ $SBTIMZUJDT͕༗໊
Τϥʔͷൃੜ66 Τϥʔͷ*% ΤϥʔͷΧςΰϦ Τϥʔൃੜͷ࣌ؒతਪҠ Τϥʔൃੜ࣌ͷσόΠε Τϥʔൃੜ࣌ͷ04
w ࣮ɺଟ͘ͷΫϥογϡϨϙʔταʔϏε ΫϥογϡҎ֎ͷΤϥʔࢹͰ͖Δ w ྫ͑ɺ8FC"1*ݺͼग़࣌͠ͷΤϥʔɺ ෦ঢ়ଶͷෆ߹ͳͲͷΤϥʔࢹͰ͖Δ ૹ৴ͷํޙͰհ͠·͢
Τϥʔࢹͷಛੑ
w ΤϥʔࢹͷಛੑҎԼͷͭɿ w ඇৗʹൣͳόάΛݕͰ͖Δ w Τϯόά͔Βൃݟ·Ͱͷ͕͍࣌ؒ
ਤղ
όάΛݟ͚ͭΔͨΊͷखஈ ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ
όά9Λݟ͚ͭΒΕΔॴ όά9 ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ
όά9 ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ্ͷํͰࢭ·Δͱ
ݪҼڀ໌ͷ͕͍࣌ؒ όά: ಛघͳΤϥʔԼͷํͰ ͔͠ݟ͚ͭΒΕͳ͍
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ Τϥʔࢹಛघͳ ΤϥʔΛݟ͚ͭΒΕΔ
΄΅࠷ޙͷࡆ όά: ͔͠͠ɺ্ͷΑΓ Τϯόά͔Βൃݟ·Ͱͷ ͕࣌ؒͱ͍ͯ
ΤϥʔࢹͰݟ͚ͭΔ͖ Τϥʔͱ
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ཧͷόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ όά͕Լͷ·Ͱ ಥ͖ൈ͚ͯ͠·͏ͷͰ ݪҼڀ໌ʹ͕͔͔࣌ؒΔ μϝͳόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ཧͷόάݕͷ࢟
ߏจϋΠϥΠτ Ϧϯτ ੩తܕݕࠪ ୯ମɾ݁߹ςετ 6*ςετ ςελʔʹΑΔಈ࡞֬ೝ Τϥʔࢹ Ϣʔβʔ͔Βͷ͓͍߹Θͤ ༧ޠλΠϙ ม໊λΠϙ
ϓϩύςΟ໊ λΠϙ ذߟྀ࿙Ε ίϯϙʔωϯτ ༷ͷෆ߹ ༷ͷޡղ ಛघͳڥͰ͔͠ ࠶ݱ͠ͳ͍Τϥʔ ҋ ΤϥʔࢹͰݕ͖͢ Τϥʔ͜ͷ͋ͨΓ
͜͜·Ͱͷ·ͱΊ w ΤϥʔࢹಛघͳόάΛ ݕ͢ΔͨΊͷखஈ w ͳ͓ɺͦͷલͷखஈͰόάΛ ݟ͚ͭΒΕΔͳΒͦͷํ͕ ݪҼڀ໌Λ͘Ͱ͖Δ
Τϥʔࢹͷ࣮ํ๏
ΤϥʔࢹαʔϏεͷ"1*ΛѲ͢Δ ΤϥʔϨϙʔλʔΛΧελϚΠζ͢Δ ΤϥʔϨϙʔλʔΛΈࠐΉ
ΤϥʔࢹαʔϏεͷ "1*ΛѲ͢Δ
Crashlytics.sharedInstance().recordError(error) $SBTIMZUJDTʹΤϥʔΛૹ৴͢Δίʔυ &SSPSͰͳ͘/4&SSPSͳͷͰҙ
ΤϥʔϨϙʔλʔΛ ΧελϚΠζ͢Δ
/4&SSPSʹม͢Δͷ ໘ͳͷͰɺ4XJGUͷ&SSPSΛ /4&SSPS͍͍ײ͡ʹ มͯ͘͠ΕΔϥούʔΛॻ͘ $SBTIMZUJDTͷ߹
class CrashlyticsErrorReporter { private let crashlytics = Crashlytics.sharedInstance() func report(error:
Error, from reporter: Any) { #if DEBUG let prefix = "DEBUG " #else let prefix = "" #endif let detailedError = NSError( domain: "\(prefix)\(type(of: reporter))", code: CrashlyticsErrorTracker.getNSErrorCode(bySwiftError: error), userInfo: [ NSLocalizedDescriptionKey: "\(error)", ] ) self.crashlytics.recordError(detailedError) } private static func getNSErrorCode(bySwiftError error: Error) -> Int { let bridgedError = error as NSError return bridgedError.code } } %(ϏϧυΛ۠ผͰ͖ΔΑ͏ʹ͓ͯ͘͠ͱ ຊ൪ڥͱ։ൃڥΛ۠ผ͘͢͠ͳΔ ΤϥʔϨϙʔλʔʹͲͷΑ͏ʹ ूܭ͞ΕΔ͔Λҙࣝ͢Δ ྫ͑ɺ$SBTIMZUJDT/4&SSPSͷ EPNBJOͱDPEFͷͰΤϥʔΛ άϧʔϐϯά͢ΔͷͰɺͦΕͧΕ Τϥʔ*%ͱൃੜݩΛࢦఆ͢Δͱ ៉ྷʹΤϥʔ͕·ͱ·Δ ΤϥʔͷશจάϧʔϐϯάʹΘͳ͍Α͏ʹ͢Δ ʢϢʔβʔ*%ͱ͔͕ೖΔͱݸผͷΤϥʔʹͳͬͯ ૯ΛѲͰ͖ͳ͘ͳΔͷͰʣ $SBTIMZUJDT༻ͷΤϥʔϨϙʔλʔΛ࡞ SFQPSUؔΛݺͿͱΤϥʔϨϙʔτ͕ ૹ৴͞ΕΔΑ͏ʹ࣮͍ͯ͠Δ ΤϥʔͱҰॹʹൃੜݩ͕ Θ͔ΔΑ͏ʹ͓ͯ͘͠ͱ ݪҼͷݟ͕͖ͭ͘͢ͳΔ
ΤϥʔϨϙʔλʔΛ ΈࠐΉ
Α͘ΈΔΈࠐΈํ๏
class UserApiRepository: UserRepositoryProtocol { private let api: GitHubApiClientProtocol func get(by
id: GitHubUser.Id) -> Promise<GitHubUser> { return self.api .fetch( endpoint: GitHubApiEndpoint(path: "/user/" + id.text), headers: [:], parameters: [] ) .then { data -> GitHubUser in let response: GitHubUserResponse = try unbox(data: data) return response.user } .catch { error in ErrorReporter.shared.report( error: error, reporter: self ) } } } Τϥʔ͕ฦ͖ͬͯͨΒ ΤϥʔϨϙʔτΛૹ৴ ʢͭ·Γϋʔυίʔυʣ "1*ݺͼग़͠ͷίʔυ
w ͔͠͠ϋʔυίʔυʹ͕ଟ͍ɿ w "1*ͷݺͼग़͠ʹؔͷͳ͍ίʔυ͕ೖΔͨΊ ୯Ұݪଇʹҧ͢Δ w ୯ମςετͰΤϥʔϨϙʔτ͕ૹΒΕͯ͠·͏ w ςετ͚࣌ͩ༗ޮͳϑϥάΛՃͯ͠ ΤϥʔϨϙʔτΛૹ৴͠ͳ͍Α͏ʹ
Ͱ͖ͳ͘ͳ͍͕Γͨ͘ͳ͍
ͦ͜Ͱ0CTFSWFSύλʔϯ
w 0CTFSWFSύλʔϯͰɺࢹऀ͕ࢹରͷ ঢ়ଶมԽΛͯ͠ಈ࡞͢Δ w ΤϥʔϨϙʔτʹԠ༻͢Δͱɿ w ࢹऀΤϥʔϨϙʔλʔ w ࢹରΤϥʔ͕ൃੜ͠͏ΔΦϒδΣΫτ w
0CTFSWFSύλʔϯΛ͑ϋʔυίʔυͷ ΛղফͰ͖Δ
Τϥʔͷൃੜݯ Τϥʔ͕ൃੜ͠·ͨ͠ ΤϥʔϨϙʔλʔ ࢹ
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ࢹ Τϥʔ͕ى͖ͨͷͰ ΤϥʔϨϙʔτΛ ૹ৴͠·͢
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ΤϥʔϨϙʔτૹ৴ ͷ Τϥʔ͕ى͜Γ͏Δ ॲཧͷ
Τϥʔͷൃੜݯ ΤϥʔϨϙʔλʔ ςετͷͱ͖ ΤϥʔϨϙʔλʔ ΛऔΓ͚ͳ͍
w ͨͩ͠ɺ0CTFSWFSύλʔϯΛ͑Δॴ ݶΒΕ͍ͯΔ w ࢹର͕ࢹՄೳͳΠϯλʔϑΣʔεΛ උ͍͑ͯͳ͍ͱ͍͚ͳ͍ͨΊ w .7 ΞʔΩςΫνϟͳΒɺ.PEFMࢹՄೳͳ ΠϯλʔϑΣʔεΛ͍࣋ͬͯΔͣͳͷͰɺ.PEFMʹ
ΤϥʔϨϙʔλʔΛΈࠐΈ͍ͣ͢ w 'MVYΞʔΩςΫνϟͷ߹4UPSF͕ࢹՄೳͳ ΠϯλʔϑΣʔεΛ͍࣋ͬͯΔͣ
.PEFM 7JFX &SSPS3FQPSUFS ࢹ ࢹ Τϥʔ͕ൃੜ͠·ͨ͠
.PEFM 7JFX &SSPS3FQPSUFS ࢹ ࢹ ΤϥʔΛදࣔ͠·͢ ΤϥʔϨϙʔτΛ ૹ৴͠·͢
func fetch() { switch self.currentState { case .fetching: return case
.fetched: self.stateMachine.transit(to: .fetching) self.repository.get(by: self.id) .then { user in self.stateMachine.transit(to: .fetched( result: .success(user) )) } .catch { error in self.stateMachine.transit(to: .fetched( result: .failure(.unspecified(debugInfo: "\(error) )) } } } ͜ͷ.PEFM"1*ݺͼग़͕͠Τϥʔʹ ͳͬͨΒΤϥʔঢ়ଶมԽ͢Δ ͦͷͨΊɺΤϥʔϨϙʔλʔ͔Βࢹ͍͢͠ .PEFMͷ"1*ݺͼग़͠ͷίʔυ ͜ͷΑ͏ͳ.PEFMͷઃܭͷৄࡉIUUQTHPPHM1G'+-Λࢀর͍ͯͩ͘͠͞
class UserModelErrorReporter { private let model: UserModelProtocol private let errorReporter:
ErrorReporterProtocol private let disposeBag = RxSwift.DisposeBag() init( observing model: UserModelProtocol, reportingBy errorReporter: ErrorReporterProtocol ) { self.model = model self.errorReporter = errorReporter self.model.didChange .subscribe(onNext: { [weak self] (state: UserModelState) in guard let `self` = self else { return } switch state { case let .fetched(result: .failure(error)): self.errorReporter.report(error: error, reporter: self) default: return } }) .disposed(by: disposeBag) } } .PEFM͕Τϥʔঢ়ଶʹͳͬͨΒ ΤϥʔϨϙʔτΛૹ৴ .PEFMͷঢ়ଶભҠΛࢹ .PEFMΛࢹ͢ΔΤϥʔϨϙʔλʔΛ࡞
͜͜·Ͱͷ·ͱΊ w Τϥʔࢹͷ࣮ํ๏ʹ 0CTFSWFSύλʔϯ͕ద͍ͯ͠Δ w .PEFM4UPSFΛࢹ͢ΔͱΑ͍
Τϥʔࢹͷίπ
ΤϥʔࢹΛ։࢝͢Δͱ ࠔౕ͕ͬͨͪΐͪ͘ΐ͘ग़ͯ͘Δ
Fatal Exception: SomethingError *** nil ใྔ͕΄ͱΜͲͳ͍ʂ
ΤϥʔʹͳΔ͘ ΫϦςΟΧϧͳใΛ٧ΊΑ͏
func example(input: String) -> String? { guard validate1(input) else {
return nil } guard validate2(input) else { return nil } guard validate3(input) else { return nil } return "OK! Hello \(input)" } ݪҼڀ໌Λ͘͢Δѱ͍ྫ ࣦഊͨ͠ݪҼ͕۠ผͰ͖ͳ͍
enum ExampleError: Error { case validate1(debugInfo: String) case validate2(debugInfo: String)
case validate3(debugInfo: String) } ͦ͏͍͏࣌FOVNͰΤϥʔΛ۠ผͰ͖ΔΑ͏ʹ͢Δ
func example(input: String) -> Result<String> { guard validate1(input) else {
return .failure(.validate1(debugInfo: input)) } guard validate2(input) else { return .failure(.validate2(debugInfo: input)) } guard validate3(input) else { return .failure(.validate3(debugInfo: input)) } return .success("OK! Hello \(input)") } ΤϥʔΛ۠ผ͍͢͠Α͍ྫ ࣦഊͨ͠ݪҼ͕۠ผͰ͖Δ ࣦഊͨ͠ࡍͷೖྗೖखͰ͖Δ
Τϥʔࢹͷ݁Ռ
w ϢʔβʔͷखݩͰൃੜ͍ͯ͠Δόάͷछྨ نΛѲͰ͖ΔΑ͏ʹͳͬͨ w छྨن͕ѲͰ͖ΔΑ͏ʹͳΔͱɺόάमਖ਼ͷ τϦΞʔδΛΓ͘͢ͳΔ w ՝ۚܥ࠷༏ઌͱ͔ɺΤϥʔͷଟ͍ͷ ͔ΒରॲͳͲ
w ϢʔβʔͷखݩͰ༧֎ͷΤϥʔ͕ى͍ͬͯͨ͜ w ςελʔʹΑΔಈ࡞֬ೝͱڥ͕ ҟͳ͍ͬͯͨͨΊɺൃݟͰ͖ͳ͔ͬͨΑ͏ͩ w ໘ന͍͜ͱʹɺ"QQMFͷϨϏϡʔΞ͕ૺ۰ͨ͠ όάͷݪҼڀ໌ʹཱͬͨ w 4BOECPYͷϨγʔτ͡Όͳ͍ͱ࠶ݱ͠ͳ͍
όάͩͬͨ
w خ͍͠෭࡞༻ͱͯ͠ɺςελʔͷૺ۰ͨ͠όάͷ ৄࡉ͕ೖखͰ͖ΔΑ͏ʹͳͬͨ w ςελʔͷಈ࡞֬ೝதʹΤϥʔϨϙʔτ͕ ඈΜͰ͘ΔͨΊʢ%(ϏϧυͳͷͰ͙͢Θ͔Δʣ w σόοά͕͍͢͝ḿΓ·͢
·ͱΊ w ΤϥʔࢹʹΑΓɺςελʔʹΑΔಈ࡞֬ೝͰ ݟ͚ͭΒΕͳ͔ͬͨΤϥʔΛൃݟͰ͖ΔΑ͏ʹ ͳͬͨ w ઃܭͷίπҎԼͷͭɿ w 0CTFSWFSύλʔϯΛ͏ w
ͳΔ͘ΤϥʔใΛΘ͔Γ͘͢͢Δ
એ w %JWFSTFͰ৽نࣄۀͷJ04։ൃνʔϜͷ νʔϜϦʔμʔΛืू͍ͯ͠·͢ʂ w தͷαʔϏεΛࣗͷྗͰಋ͍ͯΈ͍ͨͱ ࢥ͏ํʹɺͥͻ͖ͯ΄͍͠ͱࢥ͍ͬͯ·͢ʂ w ͝ڵຯ͕͋Γ·ͨ͠ΒɺҰॹʹϥϯνʹ ߦ͖·ͤΜ͔ʁ