valid,invalid

関心を持てる事柄について

1Password CLIから指紋認証でパスワードやOTPを取得する

1Password CLIから指紋認証でパスワードやOTPを取得する方法について。

1Password CLIは使ったことがなく、Your CLI wish is our command 🪄💫 | 1Passwordを見て興味を持ち、セットアップしたらとても便利だった。

セットアップ手順

1. 1Passwordのセットアップ

まず https://1password.com/downloads/mac/ 1Password 8以上のデスクトップアプリをインストールする*1

2022-03-28時点でApp Storebrew install 1password では7系しかインストールできない。かつ、macOSの1Password 8はbeta扱いなので画面下のほうにある以下のリンクからダウンロードする。

インストールした1Passwordを起動してログインしておく。

2. 1Password CLIのセットアップ

https://developer.1password.com/docs/cli/get-started を参考にすればよい。一応手順を書く。

1Password CLI v2以上をインストールする。

https://1password.com/downloads/command-line/ からダウンロードしてもいいし、brew install 1password-cliしてもよい。brewでもv2をインストールできる。

インストールしたらCLIからアカウントを追加する。

$ op account add
Enter your sign-in address (example.1password.com):
Enter the email address for your account on <sign-in address>: 
Enter the Secret Key for <email address> on <sign-in address>:
Enter the password for <email address> at <sign-in address>:

Vaultにある 1Password Account (<username>) に書いてある内容を移せばOK。

項目 入力事項
sign-in address 個人アカウントなら大抵は my.1password.com でよいはず
email address (1Passwordアカウントのメールアドレス)
Secret Key (1PasswordアカウントのSecret Key)
password (1Passwordアカウントのパスワード)

次に、追加したアカウントにCLIsign inする。

$ eval $(op signin)
Enter the password for <email address> at <sign-in address>:

account addしてもアカウントを追加しただけでsign inはできていないため、このコマンドでsign inする必要がある。ちなみに1Passwordに設定した期間で強制sign outされる。

3. 指紋認証を有効化する

1Passwordのデスクトップアプリで以下の手順を行うことで、パスワード認証ではなく指紋認証sign inできる。

  1. 1Password > Preferences で設定モーダルを開く
  2. Developer > 1Password CLI 2 にある Biometric unlock for 1Password CLI にチェックを入れる

試しにOTP取得してみる

上記のセットアップが完了していれば以下のコマンドにて、1Passwordへの指紋認証を経て各種itemのパスワードやOTPなどを取得することができる。

$ op item get my-item --otp

このOTPをパイプで流し込んだり、aliasを登録しておくとCLIでの多要素認証の手数が減る*2Your CLI wish is our command 🪄💫 | 1Passwordにあるように環境変数を流し込むようなこともできる。

コマンドについて

op item get { <itemName> | <itemID> } --otp

1Passwordに登録されたitemの情報を取得するコマンド。

itemNameに空白等が入っていてCLIとかで扱いにくいな〜ってときにItemIDが使える。

itemIDは op item listop item get で確認できる。

$ op item list
ID                            TITLE          VAULT     EDITED
2nkisfqj3bh2tb6soowptfkooa    my-item        Personal  3 years ago

--otp でOTP文字列を返す。OTP以外のフィールドも取り出し放題で、他にも様々なオプションがあるのでリファレンス参照。

関連ドキュメント

*1:当初、1Password 7で色々ためそうとして失敗した

*2:減ってよいのかどうか?は別議論

個人サイトのビルドツールをwebpackからViteに移行した

個人サイト https://ohbarye.github.io/ のビルドツールをwebpackからViteに移行した。

まぁ、移行と大げさに言っても、元々vanilla JSとSassでちょっと動きと装飾を付けただけのペライチページなのだけど。

f:id:ohbarye:20220323235841p:plain

実質ただのリンク集

理由

State of JS 2021のビルドツール部門でViteが1位になっていたが利用したことがなく気になっていたため。手元にある最小のフロントエンドプロジェクトが個人サイトだったのでplaygroundとして試してみた。

f:id:ohbarye:20220324000002p:plain

https://2021.stateofjs.com/en-US/libraries/build-tools より

Viteとは

Vite公式を斜め読みした。ランキング中だと経験あるビルドツールがwebpack, Parcel, Rollupあたりで止まっていたのでそこからの差分で理解すると...

  • esbuildというGo製の爆速ビルドツールが生まれた
  • でもまだproduction向けにbundleする機能は安定しておらず、webpackとかRollupのほうが成熟してる
  • Viteはesbuildを開発用に使い、production向けのbundleにはRollupを使う
    • esbuildを使ってdependenciesをpre-bundleしたり、HMR提供して開発体験を最高にする
  • 2つのツールの併用になるが、Viteはconfig周りの複雑さを吸収してデフォルトだとzero configで動く

