「プログラミング初心者に Rails を教えるコツ」を発表した

昨日は「表参道.rb #30」に参加して,発表をしてきた.カジュアルな雰囲気で,ディスカッションも多くとても良かった.

omotesandorb.connpass.com

資料

今日は「プログラミング初心者に Rails を教えるコツ」というタイトルにした.技術的な話ではないけど,副業で1年間講師をして感じたことをまとめた.プログラミング初心者に教えることは,もはやエンジニアリングとは別次元のスキルだなと思う.今後も「最高の教え方」を追求していきたい.

speakerdeck.com

Rails 5.2 Credentials

  • Rails 5.2 から秘匿情報を扱う Credentials 機能が出る
  • secrets はなくなるかも
  • 環境別に Credentials を管理できるように Gem を作成している
  • GitHub - sinsoku/rails-env-credentials

Rails 5.2 は全然キャッチアップできてなくて,Credentials の話も知らなかったので,勉強になった.実際に使ってみるとまだバグもあるらしく,正式リリースまでにはいろいろと修正が入りそうな感じだった.試してみるかぁー.

www.slideshare.net

Rails 製 BI ツール Blazer

Blazer は名前すら聞いたことがなかった.複数の BI ツールを知っておくと比較検討ができるし,メリットも大きいと思う.

speakerdeck.com

Ruby のトップレベルについておさらい

ライブコーディングは見てて非常に勉強になったし,vim の操作もすごかった.あと Ruby でバージョンごとに動作確認をするときには Wandbox をいうサービスを使っていると教えてもらった.スニペットを複数のバージョンで実行できるのは良さそう.

fast-ruby

サンプルコードもあって,Ruby 2.2 じゃなくてもすぐに確認できるようになっていた.これは非常に勉強になるので,自分でも読み進めてみたいと思う.

まとめ

Rubyist の集まるコミュニティは最高!今年は積極的に「表参道.rb」に参加するー.

関連記事

ariarijp.hatenablog.com

mkr plugin コマンドと mackerel-plugin-aws-ecs を試した

Mackerel で「ECS クラスタ」のメトリクスを取得する mackerel-plugin-aws-ecs を試した.ちなみに mackerel-plugin-aws-ecs を使うためには,去年11月にリリースされた「mkr プラグインインストーラー機能」も使う必要があり,この機能もまだキャッチアップできていなかったので合わせて試してみた.

mkr プラグインインストーラー機能

最初に「mkr プラグインインストーラー機能」をザッと紹介しておこうと思う.「mkr プラグインインストーラー機能」によって大きく変更されたことは,今までプラグインを一元管理していた mackerelio/mackerel-agent-plugins リポジトリに,今後新規のプラグインが入らなくなったことだと思う.今後は自分自身の GitHub リポジトリにプラグインを追加し,そのプラグインを「プラグインレジストリ」と呼ばれるリポジトリに登録することにより,幅広く活用してもらうことができる.なお,オレオレプラグインなど,限られたユースケースで使うような場合は,プラグインレジストリに登録する必要はなく,自分自身の GitHub リポジトリを参照して使うことができるけど,GitHub Releases の命名規則だけは合わせる必要がある.

github.com

他にも,Go 以外の好きな言語でプラグインを開発できるようになったりもしている.詳細な解説は以下の記事に載っている.

mackerel.io

mackerel-plugin-aws-ecs

プラグインレジストリの中に mackerel-plugin-aws-ecs がある.これは名前の通り ECS のメトリクスを取得するプラグインだけど,正確に言うと「ECS クラスタ」のメトリクスを取得する.「ECS コンテナインスタンス」や「ECS タスク」のメトリクスではないので,注意すること.さっそく試してみた.

github.com

インストール

mkr plugin install コマンドでインストールすることができる.基本的には最新版の GitHub Releases がインストールされるけど,特定のバージョンをインストールする場合は mkr plugin install mackerelio/mackerel-plugin-aws-ecs@v0.0.1 のように指定することもできる.また,プラグインを更新するときは --overwrite オプションを使う必要がある.今回は最新バージョンにした.

$ mkr --version
mkr version 0.24.1 (rev:102ee8d)

