Don't Repeat Yourself

Don't Repeat Yourself (DRY) is a principle of software development aimed at reducing repetition of all kinds. -- wikipedia

GitHubスポンサーの募集

GitHubスポンサーの募集を作ってみたので、したいなと考えています。スポンサーの詳細は下記にまとめました。

github.com

今年はもう書籍を2冊執筆しているのでお腹いっぱいなのですが、来年からたとえば

  • Rust関連では
    • ずっとやりたいと思ってるもののここ数年全く時間がなかったためにできなかった、Rust本体への貢献やその他周辺のエコシステムへの貢献。
    • Async Bookの翻訳の続き。
    • もう少し応用的な内容を含む記事の執筆(個人ブログないしはZennなどで)。
    • Rust.Tokyoへの貢献。
  • 加えて、その他の技術へのOSSでの貢献。

あたりを行っていきたいと思っています。主にOSSに割く時間を捻出したいです。

金額に応じた特別な見返りなどはないです。が、よく他の方がやっている事例を真似て、GitHubのトップページにプロフィールロゴを掲載させていただきたいと思います。One-time shotも嬉しいです(むしろこっちの方がMonthlyよりプレッシャーがなくて嬉しいです)

よろしくお願いします✨

JISキーボードからUSキーボードに切り替えた

小学生の頃にパソコンというものを触り始めてから社会人になってソフトウェアエンジニアとして働いて10年近く、ずっとJISキーボードを使ってきました。「日本語を打つのになぜUSキーボードをわざわざ使うのだ」という考えからずっと使ってきましたが、最近ついにUSキーボードに変えてしまいました。

買ったキーボード

Nuphy Halo75

Nuphyの「Halo75 Wireless Mechanical Keyboard」というものに変えました。Night Breeze軸の音と軽さがちょうどよかったのでこれにしました。あんまり指の力が強くないので軽めのものがタイプです。ただ軽すぎると押したつもりもないのに押した判定されてそれはそれでストレスなので、35g〜45gくらいがちょうどいいなと思っています。この辺りの条件にフィットしたのがNight Breeze軸でした。

テンキーは不要というかデスクのスペースを取りすぎるので96は選択肢にはありませんでした。

以前はHHKBを使っていたので、これに近い65のものも迷いました。しかし、写真をみた限りで「`~」がESCと同じ位置にあって、多分何かのキーと複合で押す形になるんでしょうが、プログラマ的には「```」を結構使用する関係で絶対面倒に感じるだろうなと思ってやめました。これさえなんとかなっていれば65を選んでたくらいには好みでしたが。

HHKBから切り替えて困ってしまったことといえば、JISのHHKBに戻すと思い出すのに時間がかかるのと持ち運びができないことです。近年はオフィスはフリーアドレスで自席がないことが多いですし、カフェなどで作業したい際にはやっぱり外付けのいいキーボードで作業したいなというのがあり、持ち運び用のものはどうしようか悩んでいます。USのHHKBを買うか、もしくはAirを買うかで頭を悩ませています。Airの方はロープロファイルなのであんまり好きじゃないかも、みたいな点で悩んでいます。JISをメルカリで売ってから考えてもいいかもしれません🤔

切り替え時にやったこと

さて本題ですが、切り替え時にやったことです。前提として、私は仕事プライベート含め、macOSしか使いません。なので、前提としてMacの話になります。

JISからUSへの切り替えですが、Karabinarを使うと比較的楽にできます。しかし変えたら変えたで苦労した点もあり、この辺りをまとめておきます。ポイントは下記でした。

  • 「かな」と「英数」の切り替えをCmd単体でできるように
  • Cmd単体操作の微調整&「Cmd+Q」を数秒押さないと稼働しないように
  • CapsLockと左下のCtrlの入れ替え

MacのUS配列標準では、「Fn」キーを単体で押すとトグル方式でかな入力と英数入力(というかIMEの入力言語でしょうか?)を切り替えられるほか、「Control + Space」でもトグル方式で切り替え可能です。しかしWindowsの「半角/かな」キーをはじめとしたステートフルなこの切り替え方式は好きではなく、MacのJIS配列にあった「英数」「かな」の切り替えが非常に良いデザインだと思っています。なのでこれをUS配列でも再現したいわけですが、一方でUS配列には「かな」「英数」の切り替え専用のキーはありません。

これを実現するためには、いくつか手段がありますが、私が最も有力かなと感じたのは「左のCmdキーを単体で押したら英数入力に切り替え、右のCmdキーを単体で押したらかな入力に切り替える」というものです。これならJIS配列のときと切り替え方法をほぼ変えずに済みます。これを実現するには、Karabinarというソフトウェアを使いつつ、このソフトウェアに追加の設定を行う必要があります。

やり方は下記のサイトに書いてあり、こちらを参照するか

misc-log.com

私のdotfilesのリポジトリを参照することでも確認できます。Karabinarは設定をJSON形式でエクスポートでき、普段はエクスポートしたものをdotfilesに置いて管理しています。

github.com

