プログラミング漫遊記

思ったことや、勉強したことをつらつらと。

初めてのLT会 vo.9に登壇しました。

10月9日にフィヨルドブートキャンプ内で行われたLT会に登壇しましたので、重い腰をあげて今更ブログにしていきます。テーマは「しくじり」ということで自分が過去しくじった体験を元に発表していきました。 以下は自分の発表スライドです。

speakerdeck.com

他の登壇者の内容やスライドに関してはタマキさんのこの記事がとても詳しく書かれているので参考にしてください。

shirotamaki.hatenablog.com

内容に関する記事というよりは登壇して、内容を考えて、発表してといった流れの中で自分がどんなことを考えて作ったのかという記事です。というか日記です。

心境をつらつら、たらたらと綴っていきます。ね。

登壇するかどうか問題

人前で自分のことを話すのはけっこう勇気がいる。そして、「しくじり」はできるなら言いたくない。なぜなら顔から火がでるほど恥ずかしいからだ。でも、そういったしくじりにこそ学びが詰まっているし、伝えるならそういったものじゃないといけない気がする。考えやすいテーマではあるんだけど、その点ではちょっと迷った。僕の場合は「孤学(ぼっち学習)」だったという自分のしくじりから、コミュニティと繋がりをもった「独学」に変えていこう。コミュニティに参加していろんな人との繋がりをもとう。ということを4月から継続して挑戦してきたので、この登壇自体がまさにしくじりに対する挑戦になると思って、勇気を持って登壇した。また、人とのコミュケーションは自己開示が大きいと思ってるのでそういう理由もある。

そのほかに迷った理由は、単純にコロナのワクチン接種を登壇日の近くに入れていたこと。最終的にはワクチン注射の日程はずらした。これは大正解でワクチン接種後4、5日寝込む羽目になった。

タイトルを決める

割と何も考えずタイトルを報告してしまった。というしくじりがある。

長い間学習を休んでいて、4月から復帰した。4月からは学習に対しても色々工夫をしたのでその部分を抽象化すると「学びを学ぶ」というメタ認知っぽい結論に至った。ただ、現実問題5分という時間制約がある中で工夫したこと全部を言えるわけではなく、取捨選択していくうちに「コミュニティ参加」の部分だけが残った。タイトルとのずれが発生。これは次登壇するときの反省にしたい。

内容を決める

1週間くらい前から1日1時間をLT会準備に当てた。

ノートに伝えたいことを箇条書きして、線で繋げていく。授業なら発問から組み立てていってそこで「おやっ」と思うようなフックポイントを作っていくのだけど、インタラクティブなコミュニケーションができないので思考のフックポイントをどこに作るか悩んだ。 ちなみにharuguchiというハンドルネームは本名ではないというフックポイントを序盤で作ったけど、思った以上に驚かれてしまい、内容が入ってこなかった人もいるようで失敗だった。もっと軽いポイントを作るべきだった。

 スライドを作る

授業を作るときと同じ流れで作ってみた。この作業からはほとんど独り言に近い呪文をみたいなにかを唱えながら作る。人に聞かせられる作業ではない。

  1. 内容は一旦スライドに全部テキスト情報として書く
  2. スライドの内容を話してみる
  3. 違和感のあるところを削る
  4. 情報の軽重をを考え、軽の部分は全削除
  5. 削除した内容は「話」で置き換えるか「図・イラスト」で置き換えるか、「単純に削るか」を考える
  6. 1から繰り返す

<しくじりポイント>
スライドに乗せる情報をできるだけ少なくするのを心がけた。ここまではいい。その分テンポよくスライドを流していき、情報量が多い部分は図やイラストで置き換えるようにした。これが失敗。というのも、今回のLT会はチャットする場所と発表する場所が違っており、ディスプレイが1枚の人は画面を切り替えてチャットするから、意外とスライドをじっくり見れていなかったのではと思う。なので、今回は「話す」という聴覚情報をメインにして「図やイラスト」という視覚情報をサブにしたほうが良かったかもな。

発表する

不特定多数の人前で話す機会が多いので、緊張しないだろうと思っていたけど緊張はした。ただ、慣れの部分も大きいのでこれは何度も挑戦していくしかない。時間がかつかつで話の間が取れなかったのが少し残念。

登壇後

次挑戦するハードルが下がった。やっぱり1回やるのとやらないのでは天と地ほどの差があることを実感。次は外部のLT会などにも挑戦していきたい。

感想

しくじらないと見えてこない世界がある。挑戦したら大なり小なり何かしら必ずしくじると思うので、しくじりは勲章みたいだなと思った。

