のらブログ

sadanoraが思ったことを書きます

るりまにリンク切れを発見したのでPRを送ってみた

この記事は「フィヨルドブートキャンプ Part 1 Advent Calendar 2023」21日目の記事です。 adventar.org

Part2はこちら adventar.org

昨日はPart1はYuki WatanabeさんのRails7 のフロントエンドライブラリ「Hotwire」を使ってみた感想と開発でお世話になったページをまとめました、Part2はumizaruさんのチェリー本の輪読会を終えてでした。

はじめに

ある日Rubyリファレンスマニュアル(るりま)を読んでいたところ、Kernel.#Integerのページ内にリンク切れを発見しました。

module Kernel (Ruby 3.2 リファレンスマニュアル)

FixnumとBignumのリンクが切れていてリンク先が404だった。
これはコントリビュートチャンスかも?ということで、るりまにPRを送ってみたのでPRを送るまでの流れを書きます。

Issueを立てる

前述の通りKernel.#Integerのページ内のFixnumとBignumのリンクが切れているのに気づいたので、次にこのリンク切れに関するIssueやPRが立っていないかるりまのリポジトリを確認しました。

みたところ該当するようなPRもIssueも無さそうだったので、自分でIssueを立てることにしました。

立てたIssue

Kernel.#IntegerのFixnumとBignumのリンクが切れている · Issue #2854 · rurema/doctree

過去のIssueとPRを参考にする

IssueとPRに目を通している中で、別ページのFixnumとBignumのリンク切れを修正しているPRをいくつか発見しました。

それらに目を通すことで、以下のようなことがわかり、とても参考になりました。

  1. FixnumとBignumはRuby3.2で削除されている
  2. 1が分かったことで、「Ruby3.1まではFixnumとBignumのリンクを表示し、Ruby3.2からは表示しない」という具体的な修正方法がわかる
  3. バージョンによって違う書き方をするやり方がわかる
    1. リファレンスマニュアルの書式はReferenceManualFormatDigestに載っていますが、@untilなどを使ってバージョンごとの説明を記述している実例が確認できてよかったです。

対象ファイルの修正と表示確認、PR作成

まず本家のリポジトリからフォークして、フォークしたリポジトリをクローンしたら、ブランチを切って対象ファイルの修正をします。

こんな感じでFixnumとBignumのリンクはRuby3.2未満の場合に表示するようにしました。

- 引数を整数([[c:Fixnum]],[[c:Bignum]])に変換した結果を返します。
+ 引数を整数
+ #@until 3.2
+ ([[c:Fixnum]],[[c:Bignum]])
+ #@end
+ に変換した結果を返します。

次にこの変更が意図した通りの表示になっているか確認したいですが、確認するためにはbitclustというgemが必要です。

ということでbitclustをインストールします。*1

$ gem install bitclust-core bitclust-dev refe2
$ bitclust setup

次にbitclustを使ってHTMLファイルを生成します。

自分が確認したいKernelモジュールのページは以下のようなコマンドで生成できました。

// Ruby3.1用のhtml
$ bitclust htmlfile ./refm/api/src/_builtin/Kernel --target=Kernel --ruby=3.1  > ファイル名
// Ruby3.2用のhtml
$ bitclust htmlfile ./refm/api/src/_builtin/Kernel --target=Kernel --ruby=3.2  > ファイル名

生成されたHTMLファイルをブラウザで開いて確認します。

Ruby3.1。FixnumとBignumのリンクが表示されている
Ruby3.2。リンクが表示されていない。

問題なさそうなので、pushしてフォークした自分のリポジトリから本家にPRを送りました。

作ったPR

Kernel.#IntegerのFixnumとBignumのリンク切れを修正した

まとめ

以前なら「るりまにPRを送るなんて...」と尻込みしていたと思いますが、9月のOSS Gateとフィヨルドブートキャンプのコラボ企画に参加しOSSにPRを送る経験ができたので、今回もやってみようかなと思えました。

今の所できたOSS活動はtypoやリンク切れの修正ですが、もっと色々チャレンジしていけたらなと思います。

感謝の参考

Rubyリファレンスマニュアルを修正する方法 - Eggshell

自分はほぼこの記事に倣って作業しただけです🙏

フォークからPR作成までの流れを画像付きで説明してくださっています。

明日のアドベントカレンダー

明日はhondaさん(Part1)、Yuukagoさん(Part2)です!

*1:Gemfileにbitclust-core、bitclust-dev、refe2が記載されていたので$ bundle installでも良さそう。