ただ、この「Cmd単体で押したとき」の判定が若干シビアです。たとえば、「Cmd」を押した後にすぐ「W」を押すと、普通にショートカットキーを押した判定をされてしまい、結果文字入力中にウィンドウが閉じてイライラしてしまうことが最初多発しました。Cmdキーを単体で押した判定をさせる時間を伸ばすなど若干のカスタマイズが必要でした。完全に対策できたわけではないので時々今でも起こりますが、頻度はかなり減りました。

上記のショートカットキーを押してしまう問題で致命的だと感じるのが「Cmd+Q」(アプリケーションの終了)でした。これが起こるとたとえばターミナルが突然落ちることになるので、コーディング中などは非常に困りました。そこで、Cmd+Qだけは特別に、1秒以上両方のキーを押し続けないと終了動作が作動しないように調整を加えました。KarabinarのJSONを直接いじって対応させました。

github.com

あとUS配列に変更したこととはあまり関係ない話かもしれませんが、Nuphyは、HHKBだとControlキーの位置にCapsLockがあって、HHKBだとCapsLockの位置にCtrlがあるレイアウトになっています。普段はNeovimで作業する関係でHHKBのレイアウトになっていてくれないと非常に厳しいので、Karabinarを使って、CapsLockとCtrlを入れ替えしました。これによりこれまでの操作感を損なうことなくVimを操作できるので快適になりました。これはやっている方が多いかなとは思いますが、重要な作業だと思います。

切り替えてよかったこと・ストレスを感じること

プログラミングで出てくる記号類が、実はUS配列だと手数少なく押せると判明した点でしょうか。たとえばバックスラッシュ\なんかは、JISだと遠い位置にあって面倒だしどこにあったかもあんまり覚えてない、みたいな感じだったんですが、USだとShiftも不要で入力できてしまいます。シングルクオート'やダブルクオート"も入力するのめんどくさいランキング上位でしたが、これもUS配列だと押しやすい位置にあります。

何よりも、キーボードを選ぶ選択肢が格段に広がるというのも大きいです。YouTubeチャンネルなどでキーボードをアンボクシングする動画を見るのが結構好きなんですが、「US配列なんだよな〜〜〜」と思うものが結構多かったです。しかし、US配列に切り替えてしまった今となっては、こうした憧れのキーボードにも手が届くようになりました。散財が捗ってしまうなあと今から悩みが尽きません。

www.youtube.com (「:3ildcat」というチャンネルをよく見ていました)

ストレスを感じることとしては、まずはホームポジションの中心がJISから微妙に右にズレる?ので、まだそれに慣れません。無意識にJISの頃の位置に指を置いてしまう関係で、よく打ち間違いをします。

また、記号はまだ完全には覚えられていません。*をよく打ち間違えるのと、()のふたつもまあまあ正確に押せずにイライラします。この辺りはストレスを感じますね。

加えて、「Cmd」を使った英数とかなのモードの切り替えをしている関係で、だんだん筆が乗ってきてタイピングのスピードが上がってくると、ショートカットキーを誤って押してしまってイライラすることがあります。「Cmd+Q」による終了は制御したのでこれは起こらなくなりましたが、たとえば「Cmd+W」のウィンドウを閉じるものはしょっちゅう起きてしまいます。ただこのショートカットはQのときのように長押しにすると使い勝手が下がってしまうのでそうするわけにもいかず、ちょっと悩み中です。

あとMac本体はJIS配列のままなので、ラップトップを開いてキーボードを使う際には頭を切り替える必要があります。これは外付けキーボードを持ち歩けば解消できる話なので、今のところはあまり気にしていませんが…。

総じてJIS配列だったころと比べると打ち間違いは格段に増え誤操作も格段に増えましたが、JIS配列だった頃には得られなかった自由も手にできたので、しばらくはUS配列を利用し続けてみようかなと思っています。

追記:このリンクのコードを使うとNuphyを10% offで買えます。もしよければぜひ使ってください→nuphy.refr.cc

はてなブログのドメインをお名前.comからCloudflare Registrarに移行した

タイトルの通りでドメインを移管したので、そのメモを残しておきます。ほとんどスムーズに行ったけど一つだけハマったポイントがありました。同様のドメイン移管を検討している方の参考になれば幸いです。

背景

このブログで利用している「blog-dry.com」ドメインの更新期日が迫っていたのですが、ちょうどお名前.comからのメール配信がうざかったことを思い出して、周囲の知人からの評判がよかったCloudflareに移管することにしました。

お名前.comは以前から「管理画面へのログインが確認できませんが保護対策はお済ですか?」という旨のタイトルのメールを送ってきていたのですが、このメールはモニタリング設定という有料オプションへの誘導になっています。ただこのオプションは利用したくないため放置していたのですが、そうすると永遠にメールが配信されます。これが嫌で移管することにしました。たぶん、メールの配信設定を管理画面でちゃんとやれば届かなくなります。

今回はサブドメインは使用しない前提です。

手順

手順は下記が参考になりました。実際この通りにやるとうまくいきます。

zenn.dev

