絶対にモテる(チームから)コードレビュー実践編

f:id:tsukahara1991:20211018140302j:plain

こんにちは。エンジニアの塚原(@AkitoTsukahara)です。

今回は弊社の内部資料として使っている「コードレビューの型」を紹介します。

個人的にエンジニアにとって、コードレビューは福利厚生だと思っています。快適な開発現場を共有できるようにコードレビューについて考えていきましょう!

PHPカンファレンス2021で発表させていただいた「【IMO】コードレビューって難しいよね」の内容とほぼ同じものになっております。スライド資料で確認したい方はこちらをご覧ください。

これはなに

M&Aクラウドにおけるコードレビューの型です。 新しく入社されたメンバーに「コードレビューで何をするのか、どのようにしたら良いのか」という共通認識を持ってもらうための資料です。

コードレビューの目的

  • ソフトウェア品質の向上
    • 技術的負債となり得るコードがないかを確認する
      • 技術的負債とは、今後の機能拡張の障壁になりうるもの。いますぐに負債として発現するものでなくても、将来の拡張により負債となることもある
    • そのコードでユーザに今届けるべき価値が実現できているか確認
  • スキルの向上及びナレッジの共有(属人性の排除)
    • 他人のコードを読むことによって学びや発見を得る
    • 開発者同士のコミュニケーションの活発化
    • 担当者の実装レベルの把握と向上(教育的観点)

コードレビューの心構え

  • レビューしたコードを自分事として捉えること
    • チームのコードを育ている意識を忘れない
    • 人のコードもバグったら自分の責任
  • 最初から完璧なコードレビューができなくても大丈夫
    • まずは理解できないコードを無くしていくことを目指す
      • 分からないところは質問してみよう!

コードレビューの手順

f:id:tsukahara1991:20211018125015p:plain
PR→コードレビューのフェーズ

PR→コードレビューのフェーズ

  • 仕様を把握する
  • コードを見て、動きを想像する(想像できない時は先に動かしてみる)
  • 設計に違和感がないか、考慮漏れがないか確認する
  • 実際に動かしてみる
  • エッジケースを洗う
    • 例)登録ステータス、会員ステータスによって動作に不具合が発生しないか
  • セキュリティの問題がないか確認する
  • コードの影響範囲を洗う

コードレビュー→マージのフェーズ

  • 他のレビュアーのサポートをする
  • マージされるように実装や仕様を固めるのをサポートする
  • 本番に入れるまでと入れた後に必要なことを確認する

コードレビューで心掛けること

  • 自分がアプルーブしたコードに責任を持ちましょう。誰かが書いたコードという認識ではなく、チームのコード(資産)として、自分事として認識すること

個人で取り組む工夫

  • システム障害が発生した事象とコードを把握する

    • 実際に不具合が発生してしまったコードからなぜ発生したのか、なぜレビューから漏れてしまったのか振り返りを行って、改善に努めましょう
  • 誰よりも先にコードレビューをする

    • 慣れないうちは後からレビューすると「もう1人が見ているから大丈夫だろう」と意識が働きやすいです。できるだけ先にレビューしましょう
    • 先のレビューで見つけられなかった指摘箇所や考慮漏れがないか確認してみましょう
  • 自分が見ていないPRもチェックする

    • 別チームのPRや過去のPRをチェックしてレビュー経験値を積んでいきましょう
      • レビューコメントにある指摘理由は他の場面でも利用できることがたくさんあります。
      • プロダクトのコードを理解する上で過去のPRを見ておくことはおすすめです

チームで取り組む工夫

チームで効率良く運用できるように蓄積されてきたノウハウです。 下記以外にも効率良くできそうだなと感じることがあれば、メンバーに提案していきましょう。

  • PRテンプレートを利用する
    • GitHubでPRを作成する際に入力項目が自動生成されます。
    • PR前にチェック項目がクリアしていることを確認しましょう
  • 一回のPRサイズは400行を目安に
    • コード量が400行を超えていくと不具合を見つける精度が下がっていきます。大きなPRになる場合は、実装のキリの良いところでPRを分割しましょう。
  • ペアプロでコードレビュー
    • コードレビューをしていると細かい修正のラリーが何度も続いてしまうことがあります。
    • ペアプロで細かい修正はその場で解決してしまいましょう

コードレビューのコツ

  • 400行程度のPRは30 ~ 60分くらいでレビューを済ませよう
    • 1ptタスクで ~30分、3ptタスクで ~60分の目安
  • コード修正をコメントする時は根拠も一緒に記載しましょう
    • 根拠があればレビュイーも修正すべきか判断しやすくなります
    • 後からそのPRを見た人もなぜ修正されたのか経緯を知ることができます
    • レビュイーももらった修正案をそのまま鵜呑みにするのでは無くて、それが適切な形なのか考えながら判断しましょう。もし腑に落ちなければ、相談してみましょう
      • 即修正ではなくて、もらったアイデアを取り込む位のスタンスで
  • LGTMには素敵な画像を贈りましょう

PRを出す時のコツ

  • レビュアーがレビューしやすい様にサポート
    • コードの中で実装の肝となる部分にGitHub上でコメントを追加する
    • 実装で最適解なのか不安な部分はコメントでわかる様にする
    • 事前知識を必要とする実装の場合は、レビュー前に解説する
      • 例)口頭で実装の全体像を説明する→その後にレビューもらう

採用やってます

弊社ではエンジニアの採用を行なっています。 スタートアップ企業でのWeb開発に興味のある方は、ぜひカジュアルにご応募ください🤝

www.wantedly.com

画像引用元: Unsplash

プロジェクトマネージャーの型

こんにちは。エンジニアの鈴木(@yamotuki)です。
今回は、弊社の内部資料として使っている「プロジェクトマネージャーの型」を紹介します。

この資料は、今までの1~3ヶ月程度のプロジェクトを進める過程で得た知見を、個人の暗黙知ではなくチームとしてPMの役割を担える人を増やそうという目的で作りました。
PMができる状態のエンジニアであればメンバーとしても効率よく仕事を回せるのではないかという仮説のもと、PMの役割をやってもらう人以外にも展開しています。

以下はほぼ原文ままです。

これは何

プロジェクトマネージャ(PM)・リーダ業務の型をできるだけ明文化して、新しいPMやリーダ業務の助けになることを期待した資料。

