Paytner Tech Blog

ペイトナーのテックブログです

フロントエンドのテストのダミーデータ作成ならrosieがおすすめ

はじめに

ペイトナー請求書のフロントエンドを主に担当している @fuqda です。 本稿では、ペイトナー請求書のフロントエンドのテストコードを書きやすくするために最近導入したrosieというライブラリが便利だったので、そちらのご紹介をさせて頂きます。

この記事の対象読者

  • Jestなどで使用するダミーデータを毎回ベタ書きして疲弊している方
  • RSpecのFactoryBotのようなライブラリがフロントエンドにも無いのかと探している方

rosieとは?

Ruby on Railsでテストコードを書く際のダミーデータ作成ライブラリとして有名なFactoryBotにインスパイヤされたJavaScript用のライブラリです。
https://github.com/rosiejs/rosie

rosieロゴ画像.jpeg (24.3 kB)

rosieのセットアップ手順

1. rosieと型定義のインストール

$ npm install rosie @types/rosie -D

2. ファクトリーの定義ファイルを追加

/test/user.factory.ts に Userオブジェクトのダミーデータを定義します。

※ 注意
公式の書き方にならって、 import { Factory } from 'rosie'; と書くと Factory not found in 'rosie' という型エラーが出たので、import rosie from "rosie"; してから const Factory = rosie.Factory; と変数に展開する形で実装しています。

import rosie from "rosie";
const Factory = rosie.Factory;

Factory.define("User")
  .sequence("id")
  .attr("name", "山田 太郎")
  .attr("age", 18)
  .attr("email", "sample@example.com")

3. 各ファクトリーのエントリーポイントとなるファイルに集約

/test/jest.factories.ts というファイルに各ファクトリーを集約します。

// Factoryを追加するたびにこのファイルにimportする
import("./user.factory");

4. グローバル設定と型定義を追加する

/test/jest.helpers.ts に型定義を追加 & 全 *.spec.ts ファイル内で、ファクトリーが使えるようにします。

// 中略
import rosie from "rosie";
const Factory = rosie.Factory;

declare global {
  // 中略
  var factory: typeof Factory; // eslint-disable-line no-var
}

// 中略
global.factory = Factory;

5. Jestの設定ファイルにファクトリの定義を反映

jest.config.ts のセットアップファイルに /jest.helpers.tsjest.factories.ts を追記します。

module.exports = {
  // 中略
  setupFiles: ["./test/jest.helpers.ts", "./test/jest.factories.ts"],
  // 中略
};

rosie導入前後のBefore / After

実際に導入Before / Afterをコードで比べてみてみましょう!

Before

import { mount } from '@vue/test-utils';
import AccountInfo from '@/components/AccountInfo.vue';

describe('AccountInfo', () => {
  test('スナップショットテスト', () => {
    const name = "山田 太郎";
    const age = 18;
    const email = "sample@example.com";
    
    const propsData = {
      user: {
        name,
        age,
        email,
      }
    };
    
    const wrapper = mount(AccountInfo, { propsData });
    expect(wrapper.element).toMatchSnapshot();
  });
});

After

import { mount } from '@vue/test-utils';
import AccountInfo from '@/components/AccountInfo.vue';

describe('AccountInfo', () => {
  test('スナップショットテスト', () => {
    const wrapper = mount(AccountInfo, {
      propsData: { user: factory.build("User") }
    });
   expect(wrapper.element).toMatchSnapshot();
  });
});

終わりに

さて、いかがだったでしょうか? サンプルは小さなテストでしたが、コードが増えて来るとだんだん毎回ダミーデータをベタ書きするのが億劫になってくると思います。
そんな時にrosieを使えば、サクッとダミーデータを定義して、本質的なテストコードの実装に集中出来るのでおすすめです。
rosieを使って面倒なダミーデータの用意をスキップしてみてはいかがでしょうか。

ペイトナー請求書のフロントエンドにスナップショットテストを導入した話

はじめに

ペイトナー請求書のフロントエンドを主に担当している @fuqda です。 本稿では、ペイトナー請求書のフロントエンドの品質改善の一つとして、最近実施したスナップショットテストの導入についてご紹介させて頂ければと思います。

この記事の対象読者

  • Vue.js / Nuxt.jsでJestのスナップショットテストを実装する方法について関心がある方
  • テストコードがないフロントエンドにこれから自動テストを導入しようとしている方

スナップショットテストとは?

スナップショットのテストはUI が予期せず変更されていないかを確かめるのに非常に有用なツールです。 https://jestjs.io/ja/docs/snapshot-testing

Jestの公式ドキュメントにも記載があるようにHTML要素の差分を検査し、違いがあれば失敗にするテストのことです。 なお、CSSのスタイル崩れなどの検知は出来ないので、そういった用途にはビジュアルリグレッションテストの導入を検討する必要がある点は注意しましょう。

導入前の状況

  • コンポーネントのテストが無いのでレビューコストが高い
    • 自動テストで担保すべき動作確認も手動で行う必要がある
  • ライブラリのアップデートや軽微な変更だと油断しているとデグレしてしまう
    • Nuxt.jsのバージョンアップでコンポーネントの自動読み込みの仕様が変わったことで、特定のコンポーネントが読み込まれなくなっていたが、気付けずリリースして障害を出してしまった...

コンポーネントのスナップショットテスト

※ Jestなど必要なパッケージはすでにインストール済みの前提で進めます
※ 実際のコンポーネントはもっと複雑ですが、あくまで例なのでご容赦ください

テスト対象のファイルの例

<template>
  <div>
    <p>{{ text }}</p>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "@nuxtjs/composition-api";

