nogahighland

グチばかりですみません

ConfluenceのページツリーChrome拡張を公開しました

chrome.google.com

ソースコードはこちら。 github.com

開発に至った経緯

今所属している楽天では、全社的にConfluenceが広く使われていて、ラクマでもノウハウを貯めるためにスペースを作成して各プロジェクトやチーム、開発内など様々な軸でツリーを成長させています。 Confluenceはマークダウンが使えないという点ではエンジニアに優しくないのですが、ストック型ドキュメントを整理するという意味では結構使えるツールだと感じています。

一方で、この「ストック型」というのが難点にも成り得てしまい、これが今回のChrome拡張を作成する動機になりました。

  • ドキュメントの場所を覚えられない
  • 場所は覚えているんだけどページツリーを辿るのが大変

その結果以下のような問題が発生してしまいます。

  • せっかく蓄積したノウハウが利用されない
  • 類似ドキュメントを作成してしまう

Confluenceのエコシステムを利用して「スペースを限定して検索する」という解決方法もあるのですが、いくつかの問題が存在しています。

  • ページ右上のグローバルサーチバーではデフォルトでスペースを絞り込めない
    • 楽天内には多くのスペースが存在していて、ビッグワードで検索すると無数の関係ないページがヒットしてしまうので、検索結果画面でスペースを絞り込むというステップが必要になる
    • インスタントサーチ結果がボックス下に表示されるが、スペースが絞り込まれていないのでかなり詳細なクエリを必要とする
  • スペース内に限定する検索ボックスも設置可能だが、画面遷移してしまう・検索スピードが遅いという課題が存在する
    • こちらはインスタント検索に対応していない
  • 検索精度が不十分
    • 例えばGoogleドキュメントを参照しているページを検索するために docs.google.com というクエリを打ち込んでも、実際にこのクエリを含むページが検索結果に表示されない

検索精度に関しては結果的に今回のソリューションに直接関係はなかったのですが、検索精度を信頼できないことで検索を選択肢として利用する自信が持てないことは、ドキュメントの場所にたどり着ける確証が持てないということなので、「せっかく蓄積したノウハウが利用されない」という問題の原因となります。

また、上記に挙げた代替手段は相互に補完関係にあるものの、探しているページを瞬時に探すための総合的なソリューションとして利用できないです。

ConfluenceにはもともとPage Tree Macroというものが存在するのですが、場所がわかっているのに階層が深いとトップの階層から下るということが非常に苦痛になってきます。 各種検索に頼ってもなかなかヒットしない場合や、場所がわかっているのに検索結果が表示されるまでの時間が長いというストレスも増えてきました。

「場所がわかりきっている」というのをもう少し掘り下げてみると、「ページタイトルの一部を知っている」ということが大半を占めるのではないかと思いました。ここで、ソリューションがミートする範囲を「ドキュメントがあるかどうか検索する」ことよりも「既にあることが分かっているドキュメントを見つける(経験的におそらくあるだろう、も含む)」 に絞り込みました。

何があればいいのか

ここまでをまとめると

  • 頭の中に情報のインデックスは張られていて、タイトルの一部は覚えている
  • または、傾向的に〇〇プロジェクトの議事録的なものは「プロジェクト名 2020XXXX」というタイトルで存在している可能性が高いと分かっている
  • しかしページに辿り着くまでの手段に効率的なものが存在しない

ということになりました。ということは、ページツリーの中から入力したキーワードが部分一致するページのみを表示することが実現できれば良さそうです。 ページツリーのインクリメンタルサーチです。

※実際はここまで言語化せずに「ツリー検索無いとかマジか!!!もう怒ったった!!!作るったら作る!!!」という半ば衝動的な行動でした。カッとなってしまいました。

そこで作った

こんなものを作りました。

何もしていない状態 クエリを打ち込んだ状態 親ページを開いた状態

どうやって作ったか

大まかな設計を考え、最近覚えたてのVue.jsで作ろうと考えました。

  1. ページツリーデータを取得して再帰的に親子関係をレンダリングする
  2. クエリをstateとして管理し、各ノードのコンポーネントがクエリの変化に応じて自身を表示するかどうかの判定ロジックを以て表示を切り替える
  3. 子が開いている状態では親も開き、開いているノードは太字にして階層を認識しやすくする

f:id:nogahighland:20200307232227p:plain

まずは、 el を使って既存のツリーをVueコンポーネント化してしまうことができないか検討しましたが、早々にできないっぽいことがわかり断念しました。そうなると、既存のツリーをまるまるリプレースするしかなくなり、ツリーデータを取得するしかなくなりました。

ツリーデータの取得

既存のツリーをハックしようと、Chromeのインスペクタを開いて階層構造のハックを試みます。

  • 階層構造は、初期表示時には全件取得されておらず、ツリーを開いたタイミングでXHRで取得している(レスポンスはそのまま描画できるHTML形式😇)
  • XHRのページIDを変えることで、異なる親のツリーを取得できる

という事がわかり、子コンポーネントにページIDを渡して、 monted のタイミングでその更に子、孫・・・を都度取得するように実装しましたが、これだとロード回数が半端なくて、毎度開き直す度に数百のリクエストが生じるのは流石にユーザービリティ的に悪そうです。さらに、社内や果ては全世界のConfluenceユーザーに使ってもらいたいのにこの無駄なリクエストが走ってしまうのは社内のConfluence管理者たちに申し訳なさすぎます。

