FactoryBot運用ガイドを作りました

はじめに

こんにちは、プレックスの種井です。

PlexJob開発チームではRSpecによるテストに使用するfixtureの作成に、FactoryBotを使用しています。 テストコードに対してはrubocop-rspecにより一定のルールに則ったコードが作成されていますが、Factoryの定義やオブジェクトの生成方法などは個々のメンバーに委ねられており、オンボーディングやコードレビューの際に方針に対して方針に対して疑問が上がる箇所になっていました。 今回、所属するチーム向けに運用やコーディングのルールを作成したので、この場を借りて紹介したいと思います。

目次

  • はじめに
  • 目次
  • 運用ガイド
    • 運用の観点
    • 運用時のルール
  • 終わりに
  • 参考資料

運用ガイド

前提と運用の観点

運用するにあたっての観点として「可読性」や「再利用性」はもちろんですが、DBへのアクセスを伴うこともあるため「パフォーマンス」にも配慮する必要があります。

また、オペレーションやコーディングの作業上のどの部分で考慮すべきかがわかりやすいように、各方針やルールを「設定」、「定義」、「作成」に分類しました。

運用時のルール

  • 設定
    • FactoryBot::Syntax::Methodsを設定、クラス名を省略して、メソッドの呼び出しをする
    • FactoryBot公式のlinterを使う
  • 定義
    • ファイル名は複数形にする
    • 例: Userを定義する場合はusers.rbにする
    • 1ファイル1定義にする
    • デフォルトデータはなるべく最小限かつ簡潔にする
      • テストに必要なattributeのみを定義する
      • traitでhook(after(…))を使用して、関連データ(has_manyな)の作成はオプションにする
      • 特殊な状態の最小単位をtraitで定義する
        • ただし、なんでもtraitにせず汎用的なデータ状態のみに限る
    • 固定値ではなく本物に近いデータを定義する
      • sequenceやFakerの活用を検討する
  • 作成
    • 何でもcreate(…)にしない
      • association先はassociationで定義する
    • 1度に複数のオブジェクトが必要になる場合はbuild_list,create_listを利用する

設定

クラス名を省略して、メソッドの呼び出しをする

公式のセットアップガイドにもありますが、rails_helper.rbFactoryBot::Syntax::Methodsを定義することで、クラス名を省略してメソッドを呼び出すことができます。

# rails_helper.rb

RSpec.configure do |config| 
  config.include FactoryBot::Syntax::Methods 
end
# クラス名(FactoryBot)を省略してメソッドを呼び出します。

# build 
user = build(:user) 

# create 
user = create(:user)

FactoryBot公式のlinterを使う

FactoryBot.lintを実行することで、定義された全Factoryに対してcreateを実行し、データの作成時に例外が発生する場合は、該当するFactoryの一覧とともにFactoryBot::InvalidFactoryErrorを例外として投げてくれます。

未定義の必須フィールドのような、Factoryのデータ定義の不備を事前に検知することができます。

公式にあるようにrakeタスクを作成して、GitHub Actionsなどから呼び出すことが推奨されています。

# lib/tasks/factory_bot.rake

namespace :factory_bot do
  desc "Verify that all FactoryBot factories are valid"
  task lint: :environment do
    if Rails.env.test?
      conn = ActiveRecord::Base.connection
      conn.transaction do
        FactoryBot.lint
        raise ActiveRecord::Rollback    
      end
    else
      system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
      fail if $?.exitstatus.nonzero?
    end
  end
end
$ bundle exec rake factory_bot:lint RAILS_ENV='test'

定義

ファイル名は複数形にする

例として、Userモデルが定義されている場合に対応するFactoryのファイル名はusers.rbにします。

1ファイル1定義にする

例として、users.rbを作成する場合

FactoryBot.define do 
  factory :user do # 1ファイルに対して1定義にする
    ... 
  end
end

デフォルトのFactory定義はなるべく最小かつ簡潔にする

テストに必要なattributeのみを定義し、使用しないattributeまでデフォルトのデータを定義しないようにします。

traitでhook(after(...))を使用し、has_manyな関連データの作成はオプションとして呼び出し時に選択できるようにします。

FactoryBot.define do
  factory :user do
    trait(:with_posts) do # 最小単位にする&オプションとして、使用時に選択できるようにする
      transient do
        posts_count { 5 }
      end

      # has_manyな関連データの作成
      after(:create) do |user, evaluator|
        create_list(:post, evaluator.posts_count, user: user)
        user.reload
      end
    end
  end
end

使用頻度が高い、特定の状態はtraitで定義しておきます。

ただし、なんでもtraitにするのではなく、汎用的なデータ状態のみに限ります。

FactoryBot.define do
  factory(:post) do
    trait :published do
      published { true }
    end  

    trait :unpublished do
      published { false }
    end
    
    trait :week_long_publishing do
      start_at { 1.week.ago }
      end_at { Time.now }
    end
    
    trait :month_long_publishing do
      start_at { 1.month.ago }
      end_at { Time.now }
    end

    factory :week_long_published_post, traits: [:published, :week_long_publishing]
    factory :month_long_published_post, traits: [:published, :month_long_publishing]
    factory :week_long_unpublished_post, traits: [:unpublished, :week_long_publishing]
    factory :month_long_unpublished_post, traits: [:unpublished, :month_long_publishing]
  end
end

固定値ではなく本物に近いデータを定義する

一意性の必要な値にはsequenceの利用を検討します。

また、本物に近い適当な値を設定したい場合はFakerの利用を検討します。

FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "person#{n}@example.com" } # sequence
    
    name { Faker::Name.name } # Faker
  end
end

作成