$ mkr plugin install mackerelio/mackerel-plugin-aws-ecs
           Downloading https://github.com/mackerelio/mackerel-plugin-aws-ecs/releases/download/v0.0.2/mackerel-plugin-aws-ecs_linux_386.zip
           Installing /opt/mackerel-agent/plugins/bin/mackerel-plugin-aws-ecs
           Successfully installed mackerelio/mackerel-plugin-aws-ecs

インストールしたプラグイン一覧

無意識に mkr plugin list と打ってみたけど list はサポートされていなかった.あれば良いのにー!今回は /opt/mackerel-agent/plugins/bin/ を ls して確認した.

$ mkr plugin list
No help topic for 'list'

$ ls -1 /opt/mackerel-agent/plugins/bin/
mackerel-plugin-aws-ecs

実行と設定

必要なオプションは複数あるけど,クレデンシャル関連は IAM Role で解決をしているため使わず,以下のようなコマンドにした.なお,メトリクスの値は仮で 0 にしている.あとオプションに付けるハイフンは,単語の場合は - じゃなくて -- 派なので,そうしている.

$ /opt/mackerel-agent/plugins/bin/mackerel-plugin-aws-ecs --metric-key-prefix ecs.kakakakakku-cluster --cluster-name kakakakakku-cluster --region ap-northeast-1
ecs.kakakakakku-cluster.CPUReservation.CPUReservationAverage    0  1515567018
ecs.kakakakakku-cluster.CPUReservation.CPUReservationMinimum    0  1515567018
ecs.kakakakakku-cluster.CPUReservation.CPUReservationMaximum    0  1515567018
ecs.kakakakakku-cluster.CPUUtilization.CPUUtilizationAverage    0  1515567018
ecs.kakakakakku-cluster.CPUUtilization.CPUUtilizationMinimum    0  1515567018
ecs.kakakakakku-cluster.CPUUtilization.CPUUtilizationMaximum    0  1515567018
ecs.kakakakakku-cluster.MemoryReservation.MemoryReservationAverage  0  1515567018
ecs.kakakakakku-cluster.MemoryReservation.MemoryReservationMinimum  0  1515567018
ecs.kakakakakku-cluster.MemoryReservation.MemoryReservationMaximum  0  1515567018
ecs.kakakakakku-cluster.MemoryUtilization.MemoryUtilizationAverage  0  1515567018
ecs.kakakakakku-cluster.MemoryUtilization.MemoryUtilizationMinimum  0  1515567018
ecs.kakakakakku-cluster.MemoryUtilization.MemoryUtilizationMaximum  0  1515567018

あとは /etc/mackerel-agent/mackerel-agent.conf に以下の設定を追加する.

[plugin.metrics.aws-ecs]
command = "/opt/mackerel-agent/plugins/bin/mackerel-plugin-aws-ecs --metric-key-prefix ecs.kakakakakku-cluster --cluster-name kakakakakku-cluster --region ap-northeast-1"

1日様子を見てみて,正常にメトリクスが取得できていた.

f:id:kakku22:20180111172255p:plain

(検証環境で取得した CPUUtilization と MemoryUtilization)

メトリクス

既に書いた通り,mackerel-plugin-aws-ecs で取得できるメトリクスは「ECS クラスタ」のメトリクスで,以下の計12種類となっている.

  • CPUReservation
    • Average
    • Minimum
    • Maximum
  • CPUUtilization
    • Average
    • Minimum
    • Maximum
  • MemoryReservation
    • Average
    • Minimum
    • Maximum
  • MemoryUtilization
    • Average
    • Minimum
    • Maximum

詳細は以下のドキュメントに載っているけど,CPUReservation など,コンテナインスタンスのオートスケールに活用できるメトリクスを取得することができる.なお,CloudWatch だと「3ヶ月間」のメトリクスしか残らない(ドキュメント「2週間」と書いてあったけど,確認したら「3ヶ月間」残っていた)けど,Mackerel なら「400日間」残せるため,メトリクスの長期的な傾向を知るためには Mackerel にメリットがある.

docs.aws.amazon.com

