わくわく技術ブログ

プログラミング・統計・機械学習

JJUG CCC 2024 Spring で LT発表してきた (タイトル「日付と闘う」)

JJUG CCC 2024 Springの懇親会LTで発表してきたので、
今回はその簡単な経緯と感想などを。

経緯

JJUGには参加するつもりで申し込んでいた。 LTがあることを知ったのはこのツイートだったと思う。ITエンジニアにとって、Twitterは大事な情報源だ…。 (今はXとかポストとか言うようですが、以下も旧称で。)

以前に、Server-Side Kotlin Meetup Vol.10 というイベントで外部LTは参加経験があり、
半年以上経ったしそろそろどこかで何か発表してみようか と思っていたところだったので、JJUGで話せるネタがないか検討すること数日。

最近は自分自身ではJava/Kotlinのコードをほとんど書いていなかったものの、同僚が最近ぶつかった問題を題材に話ができるなと思い、
その同僚の許可を得て(※本当はその同僚に発表を勧めたのだが外部はチョット..って感じだったので)、自分が発表することに。

5/30(木)にLT枠の存在を知り、6/7(金)に申し込み。
この時点で、10人中7番目だった。週末には埋まったようなので、わりと伸びが早かった。

この段階でタイトルを出す必要がある点が、意外とハードルだった。

内容練りと資料づくり

「和暦」の扱いがJavaだと (他言語よりは便利だけど)ちょっと罠がある
というのをテーマにするのは、申し込み時点で決めていたのだが、3分話すにはちょっと薄いなぁ ということで、話を膨らませるべく色々試したりする。

検討の結果

  • DateTimeFormatterのデフォルト設定だと、元号の切り替わりの年だけ存在しない元号+月日の組み合わせでもパース成功する
    • 例) 平成31年5月1日 は 令和1年5月1日 としてパースされる、平成32年1月1日はパース失敗する
  • 「年度」表記にする良い方法はない (& 自治体によって 平成31年度と令和1年度とどちらで表記するか変わる)
  • 元号切り替わりの年は、"年末"の判定が狂う

3本立てで話すことにした。
何かを話すときに、3つあるとちょうど良いとはよく言うもので。

だがしかし、発表時間が3分だったのと、
話の流れ的に建設業に絡めたかったので、話が収まらないことなんのその。

普段は社内で15分発表をしているものだから、普通に短めくらいで作っても5分以上にはなってしまい、
そこから頑張って削り、
さらにさらに削り、 さらにスラスラ良い感じのテンポで話せるように練習を重ね、、 気付いたら当日の朝4時ごろまで作業することに(:3 」∠ )

LTというのは、ほんとにLightningにトークするのは大変だということがよく分かったのであった。

当日

日中は普通に講演を聴き。
懇親会準備を少し待ったら、ビール片手に乾杯。
JJUGは何度か参加していたが、懇親会に残ったのは初めてであった。なるほどこういう雰囲気ね。

といっても、過去のLT資料を検索して参考にしていたので、雰囲気はおおよそ予想通り。
8番目で、良い感じに場が盛り上がっていてとても話しやすかった。
発表中のことはよく覚えてないけど、わりと盛り上がってた気がする。覚えてないけど。

発表直後に

和暦の扱いが良くないのは、日本のコミュニティの力が足りなかったから.. 的なコメントを言わせてしまった。
いやーそういう事を言いたかった訳では無いのです(‥;)ゴメンナサイ

その後

発表ネタで話しかけてくれた人が2人いらっしゃった。
ありがたや。

和暦に関しては結局、良い感じの回避策はあまり無かったりするんですよねー って話をしたのと、
日付や日時の扱いに関する苦労ポイントあれこれを話したりして楽しかった。
(パフォーマンス気にするところでは日付型ではなく数値型で値をもってたりする とか、 今時なら生成AIを使うとなんとかなるんじゃないかとか。)

発表してなかったらぼっち確定な場だったので、ありがたや(再)

翌日

発表資料をSpeaker Deckに上げ、Twitterに書き込んだところ、いくつかコメントが。

内容について補足してくださる人もいて助かる限り。

前者のどうしようもない側はJavaDoc読んで(コードも読んで)いたが、
LENIENT指定する件は忘れていた(理由は後日調べようと思っていた)ので、ズバリな回答を頂いた。

