鯨飲馬食

いろいろつまみ食いで勉強したことのメモ書き

みんなの「わがまま」入門を読んで、わがままの受け止め方を考え直した

みんなの「わがまま」入門

みんなの「わがまま」入門

中高生向けに書かれた社会運動論の本。自分の周囲に当てはめて、多様な人々と一緒に働いている会社とか、たった3人とはいえ妻と子と私で好みも性格も異なる家族とか、それらの集団の中で「もやもやを声に出して伝えること」を想像しつつ読んだ。

集団の中で生活をしていると、それぞれの事情の違いは確実に存在していて、もやもやが出てくるのは当然。でも、思ったわがままを口に出して言うことはそれなりに障壁がある。

  • 解決するアイデアがなくても言っていい
  • 言ったことで短期的にもやもやが解決できなくてもいい
  • 当人じゃない他の人が言ってもいい
  • 対象に直接言わず、別の人に言ってもいい

と考えることで、深刻に考えすぎずに、頑張りすぎずに、わがままを誰かに伝える。なんとかわがままを表に出すことができれば、周囲に何かしらの影響を与えられる。あと、頑張りすぎないに関しては、気が向かないならやめてもいいとも。

自分が聞く側に立った時のことを思い出し、固い頭をガツンと殴られた感じがした。

業務の中で他の人が困ってそうなことについて改善提案をもらった時に、「実際に体験してなくてそう思ったのかもしれないが、実はそこが大きな困り事ではないんじゃないの?」と深掘りを求めたり、「やってる人を巻き込んでみて」とか「自身も体験してみて」と、障壁を越えて言ってくれた人を、追い込むような対応をしてしまった心当たりがたくさん。高い障壁を越えて課題をなんとか伝えてくれた状況だったかもしれないのに。

まずは伝えてくれたことに対して「ありがとう」と言おう。あと、言い出しっぺの法則ではなく、適切な他の人に続きを繋いであげるというのも、聞いた側がやれることの選択肢として持っておこう。もちろん言ってくれた人がやりたいと言うなら止めはしないけど、それでも一人で抱えずに適度に周りを巻き込んで進めていいんだよと言おう。

今でも全くできてない訳ではないと思うけど、改めて意識する。

最高のチームに変わる「仕組み」のつくり方

目次の「人を育てない」が気になって読みました。

  • トップからの抽象的なスローガンを翻訳して、具体的な望まれる行動として伝えること。
  • ハイパフォーマーの業務を観察、分析し、ピンポイント行動を見つけること。
  • 部下の一人ひとりとコミュニケーションをとり、それぞれの価値観を知ること。
  • 毎日の声かけ、その中で望ましい行動について認めること。

闇雲に人を育てることを目的にするのではなく、会社の業績につながる行動を増やす仕組みづくりをすべきとのこと。望ましい行動が自然と生まれてくる場づくり、していきたいです。

自衛隊メンタル教官が教える折れないリーダーの仕事

勝つためのリーダーシップではなく、負けないためのリーダーシップについて書かれた本。同僚の紹介で興味を持って、図書館で借りてきて一気に読みました。面白かった。

リーダーの仕事の切り方4通りの2つ目に「仕事の完成度を下げる」が来ていたが、自分はなかなかそれを選択できてなかったな。時間切れで妥協、許容することはあっても、短期的に品質を捨てる選択を積極的に取れてなかった。チームのこともっと考えて、持続するいいチームをつくっていきたい。

Dockerコンテナ内からターミナルを識別する

プログラムからターミナルの種類を判定する方法について、longcat で対応したやり方を説明します。

TERM_PROGRAM環境変数による識別

TERM_PROGRAM環境変数には利用しているターミナルのプログラム名がセットされます。例えば

  • iTerm2 の場合は iTerm.app
  • Terminal.app の場合は Apple_Terminal

という値がセットされる。ネイティブで実行している場合には、プログラム中でこの環境変数の値に応じた処理をさせることで、ターミナルの自動判定を行えます。実際、longcat に Terminal.app 対応を入れた際にはその方法で判定していました。

Dockerコンテナの中から

dockerコンテナ内のプログラムにターミナルに応じた処理をさせたい場合にはどうすればよいでしょうか?デフォルトでは環境変数はコンテナ内のプログラムには引き継がれず、docker run の -e オプションでこのTERM_PROGRAMを明示的に指定すれば伝達できます。しかしこれでは自動判定を行なっているとは言えません。

f:id:yoichi22:20200811115101p:plain

DA2による識別