ギターの指板図をさっと作れるサービスGuitar Scale Sketchをリリースしました

ギターの指板図作成ツール「Guitar Scale Sketch」をリリースしました。

guitar-scale-sketch.com

自己紹介

フィヨルドブートキャンプ(以下FBC)でプログラミングを学習しているsadanoraです。 前職ではWeb制作会社でWebディレクターをしていましたが、「面白そう&業務に役立つ」という動機でプログラミングの学習をしているうちにプログラマを目指すようになりました。

好きな楽器はベースとピアノです。

Guitar Scale Sketchとは

Guitar Scale Sketchは、ギターの指板図を人に渡したり自分用に保存したい、ギターを弾く人向けの指板図作成ツールです。

指板の幅をきめてドットを打つだけで指板図を素早く作成できて、作った指板図はブラウザから印刷したり、URLをシェアして共有できます。

解決したい問題

  • デザインツールなどで綺麗な指板図を作るのが手間
    • Guitar Scale Sketchを使うことによって、指板の図を書き、抑えるポジションに印を付け、色を選択し、作った指板図を印刷用にレイアウトする、といった手間がなくなります。
  • ネットや書籍にある指板図で練習をしているけど、実は情報が多すぎる/少なすぎると感じている
    • 自分がいま練習したい情報に絞った指板図を簡単に作れます。

ギターの先生が「次までにこれを練習してきてね」と指板図を生徒に渡したいケースのような、「指板図をさっと書いて誰かに渡したい」という人には特に便利に使ってもらえるんじゃないかと思って開発しています。

使い方

  1. Googleアカウントでログイン
    • ログインしなくても使えます。ただしログインしないと指板図の保存ができません。
  2. 「指板図をつくる」画面で指板図を作成、保存
  3. 練習🎸
    • 自分で使う場合はそのままギターの練習をしましょう。
    • 誰かに渡したい、シェアしたい方はURLを相手に伝えましょう。紙で手渡したければブラウザから印刷もできます。

技術スタック

canvasの描画

ソーシャルログイン

テスティングフレームワーク

Linter/Formatter

CI / CD

インフラ

フロントエンドにHotwireを使ったRailsアプリです。指板図の描画はKonvaというライブラリを使ってcanvasで描画しています。

開発経緯

なぜこのサービスを作ることにしたか

FBCでは自作サービスを作るにあたり「自分で考えたサービスを作る」or「FBCで用意したサービス案から選んで作る」どちらかを選択できます。 自分の場合は後者で、FBCが用意したサービス案のリストから「ギターの指板図が簡単に作れるサービス」を選びました。

最初は何か自分で考えたサービスを作ろうかといくつかアイディアを出したりしたものの、FBCのサービス案でみかけた「ギターの指板図が簡単に作れるサービス」について、ふとした時に考えていることが多いことに気づき、「自分は結構このサービス作りたいのかもしれない」ということでこのサービスを開発することを決めました。

もうすこし細かく説明すると、自分はギターはあまり弾いたことがないのですがピアノやベースといった楽器には学生時代に下手くそなりに触れていて、今も気晴らし程度にたまに触ります。 自作サービスのプラクティスに入った時期は、「スケールを覚えてジャズのアドリブとか自分で弾けるようになりたいな」と思っていた時期だったので、ギターのスケール練習のためのツールであるこのサービスが余計に気になったという感じです。

この「ギターの指板図が簡単に作れるサービス」はFBCのメンターのmachidaさんが欲しいサービスということで、ユーザーであるmachidaさんに色々とヒアリングしながら開発を進めていきました。

エレベーターピッチ

FBCのサービス案は最初から仮のエレベーターピッチが用意されているため、ゼロからエレベーターピッチを考える必要はありませんでした。

ただ、ギターの練習をしたことがない自分にはこのサービスによって何がどう便利になるのかいまひとつピンときていなかったので、ユーザーであるmachidaさんに色々とヒアリングし、それを踏まえてエレベーターピッチを練り直しました。 Web上には指板図作成サービスが色々とあるので、それらでは何が不満なのか、今回作るツールと何が違うのかを聞きました。

自分の理解が足りなくて同じような質問を何度かしてしまうこともありましたが、ユーザーが解決したい問題についてしっかり聞いておかないとブレたものを作ってしまいそうだったので、わからないことは繰り返し聞きました。

元々用意されていたエレベーターピッチ

