GitHub Actionsでワークフローから他のワークフローのpushイベントがトリガーされない問題の対応方法

GitHub Actions内でpushを実行しているのに、他のワークフローのpushイベントがトリガーされない事象が発生しました。いろいろ調べて対応できたので、メモ書き程度に記載してみました。

ワークフローから他のワークフローのpushイベントがトリガーされないケース

まず、ワークフローAでブランチを作成しpushをします。

# .github/workflows/create-release-branch.yml
name: Create release branch

on: workflow_dispatch

jobs:
  branch:
    name: Create and push branch
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.MY_GITHUB_TOKEN }}
      - name: create and push release branch
        run: |
          branch_name=release-$(date +'%Y-%m-%d-%H-%M-%S')
          git switch -c ${branch_name}
          git push origin ${branch_name}

次に、ワークフローBではpushイベントをトリガーにしてジョブを実行します。しかし、なぜかpushをしても、このワークフローBが動きません。

# .github/workflows/deploy-release-branch.yml
name: Deploy release branch

on:
  push:
    branches:
      - release-*

jobs:
  deploy:
    name: Deploy release branch
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - uses: actions/checkout@v4

      # ... Do deployment

ワークフローから他のワークフローをトリガーしない原因

GitHub Actionsでは暗黙的にデフォルトでGITHUB_TOKENというシークレットが自動で作成されます。(参考: 自動トークン認証 - GitHub Docs

このGITHUB_TOKENを使っている場合は、ワークフローからワークフローをトリガーしないようになっています。これは、「意図せずワークフローからワークフローがトリガーされて、再起的なワークフローの実行がされてしまう」ということを防ぐためとのことです。(参考:ワークフローのトリガー - GitHub Docs

ワークフローから他のワークフローをトリガーする方法

これに対応するには、GITHUB_TOKENの代わりにパーソナルアクセストークンを指定する必要があります。パーソナルアクセストークンを指定すると次のようになります。これで、無事にdeploy-release-branch.ymlがトリガーされるようになります。(参考: 個人用アクセス トークンを管理する - GitHub Docs

# .github/workflows/create-release-branch.yml
name: Create release branch

on: workflow_dispatch

jobs:
  branch:
    name: Create and push branch
    runs-on: ubuntu-latest
    timeout-minutes: 5

    steps:
      - uses: actions/checkout@v4
        with:
          # 追加: checkout時にパーソナルアクセストークンを指定
          token: ${{ secrets.MY_PERSONAL_ACCESS_TOKEN }}
      - name: create and push release branch
        run: |
          branch_name=release-$(date +'%Y-%m-%d-%H-%M-%S')
          git switch -c ${branch_name}
          git push origin ${branch_name}

上記はcheckout時のトークンの指定方法なので、他のactions/github-scriptghコマンドの場合はそれぞれ次のようにパーソナルアクセストークンを指定する必要があります。

# actions/github-scriptの場合
- uses: actions/github-script@v7
  with:
    github-token: ${{ secrets.MY_PERSONAL_ACCESS_TOKEN }}
    script: |
      github.rest.issues.addLabels({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        labels: ['Triage']
      })

# ghコマンドの場合
- env:
    GH_TOKEN: ${{ secrets.MY_TOKEN }}
    ISSUE_URL: ${{ github.event.issue.html_url }}
  run: |
    gh issue edit $ISSUE_URL --add-label "triage"

※ そもそもpushイベントのトリガーではなく、ワークフローの流れやファイル内容を見直して、workflow_runworkflow_callなどでも対応することは可能です

以上です。こちら参考になれば嬉しいです。

React Testing LibraryでReactコンポーネントを基本的なテストをする方法

React Testing Libraryで基本的なReactコンポーネントをテストする使い方を説明します。

React Testing Libraryとは

(確認したバージョン 15.0.2 です)

Reactコンポーネントをレンダーして要素をテストする方法

与えられたpropsに対してコンポーネントが正しくレンダリングされるかをテストしたいことはよくあります。 renderコンポーネントレンダリングscreenのクエリ系のメソッドで要素を取得し、expectアサーションをします。

また、@testing-library/jest-domを使うことで、DOM要素に対する便利なマッチャーを使えます。よく使うのは、次のようなメソッドです。

メソッド 説明
toBeInTheDocument() 要素が存在するか
toHaveTextContent(...) 要素のテキストが一致するか
toHaveAttribute(...) 要素の属性が一致するか
// hello.test.jsx
import React from 'react'
import '@testing-library/jest-dom';
import { render, screen } from "@testing-library/react";

import Hello from "./hello";

describe('Hello', () => {
  it('renders "Hey, stranger"', () => {
    // renderでコンポーネントをレンダリング
    render(<Hello />);
    // screen経由で要素を取得し、アサーションをする
    expect(screen.getByText('Hey, stranger')).toBeInTheDocument();
  });

  it('renders "Hello, John" with the name props', () => {
    render(<Hello name="John" />);
    expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent('Hello, John');
  });
});
// hello.jsx - テスト対象のコンポーネント
import React from "react";

export default function Hello(props) {
  if (props.name) {
    return <h1>Hello, {props.name}!</h1>;
  } else {
    return <span>Hey, stranger</span>;
  }
}

要素を取得する方法

React Testing Libraryで要素を取得するために、

  • getBy (複数の要素の場合は getAllBy
  • findBy (複数の要素の場合は findAllBy
  • queryBy (複数の要素の場合は queryAllBy

また、要素の取得方法も、次のように様々な方法がサポートされています。

  • Role:role属性で要素を取得
  • LabelText : ラベルのテキストで要素を取得
  • PlaceholderText: プレースホルダーのテキストで要素を取得
  • Text : テキストで要素を取得
  • DisplayValue:表示されている値で要素を取得
  • AltText:alt属性で要素を取得
  • Title:title属性で要素を取得。SVGなどで利用
  • TestId:data-testid属性で要素を取得:

これらを組み合わせて、getByRolequeryAllByTextなど目的に合わせて使い分けることができます。

getBy / findBy / queryBy の使い分けとしては、要素がある場合は、getBy、要素を待つ場合はfindBy、要素がない場合はqueryByを使うと良いでしょう。

またgetAllBy / findAllBy / queryAllBy は、複数の要素を取得する場合に使います。こちらも同様に、要素がある場合は、getAllBy、要素を待つ場合はfindAllBy、要素がない場合はqueryAllByを使うと良いでしょう。

各メソッドの早見表は次のとおりです。

メソッド 要素が0件 要素が1件 要素が複数 Waitするか?
getBy エラー 1要素 エラー No
findBy エラー 1要素 エラー Yes
queryBy null 1要素 エラー No
getAllBy エラー 配列 配列 No
findAllBy エラー 配列 配列 Yes
queryAllBy [] 配列 配列 No

参考: Testing LibraryのQueryについて

Reactコンポーネントのインタラクションテストをする方法

コンポーネントに対して、ユーザー操作をテストしたいこともよくあります。@testing-library/user-eventを使うことでユーザー操作をシミュレートすることができます。(他の方法もあります)

import React from 'react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event'
import { render, screen } from "@testing-library/react";

import Toggle from "./toggle";

describe('Toggle', () => {
  it('renders "Turn on" button', () => {
    const onChange = jest.fn();
    render(<Toggle onChange={onChange} />);

    expect(screen.getByRole('button')).toHaveTextContent('Turn on');
    expect(onChange).not.toHaveBeenCalled();
  });

  it('renders "Turn off" button after click and called onChange', async () => {
    const onChange = jest.fn();
    // userEvent.setup()でユーザーイベントをセットアップ
    // コンポーネントをレンダリングする前に呼び出すのを推奨
    const user = userEvent.setup();
    render(<Toggle onChange={onChange} />);

    const button = screen.getByRole('button')
    // ボタンクリックをシミュレート
    await user.click(button)

    expect(button).toHaveTextContent('Turn off');
    expect(onChange).toHaveBeenCalledWith(true);
  });

  // ...
});
// toggle.jsx - テスト対象のコンポーネント
import React, { useState } from "react";

export default function Toggle({ onChange }) {
  const [state, setState] = useState(false);

  return (
    <button
      onClick={() => {
        setState(previousState => !previousState);
        onChange(!state);
      }}
    >
      {state === true ? "Turn off" : "Turn on"}
    </button>
  );
}

APIから非同期でデータ取得するコンポーネントをテストする

APIからデータを非同期で取得して、その内容を表示するコンポーネントはよくあります。このようなコンポーネントをテストする場合、jest.mockを使ってAPIのレスポンスをモック化し、waitForを使って非同期処理が終わるまで待つことができます。

// posts.tests.jsx
import React from 'react'
import '@testing-library/jest-dom';
import { render, screen, waitFor } from "@testing-library/react";
import axios from 'axios';

import Posts from './posts';

jest.mock('axios');

describe('Posts', () => {
  it('renders the posts', async () => {
    // axios.getをモック化
    const fakePosts = [
      { id: 1, title: 'First post' },
      { id: 2, title: 'Second post' },
    ];
    axios.get.mockImplementation(() =>
      Promise.resolve({
        json: () => Promise.resolve(fakePosts)
      })
    );

    render(<Posts />);

    // waitForで"loading..."が表示されなくなることを待つ
    await waitFor(() => {
      expect(screen.queryByText(/loading.../)).not.toBeInTheDocument();
    });
    expect(screen.getByText('First post')).toBeInTheDocument();
    expect(screen.getByText('Second post')).toBeInTheDocument();
  });
});
// posts.jsx - テスト対象のコンポーネント
import React, { useState, useEffect } from "react";
import axios from "axios";

export default function Posts() {
  const [posts, setPosts] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  const fetchPosts = async () => {
    const response = await axios.get('/posts').then((res) => res.json());
    console.log(response);
    setPosts(response);
    setIsLoading(false);
  };

  useEffect(() => {
    fetchPosts();
  }, []);

  if (isLoading) {
    return "loading...";
  }

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

React Hooksのテスト方法

React Hooksをテストしたい場合は、renderHookを使います。renderHookはHooksをテストするためのユーティリティです。

// use-logged-in-user.test.js
import { renderHook } from '@testing-library/react';
import { waitFor } from "@testing-library/react";
import axios from 'axios';

import useLoggedInUser from './use-logged-in-user';

// Jestでaxiosをモック化
jest.mock('axios');

describe('useLoggedInUser', () => {
  it('returns logged in user when logged in', async () => {
    axios.get.mockResolvedValue({ name: 'Alice' });

    // renderHookでHooksを実行
    const { result } = renderHook(() => useLoggedInUser());

    // Hooksの処理が非同期なので処理が終わるまでwaitForで待つ
    await waitFor(() => {
      expect(result.current.isLoading).toEqual(false)
    });
    expect(result.current.user).toEqual({ name: 'Alice' });
  });

  it('returns null when not logged in', async () => {
    axios.get.mockResolvedValue(null);

    // renderHookでHooksを実行
    const { result } = renderHook(() => useLoggedInUser());

    // Hooksの処理が非同期なので処理が終わるまでwaitForで待つ
    await waitFor(() => {
      expect(result.current.isLoading).toEqual(false)
    });
    expect(result.current.user).toEqual(null);
  });
});
// use-logged-in-user.js
import { useState, useEffect } from 'react';
import axios from 'axios';

export default function useLoggedInUser() {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    axios.get('/api/user')
      .then((data) => {
        setUser(data)
        setIsLoading(false)
      })
      .catch(() => {
        setIsLoading(false)
      });
  }, []);

  return { isLoading, user };
};

参考: renderHookのAPI仕様

スナップショットテスト

JestのtoMatchSnapshotを使うことで、コンポーネントレンダリング結果をスナップショットとして保存し、次回のテスト時にスナップショットと比較することができます。

// hello.test.jsx
import React from 'react'
import '@testing-library/jest-dom';
import { render, screen } from "@testing-library/react";

import Hello from "./hello";

describe('Hello', () => {
  it('renders Hello component', () => {
    const { asFragment } = render(<Hello />);

    // スナップショットを作成
    expect(asFragment()).toMatchSnapshot();
  })

  // ...
});

作成されたスナップショットは次のようになります。今後Helloコンポーネントを修正して、スナップショットと差分が出てくる場合は、スナップショットテストが失敗します。スナップショットの更新はjest --updateSnapshotで行うことができます。

// __snapshots__/hello.test.jsx.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Hello renders Hello component 1`] = `
<DocumentFragment>
  <span>
    Hey, stranger
  </span>
</DocumentFragment>
`;

より高度なことをしたい場合

JavaScriptのテスティングフレームワークのJestを5分でキャッチアップ

この記事では、Jestの基本的な使い方をざっくり説明します。Jestの主要機能を確認したい、Jestの雰囲気をつかみたいといった方向けです。Jestをより詳しく知りたい場合は、公式ドキュメントをご確認ください。

Jestとは

  • Jestはシンプルさを重視したJavaScriptのテスティングフレームワークです。
  • 哲学として「テストを楽しくする」が掲げられています。
  • Jestは、TypeScript, Node, React, Angular, Vueなどさまざまなプロジェクトで利用できます。

Jestの特徴は次の通りです。

  • 設定なしで導入できる
  • テストを並列で実行するので速い
  • モックが簡単
  • フラグを追加するだけでコードカバレッジを計測できる

Jestでテストを書く

  • describeメソッドでいくつかの関連するテストをまとめます。
  • そして、testメソッド(別名のitメソッドもある)で、テストケースを記載します。
  • テストケース内では、expectとMatcherを使ってアサーションをします。
  • MatcherはtoBe()toEqual()などテスト対象の値を比較をするメソッドです。
// sum.js
// テスト対象のコード
function sum(a, b) {
  return a + b;
}
module.exports = sum;

// sum.test.js
// テストコード
const sum = require('./sum');

describe('sum', () => {
  it('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
  });

  it('adds -1 + 2 to equal 1', () => {
    expect(sum(-1, 2)).toBe(1);
  });
});

JestのMatcherを使いこなす

  • Jestではexpectで検証します。
  • .notをメソッドチェインすることで否定を表せます。
  • さまざまな種類のMatcherがあるのでテストケースの実装で困ることはほぼないでしょう。
  • 参考: Jestで利用できるMatchers
describe('sum', () => {
  it('should not return null', () => {
    expect(sum(1, 2)).not.toBeNull();
  });
});

Jestで非同期処理のテストコードを書く

  • Jestで非同期処理のテストをする方法はいくつかありますが、async/await を使うと良いでしょう。
  • 他のテストの書き方としては、then/catchでテストする方法、.resolves/.rejectsでテストする方法などがあります。

testの関数をasyncキーワードで定義し、awaitで非同期処理を待ちます。

// Async/Awaitで非同期処理をテスト

// テスト対象の非同期処理のコード
const fetchUser = async (id) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // テストのためのダミー実装
      if (id === 1) {
        resolve('John Doe');
      } else {
        reject('not found user');
      }
    }, 200);
  });
}

// テストコード
describe('fetchUser', () => {
  // 非同期処理が成功するケース
  test('the data is John Doe', async () => {
    const user = await fetchUser(1);
    expect(user).toBe('John Doe');
  });

  // 非同期処理が失敗するケース
  test('the fetch fails with an error', async () => {
    await expect(fetchUser(2)).rejects.toMatch('not found user');
  });
});

参考: Jestで非同期コードのテストの書き方

Jestでモックを使う

  • モックする方法は、「テストコード中でモック関数を作成する方法」と「マニュアルモックを使う方法」の2つがあります。
  • ここでは、「テストコード中でモック関数を作成する方法」を説明します。
  • モジュールのモックをクリアするには、Jestの設定ファイルでclearMockstrueにすると良いでしょう。

Jestのモックはjest.fn()で作成し、mockReturnValue()mockImplementation()でモックの返り値の指定やモックの振る舞いを実装できます。

// jest.fn()でモックを作成
// mockReturnValue()でモックの返り値を指定できる
test('the mock returns 10', () => {
  const myMock = jest.fn().mockReturnValue(10);
  expect(myMock()).toBe(10);
});

// mockReturnValueOnce()で呼び出し回数に応じてモックの返り値を変えることができる
test('the mock returns 10, "x", false', () => {
  const myMock = jest.fn()
    .mockReturnValueOnce(10)
    .mockReturnValueOnce('x')
    .mockReturnValueOnce(false);

  expect(myMock()).toBe(10);
  expect(myMock()).toBe('x');
  expect(myMock()).toBe(false);
});

// mockImplementation()でモックの振る舞いを実装できる
test('the mock adds a and b', () => {
  const myAddMock = jest.fn()
    .mockImplementation((a, b) => a + b);

  expect(myAddMock(1, 3)).toBe(4);
});

また、外部のモジュールをモックしたい場合はjest.mock()を使います。

// users.js
import axios from 'axios';

class Users {
  static all() {
    return axios.get('/users.json').then(resp => resp.data);
  }
}
export default Users;

// users.test.js
import axios from 'axios';
import Users from './users';

jest.mock('axios');

it('should fetch users', async () => {
  const users = [{ name: 'Bob' }];
  const resp = { data: users };
  axios.get.mockResolvedValue(resp);
  // もしくは mockImplementationで次のように実装可能
  // axios.get.mockImplementation(() => Promise.resolve(resp))

  const data = await Users.all()
  expect(data).toEqual(users);
});

参考: マニュアルモックモック関数

テストのSetupとTeardown

  • beforeEach()で各テストケースのセットアップ処理を共通化することができます。
  • afterEach()で各テストケースの終了後の処理を共通化することができます。
  • beforeAll()afterAll()を使うことでテストケースのまとまりに応じてセットアップや終了後の処理を記載できます。
describe('isCity', () => {
  // 各テストケースの実行前に実行される
  beforeEach(() => {
    initializeCityDatabase();
  });

  // 各テストケースの終了後に実行される
  afterEach(() => {
    clearCityDatabase();
  });

  test('city database has Vienna', () => {
    expect(isCity('Vienna')).toBeTruthy();
  });

  test('city database has San Juan', () => {
    expect(isCity('San Juan')).toBeTruthy();
  });
});

その他の使い方

エンジニアリングマネージャーと目標管理

🎯 目標管理とは

目標管理とは

目標管理とは、目標を設定し、定期的に達成度を確認しながら、目標達成を実現していくマネジメント手法です。

目標管理が人事評価と強く結びついて保守的な目標になったり、目標を振り返らず形式的になって、上手く目標管理がワークしていないことがよくあります。しかし、目標管理の目的を理解し適切に運用することで、メンバーのやる気や主体性を促し成長や成果を高めていけます。

⚠️ここでの「目標管理」は、EMのピープルマネジメントにおける個人の目標管理について説明しています。組織やチームの目標管理などについては当てはまらない内容もあります。

目標管理の目的

一般的な目標管理の目的は次のとおりです。

  • 組織全体の方向性を揃えて、効率的に組織の目標達成を目指す
    • 目標は「会社の目標 → 事業の目標 → チームの目標 → 個人の目標」というように繋がっています。
    • 組織から個人まで方向性を揃えることで、効率的に目標達成を目指せます。
    • そのため、個人目標では、チームの目標と個人のWill/Canを加味して、期待値をすり合わせながら目標を立てていきます。
    • そうすることで、個人目標の達成が「メンバーの自己実現」と「組織目標の達成」の両方の実現につながります。
  • メンバーの主体性やモチベーションを高め、能力を最大限に発揮させる
    • 個人目標は、メンバー自身の目標なので、メンバーが主体となって目標を立てていきます。
    • 目標の自己管理を促すことで、個人目標を自分事として取り組むことができます。
    • そして、目標に対する責任感が高まり能力が発揮され、その結果として成長や成果も向上します。
  • 成果や成長を客観的に評価して個人の頑張りに報いる
    • 「どういう成果をだしたか」、「どんなスキルを身につけたか」を評価して、フィードバックすることで、メンバーの頑張りを認めていきます。
    • また、頑張りを認めるだけでなく、昇給や給与、やりがいのある機会の提供などで報いていきます。
    • そして、現状の課題や今後の伸びしろを話し合うことで、メンバーのやりたいことやなりたい姿へ近づくモチベーションを高めていきます。

🔄目標管理のサイクル

全体的な、目標管理のサイクルは次のとおりです。

  • 期初:目標を設定する
  • 期中:随時目標の達成を支援をする
  • 期中:定期的に目標を振り返る
  • 期末:目標の達成度を評価する

①期初に目標を設定する

まずは、期初に目標を設定します。目標設定は、メンバー自身が主体的に進めていきます。目標設定を主体的に考えることで、メンバー自身が目標や実現方法に対する理解を深め、前向きに達成に取り組めるようになります。

1. マネージャーから事前にチーム目標や期待値を伝えておく

組織目標から個人目標までつながりを意識して、個人目標を立てる必要があります。そのため、マネージャーから事前にチーム目標や個人に対する期待値を伝えておきます。こうすることで、メンバーがどうやってチームに貢献して成果を上げるか考えられるようにします。

  • チーム活動を通して、チームに向けてプロダクト戦略やチーム目標を伝え続ける
  • 1on1や目標設定の対話を通して、メンバーに期待する能力や言動、成果を明確に伝える

2. メンバーに個人目標を立ててもらう

次に、メンバーに個人目標を立ててもらいます。目標を上手く立てれなくても今できる範囲で実施してもらいます。目標がうまく立てれないということは、「期待値が上手く伝わっていない」、「現状把握がうまくできてない」、「自分がチームにどう貢献すれば良いかわからない」などの状況の裏返しでもあるので、そこは目標設定を通してフォローしていくと良いでしょう。

また、目標を立てるだけでなく、目標の実現に向けたアクションプランも言語化してもらいます。アクションプランを考えることで、本当に目標を実現できるかどうかを検証できるようになります。

3. 個人目標について話し合う

メンバーから個人目標について共有してもらい、組織と個人の期待値を擦り合わせていきます。理想的には、組織も個人もお互いにWin-Winになる状態を目指していきます。

  • チームメンバーとして、個人目標がチーム目標の達成につながるようにする
  • 個人としても、自己実現のために新しい挑戦やスキル成長に繋がるようにする
  • 個人のやりたいことや強みが活かせるような目標やアクションプランにする
  • メンバー自身がやりたいと思えるような目標にする

②期中は随時目標の達成を支援をする

個人目標の管理は、自己管理が求められます。EMはサポート役と振る舞うことで目標の達成を支援します。

自己管理のレベルやスキル感などに応じて支援の度合いも変わります。例えば、そもそもアクションプランを上手く描ききれていない場合は壁打ちして思考の整理を手伝ったりやり方自体を教えたりします。

支援する方法としては、次のような方法があります。

  • 業務を通じて支援する
    • 機会を作る、議論する、レビューする、一緒に手を動かすなどで業務を通じて目標達成を支援します。
  • 1on1を通じて支援をする
    • ティーチング、コーチング、フィードバックなどを通してメンバーの達成を支援していきます。
  • 仕組みで支援していく
    • チーム体制、プロセス変更、コミュニケーション設計、アサイン、インセンティブ設計の変更、他チームへの働きかけなどを通して仕組みで解決していきます。

③期中は定期的に目標を振り返る

定期的に毎月1回ほど目標の振り返りをしていくことを推奨します。振り返りの中で、達成度をすり合わせ、学びを言語化し、フィードバックをし、必要なら軌道修正をすることで、目標の実現に向けて前向きに取り組んでいくことができるようになります。

  • 現在の達成度を認識合わせする
    • まずは、達成度に対して認識を合わせることで振り返りの対話を始めていけます。 -「達成度はどのぐらいか?」、「残りはどのぐらいか?」、「ペースとしては早いのか遅いのか?」を話し合います
    • 数値で測定可能な目標であれば分かりやすいですが、数値で測定できない目標であればすり合わせは丁寧に実施します
  • 学びを言語化して次に活かす
    • 目標を目指して仕事をするとさまざまな発見や学びがあります。それを言語化してもらうことで、次に活きるようにします。
    • 「上手くいったことはどんなことでしたか?」「うまくいかなかったいかなかったことは?」「目標達成に活かせる学びはどのようなものがあったか?」などを質問していきます。
  • 目標達成に向けた方針やアクションを設定する
    • メンバー自身に目標達成の方法を考えてもらいます。また必要であれば、EMから方法を教えたり議論をします。
    • 「目標達成に向けて何をしていきますか?」、「それはいつまでに実施しますか?」、「上手くできたかどうかどうやって評価しますか?」

また、振り返りの際は、フィードバックで学びを促したり、承認をすることでエンゲージメントも高めていくこともとても大事です。

④期末に目標の達成度を評価する

評価はメンバーにとってとても重要な関心事です。評価結果が給与に影響するのはもちろんありますがが、頑張って働いたのに誰も見てくれてなくコメントがないでは寂しいものです。また、働いても報われない、成長にも繋がらないと考えて離職リスクが高 まってしまうでしょう。そのため、しっかりと目標の達成度について評価をして、承認やフィードバックをし、次の目標に活かしていきます。

  • 自己評価をしてもらう
    • 目標を設定したメンバー自身に自己評価とその理由を言語化してもらいます。
    • 上手く行った点、上手く行かなかった点、チームとして改善すべき点などを記載してもらいます。
  • EMとメンバーで達成度について認識を合わせる
    • 定期的に達成度をすり合わせているので、期末時点でお互いに達成度の認識が大きくずれることはないはずです。
    • お互いに納得感が高い評価に繋がり、次の目標や課題について前向きに取り組めるようになります。
    • また、達成した目標の成功要因、未達成の目標の障害を振り返り、学びに活かしていきます。

詳細については、「評価」の記事で記載していく予定です。

☝️目標を立てる時のポイント

参考までに、目標を立てるときのポイントをいくつか列挙します。目標の運用はしっかりやっているが目標管理が上手くいかない時は、大体目標設定でうまくいっていないのが原因です。目標が上手く立てれるかチェックしてみてください。

  • 重要な部分に焦点を当ているか?
  • 目標は客観的に判断が可能か?
  • 目標達成の道筋が6-7割は見えているか?
  • 個人のやりたいことや強みが活かせるか?
  • 目標達成したら個人の成長が実現できるか?
  • メンバーが目標を達成したいと考えているか?

重要な部分に焦点を当ているか?

枝葉をやっても成果はでません。「目標の数が多すぎる」、「目標がタスクリストになっている」といった状況の場合は黄色信号です。

やりたいことは常にリソース以上にあるので、その中で優先度をつけて、何をやって何をやらないかを決める必要があります。その時に、プロダクト戦略やチーム目標の達成において、本質的な部分に焦点を当てたものにします。

また焦点を当てるには、課題の解像度を高め、問題設定をする力がとても大事です。ドメイン知識や技術的なスキルを高めたり、ロジカルシンキングクリティカルシンキング・システム思考などを学ぶと良いでしょう。

目標は客観的に判断が可能か?

よく目標を振り返るときに、目標が主観的すぎて達成度合いが分からないことがあります。

客観的な判断が可能な目標をたてるには、OKRのような形で目標をたてると方向性と主要な判断軸が決まるのでオススメです。また、エンジニアリングの場合は必ずしも定量化できないこともあるりますが問題ありません。

目標の例です。

  • O
    • 使い勝手と安定性が良いXの体験を提供することで事業拡大に貢献する
  • KR
    • N月までにX機能をリリースする
    • 可用性を99.5%以上を保つ
    • サイト全体の95%タイルのレスポンスタイムを200ms以下にする

目標達成の道筋が最低6-7割は見えているか?

目標を達成するには、達成の道筋をアクションプランという形で大まかに考えておく必要があります。アクションプランを考えることで、目標の達成が現実的なものなのかどうかを判断することができます。

個人のやりたいことや強みが活かせるか?

個人のやりたいことで強みが活かせると、成果はとてもでやすくなります。なぜなら、やりたいことなので主体的にモチベーション高く取り組み、強みが活かせるので上手くいきやすいので、成果がでます。

ドラッガーも「人は強みによって成果を上げる。弱みで優れた成果を上げることはない。」と言われるように、強みを活かした目標設定はかなり大事になってきます。弱みで戦っても成果が出るまでなかなか時間がかかるの、かつ、成果も非凡なものになってしまうでしょう。

目標達成したら個人の成長が実現できるか?

「コンフォートゾーン(現状維持で成長が見込めない)」、「チャレンジゾーン(やりがいがあり挑戦的なので成長が見込める)」、「パニックゾーン(想像が全くつかなく心身が疲弊する)」と3つのゾーンがあります。

全ての目標ではなくてもいいので、チャレンジゾーンの目標もいくつか立てるることで、個人の能力を向上させることができます。もし、目標に届かなかったとしても大きく成長しますし、目標に届いた場合は成長だけでなく大きな成果も実現できます。

チャンレンジゾーンの目標を立ててもらうには、失敗を許容して、挑戦を推奨するような文化作りが必要です。また、人事評価と目標管理が直接的に結びついてしまうと、保守的な目標を立てるインセンティブが働いてしまって上手くいかないでしょう。

メンバーが目標を達成したいと考えているか?

メンバー自身がモチベーション高く主体性を発揮して目標達成を目指すには、自分で目標を設定し、それを達成したいと思えているのがとても大切です。評価のための形だけの目標か、本当に達成したい目標か見極めていきます。

📚参考書籍・サイト

エンジニアリングマネージャーと委譲

⏩ 委譲とは

委譲とは、上司が持つ権限を、部下に部分的に譲り渡すことです。

委譲は組織の成果や個人の自己実現の達成においてとても重要な手法であり、優秀なエンジニアリングマネージャーになるには上手く委譲するスキルを学んでいく必要があります。

次のようなことがある人は、委譲のスキルを磨いていく必要があるでしょう。

  • 自分で仕事を抱え込みがちでいつも忙しい
  • 自分でやった方が早いと考えてなかなか任せられない
  • 任せてもいまいち期待する成果をだしてくれない

委譲のメリット

よく言われる委譲のメリットは次の通りです。

  • モチベーションの向上:メンバーは任せてもらえたと感じ、裁量権が与えられて自主性を発揮できるので、仕事への意欲が高まる
  • 成長促進:メンバーが新しい視野や視座で自ら考えて行動する機会を得ることで、成長をすることができる
  • 組織成果の向上:EMが委譲した業務から手が離れ、組織全体の成果を高めることに集中できるようになる

委譲の最終的なゴール

こちらもよく言われていることですが、委譲の最終的なゴールは自分が不要になることです。

仮に自分が不要になった場合のイメージとしては、次のような状態でしょう。

  • メンバーが自律的に業務を遂行できる
    • メンバー自身で自立して計画、実行、振り返り、改善を実施できる
    • 問題が発生しても、自力で解決できる
    • 新しい知識やスキルを積極的に学び、自己成長に励む
  • チームが自立してうまく機能する
    • チーム目標に向けて、チームが重要なことにフォーカスして取り組む
    • メンバー同士が協力し、情報共有や助け合いが活発に行われる
    • 他チームと連携してチームの成果を高めていける
  • EMは技術戦略や組織運営に集中できる
    • EMは細かい業務指示が不要になり、戦略策定や組織運営に多くの時間を使える
    • 業界動向や最新技術を把握し、開発組織の戦略を考える
    • 採用や育成の仕組みづくりをすることで、中長期的に組織のケイパビリティを高める

補足として、自分が不要になるといっても、存在価値がなくなるというわけではありません。組織やチームという視点で、チームやメンバーを支援し続けて、組織全体のパフォーマンスを高めていくことは責務として持っているため引き続き実施していきます。

🔎 委譲のやり方

委譲する中で一番大切なことは、「成果の期待値を擦り合わせ、タスクをできる能力があるか確認し、能力とタスクの重要度を鑑みて委譲の度合いするか決めていく」ことです。

誰に委譲するか

基本系としては、委譲するタスクに対して、Will(やりたいこと)とCan(できること)がマッチした人に委譲します。なぜなら、やりたいことなので高いモチベーションで取り組んでもらえ、また、できることなので高いパフォーマンスを発揮してもらえるでしょう。

しかし、次のように必ずしもWill/Canとマッチしないこともあります。

  • できることをやり続けても成長角度は下がってしまうので、ときにはチャレンジングなことを実行してもらい成長を促す
  • 業務として重要かつ必要だけどできる人がいないので、やりたいことではないが意義を説明しつつタスクをお願いする

また、中級編として、委譲においては、チーム全体を見渡して誰がどのように動くとチームの成果の最大化をできるかを考えます。メンバー同士の強みを活かし、弱みを補完しあえるように動ける体制を組めるとチームの成果をさらに高めていくことができます。

ちなみに、メンバーのWill/Canの把握については、1on1や日々の観察などを通して事前に準備しておく必要があります。

何を委譲するか

委譲のゴールである「自分が不要になる」と照らし合わせると、次のような観点で委譲を進めていくと良いでしょう。

  • 普段の開発・保守運用はチーム内で完結できるようにする
  • 個々のメンバーが自律して業務を進められるようにする
  • 次のリーダーやエンジニアリングマネージャー候補が育っている

このようにすることで、開発を進めていく中でEMがボトルネックになることはなくなります。また、課題が起きてもチームやメンバーの成長機会となり、強いチームや自立したメンバーに育っていくでしょう。

もちろん、あくまで理想なので、足元何かしら課題がある中で、短期と中長期のバランス、成果と成長のバランスをとりながら、支援や介在していく必要はあります。

委譲する内容として、以下2つは注意が必要です。

  • 失敗したらチーム全体の成果が大きく毀損する重要度が高いタスクでリスクを取らない
  • 全ての責任は委譲できない。実行を任せたとしても、最終的な結果の責任は上司が持ち続ける

どうやって委譲するか

委譲を打診し、お互いに納得したら、期待値を擦り合わせていきます。

まず、委譲を打診して納得してもらうには、日々の感謝や賞賛を伝え、タスクの意図や意義を伝え、相手のメリットを伝えます。

  • 感謝や称賛を伝える
    • 褒める、相手の名前を呼ぶ、相手に重要感を持たせる、良いところを承認して後押しするなどして相手を認めます。
    • 上っ面のテクニックではなく、素直な気持ちで本心から伝えることが大切です。
  • 意図や意義を伝える
    • タスク内容を伝えるだけでなく、そのタスクの意図や意義を伝えます。
    • 目的がはっきりすることで、意欲が高まったり、成果に繋げる動きがしやすくなる。
  • メリットを提示する
    • 人を動かすためには、相手に自らの意思で行動を起こさせるよう働きかけることが重要です。
    • そのためには、相手の立場に身を置き、相手の視点から考えて、「行動したい!」と思ってもらうように働きかけます。

次にお互いに納得したら、委託する内容の期待値を擦り合わせていきます。擦り合わせる内容としては、「成果」「権限」「評価」を中心に擦り合わせていきます。

  • 成果
    • いつまでになにを達成して、どのような成果を上げるか
  • 権限
    • 責任と権限はセットなので、実施できる権限を与える
    • また、使用できるリソース(人、カネ、技術など)を明確にする
  • 評価
    • 成果を評価する基準と時期を明確にする
    • また、報酬やキャリアの影響、組織や顧客への影響も伝える

どのぐらい委譲するか

「エンジニアリングマネージャーのしごと」では、タスクをどのぐらい委譲するかという度合いを以下のように紹介しています。左から右に行くほど委譲の度合いが大きくなる一方、コントロールの度合いもどんどん下がっていきます。

委譲の物差し(引用元:エンジニアリングマネージャーのしごと)

「委譲する相手のスキル」と「委譲するタスクの難易度」を照らし合わせながら、どのぐらい委譲をするかを擦り合わせていきましょう。そして、「完全な委譲」に向けて、ティーチング、コーチング、メンタリングなどを通して委譲の度合いを高めていきます。

委譲を成功させるポイント

よく言われる委譲の成功させるポイントです。当たり前と思うような内容ですが、なかなか実践するのは難しいです。

  • 部下の能力を把握する: 部下の能力や経験に合った権限を委譲することが重要です。
  • 明確な指示を与える: 委譲する前に、目標や期待値を明確に伝えましょう。
  • 定期的にフォローアップを行う: 部下の状況を把握し、必要に応じてアドバイスやサポートを提供しましょう。
  • 失敗を恐れない: 部下が失敗しても、責めるのではなく、学習の機会と捉えましょう。

よくある委譲の失敗パターン

今度はよくある失敗例から、自分がこのような委譲をしていないか振り返ってみてください。

自分でやってしまい全く委譲できていない

あれもこれも自分でやって委譲が上手くできてないケースです。全てを自分で抱え込むと、自分がボトルネックになり、チーム全体の成果を阻害します。また、委譲ができないことでメンバーの成長機会を奪ってしまいます。

重要な仕事は自分ではなくチームに任せ、自分はチームが仕事の成果を120%発揮できるようにサポートをするという考え方に変えていく必要があります。

丸投げしてその後はフォローしない

丸投げしてその後の状況は全く追わないというケースです。タスクの進捗はどうか、品質は満たしているか、メンバーはサポートを必要としているかなど全くわかっていません。これでは、任せたタスクがうまくいくかいかないかは運頼みになってしまいます。

期待値をすり合わせて、適切な支援をしていくことで、タスクの委譲を進めながら、メンバーの成長も促すことができます。

任せたタスクのやり方にまで介入してしまう

EMがマイクロマネジメントして具体的なやり方までに介入してしまうケースです。これでは、委譲された人の自主性が毀損され、モチベーション低下が起こったり、いつまでたっても委譲ができません。

他の人のやり方が自分と同じであることを期待してはいけません。目的、背景、期限を伝え、具体的な実現方法については任せます。その中で、メンバーが実現方法について支援を必要としている場合のみ、やり方について助言をしていきます。また、大事になる失敗以外は許容して任せるという胆力も必要になってきます。ちなみに、ジュニアの方は、必要に応じてHRTの精神を持ち大きく介在することで実力を大きく伸ばすこともできます。

⬆️ 成長を促す任せ方

メンバーを成長させ、組織全体のレベルアップを実現するためには、単に仕事を任せるだけでなく、持続的な成長支援を行うことが重要です。ここでは、成長を促す任せ方の4ステップを紹介します。

1. 失敗を許容する環境を作る

ビジネスで成功するには、チャンスを捉えて全速力で駆け抜けることが必要です。しかし、チャンスを見極めるためには経験が必要であり、失敗はつきものです。

良いマネージャーは、メンバーがチャンスを見極められるようサポートし、失敗しても大丈夫と思える環境を作ります。失敗を責めるのではなく、挑戦したこと自体を称賛する文化を醸成することで、メンバーは積極的にチャレンジし、そこから学ぶことができます。

2. チャレンジングなタスクを任せる

メンバーの成長を促すためには、意欲や適正に沿った、適度な挑戦しがいのあるタスクを任せることが重要です。メンバーの実力やポテンシャルを観察し、コンフォートゾーンから抜けたチョレンジングな目標を設定します。

誰に、どんな舞台を与え、どのように準備するのか。適切な期待と挑戦を促すことで、メンバーは潜在能力を発揮し、大きく成長することができます。

3. 忍耐強く見守り、必要に応じて支援する

仕事を任せたら、口を挟まずに相手を信じて見守りましょう。また必要に応じて支援するときも、答えを教えるのではなく答えを見つけるためのヒントを与えることで、メンバーの思考力や問題解決能力を養うことができます。

また、メンバーひとりひとりの個性や強みを尊重し、それぞれのやり方で成果を出せるように支援することが大切です。任せた後は、適切なタイミングでフィードバックを行い、成長をサポートしましょう。

4. 成果に報いる

メンバーが成果を達成したら、具体的なフィードバックと称賛を伝えることで、モチベーションを高めることができます。さらに、次のゴールを示し、その魅力を伝えることで、さらなる挑戦と成長を促すことができます。

なぜその仕事をするのか、目標達成によってどのような未来が待っているのかを明確にすることで、メンバーは仕事への意欲を高め、主体的に取り組むようになります。

これらのポイントを意識することで、メンバーの成長を促しながら、組織全体のレベルアップを実現することができるでしょう。

📚 参考書籍・サイト

エンジニアリングマネージャーと1on1

👥1on1とは

1on1は、定期的に1対1で対話をするミーティングのことです。上司と部下、メンターとメンティといった関係性において、信頼関係を構築し、コーチングやメンタリングなどを通して個人の成功を支援し、組織の成果に繋げていきます。

エンジニアリングマネージャーになると、1on1に多くの時間を使うことになります。例えば、チームメンバーが7名から8名いる場合、1on1にまつわる時間は業務時間の1〜2割ほどになります。周りがやってるからとりあえず1on1をやるという考えでは、マネージャーとメンバーの時間の無駄になってしまいます。

メンバーに合わせて戦略的に1on1を実施することで、メンバーの自己実現と組織の成果向上を実現することができるでしょう。

1on1の目的

1on1の目的は、個人の成功をサポートし、組織の成果を高めていくことです。そのため、1on1はメンバーのための時間とし、メンバーが成功することを全力でサポートしながら、組織の成功に結びつくようにしていきます。

1on1の重要性

1on1は、ピープルマネジメントの多くの活動をカバーしており、ピープルマネジメントにおいてとても重要な活動になってきます。

具体的には、1on1で次のようなことを実現できます。

  • 親近感や信頼関係を構築する
  • 心理的安全性を高める
  • 期待値のすり合わせ
  • 主体性を促す
  • モチベーションを高める
  • 課題解決を支援する
  • 成長を促進する
  • キャリア実現を支援する

また、効果的な1on1を実施するには、コミュニケーションスキルも必要になります。

このように、何も準備をしていない雑談と、意味があり焦点が明確な1on1では効果が大きく異なることは容易に想像がつくでしょう。

1on1の頻度と時間

エンジニアに対する1on1の頻度と時間は、週1回30分を推奨しています。

理由としては次の通りです。

  • リモートワークで働く環境が多く、こまめな認識のすり合わせが必要なため
  • 転職周期も早い職種なので、やりがいや成長機会がなくなると離職につながりやすいため

また、個人の状況に合わせて、頻度や時間は調整するのが良いです。

  • ジュニア〜ミドル、入社直後や異動直後など環境変化が大きい場合
  • コーチングが多めに必要、情報共有が得意かどうか、チームや会社に対する不安や不満が多い場合

1on1の心構え

1on1をする中で、大切な心構えを説明します。

1on1はメンバーのための時間

  • 1on1をどういう場所にしたいか話し合い、メンバーごとに内容をカスタマイズする
  • 自分が話すのではなく、メンバーに話してもらい、しっかりと聴く
  • 1人の人間として常に思いやりを示し、マイクロマネジメントをせず、メンバーの自主性を尊重する
  • メンバーが自分の言いたいことを言えて、マネージャーがそれをしっかり受け止め、組織としての考えを伝えてくれるという場を作る

最初は信頼関係を構築する

  • 信頼していない人に悩みは打ち明けてくれない
  • 1on1を始めると自分の話を聞いてもらえる場が定期的にあることが良かったという声が多い
  • 自分のことを見てくれている、話を聞いてくれる、認めてくれるということはとても大事

メンバーの可能性を信じる

  • 1人の人間として常に思いやりを示し、マイクロマネジメントをせず、メンバーの自主性を尊重する
  • メンバーの困りごとを解決すると、メンバーの成長の機会を奪ってしまう
  • 問題に対して解決策を示すのではなく、相手が自分自身で問題を解決するために、頭の上に思考のふきだしをうかばせるようにする
  • 与えられた答えでは納得しない。答えを自分で見つけれるように支援する

🔁1on1の全体的な流れ

新しいメンバーと1on1をはじめてから振り返りまでの、半年ぐらいのスパンを想定しています。

①1on1を始める(2-3ヶ月程度)

まず、メンバーとの親近感や信頼関係を構築しながら、メンバーの理解を進めます。

  • どういう1on1にしたいか話す
    • 1on1はメンバーのための時間であり、メンバーによって1on1に期待することややり方は違います
    • 実際にどういう1on1にしたいか聞いても上手く答えられない人が多いので、自分はこうしたいと伝えて、それをベースに話し合うと良いでしょう。
  • 親近感・信頼関係の構築
    • 親近感や信頼関係ない中で効果的な1on1はできません。
    • 信頼していない人に対して、悩みを打ち明けたり、アドバイスを聞くということはできないでしょう。
    • メンバーと頻度高く話すこと、話を真摯に聞くこと、相手を認めることを通しながら信頼関係を構築していきます。
  • Will・Canの把握
    • Will(やりたいこと)やCan(できること)は個人個人違います。
    • もちろん、WillやCanによって、個人の成果や成長の仕方も変わります。
    • メンバーの自己実現と組織の成果を両立させるには、Will・Canの把握は必須と言っても良いでしょう。
  • 期待値のすり合わせ
    • 「個人としてやりたいこと」と「組織として必要なこと」を期待値という形ですり合わせます。
    • 期待値は、目標管理として明文化されることもあれば、暗黙的な期待値として存在する場合もありますが、お互いにすり合わせておくことがとても大事です。
    • 状況は常に変わるので、期待値は定期的にすり合わせてギャップを減らせるようにします。

②成果や成長を支援する(3ヶ月-半年程度)

親近感や信頼関係が構築でき、人となりを理解しお互いに気兼ねなく話せる状態になってきたら、次は、成果や成長を支援していきます。

  • 月1で目標の振り返り
    • 目標の運用は形骸化されやすいので、月1で実施することで目標管理を機能させることができます。
    • 目標を振り返ってもらい、内省を促し、自分の言葉で行動にコミットしてもらうことで次のアクションを促していきます。
    • 月1で目標の進捗を書いておくことで、半期や年次の人事評価時の納得感が高まるのでオススメです。
  • チーム目標の理解を促す
    • 個々のチームメンバーがチームの目標を理解してない状況で、チーム目標を達成することは難しいでしょう。
    • チーム目標の理解度を把握し、理解を促し、メンバーがどう貢献していくかを語れるように促していきます。
  • 個人やチームの課題を聞く
    • メンバー目線での個人やチームの課題を聞きます。
    • マネージャーとして自分が動いて解決したほうが良さそうな場合はアクションを打っていきます。
  • 満足度や不安・不満を確認する
    • やる気が高いと成果も高くなります。
    • 不安や不満が高くなると離職リスクが高ります。
    • やる気や不安・不満を確認して、適切に対処していきます。
  • フィードバックをする
    • フィードバックは成果や成長を促す手段の1つです。
    • 評価面談の時にいきなりフィードバックするのではなく、日々の1on1の中でこまめにフィードバックをします。
    • フィードバックの仕方としては、SBIモデル(状況、行動、影響)が有名です。

③1on1を振り返る(1ヶ月程度)

最後に、半年ほど活動した振り返りを実施しながら、人事評価、今後のキャリアや1on1の方法について対話していきます。

  • 人事評価
    • 評価スケジュールに基づき実施していきます。
    • 良い評価をだせるように、期中の中で成果や成長をいかに支援できたかが大事です。
  • キャリアについて話し合う
    • 今期の活動により、キャリアに向けてどんだけ進捗しているかを話します。
    • キャリアの進捗がわかることで、次の期もますます頑張ろうとやる気も高まるでしょう。
    • もちろん、やってみたことでキャリアの方向性を変えることもありです。
  • マネジメントに対するフィードバックをもらう
    • アンケートとったり、1on1で聞いたりして、自己のマネジメントに対するフィードバックをもらいます。
    • マネージャーはフィードバックをもらう機会が少ないので、積極的にもらうことで、自己認識を高めて今後の改善につなげることができます。
  • 1on1のやり方を話し合う
    • 半年ぐらい1on1やってきたので、やり方について話し合います。
    • 「どういうところが良かったか」、「どこらへんはあまり効果がなかったか」など話して今後の1on1のやり方に活かせると良いでしょう。

✅1on1のセルフチェック

最後に、1on1が上手くできているかのセルフチェックできるリストを紹介します。
普段の1on1を思い出しながらこのチェックリストを確認することで、今後の1on1の改善のきっかけにできるでしょう。

  • 1on1の進め方
    • ほとんど自分が話していないか?話を遮ってないか?
    • メンバーが自分の意見を言っているか?
    • メンバーから1on1のフィードバックをもらっているか?
  • 信頼関係
    • お互いに親近感を感じているか?
    • 気兼ねなく話をできるか?話をしてくれるか?
  • パーソナリティ
    • メンバーの性格や価値観を把握しているか?
    • メンバーの強みや弱みを把握しているか?
    • メンバーの思考や行動パターンを把握しているか?
  • やる気・エンゲージメント
    • やる気は高い状態か?(10点満点中何点?)
    • 何にやりがいを感じているか?
    • 不満や不安を感じていないか?
  • 成果
    • 目標の期待値はすり合っているか?
    • 期待する成果をだせているか?
    • 成果に対する評価はすり合っているか?
    • 成果をより高めるための活動・支援ができているか?
  • キャリア・成長
    • メンバーのキャリアビジョンを把握しているか?
    • キャリアビジョンの実現に向けて、今期何をやるかお互いに明文化できているか?
    • 定期的に経験学習を実施し成長できているか?
    • メンバーに成長実感があるか?その成長は満足いくものか?

📚参考書籍・サイト

  • 部下が自ら成長し、チームが回り出す 1ON1戦術(具体的な会話例があるのでイメージつきやすい)
  • 対話型マネージャー(型化されておりバランスが良い)
  • 1on1マネジメント
  • One-on-One Meetings Resources for Managers | Lara Hogan

1チームをマネジメントするエンジニアリングマネージャー

1つのソフトウェア開発チームをマネジメントするエンジニアリングマネージャーについてのまとめ記事です。

エンジニアリングマネージャーとは

エンジニアリングマネージャー(EM : Enginnering Manager)は、技術的な知識や経験を持ったエンジニアのマネジメントポジションで、開発チームや開発メンバーをマネジメントして事業の成長に貢献していく職種です。

マネージャーはビジネスの成果や従業員のエンゲージメントに大きな影響を与える存在です。会社から開発チームやメンバーのマネジメントをする権限を与えられており、チームの最終的な成果に責任を負います。そのため、チームやチームメンバーがうまく成果を出せないときに改善に向けて動くのはEMの仕事です。

よくEMは「人のマネジメントをする」職種と思われがちです。しかし、人を中心にしつつも、今まで培った技術、プロセス、プロジェクト管理などのスキル・経験をフル動員してチームの成果を高めていくことが求められます。

エンジニアリングマネージャーの役割

EMの役割は主に2つあリます。

  1. 開発チームの成果を最大化する
  2. 開発組織をスケールさせる

「開発チームの成果を最大化させる」ために、チームの方向づけ、チームビルディング、技術的な課題解決のサポート、ピープルマネジメントなどを行います。

「開発組織をスケールさせる」ために、エンジニアの採用、配置、育成、評価についても実施します。

状況によるEMの役割の違い

EMの役割は、会社のフェイズやチームの置かれている状況によって変わってきます。

例えば、次のように状況によってEMに求められることは変わります。

  • 事業が急成長しておりエンジニアが足りない場合、エンジニアの採用や採用後のオンボーディングに注力する
  • チームの開発が遅れがちな場合、開発上のボトルネックを発見し改善をリードしてスムーズな開発ができるようにする
  • リリースした機能のバグが多い場合、バグの分析をして、短期と中長期目線でシステム品質を高める取り組みを推進する

求人票から見るEMの役割

EMの役割のイメージがつきやすいように、実際の求人票(2022年時点)からEMの役割をみてみます。

Google Cloud エンジニアリングマネージャー

プロジェクトの目標を管理し、製品戦略に貢献し、チームの開発を支援する。

  • ソフトウェアエンジニアのチームを管理し、タスクを計画し、コードレビューをおこなう
  • 技術プロジェクトを推進し、革新的でペースの早い環境でリーダーシップを発揮する
  • 技術プロジェクトの全体的な計画と実行を管理する
  • プロダクトマネジメントチームと協力して、高品質のプロダクトを構築する

Microsoft ソフトウェアエンジニアリングマネージャー

優れた技術力やピープルマネジメントとリーダーシップ、人を魅了するスキルを駆使してソフトウェアエンジニアのチームを率いる。

  • 3~8人のエンジニアのチームをリードする
  • チームメンバーをメンタリングし、成長とキャリア開発を支援する
  • プロダクトマネージャーと連携し、エンジニアリング分野全体で機能開発を主導し、優れたエクスペリエンスを提供する
  • 技術的な決定に対する監督、説明責任、リーダーシップを実施する
  • 他の製品やエンジニアリングチームとのコラボレーションをする

メルカリ エンジニアリングマネージャー プラットフォームグループ

組織の目標にそった長期的な目標とロードマップを構想し、メンバーのキャリア成長と採用によるチームのスケーリングをサポートし、プロセスを改善することで、チームの成果を高めることにコミットする。

  • プラットフォーム改善の長期的な目標とロードマップを構想し、実行する
  • 組織全体のインフラストラクチャの問題を解決するための戦略を提案する
  • チームが最高の仕事をできるようにプロセスを管理する
  • 四半期ごとのエンジニア成長の目標設定と評価をする
  • 定期的なコミュニケーションとフィードバックのために、直属の部下と 1on1 を実施する
  • 将来のキャリア成長を考慮して、エンジニアにプロジェクトと役割を割り当てる
  • 優秀なエンジニアを採用する

EMとしての役割を把握するテクニック

経験の浅いEMの場合、課題がわからない、何に注力すれば分からない、あれこれ行動するわりに成果が上手くだせないことがあります。

そういう場合は、上司と現状において求められる期待値やレベル感をすり合わせて、何に注力していくと良さそうかを話し合うことがとても大切になります。上司はマネジメント経験が豊かで立場上も視座が高くなるので、より適切なアドバイスをもらうことができるでしょう。

エンジニアリングマネージャーのしごと

エンジニアリングマネージャー(EM)の具体的な仕事内容について説明します。
EMの役割は「開発チームの成果を最大化すること」と「開発組織をスケールさせること」です。
ここでは、その役割を達成するために必要な仕事内容を中心にまとめています。

留意点として、ここに記載されている仕事内容を一度にすべて実施することはできません。チームの現状や目標から逆算して「今、自分は何に注力するべきか?」という逆算思考が大切になってきます。

ピープルマネジメント

ピープルマネジメントでは、メンバー個人の成功と組織の成功の両立を目指していきます。 個人の成果や成長を支援することで、チームの成果を持続的に高めていきます。

  • 1on1
    • 定期的に1対1のミーティングを実施して信頼関係を構築する
    • ティーチング、コーチング、メンタリングなどを通して個人の成功を支援する
    • 詳細についてはEMと1on1
  • メンバー理解
    • メンバーの理解を深め、信頼関係や親近感を構築する
    • 個人の理解が深まることで、より効果的なピープルマネジメントができる
  • キャリア開発
    • キャリアアップについて定期的に話し合い、実現に向けて支援していく
  • アサイン・委譲
    • キャリア、成長、成果のバランスを見つつアサインをする
    • また、実行権限を委譲して、メンバー成長やチームのスケールを促進する
    • 詳細についてはEMと委譲
  • 目標管理
    • 目標設定を通して個人と組織の目標の期待値をすり合わせる
    • また定期的に目標の進捗を話し合い、達成に向けて支援していく
    • 詳細についてはEMと目標管理
  • 動機づけ
    • モチベーションの向上や不安や不満の解消を進める
    • メンバーの成果や満足度が高まる
  • 成果支援
    • 優先度の整理、課題把握、課題解決などを支援してメンバーの成果を高める
  • 育成
    • メンバーと一緒に研鑽が必要な領域を探す
    • そして、挑戦する機会の提供やコーチングなどを通して成長を促す
  • フィードバック
    • 継続的にフィードバックをすることでメンバーの成果や成長を促す
    • 日頃からメンバーを観察し、具体的なフィードバックを与えていく必要がある
  • 評価
    • バリュー、成果、スキルの1次評価をする
    • 評価を通して、メンバーの気づきを促し、今後の方向性を考え、成長を促す

チームマネジメント

チームマネジメントは、チームをリードしてチームの成果や満足度を高めていくマネジメント手法です。
EMとしては、今までエンジニアとして培った技術やプロジェクト管理などのスキルや経験を活用しながら、チームビルディング、ロードマップの策定・実現、開発手法や開発プラクティスの導入・改善に関与することで、チームの成果を高めていきます。

  • チームの方向づけ
    • チームの目標を設定し、計画、体制、プロセスを策定・運用する
    • プロダクトマネージャーと協力し、ロードマップの策定・実現をリードする
  • チームビルディング
    • 心理的安全性が高く満足度が高い効果的なチームを形成し維持する
  • チームの成果を促進する
    • 生産性と品質の測定、開発プロセスや開発手法の導入・改善を行う
    • チームのボトルネックの排除や成果をだしやすい環境を作っていく
  • 社内ネットワークを広げる
    • 社内のチーム間の協働を促す
    • チームがより効果性を高めるための情報を集める

開発組織に対する貢献

組織開発自体は、CTO/VPoE、複数チームをマネジメントするEMが中心になって進めていくことが多いです。
その中で、1チームをマネジメントするEMは、組織の状況に応じて、採用や配置などを中心に組織開発に貢献することが多いでしょう。

  • 採用
    • エンジニアの採用に貢献することで、組織の成長に貢献する
  • 配置
    • 組織全体、チーム、個人のバランスを考えながら、適切な人材配置を提案する

エンジニアリングマネージャーのキャリア

多くのソフトウェア開発の企業では、ソフトウェアエンジニアのキャリアラダーとしては2つのパスがあります。

  • テクニカルトラック:技術を磨いてキャリアを高める(IC: Individual Contributerとも呼ばれる)
  • マネジメントトラック:マネジメントする対象を広げてキャリアを高める

エンジニアのキャリアラダーの例

テクニカルトラック

テクニカルトラックでは、技術的なスキルを磨いて影響力を広げていくことでキャリアを高めていきます。

  • エンジニア Ⅰ(ジュニアレベル)
  • エンジニア Ⅱ(ミドルレベル)
  • エンジニア Ⅲ(シニアレベル)
  • スタッフエンジニア
  • シニアスタッフエンジニア
  • プリンシパルエンジニア

マネジメントトラック

マネジメントトラックでは、技術的なスキルを土台にし、組織・チーム・人のマネジメントをしていきます。 その中で、エンジニアマネージャーはマネジメントトラックの入り口に位置しています。

マネジメントトラックでは、マネジメントする対象を1つのチームから複数チーム、開発組織全体と広げていくことでキャリアを高めていきます。

  • エンジニア Ⅰ(ジュニアレベル)
  • エンジニア Ⅱ(ミドルレベル)
  • エンジニア Ⅲ(シニアレベル)
  • エンジニアリングマネージャー(1つのチームを管理する)
  • エンジニアリングディレクター(複数チームを管理する)
  • VP of Engineering(開発組織全体を管理する)
  • CTO

カンパニー制事業部制などを実施するぐらいの組織規模になると、CTOやVPoEが事業ごとに複数いることもあります。

エンジニアリングマネージャーのなり方

EMになるには、マネージャーができるポジションがあることと、会社からチームをマネジメントできるという信頼を得る必要があります。

マネージャーができるポジションにおいては、エンジニアリングマネージャーは不足している傾向があるので、そういった環境を見つけるのはあまり難しくないでしょう。

会社からチームをマネジメントできる信頼を得るには、シニアレベルのエンジニアスキルを土台にしつつ、チームのマネジメントの実績を小さく作っていくことが大事です。

エンジニアリングマネージャーになるための4ステップ

ここでは、理想的なEMになるためのステップを説明します。

  1. シニアレベルのエンジニアのスキルと経験をつける
    • EMのキャリアラダーを見てもらうとわかりますが、EMになるには、シニアレベルのエンジニアスキルや経験が必要になります。
    • まずは、エンジニアとしてのスキルや経験を磨きます。
  2. 社内でエンジニアとしての成果と信頼をつくる
    • エンジニアとして成果をだし、会社や周りの人から認めれて信頼される必要があります。
    • 必ずしも社内でトップレベルのスキルが必要ではありませんが、上司やチームメンバーに人柄や技術で信頼されている状態をつくります。
  3. 可能な範囲でチームや人のマネジメントの実績をつくる
    • ここからは、明確に上司にEMになりたいと相談し、一緒に並走していきます。
    • メンター、チームリーダー、1on1などの役割を少しずつ上司から委譲してもらいます。
    • その結果として、会社、上司から「この人にならチームや人の管理を任せても大丈夫そう」という信頼と実績を得ます。
  4. マネジメントするポジションがある
    • 最後に実際にあなたがマネジメントをするチームがいることが必要です。
    • ここは、実力だけでなく運とタイミングもかなり重要になってきます。

補足:ピーターの法則と対策

ピーターの法則は、階層型の組織において、従業員はそれまでの成功にもとづいて出世していき、有能な人でも自分が無能なレベルになるまで出世してしまい、結果として組織の各階層が無能な人で埋め尽くされてしまうという法則です。

このピーターの法則の対策として、昇進先のポジションで成果がだせることが証明された場合にポジションを認める形で昇進をするようにします。
こうすることで、EMになるためには、EMの役割を積極的に引き受けることで、EMとしての実績づくりや昇進しても成果がだせそうということを会社やチームなどに示すことが有効です。EMにならないとできないこともありますが、EMになる前からもやれることはあるので、上司と相談しながら委譲をしてもらうとよいでしょう。