そういう意味では良いしくじりは挑戦した結果。ダメなしくじりは、やりたいという思いがあるのになにもしない後悔であることが多いと思う。

この記事を書くのにかなり時間がかかっているが、これはLT会で発表した後すぐに感想を書かなかったという「何もしなかった」しくじりなので、ダメなしくじりだということは示しておきたい。

フィヨルドブートキャンプ8・9月の学習ふり返り

この記事はフィヨルドブートキャンプで学習しているかわせさんの記事に触発され、自分も学習の成長を感じられるようにふり返りたいな〜という願望から書いた記事でございます。

kawase-k.hatenablog.com

タイトルの感じからパクらせて真似させてもらっていますが、あの素敵な絵だけは真似できないのでみなさんぜひ読んでください。内容も素敵です。

8月のふりかえり

個人的な話。7月は引っ越しでバタバタしていたのですが、8月になってようやく落ち着いてきました。学習時間もおおよそ満足できるくらいになってきて、生活リズムも安定し、フィヨルド内のいろんなコミュニティに参加できるようになったのもこの頃から。

学習時間と内容

フィヨルド内での日報を書く時間・ブログを書く時間なども学習時間に含めています。何でもかんでも学習時間に入れて自分をほめていくスタイル。

やったこと 細かい内容 おおよその時間
JavaScriptの基本的な学習 Webサイトjsprimer,書籍『初めてのJavaScript』,FizzBuzzプログラム, カレンダープログラム 15h
非同期処理 YouTubeの動画で学習 8h
メモアプリ コマンドラインインターフェースで動くメモアプリの作成。 45h
npm作成 4x4のナンバープレース数独)生成npmを作った 12h
オブジェクト指向 書籍『オブジェクト指向でなぜつくるのか』、輪読会参加 10h
Ruby 書籍『Ruby超入門』の輪読会 11h
Railsの復習 書籍『Ruby on Rails 5 速習実践ガイド』 25h
ブログ このブログを始めた 5h
日報 フィヨルドブートキャンプでの日々の学習の記録 25h

最終的な学習時間は160hくらいになりました。日報にかなりの時間を使っていることが判明。

8月はJavaScriptの学習がメインでした。Rubyに続く2つ目の言語ということもあって、文法の差異や非同期処理など難しいところが多く、戸惑いながらの学習でした。しかし、今振り返ってみると違う言語を学習することでRubyについての理解も深まったので良かったです。

ラクティスでいうとメモアプリのCLI版を作るのはなかなか辛かった、、、。 記事にもしています。

haruguchi-yuma.hatenablog.com

enquirerなどのnpmの使い方がわからずかなりの時間を調べ物に費やしていた気がします。クラス化することに関してはオブジェクト指向(Ruby)のプラクティスである程できる状態になったのでJavaScriptでも同じ考えで作ることができました。

逆にnpmを作っている時間はとても楽しく「気づけば3時間経っていた」みたいなことも多かったです。テーマは「人の役には立たないが自分が欲しいものを作る」です。npmを公開したときはなんだかプログラマーの一歩目を踏み出したかのような感動がありました。

www.npmjs.com

8月の新たな取り組み

8月はいろんなことに挑戦した気がします。

  • 輪読会に参加
  • 仕事を辞めて以来のミートアップに参加
  • ブログを再開
  • 動画教材を使用してみた

輪読会に参加

Ruby本2冊(『Ruby超入門』と『プロを目指す人のためのRuby入門』)よみんなで読んでいく輪読会に参加しました。 それまで、『パーフェクトRuby on Rails』には参加したことがあったのですが、最初数回ほど行ってからフィヨルドブートキャンプ自体に参加できなくなってしまい断念。7月から『オブジェクト指向でなぜつくるのか』の輪読会に参加して、少しオンラインでのコミュニケーションに慣れてきたので思い切って参加してみました。

結果的には参加して良かったです。Rubyの知識がつく以外にもメンバーとの交流が楽しく、やっとオンラインコミュニティー慣れできるようになった気がします。みんなでワイワイ学習する雰囲気があり、夕方まで猛勉強して疲れた頭をリフレッシュさせるいい機会になっています。

仕事を辞めて以来のミートアアップに参加

ミートアップとはフィヨルドブートキャンプ内で行われる毎月1回のオンラインの交流会で、受講生・卒業生・メンターの方とご飯を食べながら実際に交流できる機会になります。卒業される方の作った自作サービスのデモがあったり、質問コーナーがあったり、フリートークのコーナーがあります。

