esm アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

Rails / OSS パッチ会オンライン 2020年10月のお知らせ

2020年10月の Rails / OSS パッチ会を 10月8日(木)にオンライン開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS への upstream にパッチを送る会です。

会には RubyRails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。Google Meet あたりのテレビ会議システムを使います。

当日の招待 URL は Idobata の esminc/rails ルームで共有する予定です。

idobata.io

特に募集ページなど設けませんが、上記理由から Idobata のアカウントと (TV 会議システムによっては Google アカウント) が必要になると思います。

以下、前回の活動が関わる成果です。

koic: RuboCop

github.com

yahonda: activerecord-oracle_enhanced-adapter

github.com

その他の開催方針については以下の Gist に記していますので、ご参照ください。

gist.github.com

XP祭り2020に参加して野良LTしてきました

こんにちは。@junk0612 です。

シルバーウィークの初日9/19(土)に、XP祭り 2020 が開催されました。 それに参加してきましたので、感想などを書いていこうと思います。

野良LT

XP祭りには 野良LT という企画があります。 お昼の時間を利用して、飛び入りでLTしたり、午後のタイムテーブルの内容を眺めたり、勉強会の告知をしたりします。 もちろんお昼なので参加は任意だし、途中参加・途中抜けOKというゆるいけれどXP祭りらしい楽しい時間です。

実は、僕はもともとタイムテーブルの終わりの方にある LT の時間に参加登録をしていたのですが、登録者多数で抽選となり、残念ながら落選してしまっていました。 野良 LT の存在をすっかり忘れていて「発表したい内容だったけどしょうがないな、まあ気楽に楽しもう」なんて思いながらのんきに朝から参加したのですが、 開会の「まんざい」で野良 LT の話が出てハッとなり、午前の基調講演を聞きながら急いで間にあわせの資料を作って発表してきました。 発表資料はこちらです。

内容を一言で表すと「アジャイルって考え方とか取り組む姿勢が一番大事だよね」という感じです。 アジャイル開発は、世間にはよく「開発手法」という側面で紹介されることが多いですが、『達人プログラマー』 (「常に心に聖堂を思い描く」) や、『アジャイルサムライ』 (「信頼貯金を増やす」) 、『エクストリーム・プログラミング』 (「XPとはソーシャルチェンジだ」) などに書かれている通り、今直面している問題だけでなく、最終的な目標や周囲の状況を正しく捉え、そのなかでよりよい解決方法を探していく心構えこそがアジャイルの本質なんだろうな、ということを最近よく考えていたので、それを素直にそのまま書いています。

書いている途中で「そもそも『アジャイルソフトウェア開発宣言』だって価値の話をしていたじゃないか。もしかしてすごく今更なことを言っているのでは……?」という疑念が浮かびましたが、それはそれ。 今後も変わっていくであろう自分の中の考えをスナップショットとして残しておくことを優先しました。 準備もそれほどしていない中で拙い発表でしたが、温かい反応をいただけてよかったです。「ぜひこれを読んでほしいなー」というリンクもコメントでいただいて、発表したかいがあったなと思いました。

面白かった発表

意外に野良 LT の話が長くなってしまったのですが、参加した中で面白かった発表を手短に2つほどご紹介しようと思います。

エンジニアの創造力を解き放て! XPと歩んだ17年・技術・現場・仲間

基調講演です。大企業の中で17年もの間アジャイル開発の普及に挑んできた発表者の神部さんの経験や工夫の詰まった興味深い発表でした。 大企業ならではのとんでもない状況や事態がたくさんあり、信じられなかったと同時に、聴衆のみなさんが笑っているのを見てきっと似たような経験があるのだろうと思いました。 アジャイル開発が「ふつう」になるにはまだまだ頑張らないといけないんだなあ、と (LT の資料作成で慌てつつ) 身の引き締まる思いで聞いていました。 発表資料はこちらに公開されています。