何でもcreate(...)にしない

createメソッドは毎回SQLが実行されるため、テスト実行のパフォーマンスに影響を与えます。

モデルのバリデーションなど、DBに値が生成されている必要がないテスト対象の場合はbuildメソッドをはじめとした、メモリ上にオブジェクトを作成する機能を使用します。

build(:user)
build_stubbed(:user) # buildで済ましたいが、idやtimestampが必要な場合はbuild_stubbedを使用する

association先を事前に作成する場合は、associationで定義しておくことが推奨されます。

createメソッドを使用してassociation先を作成すると、buildした際に常にcreateが伴ってしまうためです。

FactoryBot.define do 
  factory :post do
    user # belongs_toの関連(associationの省略記法) 
    user { create(:user) } # NG postをbuildした場合でもuserがcreateされてしまう
  end
end

また、作成時にかかる処理はinstance_double,spy(RSpecの機能) > build(…) > create(…) の順で速いです。

1度に複数のオブジェクトが必要になる場合はbuild_list,create_listを使用する

必要以上にオブジェクトを作成しないようにします。

また、transientを使用して、作成数に対してラベル付けをしておくようにします。

FactoryBot.define do 
  factory :user do
    trait(:with_posts) do
      transient do
        posts_count { 5 } 
      end

      # 必要な分だけ作成する 
      after(:create) do |user, evaluator| 
        create_list(:post, evaluator.posts_count, user: user) 
        user.reload 
      end 
    end 
  end 
end

終わりに

公式ドキュメントや先人達がベストプラクティスとして公開してくださっている資料を参考に、まず弊社チームでも取り組んでみるとよさそうなものをピックアップし、ガイドの作成を行いました。

今回作成したものをベースに運用しつつ、その中でさらに取り入れたものや、工夫したものは今後もブログなどで紹介したいと思います。

最後になりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニアを募集しています。

上述のような、開発上の取り組みや課題に対してご一緒していただける方、少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。

参考資料

【入社エントリ】事業とエンジニアの関わりからみたプレックスの働きやすさ

はじめまして、小松と申します。2ヶ月連続入社エントリで恐縮です。

昨年2022年11月に入社しました。なんだかんだ入社5ヶ月程たっており、先月の池川の1ヶ月先輩です。ちょっと何を書こうか考えているうちに先をこされたりなぞしてしまいました。えへへ。

簡単な自己紹介

社会に出てから何年か数えてみましたが12年目だと思います。ここまで一瞬です。なぜプレックスに来たのかと言うと、みんな元気があって強そうだったからです。

以下が私の略歴です。ざっくり社会人になってからエンジニアを志して、気がついたらここにいました。

  • 2013年 SES企業へ入社、ITエンジニアとしてのキャリアを開始
  • 2016年 保険代理店へ転職、情シスとして事務業務の改善業務を行う
  • 2018年 オンラインでカーメンテナンスを行う事業会社へ転職、WEBエンジニアとしてのキャリアが始まる
  • 2022年11月 プレックスへ入社 ソフトウェアエンジニアとしてスキルを広げたいと考える

入社前のプレックスの働き方への不安について

まず正直に感じた不安から書いておきます。みんなが元気そう、という理由で入社を決めたのとは矛盾しますが、今までフルリモートで働いていたところから出社を伴う働き方になるというところには不安を感じていました。

入社前はフルリモートだったが果たして出社に戻れるか

事前にリモートは週3回までと聞いていており、個人的にプレックス入社前に感じていた不安はこれにつきました。毎日でないにせよちゃんと通えるのかと。

前職はほとんどフルリモートであった為、出社に対する抵抗感は正直少なからずありました。かといって前職も始めからフルリモートだったわけではなく、例のごとくコロナ禍を経てのリモート化だったので初めからフルリモートの会社に勤める事とは事情が違った事もあり、はなからフルリモートの会社を選択することにも抵抗がありました。

最初の2週間は慣らしの為に全日出社しました。意外にも、新しい職場に慣れる事に精一杯であった為、出社のつらさはあまり感じませんでした。そして、現状は私は週2リモート、週3出社というスケジュールで行動しています。リモートの日はプロダクトチーム内で共有して基本的に作業集中日として、出社日にコミュニケーションを凝縮させるというスタイルの働き方をしています。今の所これは中々心地よく効率的に感じます。

ただし、出社/リモートのハイブリッドワークに伴う課題は月並みに存在する為、メンバーが増えてくれば課題解決をもっと真剣に考える必要があると思っています。

事業とエンジニアの関わりから見るプレックスの働き易さについて

プレックスのエンジニア文化の良さ、面白さというのは過去のエントリーから分かるかなと思うので、今回はエンジニアの組織とビジネスサイド(という呼び方は好きじゃないですが便宜上)との関係からプレックスの意外(?)な働きやすさを書いてみます。

事業部とエンジニアグループの距離感

現在の組織図はこちらのエントリーから変わらず、エンジニアグループの中に事業部で割られているマトリクス状の組織図となっています。プレックスのエンジニア組織ではこの形が上手く機能しているなと感じます。

組織の中に階層や役割分担はありますが、プレックス内ではそれがゆるやかで、プロダクト開発において情報のやり取りを誰かをハブとする点の形ではなく、各々が能動的に取り合う正に網のような形のコミュニケーションを行っています。また、プロダクト(事業)軸の定例の他、網の中で見つけた情報や課題を持ち帰り共有できるエンジニア定例も行っており、事業部とのコミュニケーションとエンジニア間のコミュニケーションが安心して両立できる仕組みとなっています。

事業とプロダクトの絶妙な関係