余談ですが私も VISA の楽天カードで支払い登録をして移管作業を行い、最後の最後まで来て支払いを押したところ、なぜか決済がエラーでうまくいきませんでした。PayPal に変えたらうまくいったので、最初から PayPal で登録しておくとスムーズだと思います。

はてなブログ特有のはまりポイント

ドメインを移管すると自動でお名前.comから設定が読み込まれますが、「DNS Records」の画面の「Proxy Status」が「Proxied」になっているとうまくいきません。「DNS only」のモードに直す必要があるようです。

developers.cloudflare.com

Proxied にすると Cloudflare のグローバルネットワークを利用し、これによりキャッシュの最適化やより強固なセキュリティ保護を受けることができるようになります。ただ、Proxied にすると全然違うところ(Cloudflare 管理の IP)を向いてしまいます。

❯ dig blog-dry.com

; <<>> DiG 9.10.6 <<>> blog-dry.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6515
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;blog-dry.com.                  IN      A

;; ANSWER SECTION:
blog-dry.com.           93      IN      A       172.67.188.61
blog-dry.com.           93      IN      A       104.21.48.225

;; Query time: 10 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul 12 06:29:50 JST 2023
;; MSG SIZE  rcvd: 73

DNS only にしておくと、Cloudflare をバイパスして DNS サーバーだけを利用するようになります。この設定に直すと正しくはてなブログの求める 13.230.115.16113.115.18.61 が返ってくるようになります。

❯ dig blog-dry.com

; <<>> DiG 9.10.6 <<>> blog-dry.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11987
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;blog-dry.com.                  IN      A

;; ANSWER SECTION:
blog-dry.com.           300     IN      A       13.115.18.61
blog-dry.com.           300     IN      A       13.230.115.161

;; Query time: 200 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jul 12 07:03:03 JST 2023
;; MSG SIZE  rcvd: 73

qiita.com

DNS only モードでも DDoS からは守ってくれます。が、代わりに Cloudflare に置き換えることによるページ表示スピードの高速化といった恩恵は一切受けられなくなります。はてなブログで Cloudflare を用いてサイト表示スピードの高速化を検討している方は、最初からこの選択肢がないように思います。注意が必要なポイントです。

『フロントエンド開発のためのセキュリティ入門』を読んだ

『フロントエンド開発のためのセキュリティ入門』という本を読んだので、簡単にどのような内容だったかをまとめておきたいと思います。

内容について

フロントエンド開発で必要になるセキュリティ面の知識を体系的に得ることができます。対象としてはフロントエンドエンジニアになって1年目〜3年目くらいの若手向けのようなことが本書のどこかに書いてあった気がしますが、フロントエンド歴の短い私のようなエンジニアが最初さらっと入門するのにちょうどよい塩梅だと思いました。

一方で深めの内容は意図的にカットしてあるか別の書籍を参照するように誘導がなされています。フロントエンド歴は短いもののバックエンドの歴は比較的長めな私のようなエンジニアが入門する際には、少し物足りないと思ってしまうかもしれません。購入の際にはご自身が想定読者に含まれるかは検討したほうがよいかと思いました。

ハンズオンがあったのはとても嬉しかったです。まずセキュリティバグが含まれるコードを書いてみて、そのあと本書の中で解説していた対策をもとに実際にセキュリティリスクを潰していくことができます。ハンズオンは Node.js を使用します。

構成としては、いくつかの導入ののちにまず HTTP の解説が行われます。その後はいわゆる CORS 周りの話、XSSCSRF、クリックジャッキング、オープンリダイレクトの話が続きます。認証認可周りのセキュリティリスクを確認したのち、近年話題に上ることの多いサプライチェーンアタックに関連する話が続きます。

目次は下記です(翔泳社のサイトより引用)。

第1章 Webセキュリティ概要
第2章 本書のハンズオンの準備
第3章 HTTP
第4章 オリジンによるWebアプリケーション間のアクセス制限
第5章 XSS
第6章 その他の受動的攻撃(CSRF、クリックジャッキング、オープンリダイレクト)
第7章 認証・認可
第8章 ライブラリを狙ったセキュリティリスク

感想とか

読んだ動機としては、しっかりめのフロントエンド開発をする必要が出てきたからでした。フロントエンド周りの開発はこれまでも何度か経験はあり、本書に出てくる用語のほとんどは直面したことがあるか、聞き馴染みがあるか、調べたことがあるかのどれかでした。が、改めて書籍でしっかり説明されると体系的に自分の知識を整理することができ、よい読書になったなと思っています。

とくにその場しのぎの理解で終わっていたなと思っていた箇所は

  • Content Security Policy に関するもの
  • SameSite Cookie に関するもの

あたりで、昔業務で直面して対策をした記憶はあるのですが、改めて何がダメで、防げると何が嬉しくて…といった点を整理できました。

ハンズオンはとりあえず興味があったり、「そもそもこの言葉を知ってはいるけど、具体的になんだっけ」と思った箇所を中心に取り組み中です。書籍の手順をそのままさらうだけで再現できたのもよかったです。