昔、数回参加したことがあったのですがオンラインでコミュニケーションをとる難しさや恥ずかしさからしばらく参加していませんでした。輪読会に参加したことで少し顔見知り?(声見知り?)が増え、参加するハードルが下がったので思い切って参加してみました。話してみるとみんな「最初は緊張した」たとか「フリートークになったら接続切ってました」みたいな人もいて、自分だけじゃなかったんだと安心しました。

ブログを再開

過去に、似たようなふり返りブログは書いていたのですが定期的に継続することができずお蔵入りにし、8月から心機一転ブログタイトルを変更して始めてみました。これは、ミートキャンプでメンターさんが「ブログでなくていいけど、アウトプット大事だよ(意訳)」とおっしゃっていたので自分の書ける範囲で何か書き留めておこうと思い始めました。

ちなみにタイトルはスピッツのボーカルマサムネさんがやっているラジオ「ロック大陸漫遊記」からとりました。「プログラミング大陸漫遊記」にしたらよかった、、、

動画教材を使用してみた

JavaScriptの非同期処理がよく理解できず苦戦していると他の受講生の日報でYouTubeの動画教材のリンクが張ってありました。僕はどちらかというと自分のタイミングで読み進められる書籍での学習が好きでしたが、藁をもすがる気持ちで動画教材を使用してみました。集中力が切れないように1.5倍速で効いていると話者の例え話がイメージしやすく導入として動画で学習するのもありだなという気持ちになりました。

のちにVue.jsでの学習でも動画を使っているのでこの時の発見が生きました。

9月のふりかえり

9月はかなり集中して学習することができました。学習時間にも表れています。比較的アウトプットしている時間が多く、気づいたら3、4時間経っていた。ということが多かったように思います。

学習時間と内容

やったこと 細かい内容 おおよその時間
Vue.jsの基本的な学習 YouTubeの動画で学習、書籍『Vue入門』、Todoアプリ作成 42h
Vue CLI YouTubeでの学習、コンポーネント理解、Vue CLIでSPAのメモアプリ作成 14h
アジャイル開発/スクラム 書籍『アジャイル開発の教本』『SCRUM BOOT CAMP THE BOOK』 12h
チーム開発(スクラム開発) 割り振ってもらったIssueに対してPRを出す 7h
競技プログラミング AtCoder 8h
Git 書籍『独習Git』 10h
オブジェクト指向 書籍『オブジェクト指向でなぜつくるのか』輪読会参加、『オブジェクト指向設計実践ガイド』 15h
Ruby 書籍『Ruby超入門』『プロを目指す人のためのRuby入門』の輪読会 16h
Railsの復習 書籍『Ruby on Rails 5 速習実践ガイド』輪読会、『独習Ruby on Rails 30h
ブログ このブログ 3h
日報 フィヨルドブートキャンプでの日々の学習の記録 22h

全然計算合いませんが最終的な学習時間は205hになりました。

9月の前半はVue.jsの学習でした。いつもの如く、意味わからん!ということからのスタートでしたが、苦しんだ割には60時間弱で終わっているので、苦しいなりにうまく調べながら学習できたように感じます。 Vue.jsの学習に関したは最初書籍で学習していたのですが、難しすぎて全部読むことができませんでした。途中から動画教材に切り替え、具体的なアプリケーションを作りながら学んでいったので抜けてる知識も多いです。

Vue CLIを使ってSPA(シングルページアプリケーション)のメモアプリを作るプラクティスでは、コンポーネントを使って見た目部分を部品化してくのですが、親コンポーネントと子コンポーネントでのデータの受け渡しに苦戦しました。ここら辺のプラクティスからGoogleデベロッパツールを使い始めて、期待した値が入っているかの確認が上手くなったような気がします。正直、デベロッパーツールの機能の一部しか使いこなせてないですが、確実にハマったところから抜け出すのが早くなった気がします。

9月の後半はチーム開発のプラクティスを進めました。実際の仕事のように誰かと一緒に開発するということでワクワクと不安が半分ずつの状態。でも、プラクティスも佳境に入ったようで嬉しかったです。この頃から、Git操作とRailsが怪しかったので書籍で復習し始めました。

9月の新たな取り組み

9月もコミュニテイを意識した取り組みが多かったです。

新らしく輪読会に参加

9月から新らしく『Ruby on Rails 5 速習実践ガイド(現場Rails)』の輪読会に参加しました。この輪読会はフィヨルドブートキャンプのやつはしさんが主催する輪読会で朝の9時からDiscord上で行われています。自分にとっては初めましての方も多く、最初は参加するのに勇気が入りましたが、暖かく迎え入れてもらって居心地良く参加することができました。ちょうどチーム開発のプラクティスに入りRailsの復習をしたいと思っていたのでよかったです。