ということで、ツリー全体を取得できる方法が存在しないかリクエストをよく観察してみると startDepth というパラメータがあったので試しに100を設定してみると見事全階層取得できました。もしお使いのスペースで100以上の階層がある場合は・・・PRください。

この全ページ目次のHTMLを再帰的にJavascriptオブジェクトとしてパースし、子TreeNodeに渡して再帰的に描画していくとツリーの完成です。ツリーと再帰は大変相性がいいですね。

VueのscopedなCSSで、子に padding: 10px とかすれば簡単に階層構造が視覚化できます。

ツリーデータのキャッシュ

ツリーデータのサイズに応じて取得には5秒ほどかかる場合もあります。毎回ページを開くごとにこれだけの時間を要するのはちょっと効率的ではありません。 調べてみるとChrome ExtensionにはStorage機構が存在するので、これをキャッシュとして利用します。key: value形式でデータを5MBくらい保存できます(詳細は下記)

developer.chrome.com

keyにはスペースごとのID, valueにはツリーデータと最終取得日時をそれぞれ保存します。そうすることで

  • 10分以内のデータであれば通信で再取得せずに使う
  • 10分経過後であれば、ひとまず古いデータで描画して描画後に通信で最新のツリーデータを取得する

という制御ができ、初回データ取得後は特に大きく待ち時間が発生しないUXを実現できました。 10分以内のページであればSlackで「ページ作りました」と直接共有されそうなので即ツリーに反映されて無くても当面は問題なさそうです。

厳密性を求めるならばリフレッシュボタンでデータを強制的に最新化するという機能を追加しても良さそうです。

ここでVue.jsのデータフローによりデータを更新しさえすれば0実装で簡単にツリーを再描画できることと、Virtual DOMによって差分のみ再描画されるというエコな仕組みを利用できるのが最高ですね。

フィルタリング処理

inputとのデータバインディング方法は onInput時にイベントハンドラevent.target.value を取得してStateにセットします。

ページをフィルタリングするUIのイメージはGithubのファイル検索UIです。検索はどうやって実装されているかよくわからなかったし、調べてもないのですが「多分こんなかんじじゃね」で作ったものが意外と使い心地が良いので特に深入りしていません。

a b と入力されたら a.*b という正規表現を作成して取得できるgetterメソッドをStoreに作成して各TreeNodeコンポーネントで取得して、合致していればtrueそうでなければfalseを v-if してあげます。実装のことを説明するとだんだん日本語が喋れなくなってきますね。要は、入力した順に部分一致してればいいんでしょ、というノリで作りました。

気になったのは数百のコンポーネントが入力値をsubscribeしており、そのフィルタリング処理がUIスレッドで行われてしまっていることで、入力イベントに応じて一気に判定処理を始めるので一瞬処理が固まってしまいます。この体験が悪いのでなんとかしたいなぁと思うのですが、普段からUI周りを触っていないことからすぐにはいいアイデアが出てこないのが残念です。コントリビューションに期待しています。いちおう、inputイベントはlodashのdebounceで間引きしてはいます。

また、クエリにマッチした部分を太字にしたいけど、これは後の改善モチベーションやコントリビューションに期待します。

ツリー開閉処理

単純にTreeNodeオブジェクトでクリックイベントをハンドリングしてtoggle状態を切り替えれば良さそうです。

  • v-ifで子ツリー要素の表示を切り替える
  • 開閉ボタンのclass要素を切り替えて中身のシンボル + -CSSで変える

あとは、階層の下の方のページを開いたときにツリー上のどこに存在するか確認するために、親までさかのぼって開いてあげる処理を実装しました。 今回はコンポーネントがマウントされた際に実行されるmountedメソッドで、そのコンポーネントが表示対象だった場合に親コンポーネントopenChild イベントをemitするということで実現しました。そうすることで「逆再帰的」に親にイベントが伝播し、やりたいことが少ないコード量で実装できたのでなかなか気持ちよかったです。

jp.vuejs.org

ほかのライフサイクルイベントでもっと効率的に処理できるのであればmountedでの実装を見直せるかもしれません。

jp.vuejs.org

ツリーの開閉とフィルタリングの関係

各ページの表示状態はツリーの開閉状況とクエリどちらに依存すればいいのかという問題が出てきました。ここでどういう試行錯誤とをしたのかあまり覚えてはいないのですがこういう感じで実装しました(あくまで暫定の仕様ではありますが)

  1. クエリ入力中はクエリに一致すれば表示する
  2. クエリが入力されていなければ親コンポーネントが子コンポーネントを開いているかどうかに依存する

上手く言語化できませんが、なんとなくこれが自分的には釈然としたのでこういうふうにしています。

この仕組みをハックすれば

  1. ある親要素をクエリで検索する
  2. その要素の+ボタンを押して開く
  3. クエリを削除する
  4. 2のサブツリーだけが開いている状態にする

ということができます。良い仕様があるかもしれませんが、それも今後のコントリビューションや自分のモチベーションに期待しようと思います。

最後に

ちょっと身の回りをハックするツールを作るとき、直感に従って対してその仕様意図を言語化せずに作ってしまうことが多いのですが、今回こうして言語化してみると意外と多くのことを考えていたのだと気づけました。同僚や部下で「改善アイデアがなかなか出ない」という人の相談に乗ることがたまにあってあまり上手な返答ができなかったのですが「なにかにペインを感じたらそこがスタートになる」ということと「直感で感じたペインを風化させずに真正面から取り組む」ということを伝えていけるのかなという気がしました。

