Guild icon
swift-developers-japan
main / ui-ux
Avatar
omochimetaru 6/16/2017 3:41 AM
applideveloper - 昨日 午後10時43分
‪アプリとWebが同じ機能をもっていて、万が一アプリで、ViewControllerが初期化できないとき開発ではfaitalError or nilでもいいが、本番ではnilで返して、遷移するコードでユーザーに遷移できません、その機能は現在使えませんでしたって伝えて戻るか、同じWebのページが表示できればバグ修正するまでWebを表示するのがいいんじゃないかと思うのですが、皆さんどうしてます?
3:42 AM
これってもう仕様の問題だと思うんですけど
3:43 AM
「万が一」のケースにややこしいフローをつけたすと
3:43 AM
それが活躍する時がもたらしてくれる利益よりも、以後のバージョンでそのロジックを動作チェックしていく保守コストの方が高くつきそうなので
3:43 AM
やらないほうがよさそう
Avatar
applideveloper 6/16/2017 4:38 AM
全部落とすとユーザーがもう一度アプリを開かない限りCrashlysticsにエラーが送られないので、障害検知できない気がするのですよ
Avatar
omochimetaru 6/16/2017 4:40 AM
Crashlysticsは使ったことがないのでわからないですが、
4:40 AM
ログを飛ばすためだけの制御はがんばる価値があると思います。
Avatar
‪アプリとWebが同じ機能をもっていて
ディープリンク見たいな構成のサービスがあるってことなんですかね?
Avatar
omochimetaru 6/16/2017 4:41 AM
(でも、なんか頑張らないとログが飛ばないなら、それ入れる意味がよくわかんないですが
Avatar
Crashlysticsってエラーログ送れませんでしたっけ
4:43 AM
Rxでerrorったら送るような仕組みできた気がする
Avatar
そもそも論でいうと、未実装部分にユーザがアクセス可能な事自体がダメな気がする
Avatar
omochimetaru 6/16/2017 4:44 AM
あ、そういう意味か、そもそも誤読していた
4:44 AM
万が一アプリで、ViewControllerが初期化できないとき開発ではfaitalError or nilでもいいが、本番ではnilで返して、遷移するコードでユーザーに遷移できません、その機能は現在使えませんでしたって伝えて戻るか、
開発でfatalErrorで良いってことからバグだと思ってたけど
4:44 AM
やるんだったら開発でも遷移させて、それを正規挙動として設計するのが良いのでは?
Avatar
failSafeどうするかって話かと思ってました
Avatar
omochimetaru 6/16/2017 4:45 AM
failSafeどうするかって話かと思ってました
同じく。
4:45 AM
そうじゃなくて、本当に未実装なだけな話か
Avatar
fail caseの話なのか?
Avatar
omochimetaru 6/16/2017 4:46 AM
どっちだろw
Avatar
webに飛ばす場合だとそれぞれアプリ・Webごとのルーティング定義を管理する必要があったり、バージョン互換もそうだし、ルーティング用のAPIいるんじゃないの、とか (edited)
4:47 AM
考えることが多そう (edited)
Avatar
万が一がどのくらい万が一なのか気になる (edited)
4:48 AM
APIとかDBのバージョンで死亡、みたいなのはError流してダイアログを表示するだけ、未来の俺出ないように頑張ってねって感じ
Avatar
Error流してダイアログを表示するだけ
自分もこっち派かなあ...確率としてどれくらい起きるのかにもよるとは思いますがあくまで異常系だしというのも
Avatar
中性子ビームで死亡、みたいなのはどうせ再起不能なんで無視するとして
4:51 AM
API、DBのバージョン違いに関して、というか基本的に開発者の責任で出てしまう再起不能系は、ダイアログに表示がベネかな、理想ではfatalErrorなんだろうけど
4:52 AM
未来永劫俺がメンテ出来るわけではない
Avatar
omochimetaru 6/16/2017 4:53 AM
まあダイアログ表示ぐらいならそんなにコストかからないし良さそう
Avatar
テスト書いてカバレッジ100%にしてfatalErrorは理想形
Avatar
中性子ビームで死亡
こんなの防げたらui/uxを超えた何かではww
Avatar
omochimetaru 6/16/2017 4:54 AM
あーでもfatalErrorだとフロー解析がneverだから
Avatar
そのためのoptional/force updateの仕組み入れるの大事だとは思ったり
Avatar
omochimetaru 6/16/2017 4:54 AM
その先の型制御にも影響アンのか
Avatar
それはそう
4:54 AM
throw Errorを許容するか、エラーは起きないという強い意志を表明するか
Avatar
omochimetaru 6/16/2017 4:54 AM
じゃあfatalErrorにできるならそのほうがいいね
Avatar
try! も一緒だけどね
Avatar
omochimetaru 6/16/2017 4:54 AM
ああ、うん
4:55 AM
なんか結局はそのアプリにとっての
4:55 AM
収益採算で
4:55 AM
どのくらいコンサバにコーディングコストをかけるかって気がする (edited)
4:56 AM
もちろん言語仕様として、エラーハンドリング側に倒すのも、クラッシュ側に倒すのも、ミスしにくく簡潔に書けるっていう進化自体は
4:57 AM
どっちのアプローチにとっても利益があるからやったらいいけど
Avatar
中性子ビーム防ぐためには、3並列で同じプログラムを横展開して、メモリマップに差異が出たら多数決によって修正する、とかかなw(あまり詳しくない)
Avatar
omochimetaru 6/16/2017 4:57 AM
最終的にどっちにするかは案件次第
Avatar
起きない、起きてはいけないエラーとどう付き合うかは結構揺れる
4:58 AM
プロジェクトのメンバーと相談かな
Avatar
omochimetaru 6/16/2017 4:58 AM
@tarunon struct Dual<T> { var value: T ; var check_value: T }
4:58 AM
全部コレであつかって全てのアクセスで == チェックしよう
4:58 AM
異なってたら例外を投げるんだ
Avatar
値2つだと、多数決による修正ができない
Avatar
omochimetaru 6/16/2017 4:59 AM
修正はしなくていいんじゃね
Avatar
3つで自動的に回復するように仕様
Avatar
omochimetaru 6/16/2017 4:59 AM
中性子があたりましたっていうダイアログが出ればいい
Avatar
中性子があたりましたダイアログ強すぎるwww
Avatar
omochimetaru 6/16/2017 4:59 AM
中性子の当たらないシェルターに移動して再度起動してください
Avatar
訂正できる符号形式にすればいいのでは?
Avatar
omochimetaru 6/16/2017 5:00 AM
確かに符号理論的にやるのが賢いのか
Avatar
符号化して実行するのしんどそう
5:03 AM
なんか圧縮されたテキストを検索する、みたいな研究があったな
5:04 AM
それ系のアーキテクチャが必要っぽい
Avatar
完全に訂正符号の話だけど ECC メモリにしたらよいのでは
5:05 AM
ソフトウェア的にやりたい話か…
Avatar
applideveloper 6/16/2017 6:14 AM
クラッシュする直前にログを送るとか自ら落とす場合以外は送れないのでは?端末ならアプリじゃないので Appleはできそう (edited)
Avatar
前提条件固めたほうがいいかもです
  • クラッシュ直前にログを送りたいのか
  • 画面遷移が正常にできない場合の対策を考えたいのか
  • ある異常系のケースのみログを送りたいのか
その上でfatalErrorでクラッシュさせるかさせないかは、前提が固まった先の話になるのかなと
Avatar
fatalError を使うのが適切かと、 Swift が fatalError を含む Universal Error をハンドリングする方法を提供していないことは切り分けて考えた方がいいと思います。
7:02 AM
たとえ fatalError だけ代わりの方法で対処できたとしても、その他の Universal Error (メモリが足りないとかスタックオーバーフローとか)は起こりうるので、結局それらが発生したっ場合のログは送れないですし。
7:04 AM
Swift could support a secondary, untyped propagation mechanism using "zero-cost" exceptions. ... However, this work is outside of the scope of Swift 2.0. https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#universal-errors とあり、将来的にサポートされる可能性もあるかと。
swift - The Swift Programming Language
7:05 AM
その場合でも、 do - try - catch 以外のメカニズムがいいと思いますが。
Avatar
omochimetaru 6/16/2017 7:05 AM
将来的にサポートされる可能性もあるかと
あれ、その場合って
7:05 AM
検査例外vs非検査例外の
7:05 AM
再来?
Avatar
非検査例外が悪いわけじゃなくて、非検査例外と検査例外を同じ仕組みでハンドリングさせたことと、 ExceptionRuntimeException のスーパークラスにしてしまったこと( Logic Failure を Recoverabble Error の下位においてしまったこと)、構文がイケてなかったことあたりが相互に影響して使い勝手が悪くなってしまったと思ってます。
7:11 AM
Java であっても Exception, Error, RuntimeException がそれぞれ Recoverable Error, Universal Error, Logic Failure の意味合いで適切に使い分けられてたら問題がないはず。 (edited)
Avatar
omochimetaru 6/16/2017 7:11 AM
あーたしかに
7:11 AM
チャンネル変えます
Avatar
多分Swiftの書き方的にどうかという話と、サービス的な運用の話とで混ざってる気がします...
7:16 AM
致命的に落として欲しいときにクラッシュさせるのは当然だとしても、例えば個別のデータにアクセスしてNot foundだったから落とすのとは温度感違いますよね
Avatar
Not Found だったら落としたいかどうかは厳密には要件次第だと思いますが、一般的には落としたくないケースが多いと思います。そういう場合は Recoverable Error や Simple Domain Error にしてハンドリングすれば良いと思います。
Avatar
一般的には落としたくないケースが多いと思います。そういう場合は Recoverable Error や Simple Domain Error にしてハンドリングすれば良いと思います
という選択肢があるよねっていうのと、fatalErrorを使うべきって話が混ざってるんじゃないかって話でした
Avatar
僕のコメントは fatalError とログにどう折り合いをつけるかについてでした。 一般的に Universal Error ( fatalError 含む)はハンドリングされることを想定しないエラーですが、とはいえログを取りたいというような用途ではハンドリングして処理を挟み込みたかったりします。ですが、 Swift にはその言語機能がないので今はできません。しかし、それを回避するために、本来 fatalError である場所を Recoverabble Error 等にしてもコードが複雑化してしまいます。たとえば、一番ルートで全部まとめてハンドリングしてログをとろうとしたら、そのスタックトレース上のすべての関数が throws でないといけなくなります。 結局、そこまでしてもそれで対処できる Universal Error は一部であり、ログをとれない Universal Error は他にもあるので、それだったら設計的にキレイな方に倒しておいて、本当に必要な箇所だけハンドリングできるようにするのが良いバランスかなと思います。 ということが「fatalError を使うのが適切かと、 Swift が fatalError を含む Universal Error をハンドリングする方法を提供していないことは切り分けて考えた方がいいと思います。」で言いたかったことです。
Avatar
なるほど、詳細にありがとうございます 自分はどちらかといえば、最初の例にあがってた本来遷移できなかった画面においてどういう対応を入れるべきかって視点で話をしてました fatalError自体がかなりサービス視点で言えば、これ以上動かしていてリスクになるかどうかっていう点でしか使う場面はない道具だと思っていて(開発時は別として) その上でエラーハンドリングどうするか、という話ですがthrowsしたからといってUIレイヤーでそこを完全にコントロールすべきかって話はあると思います そもそもfatalError自体が処理フロー的にエラーを扱うタイミングどうこう無視してクラッシュさせる訳で、それつまり処理フロー的に管轄のレイヤーで、処理の結果が圧倒的にまずいかってその場で分かりそうなものなんですよね それ踏まえた上でfatalErrorを使うところで使えばいいと思いますし、UI上で全部のエラーをハンドリングする必要な場面って稀だと思うのですよね、そこまでthrowsされてくるかどうかも設計的な話になりそうですが
7:46 AM
そしてログ送る話で言えばログ基盤あるなら、貯蓄する仕組みを設けてバルクで送るなりでtimestampとっとけば別にその瞬間を知る必要はないんじゃないかと、エラーログ貯めてからfatalErrorすればいいような気も、仕組みでどうにでもなる話じゃないですかね
Avatar
たしかに、エラー時のアラート→誘導まで作るほどじゃないから fatalError にしたいけど、万が一到達したときにはログだけはとっておきたいという話なら、 @moaible さんの言うようなログを貯めておく方法が良さそうですね。
7:51 AM
もしくは、ログ送ってから fatalError するか。
Avatar
applideveloper 6/16/2017 7:57 AM
売上を毀損したくない場合、バグを直すまで落とすのではなくWebに飛ばしてバグ検知してしのいで、バグ修正したら元に戻すイメージです。 落としてしまったらユーザーがもう一度開いてくれるかわからないですし、ひどいレビュー書いて別のサービス使われる可能性だってあります (edited)
Avatar
webに飛ばす場合だとそれぞれアプリ・Webごとのルーティング定義を管理する必要があったり、バージョン互換もそうだし、ルーティング用のAPIいるんじゃないの、とか 考えることが多そう
Avatar
落とすのが悪いかどうかは一般論では決められないと思います。それが起こりうる確率と、落ちたことによって想定される損害、落とさないようにすることによってコードのシンプルさが毀損されてしまい、別のバグを埋め込んでしまうリスク、メンテコストの増大など、総合的に考えてメリット・デメリットをケースバイケースで比較検討し、良い方を取ることにしかならないかと。
Avatar
最初からその仕組みがあるならいいですが、すでにリリースされたものに仕組みを突っ込むとなると下位互換どうするとか諸々問題が出てきそうです そのための強制アップデートである程度のユーザー離脱覚悟でその仕組みを導入して運用コストを下げるとかは選択肢としてもありそうですが (edited)
8:07 AM
あとは画面数増えた時それ、アプリもWebも一気に対応できるの?っていうのはあるかなと
Avatar
applideveloper 6/16/2017 10:27 AM
Webのトップページ、お問い合わせページに飛ばすだけでも違う気がするんですよね、ロジックも複雑にならないし、コードをキレイにするために404ページを見せずに落とす売上毀損に繋げるのはのは無責任だと思うんですよね fatalErrorで落とすなら、その前に原因エラーをサーバに送って、ユーザーを逃さないようにサポートするWebページに飛ばしてからfatalErrorした方が売上毀損を防げるのではないでしょうか?
Avatar
「万が一アプリで、ViewControllerが初期化できないとき」の「万が一」次第じゃないでしょうか。それが許容できない頻度で起こるのかによると思います。許容できないなら飛ばす必要があるでしょうし、許容できないならログだけ送って fatalError でいいと思います。
10:34 AM
「万が一」をどんなときでもケアしないといけないとすると、 Forced Unwrapping も Arraysubscript も使うなって話になっちゃいますし。
Avatar
extensionでsafetyにアクセスするようにしちゃってますね..
10:37 AM
あとアプリ殺すくらいなら、アプリ内WebView開いちゃえばいいんじゃないですかね
10:37 AM
わざわざ離脱する原因作らなくても
Avatar
そもそもその頻度で起きるのは万が一ではないw
Avatar
まあ確かにw
Avatar
applideveloper 6/16/2017 10:52 AM
fatalErrorするぐらいならnil返したい
Avatar
単に触っててオフラインだとかの異常系ならfatalErrorはやり過ぎですし、かといって連動してるWebアプリの同じコンテンツのページに飛ばすとそれはそれでその後の運用が大変ですし 結局コケたからWebに飛ばしたとしてオフラインだとそこでもコケるからそれはそれでユーザーストレスになりそうな
10:56 AM
ダイアログの選択肢として飛ばすとかが落とし所ではないですかねー🤔
Avatar
applideveloper 6/16/2017 10:58 AM
アプリもサービス全体を使ってリアクティブシステムにしたいのですよ http://www.reactivemanifesto.org/ja (edited)
Avatar
その障害耐性をどう表すかって話ですよね
Avatar
なんか話が噛み合ってない感じがする
10:59 AM
@applideveloper さんの主張自体には反対してる人は居なくて
11:00 AM
そうやったほうが損失が少ない、それはそうで
11:01 AM
ただ、荒木さんのいう「万が一」が
11:01 AM
わりとみんなのいう「万が一」と比べると
11:01 AM
「時々発生する」の意味になっていて
11:02 AM
みんなは「発生しないとみなせる」の意味で言ってるから
11:02 AM
噛み合ってないようにみえます。
Avatar
(荒木さん、、誰だろう)
Avatar
applideveloper 6/16/2017 11:03 AM
僕です
👌 2
Avatar
なるほど🙏
Avatar
applideveloper 6/16/2017 11:03 AM
障害が起きた時は404ページを出したりWebで救済したいんですが、単純に落ちたら、ユーザーがもう一回開かないとなんで落ちたかわからないんですよ、なんで落ちたかもサーバーに送って知りたい (edited)
Avatar
荒木さんの話し方を見ていると、予想だけど、 もうそのエラー自体は現場でちょこちょこ起きてるのでは。
11:04 AM
だから、「万が一にしか起こらないものはfatalErrorでよい」話をしていると噛み合わん
Avatar
サーバーサイドのエラーって、端末オフラインと同レベルでダイアログで処理するのが一般的な気がする
Avatar
applideveloper 6/16/2017 11:06 AM
どういう時にみなさんfatalErrorって書いてますか?使い所がわからなくて、僕は書きたくない派です (edited)
Avatar
DBのファイル生成できなかったとか、その関数内で絶対的にこの値は存在するはずなのにしない時ときとか、このまま操作されると困るような場合に書いてます
Avatar
applideveloper 6/16/2017 11:12 AM
その場合、単純に落とす前に、サーバーにエラーを送って、復旧するまでWebに飛ばすのってありだと思うんです。アプリと、WebのDBは別のことが多いので、アプリって申請に時間がかかるので復旧に時間がかかるので、それまでWebでしのいで売り上げ毀損したくない (edited)
Avatar
多分そこは要件次第の部分かもしれんです
Avatar
UIKitに依存してしまうのが嫌だなあ
11:14 AM
やるならモジュール側でfatalErrorHandlerみたいなプロパティを開けるとか・・・
Avatar
UIKitに依存ってWebViewの部分?
Avatar
内部ウェビューで出すなら、UIViewControllerを引数に受けてることになるし
11:16 AM
openURLならUIApplication.mainだから
11:16 AM
そのファイルにimport UIKitって書くことになる
11:16 AM
アプリ寄りなロジックならそれでいいけど
Avatar
applideveloper 6/16/2017 11:16 AM
アプリだと、エラーに巻込まれるので、別アプリのSafariに飛ばすとかもありだと思うんです。 (edited)
Avatar
fatalErrorが出てくるのって、もっと
11:17 AM
ローレベルなレイヤーで
11:17 AM
出てくることが多いと思うので。
11:17 AM
ライブラリというか運搬性の高いコードに保ってそう
11:17 AM
さっきのDBの例とかそうじゃないですか?
Avatar
めったに使わないですよね
Avatar
最近やったのだと
11:21 AM
FilePath型ってのを作っていて
11:21 AM
相対パスか絶対パスかをenumで内部でもたせてあるんだけど
11:21 AM
Append(add: FilePath)
11:22 AM
メソッドが
11:22 AM
引数に絶対パスを受けたらfatalErrorにした。
Avatar
確かにそれは落ちてほしい
Avatar
applideveloper 6/16/2017 11:22 AM
開発ではいいと思うんですよ
11:23 AM
本番は、サーバーにエラーを送って、Webに飛ばしてもいいのでは思う、アプリのpathと、Webのpathのロジックは違うから生きているかもしれない (edited)
Avatar
こういうのはほぼソースコードロジックだけで保証できるから
11:23 AM
例外を飛ばす仕様にしちゃって使いにくくなるコストの方が高い
Avatar
全部optionalで握りつぶされる辛さ
Avatar
例えば単純な Int通しのx + yって式でも
11:26 AM
21億をはみ出せばクラッシュするわけですが
11:26 AM
例外を投げる版のfunc add() throwsでも
11:26 AM
作りますか?って話になってきます
Avatar
applideveloper 6/16/2017 11:27 AM
?のoptionalで、握りつぶすのもObjective-Cと品質が変わらないので、アンラップして、場合分けしてバグ検知すべきだと思うんですよね (edited)
11:28 AM
null安全な言語のSwift, Kotlinを使えば、 リプレイス前より、安全安心になります! ( ̄ー ̄) ドヤッ! ---

本当に?

--- 前提条件 仕様がアプリによって違うため ここでは、文字列fooがni...
Avatar
そこはトレードオフな気がする だから開発中にバグを見つけたいから!、fatalError使うのであって、ロジックの質の担保が完全かどうかは人間が介入する以上完璧なパターンはないのでは
11:32 AM
俗に言う仕様バグなわけですが
Avatar
applideveloper 6/16/2017 11:32 AM
問題は、?で、バグ検知してなくて、バグに気づかないままバグを出し続けたり、fatalErrorで強制終了して、ユーザーがもう一度開いてくれなくて、Crashlysticsに送られなくて、バグに気づかない件です、本番じゃなく開発では、fatalErrorを書いていいと思います。 (edited)
Avatar
例えば
11:33 AM
x * xっていうFloatの掛け算があって
11:33 AM
これは絶対、負にはならないわけですけど
11:34 AM
数学の知識がなかったら
11:34 AM
次の行で符号チェックのif文が必要になる
11:34 AM
知識があれば、ここは負にはならない、と仮定してそのまま続きを書ける
11:35 AM
ロジックの担保ってそういう話で
11:36 AM
論理的に絶対に無いってところでfatalErrorを使ってよくて
11:36 AM
でも、見落としてしまうケースではそこに突っ込んで落ちちゃうので
11:36 AM
開発中に洗い出しましょう、となる
11:37 AM
これはいくらでも突き詰めることができて
11:37 AM
結局、コードを書くメンバーの
11:37 AM
実力をどこまで信じるか、みたいなことに
11:37 AM
なっちゃうのではないかなあ
Avatar
TDD良さあります
11:40 AM
あんまり心配なら開発時だけ落ちるfatalError書くといいかとしれないですね
Avatar
@moaible それはダメなんですよ
11:40 AM
フロー解析の関係で
Avatar
な、なんやて
Avatar
たとえば・・・
11:41 AM
let a: Int if (cond) { fatalError("illegal") } else { a = 3 } showValue(a) (edited)
11:41 AM
こういうコードの場合、showValueの行でaが初期化ずみであることがフロー的に保証されるけど
11:42 AM
もし、「リリース時は落ちないfatalError」であれば、
11:42 AM
あ、これおかしいな
11:42 AM
えーっと・・・
11:42 AM
こうだ。
11:42 AM
condが真になったばあいに、aが未初期化のままshowValueの行に到達する可能性があるんで
11:42 AM
コンパイルできないです
Avatar
-> Never なログを送る関数を作るとか。
Avatar
あー、チラッと考えただけでやってなかったけどダメなんか(´・_・`)
Avatar
@norio_nomura それならいけますね
11:45 AM
それも落ちるのは変わらないですけど。
Avatar
applideveloper 6/16/2017 11:45 AM
人間ミスをするんで障害をなくすことはできないですが、障害を前提としたアーキテクチャ設計はできると思うのです。 (edited)
Avatar
うーんでも例えば、そうやって
11:46 AM
「アプリプロセスが落ちない」事を達成したとして
11:46 AM
「ユーザのローカルデータが消えない」とか
11:46 AM
もっとクリティカルな障害が起こる可能性は結局残るしなあ
Avatar
applideveloper 6/16/2017 11:47 AM
ちゃんと書けば両方実現できると思うんですね
Avatar
それはそうだと思いますよ
11:47 AM
ただ現状のSwiftではどうしても
11:47 AM
コーディングにかかる時間が
11:47 AM
増えてしまう。
11:48 AM
アプリがクラッシュしたら銃殺される国だったら
11:48 AM
僕もそういう書き方をすると思うんですけど
11:48 AM
案件にかけるコストには一般に限界があるんで
Avatar
applideveloper 6/16/2017 11:48 AM
別にアプリはクラッシュしてもいいんですが、復旧するまでWebに送って救済してもいいのではと思うのです。 (edited)
Avatar
1%のクラッシュは諦めるとか、0.1%は諦める、みたいな限界をどこかで引く必要が出てきます
11:50 AM
fatalErrorの代わりに safariを開くクラッシュ関数を使うのは良さそうですね
11:50 AM
あんまりコーディング上の負担を増やさずに実現できる
11:52 AM
内部ブラウザとかダイアログの系はアプリのプロセスが落ちたら消えちゃうんで、どうしても、例外制御にしてアプリのメインループまで戻す必要が出てきますね
11:53 AM
その、「クラッシュレポート用のWebView」が表示されているときだけ、WebViewの周囲のボタンを特定の手順で操作すると、データが完全に壊れるバグ
11:53 AM
みたいな、二次被害フローが産まれそうで嫌だなあ
11:53 AM
そもそもが異常系でしか突入しない画面ゆえにバグ出しが甘くなりがちなのが怖い
Avatar
欠損をどう解決するかは肝ですね
Avatar
例外掴んで動作続けてるってことは他のデータモデルの一貫性も何かしらおかしくなってそうだし。
Avatar
applideveloper 6/16/2017 11:56 AM
こういうアプリの障害を前提としたアーキテクチャとUI設計を相談したいです。 (edited)
Avatar
なるほど
Avatar
applideveloper 6/16/2017 12:05 PM
人間だから、ミスルノで、障害になって、治るまで徹夜より、復旧するまで、WEBに飛ばすか、復旧するまで使えませんと言って、売り上げ既存せずに、慌てずテストして復旧させることができると思うんですよ (edited)
Avatar
それって、アプリがそもそも、何かしらのウェブサービスの、ネイティブアプリ版だからってことですよね?
12:08 PM
ある意味、二重スタンバイ状態にして、障害発生時にバックアップ系統に流してる事と同じですよね
Avatar
アプリでなくて UIKit と独立したライブラリで fatalError したいようなケースはどうするんでしょうか?
Avatar
applideveloper 6/16/2017 12:08 PM
そうですね、他に、お問い合わせページにも飛ばせば、詳細なバグレポートももらえるし、レビューに悪い書き込みをされなくて済むのでは (edited)
Avatar
ああ、お問い合わせページとかも想定しているのか
Avatar
僕は switch で網羅性を満たしてないけどフロー的に絶対に到達しないときとか fatalError にしますね。
Avatar
@koher その、「フロー的に絶対に到達しない」事自体は、人間が論理的に考えて結論してるわけですよね
Avatar
で、それがアプリなら fatalError の代わりに Web ページ開く関数作ってもいいですが、 UI と独立したモジュールの中ではそんなことはできなくて
Avatar
僕はその「論理的に考えて」の部分で、寝ぼけてたり酔っ払ってたりするかもしれないから、結局テストでどこまで洗い出せるかという課題は残るのではないかと思う
12:12 PM
あとそこで、「おっちょこちょいな人」と「精密な考慮が得意な人」という人間力の差も出てくるとは思う。
Avatar
それを fatalError の代わりに外部からハンドリングできるようにしようとしたら throws 付けたりしないといけなくなっちゃう。
Avatar
applideveloper 6/16/2017 12:12 PM
完全な網羅するテストをできるテスターとかテストエンジニアとかいる体力のある企業とか少なそう。それでも障害が起きるので 人力テスト、テストコードも人間なので、網羅ミスとかありますし (edited)
Avatar
QA部隊があるところにいましたけど、それでもバグは起きますし、テスト網羅できたプロダクトでもクラッシュフリー99.8%だったりするので、結局はどこまで確率を減らせるかってことに帰結するんじゃないかなあ...
Avatar
寝ぼけてたり酔っ払ってたりするかも
これはあり得るからアプリなら代わりのページ開くでもいいけど、 UI と独立したモジュールではそんなことはできない。
Avatar
applideveloper 6/16/2017 12:15 PM
障害をなくすことはできないので、障害を前提としたアーキテクチャ設計を考えて、障害にどう対処するかを設計する必要があると思うのです。 (edited)
Avatar
@koher fatalErrorを呼び出す前に、事前に登録しておいたクロージャを呼び出すような関数を作っておくと、一応対応できます
Avatar
よくいうリアクティブって死んでも大丈夫にするって話なので、残機が1しかないアプリに対してそれを求めても厳しいと思うんですよね
Avatar
applideveloper 6/16/2017 12:17 PM
死んだらリソースを消費するので、404などを高レスポンスに返しましょうって感じですね (edited)
Avatar
その死んだら、をフックするのはどこですか
Avatar
@omochimetaru ライブラリには必ず fatalError 互換のグローバル変数作っておいてそれに差し込む?
Avatar
@koher グローバルなのか、ライブラリの中に特定のクラスがあるなら、そのプロパティなのかはどっちでもありえるかと
Avatar
プロセス1個で粘るのと、複数プロセスで補填し合うのは全然違うから一筋にreactiveといっても意味が変わってきます
Avatar
var logger: ((String) -> Void)? プロパティがあって、セットしておくとverboseなログが取れるライブラリ設計とかはたまにみる
12:20 PM
@moaible Swiftの場合、fatalError系は完全に封印して、throwsだけでそういう世界をエミュレートする必要が出てきますよね
Avatar
サーバーだと Let it crash できるけど、アプリだと回復させる主体がいないんですよねこの話
Avatar
@omochimetaru ですね、そして外部のライブラリを1つでも入れてたら完璧性は破綻するので0から全てその仕組みを入れた状態で組み直す必要が出てきます
Avatar
Swift上でErlang処理系を実装して、全てのロジックをErlangで書いて・・・
12:24 PM
そういうパラダイムでコーディングしたことがないのでよくわからない。。
Avatar
@omochimetaru ErlangのUIKit見てみたい気もw
Avatar
Avatar
Let it crashの話はまさにそうで結局Erlangも前提としてそこがあるんですよね ''' Erlangでの並行処理では、エラー処理の基本的な方法をサポートしている。 あるプロセスが異常をきたすと、プロセスは手際良く終了し、そのプロセスを制御しているプロセス (何らかのアクションをとることができるプロセス) にメッセージを送信する。 このエラー処理の方法により、ソースコードの保守性を高め複雑性を低減することができる。 '''
Avatar
func SignalHandler(sig: Int32) { let url = URL.init(string: "http://www.google.com")! UIApplication.shared.open(url, options: [:], completionHandler: nil) sleep(1) exit(sig) } @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { signal(SIGILL, SignalHandler) なんとなく成功したけどやっちゃ駄目な気がするw
Avatar
シグナルハンドラにジャンプした時点でAutoReleasePoolの制御とかぶっ壊れそうだけどまあ後は落ちるだけだし大丈夫か・・・?
12:41 PM
あとそういうアプローチだとat_exitだっけ、なんかそういうのもありますよね
12:41 PM
シグナルハンドラより健全な感じのやつ
Avatar
Crashlytics とかの仕組みを知らないけど競合しそう。
Avatar
あ〜そこなんですよね
12:42 PM
crashlyticsはatexitとかシグナルハンドラ仕込んでおいて、飛んだところでスタックトレースを収集しておいて、それをログに吐いて落ちて
12:42 PM
次回起動時に送信する、とか、そういう仕掛けかなあと思っているんですけど
12:43 PM
実際何も触れてないのでわからないw
Avatar
死んだ瞬間に飛びませんでしたっけ
Avatar
そうなんですか〜
12:44 PM
同期的にソケット張ってやればいけるか
Avatar
applideveloper 6/16/2017 12:47 PM
クラッシュログツールって何使ってますか?
Avatar
applideveloper 6/16/2017 1:37 PM
Appleのitunes connectにはクラッシュ数は出るんですが、クラッシュログがでないので公式でサポートしてほしいですね
Avatar
applideveloper 6/16/2017 1:54 PM
アプリは落ちるけどiPhoneは落ちないのでAppleはクラッシュログを送ってるはずなので、Appleは全部捕捉できるはず (edited)
Avatar
norio_nomura 6/16/2017 2:04 PM
あれ?XcodeのOrganizerで見られない?
Avatar
applideveloper 6/16/2017 3:22 PM
それはiPhoneを接続してる開発者自身だけじゃないですか? (edited)
Avatar
applideveloper 6/16/2017 10:43 PM
おおお、サポートしてた (edited)
Avatar
applideveloper 6/16/2017 10:54 PM
However, crash logs are not sent to Apple unless the user agrees to share crash data with app developers. TestFlight users automatically agree to share crash data. (edited)
10:54 PM
TestFlightユーザー以外は収集できるできない? (edited)
Avatar
iOSアップデート時、ユーザーに対して「Appデベロッパと共有」するかどうか選択肢が表示されるので、そこで共有を選択してくれたユーザーからは収集されるはずです。TestFlightを使っていないアプリでもクラッシュログを見られます。
😀 1
Avatar
日本語だとこの記事が良かったです。1年以上前の情報なので、現在改良されている点もあるかもです(僕はあまり活用してないので細かい差分わからず)。 http://qiita.com/koogawa/items/cdbda15d32c2adc91773

Crashes Organizerとは

Xcode 6.3 から追加されたクラッシュ解析ツールです。 それよりも前は Crashlytics などのサードパーティを利用する必要がありました。 ![image](https://...
😁 1
Avatar
applideveloper 6/17/2017 2:07 AM
もしかしてアプリ利用者 がAPPデベロッパとクラッシュデータを共有することに同意してなかったらCrashlysticsでも取得できない?
Avatar
それは関係無く、大丈夫です。
2:15 AM
Enable Privacy Promptというのを設定すれば、確か許可ダイアログが出て、それに同意した端末でのみ有効になるはずです。アプリ利用規約などによってはこれをオンにしないといけない気はしつつ、オンにしているアプリ見たことないです( ´・‿・`) (edited)
2:17 AM
設定画面の右上です。
2:17 AM
昔はもっと目立つ項目でしたが、最近はこういう表示になったこともあってか、この設定があること自体知らない人多そうな気がしていました。
Avatar
これとかも https://docs.fabric.io/apple/crashlytics/advanced-setup.html#controlling-submission-behavior
There are many reasons why a developer may want to control submission behavior. One example is to request permission to submit crash reports out of privacy concerns. You also may want to build a preference into your app instead of asking on every request.Additionally, you may want to add post-crash data.
Avatar
applideveloper 6/17/2017 2:59 AM
つまりFablicではEnable Privacy Promptを設定しれ許可ダイアログで許可してないと取得できないということ? (edited)
Avatar
いえ、何もしなければ普通に取得できます
Avatar
applideveloper 6/17/2017 2:59 AM
おお
3:01 AM
Fablicの場合、クラッシュしたタイミングで送られる、クラッシュしてもう一度開いたときにクラッシュログが送られる?
Avatar
後者のはずです(サードパーティ製ツールはその選択肢しか無いような)
Avatar
applideveloper 6/17/2017 3:03 AM
アプリが死んだらアプリ組み込みのプログラムはうごかせないですよね
3:03 AM
iPhoneはいきてるのでappleは収集できそう
Avatar
omochimetaru 6/17/2017 3:03 AM
@mono シグナルハンドラからソケット通信を同期的にやればできる説
👀 1
Avatar
applideveloper 6/17/2017 3:04 AM
その説の検証結果求む
Avatar
omochimetaru 6/17/2017 3:05 AM
生ソケット呼ばないといかんからなあ libcurl使うと楽か?
Avatar
@omochimetaru へー、なるほどー 👀 Fabricは経験上は後者の挙動でしたが、いつのまにかしれっと前者の挙動になっているとかの可能性もゼロではないですね
Avatar
omochimetaru 6/17/2017 3:08 AM
結局fabricがどうなってるかは
3:08 AM
入れてある環境で試すのが早いかと
Avatar
AKIBA.swift x エウレカのコードレイアウト勉強会本日開催です!興味あれば是非!w https://classmethod.connpass.com/event/81032/
# AKIBA.swift × エウレカ コードレイアウト勉強会 ## AKIBA.swiftとは クラスメソッド株式会社が主催する、プログラミング言語 Swift とその周辺技術の勉強会です。 発展を続ける Swift とそ...
😎 1
👍 1
Exported 291 message(s)
Timezone: UTC+0