export default defineComponent({
  setup() {
    const text = ref('スナップショットテスト');

    return {
      text,
    }
  }
});
</script>

テストコードの例

import { shallowMount } from '@vue/test-utils'
import IndexPage from './index.vue';

let wrapper: ReturnType<typeof shallowMount<Vue>>;

describe("〇〇の場合", () => {
  beforeEach(() => {
    wrapper = shallowMount(IndexPage);
  });
  it("スナップショットテスト", () => {
    expect(wrapper.element).toMatchSnapshot();
  });
});

上記の例では、shallowMountしたコンポーネント対して、 toMatchSnapshot() を実行することで、キャプチャ結果と現在のHTMLを比較しています。

初回実行時は、テストファイルと同じ階層に __snapshots__/<テストファイル名>.snap のスナップショット結果ファイルが生成されます。 そのファイル作成後は、前回のキャプチャとの差分を元に差分があればテストが失敗するようになります。

差分がある場合は、以下のようにテストが失敗します。

$ npm run test pages/www/index.spec.ts

> www-frontend@1.0.0 test
> jest pages/www/index.spec.ts

 FAIL  pages/www/index.spec.ts
  〇〇の場合
    ✕ スナップショットテスト (8 ms)

  ● 〇〇の場合 › スナップショットテスト

    expect(received).toMatchSnapshot()

    Snapshot name: `〇〇の場合 スナップショットテスト 1`

    - Snapshot  - 1
    + Received  + 1

      <div>
        <p>
    -     スナップショットテスト
    +     スナップショットテストが失敗するテキスト
        </p>
      </div>

       9 |   });
      10 |   it("スナップショットテスト", () => {
    > 11 |     expect(wrapper.element).toMatchSnapshot();
         |                             ^
      12 |   });
      13 | });

      at Object.<anonymous> (pages/www/index.spec.ts:11:29)

スナップショット結果を更新したい場合は?

  • 差分を更新したい場合は、 npm test -- -u のコマンドで __snapshots__/<テストファイル名>.snap のファイルを更新することが出来ます!

スナップショット導入時にハマったこと

  • nuxt-svg-loaderを使ってSVG画像を描画している部分をJest実行時にレンダリング出来ない

解決法

image.png (173.5 kB)

const VueTemplateCompiler = require("vue-template-compiler");