PMがやること

目的を把握する

  • プロジェクトの目的を把握する
  • 目的に対してやりたいことが一致しているか確認し、一致していなかったらPdMやデザイナとすり合わせる

プロジェクトを小さくする

多くの目的を一度に達成する巨大プロジェクトになるのを防ぐ。 プロジェクトが大きくなると、以下の問題が発生する

  • 不確実性コーンは指数的に大きくなり、リリース日が読めなくなる
  • 長いプロジェクトになると開発者の脳内から初期の情報が揮発し、コードを読み直したり、リリースの手順を整えるのに苦労したりして生産性が低下する

検証したい目的に対して可能な限りリーンなプロジェクトとして小さくできないか検討する。 目安としては1~2スプリント以内(※弊社の場合は1スプリント2週間)に収めたい。

ref: 不安とストレスから解放される見積りとスケジュール方法 - Qiita

成果物をイメージする

  • PdMとデザイナが作ってくれたデザイン(またはそのカンプ)と暫定仕様書を元に、成果物のイメージをする
  • 上記の目的と、仕様・デザインが一致しているか確認し、問題提起する
  • やりたいことが技術的に無理があるところがないか、目的に対して不当に工数がかかることがないか確認する
  • デザインに無いけど既存で存在する or 重要なパーツが書かれていないみたいなことはあるので、あるべき情報は何か?をベースに考えるのが良い
成果物のイメージをするためのステップ
  • デザインや仕様書(項目整理やER図など含む)を見て、脳内で動かしてみる
    • これは慣れが必要なようだ。普段の業務から以下のステップで意識することでスキルとして鍛えられるかもしれない
      1. 小さなタスクで自分で模索しながら動くコードを書けるようにする
      2. 大きなタスクを分割してもらったり、指導をもらいながら完走できる
      3. 大きなタスクも自分でタスクをやる前に分割したり、全体設計をしたり、実装イメージをつけることができる
      4. コードと動作の関係を掴む
        1. PR や dev 環境などで、動作からコードがどう動いているかイメージする。「こういう動きをするなら、こういうケースだとバグりそうだな」が指摘できる
        2. コードから動作をイメージする。PRで、「このコードだとこんな変な動きになりません?」の指摘ができる
      5. デザインや仕様書とコードの関係を掴む
        1. まだ動作がない環境でも PR や dev 環境と同様にイメージする
          1. 「このデザインだとこの情報が足りない」
          2. 「この動きをするには情報がこのレイヤまで来ていないといけない」
          3. 「現在のコード設計だと実現が困難」「このような設計にすると楽に実現できる」

タスクを洗う

  • 上記の "デザインや仕様書とコードの関係を掴む" で掴んだ既存のコードとイメージしたコードのずれを探してリスト化する
    • 既存のコードにないものは全てタスクになる
    • 既存の設計で実現困難なものもリファクタのタスクになる

タスクを分解する

最初の分解
  • 洗ってリスト化したタスクを、可能な限り分担可能な形かつ小さなバッチに分解する
  • プロジェクトスケジュールを考えて、何人体制で対応しなければいけないか検討し、それに合わせて並列作業できるようにする
    • ある程度小さなバッチに分解した後に、クリティカルパスを特定する
    • クリティカルパスが大きすぎる場合には、そこをさらに分解してクリティカルじゃなくするためにはどうしたらいいか考える
    • 分解できない or スケジュールがきつい場合には、どうしたらクリティカルパスが最速で終わるか考える & チームを巻き込む
情報が増えたら再分解する

デザインがより詳細に固まったり、作業が途中まで進むとタスクに対しての詳細度が上がる。 その情報をもとに大きなタスクを細かく分解したり、足りないタスクを作成する。

順序を決める

優先度で組み替える

(間接的にでも)ユーザに価値を届けられる機能が優先。やってもユーザに価値が増えない機能は後回し。

不確実性の高いものから終わらせる

プロジェクト後半に不確実性の高いタスクが存在すると、いつ終わるか判断できず社内外のユーザに迷惑をかけてしまう。 できるだけ不確実性が高いタスクは早めに終わらせる。例えば以下のようなもの。

使ったことのないミドルウェアの使用
うまくいくかわからないアルゴリズムの使用
外部との連携
詳細仕様が未決定

ref: 不安とストレスから解放される見積りとスケジュール方法 - Qiita(再掲)

機能ごと完成させる
  • 原則として、1つの機能がユーザに届けられる状態まで一気にやった方が良い
    • 例えば プロジェクト全部のAPI -> プロジェクト全部のマークアップ -> プロジェクト全部の組み込み とやるより、一つの機能のAPI -> 一つの機能のマークアップ -> 一つの機能の組み込み をして都度完成させていく方が良い
    • 完成系に対してより早いフィードバックを得られ、その知見を次の機能を作るのに活かせるため

テストデータを整備する

local でテストデータが偏っていると確認が甘くなり、プロジェクト後半で問題が起こりやすくなる。 local の seeder に起こり得るパターンをあらかじめ作っておく、もしくはそれを作るタスクを作る。

割り振る

  • 可能であればメンバーの得意不得意・やりたいことを考えて割り振る
  • 途中で一人程度抜けてもプロジェクトが長く停滞しないように、情報を誰がどれくらい持っているべきか考えて進める

リリースまでにやらなくていいものを特定する

  • リリース後のインクリメンタルな改善で良いもの
  • ユーザ影響のないもの
  • コアの価値を提供するのに支障がないもの
    • できれば、コアの機能を提供するために「あれもこれも」とならないように仕様作成の段階から分離可能にするのをサポートするのが望ましい(理想)

ボールが落ちていないかチェックする

  • 落ちそうなボールは、積極的に拾う
    • 落ちていて後から出現したボールで問題になりそうなものは、軽微なものは自分で巻き取ってさっさと終わらせる or 大きそうなものであればメンバを巻き込んで分担を改めて考える
    • 後で忘れずに拾えるところに明記する
  • メンバーが落ちていたボールに気が付いてくれたり、拾ってくれたら感謝し、そういった行動を推奨する。PMにとって落ちていたボールはプロジェクト終盤の痛手になるため、拾ってくれる人は多ければ多いほど良い。

小さいイテレーションでやること