とくにペインというのは意識しなければ多くの場合見過ごしがちで、他の代替手段で根本欲求がかき消されてしまいます。そのペインのシグナルを逃さずキャッチするというのは、ある程度訓練が必要なことかもしれません。自分は「感じる」「考える」というのを区別して捉えているのですが、直感レベルで感じたことをしっかり言語化(自分の場合は即プログラミング言語化でしたが)するということが大事だと思います。

普段からアウトプットする習慣が身についていないのに急にこの記事をアウトプットしたのもなにかの直感なのだと思いますが、おそらく「思った以上に出来が良かった」「そのプロセスを知ってもらって参考にしてもらいたかった」というモチベーションなのかもしれません。ちょっと有頂天気味なので、想定外の突っ込みがあると急に恥ずかしくなって拡張の提供をやめてしまうかもしれないのでお手柔らかにお願いします。

実務でフロントエンドの実装に携わることが無いので趣味でこの拡張を作る前にVue.jsを覚えたのですが、UIをコンポーネントとして捉えることがとても自然で生産性の高い開発方法だと気づくことができました。もともとネイティブアプリがコンポーネントとしてUIを実装するというアプローチだったと思うのですが、Vue.jsではさらにstateやcomputedといった仕組みが導入されていて、これはこれで大変便利です。それより前の既知の言葉で言うと「データをpub/subしている」つまりデータの変更にUIが「反応する」というアプローチの強力さに感動しました。

本当にUI系の界隈には不勉強で辛いのですが、たぶんReduxから始まったこういうアーキテクチャがネイティブアプリにも良い影響をもたらしてReactNativeが活発になっているんでしょうね(適当)

Slackのスレッドのつらみ11選

個人の意見で〜Slackには感謝しており〜みたいな余計なマクラは省略します。良識のある人だけ読んでください。

プロローグ

僕はSlackのスレッドがあまり好きではありません。そのせいで毎日ちょっとずつストレスを感じています。

しかし、スレッドというアイデアが嫌いなのではなく、 スレッドをサポートする機能があまりに不完全だからです 。Slackはスレッド機能が搭載される以前の仕様とスレッドを完全に統合しきれていなく、便利さを上回る不便が多すぎるのです(当社比)

そのような状況では、 スレッドじゃなくても事足りる会話はスレッドを避けて 使いたいと思っています。スレッドは、会話が同時多発して会話の整理がつかなくなったタイミングで初めて使えばいいんじゃないかと思っています。

👍スレッドのメリット

前述の通り。スレッドというアイデアは好きです。

  • チャンネル内の会話を整理できる
  • 同じチャンネルで複数の話題を同時並行できる
  • スレッドは「チャンネルを作るまでもないサブトーク」を行う手段
  • メンションしなくても相手に返事ができる

👎 スレッドのデメリット

スレッド機能にはいくつかのデメリットがあります。個人的にイライラすることをイライラ度順に挙げてみたいと思います。

  1. [解決済み] 通知が激しい
  2. メッセージが埋もれる
  3. 参加してないけど気になるスレッドの更新に気づけない
  4. チャンネルショートカットで探しにくい
  5. スレッドを開くのにマウス操作が必要
  6. モバイル版ではチャンネルとスレッドを同時に表示できない
  7. スレッドを開く処理が遅い
  8. 他のメンバーがUnfollowしたことに気づけない
  9. 返信しづらい
  10. ファイルを添付しづらい
  11. スレッドの下書きがDraft一覧に現れない

1. [解決済み]通知が激しい

※同僚からのアドバイスで、以下の設定でスレッドの通知を無くすことができました。感謝。

f:id:nogahighland:20191202214122p:plainf:id:nogahighland:20191202214125p:plain

スレッドの中でメンションされたメンバーは、スレッドに新規投稿があると通知が届きます。「対応しました」「了解しました」のような大した情報じゃない場合、 本当に相手に通知が必要なのか? を一瞬だけ立ち止まって考えてもらいたいと思っています。

スレッドはリプライではありません

スレッドはリプライではありません

スレッドはリプライではありません

X replies って書いてあるからリプライなのはそうなんだが。という気持ちです。

スレッドを使わなくても、自動で展開されるリンクを共有したり「Share message」を使って返信を表現することもできます。一つ二つ前のポストであれば、わざわざ引用しなくても返事をしていることは自明でしょう。

f:id:nogahighland:20191109020228p:plain

Slackの良いところは、通知のカスタマイズ性が高いことです。通知が沢山来ても気にしない人には無用なことでしょうが、同様に重要な情報以外は通知を受け取りたくないという需要も存在します。普段からメンションが多く、一つ一つの通知に神経を尖らせざるを得ないような人です。僕は後者のタイプで、作業の瞬間的な合間を縫って自分のタイミングで未読をキャッチして返信します。

しかし、 スレッドはメンションが無くても半ば強制的に通知を送る ことから、通知のカスタマイズ性を損なってしまっています。これは送る側には意識しづらいことなので、通知される人のことを少し意識すると良いでしょう。そうすればチャンネルポストで良いという選択肢も生まれます。

極端な例ですが、例えば会社の @engineers というグループメンションは数十人もいるので、そのメンションの付いたポストでスレッドを生やして会話を続けるとどうなるか、もうお分かりかと思います。(@engineers をクリックするとそのメンションで通知が届く人数がわかる)