本当はすぐに詳しく調べてZennかQiitaの記事にでもしたかったが、
今もまだ時間を取れておらず。取り急ぎスライドの方には追記としてスクショを載せさせてもらった。

これがその資料。会社の宣伝も追記しておいた 笑

speakerdeck.com

感想

勉強会の本編は懇親会だ なんて言ったりして、それは7割は冗談だと思うけど3割は本当かもしれない。
というのも、懇親会に参加している方々の顔を見ると、「あれは、かの有名な○○さんでは..!」みたいになることがある。そんな人たちと会話をするのは、本編ではなかなかできない。

けど、自分は懇親会があまり得意ではないので、いつもそそくさと帰りがち。
そんなときに、発表すれば居場所と話題が自動で生成されるのだから、良いジェネレーターなのかもしれない。
(有名な○○さんと話せたとは言っていない)

というわけで、最近は後輩にも LT発表しなよ と何度もけしかけている。
今は会社でLT会をやっていて、月に1回くらいのペースで10分前後で発表をしているので、みんなもやってみたら話せるのではなかろうかと。

--

なおこの記事も、発表のノリが微かに残っているうちに書かねばと思って、なんとなく勢いで書いてみた。

Zennに書いてみた - Spring Framework 6.2 になると @Transactionalで検査例外もロールバックするための設定が増える (予定)

タイトルの通りである

はてなブログ(ここ)で下書きしていたが、
スマホプレビューでコードブロックが微妙な見え方になってしまったので、Zennを使ってみた。

記事本文はココ↓ zenn.dev

どうだった?

比較↓

はてなブログをスマホで見たときのコードブロック
はてなブログ

Zennをスマホで見たときのコードブロック
Zenn

次の2つの条件を満たす技術記事は、はてなブログではなくZenn(Qiitaでもいいかも)がオススメだと思った。

  • スマホでの閲覧を想定する
  • 説明の都合でコードブロック内をちゃんと読んでほしい

逆に、以下が当てはまれば、はてなブログが良いかもしれない。

  • スマホは対象外(PCから読めれば十分) or 文字が中心でスマホからでも読みやすい
  • 独自ドメイン利用など、Zennにはできない設定をしたい

記事作成中のプレビュー機能は、Zennのほうがサクサク動いたが、
どちらもMarkdown形式が使えるので、VSCodeなど使って下書きする場合には大差ないかと。

ZennはGitHubリポジトリから記事アップロード可能らしいので、いずれ試してみたい。

JavaのDBアクセスライブラリ jOOQ の紹介

先日、とある会社の方に、DBアクセスするにはjOOQ(ジョーク 【訂正】ジュークと読むらしく公式に発音記号が定義されている)というライブラリが良いと教えて頂いた。 名前はなんとなく見たことがある気がするものの、実際のところどういった物なのか知らなかったので、個人的に気になる点を調べてみた。

実際に使い倒したわけではなく、使ってみたら不満とか解決策とか見つかるかもしれないので、その点はご容赦を。

対象読者

  • JPA(Hibernate)/MyBatis/Doma2 など他のDBアクセスライブラリの利用経験がある人
  • jOOQのことを知りたい人、検討材料を探している人

jOOQが何か簡単に言うと?

ドキュメントを探しても、ズバリ一言で「jOOQは〇〇である」という記載は見つからない。ドキュメント 3.3. Different use cases for jOOQ

jOOQ has originally been created as a library for complete abstraction of JDBC and all database interaction.

と書かれており、DBアクセスを全てカバーしたいことは分かるが、どういう特徴があるかは一言では書かれていない。

一方で、他のツールとの対比や利用のバリエーションは色々書かれている。

例えば、jOOQのGitHubリポジトリREADME.mdを私なりに要約すると、JPALINQのような仕組みはSQLを隠そうとするあまり高度なクエリ発行が難しいと言っている。

また、ドキュメント 3.3. Different use cases for jOOQから抜粋すると、

  • 型安全にSQLを組み立てられる。
  • クエリ実行に便利な機能を用意している。ロギングなどの開発補助も入っている。
  • HibernateとjOOQを組み合わせて使うのもあり。
  • jOOQにはソースコードジェネレーターがあるけど、それは使わなくてもよい。

などあれこれ書かれている。