という感じか。

移行手順

プロジェクトの外側でyarn create viteを試してみてどんなファイルが生成されるかを一通り眺める。vanilla JSとTypeScriptを選んだ場合は数ファイル程度だったのですぐに理解できた。

生成されたファイルやpackage.json内のnpm scriptやdependenciesを元々のプロジェクトにコピペする。

index.htmlがあるディレクトリをrootとし、相対パスで指定したファイルが依存ツリーに勝手に追加されていく。yarn devで起動し、おかしいところがあれば直す。今回はsassのインストールと、相対パスの置換ミスぐらい。

github.com

感想

2つのツールをラップしてると聞くと「結局開発者が両方知らないといけないやつでは...?」身構えてしまう。

ただ、https://ohbarye.github.io/のようにちょろっとTypeScriptやSassでサイト作りたい程度であればconfig知識ほぼ不要でセットアップできたし、このあたりはParcelの初出の頃を思い出した。

一部ビルドに工夫*1が必要なところも、Viteのconfigからrollupにオプションを渡すぐらいのことは問題なくできた。configオブジェクトに型が付いているのはとても良い。mis configurationを避けられる。

開発時のビルド速度の向上はやはりある程度以上の規模がないと恩恵がわからないので、業務のアプリケーションでもそのうち試してみたい。

*1:GitHub Pagesのためにassetsのパスを変える程度

状態、結合、複雑性、コード量の順に最適化する

There’s No Such Thing as Clean CodeHacker Newsコメント経由でコードやシステム設計・最適化についての良いコメントを見つけた。どうやらHacker Newsで何度も引用されているらしいが日本語で言及された記事が見つからなかったので取り上げてみる。

コメントは2016年のSandi MetzThe Wrong Abstractionに関するもので、発言者のcurun1rいわく「私は設計の優先順位をこの順序で学習することで、優れた開発者になれた」。*1

4つの基準と優先順位のガイドライン

状態 > 結合 > 複雑性 > コード量

私は状態 (state)、結合 (coupling)、複雑性 (complexity)、コード量 (code) の順に削減することでコードを最適化する

  • コードがよりステートレスになるなら、結合を増やすこともいとわない
  • 結合を減らすためには、コードをもっと複雑にすることもある
  • コードの複雑さが軽減されるなら、コードをコピーする
  • コードの重複排除をするのは状態・結合・複雑性を増さない時のみに限る

ステートレスを最優先する理由

ステートレスなコードを最優先する理由は、それが最も推論可能なものだからだ。

  • ステートレスロジックは、通常のコード実行・並列処理・分散処理のいずれでも同じように機能する
  • 状態を再現するためのセットアップコードがほとんど必要ないので最もテストしやすい
  • コピーを実行するだけなので、スケーラビリティも高い

状態が入り込むとプログラムは...かなり難しくなる。

Once you introduce state, your life gets significantly harder.

初心者のプログラマはコード量にのみ注目する

初心者のプログラマがコード量を削減するのは、4つの基準の中で最も見つけやすいからだと思う。

他の3つはコード量に比べてはるかに微妙で主観的であるため、発見するにはより多くの経験が必要になる。*2


このコメントに対するツッコミと、curun1rによる回答。

「ステートレスかどうかと結合度は直行する概念では?」

対立するシーンはいくつもあり、小さいプログラムよりもシステムアーキテクチャでよく見られる。たとえばシステムコンポーネントがジョブキューをインメモリで管理する場合、その状態を別のキュー管理コンポーネントに任せる(状態--; 結合++)ほうがうまく状態を管理でき、明晰になる。

「複雑性は結合が生み出すものでは?」

複雑性にはたくさんの種類があり、結合はその一形態に過ぎない。たとえば循環的複雑度も1つの複雑性を示す指標である。複数の複雑性の組み合わせこそが私の考える複雑性であり、プログラマの認知負荷を高めるものだ。


元のコメントで述べられてるコード最適化ガイドラインについてはここまで。以下は感想。

「状態 > 結合 > 複雑性 > コード量」の優れている点

様々なシーンに適用できるエレガントなガイドラインだと感じたので、優れていると感じた点を述べてみる。

基準の普遍性

古今東西様々なプログラミング原則が存在するが、"state > coupling > complexity > code" のガイドラインはシンプルでわかりやすく、パラダイムによらない普遍性があると感じる。

重なるところの大きいCode Smellを端的に言い表しているようにも見える。

順序付き

特定の原則を遵守するときにトレードオフが発生することがあるが、優先度が付けられているので「要はバランス」とならずに判断しやすい

もちろん画一的な判断はできないがコンフリクトした際の指標があるというのが良い。

(最近はあまり聞かないかもしれないが)DRY原則を持ち出してコード量を減らすパッチを受け取ったときに「変更によって状態・結合・複雑性が増しているから受け入れない」と言うことができる。

