脈絡はありません inoway

ハードルは低いほど飛びやすいをモットーに駆け出したエンジニアです

ハッカソン初参加の感想

現職の同僚に誘っていただき、Qiitaハッカソンに参加してきました。結果は予選敗退でしたが、エンジニアとしてとても貴重な経験ができました。

ハッカソン初挑戦で得た学びや気づきを残しておきます。

自分できなさすぎ

5人チームで自分はバックエンドを2人で担当しました。Docker環境でNestJSとPostgresQLで実装しようとしましたが、まずサーバーを立ち上げることに苦戦。Dockerfileなどを書き直してなんとか立ち上がりました。この過程で、yarnとnpmの違いがよくわかっていなかったり、package.jsonやyarn.lockの用途もよくわかっていないことに気づきました。

Dockerfileにはキャッシュなしでlockファイルを元にyarn installして、具体的なパッケージなどはyarn addでpackage.jsonに追加していくやり方が効率的ということに途中で気づきました。その時点で2,3時間ぐらいは消費してしまったと思います。

また、お次はNestJSでORマッパーはTypeORMでDBマイグレーションしようとしたところ、こちらもうまくいかない。また、デバッグしようにもPostgresQLにも明るくないため、テーブル一覧出すのってどうするんだっけ(汗)レベルで躓きまくりました。

苦戦しているうちに気づけば夜になっていて、もう一人の方が機転を効かせてExpressで1つのJSファイルにAPIを全部書いて、おまけにDBはSqliteにしてしまおうという方針に切り替えました。これが功を奏してなんとか最低限のAPIを作ることができました。(とはいえ、フロント側に責務の多くを寄せてしまうことになりました。。)

このように、時間制限のある状況で取り組むと、ただ知っているだけではだめで、血肉になったスキルのみが役に立つんだなと実感しました。テーブルやEntityの設計に関しては短時間でわりと筋の良い提案をすることができたので、ここは日頃の力を発揮できました。

ハッカソンの楽しさ

基本的に体力がないので、1日目の夜で心身ともに疲れ果て、リタイヤが脳裏をよぎりました。ただ、2日間で最後までなんとか作りきって、デモが他の参加者に受けている様子をみると、とても嬉しい気持ちになりました。また、他の参加者のプロダクトをみるのも非常に面白く、勝ち負け関係なしにお祭り気分になりました。

あんなに辛かったのに、終わった直後は「他のハッカソンはないかな?」と調べ始めたりしていました。今回誘っていただいた方はハッカソンに何度も出ていて、過去には優勝したこともある方なんですが、いわくハッカソンは慣れとのことなので、何度も出るうちにスピードアップしていけるのかもしれません。

また、単に技術力の勝負ではなく、割り切り力や精神的タフネスなど色々なものが求められるため、つよつよエンジニアだからといってハッカソンで勝てるわけではないというのも面白いポイントだなと思いました。

得た気づき

ハッカソンが楽しいという一方で、自分は性格的に何かを急いでやるのは苦手だなということにも気づきました。以前からフロントをゴリゴリ書いたりするのには苦手意識がありました。一方で、じっくり考える系のタスク(バックエンドでロジックを考えたり、インフラのことを学んだり、開発基盤を整えたりする)はとても好きなので、SREや基盤エンジニアなどの方向性に舵を切るのもいいかもしれないと思いました。とは言え、方向性の話で、それをやるだけの実力はまだまだ足りないので、日頃の業務でインフラタスクをやらせてもらったり、AWS資格を取るなどして研鑽していきたいです。

最後に

君もハッカソンでボロボロになってみないか?

エンジニア2年目を振り返る

🎅GMOペパボエンジニア Advent Calendar 2023の8日目の記事です。

昨日はしおりんさんの寒さを吹き飛ばせ!GASとChatGPTで目指す自動投稿への挑戦🚀 - shiorinのアウトプットでした。たしかにブログを書いたらXに投稿する流れがあるので、自動化できたら便利そうだな〜と思いました。MuuMuu Sites、自分も使ってみます。

2021年12月からWebエンジニアとしてお仕事をいただくようになったので、今月でちょうど2年になります。 この1年は色々とチャレンジさせてもらって、成長できた実感があります。

エンジニア2年目って何ができるの?どんなことができるの?という関心がある程度ありそうなので、それに応える形で書いていけたらと思います。(2年目といっても人により千差万別ではありますが)

できるようになったこと(順不同)

  • Railsを使った基本的な実装
  • RDBの基本的なテーブル設計
  • GitHubでの開発作法
  • 基本的なLinuxコマンドでのCLI操作
  • ログをちゃんと見てデバッグする
  • テストコードが意識的に書けるようになった
    • 余裕があればTDDで開発する
  • Kubernetesの全体像をざっくり理解して、最低限のCLI操作ができるようになった
  • 既存コードを真似ながらNext.jsの開発
  • 仕様を把握している状態でのコードレビュー
  • 新機能開発時のシステム設計
    • そこまで複雑ではないシステム
  • スクラム開発
    • チケットを切って見積もりしてスプリントゴール達成を目指す
  • 技術的な内容を整理して書く
    • テックブログや技術書典15への寄稿
  • クラウドインフラの基礎知識
  • GPT、copilotを使ったコーディング

できていないこと(順不同)

  • 一次情報をメインに調査する(公式リファレンスなど)
  • 検証が不十分なままできる、できないの判断をしてしまう
  • 周囲のエンジニアをリードする
  • あるべき設計は何かという観点でのレビュー
  • フロントエンド全般
  • 先を見通して行動する
  • スプリントゴール達成のために素早く実装する
  • 体調管理
  • その他、数えきれないほど多くのこと

こうやって書き並べてみると、1年前よりもできるようになったことがたくさんあります。約1年在籍してみて、ペパボの「いるだけで成長できる環境」とはこういうことなんだろうなと実感します。 ただ、たぶん意識できていないだけで、もっとできるようになったことはあるし、逆にできていないことを自覚していない領域もまだまだありそうです。

以降、学びになったことを思いつくままに書いていきます。

テストをちゃんと書く