近代史とアジャイル

われらが @fkino の発表です。 「近代 (資料内では1776年からにスポットライトを当てています) における産業の歴史の中で、アジャイルソフトウェア開発はどのような立ち位置にいるのか?」という、面白い視点での発表でした。 アメリカ独立時に制定された合衆国憲法の中にすでにアジャイルマニフェストの精神が見出されるところや、近代合理主義と脱近代合理主義の思想に触れ、ドラッカーの言葉を引用しながら「それには現代ではアジャイルという名前がついている」というところなど、詳しくない分野が多いながら聞いていて面白かったです。 発表資料はこちらに公開されています。

全体を通して

COVID-19 の影響で、様々なカンファレンスがそれぞれの形で実施されていますが、XP祭りはオンライン開催となって自宅からゆったり参加できてよかったです。 また以前のように対面で恐れることなく会話ができるようになることを祈りつつ、これからも頑張っていくぞ、と気持ちを新たにしたイベントでした。

たくさんのファイルを巨大なアーカイブファイルにしてアップロードする

たくさんのファイルを同時に扱う際には、その処理が使うリソースに注意したいものです。さいきん私が直面した課題は、AWS S3 のあるバケットに保存されている大量のファイルをひとつのアーカイブファイルにして別のバケットに配置するというものでした。ひとつのアーカイブに含まれるファイルの数は最大で70万くらいあり、各ファイルのサイズは 10MiB を上限にさまざまです。ちなみに、アーカイブ対象のファイルをすべて合わせると、140GiB 以下であることがわかっています。

もしも70万のファイルを一気にダウンロードしてZIPアーカイブしようとしたら、ある程度のディスク容量が確保できていることを事前に確認しておいたほうがよさそうです。どれくらい必要でしょうか。もしアーカイブ処理を同じマシン上で平行して実行すると、必要な容量はさらに掛け算で増えていきそうです。そういえば、できあがったアーカイブファイルは数十GiBのサイズになる可能性がありそうですが、そもそも、果たしてそんなに大きなファイルは一度にアップロードできるんでしょうか。心配事がいろいろあります。こういった場面では、一度にすべて片付ける代わりに、少しずつ処理していくパイプラインっぽいやり方で対応できるとよさそうです。

AWS S3 Multipart Upload で少しずつアップロードする

幸い、S3 は巨大なファイルを小さなパーツに分割して少しずつアップロードする "multipart upload" と呼ばれる手段を用意しています。"multiple upload" は、アップロード対象のファイルが完成していなくても開始できるようになっています。つまり、どこかにアップロードするために、アーカイブファイルをいったん手元のファイルシステムに保存する必要は必ずしもないということです。

RubyAWS SDK も、もちろんこの機能を使う API を備えています。以下はその一例です。

s3_client = Aws::S3::Client.new(region: 'ap-northeast-1')
archive_object = Aws::S3::Object.new(bucket, 'archive.zip', client: s3_client)
archive_object.upload_stream do |upload_stream|
  upload_stream.binmode

  # write to upload_stream (one side of a pipe, IO object for writing)
end

Aws::S3::Object#upload_stream で miltiple upload の開始を知らせると、AWS SDK はブロック引数を介して IO オブジェクトを返してきます。これは IO.pipe で作成されたパイプの書き込み側なのですが、とにかく、ここにどんどんファイルの中身を書き込んでいけばライブラリが勝手にファイルを適当なサイズ (デフォルトは 5MiB) で分割しつつ、少しずつS3バケットにアップロードしてくれます。べんり!

ディスクに書き込まずに ZIP ファイルを作る

ファイルをアーカイブするとき、できあがったアーカイブファイルをまるごと保存するためのディスク容量を用意する必要がないといいですね。実は、ZIPはそういう要求にうってつけのフォーマットになっています。

ZIP フォーマットの構造