小さい目標を作る

目標は分かりやすければ分かりやすい方が良い。

  • 特定の見える成果物を作る
  • 何ポイント消化するか決める

その目標を達成するためにそれぞれのメンバーが何を頑張ればいいかブレークダウンして、担当を割り振る。 いつ、どれくらい頑張れば達成できるのか可能な限り明確化する。

成果物確認会を開催する

PdM, デザイナ, エンジニアと必要に応じてさらに上長を呼んで成果物の確認会を開催する。
開催タイミングは、機能が大体できたという状態で開催する。完全に完成してから開催するのではなく、ある程度機能ができた段階などにも開催し、プロジェクトの大きさに合わせて複数回開催しても良い。
議事録テンプレートには以下の要素を含める。

  1. 確認シナリオ
  2. エッジケース確認項目
  3. 「気になること」を書いて管理する場所

目的は早い段階でフィードバックを受け取り、改善をする。フィードバックは次の機能を作る時にも活用する。 具体的には以下のようなフィードバックを積極的に受ける。

  • やりたいことに対する成果物の方向があっているか
  • 仕様に対して実装もれがないか
  • バグがないか発見

おまけ

人数が少なければPMはストロングスタイルが通じることもある「みんな勝手にやってくれ。遅れたところや漏れたボールは俺が全部やるから。」
四人以上の場合は通用しないことが多い(体感)。三人くらいまでなら技術的に優秀なリーダがこの形でPM業務をやっているケースもある。

採用やってます

弊社ではエンジニアの採用を行なっています。
スタートアップ企業でのWeb開発に興味のある方は、ぜひカジュアルにご応募ください🤝

www.wantedly.com

画像引用元: Event illustrations by Storyset

Nuxt道場 弐面を開催しました🎉

f:id:kubotak:20210910162946p:plain

こんにちは久保田(@kubotak_public)です

2021/09/08 19:30よりNuxt道場 弐面を開催いたしました。
弐面は第二回という意味です。

記念すべき第一回の様子は以下です。

tech.macloud.jp

今回は弊社の津崎が登壇しました。
弊社のエンジニアはもともとフロントエンドを書いて来たエンジニアではなく、どちらかというとインフラやバックエンドがキャリアとしては多いです。
そんな我々も今ではNuxt.jsをTypeScriptを用いて開発しています。
今ではゴリゴリにTypeScriptを書いている津崎の発表を是非御覧ください。

以下イベント配信のアーカイブ動画です。 youtu.be

Nuxt.js x Composition API x TypeScript - Speaker Deck

また、弐面ではベースフード株式会社よりVPoE 煙草森直也さんが師範として登壇いただきました。
Shopifyとの連携した決済システムなど、なかなか聞くことのできない貴重な発表でした。
現在エンジニア募集中とのことです。気になる方はぜひチェックください)

その他、弊社プラットフォームM&Aクラウドを利用して資金調達をされた株式会社Re:Build 代表 鈴木孝之さんのMiddrewareの権限周りの大変だった話や、イベント初の道場破りtyamahoriさんのDocker Desktop on MacによるNuxtの開発Tipsの話など盛り上がりました。
配信は全てアーカイブとして残っていますので今からでも閲覧できます。ぜひご視聴ください。

Nuxt.jsのmiddlewareを使って権限チェックしたらスパゲティになってしまった話 - Speaker Deck

qiita.com

謝辞

配信をご覧くださった視聴者の皆様、また登壇をしていただいた皆様には感謝いたします。
今回の配信では私の配信環境によるトラブルで二度ほど配信が途切れることがあり大変申し訳ありませんでした。
(リモートワークのため自宅から配信してますが機材の見直しなど必要かもしれません・・・)

最後に

二度あることは三度あるということで、登壇したいという方がいらっしゃいましたらぜひ久保田までお声がけください。

M&AクラウドのPHP Conference 2021登壇速報!

こんにちは、M&Aクラウドのかずへいです。

先日、PHP Conference Japan 2021 のプロポーザル当落が発表されましたね! 今回、弊社はゴールドスポンサーもしております。

スポンサーでもトークでも盛り上げていくぞ!

全員インフルエンサー

弊社のエンジニアチームでは「全員インフルエンサー」という言葉があり、今回も全メンバーがプロポーザルを出しました。 全員インフルエンサーについては以下の記事を是非御覧ください。

tech.macloud.jp

当落発表の日はこのように各メンバー一喜一憂しておりました。

f:id:kazuhei0108:20210826235446p:plain
一喜一憂する人たち

運営さんありがとうございます!

登壇内容

それでは早速ですが、登壇内容を紹介していきます!

[ Sponsored LT ] LaravelとAWSで漸進的なプロダクト開発

fortee.jp

M&AクラウドではPHP、LaravelとAWSを使ってM&Aのマッチングプラットフォーム「M&Aクラウド」を開発しています。サービスリリースから徐々にアプリケーションとして成長していく過程でどの様な技術を組み合わせて課題を解決してきたかを、短い時間ですがご紹介させていただきます。

[ Regular Session (25 mins) ] LaravelとTailwindCSSで始めるコンポーネント指向UI

fortee.jp

Laravel7系から導入されたBlade Componentsと近年注目されているUtility FirstをコンセプトとしたTailwindCSSを利用して再利用性の高いコンポーネントの作り方を紹介します。 Blade ComponentsはVue.jsのSFC(Single File Component)のような使い方をBladeで実装できる機能です。 対象者はこれからLaravelを触る方やまだLaravel7系以前の@extend,@yield,@sectionを利用してレイアウトを作ってる方となります。

[ Regular Session (25 mins) ] 【IMO】コードレビューって難しいよね

fortee.jp

みなさんのチームでは日頃からコードレビューはされてますか? 弊社でもリリースするコードに対して2人以上のコードレビューを必須にしたりと活発に取り組んでいます。

コードレビューには以下のような効果が期待できます 「ソフトウェア品質の向上とアーキテクチャの統一」、「スキルの向上とナレッジの共有」 いかに効果的にコードレビューを実施するかによって、チームの成熟度やプロダクトの品質に影響すると言っても過言では無いかもしれませんね。