自分が実装したあるコードが原因で、インシデントを起こしてしまいました。インシデントが起きた理由は大きく2つあり、変更を加えたpublicメソッドのテストを書いていなかったこと、Pull Request(以後PR)の差分が大きすぎてレビュワーがテスト不足に気づけなかったことです。

必要なテストが抜けるぐらいなら、不必要なテストを含めた上でPRを出すぐらいの気持ちがいいのかなと思っています。コードレビューをする上で、テストコードは「何を実現したいのか = 仕様」が明確化されており、レビューを容易にしてくれます。必要なテストが抜けているとは、すなわち仕様が明記されていない状態であり、レビュアーは実装が仕様を満たせているか確認する術がなくなります。(PRのdescriptionに書かれていればまだなんとか)

一方で過剰にテストが書かれている場合、少なくとも仕様は明確に伝わるはずです。ただ、仕様とは異なる動きを検証していてテストが通っていたら、それは実装が間違っているので直さないといけないです。また、不要なテストが多いとそれはレビュアーや将来の開発者にとってノイズになり、コードの理解容易性を下げてしまいます。(しかも、テストは消しづらい。変更によって何かが壊れるのが怖いから)

つまり、必要十分なテストを書くに越したことはないですが、テスト不足はインシデント(バグ)の原因になるのでやめていこうという話です。また、PRの差分が大きいとレビュアーの負担が大きくなり、実装者本人も含めてテストが不足していることに気づけなくなるので、なるべくPRは小さく分割して出していこうと心に決めました。

検証してから判断する

筋の良さそうなコードを書いたが動かなかった、だから少し冗長な別の実装パターンを採用した。こんな感じの動きをしてしまうことがあります。動かなかったのはなぜかログを吐き出して見てみたり、デバッグコード(binding.pry)を仕込んでみたり、コンソールで擬似コードを動かしてみたりといった検証をしないまま「動かない」という判断を下してしまっている。実装に詰まって誰かに相談する時も、自分でできる限りの検証を行って、何かしらの仮説を持った状態で話を持っていった方が解決しやすいのは明らかです。それなのに焦りや不安から、この実装はダメだとつい性急に判断してしまうことが度々ありました。公式リファレンスやソースコードなどをちゃんと読むことも含めて、検証をちゃんとやることを意識していきたいです。

GPTsを脳死で使わない

2023年はchatGPTやGitHub copilotを駆使することで、現場の実装スピードが大幅に上がったようです。ただ、これらのAIツールは何かしらのインプットをこちらから与えなければ動いてくれないですし、その回答もインプットに基づいた形で返ってきます。適切なインプットを与えるためには、必要な知識や発想を使用者が持っていなければならず、方向性を誤ったインプットを与えると、その回答ももちろん誤ったものになりがちです。(AIは賢すぎて、それは間違ってます、正しくはこうですと言ってくれることもありますが)

実力のある方は、質問する前に自ら一次情報にあたったり、きちんとデバッグした上で思考やコーディング作業の補助としてGPTsを使っている印象があります。ターミナルのエラーコードを雑に投げて「これはなぜですか?」と聞くのを繰り返していては自身が成長しないですし、質の良い回答も返ってこないので、まずは調べて仮説を立てるということを基本にしていきたいです。(一方で雑に質問して思考をクリアにしていくような使い方もあるので一概には言えない)

印象は大事

自分がいくら頑張っているつもりでも、それを周囲に知らせていなければもちろん頑張っているとはみなされないということに最近気づきました。それに、周囲が気づいてないということは、誰かの役に立つような成果に結びついていないからかもしれません。日々仕事をしているとたくさんの情報量を浴びることになるので、誰かと議論したりするときには思考のショートカットの表れとして、無意識のうちに印象に基づいて判断していることがあるなと思います。悪い印象を抱かれていれば、言っていることを簡単に飲み込んでもらえず仕事もスムーズには終わらなくなります。ペパボで「みんなと仲良くすること」が重視されているのは、こういう実利的な側面もあるんだろうなと思いました。社内のルールはちゃんと守る、笑顔で挨拶する、助けてもらったら感謝を伝える、ミスをしたら謝る、など当たり前のことを当たり前にできるようになりたいです。(できていないことがあって風呂場で反省会をしたりする)

小さく分ける

先ほど書いたようにPRを小さく分割するのもそうですが、あらゆる仕事において小さく分けることは有効そうです。人は基本的には怠け者(簡単にできることならやるけど、大変そうなことはなかなか腰が上がらない)で認知資源も限られているので、大きくて大変そうなタスクを渡されると、それを解決する思考よりも「それがいかに大変であるか」という思考で頭が埋められてしまいがちです。小さく分けると精神的ハードルが下がり、仕事にすぐ着手できます。また、どう解決するかも考えられるようになります。結果として仕事が早く終わるようになります。また、小さく分けるには全体像を把握しなければならないので、その過程で現状を整理でき、何が問題なのかも見えてきます。その状態で出てくる解決策も筋の良いものになるはずです。

ここまでつらつらと書きましたが、理想はこうなんだろうなという話で、まだ自分の中で当たり前の動きにはできていないので、小さく分けるを標語にやっていきます。

終わりに

もっと技術的なことを書いた方がアドベントカレンダー的にはいいよなと思いつつも、自分としては良い振り返りになりましたし、今後の仕事で意識すべきことも明確になったので書いてよかったです。1年後の自分がこれを読んだときにどう感じるか楽しみです。

明日はgurasanさんの記事です。お楽しみに!

adventar.org

Reactの公式チュートリアルをやってみた感想

実務でそろそろNext.jsを触ることになりそうなので、Reactのチュートリアルをやってみた。

Tutorial: Tic-Tac-Toe – React

各ステップでcodesandbox(ブラウザでJavaScriptなどを書けるエディタ)を呼び出せるようになっていて、ローカルで環境構築してGitHubに上げて・・・というステップが必要ないのがありがたい。

自分は当初、以下の日本語に翻訳されたページの存在を知らずオリジナルの英語版で読んでいた。ただ、難しい表現は使われていないし、翻訳アプリを使えば難なく読める分量になっているのでそれほど苦労することなく進められた。

ja.react.dev

このチュートリアルではtic-tac-toeという三目並べ(マルバツゲーム)アプリを作りながら、コンポーネントや状態管理といった概念をステップバイステップで学んでいくような構成になっている。