現実のアプリケーションでの発生事例はもう少し詳し目に載っていると、より実感が湧いてよかったかもなとは思いました。というか知りたかったと思いました。もちろん調べればいくらでも出てくるのですが。たとえば「こういう会社でどういう事例があって、どのくらいの影響(売り上げやユーザー数など)があったか」などを軽く紹介してもらえると、深刻度合いがより伝わってよくなったかもなとは感じました。

2022年の振り返り

今年は忙しくていろいろ思うところがあったので、振り返りがてらインターネットに記事を放流しておこうと思います。仕事の話のみで、プライベートの話は書かないつもりです。

仕事

転職

6月に転職をしました。

ここ数年、今後のことを考えると早いうちに英語を使った仕事をしたいと考えていて、それを実行に移した形になりました。サイバーエージェントをやめるつもりはほとんどなく、最後までそれなりに悩んだのですが一旦離れることにしました。英語に満足するかクビになるかしたら戻りたいと思っているくらいにはいい職場でした。元同僚とも定期的にゲームや食事などに誘っていただいて、今でも遊んでもらっています。感謝。

転職自体は LinkedIn 経由です。外資転職したい方向けの情報ですが、LinkedIn に英語のプロフィールを載せておくとリクルーターから連絡が来ます。大半は人材会社からのものでスルーしているのですが、時折事業会社のリクルーターから連絡が来ます。今回はそれに返信をして、面接まで進ませていただいたという経緯です。

仕事で英語を使いたいという目標は無事に達成されました。働いている時間はずっと英語をしゃべっているかチャットを書いていますし、ミーティングもほぼすべて英語です。私は英語は困りはしないものの子どもの頃の記憶で止まっているので、中高生までいた帰国子女ガチ勢の方々と比べると全然喋れない部類に入ると思います。あと、最近だいぶ直せた気がしていますが元々ブリティッシュアクセントなのもあり、最初は同僚にそのことで「どこの出身なの?」と聞かれることが多かったです。だいたいオーストラリアですか?と聞かれるのですが、多分私の発音は RP (Received Pronunciation) というやつです…。RP は下記の動画みたいなアクセントです。

www.youtube.com

就活で外銀などを受けていたときに聞いていた話なんですが、「アメリカアクセントで話してくれ」とか「ブリティッシュな言い回しをするな」みたいなことを言われるという(まことしやかな)噂話を聞いていました。最初これにビクビクしながらアメリカの会社に入ったわけですが、今のところ直されたのはスペリング(たとえば、authorize を authorise と癖で書いてしまうとか)くらいで、それ以外は特段何も言われていません。なんか妙に安心しました。

職場は非常にグローバルです。いろんな国籍の方がいます。先日もフランス出身の同僚が入社したのですが、フランスは哲学の国ということで永遠にミシェルセールとかルネジラールの話で入社時1on1で盛り上がっていました。こういう会話をすると、グローバルな環境で働けるって楽しいなと純粋に思いますね。

ただ一方で、この「英語を使いたい」という目標の置き方はあまりよくないなと思いました。というのも「やりたい仕事ベース」や「扱いたいシステムの規模、チームの価値観ベース、好きなドメイン」の軸で移ったわけではなかったからです。なんというかサイバーエージェントにいた頃とあんまりチームの規模も扱うドメイン領域も変わらないところに移ってしまったので、ちょっと変わり映えのない仕事生活を送っています。というわけで、バックエンドエンジニアとして採用されましたがデータエンジニアに手を挙げて、今までのキャリアではあまりやったことのなかった、ちょっと新しいことをやりはじめています。これは楽しいです。ちなみに今の会社の人たちも、人格的にもスキル面でも非常に尊敬できる人たちでよい職場環境だと思っています。

アメリカの会社に入って感じたことですが、日本の会社で培った経験やスキルは普通に生きます。あるいは職位にもよるかもしれませんが、日本の会社でそれなりにソフトウェアエンジニアとしてキャリアを積んだ方であれば同等の職位で移れば普通に通用すると思うので、英語さえなんとかなれば大丈夫そうだと思いました。もし外資への転職を検討されている方がいたら、ちゃんと日本の会社で成果を出すのが外資に入って以降のためにも重要だと思います。

働き方は今の時代らしくフルリモートになりました。が、転職前から薄々気付いていましたがフルリモートが辛いことがわかってきました。やはりサイバーの頃のように、リモートとオフィス出社のハイブリッド型で働けるのが理想的みたいです。オフィスでワイワイ雑談しながら仕事を進める方が好きかも。2023年にはコロナが収まってきてハイブリッド型の出勤スタイルが世の中的に普及するでしょうか。

執筆・登壇

某大手メディアでの連載

今年は日系の大手メディアで毎月 Rust の連載を書かせていただきました。毎月連載すると文章力が明らかに向上します。また入門記事を書くと、自分の Rust に対する理解も深まります。もう Rust の入門は書かないし登壇もしないかなというくらいにはお腹いっぱいになりました。全部出し切ったという意味です。