これらを踏まえると、「Javaの型の恩恵を受けながらSQLを直接記述したいときに使うライブラリ」と言えそうだ。

競合は?

jOOQ公式ではJPA(Hibernate)を非常に意識している。ただ実際にはSQLを自在に実行できるライブラリとして、MyBatisDoma 2などが競合にあたるように思う。

MyBatisもDoma 2もいくつか使い方があるが、主には、

  • MyBatis … SQLをファイルに記述する。条件分岐などはXMLタグで表現する。
  • Doma 2 … SQLをファイルに記述する。SQLコメントをDoma 2が解析して条件分岐などを制御する。
  • jOOQ … JavaソースコードSQLを記述する。

という使い方になると思われる。型安全にするためにJavaの中でSQLを組み立てるのにこだわっている点で、他のライブラリとは方向性が異なる。

気になったこと一覧

分類 実現したいこと 調査結果 URL コメント
参照系 JOIN句 https://www.jooq.org/doc/3.16/manual/sql-building/table-expressions/joined-tables/
参照系 サブクエリ(相関サブクエリ) https://www.jooq.org/doc/3.16/manual/sql-building/column-expressions/scalar-subqueries/
参照系 ロック取得 https://www.jooq.org/doc/3.16/manual/sql-building/sql-statements/select-statement/for-update-clause/
参照系 カーソル取得(大量レコードの順次取得) https://www.jooq.org/doc/3.16/manual/sql-execution/fetching/lazy-fetching/
参照系 HINT指定 https://www.jooq.org/doc/3.16/manual/sql-building/sql-statements/select-statement/oracle-hints/ Oracleと同じコメント形式の場合対応可、型安全ではない
更新系 batchExecute https://www.jooq.org/doc/3.16/manual/sql-execution/batch-execution/
共通 プリペアードステートメントの再利用 https://www.jooq.org/doc/3.16/manual/sql-execution/reusing-statements/
共通 動的なSQLの組み立て https://www.jooq.org/doc/3.16/manual/sql-building/dynamic-sql/ 簡潔さよりシンプルさ重視か
共通 プリペアードステートメントの利用(SQLインジェクション対策) https://www.jooq.org/doc/3.16/manual/sql-execution/statement-type/
共通 組み込み関数呼び出し, キャストなど 〇? https://www.jooq.org/doc/3.16/manual/sql-building/column-expressions/ よく使う関数は揃っていそうだが、足りないものもきっとある
共通 エラー処理 https://www.jooq.org/doc/3.16/manual/sql-execution/exception-handling/ jOOQ独自例外を持っているが、Spring Bootを利用する場合はSpringの例外に変換される。
※型名が同じDataAccessExceptionなので要注意。
共通 Spring Bootとの連携
1.Starter/AutoConfiguration
https://github.com/spring-projects/spring-boot/blob/v2.6.4/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java
共通 Spring Bootとの連携
2.例外変換
https://docs.spring.io/spring-boot/docs/2.6.4/api/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.html
共通 Spring Bootとの連携
3.コード生成
https://www.jooq.org/doc/3.16/manual-single-page/#codegen-generate-annotations Springのアノテーションを付与する設定などもあり
共通 Spring Bootとの連携
4.テスト補助
https://docs.spring.io/spring-boot/docs/2.6.4/reference/html/features.html#features.testing.spring-boot-applications.autoconfigured-jooq
共通 生成されるSQL文の出力 https://www.jooq.org/doc/3.16/manual/sql-execution/logging/ ExecuteListenerを実装することでカスタマイズ可能
※SpringBootのAutoConfigurationで設定されるExecuteListenerが@Order(0) であることに注意する
共通 テスト補助 https://www.jooq.org/doc/latest/manual/sql-execution/mocking-connection/ データ読み込みとかも可

感想

気になる事を一覧で出してみた結果、ほとんどが「○」だったので実用性は十分だと思う。

悩む点:ベストマッチなシチュエーション

SQLライクな記述をしたいという需要に応えるライブラリなので、複雑なSQL、特にSELECT文を発行するときに真価を発揮するはずだと思ったので少し考えてみた。

複雑なSQLには、

  1. 発行するSQLが複雑
  2. SQLの組み立てが複雑

の2パターンがあると思う。