本当に入門したてなので正しいことを書ける自信はないが、感想を書き残しておきたい。

Reactの主要コンセプト

コンポーネント

自分がチュートリアルをやる前にReactに関して小耳に挟んでいたことの一つがコンポーネント。どうやらUIを構成するテーブルやボタンなどをコンポーネントとして切り分け、各コンポーネントを状態の変化に応じて動的に変更しながら画面を作っていくらしい。

以下のページを読むとその概念が理解しやすかった。在庫を検索する簡易的なページをReactでどう作るかを題材にしていて、検索ボックス、タイトル、アイテム表示欄などコンポーネントに切り分け、まずは静的なページを作り、次にstateなどを使用して動的に作り上げていく手順を踏んでいる。

ja.react.dev

たぶん感覚的には絵を描くことに似ていて、まずはスケッチしてラフに形を作っていき、そこから徐々に精緻化させていくようなイメージだろう。プラグラムを書く上では新規機能を作るよりも改修することの方が大抵の場合において楽なように(人によるかも)、未確定の要素を減らしながら、徐々に掘り進めていくようなプロセスは理にかなっていると思う。

宣言的UI

自分はJavaScript(バニラJS)やjQueryを何度か実務で書いたことがあり、Vue.jsやReact.jsといったいわゆる宣言的UIというコンセプトを採用したフレームワークを使用したことがなかった。

以下の記事は命令的UI(jQueryなど)と宣言的UIの違いをサンプルコードを用いて解説されていて、おかげさまで理解が深まった。

zenn.dev

先ほどのコンポートネントのくだりで書いたことと同じで、宣言的UIにおいては、「こんなDOMになりますよ」と先にマークアップしておき、動的なロジック部分を虫食い状態にしておくような考え方になるらしい。一方で命令的UIはappendメソッドなどを用いて、ロジックの中に追加するHTML要素を書いていくような形になるので、最終的にどのようなDOMになるのか、コードから理解しづらく、そのコード自体も複雑になってしまう。(DOMって言葉の使い方あってるか不安)

この辺りは理論的にはそうなんだろうけど、プロダクションコードを触ったことがないので、その明快さがまだ実感できていない。書くの楽しそうだなという感じはなんとなくしている。

ステート

動的に画面を変化させていく上で鍵となるのがステート。propsという形で親コンポーネントから子コンポーネントにデータ(オブジェクト)やイベントを渡し、データに変更が加えられた時にそれを検知し、即座に対象のコンポーネントを再構築する。宣言的UIを採用したフレームワークはDOMが滅茶苦茶になって画面が崩れたりしないという話をよく聞くけど、おそらくDOMがコンポーネントの繋がりとして表現され、何を変えればどこに影響があるのか(再レンダリングされるのか)が明確に管理されているからだろう。(これも合ってるかよくわからない)

たぶん自分が足りない知識でつらつらと書くよりも以下の公式解説を読むのが一番良いように思う。具体例付きでとてもわかりやすい。

Reactの流儀 ステップ 3:UI の状態を最小限かつ完全に表現する方法を見つける

▼事例以外の解説部分

state とは、アプリが記憶する必要のある、変化するデータの最小限のセットのことである、と考えましょう。state の構造を考える上で最も重要な原則は、DRY(Don’t Repeat Yourself; 繰り返しを避ける)です。アプリケーションが必要とする状態に関する必要最小限の表現を見つけ出し、他のすべてのものは必要になったらその場で計算します。(以下略)

時間が経っても変わらないものですか? そうであれば、state ではありません。 親から props 経由で渡されるものですか? そうであれば、state ではありません。 コンポーネント内にある既存の state や props に基づいて計算可能なデータですか? そうであれば、それは絶対に state ではありません!

これからどう学習を進めるか

まずはチュートリアルで作った三目並べアプリを自分で作ってみようと思う。三目並べに必要な概念を一つ一つ洗い出し、マス目のようなUIをどうコンポーネントとして切り出すかを考え、まずは静的なUIを作ってから、徐々にロジックを入れ込んでいくようなステップを踏むとよさそう。たぶん出来上がるコードはチュートリアルのものと比較して冗長だったり汚かったりするだろうけど、その差分を埋める作業を通してまた学びが深まりそうな気がする。

次に、Next.jsで簡易的なアプリを作ってみて、Vercelを使ってデプロイしてみる。聞くところによるとReact単体で作るよりもNext.jsを使用した方がルーティングなど複雑になりがちな部分をよしなにやってくれるので、初心者にはNext.jsから入った方がよかったりするらしい。たぶんRubyだけでアプリ作るよりも、Ruby on Railsrails newした方が簡単に作れるのと同じことだろう。

後はTypeScriptもやっていかなければ。最近、実務でGraphQLのサーバーサイドの実装を行っていて型定義などをちょっとだけやっていたりするが、型があることでどんな値が入出力されるのかコードから読み解けるようになりとても見通しがよくなるなと思っている。TypeScriptもこれだけで複数のオライリー本が書けるような体系になっていて、さらにHTML、CSSJavaScriptなどもやっていこうとするとWebフロントエンドをちゃんと書けるようになる日はいつになるのだろうかと気の遠くなる思いだ。ただ、もっと幅広く課題解決できるエンジニアになるためにもやっていきたい。

終わりに

Reactはコンセプトがとてもシンプルかつ理にかなっていて、素晴らしいなと思った。多くのエンジニアが熱狂する理由がわかったような気がした。2024年にはフロントエンド書けますと自信を持って言えるようにこれからやっていくぞ。

RubyKaigi 2023に3日目だけ現地参加したらものすごく濃い経験になった

長野県松本市にて開催された今年のRubyKaigiに3日目だけ現地参加しました。 所属会社であるGMOペパボ株式会社に参加費用を出していただきました。

昨年はリモート参加して、プレゼンを拝聴していましたが、相変わらず内容に追いつくので精一杯という感じでした。

ただ、現地参加して得られたものはたくさんありました。

まず、企業ブースにて有名企業のCTOとカジュアル面談できたり、技術的な話をできる機会がありました。

