Day2 src/choosenimpkg/telemetory.nim
Day2はtelemetory.nimを読んでいく。
私は賢くないので何度もコードを読み返していくが、賢い人は流し読みで理解したら読まなくていいと思う。
初手
とりあえずアウトラインを眺めてみる。
「ん?report()が2つあるぞ?」と思って先にコードをチラ見したら宣言だった。
先に宣言することで、loadAnalyticsよりも後に記述されているreportを呼び出す事ができる。
個人的には宣言よりも先行定義(呼び出されるよりも先に関数を定義する)のほうがメンテナンスは楽だと思う。
呼び出される関数は前(上)にあることが保証されているし、宣言と定義で2回書かなくてもいい。
ただ宣言にもメリットはあって、ありきたりな名前のreport
関数がこのモジュール内に存在することが明示的になり「これはオリジナルな関数なんだな」ということがわかって、可読性がよくなる。
まぁ用法用量を守ればだと思いますが…。
流し読み
さて流し読みをしていく。
どうやって読んだコードを解説したらいいか試行錯誤中なので、唐突に進め方が変わるかもしれない。ご容赦をば。
今日は先頭から処理ごとに読んで感想や気になったところを述べていくことにする。
気にならないような処理とかはスキップするかも。
import
- [疑問] よく知らないanalyticsパッケージが出てきた。
- [補足] Google Analyticsで収集・分析しているらしい。
https://github.com/dom96/analytics
- [補足] Google Analyticsで収集・分析しているらしい。
- [感想]
nimblepkg/cli
はエラーやINFOの標準出力のために使っている。display()でエラーの見た目が良くなるから使っているみたいだ。 - [感想]
when defined(os)
は見慣れてきた。
型定義
- [感想] enum使ったりOption使ったりしてる。モダンだなぁ(小学生並みの感想)
proc initEvent
- [感想] 他の関数もそうだけど引数が長くなると改行入れて読みやすくしてるなぁ。
- [感想] 47行目は汎用性を高めるために、action引数が省略されればcmd、あればそれを返すようにしてる。
proc initTiming
- [感想] コメントに仕様が書いてある通り。
- [補足] Nimのドキュメンテーションコメントについてはjiro4989さんが良い記事を書いてくれています。
proc promptCustom
- [感想]対話プロンプトを独自実装せずにnimblepkgと共通した処理で見た目とか良くしている印象。
- [疑問]正直なところelseの場合の再帰処理の意図がよくわからない。
- [補足] 再帰ではありません。オーバーロードで
nimblepkg/cli.prompt
が呼び出されます。勝手にハマって、すごく脱線してたので余談に書きました→ForcePrompt
- [補足] 再帰ではありません。オーバーロードで
proc analyticsPrompt
- [感想] デフォルトだと
~/.choosenim/analytics
にClientIDが書き出される。
エラーハンドリングはchoosenim.nim
のisMainModuleブロックで行われています。
トレースするとchoosenim(isMainModule)
→loadAnalytics
→analyticsPrompt
でした。
ちなみにClientIDの払い出しに使われている処理を追いかけてみたらこんな感じでした。
https://github.com/dom96/analytics/blob/master/src/analytics.nim#L129
https://github.com/pragmagic/uuids/blob/master/uuids.nim#L76
loadAnalytics
- [感想] インデント深くしないようにelse省略良くやる。個人的に読みやすい。
- [感想]
analyticsFile
の有無でanalyticsPrompt
を呼び出してる。- [補足]テレメトリーに同意しない場合はclientIDが空なので、データは送られない。
proc reportAsyncError
- [感想] 非同期処理のコールバックは初めて見た。
proc hasPendingReports
- [感想]
pendingReports
があるかどうかを返しているだけ。
waitForReport
- operationsとrepotsが終わるか、指定秒数を超えるまでのWait処理。
proc report
- [発見] 引数の
obj: Event | Timing | ref Exception
はobjの型がEvent
orTiming
orref Exception
という書き方。ジェネリクスっぽい。- [感想] 共通の処理があって一部だけ個別にしたいケースで、オーバーロードより便利そう。
- [疑問] ジェネリクスではないのは何故だろう。。。予測できない入力を受け付けないため?
- [感想] コンパイル時にこの関数に渡される型はわかるため
when obj in Evvent:
で分岐している。
今日のまとめ
nimblepkg/cliのdisplay()で出力の見栄えをよくしている。これは活用できる。
Google Analyticsを活用して、テレメトリーデータの収集をしていたので今後、収集するようなアプリの参考になる。
それにしてもきれいに設計されてるなーと思う。report()とか特に抽象化がうまいなぁ。
残っているタスク
[タスク]telemetry.loadAnalyticsを読む[タスク]telemetry.waitForReportを読む。- [タスク]cliparams.parseCliParamsを読む
- [タスク]choosenimpkgをすべて読んだらupdate,show,versions,chooseを読み直す
明日やること
- cliparams.nimを読む
余談
ForcePrompt
proc promptCustomで気になった処理。
proc promptCustom(msg: string, params: CliParams): string =
if params.nimbleOptions.forcePrompts == forcePromptYes:
display("Prompt:", msg, Warning, HighPriority)
display("Answer:", "Forced Yes", Warning, HighPriority)
return "y"
else:
return promptCustom(msg, "")
このelseの再帰の意図がよくわからないので、処理を考える。
まず、forcePrompts == forcePromptYes
がfalse
になるケースを考える。
ForcePrompt* = enum
dontForcePrompt, forcePromptYes, forcePromptNo
引用元:https://github.com/nim-lang/nimble/blob/master/src/nimblepkg/cli.nim
forcePromptsがdontForcePrompt
orforcePromptNo
の場合にfalseになる。
でもなんで再帰…ん…?
「あっ、これ別のメソッドだ。オーバーロードじゃん!!」
そもそも引数の型がpromptCustom(msg:string, "":string)
の時点で気づきたかった。
最近、再帰処理をよく見ていたので脳みそが勝手に勘違いしていた。
66行目でよばれるcli.promptCustom()
は以下です。
https://github.com/nim-lang/nimble/blob/master/src/nimblepkg/cli.nim#L181
めでたしめでたし。
-
performActions.paramsはchoosenim.paramsが渡されるので両者は同等。 ↩