1.については、頭の中でSQLを考えるのであれば、Javaではなく別ファイルにSQLを書く形式の方が素直なのではと思う。 一方で2.については、Javaの処理で書くよりも、MyBatisでXMLで宣言的に書いたりする方がスッキリすると個人的には感じていて、これもjOOQがベストとは言いかねる感じがある。

ではどんな時に真価を発揮するのか?
これは想像になってしまうが、そこまで複雑ではないけど、色々なパターンのSQLを書かなくてはいけないときなのかなと今のところ思っている。

あと、自分は普段Javaを書いているが、Kotlinなどから呼び出すときには印象が変わるかもしれない。

他より分かりやすく優れる点

Spring Boot連携の扱いは特徴である。

StarterパッケージがSpring Bootから公式に出されているのは頼もしいポイントで、MyBatisやDoma2よりもSpringのバージョンアップで使えなくなるリスクが低いと考えて良いと思う。 (Spring Bootが出している情報全般に言えることだが)ドキュメントが少ないのでソースコードを読む必要があるのが玉に瑕だが、それでも十分な利点だと思う。

あとは、上には表現されていない使い方の特徴として、基本的にソースコードはDB定義から自動生成するのが基本のようになっている点がある。 逆に、自動生成しないと文字列で記述する部分が多くて、型安全の恩恵を受けることが出来なくなってしまうとも言える。

自動生成にもオプションが多数あり、最初にどういうコードを自動生成させるかが大事になってくる点が他との違いである。

最後に

この手のライブラリを使うときに何を重視するかは人それぞれだと思う。上記を見て気になったことがあれば試して見て欲しい。
自分ももう少し触ってみて、気づいた事があれば更新を掛けていきたい。

Azure Developer Associate 向いている人/勉強方法

Microsoft Azureの開発者向け資格の Azure Developer Associate を受験して、なんとか合格しました (/・ω・)/
その感想として、これから受ける人向けの情報をいくつか書こうと思います。

この記事を書いた動機

この資格の情報が少ないです。特に日本語情報がなかなか見当たりません。そういう点も含めて、AWS等の同様の資格よりも癖が強い資格だと感じました。

そんな中で他の人の個人ブログの記事が役に立ったので、忘れる前に自分も記録を残しておこうと思いました。

どんな人向けの資格か?

向いている人

次の項目をすべて満たしている人です

  • 英語の資料だけでも勉強できる ← けっこう大事
  • C#で、ASP.NETおよびASP.NET Coreを使って実装を行っている。
  • Azureの主要なPaaSを利用している、もしくは利用したいと思っている。
    • その中でも「全部AKSで…」などという形ではなく、「FunctionsとLogicAppsとServiceBusと…」というように使い分けている(分けたいと思っている)

再考した方がいい人

次のいずれかに当てはまる人には勧めにくいです。

  • 日本語だけで完結させたい
  • JavaNode.jsPHPでAzure上で動くプログラムを組んでいる
  • ベンダーロックインされないように、他のクラウドと共通点の多いサービスを主として利用している

参考となるテキストも模擬試験(公式、非公式それぞれ)も、いずれも英語が基本です。記事執筆時点では、まず試験範囲を知るためにすら英語のPDFを開くしかありません。
唯一の日本語で使える資料としてMicrosoft Learnにこの資格向けの独学用資料があるものの、試験範囲と必ずしも一致していないですし、これだけだと落ちる可能性が高いので注意が必要です。

また、試験本番も変な翻訳が交じった日本語での出題になるので、何割かの問題は元の英文を確認するという作業が必要になりました。
ドキュメントと違う訳語が当たっているのは困りますね。

SDKの使い方レベルの話が出てきたりもしますが、Microsoftのサービス,資格なのでC#が基本となります。それ以外の言語を使っている人は、「いや、C#でのクラス名とか文法的な注意点とか知らないし…」という気持ちになると思います。
Pythonという選択肢もあるみたいですが、受験方法によってはC#限定だったりするのでやっぱり基本はC#です。JavaとNode.jsとPHPは蚊帳の外です。

あとこれは考えてみれば当然ですが、Microsoftとしては自社独自サービスを使うと他より楽になるよと主張したいわけです。
例えばAzureにはKubernetesPostgreSQLやMongoDBをPaaS化したサービスがそれぞれありますが、そういうのは試験範囲に入っていないか、入っていても割合がかなり少なくなっています。App Service(Functions, Web Apps)やApplication Insightsなど独自性が高いものが主な対象でした。