あの記事の裏話ですが、結構文字数制限が厳しく書きたいと思っていた内容をすべて書き切ることはできませんでした。編集の方が大変がんばってくださって、たとえば連載を3回に分けていただくなどしていただきましたが、それでもかなり意識をして分量を減らした上での提出でした。単純に私が書く文章が長いのもありますが、そもそも Rust の機能が幅広すぎて収まりようがなかったようにも見えます。

国内では由緒あるメディアですし、読者はおそらく IT 関連の会社の経営者や部長クラスではあるため、そうしたレイヤーに Rust を売り込めるという意味ではよい機会でした。売り込めたのかはわかりませんが。ただ、有料記事だったこともあって主に周りからの反応が観測しづらかったのは、記事を書いている側としては物足りないポイントではありました。

ちなみにこの連載により Rust の本を経費で買う口実ができたので、今年は経費で Rust の関連書籍を片っ端から買っておきました。

WEB+DB PRESSの寄稿のレビュー

雑誌への寄稿を実践Rustプログラミング入門の共著者の吉川さんがすることになったようで、レビュワーとして声かけしていただきレビュワーとして参加しました。貴重な機会になりました。ありがとうございます。

これまでの技術関連の書籍の執筆や連載の経験から、おそらく一番大変なのはファクトチェックだろうと思い、その辺りの話を中心にレビューコメントを残すようにしました。ファクトチェックというのは、たとえば「Rust のライフタイム」という単語があったとき、その和訳であっているかをソースを辿ってチェックしたり、言葉の定義を何箇所かの文献で確認して正しそうかを確かめたりすることです。

ファクトチェックは本来であれば編集者がやる仕事かなとは思いますが、出版社の編集者は実質 PM なのでとくにされない傾向にあります(してくれる方もいます)。この作業をやらないと書籍としてのクオリティが普通に下がるので個人的には必須の作業だと思います。

費用対効果では雑誌への寄稿が一番おいしいと聞いていましたが本当でした。個人的には、「雑誌への寄稿 >>>>> 単著出版 >>>>>> 共著出版 >>>>> Web メディア執筆」くらいの順かなと思いました。

登壇

というわけでこの2つとさらに ISUCON があった関係で、登壇は意識的に抑えていました。今後も絞って登壇すると思います。基本的には入門者向けの登壇はほぼしない方針で、中上級者向けというかすでに Rust を使っている方向けの話をしていきたいです。

今年は TechFeed Experts になった関係で、TechFeed さんのイベントに呼んでいただき一度だけ登壇しました。20分間の枠の登壇はかなり久々でしたが、なんとか時間通りくらいで登壇できたように思います。登壇時の書き起こしは下記です。

techfeed.io

ISUCON

今年の特筆事項としては ISUCON があります。準備から開催まで、正直にいうと大変でなかったわけではないのですが、前職の同僚と最後にチームプレーで開発できた最後の機会で、改めて非常に楽しかったです。実装面での詳しい話は下記の Zenn にまとまっています。

zenn.dev

今年はサイバーエージェントが作問を行うということで参加した形でした。もともとサイバーエージェントのゲーム部門では「ヒダッカソン」という ISUCON を参考にした競技が行われていて、学生向けのそれを1日インターンとしてやった際、レビュワーとして参加させてもらったことがありました。その縁で今回のリーダーの方に声をかけていただき、作問に参加したという経緯です。私は唯一広告部門の人間でしたが、他のメンバーは全員ゲーム部門の方々でした。

OSS

OSS については今年はほとんどやれませんでした……といいつつ、実は仕事でライブラリをいくつか作ったり公開したりしています。

一つは Conventional Commits の記法を利用したコミットログを分類して、リリースノートを生成するツールです。TypeScript で関数型プログラミングをするという完全に趣味全開の実装にしました。ただこれはあとで気づいたのですが、実は Google が同様のツールを出していました。

github.com

また、使っているクレートにパッチを投げました。こちらは手続きマクロを使って新しい機能を追加しました。

github.com

来年は、とくに OSS への比重を高めていきたいと思っています。Rust もそろそろ十分に普及しうるフェーズに入ってきたと思いますし、執筆や登壇よりは優先度を上げたいと思っています。使っているクレートにほしい機能があったら積極的に追加実装したいし、ドキュメントのリンク切れがあれば修正パッチを投げていきたいです。ならびに、仕事で Web アプリケーションを実装するだけだと自分の力量が伸び悩んだりあるいは飽きが来たりすると思うので、たとえば言語処理系のプロジェクトに参加してみるなどして自分の知見を広められるようにしていきたいです。

来年

来年は30代にはよくあるライフイベントが発生する関係で、5月か6月くらいからしばらくお休みをいただく予定です。復職したらまた適当にがんばっていきたいと思います。まずは人生の最難関を乗り越えるとき…!無事に生きて帰ってこられることを願っています。

『ソフトウェアアーキテクチャ・ハードパーツ』

『ソフトウェアアーキテクチャ・ハードパーツ』を訳者の方からご恵贈いただきました。ありがとうございます。献本については基本的にすべて書評を書こうと思っているため、今回も記事にします。発売は10/27のようです。

おことわり