プレックスには(必ずしも1対1ではありませんが)いくつかの事業部とプロダクトがあります。

広義の意味でのソフトウェアエンジニアとして、プロダクトを前面に出して自社サービスを行っている事業会社で働くというのはある種のロマンがあります。しかし、すげープロダクトを作ってやるぞと入社してみると、多くのプロダクトの表に出ている面は全体のごく一部で、それは営業、CS、バックオフィスなど多くのメンバーのオペレーションで成り立っている事を知ったりします。また、ここでのバランス感覚が崩れると事業部とプロダクトチームの気持ちがばらばらになってしまう事もままあります。

プレックスで私はPlexJobというサービスに関わっており、出面としてはWEBサービスですが、例に漏れずに多くのメンバーのオペレーションで成り立っています。そんなPlexJobの事業責任者はオペレーションとプロダクトに対して中立的であると感じます。非常に現実主義ではありますが、良いものを作りたい気持ちも強く持っています。おかげで事業部内では職種に関係なく互いをリスペクトする文化が醸成されており、エンジニアが働きやすい環境の大きな要因となっていると感じます。

経済的に独立した事業会社であるということ

エンジニアって技術を武器に社内でそれなりに独立した姿勢を見せられそうな感じは見せますが、実際のところはトップの経営判断や社内の政治情勢の波をそれなりに強く受けますよね〜。会社にもよるのでしょうが、私が以前勤めた会社のいくつかは母体の大きい子会社だったので本当に良くも悪くも親会社の出す意見、方針の影響が仕事にありました。

この辺りは専門外である為細かい記載はしませんが、現状そうでないプレックスはここにいる代表、事業責任者、メンバーが本気でプレックスの成長の為に会社を動かしています。当たり前とい言われればそれまでですが、自分たちの作るものが本気で自社の成長を願って作られているものであるという実感は大きなモチベーションとなっています。

最後に

前回の池川さんも書いていましたが、プレックスに来てから毎日が爆速で進んで行きます。各職種に様々なキャラクターのメンバーがおり、日々が刺激的です。

そして恒例になりますが、プレックスでは一緒に働くメンバーを募集しています。組織にもプロダクトにもまだまだ改善点があり、人の手も脳みそも足りていません。

現在エンジニアの他、UIデザイナーの募集もありますので、今回の記事を読んで少しでも興味を持って下さった方はお気軽にご連絡ください。

dev.plex.co.jp

宣伝:私のプレックス内の私的な活動について

Plex電子工作部やってます

なぜ私がエンジニアリング(というより最初はプログラミング)の世界に興味を持ったかというと、なんとなく格好良い感じがしたからです。というより出身が文系というのもあり、工学全般に憧れを感じています。

そこで最近ははんだごてを購入して電子工作をはじめました。まずは電子工作入門の王道、自作キーボードから始めています。

そしてなんとプレックスにはそういった事に興味を持ってくれるメンバーがおりましたので、(非公式ですが)電子工作部の活動も始まりました。プレックスでは一緒に働くメンバーを募集しておりますが、私は一緒に電子工作をしてくれるメンバーも探しております。今回の記事を読んで少しでも興味を持って下さった方はお気軽にご連絡ください!

↓は個人活動ですがこんな感じでやってます・・・!

自作キーボード チェリーパイ(CherryPie)ビルドログ 前編

youtu.be

【入社エントリ】プレックスに入社しました!

はじめまして、プレックスの池川と申します。

2022年12月に株式会社プレックス(以下、プレックス)にエンジニアとして入社しました。

今回、入社して3ヶ月経って新しい環境にも慣れてきたので、入社経緯や感想、課題に感じていることをまとめておきたいと思います。

何か新しいことにチャレンジしたいエンジニアの方や、ベンチャー企業に興味のある方にプレックスのことを知ってもらえると嬉しいです。

自己紹介

私のこれまでのキャリアを簡単に紹介します。

- 2008/4  新卒で地方銀行に入行
- 2019/6  エンジニアとしてIT企業に転職
- 2022/12 プレックスにジョイン

新卒では地元の地方銀行に入って、融資や資産運用の営業を行っていました。

銀行には10年ほど勤めたのち、一念発起してエンジニアにキャリアチェンジして受託開発系の会社に転職しました。

その会社ではバックエンドエンジニアとして業務システムの開発・運用を行ったり、プロジェクトマネージャーとして新規プロジェクトの管理を行いました。

その後、プレックスに転職して今はドライバー向けの求人サービスであるプレックスジョブの開発にフロントエンド・バックエンドの両面で携わっています。

プレックスはこれまでのキャリアで3社目、エンジニアとしては2社目の会社です。

プレックスに入社した理由

転職活動を行うにあたり、以下の3点を軸としていました。

- エンジニアとして開発ができる(マネジメントやプロジェクトマネージャーの業務も面白かったが、開発がしたい)
- 自社開発をメインで行っている(前職で受託開発は経験したので自社開発もやってみたい)
- 社会的に意義のあるサービスを展開している(自分の仕事に意味を見出したい)

上記の点を満たしていたことに加えて、カジュアル面談や面接で代表や先輩社員と話す中で、よく分からないけど面白そうなことやってるな、と感じたことがプレックスに入社を決めたポイントでした。

入社前、不安だったところ

とはいえプレックスへの入社を決める際にいくつか不安な点もありました。

同じような不安を持つ人もいるかもしれないので、ここで払拭しておきます。

おじさんだけど大丈夫?

大丈夫です!

プレックスは平均年齢28歳と若い人が多いですが、エンジニア組織は少し年齢層高めなので安心してください。