適用範囲の広さ

ソースコードだけでなくシステムアーキテクチャについても同様の最適化が可能であるという一貫性も良い。マイクロサービスアーキテクチャにSOLIDの一部は適用できる、といった半端さがない。

たとえば、HTTPやイベントソーシング*3が状態を削減しつつ結合や複雑性を増やしていることも、同じ基準によって評価できる。

覚えやすさ

そして、何より覚えやすい。4という数が覚えるのにちょうどよい。

欲を言えば、より端的に表す名前が欲しい。acronymでSCCCとかS3Cみたいな名前が付けられそう*4

関連する言説

思いついたものを2つ。

同主張への関連を見出だせる設計原則やソフトウェアに対する考察は無数にありそう。

Out of the Tar Pit

複雑性といえば、Rich HickeyClojureを作る時に影響を受けたという"Out of the Tar Pit"。同論文では複雑性について以下の主張をする。

  • 複雑であるとは、推論が効きにくいか、不可能であること
  • プログラムの複雑性は、状態・制御・コード量・言語のパワフルさに由来する
  • 複雑性はコントロールできる(とりわけ、"偶発的な複雑性"を指して)

ここでは複雑性がより広い概念として扱われ、状態 (state)・コード量 (code) は複雑性を生む要因の1つに含まれている。

ただし、状態は「コンピューターシステムにおいて絶対になくならない"本質的な複雑性"」とラベリングされているので、コントロールの難易度・アプローチが異なる"偶発的な複雑性"とは切り分けて扱うのが妥当に思う。

「複雑性にはたくさんの種類がある」という補足を先述したが、4つの基準が原則たるためには複雑性という言葉に明晰な定義が必要かもしれない

Clean Architecture

クリーンアーキテクチャ』本における「プログラミングパラダイムは制約を課すものであり、何をすべきでないかを伝えている」という一節を思い出した。

パラダイムの制約が促すプログラム設計により、4つの基準での最適化が推進されるのではないだろうか、と。具体的には以下のようになる。

構造化プログラミングは、直接的な制御の移行に規律を課すものである

モジュール分割によって、結合・複雑性が削減される。

オブジェクト指向プログラミングは、間接的な制御の移行に規律を課すものである

コードの依存関係の制御によって、結合が削減される。

関数型プログラミングは、代入に規律を課すものである

タスクの関数化によって、状態が削減される。

最近の業務であった設計

卑近な例との関連。

これまで1つの責務しかなかったモデルに新たな役割(ユースケース)が追加されそうになる、というありがちなシーンに同僚が直面していた。一緒に設計の相談をした末に2つの実装パターンに思い至ったので、どちらが良いかを評価するために両方のパターンのコードを同僚に書いてもらった。

  1. 同モデルで複数のユースケースの振る舞いを扱えるようにする。変更にかかるコード量は最も少なくても済むが、同一モデル内で気にすべき状態が増える。*5
  2. ユースケースごとに対応するモデルを追加し、元のモデルは抽象にする。変更するコード量はかなり多いが各モデルで気にする状態は少なくなる。

最終的には2を選び、「コード量と複雑性は高いけれども状態と結合は少なくてすむことを優先した」と説明できるようなプログラムになった。

この選択が正解かどうかは時の洗礼を受ける必要があるが、試し書きしたコードをレビューする時点で認知負荷の低さを感じたし、テストもユースケースごとに分割できていて見通しが良かった。

AI Programmer

オフトピック。

最近tabnineCopilotを使っていてコード補完や生成におけるすさまじい技術の進歩を感じるが、この4つの基準で最適化されたコードがsuggestされると面白そう。

現時点でもコードの重複の削減は簡単に提案されるし、状態・結合・複雑性の削減も、循環的複雑度の高さやローカル変数の個数など特定の指標ごとに指摘するツールは多くあるが、さらに一歩先で「インスタンス変数への依存をなくし関数にしませんか」「このクラスは2つの状態に依存していますが取り除くことができます」的な。

まぁ、機械が書いたコードを機械が読むような、真にプログラマが不要な世界に到達したら人間にとってのコードの認知負荷は問題ではなくなるのだが。

*1:優れた開発者を自称できるのすごい

*2:プロとアマチュアプログラマはコードベースを成長させる際の優先順位を確認することでわかる、という別のユーザーからのコメントもあった。

*3:状態ではなく取引(トランザクション)を保存し、状態はトランザクションから導出するという戦略

*4:そして順番を間違える輩が現れそう

*5:ユースケースが複数ある=アクターが複数いる」と考えればそもそも単一責任原則に反しているのだが、コード量の変更は数十行で済むので一見シンプルな変更に見える魅力があった

無職を経てSmartBank, Inc.に入社しました