module.exports.process = (svgSource, _) => {
  const result = VueTemplateCompiler.compileToFunctions(`${svgSource}`);

  return {
    code: `module.exports = { render: ${result.render} }`,
  };
};
module.exports = {
  // 中略
  transform: {
    // 中略
    "^.+\\.svg$": "<rootDir>/svgTransform.ts",
  },

導入後の状況

CIでテストがパスしなければfailするようになったので以前より表示関連のバグを検知しやすくなりました。 以前はCIで自動テストが動いてなかったのもあり、GitHubのPRを開いてCIが落ちていればデグレに気付けるだけでだいぶ動作確認コストは減ったように思います。

jest-ci-result.png (72.0 kB)

終わりに

意図しない変更差分によるデグレをお手軽に検知するための第一歩としてスナップショットはおすすめです。 今回はテストの対象にNuxt.jsのコンポーネントを取り上げましたが、スナップショットテストはReactなどのその他のフレームワークでも活用出来ます。 まだテストコードが無くて何からテストを始めていいかわからないという方も、手始めにスナップショットテストから始めてみてはいかがでしょうか。

「コード品質?レビュー効率?いや、PR数だ!!!」

開発生産性 Advent Calendar 2022 16日目の記事です。

はじめに

ペイトナー株式会社の脇田(@shimpeee_)です!『ペイトナー ファクタリング』開発チームでエンジニアリングマネージャー兼スクラムマスターとして、開発生産性と日々向き合っています。

「コード品質?レビュー効率?いや、PR数だ!!!」これは、他の誰でもなく、半年前の自分に声を大にして伝えたい叫びです。

「PR作成数をKPIにすると良い」とは知っていましたが、実は勘違いしていました。

コード品質やレビュー効率が改善された結果、PR作成数が増えると思っていました。ですが、実際は逆でした。

PR数を増やそうとする(つまり、 PRサイズを小さくする)ことで、レビュー効率が改善され、コード品質も高まっていくのです。

本記事は「PRサイズが大きいことが、生産性を落としている全ての元凶だったのか・・・!」と気づくまでの物語となっております。

僕は半年という長い期間を経てこの事実に気づくことができましたが、同じだけの時間を無駄にする人が少しでも減るようにという想いで書きました。

入社当時の状況

入社して開発チームに入ってすぐ肌で感じたのは、「コードレビューが明らかにボトルネックになっている」ことでした。Findy Team+を導入し生産性可視化を行なっていますが、レビューボトルネック問題は、変更リードタイムの長さにも表れていました。

現状把握

レビューがボトルネックになっていることはわかりました。その原因を深掘りしました。

その結果、一次レビュー後、実質チームのテックリードでもあるCTOによる最終コードレビューでの手戻りが多いことがわかりました。

どんな理由で手戻りが発生しているのか

直近数十件分のPRに目を通し、手戻りの理由を分類すると大きく①コード品質に関するもの ②仕様に関するもの の2つに分けられました。

そして、チケット作成〜リリースまでの開発全工程のフェーズごとに要素分解し、レビューのボトルネックになっているコード品質向上・仕様の認識齟齬や考慮不足に効きそうな部分を探しました。

スクリーンショット_2022-12-14_1_39_25.png (103.1 kB)

↑実際に分解で使ったロジックツリー

やったこと

停滞タスクの解消

まず、レビュー工程で止まっているタスクが数十件になっていたので、それを全て消化しようと決めました。

停滞しているところにどんどんレビュー待ちのタスクが追加され、リードタイムが伸び、レビューで指摘事項があって修正しようと思ったら時間が経ちすぎて思い出すのに時間がかかり、さらにリードタイムが伸びて停滞し、、、という悪循環を断ち切りたかったためです。

結局、最終的にほぼ全てが消化されるまでに2〜3ヶ月かかりました。それだけ溜まっていたということですね。

コード品質・レビュー効率向上施策

停滞タスクの解消をしたとしても、その後同じやり方をすればあっという間に元の状態に戻ってしまいます。

停滞タスク解消期間に、コード品質・レビュー効率向上の施策として

  • ペアプロ・ペアレビューの導入
  • 技術書輪読会の開始
  • 設計レビュー導入
  • スクラムの導入
  • レビュワー増員
  • レビューフロー改善

など、他にも細かいことを挙げればキリがないほどたくさんの取り組みを行ないました。

結果

「1人あたりPR作成数」と、「変更リードタイム」を評価指標として、半年間の結果は以下のようになりました。

  • 一人あたりPR作成数
    • 新規タスクストップ期間を経て、やや上昇傾向
  • 変更リードタイム
    • 短期ではバラツキが非常に大きく、長期スパンでは改善も悪化もしていない

一人あたりPR作成数、上がってはいるけど・・・

一人あたりPR作成数はたしかに上昇傾向にありました。しかし、その要因を分析してみると、気になる点が。。。

Four Keysの一つ、「変更障害率」が大きく悪化していました。直近の大きなリリースで仕様不備が見つかり、何度かリバートしたことが直接の要因です。

その切り戻しのためリバートPRが多く作られた結果、一人あたりPR数が増加していました。つまり、純粋な価値提供をしているPR作成数は伸びていませんでした。。

結果まとめ

まとめると、「1人あたりPR作成数」「変更リードタイム」ともに改善されなかった、という結果でした。

多くの施策を推進してきた立場としては、正直かなりショッキングな事実です。。

意外な結果だった?

開発者体験、上がってますけど?

この事実をメンバーに話すと、意外だという反応をされました。肌感覚として、開発者体験は上がっているとのことでした。

開発者体験上がっていると感じる部分を具体的に聞いてみると、以下が出てきました。

  • レビューフローの改善により、レビューのレスポンスが早くなっている
  • タスクを適切な粒度で分割することにより、進捗が見えやすくなったり、優先度を付けやすくなった
  • スクラムの枠組みの中で振り返りを開始して、1週間単位で改善のサイクルが回るようになり、日々感じる負がすぐに解消されるようになった
  • スクラムにおいて「スプリントゴール」を定めるようになり、同じ方向を向いて開発を進められるようになった
  • ...

僕自身もスクラムマスターとしてチームに入っているので、肌感としては合っています。

しかし、主要指標には改善が見られませんでした。特に上の二つ、「レビューのレスポンスが早くなっている」「適切にタスク分割できている」は、「1人あたりPR作成数」「変更リードタイム」にもダイレクトに効いても良さそうなはずです。

ちゃんと理由があった

次の打ち手を考えるべく、現状の課題を深掘りします。 各種指標を見ていると、「1PRあたりの変更行数」が半年前と変わっていないことが分かりました。

仮説として考えたのは、「適切なタスク分割ができたチケットはリードタイム短くリリースまで持っていけるが、タスクが大きいまま進めてしまったものがチーム全体の生産性を下げている」です。

実際メンバーにヒヤリングしてみると、「小さいPRが増えてレビューもやりやすくなったが、たまにでかいPRがあってしんどい」という声がありました。

これも実感と合っていて、1000行を超えるようなPRも散見されます。しかし、これらの大半はスクラム導入以前に着手したチケットであり、スクラムのリファインメント内でのチケット分割議論を経由していないものでした。

つまり、スクラム開始以降に着手したチケットは正しく分割され、小さい単位のPRで開発できている、ということになります。これは、間違いなく改善が進んでいるといえます。

このことから、「PRサイズ」こそがリードタイムや開発者体験を決める決定的な因子であると特定しました。

これからやること

何をやる?

スクラム開始以降は適切にタスク分割でき、PRサイズを小さくできていることが分かりました。しかし、実際にデータを見ると、1PRあたりの変更行数は200行くらいあります。

他社の取り組みを見ていると、「1PRの変更行数は100行以下」を目安とする会社が多いようです。さらなる生産性改善のため、まずはこの水準を目指したいと思います!!!

どうやってやる?

チケット分割においてかなり手応えは感じているものの、現状のやり方ではある程度限界も見えているので、他の打ち手も検討しています。

具体的な方法の一つとしては、「フィーチャーフラグを使ったトランクベース開発」に挑戦したいと思っています!

codezine.jp

現在、FindyTeam+の運用サポートのため月一ペースでFindyさんとMTGの場を設けていただいています。

そこで聞いたFindyさんの開発手法が「機能として不完全な状態でもガンガンmainにマージして本番にデプロイする」というものでした(Findyさんはトランクベース開発という言葉を使っていたか定かではありませんが、恐らく同義だと解釈しています)。

そして、既存のUXに影響を与える部分はフィーチャーフラグを使って隠していきます。

この開発手法が実現できれば、間違いなくPRサイズを小さくすることができ、PR作成数は増え、リードタイムも短くなっていくでしょう。

ただ、「不完全なコードを本番にマージする」というチームとして経験のない新たな試みです。 リスクを適切にコントロールしながら進めるため、現在は他社事例等参考に運用方法を整備中です。

この開発手法を取る上での難しさとして、「未完成のコードをマージしていくという文化作りが大切」とFindyさんも仰っていました。 エンジニアだけでなく、PMサイドも含めて合意形成必要なところなので、ステークホルダー巻き込みながら推進していきたいと思います。

まとめ

半年間の取り組みは、チーム全体の結果として主要指標に跳ね返ってはきませんでしたが、やったことは確実に効果が出ていることも確認できました!チームとしてのモメンタムを感じます!

効果の出た取り組みは継続しつつ、新たな取り組みも実施することで、さらに生産性高く開発者体験のよいチームを目指してがんばっていきます!!!

余談

本記事では、半年間の試行錯誤の結果を共有しました。このような継続的な改善活動の結果、直近1年ほどの取り組みが評価され「Findy Team+ Award2022」に選出いただきました 🎉

今後も、引き続き生産性の高い開発組織を目指して全社で取り組んでいきます!!!

終わりに

最後まで読んでいただきありがとうございました!!!

ペイトナーに少しでも興味を持っていただけましたら是非、ペイトナー 採用情報 をご覧ください!!

現在ペイトナーでは、以下ポジション積極採用中です!!!

  • VPoE
  • リードエンジニア

paytner.co.jp

「マネジメントの型」がある会社にEMとして入社しました

Engineering Manager Advent Calendar 2022 15日目の記事です。

はじめに

こんにちは!ペイトナー株式会社で1人目エンジニアリングマネージャーをやっている脇田(@shimpeee_)です。2022年5月にペイトナーに入社しました。マネージャー歴2年目の、新米マネージャーです。

ペイトナーでは、会社として「マネジメントの型化」に取り組んでおり、そのおかげで新米マネージャーの自分も経営陣と共通認識を持ちながらスピード感を持って日々の業務と向き合うことができています。

本記事では、ペイトナーでマネジメントの教科書としている「EVeMのベンチャーマネジメント理論(自分が勝手にそう呼んでいる)」の素晴らしさについて熱く語ってみようと思います。

マネジメントの目的とは

この章では、これまで持っていた自分なりのマネジメントに対する解釈や思いについて触れたいと思います。

いいマネージャーとは?

そもそも、「いいマネージャーの条件」とは何なのでしょうか。

自分がマネジメントするようになる以前から、とても謎でした。 思い返すと、これまでの社会人人生で見てきたマネージャーの中で、上からも下からも厚い信頼を寄せられ「あの人はいいマネージャーだ」と言われている人はいました。

しかし、なぜあの人は「いいマネージャー」だったのか?「いいマネージャー」の要素とは何なのか?を自分なりに言語化することはできていませんでした。

それはつまり、「マネジメントの目的」が言語化できていないことと同義になります。

抽象的すぎる

マネジメントの目的を理解するのが難しい要因として、本や先人の言葉が「抽象的すぎる」ことが大きいと感じます。

マネジメント経験のある人たちとの会話や、マネジメント系の本を読んだ結果、「組織の成果を最大化させる」というのが自分なりに出した「マネジメントの目的」の答えの一つでした。

とはいえ、メンバーを酷使し24時間365日働かせた結果、短期的に「組織の成果が最大化」している状態を作ることはできます。当然ながら、これはいいマネージメントとは言えなそうです。

また『エンジニアリング組織論への招待』では、"不確実性をコントロールすることそのものがエンジニアリングである"と言ってました。つまり、エンジニア組織のマネジメントにおいては、「チームの不確実性をコントロールする」ことがマネージャーの役割なのかもしれません。

しかし、仮にこれらが答えだとして「じゃあ日々の業務でどうすればよいのか?」があまり見えてこないなーというのが率直な感想です(僕の力量不足・勉強不足なだけな気もしますが)。

具体的すぎる

一方、矛盾するようですが、本や先人の言葉が「具体的すぎる」ことも理解を難しくさせている要因です。

Twitterを見ていると、他社の組織運営の事例がたくさん流れてきます。しかし、それらのほとんどは個別具体の事象についての取り組みであり、マネジメント全体におけるほんの一部です。

最近発売されて話題になった『エンジニアリングマネジメントのすべて』も読みました。周りの評判通り確かにいい本でした。それでも自分にとっては「面白いけど、これも具体例の一つでしかないよなあ。。」と、モヤモヤが完全に晴れることはありませんでした(僕の力量不足・勉強 ry)。

やっぱり、よう分からん

つまり、「マネジメントナンモワカラン」というのが、ペイトナー入社以前の自分でした。

EVeMのマネジメント

「マネジメントナンモワカラン」な自分でしたが、ペイトナーに入社し「EVeMのベンチャーマネジメント理論」と出会います。

株式会社EVeMは、ベンチャーマネージャー育成プログラムなどを手掛ける会社です。私の入社タイミングで、ちょうどEVeM社主催のマネジメント研修に経営陣が参加していました。

研修は、最終的なアウトプットとしてスプレッドシート全27シートで構成される「マネジメントシート」を作り上げ、研修後にそれを現場に落とし込むという内容です。

この研修のベースになっているのが、『急成長を導くマネージャーの型 ~地位・権力が通用しない時代の“イーブン"なマネジメント』という書籍です。

個人的に、人生ベスト3に入るくらい素晴らしい本です。(ベスト3といっても他の2冊はパッと思いつかないので、実質1位かも)。

特に良かった点を挙げると、以下の3点になります。

  1. 圧倒的なwhyの言語化
  2. 抽象と具体の絶妙なバランス
  3. シンプルに本としての読みやすさ

1. 圧倒的なwhyの言語化

とにかく、全てにおいて「なぜ必要か」が言語化されています。

  • なぜ目標設定が必要なのか
  • 1on1の目的は何か
  • なぜ人事評価が大切なのか

など、マネージャーであれば必ずといっていいほど関わる仕事の1つ1つについて、丁寧に説明されています。

例えば、「1on1の目的は?」と聞かれたら皆さんは何と答えますか。

メンバーの不安解消?課題吸い上げ?メンタルケア?フィードバック?もちろんどれも要素の一つではあると思います。

本書では、1on1の目的は「メンバーの目標達成支援」と断言されています。個人のパフォーマンスが最大化するような挑戦的な目標を設定し、目標に対しての達成支援をする場が1on1というわけです。

このように、圧倒的なwhyの言語化によって、全ての業務に意味があり重要であることを、マネージャー自身が腹落ちできるとともに、メンバーにも伝えやすくなります。

2. 抽象と具体の絶妙なバランス

マネジメントを理解するのが難しい要因として、「抽象的すぎる」ことと「具体的すぎる」ことを述べました。

この本はそのバランスが絶妙で、「目的や重要性を理解し、明日から即実践できる」という内容になっています。

先ほどの1on1の例でいうと、メンバーの目標達成支援のために3つのコミュニケーション技術(ティーチング・コーチング・フィードバック)を駆使せよとあります。

  • ティーチング → 知らないことや、足りないことを相手に教える
  • コーチング → 相手に質問をし、相手に気づきを与え、相手を導く
  • フィードバック → 相手が気づいていない客観的な事実を伝える

そして、3つの技術は全て使える必要があり、場面によって使い分けることができなければなりません。3つの技術の使い方・使い分けの方法も、サンプルとともに非常に具体的かつ簡潔に書かれています。まさに「明日から即実践できる」内容です。

3. シンプルに文章としての読みやすさ

内容は半端なく濃いのですが、文章がめちゃくちゃに読みやすいです。平易な表現で、かつ図表を駆使しながら「最小限の文字数でとても多くの情報量が詰まっている」、そんな本です。

その読みやすさと内容の面白さとの相乗効果で、1ページ目から興奮が止まらず2hくらいで一気に読み終えてしまったのが記憶に新しいです。

マネジメントの役割

ここまで本の魅力について語ってきましたが、冒頭でお話しした「マネジメントの役割」についてもバッチリ言語化されています。ベンチャー企業におけるマネジメントの役割は、大きく4つに分かれます。

  1. 経営からオーダーされた成果を残す
  2. 人的資産を維持・活用する
  3. 人を育てる
  4. 会社の中でチームを機能させる

1. 経営からオーダーされた成果を残す

ベンチャー企業においては、マネージャーは経営陣と直接会話することが日常茶飯事です。「経営陣が求めている」成果を残すことが求められます。

ペイトナーは執筆時点(2022年12月)で社員数15名。この規模であれば当然、マネージャーである自分が経営層と直接会話することは実際にとても多いです。著者の長村さん曰く、100〜200名規模でもそれは当たり前に発生するようです。これは、大手とベンチャーのマネージャーの役割の大きな違いの一つですね。

2. 人的資産を維持・活用する

ベンチャー企業はその事業展開の速さゆえ、組織状況もめまぐるしく変化します。その過程で、雇用形態問わず正社員、業務委託、副業といった様々な方がチームにジョインすることになります。

その人たちの活用を考えることを怠ってしまうと、たちまち「遊休資産」が増えてしまいます。ベンチャーに無駄なお金を使う余裕はないので、マネージャーは人的資産の遊びを生むことなく、フルで活用できるよう日々思考する必要があります。

3. 人を育てる

ベンチャーが現状維持することなく絶えず新しいことに挑戦し続けるためには、メンバーの育成がマストです。新しいことを仕掛ける度に採用していては費用もバカにならないですし、採用までのリードタイムやオンボーディング期間含めると半年〜1年スパンの取り組みです。マネージャーの後任人材、新しいことに異動させて任せられる人材をチームで育てなければなりません。

メンバー育成は会社として取り組んでいくことではありますが、「実際に育成を行うのはマネージャーにしかできない」と著者は言います。現場で直接メンバーと接しているマネージャーが、責任を持ってチームメンバーの育成を行っていかないといけないわけですね。

4. 会社の中でチームを機能させる

創業当初は少人数でも、会社の成長とともに人が増え、機能分化が進みチームが乱立するようになります。ベンチャー企業であっても、チームが複数存在する以上社内調整は発生します。

毎度毎度経営陣がチーム間調整に入っていてはスピード感は損なわれます。だからこそ、現場のマネージャーの役割に「会社の中でチームを機能させる」調整業務が入ります。

「スタートアップでも社内調整は必要」は、実感としても合っています。私は大手からスタートアップに来たのですが、大手で培った社内調整能力は現職でも非常に役に立っていると感じます。大手で調整業務に追われていた時は「調整ばっかりして、こんな能力どこで役に立つんだ」と思っていたものですが、ムダな経験はないんだなとしみじみ感じます。

共通言語があるメリット

ここまで述べてきたような、圧倒的に言語化されたマネジメントの型を経営陣と共通言語として使いながら、日々業務にあたっています。

マネジメントの共通言語を持つメリットをあげると、当然すぎるのであえて書くまでもないのですが、「意思決定のスピードが上がる」ことが最大のメリットかなと思います。

「マネージャーとして大事にすべき価値観」はすべてベンチャーマネージャーの本に書いてあり、いちいち経営陣とすり合わせなくともマネージャーである自分が実行に移すことができます。

「行動指針」が会社の社員として大事にすべき価値観であるならば、それのマネジメントバージョンです。

経営陣の中ではCTOのかずまさんと会話する機会が最も多いですが、「ベンマネ的に言うと〜」というキーワードが会話のあらゆる場面で登場します。それくらい、共通言語として浸透しています。

共通言語を持つことで、組織として意思決定のスピードが早い状態を作りして出すことができています。

まとめ

EVeMのベンチャーマネジメント理論の素晴らしさを語るだけの記事になってしまいました笑

繰り返しになりますが、マネジメントの型があること、その型を共通言語として持っていることは、ペイトナー組織の大きな強みの一つであると感じます。

おわりに

最後まで読んでいただきありがとうございました!!!

ペイトナーに少しでも興味を持っていただけましたら是非、ペイトナー 採用情報 をご覧ください!!

現在ペイトナーでは、以下ポジション積極採用中です!!!

  • VPoE
  • リードエンジニア

paytner.co.jp

駆け出しエンジニアインターン生が人生初テックカンファレンス"RubyKaigi"に参加した感想

はじめに

ペイトナーでエンジニアインターンをしています田崎です!

私は人生で初めて参加したテックカンファレンスであるRubyKaigi2022についての感想や自分が考えたことについてお話したいと思います! 今回はRubyKaigiのセッションの中でもTrick2022とContribute to Rubyについて取り上げたいと思います。

Trick2022

https://rubykaigi.org/2022/presentations/tric.html#sep08

Trickとは

Trickとは

  • T’ranscendental(霊的領域に関する、世俗を超越した、超絶技巧)
  • R’uby(ルビー)
  • I’mbroglio(極めて混乱した、恥ずかしい事態)
  • C’ontest(コンテスト)
  • for RubyK’aigi

から取った名前であり、Rubyで記述された複雑かつ面白いコードを発表し競い合うプログラミングコンテストです。

私がRubyに初めて触れたのはこのペイトナー社にインターンとして参加したことがきっかけで、初めからプロダクトを作ることを目標に勉強していました。ですので私は常に綺麗なコード、読みやすいコードを書くことを意識していました。 しかし、このコンテストはむしろその逆で、私はとても驚くと共に一気に興味をそそられました。

私が特に感動したものはYusuke EndohさんがMost global 「最もグローバルで賞」を受賞した地球儀が廻るような作品です。https://github.com/tric/trick2022/tree/master/03-mame

地球儀が回って見えるところや、地軸の傾き、地図としてのディティールにもとても感動し、制限のある中でこのような美しい作品を作り上げられた技術力の高さに憧れを抱きました。地球儀をRubyで実装するという点もRubyコミュニティの広さを感じることができたような気がします!

Trick感想

発表されていたコードはどれも私では解読不可能でしたが、実行結果はとてもワクワクするようなものばかりでした。 自分がプログラミングを始めた頃を思い返してみると”Hello World”が出力されることに感動し、少しずつ勉強してジャンケンができるようになったりと、楽しく、色々な可能性を秘めていると感じさせてくれる存在としてプログラミングがあったと感じています。実務や研究でコードを書いていくうちに私はそのような童心を忘れていたのかもしれません。

Contribute to Ruby

こちらはRubyの開発者であるMatz氏(https://twitter.com/yukihiro_matz/) によるセッションでした。

導入

まずはじめに語られたのはRubyという技術に対する数々の意見?についてでした

Rubyスクリプト言語として良すぎる」 「スクリプト言語オブジェクト指向はいらない」 「Rubyは遅い」 「Rubyは死んだ」etc…

これらについてMatz氏はフェアではない意見に対して不満を持っているとおっしゃっていました。 機能やツールの不足などデータに基づいた批判はありだけれど、虎の威を借る狐のようにPythonなどを引き合いに出し批判するのは建設的ではないということです。 (お話の中ではPythonの威を借るユーザーとおっしゃっていました。)

真の価値について

では真の価値とは何なのか?そのことについて”y”で終わる英単語を挙げていました。

  • Productivity

Gemやフレームワークが充実することでRubyの価値がより高まっているとのことでした。

  • Community

これはMatz氏がRubyの価値の中で一番大切であるとおっしゃっていました。 現在Rubyコアチームが中心となって開発を進めるとともに、Gemの創造や使用というところでRubyの価値を実現しているとのことでした。

  • Joy

Matz氏はRuby使用者から感謝の言葉を向けられた時に喜びを感じるそうです。 Matz氏をはじめとする開発者の方だけでなくそのご家族が使っているサービスもまたRubyで作られているということも多くあり、そういった人々の生活の中で価値を創っているということを実感するときにも喜びを感じるそうです。

  • Money

Rubyを発表した当初はアメリカで30数人程度の集まりであり、その人々は面白そうというところから来た人が多かったそうです。しかし現在はビジネス的に必要だからということでコミュニティが拡大し、それによりRubyコミュニティでお金が回るようなったとおっしゃっていました。 現在は有名な企業、サービスでRubyが使われており、経済的な規模で見てもRubyが及ぼす影響も大きいと私も感じています。

このように価値を考えていく中で世界を広くみると 上であげたような数々の批判などのノイズは無視でき、これからも価値を生み出していく中で鍵となるのはコミュニティであり、Rubyに関わる人々のコントリビューションが大切であるとMatz氏はおっしゃっていました。

Matz氏が求めるコントリビューション

  • Publicity

Rubyコミュニティに参加している人にTwitterやブログなどで情報を広めてほしい Rubyの経験やテックブログ、サービスなどの成果物等の報告など

→これらが開発者の精神安定にプラスの影響するとのことです

  • Reporting Bugs/Feature Requests

バグや提案を共有してほしい

  • Fixing/Implementing

バグ修正や機能開発を行ってほしい

  • Documentation Update

プログラマはドキュメントを書くのがあまり好きじゃないため、ドキュメントが疎かになってしまうこともある。そのためドキュメントアップデートのプルリクエストや修正依頼等を出してほしい

  • Gems

Gemを公開してほしい

→Gemを公開しオープンソースに貢献することでリクルーティングにもプラスになる

  • Triage

月1回行われる開発会議において、リクエストを捌くときにイシューが多すぎてmerge時期が前後してしまったり、重要なものの見落としが生じてしまう。ので検討事項の優先順位づけや議事録、検討事項の管理をしてほしい

  • Translation

多言語に翻訳されているが十分ではない。ユーザーの母国語ドキュメントを作りたい

  • Conferences / Meetups

カンファレンスの立ち話などで刺激を受けることがあるのでRubyKaigiをはじめとするイベントに参加してコミュニティ活性化してほしい

  • Hiring Developers

企業が使ってRubyを使っているのならRuby開発のフルコミメンバーを用意してほしい

Contribute to Ruby感想

特定の技術について使用している人や詳しい人は身近にもいますが、その技術を作った人、ましてや、Rubyという世界的に使用されている技術の開発者のお話を聞けたということはとても貴重な経験でした。開発者ならではの悩みや今後の展望などとても濃い内容のお話を聞くことができて私もモチベーションをいただきました。

最後に

3日間開催されたRubyKaigiですが、どのトピックでも共通して言えることは「Rubyという技術が好きである」ということのように思いました。好きだからこそより良くしたい、深く勉強したい、Rubyを使って面白いものを作りたいなど、皆さん情熱を持って取り組まれているのだろうと感じました。私は今まではRubyの一使用者でしたが、このカンファレンスに参加した経験をもとに、コミュニティのメンバーとして活動していけたら良いなと思います。

【RubyKaigi2022】ブースを盛り上げるだけではだめ!?本気の振り返りをやって見えた、1つの大きな反省点。

ペイトナーでエンジニアリングマネージャーをやっている脇田(@kiwatchi1991)です。

今回は、RubyKaigi2022のプラチナムスポンサー&ブース出展企業としての振り返りを社内で行ったので、その内容について書きたいと思います!

どんなことやってた?

ブースでクイズをやっていました!!

1日目は技術顧問・前島さん(@netwillnet)作のクイズ、2、3日目は弊社エンジニア作のクイズで、3日間毎日違うものを用意し、連日大盛況でありました!!!

強烈(!?)なCMを流しました




RubyKaigiのスクリーンに巨大やっぷんが登場したときは、完全に異空間でした

振り返りやりました

総評

今回のRubyKaigiをスポンサー企業目線で振り返ると、

会社やサービスの紹介、最大の目的であった「採用」につなげるというところへの手応えは残念ながらあまり感じられませんでしたが、このような技術イベントへの出展は初だったのと、クイズでブースを盛り上げることはできたので「ペイトナー」という会社の認知拡大はできた!!

という総評でした。

実際にKPT方式で振り返りを行ったので、それぞれについていくつかピックアップします!

よかった点

ブースを盛り上げることができた!!!

クイズが想像以上に盛り上がり、連日ブースに足を運んでくださる方で大盛況といえる盛り上がりを見せていました!参加してくださった皆様、ありがとうございました!!!

2日目からは、Twitterで回答をツイートすると正解者の中から抽選で技術書やTシャツをプレゼントするキャンペーンを実施!当選者のみなさま、おめでとうございました!!!

noteさんの記事でも取り上げていただきました!ありがとうございます!!! engineerteam.note.jp

Rubyistのみなさんとの交流ができた!!!

各社ブース担当者の方々、弊社ブースに遊びに来てくれたたくさんのRubyistの皆様と交流できたことも、大きな収穫でした! 特に、2日目の夜はふらっと遊びに行った飲み屋さんがRubyistによる熱気でスゴいことになっていました。

たまたまカメラ向けたら皆さんこちらを向いてくださり、とても良い写真が撮れました。

会社としても、筆者個人としてもオフラインの技術カンファレンスには初参加でしたが、オフラインならではの密な交流は、非常に楽しいものでした。

チームの一体感を感じることができた!!!

現地参加した6人のうち5人はブース運営未経験だったので、3日間通じてトラブル続きで(笑)、良くも悪くもその場しのぎで何とか事なきを得るという経験を繰り返し、参加メンバー同士の絆はより深まった気がします!

昼はブースでバタバタして、夜はみんなで津の美味しいご飯食べて、文化祭みたいで楽しかった!!!

こちら、MatzさんとCTOかずまさん(@kazuman519)の記念写真。社名の入った旗を掲示用の土台に使うという即席っぷり(重みに耐えきれず何度も転倒)。現場でのドタバタを物語っています。

コミュニティの熱気を感じることができた!!!

初めてRubyKaigiに参加し、「あ、Rubyを実際に作っている人たちがいるんだ」ということを知りました(当たり前っちゃ当たり前ですが、私にとっては当たり前ではなかった)。 RubyKaigi以降は、普段の開発でRubyを触る際にもコミュニティの方々に想いを馳せるなんてこともあり、これまでとは一味違った感情でRubyという技術と向き合うことができています。

改善すべき点

ブースに集客した後の導線が設計できていなかった

今回の最も大きな改善ポイントです。

RubyKaigi2022 Platinum Sponsors として協賛&ブース出展します! - Paytner Tech Blog でも書いた通り、

スポンサーとしてRubyコミュニティへの還元をしたいという想いも当然ありますが、本音として、採用目的で「Rubyコミュニティに『ペイトナー』という存在を知ってもらいたい!」という想いがあることをここに告白致します。

採用につなげたいという目的がありました。

事前に設定した目標として、「カジュアル面談の約束を取り付ける」があったのですが、一件も約束取り付けまでできず未達となりました。。

クイズを通じてブースを盛り上げることができた一方、そこから先、どうやって会社やサービス・社内の開発環境や技術スタックの紹介、ひいては採用につなげていくかという導線が全く設計できていませんでした。

次があったらこうしたい

最初から全員を巻き込んだプランニングを!!!

最大の反省点として「ブースに集客した後の導線が設計できていなかった」を挙げましたが、ここに対する改善策としては、「最初から、全員でブース設計を考える」に集約されそうです。

今回は、エンジニアチームで「ブースを盛り上げる」という目的のもとアイデア出しをしていました。 しかし、「そもそもなぜブースを盛り上げたいのか?」や、「そもそも我々はなぜRubyKaigiにスポンサー支援し、ブース出展を行うのか」という最上位の目的を忘れてしまう瞬間があったことは否定できません。

また前述の通り、盛り上げて集客したあとどうするのか?の設計はできていなかったので、ここはまさにエンジニアだけでなく、広報・PRチームのメンバーも含めた全員で議論すべきところだったと思います。

CTO面談ブース!?

これはあくまで具体的な案のひとつですが、「今すぐCTOと会話できるコーナー(仮)」みたいな、CTOをブースに常駐させておき、いつでもだれでもCTOとお話しできますよ!という場所を用意しておく。

「今度カジュアル面談しましょう!」なんていうケチな話ではなく、「今やっちゃおう!」ってことですね。

そうすれば、カジュアル面談の日程調整をする必要もないし、参加者も気軽にお話しできてよいのでは!?ということを考えていたりします。本当にやるかどうかは分かりませんが、乞うご期待!?

(おわりに)こんな会社です!!!

RubyKaigiでちゃんとお伝えすることができなかった、ペイトナーについて少しだけ紹介させてください!!!

ペイトナーは「スモールビジネスにやさしい支払い・請求で新しい挑戦を後押しする」というミッションのもと、 オンライン型ファクタリングサービス「ペイトナー ファクタリング」とクラウド請求書処理お任せサービス「ペイトナー 請求書」を開発・運営しております。

これらのプロダクトを爆速でさらに成長させるために絶賛エンジニア募集中です! やりたいことに対してエンジニアがまだまだ足りない状況です・・!

ペイトナーに少しでも興味を持っていただけましたら是非、ペイトナー 採用情報 をご覧ください!!

開発組織としては、以下ポジションを積極採用中です!!!

  • Webエンジニア
  • リードエンジニア
  • EM/VPoE

paytner.co.jp

Railsのコードレビューを受けてみて勉強になったところ

ペイトナーのエンジニアの井齊です。
プロダクトのコード品質を高め維持していくためには、コードレビューが欠かせないですよね。

ペイトナーでは、バックエンドにRailsを使って開発しています。
今回は、コードレビューでコメントをもらった指摘事項をまとめました。

①配列展開メソッドで、 indexの開始の値を指定したい時にeach.with_indexを使う

eachなどを使って配列展開する時に、indexを取得したい場面がありますよね。その時に、each_with_indexを使って対応しようとしていました。
例としては以下のようなケースです。

before

drinks = ["コーラ", "サイダー", "アップルジュース"] 
drinks.each_with_index do |drink, index|
    p "#{index + 1}番目: #{drink}"
end

出力結果はこんな感じでしょうか

1番目: コーラ
2番目: サイダー
3番目: アップルジュース

もちろん、これでもやりたいことは達成できるのですが、今回のように1番目から始めたい場合はindex + 1で指定する必要があります。
そこで、each.with_indexの出番です。

after

drinks = ["コーラ", "サイダー", "アップルジュース"] 
drinks.each.with_index(1) do |drink, index|
    p "#{index}番目:#{drink}"
end

each.with_index(数値)を使うと、indexの最初の値を指定することができます。

② if文の結果を変数に格納する

コントローラー層でmail_flagのパラメータで条件分岐する実装を例として挙げました。
一方はメール送信の関数を実行して「メール送信しました」のメッセージをリダイレクト先で表示させ、
もう片方はメール送信せずに「完了しました」のメッセージをリダイレクト先で表示させる実装です。

before

    if params[:mail_flag]
      send_mail(@user)
      redirect_to complete_path(@user), notice: 'メール送信しました'
    else
      redirect_to complete_path(@user), notice: '完了しました'
    end

beforeも動きますが、if文の結果を変数に格納するとDRYになります。

after

    notice_message = if params[:mail_flag]
      send_mail(@user)
      'メール送信しました'
    else
      '完了しました'
    end
    redirect_to complete_path(@user), notice: notice_message

リダイレクト先は同じで、返すメッセージだけ異なる形だったため、 if文で条件分岐の結果としてメッセージを変数に格納し、そのメッセージをリダイレクト先に渡すことでDRYにできました。

まとめ

今回挙げたようなコードレビューで指摘をもらって、拡張性・変更容易性・視認性など重要ポイントをきっちり見るということが勉強になりました! ここだけでなく、他の実装箇所にも応用できるように頑張っていきたいと思います!

終わりに

ペイトナーは「スモールビジネスにやさしい支払い・請求で新しい挑戦を後押しする」というミッションのもと、
オンライン型ファクタリングサービス「ペイトナー ファクタリング」とクラウド請求書処理お任せサービス「ペイトナー 請求書」を開発・運営しております。

これらのプロダクトを爆速でさらに成長させるために絶賛エンジニア募集中です!
ペイトナーに少しでも興味を持っていただけましたら是非、ペイトナー 採用情報 をご覧ください!!

paytner.co.jp