[指板図ジェネレーター] というサービスは、
[ギターの指板図を書くのにお絵かきツールを使い自分でデザインをしなくてはいけない問題] を解決したい
[ギターを練習している人] 向けの、
[指板図作成ツール]です。
ユーザーは [用意されたブランクの指板上のポジションにドットを打つだけでスケールの指板図画像を作成、ダウンロードすること] ができ、
[イラレで作成するの] とは違って、
[自分でデザインする必要なく綺麗で見やすい指板図になる機能] が備わっている事が特徴です。

ヒアリング後

[指板図ジェネレーター] というサービスは、
[練習したい運指に最適化された指板図の画像を作成する際に、指板の図を書き、その指板の抑えるべきポジションに印を付け、色を選択、作った指板図を印刷用にレイアウトするという作業が発生する問題] を解決したい
[ギターの指板図を人に渡したり自分用に保存したい人] 向けの、
[指板図作成ツール]です。
ユーザーは [用意されたブランクの指板上のポジションにドットを打つだけで指板図画像を作成、ダウンロードすること] ができ、
[書籍やネット上にある指板図を参照したり、自分でデザインツールで作成したりするの] とは違って、
[いま反復練習したいスケール、運指に最適化された綺麗で見やすい指板図を素早く作成できる機能] が備わっている事が特徴です。

大変だったこと・工夫したこと

指板図の描画機能

指板図の描画機能はKonva、Hotwireなどを使って実装しました。初めて扱う技術ということもあってこれが難しく、開発時間の大半は指板図の描画機能に費やされました。

特にクリックイベントに応じて指板図にドットを追加、削除する処理は最初どう実装していいかわかりませんでしたが、処理の流れがイメージできない状態からタスクの粒度を細かくする(タスクバラシ)ことで少しずつ前に進んで行くことができました。開発を進めるにつれ、一度に複数の要件を扱って混乱するのを段々と避けるようになっていったと思います。

自作サービス以前のFBCの学習の進め方が「スクール側が用意したプラクティスの終了条件を達成して進めていく」ものだとすると、自作サービスは「自分で終了条件を考えてプラクティスを作って進めていく」ようなものかもなと開発中はよく思っていました。

フロントエンドの技術を途中で変える

フロントエンドの実装はHotwireを使っていますが、実は当初はTypeScriptとReactを使って進めていました。 TypeScriptとReactはいつか学習してみたいと思っていた興味がある技術だったため、自作サービスの機会に使ってみることに決め、自分で学習をすすめました。(当時これらはFBC内のプラクティスでは学ばない技術だった)*1

実際にモックなども作って技術検証を進めていたのですが、ちょっとしたことの実装でもかなり時間がかかってしてしまっていて、使いこなせるまでにはまだまだ時間がかかりそうなことがわかってきたところで色々と不安が押し寄せてきました。

  • このままだと息切れしてしまって自作サービスを作り切れないのではという不安
  • TypeScriptやReactの学習に想定以上に時間が取られてしまっている
    • どうしたら便利に使ってもらえるかとか、サービスにとってより重要な問題に割く時間を圧迫している
  • 想定していた自作サービスの開発期間を超えてきてしまっている
    • 開発の初期の時点で、当初考えていたスケジュールの期限がすでに迫ってきていた
      • 想定通りに進めるのは難しいとしても今後も同じペースで進んでいくなら厳しい
      • 無職なので、いつまでも開発しているわけにもいかない

こんな風に思っていたところで松本で開催されたRubyKaigi 2023に参加したのですが、そこで自作サービスでHotwireを選択したFBCの卒業生の話を聞く機会がありました。 これ以上TypeScriptとReactでつまづいているくらいならHotwireに切り替えるのもありかもしれないと思いいくつかチュートリアルなどをこなした結果、Hotwireがとても使いやすかったので移行することに決めました。

Hotwireと言っていますが、Rails7でデフォルトで有効なTurbo Driveこそそのまま有効にしているもののTurbo FramesTurbo Streams*2を意識して使っている箇所はなく、実際はJavaScriptフレームワークをStimulusに乗り換えたという感覚が近いです。

サーバーに画像を保存しないようにした

ユーザーが作成した指板図の情報(指板の数、幅、ドットの座標、色など)はDBにJSON形式で保存しており、詳細画面や編集画面ではそのJSONを元にKonvaで指板図を描画しています。

詳細画面では単にDBに保存しておいた画像を表示することも検討しましたが、JSONの方がストレージに保存する容量を節約できるメリットがあるためこのような構成をとっています。

画像を扱うのであれば学習する必要があったであろうActive Storageなどについて考える必要がなくなったこともよかったです。

名づけの難しさ