まず指示語についてです。記事中で「本書」「この本」と書く場合は『ソフトウェアアーキテクチャ・ハードパーツ』を指します。また、「著者」は本書を執筆した人を指すものとします。「筆者」といった場合、それは私のことです。

いわゆるスキミングをした状態で一旦書評をするため、本書の細かい議論の見落としや用語の誤認識が含まれる可能性があります。この書評はあくまで「どういった本か」「他の書籍と比較してどういった新規性がありそうか」などを紹介することを目的としています。逆に細かい議論の是非についての議論は目的とはしていません。

概要

本書はソフトウェアのアーキテクチャを考える際に避けては通れない、適切なアーキテクチャを選定するために必要になる「選択肢を提供」する一冊です。具体的にはマイクロサービスをどう分割するかといった話題や、どうコンポーネントを再利用できるようにするか、トランザクションをどう考えていけばいいかといった話題について具体的にパターンを紹介しています。ただしそれらのパターンは「これがベストプラクティス」として一つに定められるほど単純なものではないため、トレードオフを考えつつ「選択するパーツ」として紹介されています。

また、最近話題になっていた『ソフトウェアアーキテクチャの基礎』(以降、「基礎」)を執筆した著者陣が書いたもう一冊の本でもあります。「基礎」はアーキテクトとしての姿勢や、それぞれのアーキテクチャの簡単な概要が中心でしたが、この本はより実践に近く方法論寄りです。「基礎」が「What」を扱うとすれば、本書は「How」を扱うといった関係性でしょうか。

普通は一冊の中で語られることが多いであろう What と How が、なぜ分冊になったのかという疑問が浮かぶかもしれませんがこれには理由があるようです。ソフトウェアアーキテクチャにおける方法論は現実のシステムにナイーブに適用するのは難しく、こうした込み入った話はいわゆる原則を扱いたかった「基礎」では扱えなかった話題という事情があったためのようです。本書の冒頭でまず下記のように説明されています。

Neal と Mark は前著『ソフトウェアアーキテクチャの基礎』(オライリー・ジャパン)を執筆していた際に、内容を取り上げるのを諦めざるを得ない、込み入ったアーキテクチャの例に何度も遭遇した。そうした例は、簡単なソリューションを持たない、厄介なトレードオフの塊だった。二人はそうした例を「ハードパーツ」と名づけ、脇に避けていった。

現代ではデータをどのように設計し、分割しつつ整合性を保って保管しておくかといった一連の流れの重要度が増しています。この問題についても本書は拾い上げるよう努力しています。[*1]従来のアーキテクチャの議論では、マイクロサービスはどう分割するかとか、コードの関心事がどうこうとかそういったアプリケーションに限った範囲が中心だったように私は思っています。が、そうではなくデータをどう分割、配置、保管していくかといった問題についても議論に含めるようにしています。本書は「Modern Trade-Off Analyses for Distributed Architectures(”現代の”分散アーキテクチャのためのトレードオフ分析)」という副題になっていますが[*2]、そうした意味においてまさに現代版に刷新された新しいアーキテクチャ方法論ではないかと私は思いました。

構成

目次だけを拾い上げると下記のような構成になっています。

  1. 「ベストプラクティス」がないとどうなる?
  2. ソフトウェアアーキテクチャにおける結合の見つけ方
  3. アーキテクチャのモジュール化
  4. アーキテクチャの分解
  5. コンポーネントベース分解パターン
  6. 業務データの分解
  7. サービスの粒度
  8. 再利用パターン
  9. データの所有権と分散トランザクション
  10. 分散データアクセス
  11. 分散ワークフローの管理
  12. トランザクショナルサーガ
  13. コントラクト
  14. 分散データの管理
  15. 独自トレードオフ分析を構築する

2〜7章はいわゆるマイクロサービスの分解に関する章です。そして8〜14章はマイクロサービス間をどのように繋ぎ合わせていくか、そのプラクティスが紹介される章です。最後の15章では、実際にアーキテクトが自分自身のトレードオフ分析を本書のように作り上げる手法について簡単に解説されています。

私がとくに熱心に読んで印象に残ったのは5章と7章でした。本書の雰囲気を感じ取ってもらえるように、簡単に内容を引用しておきたいと思います。

5章ではモノリシックなアプリケーションをマイクロサービスに分解していくまでに、どういった手順を踏んでいけばよいかについての例が示されています。こうした形で体系的にまとめられた例はあまり見たことがなく、私自身も仕事で活かしていきたいなと思いました。

手順は(英語版のもののスクリーンショットから引用していますが)下記の図のようにまとめられています。次のような手順を踏んでいくと、ぶれなくマイクロサービスに分類していけるはずだという手法が示されています。著者らはマイクロサービスへの移行について、「思いつきで移行していい結果を生むことはほとんどない」とp.128で語っていますが、まさにその通りで勘に頼らず明文化した手順で取り組むのは何事においても重要です。

コンポーネントベースの分解の流れと使い方(電子書籍版の原著より引用)