f:id:nogahighland:20191109155454p:plain

なので、人数が多いメンションには直接返信せずにチャンネルで返信して、そこで初めてスレッドを生やすのがお作法としては良いでしょう。

f:id:nogahighland:20191109015136p:plain

また、100も200も返信が付いて、多くの人を巻き込むような会話は、途中で通知が必要なくなる人も出てきます。そういう場合は新しいチャンネルを作ったほうが良いです。

2. メッセージが埋もれる

こういう 3 replies という返事がいくつか付いたポストをよく見かけますが、中を覗いてみるとひっそりと有用な会話が繰り広げられていることがあります。

f:id:nogahighland:20191109015159p:plain

感度が高い人はスレッドをわざわざ開いて情報を拾ってシェアしますが、興味深いスレッドを嗅ぎ当てて開くというコストはチリツモです。会話が全てスレッドだらけになってしまったら、一日何度もスレッドを開くという作業をしなければいけません。

また、スレッドになった時点で垂れ流し(=未読チャンネルを開けば目に付く)ではなくなるので、スレッドをいちいち開かない人には見えない情報となってしまいます。有益な情報が情報感度や共有力が高い人にしか伝わらないかもしれません。「沢山の人に情報を届ける」という意味でも、むやみにスレッドにしなくていいと思います。

f:id:nogahighland:20191109015234p:plain

個人的には、大量の情報が自分のタイミングで自然と視界に入る状態は良いと思っています。視覚の処理能力は非常に高いので、文字の形や並びから文脈を感じる(≠理解する)ことができるからです。

そのような状態を維持するために、敢えて情報を隠すこと無く、堂々とチャンネルで会話してほしいと思っています。

3. 参加してないけど気になるスレッドの更新に気づけない

これはメッセージが埋もれてしまうことから生じる結果でもあります。

最初から参加してないけど気になるスレッドがあったり、通知がウザくてスレッドをUnfollowしたけどその後が気になる会話ってありますよね。スレでディスカッションが始まっちゃって、しばらく静観したいときとか。しかし、参加してない未読スレッドをたどるショートカットは無いので、スターを付けておくか、チャンネルを遡ってスレッドを開くしかありません(一度でも参加していたスレッドならThreadsから辿れます)。つまり、 スレッドの未読はチャンネルの未読よりも気づきづらい ということです。

それでふとスレッドが伸びていることに気づくと、アドバイスのチャンスを逸したせいでみんな間違った方向に試行錯誤している。または、渾身のおもしろ画像を貼り付ける瞬間を逃してしまっていた。そんなガッカリを逃したくはありません。参加していないスレッドをFollowすることもできますが、最初から興味のある話ではないこともあるので、不要な会話の通知を受けて集中力を失いたくありません。

チャンネルに投稿していれば、定期的に未読が付いたそのチャンネルを見に行けばいいだけなのです。

4. チャンネルショートカットで探しにくい

+ K使ってますか?(WindowsCtrl+K)マウスを使わずにチャンネルを探せるキーボードショートカットです。かなり頻繁に使うので、覚えておいて損はありません(ショートカットの一覧は + /で確認できます)。

ところで、このショートカットは読むべき未読が優先的に上に表示されるのですが、なぜだかThreadはこのリストに表示されません。ショートカットで探す場合は最低でも「th」は打ち込まなければいけないし、「th」は結構打ちにくいのでスレッドを開くのがいちいちストレスです。日本語化している場合はカタカナの「ス」を打ち込まなければいけないのです。これもSlackに改善して欲しい上位に入ります。

という理由もあって、スレッドをむやみに乱立させてほしくないです。

f:id:nogahighland:20191109155628p:plain

「戻る」「進む」ショートカットの対象外

+[ 戻る / +] 進む ←このショートカット使ってますか?チャンネル間を高速で行き来して様々な事象を感じる(≠理解する。2回目。)のにこのショートカットは必須です。