ほかのアーカイブフォーマットと同じようにZIPファイルも、アーカイブしているファイルの名前やファイルサイズ、データ位置といったメタデータを保持している場所があります。"central directory header" と呼ばれる領域で、興味深いことに、"header" という名前に反して ファイルの末尾に配置されることになっています

つまり、ZIPファイルを作成し始める段階では、すべてのアーカイブ対象のファイルの情報を手元に持っていなくても問題ありません。それらの情報は最後に central directory を書き込むときに用意できていれば十分です。それまでは、ファイル名などのメタデータをとっておきつつ、単純に圧縮したファイルをひとつずつ頭から書き込んでいけば大丈夫です。ファイルの中身を圧縮してアーカイブに追加できた時点で、元のファイルは不要になります。ですので、ZIP形式のアーカイブを作る際に、対象のすべてのファイルをあらかじめ手元のファイルシステムに保存しておく必要はありません。

パイプと zip_tricks gem

今回は ZIP アーカイブを作成するために zip_tricks gem を選択しました。理由は、このライブラリではZIPファイルの出力先としてパイプを使えるためです。ZipTricks::Streamer.open はZIPファイルの出力先としてIOオブジェクトを受け取るのですが、このライブラリは受け取ったIOオブジェクトを rewind しないため、パイプを渡すことができます。

for_write, for_read = IO.pipe # for_read can be used to upload

ZipTricks::Streamer.open for_write do |zip|
  zip.write_deflated_file 'a-file.txt' do |input_stream|
    input_stream.write 'the content of a-file.txt'
  end
end

出力先にパイプが使えるということは、できあがったZIPアーカイブファイルを手元のファイルシステムに保存しないという選択肢がとれるようになります。そういえば、S3 の multipart upload のセクションで、Aws::S3::Object#upload_stream はブロック引数としてパイプのIOオブジェクトを提供していましたね。つまり zip_tricks を使うと、次のように、アーカイブの出力をそのパイプに直接書き込めるようになります。

archive_object.upload_stream do |upload_stream|
  upload_stream.binmode

  # upload_stream is a pipe
  ZipTricks::Streamer.open upload_stream do |zip|
    zip.write_deflated_file 'a-file.txt' do |input_stream|
      input_stream.write 'the content of a-file.txt'
    end
  end
end

サンプルコード全体

これで、手元でファイルを作成せずに、たくさんのファイルをアーカイブし巨大なアーカイブをアップロードできるようになりました。

require 'aws-sdk-s3'
require 'zip_tricks'

bucket = 'hibariya-sandbox'
s3_client = Aws::S3::Client.new(region: 'ap-northeast-1')

files_to_archive = %w[alpha bravo charlie delta] # whatever
archive_object = Aws::S3::Object.new(bucket, 'archive.zip', client: s3_client)

archive_object.upload_stream tempfile: false, part_size: 20 * 1024 * 1024, thread_count: 3 do |upload_stream|
  upload_stream.binmode

  ZipTricks::Streamer.open upload_stream do |zip|
    files_to_archive.each do |file_path|
      zip.write_deflated_file file_path do |input_stream|
        s3_client.get_object bucket: bucket, key: file_path, response_target: input_stream
      end
    end
  end
end

Aws::S3::Object#upload_stream に渡しているキーワード引数はすべて任意です。詳しくは 公式のドキュメント を確認してください。 ※話を簡単にするために、アップロード/ダウンロード両方に同じバケットを使用しています。

注意点など

AWS S3 の multiple upload を使う場合は、分割できるパーツの数や未完了のアップロードへの課金など、いくつか知っておいたほうが良い事項があります。おそらく、未完了のアップロードを定期的に掃除するためにS3バケットにライフサイクルポリシーを追加したくなるのではないかと思います。詳細は公式の記事をご確認ください。

https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html

Windowsのススメ WSL2を利用した快適な開発環境作り