RubyKaigi終了後には、たまたま出会った海外エンジニアの方としゃぶしゃぶを囲み、テクノロジー談義に花を咲かせました。

来年はなんと沖縄で開催されるらしいです。

たった1日ですごく濃い経験をさせてもらったRubyKaigi 2023について感想を書いていきます。

参加したセッション

※ あくまで個人の感想であり、スピーカーの意図や事実とは異なった内容が書かれている可能性があります。

9:40~ Ruby Committers and The World

RubyコミッターとShopify社の方々のパネルディスカッション(英語)でした。多少なりとも英語をかじっているので、何を言っているのかはなんとなく分かりましたが、そもそも技術的な内容に理解が及ばず、やっぱり本質的に重要なのは英語力以前に専門的な知識だよなあと、本題とは関係のないことを思っていました。

Matzさんが話しながら翻訳的なこともされていて流石でした。世界中のRubyistたちと向き合ってきたからこそ、その人たちとコミュニケーションを取るために英語力を磨かれてきたんだろうなあと思うと頭が下がる思いでした。

11:00~ The Adventure of RedAmber - A data frame library in Ruby

Rubyistにとって使いやすいデータフレームを作りたいという思いで、RedAmberというOSSを自作しているとのこと。職業エンジニアではなく、趣味として?活動されているそうで、お金ではなく知的好奇心に駆動されているのが素晴らしいなと思いました。

自分は前職でPythonのPandasというライブラリを使ってエクセルファイルの整形などを行ったことがあり、そういった整形や分析処理などをRubyの書き方でやりたいってことなんだろうなと理解しました。Red Data Toolsというプロジェクトの一環とのことで、Rubyでできることが広がりそうでワクワクしました。今後の動向に注目です。

13:30~ Ruby + ADBC - A single API between Ruby and DBs

ブースの面談に参加していたため、途中から参加しました。

ADBCとは、Apache Arrow Database Connectivityのことです。データベース固有のAPIをラップすることで、異なるデータベースに接続できるAPIを提供します。

役割としてはActive Recordなどと同じようですが、ADBCは大容量データとパフォーマンスにフォーカスして、Rubyのデータ処理において大容量データを扱えるようにしたとのことです。

速度差などをグラフで分かりやすく示されていてそのすごさを体感できました。ただ自分の知識不足のせいもあり、内容は深いところまで理解できませんでした。こちらもRed Data Toolsの一部とのことで、ソースコードを見てみます。

14:10~ Load gem from browser

個人的にとても印象に残ったセッションでした。JavaScriptのように、Rubyをブラウザで扱えるようにすることで、初心者にもとっつきやすい言語にしたいという想いでWasmの開発を進めてらっしゃるそうです。JSの歴史やライブラリ群から着想を得て、Rubyのgemをブラウザ上でロードできるように試行錯誤されている過程をお話されていました。

実際のデモでは、ブラウザ上で外部ファイルが読み込まれ結果としてコンソールに出力されていて、会場では拍手が起こりました。ただ、外部ファイルの中でさらに別ファイルを読み込むという処理はまだできないらしく、そこを解決すべく試行錯誤されているとのことでした。自分もその様子を見て感動しましたし、とても興奮しました。

14:50~ Unleashing the Power of Asynchronous HTTP with Ruby

こちらもとても印象に残ったセッション。スライドが非常に分かりやすく話し方も明瞭で、素晴らしいプレゼンでした。英語でしたがスルスルと頭に入ってきました。

内容はRubyのHTTPクライアントとサーバに関するお話で、HTTP/0.9からHTTP/3までどのような進化の変遷を辿ってきたのかをサンプルコード付きで説明されていました。とてもシンプルなコードだけど、その中にはこれまでの歴史が詰まっているということを知ってすごいなと思いました。(すごいしか言ってない、語彙力・・・)

プレゼンターのSamuelさんは一緒に開発していきませんか?という声かけもされていたの印象的でした。Rubyistが一堂に介するRubyKaigiは新たな仲間を探す場として最適で、だからこそ自分のプロジェクトに興味を持ってもらうためのプレゼンにとても力を入れられていたんだなと気づきました。RubyKaigiの新たな側面を知る良い機会でした。

ご本人がツイートされてますが、以下で紹介されている記事でとても分かりやすく解説されていました。

16:00~ Let's write RBS!

実際にRBSを書いて、どのように型判定されるのかをデモしていただきました。参加時点ではRBSに関する知識がほぼゼロだったので、恥ずかしながらへーこんな感じなんだというざっくりとした感想を抱くぐらいしかできませんでした。

参加後のメモに「Steep」とキーワードを残していたので、それを元に検索すると、Rubyコミッターの@mametterさんの記事を見つけました。(分からなくてもメモするの大事ですね)

techlife.cookpad.com

Ruby3にバンドルされているTypeProfで型注釈のないコードを静的型解析できるようになること、Steepで型エラーを検査し、さらにRubocopのようにエディタ上でエラー表示までやってくれるんだなということを学びました。

また、上記の記事内で紹介されている@jnchitoさんの記事で、実際にどのように活用するのかを知り、すごい、自分も使ってみたいと思いました。

qiita.com

弊社のメンバー内でもRBSを使っていくぞ的な話があったので、実務で書ける日も近いかもしれません。

16:40~ Parsing RBS

RubyKaigi 2023のラストを飾るキーノートセッションでした。@soutaroさんは15年前から一貫してRubyの型チェックに関するコントリビュートをされていて、前項で紹介したSteepを開発された方です。

github.com

RBSに関する知識がほぼなかったこともあり、お話の内容には残念ながら理解が及ばなかったのですが、15年間の努力と今こうして多くの方がSteepを活用されていることを知り、その凄みを感じました。ありがたいことにスライドを公開されていたので、RBSの知見がついてきた段階で改めて勉強させてもらいます。

speakerdeck.com

RubyKaigi 2024に向けて

企業ブースでCookpad CTOの@kani_bさんと面談させてもらった時、RESTからGraphQL APIへの移行をどのようにしていくと良いかといった相談をさせてもらいました。

Cookpadではスクラップ&ビルドをよく行うらしく、技術的負債が積み上がりすぎて拡張性が損なわれてきた時は、一から作り直したりするようです。