掲題の通り、SmartBank, Inc に入社しました。

  • From: Quipper, Inc.
  • To: SmartBank, Inc.

smartbank.co.jp

2021 in review - valid,invalidに書いたとおり転職は2020年の出来事で、入社日は 2020-08-01。2021 の間違いではなく 2020 である。入社してから半年程度はステルスでプロダクト開発を行っていたため書くきっかけを見失ってしまい、以降ずっと執筆をサボっていた。

当記事は入社後 1 年半の振り返りではなく2020年のオファー受諾時や入社時に何を考えていたかを主に記述する。(が、結果として当時の期待やオファー受諾の決め手が概ね間違っていなかったことを追認することになった)

続きを読む

CLIでpull requestsをまとめてapproveするワンライナー

GitHub公式CLIのghを使って複数のpull requestsをまとめてapproveする。

まれに使うのでメモ。

前提

gh install済み、かつcurrent directoryが対象のrepositoryであること

コマンド例

Approve all pull requests in the repositrory

$ for pr in $(gh pr list --json 'number' -t '{{ range $i, $pr := . }}{{ $pr.number }} {{end}}'); do gh pr review -a $pr; done

Approve all pull requests with dependencies label in the repositrory

$ for pr in $(gh pr list --json 'number' -t '{{ range $i, $pr := . }}{{ $pr.number }} {{end}}' --label dependencies); do gh pr review -a $pr; done

環境

  • gh version 2.4.0 (2021-12-21)
  • zsh 5.8 (x86_64-apple-darwin19.6.0)

Advent of Code 2021 に Go で取り組んだ

存在は知っていたが取り組んだことなかったのでやってみたシリーズ*1の1つ、Advent of Code 2021に取り組んだ。

adventofcode.com

Advent of Code とは Advent Calendar にちなんで毎日2問ずつクイズが出題され、25日まで解かせるというイベントである。2016年ぐらいからやっているらしい。

結果、8割クリア

結果、独力で完答はできず、一部は自力で解くのを諦めてRedditの回答スレッドを見て写経して終わらせることになった。

解けなかったのは 20, 21, 22 の part2、および 18, 23, 24。全49問なので8割クリアといったところ。

前半の15 daysぐらいは楽勝な問題と良い歯ごたえの問題が並んでおり、1日15分~60分ぐらいを使って楽しんで取り組めた。アルゴリズム面よりも英語の問題文の読解に悩む問題のほうが多かったぐらいだった。

しかし後半、day16あたりから仕様理解やデバグの難しさが急激に上がり始め、day20以降は半ば諦めつつ「30分考えて良いアプローチができなかったら諦める」撤退戦略を取ることになった。プライベートな時間の制約もあったのでやむなしと言いつつもアプローチの仕方すら思いつかない問題があるのには力不足を感じずにはいられない。

f:id:ohbarye:20211230154043p:plain
この絵、何?ってずっと思ってたけど終わってようやく理解した

使用した言語は Go

使用したメイン言語は2021年最後のクォーターあたりから仕事で書くようになったGo。習熟度を試す意味合いもあるし、仕事ではWebアプリケーションやバッチ処理を書いているので、そこからちょっと離れてアルゴリズムの書き味はどんなものか知りたかったというのもある。

最近あまりやっていないけど競技プログラミングRubyで取り組んでいたので、そことの比較でいうと…まぁ、ちょっとした便利utilみたいなものを用意しないと辛いかな…というのは思ったが、だいたい使うイディオムやデータ構造は決まっているのでそこまででもなかった。

どれか忘れたけどゼロ値が便利に使える問題だとクールにGoをキメられた感が出て良い。

特段良かったところはコードの変更がとても簡単なところ。僕の場合、こういった趣向で探索的にプログラムを書いていると変数名やインタフェースがひどいコードを書くことになる。一筆書きで正答できればそれで良いのだけど、一発でうまくいかずにアルゴリズムや使用するデータ構造を変えるにあたり、IDEの支援が効くのはめちゃめちゃ便利だった。致命的なミスはコンパイル時に死んでくれるので、ある程度対象を絞り込んだ状態でできるデバグの体験も良かった。

モチベーション

後半は問題を読解するのも辛い時もあったが、Twitterで回答する人々(日本語)を見たり、(去年のだけど)完答しましたブログを見たり、Redditのネタスレクールなvisualizationを見るために問題文を読む気持ちを奮い立たせたりしていた。

来年の抱負

来年は9割を自力で正答できるところまでいきたい。

力量不足は感じたが今年学んだ言語で取り組めたことは良かったので、来年も新しい言語でやれると良い気持ちになれるかもしれない。

*1:正確に言うとAoC 2020が終わったあとに存在を知ってちょっと取り組んでみたけど出遅れてアドベント感が薄くて続かなかった