解説
この作りにした理由
Hikidashiの設計の考え方:データを持たない、推測するより答えない、純粋な関数、引き出しごとのエントリーポイント。
Hikidashiは、同じ作者の日本語学習アプリUmaKumaから取り出したもので、どの関数もそこで書かれ、テストされ、使われてきました。このページでは、それらに共通する考え方を説明します。それが、このパッケージのどの関数に何を期待できるかを左右するからです。
自分ではデータを持たない
知識が必要な引き出しは、どれもそれを引数として受け取ります。extractFromTextは辞書をknownとして、wordClassesOfは辞書の品詞を、kanjiCostは学年と使用頻度のデータを、kanjiAsWordは読みを受け取ります。パッケージには、辞書も単語の一覧も学年の表も入っていません。
辞書は大きく、毎月のように更新され、独自のライセンスがあります(JMdictとKANJIDIC2はクリエイティブ・コモンズの表示・継承ライセンスです)。辞書を含めれば、パッケージはキロバイトではなくメガバイトの大きさになり、インストールする人全員にそのライセンスが及び、リリースの翌週には古くなってしまいます。アプリにはすでに辞書があり、利用者が目にするのはその辞書なので、答えもその辞書と一致するべきです。
ただ一つの例外はJAPANESE_ERASの五つの元号で、これは天皇の代替わりのときにしか変わりません。
推測するより、答えない
答えられないとき、関数はnullか空のリストでそれを伝えます。正しそうに見えて正しくない値を返すことはありません。「昭和65年」は1990ではなくnull、「一二三」は123ではなくnull、語に合わない読みは、テストが正解にしてしまうような割り当てではなくnullです。
理由は、その後に起きることにあります。nullなら気づけます。ページは「年ではありません」と表示し、テストはその単語を外し、フォームはもう一度入力を求めます。もっともらしい間違った数は気づかれず、保存され、印刷され、教えられてしまいます。リファレンスの@returnsには、どれもそのnullの意味が書いてあります。
候補を挙げ、確かめるのは呼び出す側
いちばん分かりやすいのはdictionaryFormsです。日本語の活用は、辞書がなければあいまいです。「食べる」は「食べる」の辞書形であり、実在しない動詞「食ぶ」の可能形でもあります。知っているふりをするのではなく、この関数はすべての可能性を、可能性の高い順に、それぞれ必要な語の種類を付けて挙げ、呼び出す側が辞書で確かめられたものを残します。/extractも同じ分担です。単語になりうるものを見つけるのはHikidashi、それが単語かどうかを決めるのは手元の辞書です。
純粋な関数
どの関数も値を受け取り、新しい値を返します。呼び出しの間に状態を持たず、引数を変えず、現在時刻を読まず、DOMにもネットワークにもファイルシステムにも触れません。だから、ブラウザーでもサーバーでもテストでも同じように動き、buildKanjiTestはMath.randomを呼ぶ代わりにシードを受け取ります。このドキュメントの例が、ページを作ったときに実際に出力した結果をそのまま載せているのも、そのためです。
引き出しごとのエントリーポイント
引き出しどうしで共有しているものはほとんどありません(二つのかな変換と、/extractが/deinflectを使うことだけです)。そこで、それぞれを@johnmorrisdotca/hikidashi/warekiのような独立したエントリーポイントにしています。元号の年を変換するページは、元号のコードだけを読み込みます。パッケージはsideEffects: falseなので、メインのエントリーポイントから読み込んでも、バンドラーは残りを取り除けます。各エントリーポイントの、最小化とgzip圧縮をしたサイズは概要にあります。
処理の量に上限がある
ページに貼り付けられる文は、どんな大きさにもなりうる唯一の入力です。そこで、それを読む関数にはどれも上限があります。上限はEXTRACT_LIMITSとALIGN_LIMITSにあり、活用の連なりは五段階までです。長い入力や悪意のある入力でも、かかる時間には上限があり、切り詰めた結果はそのことを示します(stats.truncated)。時間がかかりすぎる入力を見つけたら、セキュリティポリシーに従って報告してください。
この日本語は、まだ日本語を母語とする方の確認を受けていません。訂正を歓迎します。