それでもエンジニアの中では一番年上ですが、各々がプロフェッショナルとして業務を行うなかで互いに尊重する文化があり、すぐに馴染めました。

おじさんだからこそできることをやっていきましょう💪

不安な方はカジュアル面談やオフィスへの訪問もいただけますし、まずは業務委託や副業といった形でお手伝いいただくことも可能です。

物流・インフラのことよく分からないけど大丈夫?

大丈夫です!!

私も入社までよく分かっていませんでした。

プレックスでは事業部制を採用しており、各事業へエンジニア個人が注力できるような組織作りを行っています。

ビジネス側との距離も近いため、日々コミュニケーションをする中で不明点を解消することができます。

また、エンジニア組織の中でもドメインモデル図やシーケンス図の整備に取り組んでおり、ドメイン知識をいち早くキャッチアップして開発できる体制作りを進めています。

ドキュメント整理については過去の記事「開発合宿でドキュメント整理やER図の自動生成やってみた」に詳細が書いてありますので参照ください。

入社後やったこと

入社後1ヶ月はオンボーディング期間として設定されており、小さめのタスクを担当しながらドメイン知識やプロダクト、使用されている技術のキャッチアップを行いました。

初めてのリリースは入社して4日目だったのですが、リリース時の報告でお祝いのメッセージをいただけたのが印象に残っています。

2ヶ月目以降は既存サービスの新機能開発やデザインリニューアルを行ったり、オンボーディング改善や勉強会の主催など、改めて振り返ってみると色々なことをやりました。

今回の記事ではその中でオンボーディング改善の取り組みの一環でやったことを紹介できればと思います。

オンボーディング改善とは

入社後のオンボーディング期間を終えた後、1スプリント分(一週間)をメインの開発から外れて、オンボーディング中で出た課題の改善時間として使ってもらう というものです。

オンボーディング改善については過去の記事「2人目のエンジニアとして入社してオンボーディングを改善した話」に詳細が書いてありますので参照ください。

実施したオンボーディング改善の取り組み

下記の2つを行いました。

1. デバッグ環境の整備
2. 社内用語集の作成

1. デバッグ環境の整備

プレックスで使用している技術は私にとって未経験のものが多かったため、同じような人のためにデバッグ環境の整備を行いました。

使用している人が多い IDE やブラウザごとに、設定の方法やデバッグの仕方を Notion 上にドキュメント化しました。

取り組んだことでデバッグ関連の知識の共有化がチーム内で図れたほか、今後新しく入ってくるメンバーが開発に早く入れる、効率的に開発ができるような環境づくりができました。

言語や IDE も日々アップデートされているため、適宜情報をブラッシュアップして開発の効率化に繋げたいと思います。

2. 社内・専門用語集の作成

私自身、入社後一番困ったのが専門用語の理解だったため、社内・専門用語集の作成を行いました。

ミーティング中やドキュメントを読んでいると知らない単語(例:CSやDR)が出てくるのですが、都度確認もできず、ミーティングが終わってから聞いたり、過去のドキュメントを検索したりしていました。

特に社内用語が分からないのが辛かったです💦(Google検索しても出てこないので)

そこでスプレッドシートに用語をまとめた上で、普段使用している Slack 上で管理できるように Slack Bot を作りました。

こちらについてもデバッグ環境の整備と同様、定期的に見直しを行い機能の拡充など行っていきたいです。

入社して感じたこと

入社してからは本当に一週間が早く、それだけ刺激的な毎日が過ごせているのかなと思います。

プレックスには「仮説検証して学びを次に活かす文化」があり、技術的なことはもちろんのこと、事業やプロダクトへの課題感を持ち改善をしようとする意識が高い点は入社してすごいと感じました。

一方で組織の体制や制度が整っていない、開発においても属人化されている部分があるなどの課題もあるため、できることやるべきことはまだまだあります。

最後にはなりますが、プレックスではソフトウェアエンジニア、フロントエンドエンジニアを募集しています。

もしこの記事を読んで、一緒に挑戦してみたいと思った方がいましたら是非ご連絡をお待ちしています!!

dev.plex.co.jp

DevOpsの指標を開発の振り返りに活用しはじめた話

こんにちは、プレックスの種井です。

今回は、2022年Plex開発合宿(秋)シリーズ最後の記事になります。(過去の記事はこちら)

10月の開発合宿で私が取り組んだ内容「開発チームの生産性の可視化」とPlexJob開発チームにおける「振り返り」の取り組みに関してご紹介させていただきます。

開発合宿で扱ったテーマ「振り返り」

私の所属するPlexJob開発チームではスクラム開発を取り入れています。合宿時点では月に一回、その月に取り組んだ各スプリントの振り返りをまとめて行っていました。

振り返りを行うなかで

  • 個々人の課題感やその粒度に関してばらつきがある
  • 課題に対してのアクションの優先度がつけづらい

という課題感がありました。

開発合宿で取り組んだ内容

振り返りの場では、各メンバー感じている課題を思い思い自由に出してもらいつつも開発チームとして重要視することを明確にしておくことは振り返りの質の向上や、個々人の課題感の洗い出しのしやすさという観点から重要だと考えました。

書籍エッセンシャルスクラムにも振り返り(スプリントレトロスペクティブ)の事前準備として、「フォーカスの定義」や「客観的データの収集」が要素として上げられています。 今回は、取り掛かりとして、「スプリント毎のベロシティ」と「デリバリのパフォーマンス(Four Keys)」の一部を計測することにしました。

上記の指標は

  • スプリントごとのベロシティ
    • チームの健全性の把握や提供した顧客価値の程度を測るものとして
  • デリバリのパフォーマンス(Four Keys)
  • 合宿の限られた時間内で試せるもの