しかし、正直なところ自分はコードレビューに苦手意識がありました。 一度のレビューに時間がかかったり、他のメンバーと比較してコードの改善提案をする回数が少ないのです。。。 そんな私が苦手意識のあるコードレビューをどの様に克服していくのか、体験談を踏まえてお話しできればと思います!

[ Regular Session (25 mins) ] Repositoryパターンを維持しながらN+1問題を起こさないようにする方法論について

fortee.jp

速度は求めたい。ユーザのためである。 設計方針は崩したくない。開発者のためである。 「速度も求めつつ、既存の設計方針を守り、ユーザに価値を届ける。そんな方法が欲しい。」

こちらはそんな思いから生まれたテクニックを紹介するセッションです。

[ Lightning talk (4 mins) ] 【超特急】「SQLアンチパターン」 総おさらいLT 【4分で25個】

fortee.jp

PHPといえば、Web開発。 Web開発と切っては切り離せないのが「データベース」と「SQL」です。

このトークは、オライリー・ジャパン出版の名著「SQLアンチパターン」で紹介されている25のアンチパターンを「超特急」で学ぶものです。 わずか4分のLTで、25個のアンチパターンをおさらいします。 東京2020オリンピックのピクトグラムパフォーマンスのようなスピード感のある超特急LTをお楽しみください。

大事なところだけをギュッとして、明日からすぐ使える知識としてお届けできたら幸いです。

まとめ

いかがでしたでしょうか?どれか一つでも聞いてみたいトークはありましたでしょうか? 2021/10/02 - 10/03はぜひPHP Conference Japan 2021でM&Aクラウドのメンバーとお会いしましょう! カンファレンス当日はスポンサーツアーも行われるということで、弊社について直接質問などありましたら、ぜひお気軽にしていただければと思います!

また、弊社ではエンジニアの採用を行なっています。 ベンチャー企業でのWeb開発に興味のある方は、ぜひカジュアルにご応募ください🤝

www.wantedly.com

www.wantedly.com

それではみなさん、カンファレンスまでもう1ヶ月です!頑張って発表資料作りましょう!

Vue.js で入力フォームに Google reCAPTCHA v2 を埋め込む

f:id:hamakou108:20210802213420j:plain

Vue Composition API-0.3 Nuxt-2.1 TypeScript-3.7

こんにちは。エンジニアの濱田( @hamakou108 )です。

今回は Vue.js で作成した入力フォームに Google reCAPTCHA v2 を埋め込むコードを書く機会があったので、その実装例を紹介します。 またその際に利用した vue-recaptcha というライブラリについても軽く紹介します。

はじめに

  • 本記事執筆時点では vue-recaptcha は v2 のみ対応しています。
  • reCAPTCHA へのサイトの登録、サーバーサイドでのトークンの検証に関しては本題から逸れるため割愛します。

背景

M&Aクラウドの幾つかの入力フォームでは、スパムなどの不審なリクエストへの対策として Google reCAPTCHA を導入しています。 一方、以前からフロントエンドの Nuxt.js 移行を進めており、これらのフォームについても移行を行いました。

tech.macloud.jp

旧ページで reCAPTCHA を埋め込んでいた箇所では HTML のフォームによる POST を行っていました。 この場合はドキュメントにある通り、フォーム要素内に g-recaptcha タグを埋め込むだけで事足ります。

一方、 Nuxt.js の新ページでは API による POST を使用しています。 旧ページと同じ手法は使えないため、実装方法を再検討する必要がありました。

reCAPTCHA 埋め込みの実装

vue-recaptcha の利用

先人の知恵がないかググってみたところ、 vue-recaptcha というドンピシャなライブラリがありました。

github.com

vue-recaptcha は reCAPTCHA を埋め込みたいページにコンポーネントを埋め込むだけで利用できます。 また reCAPTCHA のオプションについては v-bind で設定でき、検証の成功やエラーのイベントも v-on でハンドリングできるので便利です。

vue-recaptcha は reCAPTCHA v2 にのみ対応していますが、弊社で利用しているものも v2 のみだったため、特に問題なく採用することができました。 またフロント移行が進むにつれて reCAPTCHA を使用するフォームが増えることが予想されたため、最低限の知識で reCAPTCHA を埋め込めるようなコンポーネントを vue-recaptcha をラップして実装しました。

実装したコンポーネント

以下のようなコンポーネントを実装しました 1

<template>
  <vue-recaptcha
    ref="recaptcha"
    :sitekey="sitekey"
    size="invisible"
    :load-recaptcha-script="true"
    class="recaptcha"
    @verify="onVerify"
  ></vue-recaptcha>
</template>

<script lang="ts">
import VueRecaptcha from 'vue-recaptcha'
import { defineComponent, ref, SetupContext, toRefs, watch } from '@vue/composition-api'

export default defineComponent({
  components: {
    VueRecaptcha
  },
  props: {
    submit: {
      type: Boolean,
      default: false
    }
  },
  setup(props, { emit }: SetupContext) {
    const { submit } = toRefs(props)
    const recaptcha = ref<InstanceType<typeof VueRecaptcha> | null>(null)
    const sitekey = // サイトキーを設定
    const onSubmit = (): void => {
      if (submit.value) {
        return recaptcha.value?.execute()
      }
    }
    const onVerify = (response: any): void => {
      emit('verify', String(response))
    }
    watch(submit, onSubmit)

    return {
      recaptcha,
      sitekey,
      onVerify
    }
  }
})
</script>

<style src="./recaptcha.scss" lang="scss" scoped></style>

以下、要点を説明します。

reCAPTHCA の実行

vue-recaptcha を使って reCAPTCHA の認証を実行する際は VueRecaptcha コンポーネントexecute メソッドを呼び出します。 呼び出しタイミングをロジック側で制御したいため、 template refs を使ってコンポーネントインスタンスrecaptcha という定数に格納し、 recaptcha.value?.execute() のような形で呼び出せるようにしています。

props の submit は親コンポーネントが reCAPTCHA を呼び出したいタイミングで true に変更されることを期待しています。 submitwatch で監視しているため、 true に更新された際に onSubmit メソッドが呼び出され、 reCAPTCHA の認証が実行されます。

reCAPTCHA の認証トークンの受け取り

reCAPTCHA の認証が成功すると VueRecaptcha コンポーネントから verify イベントが emit されます。 reCAPTCHA のレスポンスも一緒に渡されるので、それを文字列に型変換して親コンポーネントに emit します。 親コンポーネントではこのレスポンスを POST API のパラメータに含めることができます。