指板図はRailsのモデル名を当初Scoreとしましたが、最終的にはFingeringに変更しました。 Scoreというと楽譜のことですが、開発を進めるにつれ楽譜と言い切ってしまうには違和感がある名づけであることに無理が生じてきたためです。

英語のギターの教本でどんな表現がされているか調べたり、ギターの指板図に関連するライブラリをGitHubで検索したりとしましたが、自分のケースでそのまま使えそうな英語が見つけられなくてモデリングの仕方がおかしいんじゃないかと不安になりつつも、質問雑談タイム*3で何度か質問しつつ、今の形に落ち着きました。

質問雑談タイムは、チーム開発のプラクティス*4に入る前くらいまではラジオ参加(聞いてるだけ)が多かったのですが、自作サービスの開発中は生煮えの状態でも気になることがあったらなるべく質問や相談をするようにしていました。

とにかくやることが多い

当たり前ですがインフラからCSSまで全部自分で実装するのでやることの範囲が広く、こんなに色々やるのかと思いました。

  • 調べる
  • 試す
  • 決める
  • 実装する
  • 検証する

些細なことでも上記を自分で考えながら繰り返していくので、わからないことへの耐性が上がったと思います。

サービス名の決め方

自分で考えたり、Chat GPTに壁打ち相手になってもらったりして決めました。 ポイントとしては、あえてサービス名にScaleという単語を入れてギターのスケールに関係したツールっぽさを出したことです。

指板図作成ツールなのでスケールに限らずコードを書いて使うことも出来なくはないのですが、メインのターゲットとしてはスケールの練習をする人のためのツールなので、「スケールの練習のためのツールです」という雰囲気を出しました。

機能の検討

解決したい問題に対してユーザーが使えるものを提供できるのであれば、余計な機能をファーストリリースに盛り込まないようにしました。 指板図の並び替えやコピー、ユーザー名の編集など欲しい機能がいくつかありましたが、ファーストリリース前に開発する意味があるのか考えて不要と判断したものはどんどん削り、とにかくファーストリリースまで辿り着くことに集中しました。

Gitのコミットメッセージ

semanticコミットメッセージとgitmojiを試してみました。

Semantic Commit Messages · GitHub

gitmoji | An emoji guide for your commit messages

コミットログがemojiで賑やかなのは良いのですが、typeやemojiの使い分けが統一できていない、オレオレルールでしかないなど、自分には使いこなせなかったなあと思っています。 経験として一度試せたことはよかったです。

最後に

開発初期から中盤はなかなか進捗が出せず、本当にリリースできるのか...?と不安な時もありましたが、後半になるにつれ開発している時間がだんだんと楽しくなっていったと思います。 理由として思いつくものを挙げてみます。

  • やることが明確になり、かつ初見の技術の検証のような見積もりが難しいタスクが少なくなっていった
  • 「これから作るもの」より「作ったもの」の割合が増えてきてサービスの形がみえてきた
  • 開発開始当初は全く知らなかった技術も、知っていることが少しずつ増えてきた
  • 「知らないこと」「わからないこと」との付き合いに慣れてきた

FBCのメンターさんや受講生、卒業生のみなさんなど、色々なところでアドバイスいただいたり話を聞いてもらえたこともとても大きかったです。 一人でやっていたらリリースまで辿り着けたかわかりません。

ギターを弾く人の中でも割とニッチな要望に応えるツールだと思いますが、ピンときた方は是非使ってみてもらえると嬉しいです。

*1:現在はReactのプラクティスがある。

*2:リクエストに応じて、HTMLのカスタム要素で指定した特定箇所のDOMを置換してくれるTurboの機能。Turbo Framesは一箇所だけ置換できるのに対し、TurboStreamsは複数箇所を置換できる。 https://turbo.hotwired.dev/handbook/frames

*3:FBCで平日の夕方に開催されているイベント。メンターさんに質問できる。

*4:FBCの課題。自作サービスのひとつまえにやる。

はじめてのRubyKaigi

2023年5月11~13日まで松本で開催されたRubyKaigi 2023に参加してきました。 初めてのRubyKaigiはとても強烈な体験でした。

目次

自己紹介

フィヨルドブートキャンプ(以下FBC)でプログラミング学習をしているsadanoraです。

FBCには2020年8月から参加していて現在は自作サービスという最後の課題に取り組んでいます。

RubyKaigiは今年初参加。

事前イベント

RubyKaigiに行くなら少しでも楽しみたいので、以下の事前イベントに参加。

gmo.connpass.com hey.connpass.com

Shibuya.rbの感想Shibuya.rb RubyKaigi 2023 前夜祭にいってきた - sadanora's scrapbox