そのような発想を持っていなかったので、なるほどそういう考え方もあるのかという気持ちになりました。そしてそういったリプレイス作業には幅広い技術的知見が必要になるはずなので、息の長いプロダクトにおいては、強いエンジニアを採用して技術的負債を解消していきたいニーズが強くあるんだろうなという推測をしました。

開発プロセスを早めたい時は、思い切って作り直す時間を設けて、設計をきれいにするのも手段の一つなんでしょうね。ポケモンでいえばソーラービームみたいな。

なぜこの話を書いたのかというと、技術的イベントには問いを持って参加すると得られるものが多いんだろうなと思ったからです。

今回でいえば、RESTからGraphQLへの移行を進めるにはどうするか、という問い。ソースコードを他社に見せてどうこうとかはできないまでも、話を一段抽象化すれば、他社のエンジニアに課題感を共有して、解決策を一緒に模索し合えたりする。それはとても素晴らしいことだし、楽しいことだなと思います。

だから、RubyKaigi 2024には自分なりの問いをたくさん持っていこうと思います。そして技術的知見を磨いて、誰かの問題解決をお手伝いできるようになっていたいです。

また、個人の技術者としてどう成長していくかというアドバイスもいただいて、「とにかくたくさん作ること」というお話が印象的でした。勉強になったで終わらせるのではなく、実際に問題を解決するためのアクションとしてコードを書いて成果物を作っていくようにしようと心に決めました。

思い出たち

天然温泉 あづみの湯 御宿 野乃松本に一泊しました。松本の街並みを一望できる露天風呂は最高のひと言でした。セルフロウリュがあるサウナと水風呂もいい塩梅で、心身ともに整いました。RubyKaigi前日にとても良い準備ができました。人気漫画がずらりと並ぶコーナーがあって、前から気になっていた『チ。―地球の運動について―』を読みました。地動説を証明するために、死をも厭わないシーンに鳥肌が立ちました。知的好奇心は誰にも止められないんだな。

お世話になったプログラミングスクールRUNTEQの卒業生の方と集まり、ボードの前で記念撮影をしました。皆さん有名企業の最前線で活躍されていて、自分も負けてられないなと思いました。コミュ力不足で十分な交流ができなかったのがちょっと反省です。

RubyKaigi遠征の締めはとても素敵な時間になりました。同じチームで働いているakiさん(@aki90935433)としゃぶしゃぶを食べに行こうという話になりお店に着くと、エレベータの前で偶然RubyKaigiに参加されていたガブリエルさん(@gazayas)に出会いました。一緒に食べましょう!ということになり、1時間半ほど技術談義に花を咲かせました。ガブリエルさんはBullet TrainというOSSの開発に参加されていて、RBSのトピックでも出ていた抽象構文木に関する知見もお持ちのようでした。

github.com

サミュエルさんのHTTPのプレゼンがすごかったと仰っていて、自分たちのOSSにいかに興味を持ってもらうかって大事だよねというお話をしました。OSSではないけど、自分もLTなどに参加する時は聞き手に興味を持ってもらうにはどのような構成がいいか?など考えるようにしたいと思いました。ガブリエルさんは大阪で活動されているそうなので、地元の京都に帰った際にまたお会いできたら嬉しいです。

akiさんがエンジニアになろうと思ったルーツもお聞きして、誰かの役に立ちたいって想いが根本にあることを知り、素敵な仲間と今こうして働けてるんだなと感慨深く思いました。お二人ともありがとうございました!

最後に

1日だけの参加なのにこうして書いてみると、ものすごく濃い経験をしたんだなと気づきました。オンラインで視聴していただけだった2022と比較すると、学びが段違いでした。オフラインの偉大さを改めて実感します。

冒頭にも書いたように相変わらず技術的な話については5%ぐらいしか理解できていない感がありましたが、プレゼンターの熱量を体感し、キーワードを知り、デモを目の当たりにしたことで、入り口に立てた気がします。参加して勉強になったな〜で終わらせるのではなく、この強く印象に残る体験をベースに自分なりに探求していくことが重要なんだと思います。RubyKaigi 2024では1年間で得た学びと問いをポケットに詰めて、より良い経験ができるようにしたいです。

RubyKaigi 2023の運営メンバー・スピーカーの皆さん、GMOペパボの皆さん、このような貴重な機会をいただきありがとうございました!

集中力と生産性

エンジニアとして良い仕事をしようと思ったら、集中力が必要になる。何かと注意散漫になりがちなので、集中はいつも自分の中にあるテーマだ。

例えば寝不足した状態でコードを書こうとしたら、typoをたくさんしてしまう。エラーが発生した時に、考慮すべき前提を飛ばしてしまい延々とハマり続けたりする。

十分な睡眠をとったとしても、集中を妨げるものはまだまだある。YouTubeSNSなど大量の刺激的なコンテンツは簡単に注意を奪う。ながら見しながらやればいいじゃないかと思うかもしれないが、人間は基本的にマルチタスクが苦手なため、同時並行でやれているように思えても実はうまくやれていなかったりする。

あとはSlackの通知も集中を中断する。仕事は一人でするものではない以上、こればかりは仕方がない。対策できるとしたら、カレンダーに「集中タイム」など入れておき通知を一時的に切ることなど。あとは心の持ちようとして、他のメンバーを信頼して集中タイムではない誰かが問題を解決してくれるだろうと任せること。そして解決してくれた人に感謝と賞賛をギブすること。

以下、シーン別に集中力について考察していく。

学習

技術的なことを学ぼうと思うと、OSSの公式ドキュメントを始めとして、最新情報はネットから得る必要がある。また、手を動かしながらインプットするのが一番定着することを考慮すると、やはりエディタを開きつつドキュメントを読むのが良いやり方だと思う。

ただ、ネット上には前述のようにたくさんの楽しいコンテンツが転がっているので、ちょっと気を抜くと別タブを開いてサブスク動画を観ていたりする。どんな教材も注意をしっかりと向けて着実に取り組まなければ、身につかない。Udemyには過去に面白そうだと思って購入した教材が大量にあるが、最後までクリアできたものはほんのひと握りだ。この課題をどう克服しよう。