という観点で選びました。

また、週次のスプリントにおけるベロシティは開発だけではなく、設計からリリースまでの間に複数の役割や要素が影響します。デリバリのパフォーマンス(Four Keys)も合わせて計測することで、開発者内でボトルネックの発見や改善に向けての意識が向きやすいのではないかと考えました。

Four Keysは4項目ありますが、今回は合宿の時間に限りがあるため比較的計測の容易な「デプロイの頻度」と「変更のリードタイム」の2項目のみをスコープとしました。

スプリントごとのベロシティの計測

PlexJob開発チームでは、スクラムにおけるタスクをNotionのデータベースとBoard viewを使用して管理しています。

  1. Notion APIを使用し、データベースからスプリント毎の完了タスクを収集
  2. BigQueryに保存
  3. Metabaseから集計

という流れで、ダッシュボードを作成することにしました。 1,2はスクリプトを作成し、自分の手元のPCで実行するような簡易的なものにしました。

スプリント毎の完了ポイント

Four Keysの計測

前述の通り今回「デプロイの頻度」と「変更のリードタイム」の2項目を対象とします。 両指標ともGitHub APIにて提供されているデータを活用しました。 また、

  • 計測の対象としてPlexJobのAPIリポジトリ上のデータのみを使用
  • 土日は除く
  • dependabotによるPRのマージは除く

という前提で集計を行いました。

デプロイの頻度

本番環境へのリリース頻度です。 master(main)ブランチへのPRがマージされたタイミングをリリースとして、1日あたりのリリース頻度を月毎の平均として算出してみました。

リリース頻度

変更のリードタイム

初回コミットから本番環境へのリリースまでにかかった所要時間です。 master(main)ブランチへマージされたPRの初回コミットからマージまでにかかった時間(日数)を月毎の平均として算出してみました。

リリースまでのリードタイム

合宿時点までの直近3ヶ月の指標を、パフォーマンスレベルに照らし合わせると両項目で「High」にあたることが分かりました。

まとめ

簡易的ではありますが、上記の指標を出してみて改めて個人の負荷状況、開発上のボトルネック、改善点について考える客観的な指標として活用できそうだと実感しました。

実際、合宿の最後の発表の際にも

  • さらにリリース頻度を上げるためにはリリース対象を分割していくべきか?
  • 逆に分割しすぎてQAやプロセスの最適化をしないと、リリースが遅くなることはないか?
  • Four Keysの指標とスプリントのヴェロシティを合わせて計測すると分割の最適化ができるのはないか?

のような議論をすることができました。

PlexJob開発チームでの振り返りの取り組みについて

ここまで、10月の開発合宿で取り組んだ内容の紹介をさせていただきましたが、早いもので気がつけば3ヶ月以上経過しており、開発の体制としてもいくつか変化がありました。

この間、振り返りに関しても新たな取り組みをはじめました。 合宿で取り組んだDevOpsの指標もこの取り組みの中で活用しはじめたこともあり、この場を借りて紹介させていただきます。

前述させていただいた通り、10月時点では月に1回の振り返りを行っていましたが、11月、12月で開発チームに新たなメンバーが計2名ジョインしてくれたこともあり、よりチームとして情報の共有をオープンにし課題や方針に対してのアクションなどに共通認識を持てるようにすべきだと考え、振り返りの場の頻度や内容を再設計することにしました。

振り返りの内容としては、アジャイルなチームをつくる ふりかえりガイドブックなどを参考に以下のようなものにしました。

  1. 週1回金曜日に1時間程度の定例MTGを設ける
  2. 事前に振り返りシートを共有し、各メンバーにKPT用のJamboardに今週のアクションや課題と負荷状況を記入してもらう
  3. 前週のTryの実施状況の確認をする
  4. Jamboardに各自作成してもらった今週のアクションや課題を発表しながらKeepとProblemに振り分ける
  5. 全員のKeepとProblemが分類でき次第、Tryを議論して決め、次週のアクションにする
  6. Tryの中で開発Issueとして扱うべきものはタスク化する
  7. 各メンバーの調子と一言コメントを発表する

以下は、使用している振り返りシートの一部です。

振り返りシート(一部抜粋)

運用をはじめて1ヶ月程度経ちました、まだまだ試行錯誤の段階ではありますが取り組みの中で、プロダクトチーム全体での勉強会や、問い合わせ対応の当番化などの実際のアクションにつながるものもいくつか出てきています。 引き続きメンバーのフィードバックをもらいながら続けていきたいと思います。

合宿で取り組んだ内容のその後と活用

最後に合宿で取り組んだ内容の活用ですが、Four Keysの2項目を振り返りシートに埋め込んで各自の振り返り時に使用してもらうことにしました。 KPTの洗い出しや次アクションを決める際の観点として活用してもらいたいという意図があります。

  1. GitHub APIから取得したデータを加工してtsvとして書き出すスクリプトを実行
  2. tsvをスプレッドシートにインポート
  3. Google Looker Studioで2.のスプレッドシートをデータソースにしてダッシュボードを作成
  4. Notionの振り返りシートに埋め込み

指標の活用例

おわりに

今回、合宿での振り返りの効率化としてのDevOps指標の検証と、PlexJob開発チームでの「振り返り」の取り組みに関して紹介させていただきました。

効果的な振り返りを継続的に実施することは難しいことです。 なるべく各メンバーの負荷を最低限にしつつも、効果的な振り返りを続けることは重要であると考えています。 事例として少しでもご参考になればと思います。

振り返りの取り組みやFour Keysをはじめとした指標の活用の変化に関しても引き続きアップデートがあれば、本ブログで紹介していきたいです。