リアルなRubyコミュニティの雰囲気やRubyKaigi前の盛り上がりを感じられる、特に気になるセッションの目星がつけられる、顔見知りの人が増える等々いいこと尽くめだったのでRubyKaigi初参加者こそ事前イベントに参加した方がいいと思いました。

「Niceに過ごしてください」「MINASWAN」「わからないものを聞きたい」などなど、RubyKaigiへの心構えやお馴染みの言葉、Rubyコミュニティの雰囲気などを知る機会にもなりました。

Rubyists on rails

cookpad.connpass.com

今回行きの交通手段はcookpadさん主催のRubyists on railsに参加しました。

交通費無料の上にノベルティまで!かわいい

隣の方が英語話者だったら翻訳アプリ頼りだな、なんて思っていたものの、なんと隣はフィヨルドブートキャンプのアドバイザーのimaharuさんで、エンジニアのお仕事のことやアカウント名の由来を聞いたり、松本まで色々とお話できました。*1

松本についたら自分はコワーキングスペースで自作サービスの開発を進めようと思っていたのですが、imaharuさんが温泉に行くメンバーを募っていて楽しそうだったので参加させていただきました。蕎麦を食べたり温泉に行ったりと、0日目から松本観光を楽しみました。

フィヨブーハウス

FBCでは今年はフィヨブーハウスという企画をしていて、受講生がRubyKaigi中に泊まれるシェアハウスをなんと宿泊費無料で用意してくださりました! 0日目には前夜祭パーティがあって、FBC関係者と交流する機会もありました。

bootcamp.fjord.jp

RubyKaigi 2023に行ってみたいけどぼっちだと辛いし楽しみ方もわからなくて心配…

まさに自分はこれだったのですが、フィヨブーハウスのおかげで一緒にRubyKaigiを楽しむ仲間ができたことでそういった不安が全くなくなりました。

初参加のRubyKaigiは(オフラインで)初対面の人とめちゃくちゃ話すことになります。 とても楽しいことでしたが、普段家からあまり出ない自分はこれが結構負担でした。 念の為書くと、人と話すことが嫌だということではなくて、プログラミング学習だけしていると家からあまり出ない、オフラインで初対面の人と交流する機会が極端に少ない、という引きこもり生活を送っている自分には普段の生活とギャップがありすぎてMPが削られまくった感じです。

フィヨブーハウスの仲間とは雑談したり飲みに行ったり、セッションで出てきたコードの気になったところについて話し合ったり、FBCのプラクティスの質問をしたり、気軽にそういうことができたのが本当に心強かったです。

コードの向こうには人がいる

RubyKaigiに参加して一番強烈に感じたことを挙げるなら、この言葉の解像度がとても変わったことだと思います。

「コードの向こうには人がいる」という言葉は過去の角谷トーク*2にて繰り返し扱われていたので、言葉としては知っていました。

コードの向こうには人がいる
Fjorb Boot Camp as a Gate - Speaker Deck

RubyKaigi参加前のミートアップでもjune29さんから「コードの先に人がいるというか。こんな人たちが作っているんだなというのがわかるとまた色々変わると思います。」というような話をお聞きできたのですが、その時の自分はこの言葉の意味を全然理解できていなかったなと思います。

RubyKaigiのセッションは内容が高度で英語の発表も多く知らない言葉やわからないことの嵐で、聴くと言うより浴びるような感じでした。 理解できることは10%もない*3のに、モチベーションが爆上がりします。 そんなにもわからない話を聴いて何故モチベーションが上がるのかは、たぶん「コードの向こうに人がいる。」のを直に感じられたことが起点になっている気がしています。

「コードの向こうには人がいる。」はセッションに限らなくて、RubyKaigiの色々な場面でこの言葉が頭に浮かぶことが多かったです。

まとめ

RubyKaigiは本当に楽しかったです。

実はRubyKaigi 2023には参加しないつもりでした。 去年の津の盛り上がりを感じて今年は参加したいと思っていたものの、RubyKaigiに参加するのは就職してからだと思っていたし、FBCの卒業までもう少し時間がかかりそうだったので「今年も無理か〜」と思っていました。 そんな時にFBCの質問雑談タイムでmachidaさんから背中を押していただき、「これは行くしかないな」となった勢いで参加して本当によかったです。

なるべく来年の3月くらいにRubyKaigi参加を悩んでいるFBC受講生の参考になるようなことを書きたかったんですが、他にもほんとーに沢山のことがありすぎてとても書ききれないです。