LT会に応募

フィヨルドブートキャンプでは不定期でLT会が開催されています。LT会とはライトニングトークの略で、登壇者が自分の気づきや発見、学習したことなどを短い時間で話す発表会のことです。 フィヨルド内では趣味でBotをつくる人がいたり、外部の学習会などでLT会に参加される人がいたり、日々誰かしらが挑戦しているコミュニテイです。そんな挑戦を見ているうちに自分も何かしたいなぁと思い。LT会に登壇ことに決めました。前向きな挑戦は周りに伝播するのだなぁと改めて思いました。

LT会は10月なので楽しみです。

質問に答える

フィヨルドブートキャンプ内のQ&AやDiscord上での質問に積極的に答えていきました。最初は間違ったこと言ってたらどうしようかなという思いがあったのですが、自分も人に助けてもらい理解することができたので積極的に答えていきたいです。間違っていたらメンターさんに訂正してもらえるという安心もあるかもしれません。

競技プログラミングやってみた

AtCoderの問題に挑戦してみました。https://kenkoooo.com/atcoder/#/table/

A,B問題は数をこなしていくうちに慣れてきたのですが、C問題は解けたり解けなかったりという感じ。そして、解けないと何時間でも考えてしまう性格なので、早々に封印しました。中毒性がありそうで要注意です。 1日1問だけって止められたらいいんだけど、、、数学っぽくて楽しかったので時間があったらまたやってみたいです。

2ヶ月を振り返って

やっとチーム開発のプラクティスまで来たかーという気持ちと、ここからまだまだ長いぞーという気持ち。

7月ごろから徐々にコミュニティに加わるようになって学習が一段と楽しくなってきました。一人でコツコツ学習するのも好きなのですが、学習で辛くなった時に仲間がいるっていうのは思っているよりも心理的安全を感じます。

やりたいことはまだまだあるので、ちょっとずつ挑戦して行けたらいいなと思います。

【Ruby】二次元配列についての色々な操作を考えてみた#2(配列の合計値)

こんにちは!はるぐちです。フィヨルドブートキャンプで学習中です。 この記事は二次元配列シリーズの第2弾で、二次元配列の合計値を計算することについて考えていきます。

前回の記事はこちら。

haruguchi-yuma.hatenablog.com

2.二次元配列の合計値を計算する

こんな二次元配列を用意します。

scores = [ [10, 20, 30 ] , [40, 50, 60], [70, 80, 90] ]

この配列全体の合計値を取得します。期待される値は10+20+…+90=450です。

結論

前回と同様、2パターン考えました。

  1. 配列の要素(内側の配列)を取り出しれぞれの合計値を出し、最後にそれらを足し合わせるパターン
  2. 配列を平坦化し、合計を出すパターン

以下がそのコードになります。

 scores.sum(&:sum)
#=> 450

scores.flatten.sum
#=> 450

解説

パターン1

上記の書き方は下の書き方の省略形になります。 下の書き方を例にどういった処理が行われているか確認していきましょう!

scores.sum{ |score| score.sum }

ブロック変数のスコアに対してsumメソッドを呼び出しています。 tapメソッドを使ってブロック変数scoreに何が入っているか確認します。

scores.sum{ |score| score.tap{ |o| p o }.sum } 
#=> [10, 20, 30]
#=> [40, 50, 60]
#=> [70, 80, 90]

ブロック変数scoreには[10, 20, 30]…などの内側の配列がブロック変数に入ってるのでそれぞれに対してsumメソッドで合計値を出しています。

scores.sum{ |score|  score.sum } 
# ブロックの中での処理のイメージ
[10, 20, 30].sum #=> 60
[40, 50, 60].sum #=> 150
[70, 80, 90].sum #=> 240

# 外側のsumの処理のイメージ
[ 60, 150, 240].sum #=> 450

パターン2

これは単純です。 flattenメソッドで配列のネストを無くします。

scores.flatten
#=> [10, 20, 30, 40, 50, 60, 70, 80, 90]

そこにsumメソッドで合計値を取得します。

るりまにはflattenの方が高速だと書いてあるので、速度を気にするならパターン2の方かもしれませんね。 参考:https://docs.ruby-lang.org/ja/latest/method/Array/i/sum.html

個人的にはsumメソッドにブロックを渡せるのが意外でした。 番外編ですが、sumメソッドにブロックを渡すと各要素の積の和を求めることもできます。

番外編 積の和

こんな配列を考える

nums_ary = [ [1, 2], [3, 4], [5, 6]]
# 各要素の積を足し合わせる

nums_ary.sum{ |nums| nums.inject(:*) }
#=> 44

