ちなみに

火曜日の空は僕を押しつぶした。

京都市内で会議室として使える古民家・寺情報

仕事で必要になって聞いてみたところたくさん情報をいただきました。 良さそうなところばかりなのでしばらく合宿先には困らなさそう。 ありがたや。

細かくリリースする

合計すると7ヶ月分くらいのブランチをビッグバンリリースするという経験をしました。 サービスのリリース時以外だといままでで一番長く生存したブランチかも。

当初の想定だとシュッとリリース出来るつもりで少数で作っていたのが、どんどん膨らんで全員が関わることになって、結果的にこういう感じになったのだけれど、最初から細かくリリース出来るように意識していれば途中でもリリースしてしまうことが出来たはずなので悔やむことが多い。

いまのチームでは、機能単位でブランチを切っておいて、そこにいったん全ての変更を溜めてからまとめて master にマージする風習がある。 変更を確実にテストしてから、masterにマージしたいのでこういうことをしているのだけれど、デメリットも多い気がしている。 ここでいうテストは結合テストと、POによるレビューを指していて、手順に従って人間がポチポチしている。もちろんユニットテストなどの自動テストは書いた上で。

では、実際にどういうデメリットがあるのだろうか。

  • 確認に使う時間の無駄
    • 見る範囲が莫大になるので見落とさないようにするのは至難のわざ
    • プルリクで一度見ているはずなのにまた全体で確認している無駄
  • 問題が起きたときの原因調査にかかる時間の無駄
    • 各プルリクを細かくリリースしていたら、壊れる前にリリースしたものが原因とすぐに分かる
    • 7ヶ月分のブランチをリリースしても、どの差分が問題だったのかぱっと分からない
  • ブランチ管理の無駄
    • 当然、7ヶ月もあればmasterはどんどん進んでいく
    • たびたびコンフリクトするブランチを直すてまが無駄
    • しかもどんどん難易度は上がっていく
  • 開発時のオーバーヘッドの増加
    • ブランチ管理と近いけれど、masterと乖離しまくっているブランチに切り替えるのは大変
    • 今回は特に開発環境への変更が入ったりしていたのでブランチを切り替える毎に環境の再構築が必要だった
    • いくらDocker化していても毎回やるのはつらい
    • コンテキストスイッチも大変になる

こういう悲劇を起こさないように、フィーチャートグルなんかが使えるのだけれど、なかなか導入が進まない。 一因としてはフィーチャトグルを導入することでの、開発の複雑さが増加するのではという漠然とした不安をチームがもっていることが挙げられる。 複雑さが増すことで、開発速度が落ちたり、分岐を間違えて見せてはいけないものが見えてしまうことへの恐怖がありそう。

しかし、よく考えてみると我々は7ヶ月分の巨大なブランチをリリースしたのだ。 この(不要な)偉業を越える難しさはそうそうないのではないだろうか。

巨大なブランチを扱う方が複雑だし、結局リリースまでに起きた問題の対処や、これから起きる不具合への対応を考えると開発速度も遅くなってないだろうか。

いまこそこまめなリリースに取り組むべき時ではないだろうか。

Internet Explorer のサポートを切ると何が嬉しいのか

f:id:Sixeight:20211027203958p:plain

社内勉強会向けにまとめた資料から社内特有なところを削除したものです。

ゴール

Internet Explorerとは

Chakraとは

JavaScriptエンジンとは

ECMAScriptとは

  • JavaScriptの仕様
  • 策定プロセスの歴史
    • 全ての仕様の合意が取れたらリリースしていた
      • リリースまでに膨大なリソースが必要で大変
    • 合意出来たプロポーザルからリリースする
      • 常に最新が公開されている
  • ES2015とかって?
    • 年に一回リリースされる仕様のスナップショット
    • ES6(2015)以降の仕様書のバージョン名

Web APIとは

Web標準とは

  • Webの技術を標準化する動き
    • 戦国時代を経て世界平和へ
  • W3C
    • 標準化団体
  • WHATWG
    • Living Standard

(おさらい) JavaScriptとWeb API

(余談) ES2015以降のECMAScriptの歩み

クラス 追加された機能の代表例
ES2015 クラス、let / const、Arrow Function
ES2016 Array.prototype.includes
ES2017 async/await
ES2018 オブジェクトのスプレッド構文
ES2019 Array.prototype.flatMap
ES2020 オプショナルチェイニング演算子 ?.、Null合体演算子 ??
ES2021 String.prototype.replaceAll、Logical Assignment Operators

(余談) トランスパイル / Polyfill

  • トランスパイル
    • 特定の機能を(古い)ブラウザでも動くように変換すること
  • Polyfill
    • 特定の機能を(古い)ブラウザでも動くように実装したコード