自分一人で学習するのではなく、勉強会などのイベントを設定するのはどうだろう。怠惰な人間だと思われたくない心理が働いて、最後までやり遂げられる可能性が上がりそうだ。さらに双方向のアウトプットの機会が与えられるのでより深い理解を得られるだろう。エンジニア界隈が頻繁に勉強会を開いているのはこの効果を狙ってのものかもしれない。

ただ、いつも複数人で学習するわけにもいかないので、一人でどのように学習していくと良いのか。集中できなくてもいいから、1つの教材を最後までやると決めて、それが終わるまでは他に手をつけないようにするのはどうか。内容の質とかはあまり気にせず、まずは最後までやり切る習慣を身につけるのが重要なように思う。今見かけているUdemyのReactの教材を今週末は最後までやってみよう。

仕事

日によって集中できる時とそうでない時がある。前日遅くまで残って仕事をしていた場合、たいてい次の日は集中力を欠いてしまう傾向があることに気づいた。おそらく集中エネルギーなるものが脳内にあって、それを使いすぎると集中エネルギーが満タンになるまでに時間を要するのかもしれない。

集中力がある日とない日を交互に迎えるより、コンスタントに集中が続く方が生産性は高い。なぜなら集中を欠いている日は不要なコンテンツを見て時間を無駄にし、坂を転がるようにまた無駄なことをしてしまうからだ。最近読んだ本で、こういう現象のことを「ドミノ倒し」と表現していて、SNS、ジャンクフード、アルコールなどがその代表例だったりする。他の観点でも、集中力(と思考力)が低い日に設計したシステムに考慮漏れがあり、後々手戻りを発生させたりもしそうだ。もっと悪い場合、リリースフローをミスして他の人に迷惑をかけたりする可能性もある。

どうすればコンスタントに集中力を保てるのか。十分な睡眠、食事、運動を心がけることは基本的かつ最も効果がある対策になりそうだ。睡眠は特にドミノ倒しの影響を受けやすく、刺激的なコンテンツを見始める→夜ふかしをする→十分な睡眠を確保できない→自制心がない状態で翌日を迎えまた刺激的なコンテンツを見る・・・という悪循環に陥ることが多い。ちょっと大袈裟に書きすぎたけど、どうでもいいコンテンツを見ると、仕事のパフォーマンスに影響が出る可能性があることは頭の片隅に入れておきたい。

身体を動かすと、頭がよく働くようになるのを実感する。京都にいた時は近くに小さな森があり、詰まった時に森を30分ぐらい散歩するようにしていた。散歩から帰ってきた後に再びコードに向き合うと、さっき詰まっていたのが嘘のように解決できたりする。東京に来てからはジムに最低週1回は通っている。クロストレーナーが最近のお気に入りで、膝に大きな負担をかけないし、全身運動にもなっていい。音楽を聴きながらやると踊っているような感覚になって楽しい。話が逸れたが、運動は高い集中力を保つ上でとても良い効果をもたらしてくれるのでこれも意識して続けたい。

食事については、ジャンクフードを食べるとやはり眠気が強い気がする。あとは量も重要で、食べすぎると血流が消化に充てられてしまい、眠気を誘うことになる。カフェインも集中力をコントロールするのによく活用していて、カフェインレスコーヒーとブラックチョコレートを昼食後に摂るようにしている。ブラックだと強すぎて夕方に急激に疲れてくるので、カフェインレスぐらいがちょうどいい。たまにブーストしたい時は、ほうじ茶を飲んでいる。

あとはマインドフルネス瞑想も集中力を鍛える効果があるようだ。大学生の頃から寝る前に5分ほど呼吸に集中するようにしている。ただ、最近はあまりしっかりやれていない。今日からもっと意識的にやっていこうと思う。色々な手法があって正解がよく分かっていないが、とにかく自然に呼吸して、注意が逸れたら静かにまた戻すことを繰り返すのが良いらしい。

生活

ちょっと本題とは逸れるけど、日々の生活でも集中力は重要だ。例えば友人や恋人と会話をしている時。スマホにばかり気を取られて会話に集中できなければ、人間関係は簡単に壊れてしまうだろう。誰かと出かけている時に、退屈な時間はたびたび発生する。電車で移動している時や何かの列に並んでいる時など。そんな時に目の前にいる相手に集中して、会話を楽しむことができればいいだろうなと思う。会話をしなくても、電車の音や乗客の服装に注意を向けてみたりして楽しむこともできそうだ。これは果たして集中力なのか?と書きながら疑問に思ったけど、自分にとって重要な内容であることには違いない。

特に相手の話を注意深く聞くこと、その人自身に集中することは心がけていきたい。そんな姿勢から良い人間関係は生まれるのだと思う。

まとめ

例のごとく書きながら考えているのであまりまとまりはなかったけど、いくつかの良い視点を得ることができたのでよかった。引き続き高い集中力を保つにはどうすれば良いか探究していきたい。

Dependabot対応とオンラインDDLについて

特にテーマを決めずに技術的な記事を書いてみようと思い立って書いている。

今までのペースだと月に2回ぐらいで書いていて、それが当たり前になるとだんだんアウトプットの腰が重くなってきて良くないよなと感じていた。

月に1回はちゃんと腰を据えて書くとして、それ以外はわりと気楽に書いて知識を定着させたり、考えを深掘りする機会を増やそうと思った。

最近やってたこと

Dependabotが立てたPRをオートアサインする

Dependabotはライブラリの依存関係を自動的にアップデートするPRを作ってくれるbotで、アプリの脆弱性への対応をサポートしてくれる非常に優れたツールだ。このDependabotが立てたPRにworkflowを発火させて、CODEOWNERSを自動的にアサインするようにしようとしていた。

ただ、Dependabotが作成するPRはセキュリティの観点で、write権限が制限されていたり、tokenを渡せなかったりする制約があって、なかなかworkflowを正常に動かすことができなかった。

(以下記事などを参考にさせてもらっていました)

engineering.mobalab.net

当初、複数リポジトリでDRYに動かせるようにreusable workflowを使って発火させていたが、前述のtokenの制約によりなかなか動いてくれなかったりした。悪戦苦闘したおかげでworkflow周りに詳しくなることができたけど、デバッグがしづらくてなかなか大変だった。