まとめ

  • 去年11月にリリースされた「mkr プラグインインストーラー機能」を試してみた
  • mkr plugin install でインストールできる mackerel-plugin-aws-ecs を導入してみた
  • 「ECS クラスタ」のメトリクスが取得できて便利だった(AWS インテグレーションに追加されたらまた話は変わりそう)
  • ECS 関連のアラート設定を Mackerel で管理できるので,運用も楽になる

typo 警察

mackerel-plugin-aws-ecs の README を読んでいたら,コマンド名が間違っていたので,修正しておいた.

github.com

mkr plugin で気になったこと

最後に mkr plugin で気になったこと(もしくは,僕の認識が間違っているかも)を箇条書きにしておこうと思う.

  • バイナリ(例えば /opt/mackerel-agent/plugins/bin/mackerel-plugin-aws-ecs など)からバージョンを確認できなかった
    • プラグインに問題があったときなど,バージョンを確認できないと不安になる
    • Chef でプラグインをプロビジョニングする場合,冪等性が保証できなくなる
  • mkr plugin list のような,プラグインを一覧するサブコマンドがなかった
  • Mackerel 関連のプロビジョニングは,全て cookbook-mackerel-agent で管理しているので,attributes にプラグイン名とバージョンを書けると助かる

github.com

教えることを教える先生が書いた「いちばんやさしい教える技術」を読んだ

去年に引き続き「教えるとは何か?」というテーマで探求をしていて,図書館で前から気になっていた「いちばんやさしい教える技術」を借りることができたので,ザッと読んでみた.非常にカジュアルな本で,2時間程度で読めてしまった.理論的な話はほとんど出てこないため,気軽にパラパラと読めるように構成されていた.

いちばんやさしい教える技術

いちばんやさしい教える技術

「教える」とは身近な行動である

本書の第1章に「教える場面はいくらでもある!」という話があり,すごく同意できる内容だった.なんとなく「教える」という行動を難しく考えている人が多いように思うし,「教えることができるのは先生だけだ」と考えている人もいると思うけど,例えば仕事をメンバーに引き継ぐときも,ツールの便利な操作方法を紹介するときも,はたまた子供の素朴な質問に答えるときも,それらは全て「教える」ことで,誰しも無意識に教えている.また最近よく記事にも書いているけど,ブログを書いたり,イベントで登壇をしたりして,成果をアウトプットすることも本質的には「教える」ことだと思っている.「教える」という行動が,非常に身近であるということを認識しておくことが重要だと思う.

運動/認知/態度

本書の第3章では,教える内容は大きく3種類に分類できると書いてあった.

  • 運動スキル
  • 認知スキル
  • 態度スキル

エンジニアリング的な観点でも,全てのスキルを教える機会がある.例えば,vim の操作を教えたり,IDE の操作を教えるのは「運動スキル」に該当すると思うし,プログラミングの文法を教えるのは「認知スキル」に該当すると思う.また,継続的に学ぶモチベーションを維持するのは「態度スキル」と言えるのではないかと思う.教えるスキルを分類するという考え方は今までなかったので,参考になった.

GROW モデル

第6章を読んでいたら,コーチング関連の情報を調べているとよく出てくる「GROW モデル」の話もあった.一言で言うと,目標達成を目指すための思考プロセスで,GROW の順番に考えることによって具体的な行動に繋がる.さらに,ゴール考えるときに「SMART の法則」と併用することが多いと思う.僕がブログメンターをしているときも,初回のキックオフでは GROW を意識して話を引き出すようにしている.

  • Goal : ゴール
  • Reallity : 現実
  • Options : 選択肢
  • What / When / Who / Will : 意志

教えたがり屋にならないように

第7章には「教えたがり屋にならないように」という注意喚起もあり,これは身が引き締まる思いだった.「丁寧に教えること」と紙一重だなとは思っていて(世話好きとお節介の関係に似ている),相手が本当に知りたいこと,もしくは知るべきことにフォーカスして教えるように意識したいと思う.さらに,相手が処理し切れないほどの情報量を投げ込むのではなく,適切な情報量に絞りたいとも思った.

まとめ

  • 「教える」を知るための入門書として良かった
  • 「教える」とは身近な行動である
  • 運動/認知/態度と,3種類のスキルに分類して考える
  • 「インストラクションデザイン(教育設計)」という分野に興味を持った