ところで

互換性をどうやって調べるのか

一部を紹介します

  • 2021/10/27時点で Internet Explorer 11 以外が対応している機能
  • なんか分かりやすいのを挙げています

JavaScript

ECMAScript 2015

Web API

Fetch API

URL API

Intersection Observer API

Resize Observer API

まとめ

JavaScript と Web API の違いが分かる

Internet Explorer のサポート終了によって何が変わるのかが分かる

  • ある機能が特定のブラウザで動くのか調べられるようになりましたか?
  • Internet Explorer のサポートを切ると出来ること
    • ECMAScript 2015 で策定された機能が使える
    • 最近のWeb APIが使える

(おまけ) TypeScript

  • JavaScriptのスーパーセット
    • 新しい仕様もどんどん取り入れている
    • TS4.5はES2022の一部を実装している
  • 出力対象のECMAScriptのバージョン
    • ECMAScript 3 以降、プロポーザルを含むES Nextまでを選択できる
    • 提供する対象によって適切なバージョンを選べる
  • 今なら何を設定すべきか
    • ES2016
    • ES2021でもいける
      • ただしSafariが以下に対応していない
        • shared memory and atomics
        • RegExp Lookbehind Assertions

参考文献

GitHub Actions の GitHub-hosted runners には gh が入っている。つまり。

GitHub Actions の GitHub-hosted runners にはいろんなソフトウェアがインストールされています。たとえば ubuntu-latest だとこういう感じ。

よく見ると GitHub CLI 2.0.0 が含まれている。つまり actions/github-script は不要だったのだ。(JSで書く方が楽な場合もあるけど)

以下のように認証して使うとだいたい何でも出来る。

echo '${{ secrets.GITHUB_TOKEN }}' | gh auth login --with-token

勘のいいみなさんなら気付いたかと思いますが、実はこれだと 権限が足りない

The minimum required scopes for the token are: "repo", "read:org". https://cli.github.com/manual/gh_auth_login

しかし、参照系ならだいたいいけるので情報取得だけならこれでよい。もうちょっと強い権限が欲しい場合は自分で PAT を用意すればいい。

さて、gh が入っていたら何が出来るのでしょうか。

答えは API で出来ることならなんでも出来ます。

なぜなら gh api サブコマンドがあるので。 REST API でも GraphQL API でも何でも実行出来るから。これで勝利したも同然。

また gh api サブコマンドには --jq オプションがあって、これを使うとAPIのレスポンスを gojq でパース出来る。よってレスポンスをごにょごにょするのもお手の物である。まじ最高。

-q, --jq string Query to select values from the response using jq syntax https://cli.github.com/manual/gh_api

しかしながら、そもそも 各種サブコマンド により、直接APIを叩かなくていいことも多々あるので、まずはドキュメント端から全部読んでみましょう。

jqで簡易テンプレート

たとえばSlackの Incoming Webhook でメッセージを送るときに、メッセージ部分だけを置き換えてJSONを組み立てたいことがあります。 プログラミング言語が使えるなら簡単なんですが、ちょっと大げさな気もするので jq だけでJSONを組み立てられるとべんりそうです。

{"text":"hi"}

このようなJSONを組み立てて送信したいとして、"hi" の部分を変数にしてみます。

{"text":$text}

この $text の部分を任意の文字列に置き換えるには --arg オプションを使います。(-n / -c)

$ jq -n -c --arg text hi '{"text":$text}'
{"text":"hi"}

今回のケースでは不要ですが文字列以外の値に置き換えるには --argjson オプションを使うことが出来ます。

$ jq -n -c --argjson text 12345 '{"text":$text}'
{"text":12345}

目的はこのJSONをSlackに投げることだったので生成結果を curl に食わせます。 -d @- で標準入力をbodyとして送信できるのではこれを利用します。 ちなみに Object Construction が使えるので { text: $text } のような書き方が出来ることも覚えておくとよさそうです。

$ jq -n -c --arg text hi '{ text: $text }' | curl -H 'Content-Type: application/json' -d @- <Incoming Webhook URL>

これで目的は達することが出来ました。

Slackに投稿するときは、恐らくもうちょと 複雑なメッセージを組み立てる 必要があると思います。 そういった場合にはテンプレートとしてファイルを用意しておきそれを読み込むことも出来ます。

以下のような内容で template.js というファイルを用意します。.js 拡張子なのは object っぽい書き方なのでシンタックスハイライトが効くから。。。