一応書いておくと、色々な企業のエンジニアの人と話せるとか、ご飯の割引券3000円分もらえるとか、飲み会が無料だとか、素敵なノベルティ山ほどもらえるとか、音楽イベントが楽しいとか、そういうのも最高に手厚く豪華で全部すごかったです。

ラーメン屋に海外のRuby commiterが並んでいるとか、Chief Organizerの松田さんからオープニングパーティーで日本酒の説明をしてもらうとか、踊り狂ってるRubyistをみれたりとか、そういう体験も沢山できました。

単純に観光も楽しいです。

RubyKaigiのこの良さはなんなんだろう〜と最終日にぼんやり思っていたら、kakutaniさんのツイートを見かけました。

自分のFeelingが「無名の質」であったのかはわからないけれど、RubyKaigiに来なければわからない感覚がたしかにあったと思います。

沖縄まで精進して、来年はさらにNiceに過ごしたいです。

*1:ちなみにそれまでFBC内で交流したことはなくて完全初対面だったはずです

*2:FBCのイベント。kakutaniさんがベテラン視点からFBC受講生に向けて話をしてくれる素敵なイベント

*3:来年はもう少しわかることを増やしたい

vite_railsのnet::ERR_CONNECTION_REFUSEDを解消する

Railsvite_ruby(vite_rails)gemを試してみたところnet::ERR_CONNECTION_REFUSEDエラーに遭遇した。 エラーを解消するためにやったことを残しておきます。

環境

エラーの内容

$ foreman start -f Procfile.devでアプリを立ち上げてみたところ、Chromeの開発者ツールでコンソールにnet::ERR_CONNECTION_REFUSEDがわらわらと現れた...

やったこと・対処方法

エラーメッセージでググったところFailed to open TCP connection to localhost:3036 · ElMassimo/vite_ruby · Discussion #89を発見した。

localhostのデフォルトが::1(IPv6) のシステムだとこのエラーが発生するらしく、hostを明示的に構成すればOKとある。

ということでconfig/vite.jsonのdevelopmentにhostを明示したらコンソールからエラーが消えた。

  "development": {
    "autoBuild": true,
+   "host": "127.0.0.1",
    "publicOutputDir": "vite-dev",
    "port": 3036
  }

音読が良かった話

これは「フィヨルドブートキャンプ Part 1 Advent Calendar 2022」の2日目の記事です。

昨日はsiroemkさんの フィヨルドブートキャンプのチーム開発に参加した話でした。 adventar.org

Part2もあります。 adventar.org

目次

はじめに

フィヨルドブートキャンプ(以下FBC)でプログラミングを学習しているsadanoraです。 早いものでFBCに参加して2年以上たちましたが、今でもプログラミングの学習は楽しいなーと思って取り組んでいます。

ただ進捗が出ない時はどうしてもつらいものです。

特に思ったような進捗が出ず気持ちが焦っている時などは、技術書を読んでいても内容が入ってこず余計にしんどくなる、ということもあります。

自分は技術書や公式ドキュメントを読む時は黙読しつつメモ、みたいなスタイルで読むことが多かったのですが、音読を取り入れてみると初学者なりに良いことがあったのでブログにまとめてみようと思います。

当たり前すぎて今更声に出して読むのがなんなんだという感じもありますが、自分にとっては「読書法によってこんなに体験が違うんだな」という再発見をした気持ちです。

そういえば音読を試したことがなかったなという人に興味をもっていただけたら嬉しいです。

これまでの自分の読書

自分は技術書を読む時は大体黙読してきました。

ただ、気が散ってあまり読書が進まなかったり、難しい部分に時間がとられたりと、当初考えていたよりも読み終わるまで長い時間がかかってしまうことも多いなーといつしか感じるようになりました。

それなら読書方法を変えてみるかということで、音読を試してみることにしました。

音読のスタイル

難しいことは何もなくただ声に出して読むだけですが、自分なりに少し工夫してみたことがあります。

時間を決める

最初にこれから読むところに目を通して、長さや難しさに応じて適当に時間を決めます。 「30分で1章を読み切る」とか、この時間内でこれだけ読み切るということを先に決めてしまいます。

速度に緩急をつける

簡単だと思うところは早口で読んでいき、難しいと思うところは少しゆっくり読みます。

疑問や気持ちを声に出す

本を読んでいて感じた疑問やわかったことを声に出します。 「なるほど」「わからん」「これがこうなるからこうで...」「いや全然わからん」のような納得や疑問もどんどん声に出していきます。

一度に全部理解しようとしない