どんな勉強をするか?

情報を集めながら勉強をしたので実際にはこの順ではありませんでしたが、 今から改めて勉強するならこの順が良いかなと思います。

1. 試験範囲を確認

まず、公式情報から最新の試験範囲を確認します。

2. 主要サービスを使ってみる

次に、Microsoft Learnの中のDeveloper Associate向けとなっているラーニングパスの中で、「このサービス使ったことないぞ」というのがあれば試します。試験対策としてはこれだけでは不十分ですが、Azureの体験には良い資料だと思います。

ただし、各サービスのドキュメントよりも更新が古いので、誤訳が残っていたり、現在と設定できる項目が違っていたりということがあります。
それから変な日本語があったら英語版を見てください。「認定資格」→「certificate = (SSL/TLSの)証明書」のことだったり。

3. Udemyで演習テストを受ける

Udemyに説明講座や演習テストがあります。
あ、全部英語です。英語だったらたくさん資料があります。私は1200円セールのときにいくつか買いました。

講座を英語で聞くのはなかなか厳しいし時間も吸われてしまいますが、演習テストだったらなんとかなります。 AZ-204 Microsoft Azure Developer Practice Tests とか AZ-204 Developing Solutions for MS Azure Practice Tests とかやりました。

上記2つの演習テストをしっかりやったら、問題の傾向や難易度、よく聞かれる内容も大体想像が出来るかと思います。
(なお、1つ目の方は少し簡単です。)

4. 苦手分野の勉強をする

演習テストを受けると苦手分野がなんとなく分かるので、MS LearnかUdemyの講座かで勉強します。
あまり細かくやるよりは、演習テストで合格点が取れるようになればまぁ十分なのかなと思います。

5. 受ける

他の試験より勉強しにくいので、合格点とれるかなと思ったら思い切って受けてしまうのが良いと思います。

演習テストを受けると分かりますが、「そんなの覚えている必要ないでしょ、必要なら調べるよ」って問題も正直出てきます。(例えば、Storageのトータルの最大容量を心配するサービスとか作る機会多分こないと思うんです。)
受験料が無駄になるのは避けたいですが、自分がAzureを使うために必要な知識よりも多くを覚える時間はもったいないです。

上の方でも書きましたが問題文の日本語がおかしくて、Azure上でやドキュメントでの表記と違ったりもするので英語表示を頻繁に確認することになります。(英語表示の機能がなかったら落ちてたと思います。)

まとめ

英語ができて、C#使っていて、PaaSを積極的に使っていきたい人向けの資格です。

特に最初の英語ができることが、勉強を始めるまで気づきにくいポイントです。他のIT系の資格(Oracle,AWS,LinuC等)も英語が出来た方がいいですが、この資格はその比ではなく英語できないと辛いです。 本来の勉強すべき対象ではないと思うので、MSさんによる今後の改善を期待しましょう。

OSSにプルリクが取り込まれた

先日、OSSに自分の書いたPull Requestが取り込まれるという実績解除(?)をしました。
別にOSS活動が偉いわけではないですが、凡人にはそれほど多い経験ではないですし今後の人生の励みにもなるかもしれないですよね。
ということで、8割が記念、2割が他の人の参考になるかもしれないという気持ちで、簡単に経緯を書いておきます。

ちなみに対象のリポジトリAzure FunctionsのNode.js用ワーカーです。

きっかけ - 仕様の不明確さに対する不安

Microsoft Azureのサービスはいくつか使ったことがあります。
その中でも、Web AppsやFunctionsは、(DB部分を除けば)ほぼ無料でWebアプリケーションをデプロイできるので重宝しています。

ただFunctionsに関しては、なにやら機能が多いらしい割に、仕様が明確でないなと感じていました。
C#はクラスがはっきりしているし、MSが推してるからドキュメントも多数揃っているけど、Node.jsで使いたいなと。JavaScrptは型が曖昧だし、ドキュメントもC#より少なく見えるので隠れた仕様とかあるのではないかと思っていました。

そんなこんなで使い方を検索していた折、Azure Functions本体がGit Hubに公開されていることを知りました。そして、別リポジトリでNode.js呼び出し用のコードも公開されていることを知りました。それが上で書いたリポジトリです。
Azure Functions系のリポジトリを整理するリポジトリもありました。