ただオートアサインがなかったとしてもDependabotが立てたPRには日々対応していくべきで、それは今後も強く意識を持ってやっていきたい。

※まるで自分がやったかのように書いたけど、全体の3%ぐらいしかやっていない。元々他の方がreusable対応などもされていて、動いてないのに気づいて直そうとして、力不足で直せなかったというお話

既存のテーブルにdefault: falseのカラムを追加する

100万件のレコードがあるテーブルに、default: falseのカラムを追加しようとしている。つまり100万件のレコードを追加することになるはずなので、DBに負荷がかかりダウンタイムが発生することが懸念されていた。

それをどうやって実行するのかというと、オンラインスキーマ変更ツール(pt-ost、go-hst)などを用いて、仮テーブルを作っておいてそれを良きタイミングで実テーブルと入れ替えるような処理が対策の一つらしい。

ただ、今日色々と先輩に教わりオンラインDDLというマイグレーション方法があるらしいことを知った。DDL(Data Definition Language)とは、データ定義言語と呼ばれるSQLの命令のことで、SELECT文などレコードを操作する DML(Data Manipulation Language)と違い、テーブルに直接変更を加える。ALTER句でテーブル全体に変更を加えて、default: falseのカラムを一括適用しようということだと思う。

まだオンラインDDLについてはキャッチアップ中なので、また進捗があれば良きタイミングでアウトプットしてみる。今日書いていて思ったけど、うっかり大事な情報を書いてしまわないように内容の抽象度を保ちながら書いていこうと思った。

chatGPTコーナー

Dependabotとは何ですか

Dependabotは、GitHubが提供する自動依存関係更新サービスです。このサービスは、プロジェクトの依存関係を自動的に更新することで、セキュリティ上のリスクを軽減し、ソフトウェアのメンテナンスを助ける目的があります。

Dependabotは、プロジェクト内で使用されているライブラリやパッケージの最新バージョンに関する情報を定期的にチェックし、新しいバージョンが利用可能になった場合に、自動的にプルリクエスト(Pull Request)を作成します。これにより、開発者は依存関係を最新の状態に保ち、セキュリティ脆弱性やバグを修正することができます。

Dependabotは、多くのプログラミング言語やパッケージマネージャーに対応しており、JavaScript(npm, yarn)、Python(pip)、Ruby(Bundler)、Java(Maven)、PHP(Composer)などがサポートされています。また、GitHubと緊密に統合されているため、プロジェクトの設定やワークフローに簡単に追加することができます。

オンラインDDLとは何ですか

オンラインDDL(Data Definition Language)は、データベース管理システムにおいて、テーブル構造やインデックスの変更など、データベースオブジェクトを操作するための言語です。DDLには、CREATE(作成)、ALTER(変更)、DROP(削除)などの操作が含まれています。

オンラインDDLとは、データベースの運用中に、これらのDDL操作を実行できる機能を指します。オンラインDDLを使用することで、データベースのダウンタイムを最小限に抑えつつ、スキーマ変更やインデックスの追加・削除が可能になります。これにより、データベースのパフォーマンスや機能性の向上が容易になります。

一部のデータベース管理システム(例:MySQL、Oracle、PostgreSQLなど)では、オンラインDDLがサポートされており、運用中のデータベースでスキーマ変更を行うことができます。ただし、オンラインDDLの実装や対応範囲は、データベース管理システムによって異なります。

chatGPTに頼りすぎると次第に脳死でコマンドを打つようになってしまう危険性を感じたので、内容を鵜呑みにしないこと、ちゃんとレビューしてから使うようにしないとなという気づきも得た今日この頃でした。chatGPTはたしかにすごいけど、使いこなすにはやはり実力が必要という当たり前のことを実感しました。

HTTP通信における冪等性と安全性、冪等な環境構築スクリプトとは何か

業務で冪等性(べきとうせい)に関する話題が出ていて、そういえば最近読んだ『Webを支える技術』 に書かれていたなと思って、改めてブログにまとめようと思う。

例のごとくchatGPTさんに聞いてみた。こういった汎用性の高い話は、chatGPTに聞くようにするとMECE(漏れなくダブりなく)な内容を答えてくれるので積極的に使っていきたい。

chatGPT-4の回答

HTTP通信における冪等性と安全性について詳しく説明してください。GET、PUT、POST、DELETEリクエストを例にしてください。

HTTP通信では、冪等性(idempotence)と安全性(safety)は、メソッドの振る舞いを理解し、適切なリクエストメソッドを選択するための重要な概念です。

冪等性(idempotence)とは、同じ操作を何度実行しても、最初の実行と同じ結果になることを指します。冪等性があるメソッドは、リクエストが途中で失敗した場合や、クライアントがリクエストの完了を確認できなかった場合に、再試行が安全であることを意味します。

安全性(safety)とは、メソッドがサーバー上のリソースに対して何も変更しないこと、つまり読み取り専用であることを指します。安全なメソッドは、リソースに対して副作用を起こさないため、何度実行しても問題ありません。

それでは、GET、PUT、POST、DELETEリクエストを例に、冪等性と安全性について説明しましょう。

1. GETリクエスト
冪等性: あり
安全性: あり
GETは、サーバー上のリソースを取得するためのメソッドで、リソースを変更しないため安全です。また、何度リクエストしても同じリソースが返されるため、冪等性もあります。

2. PUTリクエスト
冪等性: あり
安全性: なし
PUTは、サーバー上のリソースを更新または作成するためのメソッドです。リソースの内容が変更されるため、安全ではありません。ただし、同じリソースに対して同じデータを送信すれば、結果は同じになるため、冪等性があります。

3. POSTリクエスト
冪等性: なし
安全性: なし
POSTは、新しいリソースを作成するためのメソッドで、リソースの状態を変更するため安全ではありません。また、同じリクエストを繰り返すと、新しいリソースが何度も作成される可能性があるため、冪等性もありません。

4. DELETEリクエスト
冪等性: あり
安全性: なし
DELETEは、サーバー上のリソースを削除するためのメソッドで、リソースを変更するため安全ではありません。ただし、一度リソースが削除された後、同じリソースに対してDELETEリクエストを繰り返しても、それ以上削除できるものはないため、結果に変化がなく冪等性があります。