# イメージはこんな感じ
# 1 * 2 = 2
# 3 * 4 = 12 
# 5 * 6 = 30
# 2 + 12 + 30 = 44

行列計算みたいですね。

つづくかも、、、

【Ruby】二次元配列についての色々な操作を考えてみた#1(最大文字数取得)

こんにちは。はるぐちです。フィヨルドブートキャンプで学習中です。 今回は二次元配列について考えてみました。 普通の配列については以前こんな記事を書いたので参考にしてください。

haruguchi-yuma.hatenablog.com

二次元配列って?

二次元配列とは配列の中に入れ子になって配列がある配列(何言ってるかよくわからん)です。ネストの深さによっては「多次元配列」や「多重配列」と言ったりもしますが正式な名前がなんなのかは知りません。教えてください。

たとえばこんな感じ。

# 二次元配列
[ [  ,  ], [  ,  ], [  ,  ,  ] ]

ネストが深くなればなるほど自分が今どんな操作をやっているのかわからなくなってくるので難しいですよね。 この二次元配列についていろんな操作を考えてみたいと思います。 書き出してみたら思いのほか長くなったので、何回かに分けて記事にしたいと思います。記事稼ぎです。

1.配列の中の文字列に対して最大の文字数を取得する

こんな二次元配列を用意します。

word_groups = [
  ["monkey", "gorilla", "orangutan"],
  ["hawk", "woodpecker", "goose"],
  ["dlphin", "shark", "haruguchi"]
]

この中から最大の文字数を取得します。期待される結果はwoodpeckerの文字数で10です!

結論

まずは結論から。アプローチを2つ考えました。

  1. ループを回しながら探していくパターン
  2. 配列を平坦化して考えるパターン
# ループを回しながら探すパターン
word_groups.map{ |words| words.map(&:size).max }.max #=> 10

### 配列を平坦化するパターン
word_groups.flatten.map(&:size).max #=> 10

解説

メソッドチェーンが多くてわかりにくいのでいくつかのステップに分けて考えていきます。

ループを回すパターンの方

word_groups.map{ |words| words }
#=> ["monkey", "gorilla", "orangutan"],
#=> ["hawk", "woodpecker", "goose"],
#=> ["dlphin", "shark", "haruguchi"]

1回目のmapでは配列の要素(内側の配列)を1つずつ取り出しています。この内側の配列に対してmapメソッドを使って要素の('monkey'とかの文字列)文字数を確認していきます。

word_groups.map{ |words| words.map(&:size) }
#=> [6, 7, 9]
#=> [4, 10, 5]
#=> [6, 5, 9]

これで各配列での文字数が取得できました。 次に、その配列に対して最大値をとってきます。最大値を返すメソッドはmaxメソッドです。maxメソッドの場所に注意します。

word_groups.map{ |words| words.map(&:size).max }
#=> [9, 10, 9]

できました。 次に、内側の配列に対して最大値を取得したいので、maxmapの内側に記述します。 これでそれぞれの配列での最大文字数が取得できました。 あとはその中からさらに最大値をとってくるだけです。

word_groups.map{ |words| words.map(&:size).max }.max
#=> 10

慣れるまではイメージしづらいかも知れません、、、

配列を平坦化するパターン

こちらはもっとシンプルな考え方になります。 まずflattenメソッドを使って二次元配列のネストをとっぱらい、普通の配列に変換します。

word_proups.flatten
#=> ["monkey", "gorilla", "orangutan", "hawk", "woodpecker", "goose", "dlphin", "shark", "haruguchi"]

次に、文字列を文字数に変換します。

word_groups.flatten.map(&:size)
#=> [6, 7, 9, 4, 10, 5, 6, 5, 9]

それぞれの単語の文字数が出ました。そして、その中から最大値を取得すれば終わりです。

word_groups.flatten.map(&:size).max
#=> 10

ループを回すより考えやすかったと思います!

次回は値が入った二次元配列の合計値を計算するです。

【Node.js】CLI版のメモアプリを作って学んだ難しい課題への向き合い方

こんにちははるぐちです。フィヨルドブートキャンプ(以下フィヨルド)でメモアプリを作成したのですが、はっきりいって

めっちゃむずかしかった、、、

正確には「今回もちゃんと難しかった」という感想になるのですが、「何をどうすればいいのか?」というレベルで難しいと感じたのはRubyでlsコマンドを実装するとき以来だったのでびっくりしました。JavaScriptという言語に慣れていないというのも原因かもしれません。

しかし、今回に関しては「全く意味わからん」状態ながらも精神的には楽しんでできたので、その学びから難しい問題にどう立ち向かっていけばいいのか書ければいいなと思います。