こんにちは!コロナ禍の影響でライブハウス遊びができずに、気になるバンドのライブ配信をひたすら見続ける生活を送っている@hidenbaです。

アジャイル事業部では、各自が利用するPCは、予算に応じて2-3年のサイクルで買い換えを行い、各々が好きなPCを購入して利用しています。 以前はmacOSの利用率が圧倒的に高かったのですが、Dockerを利用して開発を行う際に、遅さがストレスになるという理由でLinuxを選択する 事が多くなってきているように思えます。かくいう私は、3年前まではMacを利用していましたが、同様の理由でLinuxを選択して、現在はThinkpad T490にArch Linuxを入れて利用しています。

私たちは、受託開発やお客様の業務支援を行っていますが、時として、お客様のセキュリティポリシーの都合上、お客様から貸与されたPCを利用して 開発作業を行うことがあります。そのときに支給されるPCはお客様が指定したPCになることが多く、OSの選択肢としてはmacOSがほとんどだったのですが、最近ではWindowsも選択肢に入るようになってきています。

WindowsRubyを使ったシステムの開発なんてできるのか?なんて思ったりもしたのですが、WSL2を利用することで快適に開発を行えるようになってきています。今日は、私がお客様から、貸与されたWindowsPCで開発できる 環境になるまでに、やったことをざっとあげていきます。それぞれの詳細については、公式サイトのドキュメントや詳しく解説されている記事が多数あるので割愛します。

ターミナルで作業するための準備

今回、お客様から貸与されたPCはDellXPS 13でした。初回起動後は、Windowsアップデートをして最新の状態にします。 次にコマンドラインから利用できるパッケージ管理ツールの「winget」をインストールします。 これで、コマンドラインを中心に作業ができるようなりました。

標準のPowerShellを使うのでもいいのですが、もうちょっと高機能で使いやすいWindows Terminalをインストールして以降は Windows TerminalPowerShellを利用して作業していきます

$ winget install "windows terminal"

必要なアプリケーションのインストール

必要なアプリケーションをwingetを利用してインストールしていきます。

内外とのコミュニケーションのパスを用意するためにSlackとTwitterのクライアントをインストールします。

$ winget install slack
$ winget install tweeten

エディタがないと生きていけないのでVSCodeをインストールします。

$ winget install vscode

WSL2の設定

WSL2を有効にするために、管理者権限でPowerShellを起動します。

$ Start-Process powershell.exe -Verb runas

仮想マシンプラットフォームオプションを有効にして再起動をかけます。

$ dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

※私の環境では、上記コマンドではWSLが有効化されなかったのでコントロールパネルから設定をしました

[コントロール パネル] -> [プログラムと機能] -> [Windows の機能の有効化または無効化] を開いて、 [LinuxWindows サブシステム] をチェックします。

WSLのバージョンを2に固定します。

$  wsl --set-default-version 2

カーネルコンポーネントの更新をしてWSL2が実行可能な状態にします。 https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

WSL2にLinuxをインストールします。

$ winget install ubuntu

Docker環境の構築

Windows側にDockerをインストールします。

$ winget install "Docker Desktop"

VSCodeからWSL2環境に接続して開発を行うためにRemote Development拡張をインストールを行い、WSL2のubuntuからVSCodeを起動します。

$ code

開発に必要なリポジトリをWSL2のファイルシステムにcloneしてきてdocker-compose up等Docker環境を起動して開発を行うことができるようになりました!!

より快適な環境にしてくれるPowerToysのインストール

この状態だと、開発はできるがまだまだストレスが多い環境なので、キーバインドやウィンドウの配置を固定するためにPowerToysをインストールして好みのキーバインドにカスタマイズしています。

$ winget install powertoys
$ winget install ".NET Core"

現状の課題