7章ではより細かい単位でサービスを分割する分析基準について扱われています。5章ではいわゆるドメインサービスの分割に関する粒度までが扱われていたのですが、7章では「粒度分解要因」と「粒度統合要因」の2つの観点から、もう少し小さくサービスを分解する分析基準について議論されます。

粒度分解要因については「サービスの範囲と機能」「コード変動率」「スケーラビリティとスループット」「耐障害性」「セキュリティ」「拡張性」の観点に着目し、分離できるポイントを探していくとよいとされています(各観点の詳細は本書をご覧ください)。マイクロサービスの分解については私は正直ドメイン駆動設計で言われるような「境界づけられたコンテキスト」単位での分割しか考えたことがなかったのですが、それでは粒度が大きすぎるケースが多々あるのもまた悩みでした。これらの着目点によってもう少し分解できるという新たな視点を得られたように思います。

粒度統合要因は分解の逆です。逆に小さくなりすぎて不便になったサービスを統合するための着目点について議論されます。「データベーストランザクション」「ワークフローとコレオグラフィ」「共有コード」「データ関係」の4つの観点に着目し、結合できるポイントを探すとよいとされています(各観点の詳細は本書をご覧ください)。私が知らないだけかもしれませんが、マイクロサービスはついつい分解の方法に焦点が当たりがちで、分解しすぎたものを結合する手法についてはこれまであまり解説されてこなかったように感じています。

それぞれの「要因」についてはただ手法が解説されるだけではなく、何を目的として行われるべきかも補足説明されているので、導入の際に手段が目的化することも避けられそうでよさそうに感じました。私も今の現場で、サービスの構成に関して個人的に思うところがあるので、この手法を議論の土台にして問題提起してみたいなと思いました。

新規性

概要時にある程度書ききってしまったようにも思いますが、私が思った本書の新規性を紹介しておきたいと思います。

まず全体に通ずる話として各プラクティスを「ベストプラクティス」ではなく「トレードオフ」として紹介しています。ベストプラクティスとして紹介されてしまうと「本当にこれがベストなの?たとえばXX(目的から外れたもの)の場合はどうなの?」をはじめとした本来の目的を忘れたコーナーケースを突く不毛な議論や「これがベストなのだから他を選択する必要はない」といった思考停止が発生してしまう可能性が考えられます。一方で「このプラクティスはトレードオフである」としておくことで、「このケースではこういうデメリットはあるが、それは問題なさそうなのでこれが使えそう」といった選択の考慮と余地が生まれることになります。これは結果的に建設的な議論になり得ると私は考えています。著者の「(そのシステムにとっての)最悪のアーキテクチャを選択しない」という信条ともマッチしています。

アプリケーション内におけるデータ周りの管理に関してかなり明文化されたプラクティスを紹介しています。たとえばマイクロサービス化の文脈において、デプロイの単位が分けられたデータベースの分割は切っても切り離せないという話は多くのソフトウェアエンジニアが認知するところと思います。しかし、分割時に具体的にどういう手法があって、それらにどういうメリットデメリットがあるか整理されている資料は、単に私の認識の範囲が狭いだけかもしれませんがあまり見たことがありません。システムの柔軟性担保やデプロイ容易性を目的としたマイクロサービス化のために「データベースをきちんと分割しましょう」はわかるのですが、「でも具体的にどうやって?」の部分が暗黙知だったように思っています。少なくとも私はそうでした。同様に現在多くのシステムで利用されているであろうサーガパターンについても、本書ではなんと8つもトレードオフの分析込みでプラクティスが紹介されています。

感想

最後に雑多な感想を記しておきます。

定義づけて不毛な議論を避ける

まず、暗黙的に意味を受容してしまいがちな用語の定義をきちんとしてから話題に入っていくのがよかったです。これは「基礎」のときから継続的に著者らが気をつけていることかもしれませんが。たとえば印象的だったのは「1.6」の用語集でした。下記の引用は「結合」という単語の定義です。これは「疎結合」などさまざまな場面で登場してくるような、ソフトウェアエンジニアリングの文脈では非常に一般的な用語ではあるのですが、改めて「本書での意味」をきちんと定義づけしてから議論がはじまっていきます。

2つのアーティファクト(サービスを含む)は、適切な機能を維持するのに一方の変更が他方の変更を必要とする場合、結合されている。

ソフトウェアアーキテクチャに関連する本の多くはこうした定義づけがなく、ボヤッとした状態で議論が進むように感じます。[*3]一部のディスカッションを見ていると、そのボヤッとした土台をもとに読者(識者?)が独自の解釈を生み出し、肝心のソフトウェアをどう作り上げるかの議論ではなく、用語の意味をどう解釈するかについての議論でなぜか盛り上がる印象があります。これについては解釈のできる限り余地をなくすよう、概念を導入する側が定義づけをきちんとするべきだと個人的には思っています。

用語の定義づけというのは、こうした自転車置き場の議論というか、「解釈学」の発生をある程度防ぐことができるため非常に重要です。とくに「結合」のように、もはやソフトウェアエンジニアの間で暗黙的に利用されている用語についてきちんと定義づけをし、適用範囲を閉じてから議論を始めるのは重要です。また、仮に既存の定義づけを利用するとしてもどの識者の学説や発言に依って議論を進めるかを明示するだけでも十分効果があると思います。