バグ発見 - コードリーディング1時間

一番知りたいなと思っていたことは「自分の書いた関数はどうやって呼び出されているのか?」でした。そこで、自分の関数を呼び出しているらしい箇所を探しました。
比較的小さなリポジトリになっていたので、FunctionLoader.tsなるファイルもその中のgetEntryPoint()というめぼしい関数もすぐに見つかりました。

function getEntryPoint(f: any, entryPoint?: string): Function {
    if (isObject(f)) {
        var obj = f;
        if (entryPoint) {
            // the module exports multiple functions
            // and an explicit entry point was named
            f = f[entryPoint];
        }
        else if (Object.keys(f).length === 1) {
            // a single named function was exported
            var name = Object.keys(f)[0];
            f = f[name];
        }
        else {
            // finally, see if there is an exported function named
            // 'run' or 'index' by convention
            f = f.run || f.index;
        }
        
        // ...略...

    return f;
}

ほー、関数だけじゃなくて、複数プロパティを抱えたオブジェクトでも動くんだ、しかも丁寧なコメント付きだぞ。
ということで、3種類の指定方法を理解しました。

特に、最後のrun()index()が呼び出されるパターンは知らなかったぞ。試してみよう(※後からドキュメント読み返したら、たしかに書いてありました。)
そうやって書いてみたところ、なぜか想定どおりに動かずエラーになるパターンに遭遇。run()を定義しているのに、そこにたどり着かないぞ…
たまたまこの前日に別の有名OSSのバグっぽい挙動に遭遇したばかりだったので、Functionsのバグを引いた可能性をすぐに考えました。
測ってはないけど、リポジトリを見つけてからここまで1時間くらいだったと思います。

原因特定と対処検討

とりあえずGitHubのIssueを探し、該当事象に関するものが無いことを確認しました。
その後は、動作確認環境の準備です。幸い難しいことはなくて、README.mdに書いてあるとおりにしたらすんなりローカルで立ち上がりました。

そしてVisual Studio Codeを使って、エラーになるコードをデバッグ実行。
JavaScriptObject.keys()は関数以外も拾ううえに、prototypeの関数を取得できないのが、自分の想定どおりに動いていない原因だと判明。
関数はprototypeに定義するのが一般的ですし、classを使う場合には勝手にそうなるので、考慮不足感がありますね。

原因がわかったところで、どう実装を変えるべきかを考えました。
ここでIssueに書いてMicrosoftの人に後は任せるという手もありましたが、原因が分かっているのと、英語で正確に伝えるよりコードで伝える方が簡単かもしれない説もあったので、自分でプルリクまで投げると決意しました。

一番気をつけたことは、互換性を崩さないこと。つまり、今までエラーになって起動できなかった例は起動できるようにするが、今まで動いていたプログラムは動きが変わらないこと。
Azure FunctionをNode.jsで使っている人が少ないとは思えませんし、少しでも破壊的変更が入れば、パッチの取り込みは慎重にならざるを得ないはずだからです。

それから、テストコードを書くことも気をつけました。
あまりテストコードの揃ったリポジトリではありませんでしたが、問題点/実現したいことが明確になり、動作保証にもなるのだから、こういう時にはテストは必須なのでしょう。
ここまで書いておいて難ですが、あまりJavaScript慣れてなくて、mock-requireって何者?? みたいになりながら書いたので勉強になりました。

IssueとPull Request、そして取り込みへ

Issueはソースコードを主体に記述しました。

  • このコードでエラーになるよ
  • 似てるけどこのコードはOKだよ
  • EntryPointのこのコードが怪しいよ! (問題のソースコードを貼り付けて、該当行の横に矢印でコメント入れる)

で、その後に修正をPull Requestとして出しました。
英語マナーがわからないので、ドキドキでした。

Issue/Pull Requestを出した後には、日々「はやく取り込まれないかなー」「意図伝わってるかな…」とほぼ毎日リポジトリを覗きました。(※書いたIssueに何か動きがあったらメール通知が来るのは知ってましたが気分的にね。) シンプルな変更なのに1週間以上待つとちょっと不安になりますが、10日目で "This looks great - thank you! And thank you for adding tests :)!!" のコメントと共に取り込んでもらえました。ヤッタネ!

簡単に不具合(っぽい挙動)を見つけられた理由

JavaScript/TypeScriptに詳しいわけでもなければ、Azure Functionsの内部実装に詳しいわけでもない自分が、すぐに不具合に気づいた理由を考えます。

1. 規模の小さいリポジトリだった

Azure Functionsというサービスはなかなかに大きいですが、コア部分はC#で書かれていて、Node.js用の実装規模は小さいです。
リポジトリにファイルが多いと、目当ての機能を探すだけでも一苦労になってしまうので、当然かもしれませんが小さなリポジトリは初心者には優しいです。

2. コードを見ながら手を動かした

不具合に気づく前に、ソースコードを見ながら「ふ~ん」と手を動かしてみました。
この 「ソースコードを見ながら」「手を動かす」 というのがポイントなんだろうなと思います。
なぜそのコードが書かれたかという意図を考えながら深く読もうとする、そして実際の動きを確認して納得する/しないというのが、コード細部の理解につながるのかなと。

業務でプログラムを書く時には、多かれ少なかれドキュメントを書いてから手を付けることが多いと思います。ドキュメントを作らないスタイルの場合は、先にしっかり話し合いをして方針共有をするでしょう。
そういう状況とは手順が逆になるので、細部に気づくことができたのだろうと思います。

古より引き継がれし、ドキュメントが存在しないシステムのバグを見つけちゃったりするのは、こういう事なんですかね。(単に色々雑なだけかも。)

まとめとこれから

Azure Functionsという自分も使うことのあるOSSプロダクトに、Pull Requestを出して取り込まれました。 小さなパッチですが、不具合発見から取り込まれるまでの一連の手続きをちゃんと業務外で行ったのは初めてだったので、緊張したり喜んだりでした。
特にバグを探そうと意気込んでソースを読んだ訳ではありませんが、手を動かしていたら自然と発見しました。コードをちゃんと読むためには書くのも必要だと思いました。

Azureに貢献するべく云々というつもりは今の所ありませんが、一回経験したことで、不具合報告やPull Request提出に対する自分の中での心理的ハードルは下がったかなと思います。
OSSを使っていて何か怪しい動きに気づいたら、これからも何か行動できそうです。

余談ですが、途中にも書いた通りNode.jsはあまり使わないですし、フロント側もあまり知らないし、もうちょっとJavaScript強くなりたいですね。サーバー側をガリガリに書きたいときには、別言語を選択すると思いますが。

【統計 小ネタ】視聴率のずれ

今回はテレビの視聴率について。

年末になると視聴率のランキング形式で紹介していく番組があったりしますし、ネットで検索すれば細かい数字とともに紹介サイトがヒットします。(ex. https://tvkansou.info/rekidai2018/ )
ところで、視聴率の求め方や正確さって気にしたことはありますか?

視聴率の調査方法

日本テレビのウェブサイト 日テレ 広告ガイド に詳しい情報が出ています。

機械で測定する方式が2種類と、毎日どの時間帯にどの番組を見たかを手で記録してもらう方式があるそうです。
そして、各地域ごとにこちらに書かれた人数の参加世帯がいるとのこと。

最も大きな調査地区が、関東地区(※東京だけではない)の900世帯です。(表だと600になっている気がしますが…。)
札幌、宮城、福岡あたりもかなりの大都市を抱えていますが、それぞれ200世帯だけです。

視聴率の「誤差」

さきほどの日テレのサイト 視聴率には誤差がある!? | テレビCM検討編 | 日テレ 広告ガイド のほか、視聴率調査を行っているビデオリサーチ社のサイト 視聴率をご覧いただくときの注意事項 | 週間高世帯視聴率番組10 にも書かれていますが、 視聴率の測定には誤差が伴います。

上記サイトの表を見ると分かりますが、例えば関東地区限定の調査であれば、「視聴率10%」と測定されたとき、本当は8%以下や12%以上だった可能性が5%ほどあります。
地方のローカル番組であれば200世帯の調査のこともあるはずなので、そうすると「視聴率10%」は本当は5.8%以下や14.2%以上の可能性が5%ほどです。

ただし、上の計算はあくまで「1回あたりの視聴率が10%だった」ときの話です。1クールを13回の放送としてその平均視聴率をとれば誤差は13の平方根で割った値、すなわち約3.6分の1になります。2クールなら約5分の1です。
地方ローカル番組でも「2クールの平均視聴率10%」はほぼ9%から11%の間に収まります。

ラジオの聴取率と最先端の取り組み

テレビの視聴率の測定に、手作業での記録方式もあると書きました。ラジオは機械測定はされていなくて、測定習慣にやはり手作業で日記をつけてもらう方式で聴取率を測定しているそうです。 ラジオ個人聴取率調査 | コーポレートサイト || コーポレートサイト

今やネットラジオも広まりました。そんな中で、 首都圏ラジオ聴取データ × radikoデータ~推計によるラジオ聴取データの365日化へ~ | ニュース || コーポレートサイト 今の方式ではなく、radiko の聴取データと手作業での日記とを組み合わせた方式での聴取率の計算を準備しているとの発表がありました。
機械学習を使って、radikoユーザーだけが測定対象になることのバイアスを除去するということでしょうか。

感想

毎年視聴率ランキングを目にするわりに、視聴率がどのくらいの規模で計算されるかといったことは考えたことがありませんでした。関東地区でも900人というのは、かなり少ないという印象です。
「○○の瞬間、12.3%!!」みたいに扱われますが、0.1%刻みのランキングは真実を映し出してないかもしれませんね。

テレビと同様、ラジオにとっても聴取率が生命線でしょう。それが通年で測定されていないというのも意外でしたが、たしかに測定が大変だったというのも分かります。大事な指標が機械学習の予測値で良いのかという疑問もありますが、通年で測定できるようになるのは意義が大きそうです。

参考, 利用

【統計 小ネタ】チャーノフの顔グラフ

先日、統計検定の準1級を受けてきました。

結果の良し悪しは別として、勉強するなかで面白い話をいくつか拾ったので少しずつ紹介していきます。

今回はチャーノフの顔グラフについて

データをグラフ化する方法はいくつかあります。よく使われるのが棒グラフや折れ線グラフ、散布図などです。 ただ、面白いことを考える偉人もいたようで、データを顔の絵にすることで違いがわかりやすいのではないかと。

なるほど??

チャーノフの顔グラフ 概要

チャーノフの顔グラフは、Herman Chernoffさんが発表したデータの可視化の方法。恐らく発表論文は これ http://The use of faces to represent points in k-dimensional space graphically (中身は読んでません)。Wikipediaのこの方のページによるとまだご存命のよう。

人間は表情のちょっとした変化に敏感なので、データの可視化に表情を使えば良いのではという発想のよう。なるほど、ちょっと笑っただけでも人間すぐにバレてしまうしアイデアには納得。

論文としては、データ(数値)を顔の絵にするための方法も楕円とかを組み合わせるルールを定義している。(そうしないと客観評価もできないから当然か。) このときは最大18次元のデータを扱えるようにしたらしい。 世の中の実装はそのルールに必ずしも従っていないようだが、概要は同じ。

試してみる

顔グラフの絵は検索すればたくさん出てくるが、使ってみてどうなのかを知りたかったのでデータを作って試した。 なお、顔グラフ表現の実装は下記のものを使わせて頂いた。 aoki2.si.gunma-u.ac.jp

架空の学校での生徒のテスト結果を考える。表が生データ、顔の絵がそれぞれに対応するグラフ(国~社を1~5次元目に割り当て)だ。

f:id:wkwkhautbois:20190623220428p:plain
可視化対象データ(テスト結果)
f:id:wkwkhautbois:20190623220654p:plain
顔グラフ

どうだろうか。

比較用にレーダーチャートも作成した。こちらは下記記事の実装を使わせて頂いた。

qiita.com

f:id:wkwkhautbois:20190623220918p:plain
レーダーチャート

感想

まぁ確かに顔グラフではそれぞれ違うのは分かる。
一方で、何がどのくらい違うのかはさっぱりだ…

レーダーチャートは数値で示されるし、今回の場合はチャート内の面積も「全体的な成績」として意味を持つので、顔グラフより見やすくて情報も多く優れているという感想だ。

10次元くらいになるとレーダーチャートでは見るのも大変になるので、その時に顔グラフの出番になる…だろうか。今どきなら3Dモデルでリアルな顔をグラフとして使うこともできるだろうから、もしかしたら今後機会がある、かもしれない。

参考, 利用