難しい技術書ほど理解しきれない部分は必ず出てくるはずですが、その場で全部を理解することよりも読み切ることを優先します。

「いま書いているプログラムと関係ありそうなのでここは読み直したい」という部分は一旦本の全体を通読した後に再読するようにします。

音読の良かったところ

音読してみて、黙読で感じていた問題はほとんど解決しました。

気が散らなくなった

音読によって、読書中に気が散るということはほとんどなくなり、決めた箇所までは一気に読み切ることができるようになりました。

本の内容を声に出しその声を自分の耳から聞く、ということを常に行っていることで、余計なことを考える余裕がないのが良いです。

黙読では別のことを調べ始めてしまい気づいたら30分経ってた...みたいなこともありましたが、音読では集中力がなくなってくるとそもそも読むことをやめるので集中のオンオフが明確になり、そういったこともなくなりました。

時間内に読み終わる

いつまでも同じ箇所に時間をかけることなくとにかく読み進めるので、本の通読まで計画の倍時間がかかるようなことはなくなりました。

再読したい部分は1度全体を読み終えた後にプラスで時間を取る必要がありますが、技術書はそもそも再読するものとして気にしていないです。

疑問を頭の中だけに残さずに済む

疑問や気持ちも声に出してみることが、思いのほか良かったです。

思ったことをそのまま声に出し続けるので、頭の中に余計なものを置いとかなくて済む感じが良いです。

まとめ

ということで音読についてでした🎄

ターミナルに🐣を降らせるnpmを作りました

こんにちは、FjordBootCamp(以下FBC)でプログラミングを勉強しているsadanoraです。

FBCに「npmを作る」という課題があり、その名の通り自分で考えて何かひとつnpmを作るプラクティスです。

自分はターミナルに🐣(ひよこ)を降らせるnpmを作ったので、npmの紹介と学びを書きます。

🐣が降ります

目次

作ったnpm

前述の通りターミナルにひよこが降ります。

-eオプションでひよこに限らず好きな文字を降らせることができます。

🍺が降る
圧倒的感謝も降る

使い方

  • npmが入っていればターミナルで$ npx hiyoko-rainで使えます。*1
  • -eオプションで好きな文字列を指定できます。
    • e.g.)
      • 🍺を降らせる
        • $ npx hiyoko-rain -e 🍺
      • 圧倒的感謝...!を降らせる
        • $ npx hiyoko-rain -e 圧倒的感謝...!
  • -iオプション(interval)で文字の落下する速さを変えられます。
    • デフォルトは150です。0に近づくほど速くなります。

npmサイト上のURL

hiyoko-rain - npm

使い方に書いたことと同じような説明が書いてあります。

なぜ作ったか

プログラミング学習やPC作業に疲れたときに和みたい

プログラミング学習に励んでいるとどうにもわからん、詰まった、という時はよく訪れるのでちょっと馬鹿馬鹿しく和むようなコマンドが欲しいと思いました。

他に検討した案

  • radikoの番組表を取得するnpm
  • IMDBから映画の情報を拾ってきて何かするnpm

などがありましたが、ボツにしました。

理由は費用や権利の考慮が面倒だったためです。*2

その結果、外部サービスに依存しない自分の書いたスクリプト内で完結するアイディアに絞ることにし、冗談みたいなアイディアだったひよこを降らせるnpmを作ってみることにしました。

工夫した点など

余計な機能はつけない

当初ひよこを降らせるだけではシンプルすぎるかなと思い、ポモドーロタイマー機能をつけようと思っていました。

しかしこのnpmの目的は「プログラミング学習やPC作業に疲れたときに和みたい」なのでポモドーロタイマー機能は余計な機能だと思い、途中でやめました。

文字が溢れないようにした

文字を降らせる処理は、配列に文字をプリントする行と列の情報をひたすら追加していくのですが、放っておくと要素が増えすぎてターミナルが文字で埋め尽くされます。

雨あられ

画面の下端に到達した要素は取り除くことで解決しました。

const run = (emoji, interval) => {
  let positions = []
  const startingLine = 3

  setInterval(() => {
    const [column, line] = process.stdout.getWindowSize()
    //要素を削除する位置
    const vanishingLine = line - 1
    const printingColumn = Math.floor(Math.random() * column)
    console.clear()

    positions.push([printingColumn, startingLine])
    // Array.prototype.filter()でvanishingLineに到達済みの要素を省いた新しい配列を作る
    positions = positions.filter(position => position[1] < vanishingLine)
    positions.forEach((position) => {
      ++position[1]
      process.stdout.write(`\x1b[${position[1]};${position[0]}H${emoji} \x1b[0;0H`)
    })
  }, interval)
}