以上のように、HTTPメソッドにはそれぞれ冪等性と安全性の特性があります。これらの特性を理解することで、適切なリクエストメソッドを選択し、効率的なWebアプリケーションの設計や開発が可能になります。

冪等性はどんな時に意識するものか

安全性については、リソースを変更するかどうかという意味で、理解が容易いが、冪等性は直感的に分かりづらい概念だと思う。

実務で冪等性について触れられたのは環境構築スクリプトに関する話で、一度スクリプトを走らせて途中で失敗した時、そのスクリプトが冪等であれば再実行しても問題ないし、冪等でないなら安全に再実行することはできないと判断できる。ここでふとDocker buildコマンドに--no-cacheオプションを付ける理由は、冪等性を確保するためなのかなと思って、またchatGPTに聞いてみた。

Docker buildコマンド実行時にnocacheオプションを付ける理由は、冪等性を確保するためでしょうか。

docker build コマンド実行時に --no-cache オプションを付ける理由は、冪等性を確保するためというよりも、ビルドプロセスを完全に再実行し、キャッシュに依存しないビルドを行うためです。

Dockerは、ビルドプロセスの各ステップごとにキャッシュを作成します。これにより、変更があったステップ以降のみビルドを行い、キャッシュを利用してビルド時間を短縮することができます。しかし、このキャッシュ機能は、外部リソース(例えば、リモートリポジトリからのパッケージの取得)に依存するステップがある場合、古いキャッシュを利用してしまい、最新のリソースが反映されないという問題が生じることがあります。

--no-cache オプションを使用すると、キャッシュを無視し、すべてのビルドステップが最初から実行されます。これにより、最新のリソースを取得し、期待される状態のイメージがビルドされることを確実にすることができます。

つまり、--no-cache オプションは、冪等性を確保するというよりも、キャッシュに依存せず、最新の状態でのイメージビルドを確実にするために使用されます。

古いキャッシュを利用してしまい、最新のリソースが反映されないという問題が生じる

この記述からやはり冪等性を確保するためなんじゃないかという気もしたが、そもそも常に更新されうる外部リソースに依存している時点で、docker buildコマンドには冪等性がないのかもしれない。そうなる場合、Docker環境を構築するためのスクリプトを冪等にするのは事実上不可能なのでは?という気もしてくる。バージョン指定を固定すれば実現できたりするのかな。

というわけでまたchatGPTに聞いてみた。

Docker環境を構築するスクリプトを冪等にすることは可能ですか

Docker環境を構築するスクリプトを冪等にすることは可能です。冪等性を持たせるためには、スクリプトが繰り返し実行されても同じ結果が得られるように設計する必要があります。以下に、冪等性を確保するための一般的な方法をいくつか示します。

1. コンテナの起動前に既存のコンテナを削除する
Dockerでコンテナを起動する前に、同じ名前のコンテナが既に存在する場合は削除しておくことで、スクリプトが繰り返し実行されても同じ結果が得られます。

docker rm -f container_name || true
docker run --name container_name ...

2. Dockerイメージのビルド時に --pull オプションを使用する
Dockerイメージをビルドする際に、--pull オプションを使用することで、ベースイメージを常に最新のものに更新できます。これにより、スクリプトの実行結果が常に最新の状態であることを確保できます。

docker build --pull -t image_name .

3. Docker Composeを使用する
Docker Composeは、複数のコンテナを定義し、管理するためのツールです。docker-compose.yml ファイルにサービスとしてコンテナを定義し、docker-compose up コマンドで環境を構築することができます。Docker Composeは、環境の状態を管理するため、冪等性を持った環境構築が可能です。

4. スクリプトや設定ファイルの変更を最小限にする
スクリプトや設定ファイルの変更が少ないほど、冪等性を維持しやすくなります。不要な変更を避けることで、環境構築の安定性を向上させることができます。

これらの方法を適用することで、Docker環境を構築するスクリプトを冪等にすることが可能です。ただし、実際の状況や要件に応じて、最適な方法を選択することが重要です。

そうかたしかに--pullオプションでコンテナを生成するimageを指定すれば、常に同じ結果が得られると考えてよさそう。マネージャーがpullでビルドするようにスクリプトを修正してくださいと言っていたのはこういうことだったのかも。ただ、同じDocker imageを元にしても中身の各ソフトウェアのバージョン(依存関係)も常に同じ結果になるのかが疑問だ。その点を聞いてみる。

1つのimageから生成されるコンテナは、誰がどの環境で生成しても、中身のソフトウェアのバージョンや依存関係も常に同じと考えてよいですか。

はい、1つのDockerイメージから生成されるコンテナは、誰がどの環境で生成しても、中身のソフトウェアのバージョンや依存関係も常に同じと考えてよいです。Dockerの目的の一つは、開発環境と本番環境の一貫性を確保することです。Dockerイメージには、ソフトウェア、ライブラリ、設定ファイル、実行環境などが含まれており、イメージからコンテナを生成する際にこれらの情報がそのまま利用されます。

Dockerイメージはレイヤー構造を持っており、それぞれのレイヤーはDockerfileの命令に対応しています。イメージを生成する際、Dockerはこれらのレイヤーを一つずつスタックし、最終的なイメージを構築します。この仕組みにより、同じDockerイメージを使用する限り、生成されるコンテナの内容は同じになります。

ただし、Dockerイメージ内で動的に変更される設定や、ホストマシンからマウントされるデータボリュームなど、コンテナの実行環境に依存する部分も存在します。これらの要素はコンテナ間で異なる可能性があります。しかし、Dockerイメージのソフトウェアや依存関係に関しては、同じイメージを使用してコンテナを生成する場合、常に同じと考えてよいです。

この回答を信頼するなら、あるDocker imageをpullしてbuildするようにすれば、コンテナの生成に関しては冪等なスクリプトになると考えてよさそう。

まとめ

chatGPTから回答を得る→新たに生じた疑問を聞いてみるというサイクルを繰り返すと、効率よく学ぶことができるんだなと分かった。こんな感じで、また実務で生じた疑問をテーマに記事を書いていきたい。