reCAPTCHA 実行用スクリプトの埋め込み

本来は reCAPTCHA の共通的な導入手順として実行用の JavaScript<script> タグで埋め込む必要があります。 しかし vue-recaptcha には<script>タグの inject 機能があり、 props に :load-recaptcha-script="true" を渡すことで必要なタグを自動的に <head> 内に追加してくれます。

まとめ

vue-recaptcha を利用して

  1. reCAPTCHA の起動が必要なタイミングで submit props の値を true にする
  2. verify イベントで reCAPTCHA のレスポンスを受け取る

の2つの手順のみで reCAPTCHA を埋め込むことができるコンポーネントを実装しました。 Vue.js で作成した web ページに reCAPTCHA を埋め込みたい方の参考になれば幸いです。

おわりに

M&Aクラウドではデザイナーやエンジニアを募集しています! 是非お気軽にご連絡ください!

www.wantedly.com

www.wantedly.com

www.wantedly.com


  1. Vue.js の Composition API 0.3 による実装のため、バージョン 1.0 以降の記法と異なる場合があります。

開発大臣制度とMACテック勉強会、あるいはフルスタックVSスペシャリスト

f:id:zacky2:20210718234003p:plain

どうもこんにちは、エンジニアの津崎です。

梅雨が明けて、モワっと蒸し暑くて気が狂いそうですね。

夏といえば、海。 海といえば「開発大臣制度」と、MACテック勉強会」でございます。(?)

そんなわけで今回は、今年から実験的に開始された「開発大臣制度」と、MACテック勉強会」についてご紹介したいと思います。

テクノロジーの力でM&A流通革命

f:id:zacky2:20210719002754p:plain

弊社のエンジニアチームでは、全ての作業を全員ができるように専門分野というものをあえて作らずにタスクを分配しています。 今までのフェーズでは「他のWebサービスにあるような便利な機能」をいち早く作ることが求められていました。 そのため、特別何かに詳しい必要はなく、エンジニア全員が「Webサービス開発」に詳しければ問題はありませんでした。

テクノロジーの力でM&A流通革命

この言葉は、弊社のミッションです。

Webサービス開発」に詳しいだけで、ミッションを実現できるのか?

私たちは、「革新的なサービスを作るには、新しい技術や深い専門知識をベースとした機能提案が必要である」と考えました。 その考えに基づき、新しい技術や専門知識をキャッチアップするために生まれたのが「開発大臣制度」です。

開発大臣制度

開発大臣制度とは、弊社のM&Aプラットフォームに関連するテクノロジーについて、各エンジニアが担当(=大臣)となり、そのテクノロジーについて独自に調査を行うというものです。 (チーム内で担当のことを大臣と呼ぶのが流行っています) それぞれが自由にいろんなことを調べるより、分野を区切り、分野ごとの担当を決めることで、効率良く知識レベルが上がることを期待しています。

弊社のM&Aプラットフォームに関連する技術は、CTOの荒井が以下のように分類しました。

  • ログ集計と分析
  • 検索
  • レコメンド
  • queue、メッセージ、非同期処理
  • セキュリティ
  • 外部API連携・スクレイピング

MACテック勉強会

大臣がそれぞれの担当技術について、社内のエンジニア(およびPdM、デザイナー)に知見共有する場が「MACテック勉強会※」です。 (※MACM&Aクラウドの略称)

週に一度、1時間の枠で行っています。各技術について3回行う想定で実施しており、これまで3回実施しました。

「レコメンド」

「レコメンド」の分野はCTOの荒井が担当しました。第一回は「レコメンドシステムとはなにか?」という話から、具体的なレコメンドアルゴリズムの解説について学ぶ内容となっておりました。

聞きかじったことのあるワードはありましたが、体型的に学んだことはなかったので勉強になりました。

f:id:zacky2:20210719110505p:plain
スライドタイトル
f:id:zacky2:20210719110500p:plain
目次
f:id:zacky2:20210719110731p:plain
強調フィルタリングの図解
f:id:zacky2:20210719111130p:plain
数式が載っていてかっこいいページ

「ログ集計と分析」

「ログ集計と分析」の分野は私が担当しました。第一回はデータ分析やビッグデータ分析基盤についての概要や他社事例について発表しました。 データレイク、データウェアハウス、データマートなどの分析基盤の構成要素についてや、実際の製品などについて紹介しました。

次回は、実際にRedShiftやAthenaなどの製品を使った具体的な紹介ができたらと思っております。

f:id:zacky2:20210719005043p:plain
スライドタイトル

f:id:zacky2:20210719103746p:plain
分散処理の図

f:id:zacky2:20210719103742p:plain
分析システムの全体像
(画像はデータ収集の基本と「JapanTaxi」アプリにおける実践例 こちらから引用)

f:id:zacky2:20210719103755p:plain

f:id:zacky2:20210719103751p:plain
データ分析のフロー

フルスタックVSスペシャリスト

私たちのチームでは、基本的には、全ての仕事を皆ができるようにフルスタックなスキルを求めています。 しかしながら、Web開発の技術だけではテクノロジーの力でサービスの爆発的なグロースを起こすことはできません。 一方で、私たちのような小さなチームでは、完全に分業スタイルではスムーズな開発ができません。 そこで、「開発大臣制度」というフルスタックにスペシャリストをちょい足しするという手法をとりました。

キャッチーなタイトルにするために「フルスタックVSスペシャリスト」をつけたことをここでお詫びします。すみませんでした。

おわりに

今回は、今年から実験的に開始された「開発大臣制度」と、「MACテック勉強会」についてご紹介しました。 「テクノロジーの力でM&A流通革命を」というミッションに従い、関連技術についてエンジニアそれぞれが担当をもち専門性を深める施策「開発大臣制度」。 そして、身につけた専門性をチームに共有する「MACテック勉強会」。 この施策がうまく機能するかまだ不明ですが、色々なことを試しながら、M&A×テクノロジーで最先端をいくエンジニアチームになれるよう努力していきます。

おっと、もしかして僕たちに興味がありますか?

なんということでしょう! M&Aクラウドでは共に働く仲間を募集しているようですよ!

www.wantedly.com

www.wantedly.com