ターミナルに特定のエスケープシーケンスを送信することで、ターミナルの種別に応じた応答を得ることができます。DA2 (Secondary Device Attributes)では、ESC [ > c を送信します。試しにprintfコマンドを使ってやってみると、iTerm2 の場合

$ printf "\x1b[>c"
$ 0;95;0c

と "0;95;0c" という応答が得られます。Terminal.app の場合は以下のようになります。

$ printf "\x1b[>c"
$ 1;95;0c

この応答を読み取って、読み取った値で判定すればターミナルに応じた処理ができます。ターミナル自身が応答するので、この方法は docker run -it してttyを割り当てていればコンテナ内からも判定に使えます。

実装

既にDA1 (Primary Device Attributes)を使ってsixel対応を判定するコードがあったので、それを参考にして実装して動作確認したのですが、うまく動作するときとしない場合がありました。得られた応答をプリントしてデバッグすると、応答の途中までしか読み込まれていないことがわかり、少し待ちを入れることで対処しました。

github.com

猫を表示するだけのプログラムから、ターミナルの知識をまた一つもらいました。面白い。

参考文献

macOS標準ターミナルでlongcatが出るまで

概要

256色出力に対応することで、macOS標準のターミナル (Terminal.app) での longcat の動作を修正したのでその過程で学んだこと。

github.com

問題と回避方法を確認

もともとdockerで実行した時の現象がTwitterで報告されていたのだが、macOS標準のターミナル(Terminal.app)で longcat を実行するとおかしな表示になるとのこと。再現確認すると、dockerは関係なくて、そのまま実行しても駄目で、tmux -2 の上で実行すれば綺麗に出ることがわかった。

f:id:yoichi22:20200712093002p:plain

tmux を経由するとうまくいくということは、何らか対処すれば tmux なしでもいけるだろうと期待して調査に着手。

pixterm出力を読む

そもそもどうやってターミナルに描画しているのかを理解してなかったので、まずはそこから。

longcat | more すると、

f:id:yoichi22:20200712093510p:plain

のような文字列が出力されている。

ANSI escape code - Wikipedia によると、

  • 38 は forground color の設定
  • 48 は background color の設定

で、それに続く 2;r;g;b (0 <= r,g,b <= 255) で色を指定するとのこと。

また、▄ についてはEmacsでM-x describe-charすると、LOWER HALF BLOCKだった。

f:id:yoichi22:20200712093923p:plain

つまり、background colorで上半分を塗り、foreground color で下半分を塗ることで、1文字で2ピクセル分を表現しているとわかった。

longcat がうまく動作した tmux のオプションの意味は

     -2            Force tmux to assume the terminal supports 256 colours.

で、 https://gist.github.com/XVilka/8346728 にも Terminal.app は true color をサポートしてないとあるので、256色で出力すれば何とかなりそうと予想した。

256色指定にしてみた

上述のエスケープシーケンスの説明にもあるが、ESC[38;5;n あるいは ESC[48;5;n (0 <= n <= 255) で256色での指定ができ、うち、16 <= n <= 231 で r, g, b をそれぞれ 0-5 の 6x6x6 で表現できるとわかったので、0-255 から 0-5 に変換するように python でフィルタを書いて試すと、

とそれっぽいが、tmux の出力と比べると若干見劣りする猫が出た。何かが足りてない。

tmux の実装を確認すると、 232-255 のグレースケールも使って、6x6x6と比べてより近い方を選ぶロジックだった。それに合わせてフィルタの実装を修正して試すと綺麗な猫が出せた。

gist.github.com

フィードバック

どう対処すればうまく動作するかの仕組みはわかったのでほぼ満足してしまったのだが、せっかくなのでlongcatにフィードバックしようと思った。

活用範囲が広げられるよう、 pixterm に対処を入れたらどうかと最初に考えた。しかし、

  • pixterm は true color 対応のターミナルをターゲットとしており、true color 非対応ターミナルのための対処を入れるのはどうか
  • 拡張した時に longcat から動作を制御するにはインタフェースを変更する必要がありそう

というあたりが気になったのでやめた。

longcat で対応するにしても、応用ができるように色変換のロジックは外に出しておいたほうがいいと考えた。 tmuxの実装をgoに移植してライブラリを実装しようとも思ったが、適当なライブラリが既にあるのではと探して、まず gookit/color を組み込んでみた。動作させてみると6x6x6の部分に合わせた時のような色だったので却下。次に見つけた tomnomnom/xtermcolor を組み込むといい感じになったので、それでプルリクエストを作った。

プルリクエスト出したら一瞬で取り込まれてしまって、後からオプション指定の処理が中途半端になっていたことに気付き再度修正を送った。

まとめ

  • エスケープシーケンスによるターミナル上の色付けの方法について知った。
  • U+2584 (LOWER HALF BLOCK) を使ってターミナルに描画できることを知った。
  • 現状の自動判定は環境変数TERM_PROGRAMに頼っており、 docker では明示的に伝達しないといけない。

カルチャーコード - 最強チームをつくる方法

強いチームの作り方に興味があるので読みました。先日参加したモブLOVE勉強会の @TAKAKING22 さんの発表で書名がちらっと出てて知った本。

弱さをみせる

第7章。飛行機が異常状態になり、パイロットの間のやりとりで「わからない」「どうしたらいい?」という不安や疑問をどんどん口にして表に出すことで、答えを持っていない状態から解決策を見出すために協力して事に当たれたという話。緊迫感の中なされた短い言葉のやりとりは「通知(notification)」と呼ばれるもので、自分が気づいたことを相手に伝え、お互いが状況の理解をより深められるようにするコミュニケーション方法とのこと。

自分の現場だと、夜間のシステムトラブルの対応のとき、それぞれが見たこと、わかったことだけでなく、わからないこと、不安なところをSlackのメッセージでやりとりして、事態収束に向かって行くときのことが思い浮かんだ。わからないところや自信のないところをカッコつけずに表に出して、まわりの人の助けを受けると、より早く問題解決に向かえるのをさんざん見てきた。

新しくオンコールローテーションに入ってもらうメンバーの導入のときには、できません、わかりませんといった弱さを怯えずに表に出してもらえるかどうか?というのをしっかり確認するようにしている。弱さを隠さず見せ合って、チームとしてより強くなれるとよいな。

真実を追求することを習慣にする

第10章。ネイビーシールズが作戦の直後に行うAAR(After Action Review)の話。真実を追求することで、態度をチーム全員で共有し、その先の作戦で生かすことがAARの目的とのこと。実際におこったこと、その中でとられた判断や行動の理由と、他の選択肢がなかったかを深堀りする。

次も全く同じ状況というのはないわけだが、おこったことの過程における、判断の理由や考え方を学んでおくことで、状況に応じて判断し、うまく行動を選んでいけるようになるってことかな。

自チームで最近、問い合わせ由来の調査や、障害対応が終わったあとにその過程をふりかえってそこから学ぼうという会を何度かやっているが、その場の良い呼び名を見つけられてなかった(リプレイとかふりかえりとか言ってたけど微妙にしっくり来てなかった)。AARというのはやってる内容にあってそうなので提案してみよう。

実装の経緯は記憶していません

記憶してるんじゃなくて記録{して,させて}いますという話。

同僚との会話から

チームでメンテナンスしているプロダクトの実装について質問を受けたときに、私がささっと調べて答えているのを見た同僚から「長いこと関わってるからあちこち触っていて、実装の経緯とか知ってるから答えられるんですね」と言われて、記憶でとっかかりが得られることもあるけど、最近はほぼ記憶に頼らずにやっていたのでそう言われて驚いた。

記憶をたどる

記憶に辿らなくて良くなった経緯を思い出してみた。

今の会社に入った当初、既に書かれたコードのメンテナンスをするにあたり、もちろん記憶に頼ってとかはできないし、コミット履歴を見ても有益な情報が得られなかったので、周りの人に聞きつつ頑張ってコード読んでたように思う。コード量も今のコードと比べると少なかったし、要求されるスピードも今と比べるとそれほどでもなかったのでなんとかなったところはあると思う。

人の記憶に頼って何とかしようというのは、設計、実装した人が離職されたら途切れてしまうし、人がどんどん増えたときにそれをすべて伝承し続けるのは筋が悪い。自分のそれまでの経験でも、問いの宛先となる設計、実装した人が過去の自分で、記憶に頼るというのはあてにならないというのを自ら痛感することも度々あった。

そういうわけで、JIRAのチケットに途中の検討内容のメモを書いときましょうとか、関係する情報をリンクしましょうとか、git のコミットメッセージちゃんと書きましょうとか、情報を記録することと、それらをリンクしていくことは大事だよと周りにもおすすめしつつやってきた。そういった活動を始めた時点から増えてきた分のコードには、付随してある程度の情報が保持される状態になっているのが今。

記録の辿り方

使える情報が存在していても、辿れないとそれは存在しないのと同じ。冒頭で出てきた同僚は辿り方を知らないのかもしれないなと思って、先日チーム向けに git blame の使い方のデモをした。

blame したときにできるとよいこととして、

  • 特定行からコミットメッセージに飛ぶこと
  • ひとつ前のコードでblameし直す

がある。前者はコミットメッセージに残された情報や、コミットメッセージ中のチケット番号からJIRAへと辿り着くのに使える。後者は、フォーマットの変更などの意味のないコミットがあったときに、本質的な変更のコミットを探すのに使える。

ある時点のコードを空間方向に眺めて得られる情報の他に、git blame や git log で時間方向に視点を動かして得られる情報を加えることで、よりコードの理解が容易になる。

手でgitコマンドを叩きまくってもできるけど、ツール使うと楽ができる。デモに使った magit-blame ではこれらはキー一つでできる。Emacs使ってるの私だけなのでそのままでは聞いてる人の役に立たないので、tig blame とか vimagit にも軽く触れておいた。

magit.vc

jonas.github.io

github.com

記憶するのではなく、記録する

記憶に辿らないコードの読み方を共有したので、将来の自分たちや仲間たちのためにさらに有用な記録を残していけると良いな。