例の件、コンプライアンスはちゃんとしろと思う一方で、関係ないけど、ソースコードをプロプライエタリ化するのはクソ、サービス提供者はユーザーにソースコード見せろやとも思う……
例の件、コンプライアンスはちゃんとしろと思う一方で、関係ないけど、ソースコードをプロプライエタリ化するのはクソ、サービス提供者はユーザーにソースコード見せろやとも思う……
そういえば大昔にジャッヴァで型とかフィールドにアノテーション付けまくると DB スキーマが生えてくる感じのフレームワーク使ったことがある気がするな。まあ私そのフレームワーク嫌いだったんだけど、DB との統合としては筋は悪くなかったと思っている
とりあえず "stringly typed" という概念だけ今日は覚えて帰ってもらいましょ
Stringly Typed
https://wiki.c2.com/?StringlyTyped
なんらかの超能力を発揮して、リプと空リプを使い分けるか、そもそもコメントを付けないか、といったことをする必要がある
たとえばですが、
「jsonファイルがフィールド a と b を持っている」
という想定があったとして、「a や b がなかったり余計な c があったりするファイルを読んだ」は「想定可能なエラー」なんですよ。この場合クラッシュすべきでない。
で、じゃあどういう場合にクラッシュすべきかというと、
「json ファイルがフィールド a と b を持っていてそれを読んだのに、返すオブジェクトで a の値を設定し忘れた」とかそういう「デシリアライザが仕様違反を犯している場合」です。
この場合「デシリアライザが『こういうデータを読みますよ』と (仕様で暗黙に) 表明したデータ以外を返す」というのは仕様外動作なので、そこから復帰しようとすべきでない。
私の中では明確で整合した理解が確立されているんだけど、それをダンプするのが難しい
なんというか、分割したコンポーネントを、どうやって整合性のある形で合成するかという問題への対処法としてあるものだという観点が、エラー処理やパニックの話をする上で大事なのかなって気がした
my fault と your fault の区別が重要で、他人の失敗は穏やかに指摘するべきだが、自分が失敗するときはまず正気でないのでクラッシュする必要がある
あとは、通信が絡む場合は、外部のコンポーネントはたとえ自分が作ったものだとしても他人とみなす、みたいな作法があるとか……
オレンジ的には不整合を見つけた場合にはユーザーに知らせるべきではある一方でクラッシュするべきでは無いと考えるかも><
たぶんそのアプリの実行してる時間の差で意識が違うんだと思う><
CLI中心の人にとってはUNIX哲学の通りひとつの事しかさせないのでクラッシュ自体を重大とは捉えないかも><
GUI中心の発想や失敗したら人が死ぬ分野の発想では、クラッシュして止まること自体を重大に考えるので、クラッシュさせるのは最後の最後の手段と考えるかも><
(失敗したら人が死ぬ分野の場合は、なんらかの(例えば物理的な)更なるバックアップがない状況ではそもそもクラッシュさせるという選択肢はとらないかも><)
プログラムは、他のプログラムとも通信するし、人間ともコミュニケーションをとる必要があって、その通信・コミュニケーションをどう制御し組み上げるかという話ですよね
「黙ってクラッシュ」って言ったとき、その黙る対象はふつうは出力したデータに依拠して動く他のプログラムであって、人間に対して黙っているとは限らないわけです。
黙ってクラッシュ、人間に対しても黙っているときはふつうにあるというか、リトライで解消できるエラーを人間にいちいち報告してきたら人間がパンクしちゃいますからね
「UNIXという考え方」における「沈黙は金」は常に正しいか https://songmu.jp/riji/entry/2018-08-15-unix-silence-is-golden.html
実用的なプログラムは必ずそういう「そこは信用します」というレベルを程度の差こそあれ持っていて、「そこは信用しますレベル」は invariant がどれだけあるか、どれだけ強い条件かで決まってくる。
で、その信用を裏切られたときクラッシュ以外の行為に意味がない、という話です
不変条件が破られるかもしれない、その破られたときのフェイルセーフとしてのクラッシュが要求されるの、まあシステムプログラミングとか、広くデプロイされるシステムとか、危険なマシンを動かすシステムとか、そういう領域になってくるのかなって気はする(雑なアプリケーションでは気にしなくて良いのでは?)
まあそういう考え方もあるけど、私は単に思想ゆえそのように作ってるだけですね (不変条件が破られた狂ったコードが動き続けることに意義を感じられないので) (正しく動く可能性はあるが、同時に傷口を広げる可能性も高い)
バグったまま動き続けるより、「バグです!」と叫んで死んでくれた方が嬉しくない? というお気持ちですね
ただ、ここで throw new RangeError() を書く必要があるのは、JavaScriptだからってのがあって、代数的データ型で網羅性検査があるときは、こういうthrowって要らないですよね
「狂っていると判断することに期待する」はたぶん捉え方が逆で、「狂っていないことを期待する場所で何かがおかしかったら全てを諦める」というのが私の考えに近い表現ですね。
let a = 42;
let b = a + 1;
assert!(a == 42);
みたいなのがあったとして、この assert で a が 43 になってたらエラーとして復帰したいですか?
私はそんなのナンセンスだと思うので a == 42 でなかったらさっさとクラッシュしてほしいです
そもそも
let a = 42;
let b = a + 1;
assert!(a == 42);
って例だと、assert文が近すぎて成立することが自明だけど、間にfor文があるとか、関数呼び出しがあるとかだと自明じゃなくなって、そういう時にassertは重要だし、そういう例じゃないと必要性がわからないですよね
https://pleroma.ryusei.dev/objects/47d716d7-8477-44db-9ccd-3a817722309b
そういうところ、「ユーザにとっては (間に挟まる for 文などで a が変更されないことが) 明らかだとしてもコンパイラやレビュアーや将来の自分にとってそうだとは限らない」みたいなところで整合性の検査が生きる
https://blog.cardina1.red/2019/12/19/dont-fear-the-panic/#usage--where-to-use-which--just-to-be-sure
> また、開発初期にそのような条件が持続することが自明に見えても、コードが膨らんでいくにつれ、間に多くの処理が挟まるかもしれない。 そのとき、追加・変更された全てのコードがまだ先に確認した条件を壊さないと、本当に確信できるだろうか?
コードを書く時に、将来この部分に追加の記述が入って自明じゃなくなるよなって時にはもちろん書くかもしれないけど、記述が変更されることはなく自明でなくなるかもしれないという不安が生じるまでは書かれることはない
「記述が変更されることはないことが分かっていて、自明でなくなるかもしれないという不安が生じないのであれば、書かれることはない」
http://www.taikaisyu.com/00roc/roc-012/11.html
この身に起こる あらゆる事態を想定し その対応策を「設定」した 聡明なる頃の「ワシ」だ
「ワシ」よ! この「ワシ」の声を聴け
その例で言うと、狂ってるのは42に1を足す処理の部分か計算機そのもののどちらが狂ってるわけであろうから、その部分をスキップさせてエラーを通知して出来る限り穏便に済ませる処理を書くか、計算機をシャットダウンさせる処理を書くべきかも><
単位がアプリケーションというかプロセスって発想ってモノリシック的かも><
ハナっから信用してない部分で裏切られる分にはまあエラーログなりデフォルト値で対処すれば良くて、信用を裏切られたらそれ以上続けようとしたところでろくなことにならないんだからさっさと死のうやという以上の説明を思いつかない
フェイルセーフ的に到達不可能なpanicを入れるのはともかく、関数をトータルに作ろうとする分には、パニックがないからなー
Panic on semantic error, instead of returning error by lo48576 · Pull Request #31 · saschagrunert/indextree
https://github.com/saschagrunert/indextree/pull/31
というか実例見た方が早いな、これとかが「実装ミスで内部的な整合性が破綻したときエラーを返してユーザに復帰を試みさせるな」のプルリコです
アルゴリズムを書くとき、インバリアントに依存した処理を書くことはよくあることで、それを明示的にコードに書くのは行儀が良いことだといえる
例外は「想定されたエラー (明示的に throw されるもの)」と「本当に誰も想定していなかったエラー (意図せぬ場所から propagate されてきたもの)」が混ざるので、失敗や不整合の表現としてはあまり優れた手段ではないという感覚がある
一回だけ動かしたいスクリプトで厳密な仕様とか異常系とかあんまり考えないしな(しかしその使い捨てのつもりのスクリプトが本番環境に組み込まれて使われることになる……)
プログラムを最初からトータルに作ることは考えていない領域というか、パーシャルなプログラムを動かしながら作っていく領域では例外は有用だと思いますよ システムプログラミングはそういう領域ではないけど
C++ の中では仕方なかったと思うけど、 C++ 以外の世界を含めて考えたとき、「起きうるエラーの指定がひたすら面倒」というのは言語デザインとして弱点
これはそうで、起きうるエラーを (継承以外のヒエラルキーで) どうまとめるかの表現に成功しましたか、失敗しましたか、というのが既存言語の例外の使いづらさの本質だと思う
噛み合ってない……
私はいつも「(仕様上) 起きえないエラー」をどうするかの話をしていて、例外ハンドリングや「起きうるエラー」からの復帰の話をしているわけではないです
整合性がオブジェクトで閉じてるなら、オブジェクトレベルでクラッシュして、他のオブジェクトにクラッシュが波及しないみたいな仕組みでもいいわけじゃん?
不整合や仕様外動作に汚染された領域を破棄する手段として通常は文脈の破棄しか用意されていないという話と、仕様外動作を仕様に含んでいるかのように振る舞うことは根本的におかしいというデザインの話が混ざっていたか
もちろんプロセスより細かく分割することもできて、その場合何か起きたら Result<_, _> なりで実行時エラーとして通知することになるんですが、それって「信用していない」ということなので、信用していないコードのクラッシュに巻き込まれるべきであるという話はしてないです…… (やっぱり「クラッシュ」という言葉がアカン気がしてきた)
はい、適切に分割してください。
ただ、その「汚染範囲を小さくする」を誰が行うかの話で、「この変数は、こことここと、この部分に影響してます!」とかいうオプトインな列挙方式でうまく汚染を隔離できると思うなよという思想の話ですね
“実は谷口住職の趣味はプログラミング。約20年前にはインターネット統合アプリケーション「SeaMonkey」の開発プロジェクトに参画していたという。「Mozilla」の日本語パックをほぼ1人で作ったこともある。”
「リモート初詣」で参拝客が130倍に、住職のこだわりと技術力に驚いた(2ページ目) | 日経クロステック(xTECH) https://xtech.nikkei.com/atcl/nxt/column/18/00138/010500702/?P=2
このアカウントは、notestockで公開設定になっていません。
このアカウントは、notestockで公開設定になっていません。
このアカウントは、notestockで公開設定になっていません。
「意味論って何?」って話、前提が多すぎてうまく説明しづらい 自分もブログに書いてみたことはあるけど、出来にあんまり納得いっていない https://mandel59.hateblo.jp/entry/2016/05/11/002356
とにかく、プログラミング言語におけるコードの動作や解釈を規定するのが意味論なわけですが、これが明確に示されていない言語は言ってみれば妄想みたいなものというか、「みんななんとなく常識的に解釈したり自然言語の文書を読んでわかった気になっているけど、数学的な証明とかに使えるような明確な定義が実は存在しない」という若干危うい状態なわけです。
あるいは「唯一の公式処理系である俺が意味論だ!! (意味論だとは言ってない)」みたいな。
「言語である以上」って言ったけど、実際のところは意味を直接考えることに向かず、語用論的に考えるしかない言語というものもあるかもしれないが
語用論と意味論の境界は、人間の自然言語ならともかく、形式言語とか一般化された記号体系まで含めると、ちょっと微妙かなって思う
まあ、具体的には、信号機の色が何を意味しているのかと、実際の運転士が信号に応じてどう振る舞っているのかというのは別の話なので、そこが意味論と語用論の違いになるんだろうけど
床井先生の GLUT のページ、いつのまにか GitHub Pages になっててわろた
そういえばプログラミング言語の文脈だとそもそも意味論 (semantics) という用語自体が多義的でアレな面は確かにあるなぁ。
特定のプログラムについて定義される挙動や解釈自体も「意味論」と呼ばれるし、それら個々のプログラムの挙動や解釈を規定する一連のルール群 (つまりプログラミング言語の仕様の一部) もまた「意味論」と呼ばれる