tobb422のブログ

スタートアップエンジニアの奔走

良いチームの正体

はじめに

完全に迷走して、自分でも調子乗ったタイトルつけたなって思うので、許してください。

スタートアップで開発をしているエンジニアです。
「良いチームってなんだ?」という議題について考えることが多く、
実務を通して得た学びや、書籍を通じて得た視点を
言語化する練習も兼ねて、つらつらと書いていきます。

目的 → 結果へのシフト

1人で開発をしていたところから、2, 3人 と人数がふえてい増えていく中で
チームに対して考え方が変わってきました。

チームビルディングを始めたとき

  • 良いチームってどうやったらつくれるか?
  • カッコいい開発チームを作りたい

上記のようなことを思い、
「理想のチーム」について考え、取り組む
というサイクルを回していました。
これ自体見当違いだ!と思っているわけではないのですが、私自身の考えとして
「良いチームを作ることが目的」ということに非常に違和感を持つようになりました。

いまでも「カッコいい開発チームを作りたい」という漠然とした理想は持っている一方で、
こうした良いチームというものは、あくまで自分達が取り組んだ結果かもしれないと考えています。
私の中でこの変化は非常に大きいものでした。

いまチームビルディングに対して、わたしが考えているのは

  • 事業をスケールさせる方法
  • 開発速度を上げるために必要なこと
  • メンバーが自律的に動けるきっかけ

といった具合に、いわゆる「仕組みづくり」です。

実際これは程度の問題で
「良いチームとは?」を考えて、仕組みづくりにたどり着ける方も多くいると思います。
わたしは、
「チーム・事業にとって、良い仕組みを作ること」を目的にするほうがしっくり来たという話です。

よく「良いチームには、良い文化がある」という話を目にしますが、
わたしは、「良い文化が、良いチームを作る」という発想のほうが好きで、
実際にチームビルディングをしていく中で、後者のほうがしっくりきています。

ここからは、「良い文化が良いチームを作る」という前提で話を進めます。

良いチームは、成長で作られる

私の好きな言葉に
「偉大な(高機能な)チームは成長によって作られる。雇うことで作られるものではない」
という言葉があるのですが、最近この言葉がより一層好きになってきました。

事業が上手くいっていない、またはチームとして上手く成果を出せていないときに
チームとしての真価が問われているなと思います。
具体的には、あえて極端な言い回しをしますが、
今いる人材では決して上手く回らないと決めつけ
「スーパースターの獲得にかける」チームは、個人的にあまり好きではありません。
スーパースター級な人材が多いことは、良いチームの必要条件ではないはずです。
もし必要条件であれば、私は良いチームに一生属せませんww つらすぎます!

というのも、
優秀な人材を確保することはもちろん必要なことで、それに越したことはないですが、
その場その場のメンバーで成果を出せる(結果、良いチームを作れる)ことこそ、
再現性も高く、非常に価値のあることだと考えています。

どんなにスーパースター級な人材が集まったとしても、チームとして課題は生まれます。
「良い文化が良いチームを作る」という前提に立ち返ると
チームで課題が出た際に必要なのは、文化(仕組み)を見直すです。
こうした思考が持てると、よく会社言っていることなのですが
「個人 vs 個人」の関係ではなく「チーム vs 課題」の関係を作りやすいです。

課題が出てきた際に、

  • ○○ が、パフォーマンスを出せてない
  • ○○ は、いつもサボっているの

みたいな「個人 vs 個人」の構図に持っていくと(例で出したのは少し極端すぎましたが…)
一向に話が進みません、、そして心理的安全性も担保されないです。

事業を前に進めるためには、課題を一つ一つ解決していく必要があり
その課題を解決していくには、「チーム vs 課題」の構図をいつも保てるような仕組みを考える必要があると思っています。

「チーム vs 課題」として、課題を一つ一つ解決していくことは、
良い文化が生まれやすく、結果良いチームにつながると思うので、非常にいいなと考えています。

良い文化は、実験から生まれる

(そろそろ、着地見失ってきました。。。)

良い仕組みの話をすると、
「じゃあ、良い仕組みってたとえば何?」的な議論になるのですが、
私は、チーム・事業の状況や最終的なゴール・ビジョンによって変わるものだと思ってます。

基準として、

  • 事業をより前に進めることができる
  • 仕事がしやすい(働きやすい)
  • 個々人が 〜 がしたいという想いが持つことができる

みたいなものはあるかなと考えています。

結局、みんなで考えて、本当にこの仕組みはやりやすいのか(事業が回るのか)を試していくことでしか
良い文化(仕組み)は作れないのだと思っています。
ここを一種の実験だと楽しめる人は、素敵だな〜と感じる今日このごろです。

課題に対して、仕組みや環境を整えることで解決しようと取り組み
カイゼンを回すことで、良い文化は生まれ、結果、良いチームが作られる(はず)

まとめ

(完全に着地点見失って辛くなってきたので、ここで無理やり終わらせます。)

最近チームビルディングで考えていることは

  • 良い文化が、良いチームを作る
  • 良いチームは、成長から生まれる
  • 良い文化は、実験から生まれる