上手な教え方の教科書 ? 入門インストラクショナルデザイン

上手な教え方の教科書 ? 入門インストラクショナルデザイン

関連記事

次のステップとして,より理論的に「コーチング」という概念を学ぶ場合は「コーチングの基本」を読んでみるのが良いと思う.僕は去年に読んで「他責/自責/チャンクダウン」など,教えるときに重要なキーワードを知ることができた.

kakakakakku.hatenablog.com

SQS にポイズンピルメッセージがあると ApproximateAgeOfOldestMessage の値が正しくなくなる可能性がある

ApproximateAgeOfOldestMessage とは?

SQS には ApproximateAgeOfOldestMessage というメトリクスがあり,CloudWatch でモニタリングをすることができる.なお,SQS の歴史を考えると比較的最近に追加されたメトリクスで,2016年8月にリリースされている.

ApproximateAgeOfOldestMessage の意味を公式ドキュメントから引用すると,以下の通りとなる.ようするに,SQS に登録されているメッセージの中で「最も古い」メッセージの「登録されてからの経過時間(秒)」と言えるため,例えば SQS をポーリングするようなアプリケーションが障害で停止しているような場合は ApproximateAgeOfOldestMessage の値が増えるため,異常を検知することができる.

キューで最も古い削除されていないメッセージのおおよその経過期間。

docs.aws.amazon.com

逆に,夜間帯にポーリングしないという仕様のアプリケーションだった場合は,夜間帯に ApproximateAgeOfOldestMessage の値が増えて(期待値),翌朝にポーリングをすると ApproximateAgeOfOldestMessage の値が 0 に戻る(期待値).実際にこのようなアプリケーションを運用していて,以下のようなグラフになっている.

f:id:kakku22:20180106235238p:plain

(夜間帯にポーリングを止めている状態)

最近起きた事象

最近,特定のメッセージがアプリケーションでエラーになり,可視性タイムアウト (Visibility Timeout) が終了したら SQS にメッセージが戻されて,リトライを繰り返す状況が起きていた.アプリケーションのバグは想定していたため,このような状況を ApproximateAgeOfOldestMessage の値で検知するはずだったけど,なぜか ApproximateAgeOfOldestMessage の値が定期的に下がってしまうという事象が起きた.なお,参考のために SQS の設定を一部抜粋する.

  • 可視性タイムアウト : 30分
  • DLQ (Dead-Letter Queue) : 設定なし
  • ApproximateAgeOfOldestMessage の CloudWatch アラーム : 設定あり

以下のグラフを見るとわかる通り,なぜか「90分間隔(可視性タイムアウトとも関連性がない)」ApproximateAgeOfOldestMessage の値が下がってしまっていた.また,アプリケーション側のリトライによってメッセージの受信数も増えていて,SQS に登録されてからの経過時間は ApproximateAgeOfOldestMessage の値よりもずっと長かったため,ずっと線形に値が増えていくことを想定していた.

もう1度 ApproximateAgeOfOldestMessage の定義を振り返ると「キューで最も古い削除されていないメッセージのおおよその経過期間」なので,勝手に下がってしまうというのは変だなと感じて,AWS サポートに問い合わせた.

f:id:kakku22:20180106235247p:plain

(定期的に ApproximateAgeOfOldestMessage の値が下がってしまった状態)

ポイズンピルメッセージがあると ApproximateAgeOfOldestMessage の値が正しくなくなる可能性がある

AWS サポートに問い合わせてわかった結論としては,ポイズンピルメッセージ(アプリケーションでエラーになって SQS に戻ったメッセージのこと)があると ApproximateAgeOfOldestMessage の値が「正しくなくなる可能性がある」という仕様だった.メトリクスのドキュメントには載っていなかったけど,以下の「全般的な推奨事項」には確かに載っていた.これって結構知られている仕様?

キューにポイズンピルメッセージを含めると、ポイズンピルメッセージの誤った経過期間を指定することで、ApproximateAgeOfOldestMessage CloudWatch メトリクスが正しくなくなる可能性があります。デッドレターキューを設定すると、このメトリクスを使用する場合の誤ったアラームの回避に役立ちます。

docs.aws.amazon.com