この記事を執筆時点で早急にどうにかしなくては!と思っているのが、ssh-agentの設定です。現状はUbuntu上にkeychainをインストールして利用していますが、 VSCode起動時にパスフレーズを毎回聞かれたり、VSCodeのgit拡張からpushできずにVSCodeのターミナルからリモートリポジトリの操作をしています。 Windows側でssh-agentの設定をする方法があるみたいなので、近々試してみようと思っています。

最後に

十数年ぶりのWindowsに戸惑い多少ハマったりもしましたが、思っていた以上に簡単にWindowsでの開発環境を手に入れることができました。 みなさんも、機会があればWindowsでWSL2を利用した開発環境の構築をしてみるのもよいのではないでしょうか?

Kaigi on Rails に koic, 9sako6, yucao24hours が登壇!見どころをご紹介します

ここのところずっと RFC 1912 ばかり読んでいる inexperienced administrator の @yucao24hours です。

10 月 3 日開催予定の Ruby on Rails のカンファレンス、Kaigi on Railsスピーカー一覧タイムテーブルが公開されましたね。Rails のカンファレンスにぴったりの、汽車とレールを活かしたデザインがとてもかわいい!みなさん、もうチェックしましたか?

kaigionrails.org

わたしたちアジャイル事業部からも複数名がプロポーザルを提出しておりましたが、このたび @koic, @9sako6, @yucao24hours の計 3 名のプロポーザルが採択となり、発表の機会をいただけることになりました🎉

なお、今回のプロポーザルを提出するにあたっては、事業部内の有志のメンバーで集って「Kaigi on Rails のプロポーザルを考える会」を開き、お互いのプロポーザルについてレビューしあいました。 ぜひ以下の過去記事も併せてご覧ください。 blog.agile.esm.co.jp

今回のブログ記事では、登壇が決まったメンバー自らお伝えしたい発表の見どころや、発表をより楽しんでいただくための事前情報をギュッとまとめてお届けします。発表にかける思いの詰まったセルフライナーノーツをぜひお楽しみください。

『TDD with git. Long live engineering.』

発表者

@koic

発表者からひとこと

Martin Fowler, Kent Beck といったパイオニアPragmatic Bookshelf などによる出版によって、テスト駆動開発 (とその前に現れたテストファースト) と SCM は現場で広く親しまれるようになりました。

TDD と Git の登場には10年の隔たりがありますが、さらに10年が経過した今日における TDD と Git は有機的な繋がりを持った実践技法となっています。本編ではこれらの歴史と実践を背景に、リファクタリングのリズムに乗った TDD と相性の良い Git コマンドをもちいた TDD with git テクニックを紹介する予定です。

さらに GitHub によって、ブランチの意味合いも「開発トピックのために作るブランチ」「リリースのために作るブランチ」だけではなく「レビューのために作るブランチ」という側面が登場しました。これらによって実現されているソーシャルなリファクタリングと実戦的なコミットの適用についても取り上げます。こちらは、16 年間で 4,200 人以上が開発に関わっている rails/rails リポジトリの運用を参考にし、現場の開発でもちいている Git 術を TDD / リファクタリングと組み合わせて伝えます。

『コードレビュー100本ノックで学んだ Rails リファクタリング

発表者

@9sako6

発表者からひとこと

本発表では、Rails アプリケーションリファクタリングの Tips をお話しします。 これらの Tips は、実務で開発するなかで歴戦の先輩方にいただいた数百ものコードレビューから学びとったものです。 私の内に秘めておくのはもったいないので、言語化して発表することにしました。

大まかに「commit の意識改革」、「命名」、「分割」、「設計」、「テスト」という観点に分けて、それぞれいくつか具体例を交えながらお話しする予定です。 私のように Rails 歴が長くない方はもちろん、コードレビューや指導をする側の中・上級者の方にも参考にしていただけるのではないかと思っています。

『新ミドルウェア ActionDispatch::HostAuthorization と学ぶ DNS のしくみ』

発表者

@yucao24hours

発表者からひとこと