{
  blocks: [
    {
      type: "header",
      text: {
        type: "plain_text",
        text: "CI"
      },
    },
    {
      type: "section",
      fields: [
        {
          type: "mrkdwn",
          text: "*Result:*\n\($result)"
        },
        {
          type: "mrkdwn",
          text: "*SHA1:*\n\($sha1)"
        }
      ]
    }
  ]
}

ファイルを受け取るには -f オプションが使えるので以下のようにして生成します。

jq -c -n --arg result Success --arg sha1 eeeaaa -f template.js | curl -S -H 'Content-Type: application/json' -d @- <Incoming Webhook URL>

f:id:Sixeight:20210925170351p:plain

ちなみに gojq でももちろん同じことが出来て圧倒的に速いので、大きなJSONを生成するときはおすすめです。

$ time gojq -c -n --arg result Success --arg sha1 eeeaaa -f template.js > /dev/null

________________________________________________________
Executed in    7.56 millis    fish           external
   usr time    2.54 millis    0.09 millis    2.45 millis
   sys time    3.83 millis    1.12 millis    2.71 millis
$ time jq -c -n --arg result Success --arg sha1 eeeaaa -f template.js > /dev/null

________________________________________________________
Executed in   31.71 millis    fish           external
   usr time   40.19 millis    0.12 millis   40.07 millis
   sys time   10.60 millis    1.06 millis    9.53 millis

ISUCON 11でISUCONに初出場して予選敗退した

f:id:Sixeight:20210822231314p:plain
最初にエンキューしたベンチマークジョブIDが941で幸先良いと喜んでいる様子

いつも日和って出れないので、今年こそはISUCONに出てみようと思っていたのですが予選の申し込みが一瞬で埋まったので意気消沈。 そんなとき id:karupanerura さんに声をかけていただいて、id:aereal さんと3人で「チームにゃんこ選抜」として出場することになりました。

初めてでだいぶ緊張していましたが、練習で丁寧に教えてもらったり、過去問の解説を読んだりして、ある程度落ち着いて当日を迎えることが出来ました。

競技開始後は最初に決めておいて手順に従って初期設定や情報収集、そのあと集まってマニュアルの読み合わせをした。 これまでの会と比べて得点計算が複雑だったのでそこを理解するのに時間がかかってしまって、作業開始がかなり遅くなってしまったうえに、結局結局グラフの改善までは到達出来てなかったので理解してたてた作戦が活きてないのでもうちょっと見切り発車でも良かったかも。

読み合わせ後は初手の作戦を決めてそれぞれ独立して作業、30分くらいごとに進捗確認をして、次の作戦を決めるという方式で進めていた。 独立して動いていても30毎に同期が取れるのであんまり迷走することはなくて動きやすかったです。

github.com

今回のリポジトリはこういう感じでした。

あとから周りのチームをみていると速度優先でコミットとかけっこうめちゃくちゃにやっていて、あ、それで良かったんだという発見があった。 けっこう丁寧にコミット詰んだりしてしまっていたので、次はもっと速度優先していこうと思った。

当日はDiscordで常時つなぎながら、GitHubとSlackで文字情報の共有をしていて、すぐに声をかけられたのでやりやすかったのでオンラインでの常時音声通信は必須だなあと感じました。

isucon.net

結果としては予選敗退だったが、とても楽しかったし、自分の実力が低すぎることを痛感することが出来て勇気を出して出場してよかったです。 ただし、チームのメンバーには迷惑をかけてしまったので、完全に素振りと普段の勉強が足りていなかった。

自分が唯一貢献できたのは isu_condition.condition を別カラムに分割する案と実装したこのプルリクくらいで、それ以外はただただあたふたしていた。 落ち着きも足りないね。

github.com

かなり慣れたつもりだったけどCorneliusでの入力が若干おぼつかないシーンがあって焦るとまだ駄目だなという感じ。 この記事はCorneliusで書きました。

Corneliusは最高

foostan さんの設計されたキーボード、Corneliusを組み立てました。

忙しいというか仕事が終わるとMPがつきている状態が続いていたので、届いてからしばらく放置したいたのですが先週末にやっと元気が出てがっとやりました。 スイッチは Diamond Linear をストックのまま。 キーキャップは Grab Bag に入っていたSAプロファイルのものをかき集めて。一部足りないところは刻印に重複があったりする。

もうこれでいいやんという境地に達している打鍵感と音で大満足。ただし、やはりLubeしていないスイッチはたまにスプリングのすれる音が聞こえたりして微妙なのでそのうち潤滑したい。

この記事は Cornelius で書きました。

おまけ。キーマップは現在こんな感じです。

f:id:Sixeight:20210817003621p:plain f:id:Sixeight:20210817003636p:plain f:id:Sixeight:20210817003651p:plain f:id:Sixeight:20210817003705p:plain