「最悪を避ける」ための「トレードオフ」 = 「その状況によりあったもの」を探す旅

「基礎」に引き続き「これが唯一の正しいベストプラクティス」として本書の中のパターンを紹介しないのもよかったなと思いました。トレードオフという言葉はまさに言い得て妙です。私も日常業務で経験がありますが、アーキテクチャの考案というのは「どちらかを立てるとどちらかが立たなくなる」選択の連続のゲームです。

一方で本書では「ケースバイケースだよね」とか、「唯一の絶対正しい解はこれだ。議論の余地なし」として思考停止して片付けず、「最悪でないもの」を探るべく対話を繰り返しながらトレードオフの選択をひとつひとつ決めていきます。アーキテクチャの議論をしていると、ついつい「こうしなければならない」といった思考に陥りがちですが、実はとった選択肢にも何かしらの不味い点があることが多いです。たとえば思いつく単純な例ですと、レイヤードアーキテクチャを選択して各レイヤー間の依存を分けておくと、一部に変更が生じたとしても影響範囲が狭まるというメリットがあるかと思います。一方で、影響範囲を抑えるために多くのデータ変換を行う必要が出てくるわけですが、このデータ変換のメンテナンスコストが意外とかさみ、結果開発を遅らせることがある…などでしょうか。

少し話が逸れてしまいますが、現代は「ケースバイケース」の時代ではあると思います。(私は学生の頃哲学が専攻でしたので少しこの話を掘っておくと、)これを哲学の用語で相対主義と言ったりします。[*4]ただこのケースバイケース、「ケースバイケースである」としてそれ以上の議論を避ける傾向にあります。「ケースバイケース」が一つの結論になってしまうからです。しかしこの結論では議論によって合意をし、何かひとつ選ぶという行為を放棄してしまうため、そもそも何かが新しく判明したりはしません。仕事で言えば、何度ミーティングを開いたとしてもいつまでも物事が決まらず前に進んでいないのです。

私たちはアーキテクチャを考える際、相対主義に取り憑かれることなく、著者らのいう「最悪でないもの」、つまり裏を返せば「より適切」を見つける旅に出る必要があります。歴史が証明してきた通り唯一の正解というものはこの世界にはありませんが、その状況に合ったより適切な選択は合意によって導き出せます。その議論の際に「トレードオフ」の形で本書のプラクティスをひとつひとつ見つめ、その中から一つを吟味して選びとるのはとても有意義な結果を我々にもたらすはずです。

合意を取り物事を決める様は、本書の「Syspos Squad」の例を通じて一部知ることができますが、私も日々の開発の現場でこうした対話をできるようになりたいなと思わされました。本書を読み終えた後の次なる課題は「チーム全体にこのようなディスカッションをできる土壌をどう育てていくか」だったりするわけですが、それはまた別の解を探すことにしましょう。

*1:同じくオライリーの『データ指向アプリケーションデザイン』という本を読んでそれを熱心に考えた方も多かったはずです。

*2:邦訳時になぜか Modern の部分がまるっと落とされているのが気になりましたが。

*3:DDD の青い本とか。解釈するのは一つの享楽ではあるのですが、ただそれは何か別の学問のように感じます。そもそも読みが複数生まれる本は、少なくとも工学的な書籍においてはあまりいいものとは思えません。というのも、よく人文系学問で言われるような「読みの余地」は工学の目標ではないはずだからです。

*4:相対主義も哲学の分野によって微妙に定義づけが異なりそうなので補足ですが、私が念頭に置いているのは倫理学で一般に言われる相対主義の方です。『現代倫理学入門』(加藤尚武)や、あるいは『「みんな違ってみんないい」のか?』(山口裕之)などが念頭にあります。

26. Remove Duplicates from Sorted Array

ソート済みの、複数数字が重複する配列の中には一体何個の数字が含まれているかを考える問題。制約として、in-place で解く必要があります。たとえば、[1, 1, 2] という入力がされた場合、返り値は2で [1, 2, _] という順序の配列を返す必要があるということです。

leetcode.com

ただ、いまいち問題の意図がつかめず苦戦しました。単純に国語力の試される問題でもあります。実装は単純でした。

方針としては、

  • i と i+1 (i は配列のインデックスとする) 、要するに隣同士の数字を比較し、右の値が左の値より大きければ入れ替えるという作業を繰り返します。
  • 入れ替える作業が発生した場合、それは実質異なる数値を入れ替えることになるので、カウンターを1つ足します。

という作業を繰り返すだけで解くことができます。問題の意図が理解できれば捻りはとくになく素直な問題ではあります。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        k = 0
        for i in range(len(nums)):
            if nums[k] < nums[i]:
                k += 1
                nums[k] = nums[i]
        return k + 1

時間計算量は O(n) でしょうか。与えられる配列の長さが増えると、その分だけループが多く回ることになります。

空間計算量は in-place な操作をしていることもあり O(1) になります。