1on1は必ず議事録を残す(ときどき公開だってする)
これはFOLIO Advent Calendar 2019 16日目の記事です。
昨日は@grimroseさんのScala.jsとcatsとその仲間たち - Qiitaでした!
昨年の秋から、リーダーとして採用とかチームの健康診断(?)とかをやっています。
難しいしなかなか上手くいきませんが、自分よりずっとベテランなメンバーの皆にアドバイスや見守りをいただきつつ1年生を終えました。
書籍や先人のブログ、周りからの声なんかを参考に見よう見まねでやってきましたが、何をするにも意識していたのは「前回との繋がり」がなくならないようにすることです。
ふりかえりや月次報告会のように、数週間に1度行うようなアクティビティはどうしても前回の記憶が薄れがちです。それでも、毎度新しい気持ちで望むのでなく、あくまで連続したイベントの中の1回と意識することで
- よいことや成長の積み重ね
- 課題やもやもやの経過観察
を大事にしてきました。
些細で当然のことなようですが、忙殺されると後手になったりもするので、小さなことでも1年続けられてよかったかなという感想を抱いています。
さて、このエントリでは、中でも工夫した1on1についてちょっとだけ詳しく書いてみます。
やったこと
- メンバーごとに議事録をとり、いつでも過去を引き出せるようにした
- 1on1前に前回分を見て、引き続き取り扱った方がよさそうな話題があるかチェックしてから望んだ
(便宜上、リーダーやエンジニアリングマネージャーががやる方を1on1のホスト、メンバーを1on1のゲストと呼びます。一般的な呼称があったら教えてください)
ゲスト専門だった頃は共有ドキュメントとしてオンラインに1on1の議事録がある状態を体験したことがなかったし、自分にとってはそれを残すこと自体が新しい試みでした。
過去の経験から、自分でメモを取ると「雑すぎて見返してもよく分からん」「そもそも話すのに夢中で何もメモできなかった!」なんてことになりがちだったので、はじめから「ホストが記録を残すよ」という体にすることで、ゲストには話すことに集中してもらいつつそこそこ意味の分かる記録を残すことができたように思います。
1on1はフォーマットを大体決めていたのですが、その中に「前回との差分」という項目も入れていました。
ちょっとだけ準備に時間はかかりますが、必ず前の議事録を見返してから1on1に望むことで、「この前より状況よくなったね」「多分これ未だに解決してないよね、すまん」と経過観察を行っていました。
副次的な効果
「前回の繋がり」のみならず、1on1の記録は他にも役立ちました。
ホストとゲストで認識の齟齬が減る
ゲストが話したことをホストが書き起こすことで、ホストの理解がゲストの思いから乖離していないかを確認することができました。
実際、「これはどちらかというと○○という意味です」「さっきはそう言ったけどやっぱりこうでした」みたいな、訂正のコメントを貰うこともあって助かりました。
希望に応じホストとゲスト以外にも公開し、便利に用いることができる
せっかくドキュメントができるということで、希望者の分だけ、希望する範囲で公開もしていました。
もちろん完全自由にしたので、人によって毎度全社に公開したり、同じ職能の人にだけ見せたり、基本は非公開でときどきチームに公開したり、様々です。
公開された分は、チームメンバーが閲覧して共感コメントを残したり、他チームのリーダーとか経営メンバーが見て状況を把握したりするのに使われています。
個人的には、私だけで解決できない課題の相談相手と目線を合わせたり、リーダーの引き継ぎをしたりする際に役立ちました。
↓議事録を公開してみようと決めたとき社内wikiに書いたもの。1番思想がまとまっているので貼っておきます。おとうふっていうのは我がチームのことです📛
1on1って、やってみるまでは「何かいいことを言わないといけないんじゃないか」「相談されたらスマートに解決しないといけないんじゃないか」ととても緊張していたのですが、回数重ねるにつれ、とにかく相手に喋ってもらって、後からアクションへ移せたらいいかなと考えるようになりました。
それ以降は気持ちとしても楽になり、純粋に尊い時間として1on1を迎えられています。
まぁ、後からでも、聞いたことを日々の行動や意思決定に反映させるのはとっても難しいのですが…。
プログラミング始めた頃「わたしなら初心者の心を忘れずにいられるのに」→どうしても忘れる。リーダーになった頃「メンバーの気持ちでい続けるのに」→どうしても視点が違って気付かないことがある。
— よこな / Ayana (@ihcomega) August 27, 2019
あの頃の気持ちを忘れないことより、今話を聞いて理解することをがんばろー
よく聞く「メンバーが気持ちや意見を話してくれるのはありがたい」っていうのはリーダーのポジショントークやろって思ってたんですが笑、本当にありがたいことなんだと心から思った2019年…
勘違いしちゃいけないのは、リーダーのため(だけ)の1on1じゃないので、私が満足するだけじゃ意味ないんですけどね!
引き続き精進!!
明日は@krrrr38さんです!
『いちばんやさしいGit&GitHubの教本』執筆開始から終了までのできごと
共著で出させていただいたいちばんやさしいGit&GitHubの教本 人気講師が教えるバージョン管理&共有入門 (「いちばんやさしい教本」シリーズ)について、「執筆作業」って実際のところどんな感じなの?といった内容を、実体験とともに記録します。
昨年の終わりに書いた、執筆を進めるための自己管理に関するエントリもありまーす。
ihcomega.hatenadiary.com
本については、多分もう1エントリくらい書きます。内容にフォーカスしたやつ。
📕執筆のきっかけ
もう3年前になりますが、共著者のしょぼちむさん(@syobochim)とJJUGナイトセミナーでGitの入門セッションをやったことがあります。これを知った編集担当のリブロワークス大津さんより、JJUG宛に執筆のご依頼をいただいたのがスタートでした。2018年の1月終わり頃です。
声をかけてくださった大津さん、きっかけをくださったJJUGにはとても感謝しています。
📕協力者探し
実際の作業を開始する前に、共著者、そしてレビュアーという2大協力者を見つける必要がありました。
とてもありがたいことに、相談したらすぐにOKをくれたしょぼちむさんが共著者となり、レビュアーは昔からとってもお世話になっているうらがみさん(@backpaper0)といろふさん(@irof)が引き受けてくださることになりました。
📕構成の検討
3月の終わり頃、まずは章立てを考えるべく、しょぼちむさんと案を持ち寄り相談会をしました。ちなみに、対面で打ち合わせしたのはこれ含め2回のみ(いずれも執筆開始前)で、それ以降はすべてオンラインでのコミュニケーションでした。
あまり意見が割れることもなく、書く内容についてはスムーズに合意がとれた印象です。悩んだのは、概念の説明を先にするか、いきなり手を動かすハンズオンから始めるかといったことくらいでしょうか。なお結局、
- 理解しないままとりあえず触ってみる
- 何が起きているかよく分からないが一応バージョン管理らしいことはできる
- 雰囲気で使い続ける
- 意図しない挙動に出くわしたときに一気に詰む
という自らの経験に基づき、読者には同じ経験をしてほしくない思いから前者を取りました。
📕執筆開始
さて、構成案を提出し、5月頃から試しに第1章「Gitとは何か」を書き始めました。試しと言ったのは、
- 執筆用ツール(後述)の使い方を確認する
- 文体や内容などの方向性を確認する
といった意味合いの作業だったためです。
しかし…書き始めが5月とは…。打ち合わせが3月、しかも意見が割れずスムーズに進んだと書いておきながら1ヶ月空白期間があることが驚きですよね。そう、我々なかなか進めなかったのです。(これは私個人の話ですが、)「何から始めたらいいんだ」「やらなきゃいけないけど不安だけを募らせ進捗はない」といった状態が続いてしまったように思います。
そんなとき、うらがみさんが状況の確認やリマインドもしてくださったのに助けられました。申し訳なさと感謝でいっぱいです。はじめに紹介したエントリ(FOLIOで学んだマネジメントやリーン開発の知識を本の執筆に活かす - よこなのへたのよこずき)のような工夫も、この時期の遅れがきっかけだったりもします。ぴ、PDCA…。
✏執筆用ツール
「いちばんやさしい教本」シリーズの執筆には、強力なツールが用意されています。先程もご紹介した編集担当の大津さんが作ったatomのプラグインで、これがあれば書きながら完成イメージを確認することができます。
見たほうが早いので見せます!
すごいですよね。左側が原稿です。マークダウンをベースに、独自の記法も用いて書けば、右側のようなプレビューをリアルタイムに確認しながら執筆作業ができるのです。
- ほぼマークダウンなので楽に書けるしバージョン管理もしやすい
- 章の分量を適切に調節しやすい
- レイアウトに関する編集担当の方とのコミュニケーションがスムーズにできる
- 完成イメージが見えるためモチベーションがアップする
などメリットがたくさんで、とてもありがたいツールでした(以下、リンクです)。
📕執筆作業の本格化
試しに書いた第1章がapproveされ、構成案に従ってひたすら書くフェーズに入りました。もちろん、構成案は何度も見直しながら、10月頃まで作業が続きます。
編集担当の方と原稿をやりとりした回数を図示してみました。DTP (参考: DTP - Wikipedia) をはじめ専門用語もありますが、要は編集担当の方と著者とで交互に内容を見直し、修正とレビューを繰り返す作業をしていたということです。
✏レビュー
レビュアーのうらがみさん・いろふさんには感謝してもしきれません。特に、
- 技術的な正しさや分かりやすさ: 入門書ということもあり、両者のバランスが非常に重要だった
- 現場で使える情報: 様々な使い方ができるGitの、何を伝えれば現場で役立つ知識となるか考え続ける必要があった
を追求する上で、お2人のアドバイスは不可欠でした。様子を少しお見せします。
正確性のチェックや・・・
分かりやすさに関するアドバイスや・・・
使い方議論や・・・
そして嬉しいコメントも!
マージまで見届けてくださって、こういうリアクションつけてくださってたのも全部励みになっていました。
このレビューの内容こそ、GitHub入門者に見てほしい学び多きものですね。お2人とも、本当にありがとうございました!
✏スクリーンショットの工夫
入門書ということもあり、スクリーンショットはそりゃもう大量に撮りました。そんな中、しょぼちむさんとそれぞれ別のマシンで作業していたため、環境の差異をなるべく小さくする必要がありました。撮る範囲やフォントサイズなどをはじめ、しょぼちむさんにヒアリングして気合で揃えた部分もあるし、ちょっぴり工夫したところもあるのでそれを書いておきます。何かというと、ターミナルのプロンプトの表示をしょぼちむさんマシンに合わせる方法です。
こんな感じです。当たり前のことながらPC名が異なったので、PS1を編集することで実現しました。このおかげで、 ichiyasa
という本に登場するユーザーを作る必要もなく、ほんのちょっとだけ楽できた気がします。
export PS1="\[\033]0;$TITLEPREFIX:${PWD//[^[:ascii:]]/?}\007\]\n\[\033[32m\]ichiyasa@DESKTOP-LHHCMC7 \[\033[35m\]$MSYSTEM \[\033[33m\]\w\[\033[36m\] \`__git_ps1\`\[\033[0m\]\n$"
📕編集チェック
初稿が書き上がったら、大津さんによる編集作業が始まります。構成や表現の改善、分量の調整などをとても丁寧に行っていただき、また、未経験者がつまずきそうなポイントの補足依頼や質問も投げかけていただきました。初心者向けで書いたつもりでも、親切さが足りない部分が多々あるなぁと痛感する日々でした。特に、「なぜそうするのか」「どうしてこうなるのか」といったwhyに関する質問はとても勉強になったポイントです。
例えばこのようなご質問。 git remote -v
って同じような結果が2行表示されるんですよね。でも、私の目にはこれまで1行にしか見えていなかったと言っていいほどで、それがなぜなのかとか、各行の意味の違いとか、今回の執筆で初めて意識しました。大津さんからはこうしたコメントをたくさんいただき、知らなかったことの学習もできました。
何度も何度もレビューを繰り返しよい内容にしてくださったこと、心より感謝しております。
📕刊行
11月後半にすべての工程が終了しました。 進捗の遅れがあったり、すごい量の修正に圧倒されたり、いろいろなことを乗り越えてなんとか出版することができました。月並みですが、物理本を初めて受け取ったときはとても嬉しかったですね。我が子…。
同僚や友人に献本もして、フィードバックを貰えているのがとてもありがたいです。ブログを書いてくださるみなさまも、本当にありがとうございます。
📕写真撮影
最後に、脱力しそうな話題を。表紙のイラストについても少し書いておきます。
「いちやさ教本」シリーズは、イラストレーターさんによるとってもリアルな似顔絵がいたる所に載ります。元となる写真はプロのカメラマンによるもので、インプレスさんのスタジオで撮影しました。表紙用と中身用4種類と、結構な時間をかけて撮っていただき、これも貴重な経験でした。他の著者の方はガッツポーズやイイネポーズくらいにとどめている励ましポーズが、自分の場合 :ok_woman: 風になっているのがイチオシ(?)です。オリジナリティを出していいとカメラマンの方がおっしゃっていたので、勝手にやりました。
ちなみに、自分は無言での撮影だったにもかかわらず、しょぼちむさんは写真撮影のときカメラマンの方に「Gitがんばろう!」「よくできました!」とか言わされていてとても謎でした(面白かった)。
まわりの方にただただ感謝
そんなこんなで出版にこぎつけることができたのも、出版後に嬉しい反応をいただけているのも、多くの方の協力あってのことです。みなさまにはただひたすらに感謝が尽きません!!
ありがとうございました😊そして引き続き『いちばんやさしいGit&GitHubの教本』をよろしくおねがいします😊
『アジャイルレトロスペクティブズ』を読み、ふりかえりで「KPT」以外の技を繰り出そう
かれこれ1ヶ月ほど前でしょうか、チームで新しいことを始めようとしてるんだけどイマイチ進まないな〜という状況が訪れたので、ふりかえりをすることにしました。ここ数ヶ月属してきたチームでは、振り返りというと同僚の@Mura_Miによる次の記事にある方法が便利で、よく使ってきました。また、以前は定番の「KPT」をやることもよくありました。
ところが、今回やりたいふりかえりは、これまで取り組んだ手法ではワークしない可能性がありました。というのも、まだこれからやっていくぞというフェーズなので、見返せるような具体的な材料がスムーズに出せなかったり、チーム内のコンテキスト共有が不十分で不完全燃焼な議論に終わったりしてもおかしくない状況だったためです。
なお、弁解しておくと、コミュニケーションが苦手あるいは不足しがちなメンバーというわけではなく、「新しいこと」に向かう姿勢やイメージがまだ十分に議論・共有できていない時期だったのです。具体的には、またまた@Mura_Miによる記事 FOLIO を支えるエンジニアリング組織の七転八倒記: 2018年冬 - TechとPoemeの間 に記載の、バックエンドエンジニアをサブグループ化した直後でした。
また、これはフェーズや手法云々ではないのですが、
- 具体的なアクションに結びつかない
- 継続的な効果測定ができない
- ふりかえり自体に価値があったのか曖昧である
といった課題を残すふりかえりを過去に何度も経験してきました。
せっかく集まるからには
- 全員がアイディアを持つことができ、発言できる
- ふりかえりの場の具体的なゴールを定め、達成する
- 議論した内容がその場限りにならず、何らかのアクションに結びつく
を目指して準備をしようと決めたのですが、具体的なアイディアが浮かばず…。どうしたもんかと考えていたとき、以前@syobochimさんが書いていたブログ記事を思い出しました。
ここで紹介されている『アジャイルレトロスペクティブズ』、タイトルのとおりレトロスペクティブのhow-toやTipsが記載された本です。ふりかえりの具体的な方法も紹介されているようだったので、明日使える知識として何かヒントが得られればと手に取ってみました。
📖読んで学んだこと
💁ふりかえりをする会の構成
会の時間のすべてを、課題の抽出と解決策の検討にあててしまうことってよくありますよね。ところが、『アジャイルレトロスペクティブ』では、次のような構成に分けて取り組むことが有効だと述べています。
- 場を設定する
- まず集まったメンバーに感謝を述べ、会の目的と目標を伝える
- 全員が1度口を開くチャンスを与える
- 会の進め方を説明する
- チームの「価値」や「約束」を再確認し、見直す (ない場合は設ける)
- データを収集する
- 客観的なデータ(開発した機能、完了したストーリーなど)を収集する
- チームメンバーの感情を確認する
- 集めたデータをレビューする
- アイディアを出す
- 起こったことの原因や物事のやり方などについて考え、よりよい方向へ進むためのアイディアを出す (解決策には飛びつかない!)
- 何をすべきかを決定する
- アイディアから、取り組む項目を決定する
- 担当者を決める
- レトロスペクティブを終了する
- 板書や付箋など、アウトプットを記録に残し、共有する
- レトロスペクティブ自体に価値があったかどうか振り返る
💁ふりかえりを計画・実行するための進め方
何を検討してどう計画を立てたらよいか、実際のふりかえりの場においてどんなことを管理したらよいかといった内容も、具体的に考えねばならないことと併せて分かりやすく示されています。
計画する
- チームを知る
- 目標を決める
- 場所を決める
- 全体の時間とタイムボックスを決める
- 取り組むアクティビティを決める
- 参加者を決める
- 周りのサポートを受ける
など
実行する
- アクティビティを管理する
- 集団ダイナミクスを管理する
- 時間を管理する
- 自分自身を管理する
など
💁さまざまなふりかえりの方法
ページ数も多く割かれボリュームたっぷりなのが、会の構成に沿った分類で紹介されているふりかえりの方法たちです。
- 「場を設定する」アクティビティ: 6種
- 「データを収集する」アクティビティ: 8種
- 「アイディアを出す」アクティビティ: 9種
- 「何をすべきかを決定する」アクティビティ: 6種
- 「レトロスペクティブを終了する」アクティビティ: 9種
種類の多さを示すために数字だけ書きましたが、どんなものがあるか、こればっかりは実際に本を見てみるのが1番です。世の中KPTだけじゃないんや・・・。
これだけあれば、面白そうなものや使えそうなものもきっと見つかりますし、「長期のイテレーションに向いている」といった、役立つシーンについての説明もあるのが検討時には嬉しいです。
📖やってみたこと
自分のチームの状況に合っていて良さそうだと思った方法をいくつか実際に取り入れる予定でアジェンダを組みました。
- 場を設定する: 「チェックイン」を使おう
- データを収集する: 「満足ヒストグラム」を使おう
- アイディアを出す: 「5つのなぜ」を使おう
- 何をすべきかを決定する: nullを使おう
- レトロスペクティブを終了する: 「投資時間対効果」を使おう
null... 4つ目だけは本から合いそうなやつが見つからず、知っている方法でなんとか目的を達成しようと決めてしまいました。
💁うまくいったこと
上に挙げた方法でいうと、やり方もシンプルで明確な「満足ヒストグラム」だけは機能した気がします。 それ以外だと、
- 目的
- 目標
- タイムボックス
をしっかり決めておいたので、進行する上で派手に迷うことがなく、なんとか場のゴールにたどり着くことができました *1。
💁うまくいかなかったこと
正直、準備していた方法のうち、「満足ヒストグラム」以外はろくに実行できていません。敗因は
- 本で学んだことを自然あるいは臨機応変に使えない (おそらく理由含めての理解が足りないので、HOWを真似するので精一杯になる)
- 会の時間を短く設定しすぎた
- チームの現状に対する理解が足りなかった
- 諦めた (会のゴールさえ達成すればいいやと早々に思考を切り替えてしまった)
などだと思っています。
💁所感
うまくいったこともいかなかったこともありますが、この本は頻繁に見返したいし、行き詰まったときにヒントをくれる存在として活用していきたいです。
このエントリを書くにあたって読み返してみて、理解しきれていなかった部分や欠落してしまっていた部分も明らかになりましたし・・・。幸いチャンスはたくさんありそうなので、効果検証しながらいろいろ試してみます。
📖おまけ
そもそもファシリテーションをするときの姿勢みたいな話になりますが、準備してうまくいくイメージを持っておくことってとても大事。と最近改めて思うことが多いです。慣れていてもぶっつけでは質が落ちるし、時間がないからってサボると結局集まった人の時間が無駄になりかねません(エビデンスはあまり持ち合わせていませんが、新卒研修でも『ファシリテーションの教科書: 組織を活性化させるコミュニケーションとリーダーシップ』でもそう言ってましたし、経験上そう。もちろん、ただただ能力が高くてできちゃう人もいますが)。準備をしてうまくいく保証はないが、準備をしないとうまくいかないことが多々あるといった感じでしょうか。地道に、知識のインプットと経験を積み重ねて、その質や効率を高めていきたいですね。
*1:チームメンバーが自分より大人なので…絶大なサポートあってですが
FOLIOで学んだマネジメントやリーン開発の知識を本の執筆に活かす
これは、FOLIO Advent Calendar 2018 5日目の記事です。
FOLIOでは2年目のアドベントカレンダー!クリエイターも増えて、去年とはまた違うメンバーで埋まっていて毎日楽しみです。
突然ですが、今月生まれて初めての著書が出ます(@syobochimと共著)。
出版社の方とコンタクトを取り始めたのは1月だったので、おおよそ1年近いプロジェクトを終えたことになります。実際に書いていた期間はもっと短い(後述)ですが、いわゆるスタートアップであり日々全力疾走するFOLIOで社員をやりながら、業務時間中には一切執筆作業をすることなく*1なんとかやり遂げることができました。
ここまで来られたのは、JavaコミュニティそしてFOLIO、この2つのおかげだと思っています。この記事では後者にフォーカスし、書く際のプロセスや心構えについて考えていきます。一方、前者に関することも、また発売後に別の記事にしたいと考えています。そちらは、多少本の内容にも触れたものにする予定です。
😌モチベーションとの戦いを制する「気合い」以外の方法
今回の執筆は、書く内容自体の難易度が自分のレベルよりも高いわけではなかったし、文章を書くことにはあまり抵抗がないし、自分を突き動かすことこそがポイントでした。そして、年齢を重ねるごとに改善はしているものの、自分は何よりそれが苦手なのです。そこで、終えるために行った工夫やFOLIO社員に教わったことを3つ紹介します。
👆遠い目標と近い目標を立てる
- 長期的なモチベーションを保つための遠い目標、すなわち、達成したらどんないいことがあるか
- 短期的なモチベーションを保つための近い目標、すなわち、何をやっていくべきか
を念頭におくようにしました。遠い目標ははじめに妄想しながら設定して、やる気を失ったときに度々思い出す用途で使っていました。
などです(赤裸々)。それに対し、近い目標は、担当章が決まった時点で、
- Gitとは何かを書く
- forkについて説明する
- LGTMについて紹介する
といった粒度ですべての章に対し細かい単位で設けました。
遠い目標があることでやる気を維持し、近い目標があることで、次やることが明確になり手を止めることなく進み続けられるというわけです。何気なくこういう取り組みをしている人は多いような気もしますが、心理学で「長短比較」という名のついた手法だそうですね(『やってのける~意志力を使わずに自分を動かす~』で知りました)。
👆作業のWIP制限を設ける
効果としてはこれが1番大きいと実感しています。
WIPとは、Work In Progressの略で、完了していない仕掛りの作業を指します。特にリーン開発の文脈において、チームが同時にWIPを抱えすぎるのはアンチパターンとして語られることが多いです。今回の執筆はチームというより個人作業*3でしたが、考え方は十分活かすことができました。
これを心がけられたのは、間違いなく@Mura_Mi (同僚) たちが中心となって会社でいろいろ教えてくれてきたためです。WIP制限については、今年の3月頃、フロー効率とリソース効率*4の勉強会が開かれたことで気にするようになりました。FOLIOには #study
プレフィックスがつくチャンネルが色々あり、日々知見を共有したり議論をしたりしているのですが、その勉強会は #study-lean-agile
に集まった有志に向けてのものでした。
では、どんな執筆の進め方をしたか明かします。全部で5章担当したのですが、基本的には章ごとに作業を進めていきました。その上で、WIP制限を原則1 (レビュー進行中のみ2) として、これだけは絶対に守ると決めました。その結果、各章のPRを振り返ると、着手期間はそれぞれ次のようになっていました。
(あくまでこれは1回目に出した本文の原稿がLGTMとなるまでのようすで、この後スクショの差し込みや細かい手直しをしたり、さらに全章何周ずつか見直したり、後続の作業は山程ありました。)
複数の章に同時に手をつけている期間はほとんどなく、大体着手した順に完了まで運べていることが分かります。これがどう良かったかを伝えることで、なぜWIPがよくないかを考えてみることにします。
コンテキストスイッチを防げる
作業の切り替え時には、頭の切り替えを伴います。さらに、前やっていた作業に戻る場合は「何をどこまでやっていたか」を思い出す必要もあり、非常に時間やパワーを使います。言うまでもなく、同時に複数の作業をやると切り替えも多発してオーバーヘッドがどんどん大きくなるというわけです。WIP制限をしておけば、ある期間に考えるべきことを減らすことができます。
終わったことは忘れられる
先ほど思い出すのにかかる時間を減らせると紹介しましたが、そもそも思い出さなくてよくなるのも嬉しい点です。着手したものから順に完了させるようにしたら、一度完了まで到達したあとはしばらくその作業について考えずに済みます。今日の日付や昨日食べたものすら覚えていられないのに、複雑な作業内容をいくつも覚えているなんて難しいことです。
早めにフィードバックを受けられる
着手した順に作業が完了するということは、完了したものからレビューに回せるということを意味します。WIPが多く、どの章も終盤に完了を迎えるということになると、レビューの開始、そしてフィードバックをもらうのが遅れます。早めに気付いていたらそれ以降書く際に気をつけられたことも、終盤まとめて修正するとなると大変です。遅れることで時間的成約により妥協せざるをえなくなる可能性もあるので、クオリティが下がる原因にもなります。
やる気を保ちやすい
多くの章に手をつけると、たくさんの章の進捗があって一見良い気もしますが、「ひとつも(あるいは、ほとんど)完了していない」という状態が比較的長く続きます。これでは、TODOリストやissueに表れるようなタスクが消化できず、何も進んでいない気がして疲弊します*5。一方、WIP制限があると、少しずつ「終わった!」という体験を積み重ねられるので、小さな達成感を感じることができてちょっぴり安心します。
終わる時期の見当がつけやすい
WIPが多いと(つまみ食いのように好きなところから着手するような形をとるとさらに)、全体の何%終わっているのか図るのが意外と難しいです。制限しておけば、WIPとなっている章の進捗さえ分かったら、残りの章は終わったか終わってないかのどちらかなので、全体に対するボリュームをそのまま進捗に換算しやすいです。
レビュアーのWIPを減らせる
レビューがある場合、上記のような恩恵をレビュアーにもおすそ分けできると考えています。終盤にレビュー爆弾を送りつけることなく終えられるわけです。執筆もレビューも人がやる作業であることには変わりなく、WIPが多いと頭の切り替えが辛いし、心理的な負荷が高まります。
😞スケジュールとの戦いに敗れた「本業が多忙」以外の敗因
👆プロジェクトバッファを使ったマネジメントをしたかった
色々うまくいったことを並べましたが、失敗したり迷惑をかけたりしたことも多々ありました。1番大きいのがスケジュール管理で、脱稿予定日を出すための見積もりが何度も派手に外れた上に、ケアも疎かでした。もちろん本業の状況も刻一刻と変化するため、作業できる時間が安定しないというのは仕方ないことではあります。そうした状況だからこそ、もっと見積もりおよび予実管理に頭を使うべきでした。
これも同じく#study-lean-agile
や実際のプロジェクトでの学びですが、各タスクの作業時間見積もりのうち、バッファにあたるものをすべて合算しプロジェクトの終わりに置く方法があります。
上の図でいうと、 バッファのとりかた-1
ではなく バッファのとりかた-2
のようなスケジューリングをするということです。作業中は予定をはみ出てバッファを食いつぶしたらそれを把握しておき、各タスクの進捗とバッファの消化状況から順調なのか、危険で対策を打つべきなのか判断するといった管理をします。今回でいうと、バッファの消化状況が不穏であれば出版社にアラートをあげるといった対応をすることで、締切近くなって「すみません、出来ませんでした」とゴメンナサイするよりはマシな状況に持っていくことが可能です。
また、実はモチベーションとの戦いにも有効です。タスクごとにバッファを設けると、結局バッファ込みの時間で終えようという心理が働いてしまいがちですが、それを取り除くことでタスクの締切を守ろうという動きを取りやすくなります。
かなり前に立てたスケジュールのスクショを引っ張り出してきました。このときは全体のバッファを設け、やる気だけはあったことが伺えます。
しかし、当時
- バッファを設けたところで、何をウォッチしどうマネージすべきなのかを理解していなかった
- 余裕がなかった
- 妥協してしまった
などから途中で諦め*6、失敗に終わっています。『エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング』いわく、納期の重要な案件とも相性がよいようなので、(融通はきくものの)締切という概念の存在する執筆において取り組む価値はあったなぁと今になって残念に思います。
😍多岐にわたる同僚のヘルプ
ここからは、感謝の意を表すちょっとしたおまけエピソードです。
先輩執筆者たちのアドバイス
幸いFOLIOでは身近に執筆経験者がたくさんいたので、迷ったときに話を聞いて救われていました。
特に、@yasuharu519は、直前にGitHubの本 (競合…!) を出していたため記憶が新しかったということもあり、どんな進め方したか教えてもらったり、「完璧を求めたくなるけどできる限りやればそれで十分ですよ」「印税出たら寿司でいいですよ」などと言われたりしたおかげで勇気が出ました。
ストレスフリーな作業環境の提供
環境というと、執筆はマークダウンで行って、GitとGitHubを使って・・・みたいな話もしたいですが、ここでは作業マシンの話。今回、Windowsでスクリーンショットを撮ることになったのですが、持っていなかったので同僚に借りました。
社内Slackにて
「どなたかWindows端末貸していただけませんか」
「使ってないThinkpadありますよ」
って@d_akatsukaに渡されたのがメモリ24GBも積んだハイスペックマシンでした。壊したらどうしようと怯える日々でしたが、それはもうスムーズに、滞りなくスクリーンショットが撮れたのでした。
偶然にも著書の販売がタイムリーだったのでFOLIOの業務と直接関係のない内容となりましたが、ちょっぴりFOLIOの取り組みやメンバーを紹介するお話でした!
執筆は、8月に終えるつもりだったのが9月までかかっている時点でお察しですが、決してスムーズに進んだとは言えません。しかし、終わらせるための道具は気合いのみ、という心許ない状態で作業するのではなく、良しとされている方法で自分をコントロールするために工夫ができたのはポジティブに評価したいです。おそらくこの1年間くらいでのFOLIOにおける学びや考え方の変化がなければこうはなっていなかったでしょうし、事態はより悪化していたことが予想できます。
#study-lean-agile
チャンネルはほんの一例ですが、FOLIOには情報を持ち寄る場があること、そしてそれが活発であることがとても嬉しいです。しかも、学んだ内容はすぐに業務で活かす取り組みが日々見られるし、今回書いたように、個人でも試したくなる、あるいはより深く調べたくなるようなものが多いのがさらに嬉しいです。今どき社内勉強会なんて珍しくないものの、FOLIOのそれはとても質が高いと思っているし、実践的なのです(ありがたい)。たまにメンバーが社内勉強会のスライドを公開したりブログを書いたりしていますが、面白いものが多いのでとってもオススメです😋
さ〜て明日は!隣の席のDDDお兄さんこと@yoskhdiaによる、「Scalaを例に『仕様』パターンを実装する」です!
本記事は著書の宣伝行為ではありません。
参考文献
- やってのける~意志力を使わずに自分を動かす~
- リーン開発の現場 カンバンによる大規模プロジェクトの運営
- カンバン仕事術 *7
- エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング
*1:仕事にも執筆にも集中できず何もかも効率が悪くなることをおそれ、仕事中は急ぎの連絡を返す程度にとどめ、なるべく本の進捗を出すことは考えないようにしていました。
*2:冒頭の商品ページ参照。著者の異常にリアルな似顔絵が掲載してあります。
*3:共著とは言え、ほぼ100%分業していました
*4:フロー効率とリソース効率についてはリクルートさんのフロー効率性とリソース効率性について #xpjugの資料が分かりやすいです。
*5:もちろん、章より小さい単位でタスクを作成すれば消化できますが、章で切るのはちょうどいい粒度だと感じていました。タスクが細かくなりすぎると、今度はメンテが大変になる可能性があります。
*6:最近の業務ではやっています!
*7:WIPについての章をパラパラとめくってみたら、まさに「この本の執筆時、色々な章に手を付けてしまい失敗した」というコラムがありました。まるかぶりだ!
JOnsenでアンカンファレンスが始まるまで #JOnsenUnconf #JOnsen
ここ最近、Javaのコミュニティに出入りしているとよく聞く「JOnsen」というイベント。初めて参加しているので、ちょっとずつ様子を書き残します。
どんなイベント?
温泉地に集いアンカンファレンスをする!それだけ。2017年から始まり、年1回の5月開催です。
企画や進行はStephenやSebastianがオラクルの伊藤さんと一緒にやってくださっています。2年前に来日した際、北海道の温泉で思いついたイベントだそうです。
ちょうどJava Day Tokyoというカンファレンスのタイミングと合っていることもあり、海外のJavaチャンピオンやJavaエキスパートもたくさん参加します。彼らと2泊3日一緒に過ごすことができるあまりにも濃いお泊りイベントなのです。
ちなみにオラクルが宿泊費を負担してくださるので、交通費だけで最高温泉に行けちゃうんだな😉今回は露天風呂が本当に素晴らしい箱根の宿!!芦ノ湖に浸かってるみたいだったし富士山も見えました。
アンカンファレンスって何?
参加者がアイディアを出し合って、セッションのトピックをその場で決めて行うカンファレンスです。
JOnsenでは、テクニカルなトピック (Java SE 9、Javaの新しいリリースサイクル、マイクロサービスなど) も、そうでないテーマ (コミュニティ、教育、プレゼンテーション、カンファレンスなど) も扱います。誰かが資料を作って講義をするようなことはせず、皆で輪になってディスカッションする形式を取ります。
ここからはJOnsen 2018の報告です💁
オープニング
参加者が集まったら、JOnsenとアンカンファレンスについての説明がありました。
JOnsenは "The most relaxed unconference" であること、そして次のようなルールがあること。
- 誰でも、どんな内容でも受け入れられる。ここは「安全な場所 (safe place) 」である。
- (同時に2セッションが開催されているが、) いつでも出入りしてもう一方の部屋へ行ってよい。
- 誰かが両手を上げたら「静かにして話を聞いてね」の合図である。
大事なアナウンスをしたい1人が両手を上げだすと、皆黙ってそれに続き、話者に注目する。ディスカッションが盛り上がっていてもすぐ静かになってとてもよい。
シャイで英語に苦手意識のある日本人が多いため、「英語が母語じゃなくても大丈夫だからね、ここでは決して批判されないよ」ということがとても強調されていたのが印象的です。
さて、以上を皆が理解したら、自己紹介とトピックのアイディア出しに移ります。
輪になって、1人ずつ付箋に書いた案を説明していきます。うう、開始時、部屋がやたら暗かったのもあり写真の品質が悪い・・・
うろ覚えですが、皆が挙げていたトピックの例を。
- プロダクション環境でのマイクロサービス(教科書的な話ではなく実践的な内容)
- 関数型プログラミング
- ワークライフバランス(仕事と、OSSへのコントリビュート/ コミュニティ活動)
- 日本の小学生へのプログラミング教育
- カンファレンスでスピーカーをするにあたって大事なこと
初JOnsenということもあり、この時点でかなり緊張していました。知らない強そうな方がたくさんいるし、英語だし、内容が適切なのかな〜とかどうしても思っちゃうし。ですが、本当に何を言っても許される雰囲気を皆が作り出してくれ、今思えば心配することは何もありませんでした。
記録も兼ねて、挙げたトピックをひとつ紹介。最近公私ともに忙しかったこともあり、持ちかけたのは「皆仕事以外で色々な活動をしていると思うけど、タイムマネジメントとかモチベーションの管理どうしてる?」といった内容です。ちょうど社会人になってOSSへの貢献が難しいと感じ始めたというきつねくんのトピックとマージされ、2日目に扱われることとなりました。
30人程度の参加者が挙げた付箋は結構な数になりましたが、タイムテーブルの決定は思ったよりスムーズでした。いい感じにトピックをカテゴライズしながら進行してくれるオーガナイザーたちの慣れが大きいですねー。
く〜ここから本編ですが、今日は疲れたし寝てしまいます😪つづく・・・
同室の人々、晩酌続けてるのか全然帰ってこない。と思ったけどまだ23時かー。
MTGにPCを持ち込まない習慣が思ったより良い
最近、ノートとペンで戦う場面を増やしている。もちろんケースバイケースだけど、自分用のメモはこれで十分、むしろプラスとなる部分が多いなと思い始めた。
それまではもうPCを触りながらMTGへ参加することに慣れきって、思考停止状態に近かったのでとても新鮮。
いいこと
- MTGの度にPCのコード類をいちいち抜き差ししなくてよい
- 電源アダプターとか、モニターとつなぐケーブルとか色々。地味に面倒だから嬉しい。
- MTGに集中できる
- これが1番大きい。うっかりSlack見たり、書きかけのコードにちょっとだけ手を入れたりしちゃわないので、集中度や理解度がアップする。
- 図や絵も気軽に描ける
- アイディアを出したり入ってきた情報を整理したりしやすい。
- 後から見返しやすい
- あの時のメモは大体この辺にあるなーとすぐ見当がつくのでよい。ファイルみたいに見つけやすいような命名を考える必要もない。もちろん検索は出来ないが、それで困るような内容のメモはない。
- 文字を書くリハビリになる
- これはおまけだけど、漢字忘れとかに立ち向かえている気がする。
よくないこと
あくまでPCとノートを自分なりの基準で使い分けているという前提だけど、今のところ特に思いつかない。ノートにとった記録をデータにしたい時は困るんじゃないの?という話だが、そういうときはもちろんPC持っていってその場で書いているし、ノートの写真で済む場合も結構ある。
という小さな記録でした。今日もお疲れ様です。
TrailblazerのReformを使ってRailsのフォームとモデルを分離する
これはFOLIO Advent Calendar19日目の記事です。昨日は@asuyakonoの「デザイナーの僕がいかにしてビデオゲームのUIから「インタラクション・デザイン」を学ぶのか」でした。ゲームをやらない私にとってもめっちゃ面白くて分かりやすい記事だったし、ブクマ数もすごいことになっていました。さ、さすが・・・
さて、このアドベントカレンダーは2回目の登場です。前回は割とエモい記事(証券会社のエンジニア・デザイナーが社外でも最大限活躍するためにFOLIOで取り組んでいること)だったので今回は技術的な話を・・・ということでRuby on Railsについて書きます。
FOLIOでは、サービスとして外部に公開しているフォリオのみならず、社内で証券業務を行うために使うシステムを自前で開発しています。Scala製のマイクロサービスたちがバックエンドに構えていて、そのAPIを用いて機能提供するクライアントとして稼働しているのがRailsで作られたアプリです。最近は専らそのシステムを担当しており、入社前はほとんど書いたことのなかったRubyとも仲良くやっています(たぶん)。
今回は、FOLIOでも一部導入しているTrailblazerというgem群から、Reformというgemについて調べてみました。
業務において
- バリデーション、エラーハンドリング、エラーメッセージの指定をどのレイヤーでやるのがよいかな〜って悩んだ経験があること
- モデルクラスにおいて、入力値(フォーム)とAPIから受け取る値の区別が曖昧で管理がしづらくなっているのを何度か見かけたこと
がきっかけです。
Trailblazerの概要
TrailblazerはRubyのフレームワークに抽象レイヤーを提供するgemの集まりで、モデルやコントローラーからビジネスロジックを排除することを目指しています。純粋なRails wayでの開発にありがちなクラスの肥大化を防ぎ、メンテナビリティを上げるのに一役買ってくれそうなアーキテクチャです。
READMEも公式ドキュメントも丁寧だし、無料で手に入る情報だけで大事なことが詳しく分かります。
Trailblazerの作者が思想・使い方などについて書いた本もあって、最近気になる箇所だけつまみ食いのように読んでいます。著者も「興味のあるところから読んでね!」と言っているし、途中の章からでも理解できるような構成となっていて良いです。
余談ですが、日本語の情報が少ない印象を受けますね。
Trailblazerを構成するgemたち
先程gemの集まりと述べましたが、どういったものがあるのか簡単に見てみます。
- Operation: サービスオブジェクト。ビジネスロジックはこれに持たせ、モデルやコントローラーからは取り除く。
- Cells: UIのパーツを表現するオブジェクト。テンプレートをレンダリングするオブジェクトとも言える。
- Reform: モデルにバリデーションのためのフォームオブジェクトを提供する。
- Representable: オブジェクトとJSONやXMLなどドキュメント間の変換を行う(レンダリング・パース)。
その他、まだバージョン1.0の出ていないRoar、Formula、Disposableなんかもありますが割愛します。
Operationの使い方をざっと
Trailblazerの大きな特徴でありメインともいえる(個人の感想)gemです。Reformの解説でもちらっと登場するので簡単に紹介します。
Operation
はいわゆるサービスクラスにあたり、ビジネスロジックをカプセル化するのに有効です。サンプルコードを先に出します。
class Hoge::Create < Trailblazer::Operation step :process_hoge! step :process_fuga! failure :log_error! success :process_piyo! def process_hoge! # 処理。異常値を返したらlog_errorへ移る。 end def process_fuga! # 処理。異常値を返したらlog_errorへ移る。 end def log_error! # エラーハンドリングの処理。前段の処理でトラックが左側に移ったら実行される。 end def process_piyo! # 処理。前段の処理でトラックが左側に移っていなければ実行される。 end end
ビジネスロジックを処理のまとまりごとに分け、それぞれメソッド(上の例で言うとprocess_hoge!
とかlog_error!
とか)として定義します。
※公式(http://trailblazer.to/gems/operation/2.0/index.html#flow-control)より
メソッド化した各処理は左右2トラックのフロー(パイプと呼ぶらしい)に分かれ、正常系では右側のトラックを上から実行していき、異常系に遷移したら左側のトラックへ移ります。定義する際に step
, success
, failure
といった3つのAPIを使い分けることでどちらのトラックに配置するかを指定し、意図した順序で呼び出すことが可能です。
- step: 処理を右側のトラックに置く。異常値を返す処理が実行された時点で、パイプが左側のトラックへと移る。
- success: 処理を右側のトラックに置く。処理の返却値は考慮しない。
- failure: 処理を左側のトラックに置く。エラーハンドリングが目的。処理の返却値は考慮しない。
ネストが減ってフラットに処理が並ぶので流れを追いやすいし、正常系・異常系に分けて考えられるので分かりよいです。
Reformの使い方をじっくり
さて、この記事の本題へ。
特徴
Reformは先に書いたとおりバリデーション用のフォームオブジェクトを提供します。
- フレームワークに依存せず、Rails, Sinatra, Hanamiなど多くのプロジェクトで使える
- データベースは意識しないので、どんなORMと一緒でも使える
- データベースアクセスはせず、モデルのプロパティの書き込み・読み込みのみ行う
- モデルをフォームオブジェクトにマッピングすることが出来る
といった特徴がありますが、このあとの使い方を見てしまった方が理解しやすいはずです。
使い方
なお、ここからはビールが当たるキャンペーンの応募フォームを想定して話を進めます。画面の構成要素はこんな感じ。
- 名前入力用テキストフィールド
- 住所入力用テキストフィールド
- あなたは20歳以上ですか?確認用チェックボックス
※イメージ
定義
ではコードと一緒に使い方を見ていきます。
Reform::Form
を用いてクラスを定義するところから。フィールド定義はproperty
, collection
というキーワードで行い、バリデーションもこのクラスで指定します。
class ApplyBeerForm < Reform::Form # フィールド定義 property :name property :address property :over_nineteen #ActiveModel::Validationを用いたバリデーション validates :name, presence: true, length: { maximum: 20 } validates :address, presence: true, length: { maximum: 100 } validates :over_nineteen, acceptance: true end
バリデーションの定義はActiveModelの他にdry-validationも用いることができるようです。というかActiveModelは非推奨となっている模様ですね・・・(詳しくは: installation)。
なお、オペレーションの中ならcontract
を定義してやるとReform::Form
インスタンスが生成されます(詳しくは: validation)。
contract do property :name property :address property :over_nineteen validates :name, presence: true, length: { maximum: 20 } validates :address, presence: true, length: { maximum: 100 } validates :over_nineteen, acceptance: true end
Reform
はフォームとモデルを分離する仕組みを取り入れている(詳しくは後述)ので、両者を別物として扱うのが比較的容易です。そのため、例えば「フォームには存在するがモデルには不要な値」なんかも自然に定義出来て便利です。この例だと、20歳以上かのチェックがそれに該当しますね。
インスタンス生成
コントローラーかオペレーションでインスタンスを作ります。
まず、Applicant
(応募者)インスタンスを新しく作ってフォームインスタンスに渡すパターン。
@form = ApplyBeerForm.new(Applicant.new) #モデルのインスタンスを生成して渡す
続いて、作成済みApplicant
を渡すパターン。渡したインスタンスは編集対象となります。このとき、Reformが既存のApplicant
インスタンスに1度だけアクセスし、値を読み込んでくれます。
@form = ApplyBeerForm.new(Applicant.find(1)) #findしたモデルのインスタンスを渡す
バリデーション
#form_for
とかを使ってフォームインスタンスをレンダリングしたのち、validate
メソッドを呼び出します。バリデーションの対象はフォームオブジェクトのフィールドとして定義した値のみで、それ以外が渡された場合は無視されます。
if @form.validate(params[:applicant]) @form.save #後述 else #エラーハンドリングする end
バリデーションの結果、問題なかった場合はフォームに値が反映されます。一方、バリデーションエラーとなったら、errors
がエラーメッセージを返します。
重要なのは、値が有効で無事フォームの値が更新されたとしても、モデル側(ApplicantModel
)にはまだ変更が入らないことです。
モデルに反映・永続化
インプットをモデルにも反映するには、#save
か#sync
を呼び出します。これにより、Reformがモデルのsetterを使って値を書き換えにかかります。
@form.save #モデルに反映し、永続化する
@form.sync #モデルへの反映のみ行う
バリデーションが終わり、明示的にメソッドをコールするまではモデルの更新が行われないというわけです。フォームとモデルが、意味的にも実際の挙動としても綺麗に分かれてくれていることがよく分かりましたね。
順番をおさらい
Reformの使い方を追ってきましたが、流れをまとめるとこんな感じです。
- 定義
- インスタンス生成
- バリデーション
- モデルに反映・永続化
この手順を踏むことについて、Trailblazerの作者は「やることが多くて面倒だと思うかもしれないけどシンプルなんだよ」みたいな予防線を張ってますが、自分は割とすんなり理解・納得できました。
ちなみに、序盤でフォームの扱いに悩んだことがあると書きましたが、最近フォームを扱う画面を作る際は
- フォーム用モデル(
Reform::Form
ではなく、form以外のモデルと同様に定義している)をつくって、そのクラス内でバリデーションする - オペレーションにてバリデーション結果をチェック(し、エラーハンドリング)する
- バリデーションにひっかからなければ右側のトラックで次のステップへ進む
- ひっかかれば左側のトラックへ移り、エラーメッセージをコントローラーへ返す
こんな感じにしていて、これはこれで割といい感じにまとまりつつある気はしています。ただ、Trailblazerだけで教科書通りやるとこうなるんだなーという学びは面白かったし、フォームもモデルも複雑な画面で使うとどうなるのかしらという思いがあるので、業務でもちょっと試してみたいです。
Trailblazer、FOLIOでは主にAPI呼び出しに関連する部分から徐々に取り入れています。そういった部分的な導入により既存コードのリファクタリングをしていく方針を作者も良しとしており、本でも推奨されています。それもあってRails wayとの共存がしやすい作りになっており、導入しやすいのもメリットかなぁと思います。
機能はまだまだたくさんあるし、また何か困ったことがあったらちょっとずつ試してみたいなーと思います。自分が担当しているシステムはドメイン知識もたくさん要求されるし複雑な部分もあるので、せめてアーキテクチャは工夫してメンテしやすさを追求していきたいものです💪