M&Aクラウドで実践している不具合対応フローをご紹介します

f:id:tsukahara1991:20210709173755j:plain
不具合対応中

こんにちは、塚原(@AkitoTsukahara)です。

サービス開発を続けていると対策していても大なり小なり不具合が発生してしまいます。そのため、早期に不具合を発見して、少ない被害に抑えることが大切になります。(もちろん、不具合が発生しないことが一番!)

弊社では不具合を早期発見できるように2つの仕組みを用意しています。
1つは以前もご紹介したRollbarを利用したアラート検知する仕組みです。
Rollbarについて詳しく知りたい方は、こちらの記事をご覧ください。 tech.macloud.jp

もう1つは、非エンジニアでも不具合をSlackから報告できる仕組みです。今回はこちらの仕組みについて、ご紹介します。
弊社では非エンジニアでも不具合を報告できる「バグかもしれない報告」というSlackチャンネルを用意しています。ここでエンジニアは報告を受け取り、不具合を解消していきます。

不具合と言っても、サービスが停止してしまうような大規模障害もあれば、一部のユーザにのみ影響する不具合もあります。 緊急度に応じて対応方針が変わってくるのですが、その都度チーム間で対応方針を相談することでコミュニケーションコストが高くなり、障害対応の初動が遅れてしまう問題がありました。

そのため弊社では、不具合発生時の対応フローをまとめ、スムーズな対応ができるようにしています。

対応フロー

下の図は実際に弊社で共有されている対応フローになります。

f:id:tsukahara1991:20210712004022p:plain
不具合フロー

ポイントになるステップを補足させていただきます🙋‍♂️

「バグかもしれない報告」をSlackで受け取る

Slackのワークフロー機能を活用し、一定のフォーマットに沿って報告をしています。

f:id:tsukahara1991:20210711233414p:plain
バグかもしれない

ユーザ影響の調査を行う

不具合の影響度によって、早急に対応が必要なものかどうかをエンジニアが判断します。 影響度のポイントは「後戻りのできないユーザ影響なのかどうか?」
もう少し具体例を加えて説明させていただくと、

  1. サイト外に影響して取り返しのつかないもの
    ・ユーザへ重要な通知が届かない
    ・データベースに登録されるデータが欠損する etc

  2. ユーザ行動に影響する
    ・入力フォームの不具合で申し込みが進まない
    ・ログインできない etc

上記の2つが主な指標になります。 この判断が難しい場合は、他のエンジニアに相談するようにしています。

ユーザ影響高の場合

この場合は即日対応を行います。通常差し込みタスクが発生した場合はPMに対応すべきか確認するルールになっていますが、ユーザ影響高の場合は、エンジニア判断で不具合修正を進めて良いことになっています。エンジニア側で影響度を見極めて対応できることで、不具合発生時の初動を早めることが可能になっています。

まずはフローに沿って、早急にPMに不具合に関する情報共有を行い、報告を行ったエンジニアは取り掛かり中のタスクを一旦そのままにして不具合の対応に入ります。

ユーザ影響高ではない場合

この場合は対応タイミングをPMと確認することが必要になります。 弊社は2週間を1スプリントとして、毎週火曜と木曜をリリースタイミングにしています。 報告された不具合の程度によって、次のリリースまでに行うのか?現在のスプリント中に行うのか判断していきます。 ユーザ影響あるものは「2nd Priority」の方針に従って極力早いタイミングでの対応が奨励されています。

2nd Priorityについてはこちら。 tech.macloud.jp

報告者への対応完了報告

不具合が解消されたことを報告します。 同じ障害が起きない安心感を与えたり、似たような不具合が再発した時に再度報告してもらうことができます。

このような形で弊社では不具合の共有を行い、対応フローを整備しておくことで初動までのコミュニケーションコストを抑えて、スムーズな対応を可能にしています。このフローではコミュニケーションを減らすのではなく、不具合対応までの初動を早めることを目的としています。不具合発生時は常に報告・共有が重要なので単にコミュニケーションを減らせば良い訳でないので注意したいですね。

弊社では、一緒にサービス開発をしてくれる仲間を募集しています。 興味のある方はぜひご応募ください。

www.wantedly.com

M&Aクラウド初主催のエンジニア向け勉強会を開催しました

f:id:kubotak:20210630143334p:plain

こんにちは久保田(@kubotak_public)です

先日の2021/06/23にNuxt道場というオンライン勉強会を開催しました。

macloud.connpass.com

この勉強会は弊社でも扱っているフロントエンドのフレームワークであるNuxt.jsをテーマとした勉強会で、 株式会社Hajimariの三宅様、株式会社レアジョブの田原様を師範(登壇者)としてお迎えいたしました。

Nuxt道場はYoutubeLiveで配信したため、アーカイブとして現在でも視聴することができます。 Nuxt道場って何?という方はぜひご視聴ください。

www.youtube.com

今回の勉強会はM&Aクラウドでは初となる弊社主催によるエンジニア向け勉強会でした。 弊社主催で勉強会をすることによって次の効果を期待しています。

弊社を知ってもらう・興味を持ってもらう

弊社のようなベンチャー企業知名度が低く、エンジニア採用も難しいです。 そのため、一人でも多くのエンジニアに弊社を知ってもらうための広報活動の一環でもあります。

社外へ発信する・社内だけでは得られない知見を外から得る

広報活動だけでなく、社内のレベルを底上げするためにも自分たちが発信すること、また他社の事例や知らなかったことを知る機会を作ることが大事です。 弊社のエンジニアには「全員インフルエンサー」というバリューがあるのでこれを体現するためにも発表できる場を自分たちで作っていくことも大切です。

tech.macloud.jp

最後に

一回で終わらず、シリーズとして続けていければと思いますので登壇したいという方がいらっしゃいましたらぜひ久保田までお声がけください。 また、Nuxt道場に限らず弊社で扱っている技術であるLaravel道場やAWS道場などを開催しても良いかもしれません。

見えないエラーを見れるようにする & 効率化のため Rollbar を導入した話

こんにちは。エンジニアの鈴木(yamotuki)です。 今回は本番や開発環境でエラーが起こったときに、効率よく対応ができるように Rollbar というツールを導入した話です。

Rollbar とは

公式はこちら