でした。

<読書メモ> React Design Patterns and Best Practices 2nd Edition

はじめに

先日、React + TypeScript を使った新規プロジェクトを担当することになりました。
TypeScript は普段から使用していることもあり、
まあ大丈夫かなと思っていたのですが、React が約2年ぶり?くらいだったため、
思い出すことを目的に React Design Patterns and Best Practices という本を読みました。
本投稿は、その読書メモです。
※ 読書メモなので、私が読むことを想定して書き殴ります。
ターゲットとしている層は、「既にReactでアプリケーションを書いている人がステップアップするという位置づけ」らしいです。

↑ あとで気がついたが、なぜかこの書籍だけはてなブログの「Amazon商品紹介」で選択しても表示できない...
https://www.amazon.co.jp/gp/product/1789530172

雑感としては、知らなかった概念や機能を知るきっかけになったが、
プロダクトに導入するには、この書籍だけでは理解を深めるのが難しかったです。
(英語力の問題では....?w)

(私が)初めて知った & 使えそうと思った概念?機能? をまとめてみる

React Hooks

今回の新規プロジェクトで既に使ってみています。
後述する React.memo とそうなんですが、関数で定義していくことに優しい世の中になっているように感じます。
結果、気がついたらほぼ全てのコンポーネントfunction で定義してました。
正直、自分の英語力と技術力ではよくわからなかったので、
以下の記事とドキュメントを利用して、キャッチアップしました。
(まだ、 useStateuseEffect くらいしか使えていないのですが....)
qiita.com ja.reactjs.org

React Context

コンポーネント間で渡すデータを props でやり取りするのではなく
コンポーネントツリー内で共通で利用できるデータといったイメージですかね...?
手元で動かしてみて、こんな感じかと理解した程度で、プロダクト内に取り入れられていないです...
ja.reactjs.org

Function As Child

HoC と比較して語られているケースを良く見ます。
要は、childrenコンポーネントを渡すのではなくて、関数を渡すということです。
最初この章を読んだときは、そんなことができるんだ〜と思いましたw
コンポーネントで切り替わっていく state 等で動的に子コンポーネントを変化させたいときに有効なのでしょうか?
テストで試した程度で、まだプロダクト内では使えていないのですが...
qiita.com

react-motion で実際に使用されているソースコードを見つけたので、
そちらを見るとなんとなく理解が深まるかもしれません。
該当のコンポーネント

Pure Component → React.memo

qiita.com PureComponent は、知っていたのですが
その関数版というか、 React.memo が公開関数になっており、
関数で定義したコンポーネントをラップして、返してくれるようです。
recomposepure みたいなものですね
ただ、なんでも React.memo を使えば正解というわけではなさそうです。用法用量お守りください。
qiita.com

React.Fragment

ja.reactjs.org ドキュメントに書いてあると通りなのですが、無駄なノードを追加しなくて済む書き方と認識しておくので問題なさそうです。

まとめ

非常に雑ですが、読書メモなのでこれで良しとします。
序盤でも触れましたが、普段開発してて知らない概念や機能に触れることができたのはよかったかな〜
と思っています。 ( → ドキュメントに書いてるけど...)

Go + Headless Chrome で HTML から PDF を生成する基盤を作成した

久々にブログを更新!!
(サボりがちなので、心機一転ここからまた継続して更新できるように頑張ります....)

はじめに

one visa というプロダクトの開発を行っており、
その中で、コア機能の一つとなる PDF 生成を Go + Headless Chrome で作成するという取り組みをしたので
その取り組みについて紹介いたします!