最後になりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニアを募集しています。

上述のような、開発上の取り組みや課題に対してご一緒していただける方、少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。

dev.plex.co.jp

開発合宿でコードレビューのプロセスを改善した話

こんにちは、プレックスの石塚です。 この記事は開発生産性 Advent Calendar 2022の21日目の記事になります。

前々回の記事で、10月に開発合宿を開催し、「普段できていない開発プロセスの改善」というテーマのもと、各々が開発に取り組んだ様子をご紹介させていただきました。その中で、個人が取り組んだ内容を次回以降のブログで詳しく書いていくと言っていましたが、気付けば早2ヶ月が経過、さすがに年をまたいでしまってはまずいという思いで、焦り筆を取っている次第です。

そういったわけで、今回は自分が開発合宿の中で取り組んだテーマである「コードレビューのプロセス改善」のお話をさせていただきます。

コードレビューの目的

まずプロセス改善の話をする前に、なぜコードレビューを開発プロセスに組み込んでいるのかという話をしたいと思います。 コードレビューは多くの現場で開発プロセスの一貫として取り入れられていることが多いですが、絶対必要というわけではありません。 特に事業フェーズが初期段階かつシニアなメンバーが集まる組織では、コードレビューを省略しているパターンが多いイメージがあります。

個人的にコードレビューを導入する目的に関してはエンジニアリング的観点とビジネス的観点の2つがあると考えていますが、弊社の開発組織においては導入するメリットの方が大きいと感じています。

エンジニアリング的観点

エンジニアリング的観点としては以下のような、いわゆるコードレビューのメリットとして語られることが多い事柄です。

  • プロダクトをチームでメンテナンス可能な状態に保つ
    • リーダビリティや一貫性、品質の担保
  • プロジェクト、ドメイン、技術における知識の共有
  • オーナーシップを高める
  • ログが残る

ビジネス的観点

  • コードが目的を達成できる正しい挙動をしているか確認する
  • 不具合を減らす

ビジネス的観点は上記の2つです。 現在のプレックスの開発では、PdM、エンジニア、デザイナーの分業体制がきっちりと明確になっているわけではないので、コードの変更がユーザーストーリーのゴールを達成するものかを確認するといった目的も含まれています。

コードレビューの責務が増えてしまい、余計なコストが掛かってしまうので、本来は仕様の是非まで確認するのは理想的とは言えません。とはいえユーザーに提供してからこの機能は無駄だったよねとなってしまうと、今まで開発に掛けてきたコストが無駄になってしまうので、開発プロセスのなるべく早い段階で発見できるように、タスクの種類や大きさによって確認するようにしています。

※このあたりの生産管理の話はHIGH OUTPUT MANAGEMENTが詳しいです。

以前のプロセスと発生していた課題

前置きが長くなってしまい恐縮ですが、改善前のコードレビューのプロセスとそれにおいて発生していた課題についても軽く紹介しておきたいと思います。

以前のプロセスではSlackのワークフローを活用していました。 このようなプロセスに落ち着いた背景として、最初はSlackのメッセージでテキストで直接コードレビュー依頼を実施していたので、ワークフローを使って自動化したという経緯があります。 入力値は以下の3つで、レビュワーとレビューイにメンションが飛ぶようになっています。

  • レビュワー
  • 緊急度(お手すき・なる早・大至急の3種類)
  • プルリクのURL

Slackワークフローでのコードレビューのイメージ
Slackワークフローでのコードレビューのイメージ

この運用では特に大きな問題はなかったものの、以下のような課題がありました。

  • コードレビューが溜まりがち
  • コードレビューが漏れる
  • コードレビューに時間が掛かる
  • レビュワーのコンテキストスイッチが発生する
  • コードレビューの知識がレビュワー、レビュイー以外のメンバーに共有されない
  • Githubでのコードレビューの後、Slackでメンションする手間がある

どう改善したのか

原因の特定

合宿の前からどんな課題があるかを議論したり、書籍やブログでのインプットをした結果、主に以下の2点が根本的な原因だと考えました。

  • プルリクエストのサイズが大きい
  • Githubのリマインダーを適切に使えていない
    • 定期的にコードレビューの時間を確保できていない
    • 自分がアサインされているコードレビューを一覧できる場所がない
      • 溜まりがち、漏れる
    • Githubでのコードレビューの後、Slackでメンションする手間がある

「コードレビューの知識がレビュワー、レビュイー以外のメンバーに共有されない」という課題に関しては、比較的チームの人数が少ないこともあり、今回はコストパフォーマンスを考慮して改善のスコープ外としました。

プロセスの改善

そうした流れから、合宿では次の2つの改善を実施していきました。

1. プルリクエストの大きさを小さくする

こちらの改善はプロセスというよりは、心構えに近いですが、コードレビューガイドというドキュメントを用意して、オンボーディング時に共有する形にしました。 実際のコードレビューガイドに記載されている内容をそのまま添付しておきます。

1. プルリクエストを小さくする
- プルリクエストの元となる仕様を小さくする
  - 実装の前にWHYやWHATについて議論しておく
    - スプリントMTGでできると全員参加しているので良い
    - WHYやWHATは本来コードレビューで蒸し返されるべきポイントではないが、リリースしてから気付くよりはコードレビュー時に気付けるほうが手戻りが少ないので気付いたら言うべき
  - 実装の元となるタスク(HOW)を細かく分割する
- 変更が大きくなる際は、設計レビューを実装前に行う
  - モデリングにはドメインモデル図を推奨