注意:課題は提出しましたが、現時点ではレビューはいただいておりませんので技術的なことは書かないつもりです。なのでネタバレはありません。

注意:難しいと煽ってはいますが、実際はフィヨルドでは助け合いのコミュニティがありますので質問すれば丁寧に答えてくれますし、だいたいみんな楽しんで苦しんでいます(多分)!

対象者

  • プログラミングが難しい〜!ってなってる人
  • プログラミング難しすぎて夢に出てきたことがある人
  • プログラミングが難しすぎて晩御飯喉を通らなくなった人
  • フィヨルドブートキャンプって知ってるけど、カリキュラムどうなの?って思っている人

課題の位置付け

まずはどういうプラクティスなのか説明します。 フィヨルドではHTML・CSSからプラクティスが始まり、今回のメモアプリは後半のプラクティスであるJavaScriptの課題「クラス構文について知ろう」というプラクティスの課題でした。メモアプリ自体はすでに作ったことがあって、1回目はSinatraを使ってメモをファイルに保存する形式、2回目は同じくSinatraで作るのですがメモをデータベースに保存する形式です。今回は言語がRubyからJavaScriptに変わって3回目のメモアプリ作成となります。DLI(コマンドラインインターフェース)版を作るのは初めてなのでいったい何をどうすればできるのかわからないところからの実装になりました。

ちなみに、プラクティスを順番にやっていくとこんな感じ。85%かぁ。(随分遠いところまで来たもんだ) 学習日数はかなりかなり遅い方なので参考にしないでください(途中7、8ヶ月ほどやっていない時期がありました。)

f:id:haruguchi_yuma:20210829155342p:plain
ラクティスの進捗状況

学習カリキュラムについては公開されていますので、https://bootcamp.fjord.jp/practicesを参考にしてください。

難しいに立ち向かう

1.難しいの解像度を上げる(わからないの言語化)

ここからが本題です。

難しい。」と、一言でいうのは簡単ですが、もっと解像度をあげなければ問題は解決しないと考えました。 ということで、事実ベースでわかることわからないことを書き出していきます。ここで個々の難易度は気にしません。思いつくままに書き出していきます。

【事実】

  • メモアプリはNode.jsを使って実装する←Node.jsの環境は整っている
  • 標準入力を受け取る←現段階で方法がわからない <調べる>
  • オプションを受け取る←一つ前のプラクティスでオプションの受け取り方は学習済み、つまりわかる(minimistを使う)
  • sqlite3を使う←よくわからない <調べる>
  • メモを選択できるようにする←わからない <調べる>
  • クラス構文を使ってクラス化する←構文自体は知っている
  • クラス設計←Rubyと同じ感じならできると思う

2.簡単なところから順番に調べていく

いきなり、アプリを完成させようとしても全体像が掴めていないことがほとんどなので、先ほど列挙したわからないことを1つ1つ地道に調べていきます。 難しいところから調べていくと心が折れるのでなるべく簡単(だと感じる)なところから手をつけていき、それでもわからないことがあれば、引き続き書き出していきます。ここで、おすすめなのは公式ドキュメントから順番に調べるということです。

僕は、最初はQiitaなどのわかりやすい記事を読んでわかったつもりになっていたのですが、これは遠回りだったように感じます。全体のうちの一部しか解説されていないことも多く、使い方があっているか間違っているか自分では判断がつきません。まずは公式ドキュメントなどをみて、そのライブラリでできることの全体像を入れてからQiitaなどの記事を見た方が「どうしてそういった書き方をしているのか?」など細かいことがわかると思います。だた、公式ドキュメントは難しくて理解できないこともあります。そこが一番辛かったかもしれない。

今回readlineenquirersqlite3などのモジュールを調べたのですが、ドキュメントが英語だったのでとても時間がかかりました。とはいえ今はDeepLなどの優れた翻訳があるので時間はかかりましたが力になったように思います。

  • 標準入力を受け取る ←readlineというモジュールを使えばいいとわかった
    • readlineのドキュメントを調べる
      • <具体的な使い方>hogeがわかった
      • <具体的な使い方>fooがわかった
      • <具体的な使い方>barはよくわからん ←<調べる>

3.それでもわからなければ、基礎・基本に戻る(戻ることを恐れない)

先ほどさらっと公式ドキュメントを読めばいいと書きましたが、実際は公式ドキュメントが全然読めませんでした。 じゃあサンプルコードだ!「ん?何やってるか全然わからん!」

あるあるです。