どうやって実現するか

  • 生成したい書類を Webページとして作成する(HTML + CSS
  • 作成した Webページをレンダリングする Webサーバーを立てる
    • → (今回は、Go縛りで Echo を使って Webサーバーを立てました!)
  • 該当ページに headless chrome でアクセスする
  • 表示したページを PDF として保存する

この一連の流れを作成します! 図で表すとこんな感じです。

f:id:tobb422:20190716010611p:plain
流れのイメージ

また、今回は異なるページを PDF として生成し、最後に 一枚の PDF として合体させる必要があったので、
ゴルーチンを利用して、上記で説明したプロセスを並列で行います!

利用するツール

今回は、Chrome DevTools Protocol を利用して、Chrome を操作します。
この Chrome DevTools Protocol を go で簡単に操作できるライブラリである chromedp を利用します!
また PDF の合成には、 pdftk という PDF ファイルを編集するコマンドラインツールを利用しました!

実装

上記を実現するためのサンプルです。
echo を使った Webページのレンダリングは省略しています。
また、私は Docker コンテナに必要なツールをインストールして稼働させました!
もちろん、必要なツールが揃っていれば、ローカルで直接稼働させることもできるはずです。
(必要なツール chromedriver chrome pdftk

Docker上で、Headless Chrome を動かすということ自体はよく記事になっているので、省略します。
qiita.com

また、 pdftkapt-get install で Docker に組み込めるのでこちらも省略します。

package main

import ...

func main() {
  // 生成したいPDFに該当するWebページのパスを持った構造体をマップでひとまとめにする
  // → 後述します
  builders := []builder.PDFBuilder{
    &Sample{ Path: "sample" }
  }

  // 各WebページをPDFとして保存して
  fileNames, err := createPDF(); if err != nil {
    return
  }

  // 生成されたPDFを1つのPDFへ合体します
  mergePDF(fileNames)

  // 残ってしまった不要なファイルを削除する
  deleteTmpFile(fileNames)
}

func createPDF(builders []builder.PDFBuilder) (fileNames []string, err error){

  var wg sync.WaitGroup
  wg.Add(len(builders))

  // ゴルーチンを利用して、各PDF生成を並列で処理します
  for _, builder := range builders {
    go func(builder builder.PDFFactoryServicer) {
      defer wg.Done()
      builder.Exec()  // PDF生成
    }(v)
  }

  wg.Wait()

  // 全てのPDFが生成されたことを確認しています
  for _, builder := range builders {
    _, err := os.Stat(builder.Name()); if err != nil {
      return nil, err
    }
    fileNames = append(fileNames, builder.Name())
  }

  return fileNames, nil
}

func mergePDF(fileNames []string) (mergePDFName string, err error) {
  mergePDFName = "merge.pdf"

  mergeCommand := append(fileNames, "cat", "output", mergePDFName)
  // exec.Command を利用して pdftk のコマンドを実行しています
  err = exec.Command("pdftk", mergeCommand...).Run(); if err != nil {
    return "", err
  }

  return mergeFileName, nil
}

// 各ページごとに生成したPDFを削除
func deleteTmpFile(fileNames []string) error {
  for _, v := range fileNames {
    if err = os.Remove(v); err != nil {
      return err
    }
  }
  return nil
}
// WEBページへアクセスし、PDFとして保存するロジックをまとめる
package print

func Screenshot(path string, output string) error {
  // chromedb を実行する
  ctx, cancel := chromedp.NewContext(context.Background())
  defer cancel()

  // chrome で実行したいタスクを走らせる
  var buf []byte
  err := chromedp.Run(ctx, createTask("URL"+ path, `div`, &buf)); if err != nil {
    return err
  }

  // 指定した名前でファイルを作成する
  file, err := os.Create(output); if err != nil {
    return err
  }
  defer file.Close()

  writer := bufio.NewWriter(file)
  writer.Write(buf)
  writer.Flush()
}

func createTask(url string, sel string, res *[]byte) chromedp.Tasks {
  return chromedp.Tasks{
    chromedp.Navigate(url), // URL へアクセスして
    chromedp.WaitVisible(sel, chromedp.ByQuery), // 表示されるのを待って
    printToPDF(res), // pdf として保存する
  }
}

// chromeでPDFとして保存させる処理
func printToPDF(pdfbuf *[]byte) chromedp.Action {
  return chromedp.ActionFunc(func(ctx context.Context) error {
    buf, err := page.PrintToPDF().WithPrintBackground(true).Do(ctx)
    if err != nil {
      return err
    }
    *pdfbuf = buf
    return nil
  })
}
// PDF 生成を担当する構造体
package builder

// WebページからPDFを生成機能を持ったインターフェース
type PDFBuilder interface {
  Exec()
  Name() string
}

// 以下のように、生成したい Path を持った構造体を作る
type Sample struct {
  Path string
}

func (service *Sample) Exec() {
  print.Screenshot(service.Path, service.Name())
}

func (service *Sample) Name() string {
  return service.Path + ".pdf"
}

完成イメージ

完成形は、以下のような処理の流れになります!

f:id:tobb422:20190716021116p:plain
完成イメージ

まとめ

PDF 生成を Webページから行う方法についてまとめてみました
今回は、go で実装しましたが、 chrome 操作を簡単に行うことができれば言語は問わないと思います。
最後、PDF に変換されるため、レイアウトをうまく調整することが難しかったりもしたのですが、
PaperCSS といったツールを使えば、その辺りもうまくできそうです。
(※ 私はゴリッと生のCSSでコーディングしたので、テキトーなことを言っています)
HTML + CSS の構成なので、デザインの変更は簡単に行なえますし、
動的なデータもWebサーバーを利用して簡単に生成可能です!
(今回、例では出していませんが実際はクエリを利用して、動的なデータの表示や生成するページを切り替えるといったことも可能です!)
ゴルーチンを利用すれば、一定の速度を保って簡単にスケールできる環境も作れると思うので
大量のPDF生成にお困りの方にはおすすめです!(← そもそもここの需要が少なそうw)

チームの開発速度をあげる

はじめに

one visa というスタートアップ企業にてエンジニアをしています。
開発チームを発足するということになり、最初はわたし1人の開発チーム? だったところから
現在は、5人のエンジニアで開発を進めるまでにチームが大きくなってきました。
β版プロダクトから正式版リリースに向け、チーム一丸となって開発を進めており、
より一層スピード感を持って開発できるよう日々試行錯誤しています。
今回は、「スピードをあげるために何が必要かと」いままで考えたことをまとめておこうと思います。

チームの開発速度を上げる

チームの開発速度を上げるためには、以下2点を実現する必要があると考えました。

  • 同時に実装できる機能を増やす
  • それぞれのリードタイム(企画 ~ 実装, リリース)を短くする

以降、上記2つを実現する方法を考えます。

同時に実装できる機能を増やす

現在、開発チームでは、ストーリー毎に開発を進めており
(たとえば、ユーザーがサインアップできるといったイメージ)
要は、同時にこなすこのストーリーの数を増やせば良いと考えています。

  • 新たに開発者を増やす
  • 既存の開発者が分身する

これまでの経験から、同一人物が同時に複数のストーリーをこなすのはあまり現実的ではないと考えており
並行するストーリーを増やすためには、新たに開発者を増やすことが必要だと考えています。
(絶賛、採用中ですwよろしくおねがいします!)
ただ開発者を増やせば良いというわけではなく、
プロジェクトを任せて要件定義〜実装, リリースと一貫して担当していただける方を採用しなければなりません。
逆に言うと、ストーリー数を増やすために採用するので、
人物像(スキルセット)は明確になり、ターゲットは絞りやすいです。
採用して、同時進行できるストーリー数が増やせなければ意味がないので、採用をゴールにしないよう心がけています。

また、新たにエンジニアがジョインしてから、自走できるまでに1年を費やすようでは、
結局開発速度をあげることにはつながっていないので、
自走できるようになるまでのコストを低くしていくことも必要だと考えています。
たとえば、

  • チーム思想が明確にあり、意思決定の指針となっている
  • ドキュメントが充実している

といったことが満たされていれば、自走までのキャッチアップもしやすいと思います。

それぞれのリードタイム(企画 ~ 実装, リリース)を短くする

1ストーリー辺りにかかる時間が短くなれば、プロジェクトは全体的に前倒しになるため
リードタイムを短くできるよう心がけています。
もちろん、担当者のレベルに依存してしまう場合もありますが、
仕組み化を進めて、あらゆる面でチューニング可能だと考えています。
たとえば、以下はチューニング可能な項目です。

  • 変更・拡張しやすいアプリケーション設計になっている
  • ドキュメントが書かれており、属人化していない
  • タスクのゴールが明文化されている
  • CI/CDが自動化されている
  • チームの思想やバリューが明文化されていて、意思決定時の指針がある
  • MTGを集約して、開発にまとまった時間を確保できるようにする

上記のようなことが実現できていると、要件定義, 実装, もちろん実際のデプロイ時間など
あらゆる工程を少しずつ短くでき、トータルでかかる時間は大幅に短縮されると考えています。
漠然と開発速度あげろといわれると施策が思いつかなかったですが、
各工程を割り出して、それぞれのリードタイムを短くするためには?
と考えることで、より具体的な施策へ繋げらることができたと思います。
(今後、具体的にどういったことに取り組んでいるかもブログで紹介できるといいなぁとおもっています。)

まとめ

チームの開発速度を上げるためには、

  • 同時に実装できる機能を増やす
  • それぞれのリードタイム(企画 ~ 実装, リリース)を短くする

ことが必要ではないかと考えています。 そこから下位分析をしていくと、

  • ドキュメントをしっかり書く
  • チームのバリューを明確にする

といった割とよく言われているプラクティスにつながりました。

開発チームとしては、クライアントに継続的に価値を提供し続けられる開発体制を作るべきであり、
その際に、開発速度は非常に重要な指標ではないかと考えています。
ここは、根性論で乗り切ることは無理で、リソースが限られているスタートアップだからこそ よりハックしていかなければいけないのではないかなぁ〜と日々思っている今日このごろでした。

(最近ブログ更新をサボっていて、久々に書くとうまく文章かけない。)

SPAで利用するAPI設計を考える...

はじめに

ここ 1, 2年は、SPA + API という構成 Web アプリケーションを開発することが多く、
その度に、毎回悩み・後悔しているのですが...
書籍や Web 上に公開されている記事を読んだり、チームで API を設計・開発していく中で
少しずつではありますが、考え方がまとまってきたので、
未来の自分のためにも一度整理しておきます。
※ こちらのメモでは、チームで API を開発することを想定しています。

先人に学ぶ

Web API: The Good Parts では、
設計の美しい WebAPI について以下のような要素を挙げていました。

  • 使いやすい
  • 変更しやすい
  • 頑強である
  • 恥ずかしくない

また、APIデザインの極意 Java/NetBeansアーキテクト探究ノート では、
APIの品質検査方法として、以下を挙げています。
[補足]
こちらの書籍は、公開APIを前提にしているケース(LSUDs)が多く、
今回議題にあげているような、クローズドな Web API (SSKDs)を想定しているわけではないのですが、
いずれにせよ、参考にできることは非常に多いと、私は考えています。

  • 理解しやすさ
  • 一貫性
  • 発見できること
  • 局所性

(※ 詳しくは、書籍をご覧ください。)

上記の項目や、他の Web上で公開されている記事, チーム開発を通して、
現在、私の中では一貫性のある API がホットワードになっています。
一貫性が存在することで、特に理解しやすさ, 使いやすさは向上するのではないか
と考えおり、チーム開発において、ハッピーになれる人が増えると思っています。

一貫性があるAPIを開発するために...

一貫性を確保することは、非常に難易度が高いです、、
そして、チームの人数(関係者)が増えれば増えるほど、運用が難しいように思えます。
チーム開発をしていく中で、一貫性がある API を開発するために心がけていることをメモしておきます。

  • なるべく Web の標準に従う
  • クライアントを意識したリソースを定義する
  • ドキュメントを書く(利用者向け & 開発者向け)

詳しく追っていきます。

なるべく Web の標準に従う

結論からいうと、Web 標準というよりも、REST に従うことを意識するのが良いかなと思っています。

  • URL で、スコープ(どんなリソースか)を定義し
  • HTTP メソッドで、アクション(何をするか)を定義し
  • 統一された リソース を返す

上記に従う形で、設計をするのが良いのではないかと考えています。

クライアントを意識したリソースを定義する

上記の RESTful な API 設計にも重なる項目なのですが、
「統一されたリソース」は、必ずしも、バックエンドが知っている「モデル(= エンティティ)」と同じではないと考えています。
ここが、SPA で利用する API 設計らしさかなと思うのですが、(よく BFF として語られているようにも思います。)
今回想定しているような API 設計では、SPA を意識したもので良くて、
SPA で扱いやすい単位に、各エンティティを集約することが重要な気がします。
「1つのリソース = 1つのモデル」ではない
ということです。
私は、この集約する層をドメイン駆動設計にちなんで、Repository 層と呼ぶことが多いです。

f:id:tobb422:20190514092034p:plain
Repository層

あらゆるエンティティをもう少し SPA で利用しやすい単位にまとめて返すことが良いと考えています。
ただし、各ページに依存してしまうのは良くないので、難しいところです。
リソースを定義するために、
フロントエンドチームと議論しながら、そのアプリケーションで扱うドメインの定義を行っていく必要があると思います。

ドキュメントを書く(利用者向け & 開発者向け)

利用者向けのドキュメントでは、
主に、公開しているエンドポイント、そして定義されているリソース
を書いていくようにしています。
最近、Nest.js という FW を使って、個人アプリを作ることが多いのですが、
その場合は、Swagger のライブラリを導入することで自動でドキュメントを出力してくれます。
色んな FW で同じような仕組みを取り入れていると思うので、そちらを利用するのが便利だと思います。

開発者向けのドキュメントでは、
命名規則や、アンチパターンなどをまとめておくようにしています。
リソースの定義も書いておくと良いかもしれません。
一貫性を確保には、メンバー間での調整がかなり必要で
調整をなくすためにも、明文化できるものは全て記載しておくくらいでも良いかなと思っています。
また、こちらはドキュメントというよりも設計全般の話ですが、
開発者は、全てを知らなくても良いコーディング方法を見つけられる(選択的無知)
を意識して置くことも必須です。

まとめ

SPA で利用する API 設計の勘所として、一貫性がある API をテーマにしました。
そして、一貫性がある API を運用する要素として、以下の要素挙げました。

  • なるべく Web 標準に従う(RESTful な API
  • クライアントを意識したリソースを定義する
  • ドキュメントを書く(利用者向け & 開発者向け)

もちろん、これが正解というわけではなく、1つの考え方として思ってもらえると幸いです。

参考にした書籍・Webページ

[書籍]
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
Web API: The Good Parts
APIデザインの極意 Java/NetBeansアーキテクト探究ノート
エリック・エヴァンスのドメイン駆動設計

[Webページ]
翻訳: WebAPI 設計のベストプラクティス
ぎんざRuby会議01にて、「マイクロサービス指向 Rails API 開発ガイド」という発表をしました

スタートアップで、チームビルディングを実施して1年たった

はじめに

以前、
1人目のエンジニアとして、スタートアップに入社して1年経過した
というエントリーを書きました。今回は、その続編といいますか、
この5月で、開発チームが私だけでやっていた状態からチーム開発に変わって、約1年が経過するので
この1年間で行ってきた one visa 開発チームのチームビルディングについて書いてみたいと思います。

タイムライン

まず、前提知識の共有のため
どんな形でチームが変化したかを簡単に説明します。

  • 2018年3月
    • 私がエンジニアとしてジョイン, 開発の内製化を進める
  • 2018年5月
    • 2人目となるフロントエンドエンジニアジョイン, チーム開発へとシフト
    • フロント1名, バックエンド1名の体制へ
  • 2018年10月
    • 3人目となるバックエンドエンジニアジョイン
    • フロント1名, バックエンド1名, 雑用(私)1名の体制へ
  • 2018年12月
    • 4人目となるバックエンドエンジニアジョイン
    • フロント1名, バックエンド2名, 雑用(私)1名の体制へ
  • 2019年4月
    • 5人目となるフロントエンドエンジニアジョイン
    • フロント2名, バックエンド2名, 雑用(私)1名の体制へ

と、こんな具合にチームは拡大しています。
余談ですが、現在も開発の合間に合間に採用活動はしており、
開発チームのさらなる拡大を図っています!ご興味お持ちいただける方はぜひw

以下は、全てチームビルディングとして、取り組んでいる具体的な施策の紹介です。

恒常的に行っているもの

以下の取り組みは、恒常的に行っているものです。
チームとして活動する上で、必要不可欠な取り組みだと考えています。

スプリント計画

チーム開発がスタートして一番最初に行った施策が、スプリントの実施でした。
2週間を1スプリントとして実施しており、チーム一丸となってプロジェクトを前に進めることを前提に
見積もり(プランニングポーカー)の実施で短中期的な計画の精度をあげることや
振り返りの実施でチームとしての成熟度を高めることを目的としていました。

また、当時のスプリントは、デザイナー, フロントエンドエンジニア, バックエンドエンジニアと
職種を超えたチームでの実施だったため、
振り返りの際にでてくる視点も様々なものがあり、大変興味深いものでした。

現在のチームでもスプリントを実施しており
見積もりと振り返りを定期的に行い、チームとして成熟度を高めていけるよう心がけています。
この振り返りで出てきた改善点や称賛すべき項目は、いまでは後述する開発思想の1つになっていたりと
one visa のチームらしさを作る意味で大きな役割を果たしていると思います。

プロダクトバックログ

こちらもチームメンバーが増えても実施し続けている施策の1つです。

スプリント計画を行うことで、2週間ないしは、1ヶ月先のプランニングはできるようになってきました。
しかし、長期的な計画に対しては、不確かなものが多く、3ヶ月先の着地に相当なブレがある状況が続いていました。
(いまでも、完全に解決できているわけではないのですが...)

そこで、スプリントでは見えてこなかった、もう少し長期的な計画として
プロダクトバックログを取り入れることにしました。
大きな企画単位で見積もりを行い, 3ヶ月, 6ヶ月先に自分たちがどれくらいできそうかを見積もることができるようになってきました。

スタートアップということもあり、半年後の状況は誰も読めない...という状況なのですが、
だからこそ、「どれだけ不確実性をなくせるか」が大切だと開発チームでは考えており
いまの開発チームは、◯◯くらいの大きさの企画であれば△ヶ月で終えられると自分たちで認識を持ち、 ボードメンバー等、他のチームに説明ができるように心がけています。

デイリースクラム

毎日、夕方にチームメンバーで進捗共有を行っています。
目的としては、チームの進捗確認で

  • チームがスプリントで立てた計画を無事実施できているかの確認
  • タスクの優先順位の確認

を行っています。
これらの確認のために、カンバンを導入しており
チームとして抱えているタスクの可視化ができるようにしています。

それ以外にも、困っていることや相談ごとの共有を行う場にもなっており、
個人で実装や設計で悩んでいることがあればチームで解決していけるように心がけています。

また、弊社ではリモートワークも取り入れており、普段は何をやっているのか全く見えない状況だったりもするのですが、
このデイリースクラムのおかげで常にチームの状況を把握できるようになっています。
チームメンバーが少なった頃は、デイリースクラムを行わなくても
他のメンバーが何をやっているのか、何に困っているのかを把握することが容易だったので
デイリースクラムを行っていない時期もあったのですが、人数が3人, 4人と増えてきたタイミングで復活しました。

必要に応じて行っているもの

以下の取り組みは、状況に応じて実施しているものです。
ほとんどが、恒常的に行う施策を機能しつづけさせるための点検・すり合わせの責務を担っています。

オンボーディング

新しくメンバーが増えたタイミングで行っています。
担当者と内容を決めて、個人にあったやり方で行うようにしているのですが、
共通して行っているオンボーディング施策として、キックオフMTGがあります。

いまのところ、開発チームメンバー全員参加で行っている施策で
以下のようなアジェンダで実施しています。

  • 得意分野, 好きな技術, 興味がある分野
  • チーム開発で大切にしたいと思っていること
  • 何で貢献したいと考えているか
  • (メンバーが)期待していること

どんなことが好きで、何を大切に考えているのか, どんなことでチームに貢献したいと考えているのかを
チーム間で共有することで、タスクの振り方などにちょっとした差が出てくると思っています。
そのため、実際の業務に入る前に、メンバーについて知ってもらう, 教えてもらう場を作ることを意識しています。
また、最後の期待していることをしっかりとメンバー間で伝え合うことで、期待値のすり合わせも行っています。

全ては、心理的安全性を担保するためであり、 こうした価値観の共有を行うことが非常に重要だと考えています。

カンバンの見直し

タスク状況の可視化を目的として、カンバンを導入していますが、
人数が増えてくると、カンバンが上手く機能しなくなってきます。
これは、カンバンにかかわらず、スプリントの方法やプロダクトバックログの方法にもいえることなのですが
絶えず変化するチームの中で、常に完璧な方法は存在しないです。 そのため、定期的に時間を取り、それぞれの取り組みが
現在のやり方で果たそうとしている目的を達成できるかを点検するようにしています。

カンバンでは、人数が増えることで Waiting(待ち)にタスクが溜まってしまう事象が多くなりました。
そのため、現在では、デイリースクラムで Waiting にあるタスクについて全員でネクストアクションを確認するようにしています。

当時は、上手く機能していたとしても、メンバーが増える・プロジェクトが変わるなどして
常に機能し続けるものは存在しないと考えています。
チームとしても絶えず機能し続けるためには、
日頃の取り組むを点検する場を設けることは非常に大切だと考えています。

ドキュメント作成

ドキュメントに関わらず、議事録なども重要なのですが、
チームで決めたルールや原則は、基本的には全てドキュメントに残すことを心がけています。
スタートアップであるため、スピード感を持って開発することがが非常に重要だと考えています。
それと同時に、持続可能な開発を行っていくこともまた、非常に重要だと考えています。
そのため、開発チームとしては、1時間手が止まってしまうとしても、
決めたこと等は、必ずドキュメントに残し、明文化するように心がけています。
そのドキュメントは全メンバーがいつでもアクセスできるようにしており、
メンバー間で暗黙知が増えないようにしています。

誰が入って、誰が抜けたとしても、「開発チームとして機能し続ける」仕組みづくりは、非常に重要です。
過去に決めたルールなどは、定期的に点検するコストもあるのですが、
これが一番スピード感を持って、開発し続けられる方法だと考えています。

単発で実施した大きな取り組み

日頃行っている取り組みの指針となる指針となるより抽象的な概念について
チームですり合わせを行うことを目的に実施しているものです。
まだまだ回数をこなせていないので、ブラッシュアップの余地がある施策ではありますが、
これからも継続していきたいと考えています。

開発思想すり合わせ会

チームが4人になったタイミングで、開発思想すり合わせ会というものを行いました。
目的は、普段の開発で何を大切にすべきかについて目線を合わせることで
会社のバリューのような位置付けだと考えています。
(実際に、開発思想の中から会社のバリューとしてランクアップしたものもあります。)

詳しくは、弊社Wantedlyページにて記事が上がっているので、そちらをご覧ください。

www.wantedly.com

向き直り会

こちらは、大きなプロジェクトのリリースを終えたタイミングで実施しました。
目的としては、非連続的な成長に繋がるきっかけづくりで
チームの最終目標から逆算して、現在との差分を把握する場になっています。

こちらも詳しい記事が上がっているので、そちらをご覧ください。

www.wantedly.com

開発戦略目線合わせ会

一番最近に行った施策です。
事業戦略に沿った形で、1年先に開発チームとしてはどんな体制になっていなければならないか
そのために、いまやっておかなければならない取り組みは何かを把握する会として実施しました。

こちらは、私のブログにて、別途詳細に書いていきたいと思っています。
書きました → 【レポート】開発戦略目線合わせ会を実施した

まとめ

振り返ってみると、1年間でチーム開発といえども非常に変化があったなぁと感じます。 特に、施策に取り組むにあたっては、以下をしっかりと抑えておく必要があるなと学ぶことができました。

  • 目的のすり合わせ
  • 価値観のすり合わせ
  • 価値観の明文化, オープンな知識の蓄積
  • 仕組み(取り組み)自体の点検

その時々で、最もパフォーマンスを発揮できる仕組みを作ることが非常に重要であり、
個人的には取り組むべき面白い分野だと考えています。
これからも引き続き、チームとして正しく前に進み続けられるように
創意工夫を凝らして、より良い仕組み作りに努めていきたいと思っています。

最後に宣伝になりますが、
開発はもちろん、こうしたチームビルディング
開発チームがパフォーマンスを発揮し続けられる仕組みづくりについて
一緒に考えることに興味をお持ちいただける方がいらっしゃれば、ぜひお会いしましょう〜!
ご応募いただけると嬉しみです。

www.wantedly.com

【レポート】開発戦略目線合わせ会を実施した

はじめに

現在、one visa というスタートアップでエンジニアをしています。
現在エンジニア5名で日々開発に取り組んでいるのですが、
開発戦略目線合わせ会というものを実施したので、その備忘録を書いておきます。

会の目的と概要

開発戦略目線合わせ会ってなんやねん
って感じかと思うのでざっくり説明します。

目的

会社の事業計画を考慮した上で、
今後(今回は1年先まで)の開発体制は、どういった状態であるか把握する
また、この会を通して、技術選定や日々の取り組みの指針を決める

概要

以下のようなアジェンダで取り組みました。

  • 自分たちが開発しているプロダクトの特徴を整理
    • ex:SaaSで、市場規模××、....etc
  • 会社の事業戦略を理解する(1年後まで)
  • そのために、どんな開発体制が必要かを考える
  • 必要な開発体制を実現するために必要な項目を洗い出す
  • 現在との差分から直近で取り組むべき内容を決める

以下、具体的にどんな話をしたかを書き留めておきます。

どんな開発体制が必要か

one visa の事業や今後の方針まで書いていると
令和になりそうなので(いま平成31年4月30日)省略します。

事業戦略から落とし込んでいくと、
事業拡大に合わせてチーム(数)が拡大したとしても、
スピード感を持って開発し続けていくこと
が最も重要な要素だということがわかりました。

当たり前だろと思われるかもしれませんが、
自分たちが目指している戦略から落とし込んで導き出したものなので、
メンバー全員が納得感をもっていて、なぜこれが必要なのかを説明できる状態になっていると思います。

開発体制を決めたことも重要なのですが、
それ以上に、
メンバー全員が納得感を持って、なぜこの開発体制が必要なのかを理解している状態
になっていることが非常に価値が有ることだと思っています。

必要な開発を実現するためには?

スピード感を持って開発し続けられる状態とはどんな状態でしょうか?
もう一つの目的である「日々の取り組みの指針」を定義していくことで深ぼることにしました。

そこで、
LeanとDevOpsの科学[Accelerate] テクノロジーの戦略的活用が組織変革を加速する
という書籍を参考に考えることにしました。
この書籍は、ハイパフォーマンス組織を実現するためには?という軸で様々な企業を分析した本で、
いろんな指標から、ローパフォーマンス組織とハイパフォーマンス組織の差分を考えることができます。

開発チームとしては、
ハイパフォーマンス組織 ≒ スピード感を持って開発し続けられる開発体制として、
深ぼっていくことにしました。

書籍では、以下4つを組織のパフォーマンスを測る指標として考えています。

  • デリバリのリードタイム
  • デプロイの頻度
  • サービスの復旧所要時間 
  • 変更失敗率

そこで、私達の開発チームでも
デリバリのリードタイムを短く, オンデマンドにデプロイが可能な仕組みづくり
を行っていくことが重要と定義しました。

まとめると以下です。
スピード感を持って開発し続けていくこと
1年後、要は、事業の拡大に合わせて、開発チーム(数)が拡大したとしても達成するためには、
デリバリのリードタイムを短く, オンデマンドにデプロイが可能な仕組みづくり
が必要であると判断しました。

f:id:tobb422:20190430225824p:plain
イメージ図
(上にいくほど、リードタイムが短い & デプロイ数が多いことを示しています)

現在との差分から直近で取り組むべき内容を決める

スピード感を持って開発し続けられる状態
ボトムダウンして、↓↓↓
デリバリのリードタイムを短く, オンデマンドにデプロイが可能な仕組みづくり
を直近の目標としたわけですが、もう少し深掘りしたいと思います。
上記を達成するための指標は、以下の2点です。

  • デリバリのリードタイムを短くする
  • オンデマンドにデプロイが可能な体制作り

■ デリバリのリードタイムを短くする

  • 要件定義・設計のしやすさ
  • コミュニケーションの質
    • 適切な権限委譲
    • 文化の醸成・価値観の共有
  • 実装速度
    • 変更の加えやすさ
      • コードの質
      • 疎結合なアプリケーション設計
      • テストの自動化
    • 個々人のスキルアップ

■ オンデマンドにデプロイ可能な体制

  • 職種の分割されていないチーム構成
  • 疎結合かつ凝集度の高いアーキテクチャ設計
  • CIの整備
  • デプロイの自動化・簡略化
  • インフラ環境のスケーラビリティ
  • モニタリング(プロアクティブな通知)

初めに比べて、だいぶ何をすべきかが見えてきたように思います。

既に施策になっているものを明文化

  • デザイン・フロント・バックエンドと職種を超えたアジャイルの実施
  • 変更のしやすさ・CIを意識したテストの自動化・TDDの促進
  • インフラ環境のスケーラビリティを考慮したコンテナ化の促進

上記に加えて、1年間で行っていくテーマ

  • 文化の醸成・価値観の共有
  • 疎結合かつ凝集度の高いアーキテクチャ設計・アプリケーション設計
  • テストの自動化・CIの整備

特に意識したい具体的な施策

  • テスト方針の明確化・カバレッジ向上
  • 設計の議論やコードの品質アップを狙った、専門チームでの取り組みの活性化
  • 事業戦略を意識したアーキテクチャ設計
  • (ワークレビューやペアプロによる個人のレベルアップ)
  • (マイクロサービス化に伴うCI/CDの整備)

まとめ

結果やることは、

  • テスト書く
  • 設計を大切に

といった具合に、結構当たり前なことになりました。
現在の開発チームでも、これらは日頃から意識して行っていることです。
もちろん、詳しく
テスト方針(単体テストカバレッジ率を◯◯にするなど)や
アプリ設計にレイヤードアーキテクチャを取り入れよう!など
より詳細な話をこれからしていく必要があるのですが、
今回はそれ以上、
事業戦略から落とし込んで、日々やることにWhyをもたせることができたこと
一番の収穫だと考えています。
(それに加えて、ある程度注力すべき方針が見えたことも収穫です!)

以前、開発思想を決めたりと、
価値観のすり合わせは日頃から行っている開発チームだと思うのですが、
今回の会では、
それらの価値観や普段の業務(特にリファクタ系やテスト系)が事業に直結していると再認識できる会になったのではないかと考えています。