ウェブアプリケーションのコードを書くことが多い方にとっては、ふだんの開発作業時には DNS のしくみ ―名前解決がどのように行われるのか― を意識する機会はそう多くないかもしれません。(そのせいか、DNSドメインの世界に関しては「誤解を招く表現」や「事実からかけ離れた説明」がまことしやかに語られているさまが頻繁に見受けられるように感じます。)

かく言うわたしも少し前まではまさに "そこまで意識していなかった人間" で、これらのことについて真正面から向き合って勉強するようになったのはここ半年くらいなのですが、今となっては DNS をはじめとしたインターネット基盤技術について学ぶのが楽しくて仕方ありません。そこから溢れ出た「楽しい!」「おもしろい!」「みんなにも知ってもらいたい!」という純粋な気持ちをこれでもかとばかりにつめこんでプロポーザルをしたためましたので、こうして採択していただけて本当に感無量です。

今回の発表がウェブアプリケーションエンジニアのみなさんにとって、自分のアプリの "外" にちょっと目を向け、ふだんの開発をより広い視野で愉しめるようになるキッカケとなれたら... そして、DNS について正しい知識と理解を広めるための一助となれたらとても嬉しいです。


それでは、3 人の当日の発表にぜひご期待ください!

f:id:koic:20200910150145p:plain

仕事で遭遇したRailsのバグにパッチを送るまでの話

こんにちは、@color_boxです。 仕事でRailsを使っている時にバグに遭遇したのでそれに対してパッチを送りました。

送ったパッチはこちらです。 github.com この記事ではバグ発見からパッチ送信までの過程について書こうと思います。

続きを読む

新しいことを覚えてもらうときは実際にやってもらうが大切という話

こんにちは、@aikyo02 です。

今回は仕事で知識の継承とか新しいことをやってもらうときに感じたことを書いていこうと思います。

あるときプロジェクトの私以外のメンバーが次々に入れ替わるという事が起きました。

新たにプロジェクトに入ってくるメンバーは当然プロジェクトのことは知らないので、自分以外のメンバーにも知識を共有する必要がありました。アプリケーションの開発でよく使う部分やコードを読めばわかるようなところは日々の作業で問題なく知識共有が進むのですが、インフラ部分やプロジェクト特有の事務処理等あまり行わないことについては時間がたっても知識共有ができませんでした。

当初はメンバーにアプリケーション開発に慣れてもらうため、そういった部分は私が行っていたのですが、半年くらいたって余裕が出てくると私だけしか知らないことがあるというのはよくないという話が出てきました。(1人しか知らないことがあると休みも取りづらいということもありました)

そこで、ドキュメントを書いて共有会を開いて説明をしましたが、それだけではどうにもうまく行きませんでした。そもそも伝えることが多くドキュメントに書ききれないし、たくさんドキュメントを書いても読まれなくなっていたりメンテナンスされないという問題が私がプロジェクトに入ったときに既に起きていていたのです。

どうするといいかをいろいろと考えた結果、実際にやってもらうしかないと思うようになりました。 やってもらうにはなかなか機会がなかったり、フォローを考えておかなければなりませんが、やっぱり効果は大きかったです。インフラについてはもはや私がいる必要もなくなったかなというところまで知識共有が進みました。

もうひとつ似たようなこととして、メンバーにある機能を任せていたときに当初お客さんに話したリリース時期に間に合わなくなりそうで、私が巻き取ってしまったことがありました。

セキュリティの問題で緊急リリースを行う場合やユーザーの使いはじめる時期が決まっているなどしてリリース日がずらせない場合には仕方のないことですが、このときはそういうこともなかったのでお客さんと話し合って調整すればいいことでした。もっとメンバーに任せたほうがよかったのではないか、機会を潰してしまったのではないかと考えています。

今度はもしそうなっても最後まで任せるという判断をできるようにしたいです。

新しいことを覚えてもらうときは、実際にやってもらうのが一番という話でした。