コードレベルでプルリクエストを小さくすることも大事なのですが、それ以前の仕様を決める段階での動きがより重要だと思っています。 ユーザーストーリーのゴールを達成するミニマムの仕様はどういったものか、仕様が大きいのであればマイルストーンを引いて検証を分割することはできないかを考えるようにしています。 また大きな変更であれば、設計レビューも事前に行うことで、プルリクエストの責任範囲を小さくすることも意識しています。

2. GithubのSlack連携を軸にプロセスを構築

Githubにはscheduled remindersというSlackと連携したプルリクエストのリマインド機能があります。この機能は大変便利なのですが、個人ごとに設定をする必要があり、設定がばらついているとうまく恩恵を得ることができません。

なのでプレックスでは以下のようなルールを作って運用していくことを決めました。

  • SlackのGithub連携をしている部屋にジョインしておく
    • Slackのユーザーグループに設定して、デフォルトでジョインするようにしておく
  • 開発者は scheduled reminders を必ず設定しておく
  • 平日に1日2回はリマインダーを設定し、コードレビューの時間を取るようにする
    • 時間は任意
  • コードレビューの依頼はプルリクエストのレビュワーのアサインで行う
    • 急を要する場合のみSlack上でメンションする
  • レビューの修正が完了したらプルリクエストからレビューの再リクエストを行う

またGithubでは自分のアサインされているレビューを一覧できるリンクが取得できるので、そのリンクをSlackのカスタムレスポンスに設定したり、Slackのチャンネルのブックマークに貼っておくことで、区切りのいい時間でレビューを実施する際の手間を減らしています。

↓ゴニョゴニョしていたら取得できたリンク

https://github.com/pulls/review-requested?q=is%3Aopen+is%3Apr+archived%3Afalse+user%3A{GithubのOrganization名}

Slackのカスタムレスポンス
Slackのカスタムレスポンス

終わりに

以上の改善の結果、レビューの漏れや溜まりが減る、レビューを依頼する手間が少なくなるといった結果を実現することができました。 振り返ってみると、プロセスを改善できたというのはもちろんですが、合宿という全員が参加している場でお互いのレビューに関する共通認識を揃えることができたことも大きかったなと感じています(自分の実装とレビューのどちらが大事なのか等)。

嬉しいことに11月、12月に1名ずつ、フルタイムのエンジニアの方がジョインしてくださり、フルタイムで4名、業務委託・インターンを含め10名弱の開発組織になってきました。 組織が拡大していく中で更なる改善として

  • レビュワーに誰をアサインするのかをどうやって決めていくのか
  • コードレビューの知識の共有

などの課題にも今後取り組んでいきたいと思っています。

最後になりますが、プレックスではエンジニアを絶賛募集中です。 今回のプロセス改善のような、開発上の取り組みや課題に対してご一緒していただける方、少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。

dev.plex.co.jp

開発合宿でドキュメント整理やER図の自動生成やってみた

はじめまして、プレックスインターン生の鈴木です。

先日、PlexJob開発チームではじめての合宿に参加したので、そこでの私が行ったことを紹介していきたいと思います。開発合宿の目的などは前回の種井さんの記事も併せて、ぜひご覧ください。

product.plex.co.jp

鈴木の開発合宿テーマ

ドキュメント関連の整理や作成

  1. ドメインモデル図の移行

  2. ER図の作成

1. ドメインモデル図の移行

背景

これまで、PlexJobのドメインモデル図はNotion内のドキュメントにありました。

しかし、新機能を追加してもドメインモデル図の更新が忘れられていることが多くありました。また、ドメインモデル図の記述量が増えるにつれて、Notion内でレビューのしづらさもありました。そこでドメインモデル図をプロジェクトのディレクトリ内に置けば、コード変更時と同時にドメインモデル図も変更できるので、ドメインモデル図の更新を忘れることが少なくなる。そして、Github上で確認できるのでレビューもしやすくなるのではないかと考えました。

実際にやったこと

  1. プロジェクトのディレクトリ内にdocフォルダの作成
  2. その中にmarkdownファイルを作成
  3. markdownファイルにNotion内のドメインモデル図を参考に書いていく

実際にできたもの

GitHubでは、markdown記法とmermaid記法に対応しているので、ドメインモデル図がとても書きやすかったです。特に、mermaid記法は図形を簡単に作成できるので、とても便利な記法だということを知ることができました。ディレクトリ内に移行したので、ドメインモデル図の更新忘れも減ったのではないかと感じています。

ドメインモデル図

2. ER図の作成

背景

これまでドメインモデル図はありましたが、ER図というものは存在していませんでした。どんなテーブルが存在しているかやテーブル同士のリレーションを確認したいときは、railsのmigrationファイルを見るかコードを見るかGUIクライアントで確認という形になっていました。なので、実際にER図を作って視覚的にテーブルやリレーションを確認できるようにしたいと考えました。

実際にやったこと

現在、PlexJob内には約70のテーブルが存在しています。このテーブル数のER図を自分で書くのはとても大変です。そこで、良い方法がないか探したところrails-erdというライブラリでER図を自動生成できそうだったので使ってみました。

rails-ERDの導入

  1. まずは、OSにgraphvizというツールパッケージをインストールする必要があります。Graphviz (Graph Visualization Software)とは、DOT言語で記述されたグラフ構造を描画するパッケージ。

    弊社では、Dockerを使用してプロジェクトを管理しているので、Docker内にこのGraphvizをインストールする必要があります。なので、Dockerfileに下記コードを追加しました

    RUN apt-get install graphviz

  2. そして、今回の主役であるrails-erdをGemFileに追加します

    group :development do
     gem "rails-erd"
    end

  3. bundle installをしたら、下記コマンドで全テーブルに対してER図を自動で作成してくれます。

    bundle exec erd