しかし、 このショートカットはチャンネル単位の遷移にしか対応していない のです。右側にスレッドを開いたまま、他のスレッドを開いて、さっきのスレッドに戻るために半ば反射的に+[をタイプすると… チャンネルが一つ前に見ていたものに戻ってしまうのです。

進行中のスレッドがたくさんあると当然行き来が増えるのに、ショートカットが対応していないせいで甚大なストレスを感じながらスレッドサーフィンしなければいけません。

このような無用なストレスを減らすためにも 「スレッドにしない」という選択肢 もアリなのではないでしょうか?

5. スレッドを開くのにマウス操作が必要

チャンネルサーフィンには先述のように便利なショートカットが存在し、簡単に慣れてしまい気づけばキーボードから手を離さずに操作できるようになります。

しかし、未だスレッドには大したショートカットが存在しません。3 replies をクリックするか、ショートカットでThreadsを開いて遡るしかありません。チャンネルを巡るのにはいくつかの簡単なショートカットを覚えるだけで良かったのに、スレッドのせいで一度キーボードから手を離す必要があるのです。

不要なスレッドさえ無ければ、こんな煩雑さは味わわなくて良いのです。

6. モバイル版ではチャンネルとスレッドを同時に表示できない

モバイル版のSlackでは、チャンネルをスクロールして眺めながら気になるスレッドを開く必要があります。すると、チャンネルは表示されなくなります。そのスレッドに至るまでの文脈をおさらいするには(Androidでは)戻るボタンを押す必要があります。

チャンネルであれば上にスクロールすれば良いだけなのに、チャンネルの情報を追うために通信をしてまでスレッドを開き、他のポストを追いかけ直すために何度も戻らなければいけないのです。

通信環境の悪い場所でローディングを経て表示されたスレッドに「うける卍」としか書いていなかったとき、どう思いますか?(そんなスレッドは見たことがないけど)

7. スレッドを開く処理が遅い

チャンネル移動よりもスレッドを開く処理は明らかに遅いです。モバイル版は(?)通信処理が挟まるので、なおさら遅いです。一日に何十回もスレッドを開くので、この遅さは無視できません。なのに、通知が来てせっかく開いて「了解です!」みたいな大した情報量もないときの残念さといったら…。

急ぎじゃないならチャンネルにポストしましょう。

8. 他のメンバーがUnfollowしたことに気づけない

通知の仕様理解を誤った故に通知爆撃が届き始めたら、Unfollowボタンで通知が届く本人の意志で通知を止めることができます。

f:id:nogahighland:20191109015426p:plain

しかしながら、Unfollowしたことは他の人には分からないので、スレッドで会話をしている人はあなたがまだそこにいると思ってしまうでしょう。これは認識の非対称を生むのであまり好ましくありません。あなたが通知爆撃から解放された安堵と引き換えに、誰かの「読んでくれているだろう」という期待を知らずしらずのうちにないがしろにしてしまっているかもしれないのです。

これはスレッドの改善して欲しいポイント上位に入る不便ですが、Unfollowしないといけない状況を避ける、つまり スレッドを避ける努力 も望まれます。

9. 返信しづらい

僕は横長ディスプレイを右側に配置しているので、右の最果てを見ながらタイプしています。すると首が痛いんです。「ディスプレイを左に置けばいいじゃん?」と思うんでしょう?でもディスプレイ配置はSlackのためだけじゃないんですよ!!!!!(憤死)

f:id:nogahighland:20191109015544p:plain

また、モバイル版Slackではチャンネルとスレッドを同時に表示できないので、スレッドにいくつか過去の発言を引用したい場合は

  1. 過去の発言のリンクをコピー
  2. スレッドに戻って返信したいメッセージを探す
  3. 入力欄に貼り付ける
  4. 戻る
  5. チャンネルを検索する
  6. 遡ってメッセージを探す(1に戻る)

という大変に時間・集中力を必要とする作業が必要になります。以前はスレッドの下書きメッセージが消えてしまうことがあったので、更に不便でした。

(しかし、よく考えれば直接スレッド返信フィールドを使うよりもメモ帳を使えば少しは楽になりそうです)

10. ファイルを添付しづらい

スレッドは、スレッド一覧を開いた時だけファイルをドロップできないんです。

f:id:nogahighland:20191109020018p:plain

右ペインにスレッドを開くには、一度スレッドからチャンネル名をクリックして 3 replies をクリックして右側にスレッドを開き、首を右に傾けながらファイルをドラッグ・アンド・ドロップしないといけないんです。しかも、僕の場合はデスクトップのファイルが見えるのは左側のディスプレイなので、ドラッグ距離が長いんです。

そもそもSlackを使うのにキーボードから手を離したくない。ファイル添付だけならいざしらず、ちっこいリンク文字にカーソルを当てるという極限集中作業を2回もしないといけないのはなぜ? それはスレッドを使っているからです。 不要なスレッドさえ無ければこのストレスはないはずなのです。

11. スレッドの下書きがDraft一覧に現れない

Slackには、チャンネルに投稿していない下書きメッセージがあると「Drafts」という項目に現れる仕様があります。

f:id:nogahighland:20191109020118p:plain

しかし、まだスレッドにはこの仕様が統合が行われていないのでしょう。渾身のギャグを投下するために画像探しの旅に出てその間に他の用事で忘れてしまい、他の誰かが対して面白くないギャグでバカウケしていたとしたら、悔やんでも悔やみきれないでしょう。

うん。このへんは重要じゃないのであまりイライラしない。

まとめ

スレッドの機能コンセプト自体に文句はありません。しかしながら、スレッドをサポートする機能の数々には改善が望まれます。

  1. [解決済み]通知が激しい
  2. メッセージが埋もれる
  3. 参加してないけど気になるスレッドの更新に気づけない
  4. チャンネルショートカットで探しにくい
  5. スレッドを開くのにマウス操作が必要
  6. モバイル版ではチャンネルとスレッドを同時に表示できない
  7. スレッドを開く処理が遅い
  8. 他のメンバーがUnfollowしたことに気づけない
  9. 返信しづらい
  10. ファイルを添付しづらい
  11. スレッドの下書きがDraft一覧に現れない

また、Slackはチャンネルの出入りが自由だったり拡散しやすいという仕組みから 情報をスムーズにする というコアなコンセプトがある(と思う)にも関わらず、スレッドの使い方次第でそのコンセプトから逆行してしまうのも、気になる点の一つです。

スレッドの本来の使い方は「チャンネルを作るまでもないサブトークを行う手段」だと思います。同じチャンネルで複数の会話が同時進行し初めたとき、または、予め長い会話が予想される場面で「〇〇スレ」と名付けておくと、有効にログが残せることが多い気がします。ライブ議事録や勉強会・障害実況など。

一方で、スレッドというのは本当に難しい機能で、通知設計やショートカットによるナビゲーションまで含めたUIが大変に設計しづらいものだと感じました。その要因は以下のようなものだと感じました。

  • チャンネル名のように、ユーザーが指定できる識別子がない。
  • 同時多発的に自然発生するのですべてを追うのが不可能。
  • invite/join/leaveが暗黙的なので通知の基準を設定しづらい。
  • PCではチャンネルタイムラインと同列に共存してしまう。

革新的なアイデアを出してSlackメンバーの参考にしてもらおう、と思ってもなかなか解決策が出てこない難問です。自分ができるのは、ペインをより生々しくフィードバックすることかなと。

Slackメンバーの皆様、日々Slackを便利に使わせていただいており、応援しております! これからも頑張ってください!

考え始める勇気

日報や議事録のTODOにある「どのようなことをすればよいか調査する」のような一文にモヤモヤを抱いたことはないでしょうか? 最近、やっとこのモヤモヤを言語化することに成功しました。

これはズバリ 「誰でも分かる方向性だけ示して具体性がない」 ということだと思います。

方向性というのは割と誰の目にも明らかであり、「調査する」ことに異論は無いはずです。しかし、そのみんなが知りたいのはその具体的な調査内容や調査結果なので、あなたが先陣を切るのであれば「〇〇ができるかどうかを調査する」の〇〇をできるだけ具体的にすべきでしょう。

では、なぜ「どのようなことをすればよいか調査する」と、誰でも分かることを言ってその場を濁してしまうのでしょうか。

人間というのはわかりきっていることをするのは簡単なので大好きです。一方で、まだ何をすればよいか分からない・成功するかどうかも分からない不確実なものは非常に億劫に感じられるのです。そんな億劫に感じる自分を自覚して克服できなければ、可能な限り長くうやむやに放置してしまいます。頭を使うことが大きなコストに感じられるから、一見まっとうに見える事を言ってやり過ごしているだけなのです。それが「どのようなことをすればよいか調査する」の正体だと僕は思います。

一方で、進捗を期待する他者にとってはより具体的な方向性が見えていないと不安ですし、信用して任せることができません。鋭い人は「何をどう調査するの?」と追求してくるでしょう。そのようにお互いストレスを抱えたくなければ「考え始める勇気」を振り絞り、頭を使って方向性を具体的にしましょう。

そうすれば、信用してもらうだけでなく、有益なアドバイスをもらうこともできて一気に物事が加速するようになるでしょう。

方向性を具体的にする・しっかり考えるということを終えた後に気づくことがあると思います。

それは意外と簡単だった ということです。

しかし喉元を過ぎればの逆で、次に同じシチュエーションに遭遇したときには「めんどくさそう・・・」と思ってしまうのが常です。

では、この「めんどくさそう」「意外と簡単だった」の正体を図解してみましょう。

f:id:nogahighland:20191109013243p:plain

考え始める前には考えること自体が億劫で、大変な作業だと思っているかもしれません。そして先延ばしにして期限に迫られて実際に考えてやってみると意外と簡単だった。

これは結果だけ見れ先延ばしにしたぶんの時間はただの「考えたくないというストレス」だったということになります。しかし、この無駄さえなければ他のメンバーにどれだけの時間が生まれたでしょう。

もちろん、このような経験が身に沁みるのは極限状態に置かれて有無を言わさず考える・実行するの連続を経て体(脳筋?)がクセ付けされて初めて体験として覚えることだとは思います。しかし、できるだけ早くこういうテクニックを身につければ、簡単に仕事量を何倍にも伸ばせるような気がします。

「考え始める勇気」を持てば、自分にも周りにも多くの時間を生み出すことができ、それがひいては大きな生産性につながるのだと思います。

メッセージに色を付ける

2つの封筒が届きました。

f:id:nogahighland:20190911233723p:plainf:id:nogahighland:20190911233823p:plain

どちらのほうがメッセージをより強く感じたでしょうか?言わずもがな、後者でしょう。

  • 期限までに納付してなかったんだ😱
  • やばい、納付しないとまずい😣

さらに、メッセージのほぼ全てが伝わったところで、次にすべきアクションを想起させられるでしょう。 早く中身を確認して、取るべきアクションを明確化させるパワーが後者にはあります。

  • 期限すぎると罰金とかあるのかな?💸
  • 期限とか、振込先は書いてあるかな?
  • 税務署に行かないといけないと、行ける時間が限られちゃうな・・・

仕事上のメッセージ

あることを伝えたくて、それについて詳しい文献を見つけ、チャットで共有しました。 このリンクCTRは果たして何%でしょうか?

https://docs.ruby-lang.org/ja/latest/class/Array.html#I_FLATTEN

多少ゆとりがある時でなければ、開こうとは思わないのではないでしょうか? ただでさえ業務は毎日多忙。その中でもしかしたらロードの遅いページなんかだとイライラして最悪です。

では以下だとどうでしょう。何を伝えたいのかコアメッセージが抽出されています。

Array#flatten の使い方

flatten は自身を再帰的に平坦化した配列を生成して返します。 lv が指定された場合、lv の深さまで再帰的に平坦化します。 https://example.com/article/12345678

内容に興味を持ってくれ、その人が抱える課題にミートすることが分かれば自然とコアメッセージの周辺まで興味を持って読んでくれ、あなたが伝えたかったメッセージを十分に咀嚼してくれるのではないでしょうか?

もう一つの例。「○○について」はよくありがちなメールやドキュメントのタイトルです。 このタイトルからどのようなメッセージを受け取るでしょうか?

2019年度健康診断について

では次に、以下のようなタイトルではいかがでしょうか。

【9/11 18:00〆切】【所要3分】健康診断の希望日時アンケートの回答をお願いします

先程のタイトルが視力0.3の視界だとすれば、視力が1.5くらいに上がった気がしないでしょうか。

発信者がコストを負担する

ここまでの例は、タイトルの通り「メッセージに色を付ける」ということの例でした。 しかしもう一つの大事な側面は、発信者がコストを負担しなければ、メッセージには色が付かないということです。

こと教育という観点では教える側はすでに知っている情報をわざわざ再言語化することは直ちにはコストです。「教えてもらう側が必死に吸収すべき」という努力の期待もあるでしょう。

しかし、教育の本来の目的が、スキルや知識を伝搬することによって能力をスケールさせることがであれば、効率よく伝わることが総合的に最もコストの低いスケーリング道ではないでしょうか。抜粋を加えたり、タイトルをちょっと長くするくらい、読み解く方のコストからすれば安いものです。

もちろん、情報を提供される側は、期待された程度・あるいはそれ以上の吸収を望まれているわけなので、こうした工夫にかけられたコストに感謝すべきなのは言うまでもないでしょう。

転職1ヶ月

ある程度の中企業から正社員30名程度のスタートアップに転職し、1ヶ月が経った。

いろんな文化の違いを目の当たりにして戸惑いつつも、今までの自分に足りなかった経験を得られそうだという期待を感じている。1ヶ月の間で感じてきた文化の違いをつらつらと書いてみようと思う。

良いところ

誰にも負けない強みを持っている人が多い

人数が少ないから、エンジニアはiOS / Android / フロントエンド / サーバサイド(兼インフラ)に関して自分は社内で一番これが強い!というブランディングができている人が多いと感じた。また、その自負を持って積極的にいろいろ学びに行ったり発信したりするので、とても頼りになる人が多い。

また、デザイナーがグロースなどのビジネスに強く関与し、プロダクトの哲学を形作るところに関わっているので作ろうとするものに納得感がある。ここはスタートアップでも他社より強いところだと思うし、そういう社風に惚れ込んで転職したので、エンジニアとしてももっとエンドユーザーの話を聞きに行って、深層心理上で満足できる=良質なUXを提供するということに深く関与していけるチャンスだと感じている。

技術に対して良識がある

  • 他人のコードレビューを理由に品の悪い批判したりするようなことは無い。 Pull Requestを通して純粋にコードに対するアドバイスをしあって気持ちの良いレビュー文化が根付いている。前職ではオラオラ実装がまかり通っていた所も結構あったので、こうしたほうが良いよね、的な話がスムーズに通じるのはストレスフリーで良い。
  • 技術的負債やシステムパフォーマンスに対して日常的に課題意識をもち、対策を講じている。

知識をオープンにする

知っていること、得たことで、他人のためになることはなんでもQiita::Teamに書いている。特にユーザーインタビューをした記事は面白くて、一つの機能に対してインタビュイーの生活が深く関わった体験談が詳細に語られているのがとても新鮮である。歯に衣着せぬいいぶりも良くて、他人行儀じゃない仲間意識が前提にあるから安心して好きなことを言える文化なんだと思う。とにかく生の声が多くて、読んでいるだけで刺激にもなる。

プロダクトが少ないぶん、徹底的に最適化を考えている

  • GitHubにISSUEがたくさんあり、すごい勢いで消化されていっている。SlackのGitHubチャンネルに様々なリポジトリのコミットやレビューが死ぬほど流れてきている。

フランク

社長はじめとする創業者陣は歳が近いので、雲の上という存在では全く無い。フラットに接してくれるし、みんなも普通にフラットに接している。そんな人達でも、産みの苦しみを味わって成功したスタートアップに育て上げてきた苦労は並大抵ではないはずなので、心の奥に畏怖の念を隠して接している。

遅刻という概念が無い

朝が苦手な自分だが、今の会社では同じ出社時間でも早いほうになったっぽい。前職では電車遅延や申請休暇以外で1秒でも打刻が送れると半日分の給料が引かれてしまうというスリルがあったが、今は裁量労働制なのでちょっと疲れが溜まれば朝ゆっくりできるという安心感がある。まぁあまり朝がズルズル遅くなっていかないようにはしている。

悪いところ

結構夜遅くまで残る

前職も昔は結構平気で終電近くまで働いている人がいっぱいいいた。もちろん一人ひとりの責任範囲が広かったりパフォーマンスも高いので、無駄に仕事をしているわけではないし、残っているぶん早くプロダクトが進化している。

ただ、どうあっても夜遅くまで働くと疲れるのは事実。健康は損なわないように仕事をしたい。

深夜・休日対応

  • 悪いカテゴリじゃなくて単純に自分がなんとかしないと困るなー、という心配。
  • インフラを少ない人数で運用しているので、深夜・休日のサーバー対応なども結構発生しているよう。深酒で気絶睡眠してしまうことがよくある自分は、ちゃんと責任を果たせるようにしないとヤバいという気持ちがある。

ただびっくりしたところ

ツイッター名で呼び合う

本名とはおよそかけ離れた名前で呼び合うという文化にちょっとびっくりしている。結構シリアスな場面でもそう呼び合うのでまだちょっとむず痒い時がある。 同時に、そういう名前を自分は持ち合わせていなかったので、本名で呼ばれるとちょっと恥ずかしい。

あんまり新人扱いされなかった

少ない人数で親密度の高いコミュニティなせいか、いろいろ手取り足取り教えてくれるということも特になく、たまに困っていたら教えてくれる程度である。例えばコーヒーメーカーの使い方(粉の場所とか)、Slackの入ったほうがいいチャンネル、社内手続きのサイト、名刺の発行、夏季休暇制度、入社◯ヶ月面談等…の案内があまり無いところ。11時にB'zのBGMが突然流れはじめたときがあって、それが週1回みんなで行うお掃除タイムだとその時知った。

制度面は最低限説明があるけどちょっとギリギリだったりする。その他必須じゃない事項は自分でいろいろ情報を漁らないと永遠に知らない可能性もある。幸い漁り癖のある自分はなんとかキャッチアップしつつある。

所感

Railsも初めて触るレベルで採ってもらってまだほとんど貢献できていないのが悩みの種。自分が会社にとってプラスになったと思えるような強みを開花させていきたい。特にやっぱりサーバとクライアント(Web/iOS)触れることでのスピード感や、ユーザー体験に対するこだわりというのを活かして実のあるアウトプットを量産できることが自分にできる貢献なのかなとは感じている。

ぜひ、こういう姿になりたいと思っている。

ninjinkun.hatenablog.com

ただ、その道中で色々な刺激を受けて興味が出すぎてしまうと、とかえって路頭に迷ってしまう。 あれこれ手を出した挙句一体自分は何も身についていない。みんな凄いのに、と。

http://in.fablic.co.jp/entry/feedbackin.fablic.co.jp

「◯◯をやったほうがいい」というフィードバックが重要と思うなら、「◯◯をやめる」を見つける必要がある。

これは社内の哲学者みたいな方が書いたエントリーだけど、目が覚めるような金言の連続だった。贔屓目無しに良エントリーなんだけど、そういう思想を持った人と一緒に働けるというのは幸せなことである。

プロセスとアウトプット

華々しい成果というのはその煌めきの10倍、100倍泥臭い仕事が多い。

システムという仮想世界と、大工といった実世界の違いはその複雑性が目に見えるか見えないかの違いなのだが、ユーザーからはもちろん、管理者にも見えないために「作っちゃいなよ」とか平気で言われたりする。さらに、夏目漱石

世の中に片付くなんてものは殆どありゃしない。一遍起った事は何時までも続くのさ。

と言っていたりもするように、作りっぱなしのものなんて殆ど無い。思いついたように「機能追加してみようぜ」なんてことはざらにある。

それ自体は何の問題もない。創造性が溢れてきて具現化したくなることは、人間冥利に尽きる。ただ、作るにあたっては受け手にその責任を全うしなければいけないと思っていて、そのためには「作る」作業が効率化されているべきだと思っている。

何もコーディングだけではなくて、知識共有の習慣化だったりソースコードの標準化だったり、自動化だったりする。

  • 個同士は編隊されて合議したルールに基いて行動することで相乗効果を発揮する
    →チームメンバーがお互いのナレッジを共有しあうと、効率的だ
  • そのためにリーダーやマネージャが組織を作る
    →リーダーはそういうチームづくりを促進すべきだ
  • その先にアウトプットがある
    →そうすると早く作れるだ
  • チーム同士も個と同じ
    →チーム同士も共有するといいだ

あんまりにも状況が酷いとこんなふうになってしまうのだが、実はしれっと効率化して白鳥のように優雅に良い物を作りたいですよねって話です。

「○○性」「○○化」という言葉遣い

自分は「○○性」「○○化」という言葉遣いが結構好きである。いろんな具体例がひっくるめられていて、一言で5点セット・10点セットプレゼントした気分になるからだ。 でも、これが伝わりづらいことに気づいてきた。

反復性のある手順は資料化してアクセス容易性の高い場所に置いてください。

とか言うと「何をすればいいんですか」と言われやすいことに最近気がついてきたのだ。

でも、だからといって

今教えてくれた話、他の人も必要かもしれないからどこかに書いてURL共有して

と伝えると「次に教えてくれる話」はどこにもシェアされず終いだったりする。

「ドキュメントを書きましょう」の話であれば、自分や他の誰かが残してくれたドキュメントにお世話になったり、自分が教える手間を省けた体験が無いとダメなのかもしれない。自分はドキュメント書け書けとうるさく言われたり、辞めた人が残していってくれたものに感謝しているうちにいつの間にかドキュメントジジイになりつつある。

nogahighland.hatenablog.com

500回教えられないと人は覚えないという話を読んだことがある。

これは恥ずかしながら自分もそうで、新卒の頃は先輩方には繰り返し繰り返し教えてもらって、その度初めて知ったようなアホ面を晒していたのだと思う。具体的な話を500回聞いて、その共通項が紛れなくなった時に教えられたことが抽象化されたのだと思う。

でも、新卒なら覚えることが多すぎてそうなるかもしれない。でも、いくらなんでも5人のオトナのチームメンバーと日々情報共有するのに一人500回も教える気になんてなりゃしない。3回でも大変である。

だから教えられる側もできるだけ

今教えてくれた話、他の人も必要かもしれないからどこかに書いてURL共有して

という話を

反復性のある手順は資料化してアクセス容易性の高い場所に置いてください。

というふうに抽象化して考えてもらいたいものです。