読めないし、書けないということはそもそもJavaScriptについての基本的な文法が理解できてないのだと思い、基本的な構文を解説しているサイトや書籍で学習するところまで戻っていきました。 どの力が不足して公式ドキュメントが読めないか分かればその部分だけ学習しなおせばいいのですが、僕の場合はわからなかったので一通り学習しました。結果的によかったと感じています。

4.「分かった」から「できる」へ(小さく実験する・条件を変えて試す)

公式ドキュメントが読めるようになって「分かった」の状態になったら、実際に手を動かして「できる」の状態にします。どちらかというと公式ドキュメントを読みながら手を動かすのでほぼ同時進行かもしれませんが、実際に手を動かさないとできるようにはならないのでここはとても大事なところだと思います。

また、小さく実験するというのがポイントだと思います。

FuzzBuzz問題で例えると、いきなり「3で割り切れる場合」と「5で割り切れる場合」と「15で割り切れる場合」を考えるのではなく、まずは「3で割り切れる場合」だけを考えよう。と言った具合に小さく動かしていき、それがクリアできたら「5で割り切れる場合」を考えようとステップアップしていくのがいいと思います。

もう一つのポイントは条件を変えて試すということです。

これまたFizzBuzz問題で例えると、「3で割り切れる場合」という条件を「7で割り切れる」場合に変えたり、3つの条件から4つの条件にしたときにプログラムが自分の意図する挙動になっているか確かめるということです。条件を変えて色々試すことで本当に理解できているかの確認になりました。

5.あとはひたすら繰り返し

あとは1~4を繰り返しながら進めていきます。 進めていく中でどうしても理解できない、わからないところは友達・メンターなどに質問するといいです。

フィヨルドブートキャンプではその他に、Q&AやDiscordなどでわからねぇ!と叫べるコーナがありおすすめです。(宣伝)

以上、メモアプリを通して学んだ難しい問題への立ち向かい方でした。

【Ruby】ハッシュを使って条件分岐を減らそう!

こんにちは「はるぐち」です。フィヨルドブートキャンプで学習しています。 今回はある値によってたくさんの条件分岐をしたいとき、ハッシュを使うとシンプルになることを学んだので忘備録として記述しておきたいと思います。

想定

果物がたくさん入った配列があります(たくさんとは)。この中からランダムに1つ取り出したとき、値段が返ってくるブログラムを考えます。

仮にpriceメソッドとでも名付けましょう。 以下のような出力を期待します。(果物の値段は勘で決めました)

fruits = ['apple', 'banana', 'melon', 'pineapple']

price(fruits.sample) # ランダムに1つ選ぶ
#=> apple: 120円
#=>とか
#=> banana: 60円
#=>とか
#=> melon: 3000円
#=>とか
#=> pineapple: 800円
#=> となる

if文を使う場合

まずはif文*1で書いていきます。 elsifでの条件分岐が多いので読みにくい感じがします。

fruits = ['apple', 'banana', 'melon', 'pineapple']

def price(fruit)
  price = 
    if fruit == 'apple'
      120
    elsif fruit == 'banana'
      60
    elsif fruit == 'melon'
      3000
    elsif fruit == 'pineapple'
      800
    end
  puts "#{fruit}: #{price}"
end

price(fruit.sample)

果物が増えたとき、elsif fruit == 果物 値段と記述しないといけないためかなり面倒です。 そして何回も書くfruit ==が結構しんどい。あーなくしたいなぁ〜。

case文を使う場合

特定の値による条件分岐が多い場合はcase文*2を使うことも多いと思います。

fruits = ['apple', 'banana', 'melon', 'pineapple']

def price(fruit)
  price =
    case fruit
    when 'apple'
      120
    when 'banana'
      60
    when 'melon'
      3000
    when 'pineapple'
      800
    end
  puts "#{fruit}: #{price}"
end

price(fruits.sample)

if文のときと比べると、fruit ==の部分がないので少しだけ、本当に少しだけスッキリはしました。 また、値段を戻り値とするだけの処理なのでthenを使って1行で記述してもいいような気がします。

fruits = ['apple', 'banana', 'melon', 'pineapple']

def price(fruit)
  price =
    case fruit # thenを使って1行で記述
    when 'apple' then 120
    when 'banana' then 60
    when 'melon' then 3000
    when 'pineapple' then 800
    end
  puts "#{fruit}: #{price}"
end

price(fruits.sample)

ただ、この場合も果物が増えるごとにwhen 果物 then 値段という文を増やさないといけません。

そこで、ハッシュを使ってみます。

ハッシュを使う場合

ハッシュを使うと条件分岐が消え、果物を追加するときも楽に追加することができます。 つまり、管理も簡単ということです。