元ネタ

このnpmには元ネタがあります。

ターミナルに文字を縦に降らせるってどうやって実装するんだ?と思い文字を縦に降らせる系のコード*3を色々ググっていたところ、ターミナルに🍣を降らせるシェルワンライナーが昔流行ったらしいという情報をみつけました。

Macのターミナル画面から寿司を降らせる至高のコマンドが話題 - KAI-YOU.net

Ruby

自分にも頑張れば読めそうということで、ここで紹介されているコードたちを読み解いてJavaSciptで実装し直すという方針が固まりました。

Rubyコミュニティの先達に感謝です🙏🙏🙏

まとめ

ちょっとしたスクリプトでも、「作るものを自分で考えてリリースする」という体験にたくさんの学びをもらいました。

良かったらターミナルに好きな文字を降らせて遊んでみてください🐣

*1:一応npmにnpxがプリインストールされるようになったのはnpm5.2.0以降みたいなので、npmが古い場合はnpmのアップデートが必要かもしれない

*2:APIが有料だったり、APIは存在するが公式に利用が許可されているわけではないっぽいなど

*3:マトリックスコードとか

【Ruby】uninitialized constant (NameError)にハマった

uninitialized constant (NameError)とは

"uninitialized constant"はそのまま日本語にすると「定義されていない定数」という意味になる。

呼び出されたクラスやメソッドが定義されていないことでエラーが発生しているということなので、何かしらの理由でクラスやメソッドの呼び出しが出来ていない。

エラーの出力例としてはこんな感じ

/Users/user/project/sample.rb:7:in `<module:LS>': uninitialized constant LS::Command (NameError)

  class ShortFormat < Command
                      ^^^^^^^
#--以下バックトレースが続くが省略--

この場合は「LS::Commandクラスが定義されてないので呼び出せない」ということになる。

解決方法

解決方法はエラーが発生しているクラスやメソッドが「なぜ呼び出せないのか」を特定して、呼び出せるようにする必要がある。

この「なぜ呼び出せないのか」が特定できず、ハマった。

「requireの相互参照」が原因だったのだけれど、"uninitialized constant (NameError)"とかでググってもエラーの原因としてrequireを挙げている情報を見つけられず*1、「requireの相互参照」という言葉も知らなかった(又は聞いたことはあったのかもしれないが思いつかなかった)ので途方にくれた。

requireの相互参照とは

2つのファイル間でお互いのファイル同士をrequireすること

たとえば以下のようにお互いがお互いをrequireしていること。*2

エラーの発生しない相互参照

foo.rb

require_relative 'bar'

class Foo
end

bar.rb

require_relative 'foo'

class Bar
end

irbでrequireしてみる。

$ irb
>> require_relative 'bar'
=> true
>> require_relative 'foo'
=> false

後に実行したrequire_relative 'foo'はfalseになっている。

るりまによると、

ライブラリのロードに成功した時には true を返し、ロードした feature の名前を(拡張子も含めて) 変数 $" に追加します。ただし、feature の名前が既に $" に含まれていた場合はロードせずに false を返します。

ということなので、2回目の場合にはすでにロードされているのでfalseが返っている。

Kernel.#require (Ruby 3.1 リファレンスマニュアル)

エラーの発生する相互参照の例

たとえば以下2つのファイルを作り、irbでrequireするとuninitialized constant (NameError)が発生する。

coke.rb

require_relative 'fanta'

module Soda
  class Coke
  end
end

fanta.rb

require_relative 'coke'

module Soda
  class Fanta < Coke
  end
end
$ irb
>> require_relative 'coke'
/Users/user/project/fanta.rb:4:in `<module:Soda>': uninitialized constant Soda::Coke (NameError)
                                                           
  class Fanta < Coke                                       
                ^^^^            
#--以下略--

エラーを回避するには

サンプルコードのような継承が必要な設計はたぶんおかしい。

設計を見直す。

「継承より委譲」

まとめ

このエラーに当たったのは、フィヨルドブートキャンプの課題のひとつ「lsコマンドを作る(オブジェクト指向版)」に取り組んでいるときでした。 モジュールや継承などについて理解が浅いことが重なり「どうにもならんーー」という感じになったのですが、メンターさんに質問したところ回答を得ることができました。

参考

TIPS/requireの相互参照 - やってよ!るby!! - atwiki(アットウィキ)

*1:なのでこのブログを書いている

*2:この記事のコードはすべてRuby3.1.1で検証しています