ドキュメントを見ると,今回の件は「DLQ を活用して回避する」と載っているけど,例えば DLQ を活用するとしても最大受信数を設定して DLQ に飛ばすため,DLQ を活用したからと言ってポイズンピルメッセージを撲滅できるわけではないと理解している.そういう意味で,今回の件を通して感じたのは ApproximateAgeOfOldestMessage のモニタリングに頼りすぎるのは危険だと思った.あくまで ApproximateAgeOfOldestMessage は参考値として考えて,DLQ の ApproximateNumberOfMessagesVisible などのメトリクスをモニタリングした方が良さそう.

まとめ

  • SQS のメトリクス ApproximateAgeOfOldestMessage の値は,ポイズンピルメッセージがあると「正しくなくなる」可能性がある
    • ドキュメントに載っている「正しくなくなる」は,今回の事象では「定期的に値が下がる」だった
    • メトリクスのドキュメントにはその仕様が載っていないため注意する
  • モニタリングをする場合は ApproximateAgeOfOldestMessage の値ではなく,DLQ を用意して ApproximateNumberOfMessagesVisible などを活用する
  • 今まで知らなかった SQS の仕様を勉強できて良かった👍

「プロを目指す人のための Ruby 入門」を読んで Ruby を学び直した

11月末に出版された「プロを目指す人のための Ruby 入門」を読んだ.12月は少しバタバタしていて,読むのが遅くなってしまったけど,以下の企画に応募をしたら当選した.ありがとうございます👍

blog.jnito.com

はじめに

本書はタイトルに「入門」と書いてあるけど,正確にはプログラミングの入門書ではなく,最低限のプログラミングのスキルと Ruby のスキルが必要になる.まえがきにも似たようなことが書かれていて,その通りだなと思った.とは言え,本書はすごくキレイな流れで解説されているので,じっくり読み進めることで,プログラミング初学者でも十分ステップアップに活用できるようになっていた.なお,僕のスキルレベルとしては Ruby / Rails 歴3年ほどで,インフラの自動化を Ruby で書いたり,個人ツールを Rails で書いたりしている.また,TechAcademy で Rails 講師の副業を1年間続けている.

本書の良かったところ

例題 + テスト駆動開発

本書はほとんどの章に例題があり,実際に写経しながら進めることができる.さらに,テスト駆動開発で進めるようになっていて,テストコードを先に書いたり,テストを通しながらリファクタリングをする.この体験は素晴らしかった.

特に第4章にある「RGB 変換プログラム」のリファクタリングは良かった.最初,固定値でテストを通しつつ,DRY にリファクタリングをしながら変更し,最終的に1行になる.是非写経して欲しい.他にも第6章にある「Ruby のハッシュ記法を変換する」も,第7章にある「改札機プログラムの作成」も,本当に素晴らしい例題だった.

# Before
def to_ints(hex)
  r = hex[1..2]
  g = hex[3..4]
  b = hex[5..6]
  ints = []
  [r, g, b].each do |s|
    ints << s.hex
  end
  ints
end

# After
def to_ints(hex)
  hex.scan(/\w\w/).map(&:hex)
end

yield / Proc の解説

Ruby を学んでいると,yield / Proc あたりを理解できていることが中上級者になるポイントかなと思っているけど.本書では第10章で「ワードシンセサイザーの作成」という例題があり,3種類のエフェクトを Effects モジュールに実装し,さらに Proc を返すようになっている.Proc を写経しながら学べるのは非常に良かった.個人的にも yield / Proc を学び直すことができた.

module Effects
  def self.reverse
    ->(words) do
      words.split(' ').map(&:reverse).join(' ')
    end
  end

  def self.echo(rate)
    ->(words) do
      words.chars.map {|c| c == ' ' ? c : c * rate}.join
    end
  end

  def self.loud(level)
    ->(words) do
      words.split(' ').map {|word| word.upcase + '!' * level}.join(' ')
    end
  end
end

なお,メタプログラミングをさらに深く学ぶ場合は「メタプログラミング本」を合わせて読むと良いかと!

kakakakakku.hatenablog.com

「Ruby 技術者認定試験」の参考書にもなりそう