fruits = ['apple', 'banana', 'melon', 'pineapple']

def price(fruit)
  price = 
  {
    'apple' => 120,
    'banana' => 60,
    'melon' => 3000,
    'pineapple' => 800
  }[fruit]
  puts "#{fruit}: #{price}"
end

price(fruits.sample)

引数として受け取った果物がハッシュのキーとなって値段を返しています。 条件分岐が消えてシンプルで見やすくなりましたし、果物を追加するのも簡単です。

また果物と値段のhashを使い回すときは定数として定義しておくのもいいかも知れません。

fruits = ['apple', 'banana', 'melon', 'pineapple']

FRUITS_TABLE = {
  'apple' => 120,
  'banana' => 60,
  'melon' => 3000,
  'pineapple' => 800
}

def price(fruit)
  price = FRUITS_TABLE[fruit]
  puts "#{fruit}: #{price}"
end

price(fruits.sample)

まとめ

  • ハッシュを使ったら条件分岐をなくすことができる。
  • 条件の変更や条件そのものを増やしたり減らしたりすることも簡単!

つまり、ハッシュすごい!

もっといい方法があればぜひ教えてください。

*1:正確にはif式ですがここではif文で統一しています。そのほかも同じ扱いです。

*2:*1に同じく

【Ruby】ボウリングプログラムで気づいたeach_with_objectの便利さ!

フィヨルドブートキャンプではプラクティスとしてボウリングのスコア計算プログラムを作成します。提出物に合格をもらった後、他の受講生のコードを読んでいて初めて知ったメソッドにeach_with_objectというメソッドがあります。これはめちゃくちゃ便利じゃね?(自分が知らなかっただけ)と思った次第ですので、忘備録として、また学習ノートとしてeach_with_objectの使い方を記しておきたいと思います。フィヨルド生には若干のネタバレにはなるかもしれませんが、あんまり影響しないよう断片的なコードにしています。

ボウリングのスコア計算プログラムとは

実行例は以下の通りターミナルでコマンドラインの引数としてカンマ区切りのスコアを渡すと得点が出力されます。

$ ./bowling.rb '6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5'
139

上記でストライクは'X'として表されています。またスペアは3,7などの数字で合計10になるときです。 また、ボウリングはスコアの計算方法が改正されていますが、今回は現行のカレントフレームスコア方式ではなく、旧のスコア計算方法で実装しています。

詳しくはコチラ:ボウリングの新スコア計算方法!カレントフレームスコアシステムで遊んでみたよ

自分が書いたコード

def convert_to_value(score)
  shots = []
  score.split(',').each do |shot|
    if shot == 'X' && shots.size < 18
      shots << 10 << 0
    elsif shot == 'X'
      shots << 10
    else
      shots << shot.to_i
    end
  end
  shots
end

上のコードで記述したメソッドは引数で'6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5'といった文字列のスコアを受け取る想定をしています。 カンマで区切られている数字やマークを数値に変換し、一つの配列として出力しています。そのとき最終フレーム以外のストライクのマークX10,0として処理し、最終フレームのストライクのマーク'X'は単に10としています。

実際に引数を渡してみると以下のようになります。

convert_to_value('6,3,9,0,0,3,8,2,7,3,X,9,1,8,0,X,6,4,5')
=>  [6, 3, 9, 0, 0, 3, 8, 2, 7, 3, 10, 0, 9, 1, 8, 0, 10, 0, 6, 4, 5]

each_with_indexを使って書くと

def convert_to_value(score)
  score.split(',').each_with_object([]) do |shot, shots|
    if shot == 'X' && shot.size < 18
      shots << 10 << 0
    elsif shot == 'X'
      shots << 10
    else
      shots << shot.to_i
    end
  end
end

さて、何が変わっているでしょうか

- shots = []
- score.split(',').each do |shot|

+ score.split(',').each_with_object([]) do |shot, shots|
  • 【変更前】空の配列を用意し、条件に合うものをその配列に突っ込んでいました。

  • 【変更後】each_with_objectを使ったことにより、引数に空の配列を渡すことで、ブロック変数の第二引数であるshotsにセットされます。

- shots
end

また【変更前】は最後にshotsを記述することで配列shotsを戻り値としていたのですが、【変更後】はeach_with_objectの戻り値がshotsなためコードがスッキリしました。

まとめ

空の配列(ハッシュ)を用意して、何らかの条件によって配列に入れていくような操作はeach_with_objectが使える。またメソッドの戻り値は引数のオブジェクトになる。

つまり、配列の用意と戻り値で2行ほどお得!(ちょっと俗っぽい言い方)

参考:https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_object.html