実際にできたものと問題点

テーブル数と大体のリレーションは視覚的にわかるようになりました。

しかし、70テーブルもあると以下画像のように大変なことになってしまいました、、

対策: オプションをつける

bundle exec erd --attributes=foreign_keys, primary_keys —filetype=png

とすることで、全カラムでのER図の出力ではなく主キーと外部キーだけの表示となるので、以下画像のようにごちゃごちゃ感を少しは緩和させることができたと思います。さらに見やすくする方法はないか調べていきたいです。

開発合宿の個人的な反省点

開発テーマを決めるのに半日以上かかってしまった。

開発合宿の当日にテーマを決めたのですが、なかなか良いテーマを見つけることができずにテーマ決めに多くの時間を使ってしまいました。なぜテーマが思いつかないかを考えたときに、これまでは技術のインプットなどに意識を取られていて、開発の問題点などを探しながら業務を行うことができていないことに気が付きました。最近は、技術のインプットもできてタスクをこなすスピードも上がってきたので、普段の業務では自分のタスク以外にも目を向けて開発の問題点なども探していきたいと思います。次回の合宿では、もっと良いテーマ選定で開発ができるようにしたいです。

開発合宿の感想

とても楽しかったです!!!

はじめて開発合宿というものに参加したのですが、普段とは違う雰囲気で開発することができたので気分転換になったと思います!普段の業務では話さないコミュニケーションもできて、美味しいものもたくさん食べることができて、とても良かったです!月1回の開催にしましょう←

最後になりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニアを募集しています。少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。(インターン生も募集しています!)

dev.plex.co.jp

開発チームで初めての合宿に行ってきました

こんにちは、プレックスの種井です。

今回は、PlexJob開発チームではじめての合宿を実施したので、そこでの取り組みや様子を紹介していきたいと思います。

背景・目的

  • 普段の開発ではどうしても優先度が下がってしまうが、課題に感じていることに対して、テーマを決めて取り組む時間を設けたい
  • 場所を変えたり、道中や余白のコミュニケーションの場を作ることによりメンバーの気分転換につなげたい

今回はエンジニアのみで実施しましたが、今後はエンジニアに限らずプロダクト開発に関わるメンバーを含んだ会も設けていきたいと考えています。

場所

1日目: 千葉県 山武郡 九十九里町にある一軒家の一部屋Airbnbでレンタル

2日目: 千葉駅周辺 コトコトコワーキングさん

西船橋駅に集合し、車で目的地に移動しました。

取り組み

合宿前

今回、「普段できていない開発プロセスの改善」という大枠のテーマがありました。

事前にMTGを設け、個々人の感じている課題の洗い出しと各課題を子テーマとして分類し、子テーマに対してそれぞれ個人的に課題感の強いものや、すでにアイデアのあるものに関して挙手制で担当を決めました。

以下は今回は各々が取り組むことになった子テーマです。

  • コードレビューの改善 → 石塚
  • ドキュメントの改善 → 鈴木
  • スプリントの改善 → 種井

合宿中

2日目夕方の成果発表を目標として

担当する各子テーマの中で、日々開発する中で出た改善のアイデアをもくもくと作業し、形にしていきます。

1日目

移動中の車内では雑談を交えつつ、子テーマに対するアイデアなどに関して話ました。 ここで出たアイデアからの成果もいくつかありました。

移動の車中

宿に到着次第、それぞれ自由に作業に取り掛かります。

1日目作業の様子

2日目

千葉駅付近にあるコワーキングスペースに移動し、成果発表まで最後の追い込みをしていきます。

最後に会議室にて、成果の発表と感想、成果に対しての質疑を行いました。

以下は各々の成果物に関しての概要です。

  • 石塚(コードレビューの改善)

    • コードレビューのガイドライン作成
    • レビュー依頼リマインダーの作成
    • PR自動作成ツールの作成
  • 鈴木(ドキュメントの改善)

  • 種井(スプリントの改善)

    • 週次スプリントのストーリーポイント自動集計とダッシュボードの作成
    • DevOps指標の可視化

(各々の成果物に関しては、別途ブログとして公開する予定です)

2日目作業の様子

その他

1日目のお昼は橋本食堂さんでうな重を食べました。うなぎはもちろんのこと個人的には味噌汁の味が忘れられません。

うな重

合宿先からインターン鈴木さんのご実家で営まれているキャンプ場(有野実苑さん)が近いこともあり、 晩ごはんを兼ねてキャンプ場にお邪魔させていただきました。 場内の雰囲気、料理ともに最高でぜひまたプライベートでも伺いたいです。

併設のレストランで晩ごはん。

2日目の朝は九十九里浜で目を覚ましました。

おわりに

今回の合宿のテーマである「普段できていない開発プロセスの改善」に対しての、すぐにでも活用できるような改善やツールが成果物として生まれました。

各成果物に関しては、各メンバーに次回以降のブログで詳しく書いてもらう予定です!

また、普段の業務だけではとれないコミュニケーションができたり、開発プロセス上の各々の課題感に関してもアイデアをたくさん話し合うことができ非常に有意義な時間でした。

  • 1泊2日だと移動時間込で作業時間が限られるため、短く感じた
  • 土日の開催だと翌週疲れが抜けない状態でスタートしてしまう
  • 人数分のディスプレイがあった方が捗りそう

をはじめ、今後の開催に向けての改善点も出たので、また次回以降に活かしていきたいと思います。

最後になりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニアを募集しています。

上述のような、開発上の取り組みや課題に対してご一緒していただける方、少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。

dev.plex.co.jp