既に Ruby 資格の「Ruby Programmer Silver」と「 Ruby Programmer Gold」を取得しているけど,Ruby の言語仕様全般を学べるという意味では,参考書としても使えるなと思った.そのぐらい素晴らしい1冊だった.

kakakakakku.hatenablog.com

本書で学び直せたところ

正直,本書を読んで知った機能,そんなのもあったなーという機能が多くあり,Ruby を学び直すことができた.

Minitest

これまで Rails のテスティングフレームワークは RSpec を使っていたため,実は Minitest を使ったことがなかった.大規模なプロジェクトで使う場合は RSpec にメリットがあると思うけど,今回のように小さなスクリプトをテストする場合は Minitest も十分使えると思った.例えば,以下のように書くだけで,簡単にテストコードを書くことができる.あと,はじめて refute を見たときは,これはなんだっけ?と思った.

require 'minitest/autorun'

class SampleTest < Minitest::Test
  def test_sample
    assert_equal 'RUBY', 'ruby'.upcase
  end
end

splat 展開

メソッドの引数で可変長引数を受けるときなどに * を使うことはあるけど,配列の中に * を使って Array オブジェクトに展開する記法は知らなかった.今までは Range を使って (1..10).to_a のように書くことが多かった気がする.

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p (1..10).to_a
# Array
p (1..10).to_a.class

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p [*1..10]
# Array
p [*1..10].class

.each_with_index.each.with_index

配列に対して .each_with_index を使う場面は今までも多かったけど,添字を 0 以外にする方法があるのは知らなかった.表記が非常に似ているけど each.with_index(10) と書く.ようするに .each_with_indexeach.with_index(0) と同じと言える.使う場面あるかな?ドメイン次第ではあるかも.そもそも .each_with_index で添字を指定できるようになっていても良いような気もするけど.

fruits = ['apple', 'orange', 'melon']

# 0: apple
# 1: orange
# 2: melon
fruits.each_with_index {|fruit, i| puts "#{i}: #{fruit}"}

# 10: apple
# 11: orange
# 12: melon
fruits.each.with_index(10) {|fruit, i| puts "#{i}: #{fruit}"}

ブロックローカル変数

ブロック引数で変数名を ; で区切ることで,ブロック内部のローカル変数を宣言できるのは知らなかった.以下の例で言うと sum がブロックローカル変数になっている.知っておくと便利そうだけど,使う場面あるかな?OSS を読んでて出てきたら思い出してみようと思う.

numbers = [1, 2, 3, 4]
sum = 0

# 11
# 12
# 13
# 14
numbers.each do |n; sum|
  sum = 10
  sum += n
  p sum
end

# 0
p sum

例外専用の環境変数 $! と $@

これまた知らなかった.少しでもコード量を減らしたいときに使えそう.特に rescue => e と書かなくて良いのは便利そう.

begin
  1 / 0
rescue => e
  puts "#{e.class} #{e.message}"
  puts e.backtrace
end

begin
  1 / 0
rescue
  puts "#{$!.class} #{$!.message}"
  puts $@
end

プログラミング初学者にも読んで欲しいと思った第11章

最初にも書いた通り,僕は TechAcademy で Rails 講師の副業をしているため,日々プログラミング初学者に教えている.その中で,汎用的なスキルとして「エラーを楽しむこと」を強く伝えている.特にプログラミング初学者だと,エラーが出てうまく動かない場合にモチベーションが下がってしまうことがある.ただ,職業プログラマでもエラーなんて大量に出るし,重要なのはエラーの原因を特定して解決するスキルなので,バックトレースの読み方だったり,binding.pry の使い方だったりを教えている.また,シンタックスエラーはエディタの機能をフル活用しましょうという話もしている.そういう背景もあり,第11章の「Ruby のデバッグ技法を身につける」という内容は素晴らしかった.ここだけでも読んで欲しいと思った.

まとめ

  • Ruby スキルをステップアップするのに最高な1冊だった
  • 特に例題が素晴らしく,さらにテスト駆動開発を体験できる点も良かった
  • 仕事で Ruby / Rails を書いている人も学び直せる内容が多かった
  • 写経したコードは全て GitHub に push した

github.com

参考

本書に含まれなかった原稿も既に公開されている.合わせて読むと良いかと!

qiita.com