JavaScriptPHPで発生したエラー詳細をSlack通知してくれます。
通知や画面詳細ページは後述してあります。

導入目的

導入目的としては、フロントエンドのエラー検知とバックエンドサーバのエラー対応の簡素化の二つがあります。

1. フロントエンドのエラー検知

Universalモード(SSRCSRでシームレスに動作する仕組み)で動いているNuxt.jsによるアプリケーションのエラー検知の仕組みが欲しい、というのが一番最初の導入のきっかけでした。 SSRで動いている部分については、なんとかしてログ出力をしてエラーを検知することをできるかもしれません。しかし、それぞれのクライアントで動いているJavaScriptについてはコンソールログにだけ出ている状態で、エラーが起こっていることを知ることができない、というのが一般的なお困りごとかと思います。
Rollbarを使用すれば、エラー発生時のSSR/CSRを問わない統一的な仕組みとしてエラー通知を行うことができます。

2. バックエンドサーバのエラー対応の簡素化

弊社では AWS CloudWatch によりCloudFrontやEC2で発生した5xx系のアラートを検知してSlack通知していますが、以下のように情報量が少ないのが悩みの種でした。問題調査をするためにAWSコンソールを開いて、該当のアクセスログや、対応するエラーログを確認する必要があり、ちょっとしたエラー確認でも手間がかかっていました。

f:id:yamotuki:20210615170011p:plain
調査に時間がかかるアクセスログの5xx検知

導入結果

フロントエンドのエラーを検知して対処できた

振り返って見てみると、この記事にかけるような面白いエラーはログ保存期間の間には起こっていませんでした。 導入当初には広範囲のユーザ影響が出てしまう致命的なエラーが何度か起こっていましたが、逐次対応してきた結果、最近ではエラー頻度はぐっと減っているようです。

バックエンドサーバのエラー対応が効率化された

Rollbar を使うと以下のように何が起こったのか詳細がSlack通知され、さらに詳細を見たければリンクをクリックするだけでいいので劇的に調査が楽になります。

f:id:yamotuki:20210615165935p:plain
RollbarからSlack通知

詳細画面に行くと以下のような情報を見ることができます

  • 何回、いつ、影響したユーザ(IP)数
    • 障害対応においては、どれくらい深刻な障害なのか?というのは重要な情報なので、これがログをいちいち漁って見なくてもまとまっているのが良い
  • スタックトレースを引数つきで見れる
    • 「最終的にエラーが起こっている場所は分かったけど、途中でなんでこうなった?」みたいなケースも簡単に追跡することができます

f:id:yamotuki:20210617190317p:plain
詳細ビュー

導入でハマった点&工夫した点

Nuxt.js

nuxt-rollbar-module を用いています。細かい導入方法についてはドキュメントを参照してください。
導入に際して工夫した点だけ共有します。

  • 問題点
    • local で rollbar 通知をすると回数制限を無駄にしてしまう。TOKENを入れないとrollbar通知するためのコードが無視されるので、localでうまく動いているか判断できない。
  • 解決策
    • plugins に dummy-rollbar.ts を作成し、rollbar を呼んでいるところは local では console.log にマッピングするようにしました。
import { Context } from '@nuxt/types'

export default (ctx: Context, inject: (key: string, value: any) => void) => {
  const rollbar = ctx.$rollbar ?? {
    debug: (...e: any) => console.log(...e),
    info: (...e: any) => console.log(...e),
    warn: (...e: any) => console.log(...e),
    warning: (...e: any) => console.log(...e),
    error: (...e: any) => console.error(...e),
    critical: (...e: any) => console.error(...e)
  }
  // ref: https://github.com/gaelreyrol/nuxt-rollbar-module/blob/develop/lib/templates/rollbar-client.js#L46-L47
  ctx.$rollbar = rollbar
  inject('rollbar', rollbar)
}

plugins の差し込みについては公式ドキュメントを参考にしてください。

Laravel

基本はドキュメントを読んで導入かと思いますが、ハマったところだけ共有しておきます。

config/logging.php で以下のような設定を入れて、error log と rollbar の両方に通知するようにしてあります。

<?php

    'channels' => [
        'errorlog_and_rollbar' => [
            'driver' => 'stack',
            'channels' => ['errorlog', 'rollbar'],
            'ignore_exceptions' => true,
        ],
        'errorlog' => [
            'driver' => 'errorlog',
            'level' => 'debug',
        ],
        'rollbar' => [
            'driver' => 'monolog',
            'handler' => \App\Providers\Rollbar\MonologHandler::class,
            'access_token' => env('ROLLBAR_TOKEN'),
            'level' => 'error',
            // rollbarでマスクしたいパラメータを指定
            'scrubFields' => [
                // user
                'password',
            // 以下略

rollbar の handler として指定している MonologHandler クラスの雛形はこちらです。

雛形の namespace が間違っている問題

こちらのライブラリへのPRが出されているように、namespaceが間違っていていました。

ignore_exceptions の問題

雛形のコードを少し書き換えて使っていたのですが、とある変数の初期化がされておらず無言エラーになり、本番通知がうまくされていませんでした。”無言”である理由はignore_exceptionsがtrueになっているからでした。この設定の意図としては、片方の channel でエラーが起こっても、握りつぶしてもう片方の channel には通知が行って欲しいという意図かと思われます。localで一時的に試しにfalseにしたところ、すぐにどこでExceptionを吐いているか特定し、修正できました。

開発環境にも入れておく

上記の通り、本番環境で迅速にエラー対応するために効果的なのですが、開発環境にも入れておくことで、エラーをユーザに見せる前に修正できることがあります。
開発環境に入れるときに通知先Slackチャンネルの分離に一工夫があったので共有します。

  • 問題点
    • Project ごとで通知先が一箇所しか選べない。Projectはトップレベルの階層で、その下にEnvironmentがあります。Projectの中の Rollbar の Items(エラーの一つ一つ)には Environment が紐づいているので、それによって通知先を分離したいと思っていましたが、できませんでした
  • 解決策
    • Project を開発環境、本番環境で分離しました。Environment が情報として冗長になってしまいますが、Slack通知先を分離することができました。

終わりに

www.wantedly.com

フロントエンドのエンジニアに届かないエラーを可視化することで大きな問題でもすぐに対応できるようになりました。エラー対応を効率化すると、神経をすり減らす障害対応を少し楽にすることができました。

弊社では生産性向上をして、ユーザにより多くの価値を一緒に届ける気持ちを持ったエンジニアを募集しています。

AWS LambdaからECS Fargateへの移行

こんにちは、久保田(@kubotak_public)です

今回は弊社で運用しているサービスであるM&Aクラウドのフロントエンドの実行環境をAWS LambdaからECS Fargateへ移行した話です。 まずは弊社のサービスが動いている環境は次のようになっていました。

f:id:kubotak:20210609141326p:plain

フロントエンドにNuxt.js(JavaScript)、バックエンドにLaravel(PHP)を利用しています。 LaravelはAWS ElasticBeanstalkで作成されたEC2インスタンス上で動作しています。

そしてフロントエンドのNuxt.jsはAWS Lambda上で動作し、API Gatewayを利用してHTTPによりアクセスできるようになっていました。 もともとはLaravelの環境だけでしたが、Nuxt.jsでフロントエンドをリプレースしたページが混在しているのが現状です。 これらはCloudFrontによって各環境にリクエストがルーティングされています。

Nuxt.jsへの移行に関しては別途シリーズでお届けしていますのでよろしければご参照ください。

tech.macloud.jp

なぜ移行するのか

このNuxt.jsの実行環境であるAWS Lambdaでは次のようなメリットがありました。

  • 運用が楽
  • 費用が安い

弊社の運用においてはLambdaのコールドスタートに関しても特に問題ではありませんでした。 一年程はLambdaによる運用にも特に問題にはなっていませんでした。

しかし、Nuxt.jsのアプリの肥大化により状況が変わってしまいました。 AWS Lambdaではデプロイできるサイズがzipの状態で50MB、展開した状態で250MBの制限があり、Nuxt.jsとTypeScriptのバージョンアップを行った際にこの制限に引っかかる様になってしまいました。

そこで、容量の制限に余裕がある環境への移行が求められ、Amazon ECSのFargateが候補にあがりました。

Amazon ECSとは

Amazon Elastic Container Service(Amazon ECS)は完全マネージド型コンテナオーケストレーションサービスであり、コンテナ化されたアプリケーションを簡単にデプロイ、管理、スケールするのに役立ちます。

AWS Fargateとは

FargateはECSやEKS上で動作するコンテナ向けサーバーレスコンピューティングエンジンです。 Amazon EC2 インスタンスでサーバーまたはクラスターを管理する必要なくコンテナを実行することができます。

サーバー管理にコストを掛けずに運用したいという考えからAWS Lambdaを利用していましたので、同じようにサーバー管理をマネージドしてくれるECS Fargateを採用しました。

AWS LambdaへのデプロイからAWS Fargateへのデプロイに切り替え

まずはFargateで動作させるためにDockerコンテナ化と、そのコンテナをホスティングする必要があります。 Dockerfileは非常にシンプルです。

FROM node:12.14.0-alpine

RUN mkdir -p /var/www/workspace
WORKDIR /var/www/workspace
COPY ./.nuxt /var/www/workspace/.nuxt
COPY ./dist /var/www/workspace/dist
COPY ./node_modules /var/www/workspace/node_modules
COPY ./.env /var/www/workspace/.env

EXPOSE 80

ENTRYPOINT ["node", "dist/server/server.js"]

※一部改変しています。

ベースとなるnode.jsのDockerイメージを利用してビルドしたアプリケーションがコンテナ内に配置されるだけです。

Dockerイメージのpush

DockerイメージはAmazon Elastic Container Registry(Amazon ECR)にホスティングします。 弊社ではアプリケーションのデプロイのCI/CDとしてCircleCIを利用しています。 CircleCIでECRへpush(Dockerイメージをホスティング)するには次のプラグインを利用しています。

version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@7.0.0

定義は次のようになります。

- aws-ecr/build-and-push-image:
          account-url: AWS_ECR_ACCOUNT_URL
          aws-access-key-id: AWS_ACCESS_KEY_ID
          aws-secret-access-key: AWS_SECRET_ACCESS_KEY
          create-repo: true
          region: AWS_REGION
          repo: repository-name
          skip-when-tags-exist: true
          tag: "${CIRCLE_SHA1}"

これでDockerfileを利用してDockerイメージの作成とECRへのpushをCI上で行ってくれます。

Fargateへのデプロイ

AWS LambdaへのデプロイはServerless Frameworkを利用していたので、同じ仕組みでFargeteへのデプロイを行いました。

Serverless Pluginを追加してFargateへのデプロイを追加します。 検索すると次のプラグインが上位に出ます。

GitHub - honerlaw/serverless-fargate-plugin: Serverless plugin to deploy fargate tasks to an ECS cluster.

しかし、こちらのプラグインは保守がされてなく、弊社の環境ではデプロイも失敗しました。 そこでこのプラグインをForkしているものを使っています。

github.com

※一部subnetに関する拡張を行いたかったのでコントリビュートしました
※このプラグインの作者が別途新規でプラグインを作成中ですのでそちらもチェックされると良いかもしれません。

デプロイして新環境で動いていることが確認できたらAWS Lambdaで動いている環境から切り替えます。 この切り替えは前段であるCloudFrontからの向き先を変更するだけです。

f:id:kubotak:20210609141837p:plain

移行してみて

AWS Lambdaと異なり、Fargateでは稼働している台数のハンドリングや利用しているCPUやメモリのリソースの把握が重要になってくるかと思います。 しかし、Fargateのオートスケールの設定などはわかりやすく、スケーリング自体もスムーズな印象です。 API Gatewayが不要になり、代わりにロードバランサーが追加された点などもあり、アーキテクチャとしては複雑になったという印象があります。 デプロイ時間に関してはECRへのイメージpushやECSがローリングデプロイをする関係上遅くはなってしまいましたが、現時点では運用して間もないので過不足は特に感じていません。 引き続き監視を行い、アプリケーションの成長に合わせてインフラもスケールするように改善していきたいと思います。

最後に

弊社のフロントエンドエンジニアは今回のようにAWS環境を利用した改善・保守も行います。
アプリケーションコードにとどまらず、インフラ環境も扱いたいフロントエンドエンジニアの方は一緒にアプリケーションを成長させていきましょう。

www.wantedly.com