株式会社M&AクラウドはVueFes Japan Online 2022のブロンズスポンサーです

株式会社M&AクラウドはVueFes Japan Online 2022のブロンズスポンサーです。
Vue Fes Japan は JavaScriptのUIライブラリであるVue.jsを扱った日本最大級のカンファレンスです。
2019年、2020年は災害や感染症リスクにより開催が延期されていましたが今年2022年10月16日(日)ついに開催となります。

vuefes.jp

弊社でもVue.jsを利用したフレームワークであるNuxt.jsを採用しております。

tech.macloud.jp

また、Nuxt.jsを扱ったオンライン勉強会「Nuxt道場」なども実施しています。

tech.macloud.jp

VueFes Japan Online 2022は無料でオンライン参加可能です。

全員インフルエンサー活動が3年経過してどうなっているかお伝えします

こんにちは、こんばんは、kubotak(@kubotak_public)です。

突然私事ですが、M&Aクラウドにジョインして丸三年が経ちます。(実際には11月ですが誤差)

tech.macloud.jp

私の入社後から弊社では社外発信を強めていこうという活動が始まりました。
これをエンジニアチームでは「全員インフルエンサー」というバリューで呼んでいます。

全員インフルエンサーについては以下を参照

tech.macloud.jp

簡単にどういう活動か説明しますと、エンジニア向けの投稿サイトで記事を書いたり、イベントに登壇していこうぜ!!!というアウトプットを推奨する活動です。
他社には見かけないなかなか尖ったバリューではないかと思います。
一応勘違いを避けるために、このバリューは強制しているわけではなく基本的には自発を促しています

まずは結果を振り返ってみる。

2020年から始めた活動ですがどのような結果を残せたのかを紹介したいと思います。

2020

イベント 登壇 LT
PHPerKaigi2020 - 1
PHP Conference 2020 1 3

エンジニア人数: 5人
計: 5回

2021

イベント 登壇 LT
PHPerKaigi2021 3 2
PHP Conference 2021 3 2

エンジニア人数: 6人
計: 10回

2022

イベント 登壇 LT
PHPerKaigi2022 1 5
スクラムフェス大阪2022 1 -
PHPカンファレンス沖縄2022 2 -
PHP Conference 2022 1 3

エンジニア人数: 8人
計: 13回

いかがでしょうか?人数とともに登壇数も伸びていて、まさに「全員インフルエンサー」を体現できていると思います。
ちなみに、ほんとうの意味でメンバー全員が登壇しているので文字通りの全員インフルエンサーでもあります。
そして、入社後に初登壇を果たしたメンバーは8人中5人も居ます!

なぜ全員インフルエンサーが可能なのか

正直なところ全員インフルエンサーはエンジニア人数が増えれば増えるほど難しくなり、今後は達成することは難しいことだという認識は持っています。
しかし、現時点でなぜここまでできたのかと言うと、以下のような取り組みのおかげだと思っています。

まだ人数が少ないうちに全員登壇経験をさせる

これは強制ではないので「させる」という言い回しは適切ではないと思いますが登壇できるようにサポートすることが大事だと思います。
周りを見渡せば全員が登壇経験がある。ということは登壇に対しての相談もできるし、登壇前にどんなプロポーザルを出すべきか、どんな資料を用意しておけばよいかなどのお手本が、「誰を見ても」持っているという状態になります。
登壇することに対しての心理的ハードルを下げることに役立っていると思います(逆にプレッシャーになっていたら申し訳ない)

イベントのスポンサーをやる

所属している企業が技術系イベントのスポンサーをしていることでそのイベント自体に興味関心を持ってもらいます。
そもそも知らないというメンバーもいると思います。しかし、「こんなイベントあるよ〜行ってみなよ〜登壇してみようよ〜」と言われても関心持てないですよね。
なのでスポンサーをすることで弊社はイベントに関心を持っている。というアピールをしていくのは大事だと思います。

勉強会チャンネルを用意する

弊社ではSlackに勉強会用のチャンネルがあります。そこでは次に開催されるイベントやスポンサーをするイベントを告知したり、そのイベントのプロポーザルが開始した際の告知をします。
さらにプロポーザルの開始時には特定のメンバーにメンションを送って「○○さんのあのときの実装の話できるんじゃない?」などの明確にどんな内容を喋ってもらいたいかまで伝えます。
個人的にはこれが一番効果があると思っていて、私自身も「最近やってることで喋れる内容無くない・・・?」と思いがちですが、他のメンバーから「あの話良さそう!」と提案をもらえるとありがたいです。

まとめ

「全員インフルエンサー」活動が3年経過したのでまとめてみました。
いかがだったでしょうか?他社でも真似できる取り組みがあればぜひ真似してみてほしいです。
また、「全員インフルエンサー」いいな、と思ったらぜひ弊社のカジュアル面談でもどうぞ!!!!

www.wantedly.com

M&AクラウドはPHPカンファレンス2022のゴールドスポンサーです

弊社M&Aクラウドは2022年9月24・25日に開催されるPHPカンファレンス2022のゴールドスポンサーです。
phpcon.php.gr.jp PHPカンファレンスプログラミング言語PHP」を扱う日本最大の技術カンファレンスです。
弊社から4人のメンバーが登壇予定です。

fortee.jp

fortee.jp

fortee.jp

fortee.jp

今年はオンライン・オフラインのハイブリッド開催となり、2019年以来の大田区産業プラザPiOにて開催されます。
弊社メンバーも数人は会場にて参加予定ですので見かけた際にはぜひ声をかけてください!

【スタートアップ】会社フェーズ毎のデータ活用とデータ基盤の「これから」

こんにちは。エンジニアの鈴木(@yamotuki)です。
データの活用とデータ基盤の構築に関する考えを整理したいと思い、この記事を書いています。

M&Aマッチングプラットフォームとしての「M&Aクラウド」が立ち上がった4年ほど前から、現在に至るまでデータをどう活用してきたのかというのをざっくりまとめた後に、今のデータ基盤構想とその背景にある考えを書こうと思います。

弊社におけるこれまでのデータ活用に関わる意識の変化

2018年~ M&Aクラウドリリースからしばらく

M&Aクラウドプラットフォームのリリースは2018年4月です。データ分析に対して深い知見のある人は社内にもちろんゼロ。しかし、google analytics は入れてあり、mouseflow などユーザ行動が見れるサービスも入っていました。mouseflow は登録フォームのファネルでの離脱点がどこかといった分析もできます。これらを活用して、PdMとエンジニアは以下のような分析をしてサービス改善をしようとしていました。

  • アクセスの多いページはどこだろう。全てのページが最低限の機能しかない。analyticsを見てユーザ数が多いところから改善していこう。
  • 登録フォームの離脱が多い項目はどこだろう。mouseflowを見てフォームの項目を整理したりステップ分離したりしよう。
  • 迷いを生む機能はどこだろう。mouseflowのレコーディングを見て、特にユーザがストレスを抱えているところはどこだろう。

弊社の主な顧客は経営者であり、母数としては多くないのでデータ量としてはあまり多くありません。多くの改善は定性的な情報に基づき「えいや!」で改善をしていました。また、KPIなど指標に関わるデータはエンジニアが依頼を受けて都度出力する運用になっていました。

2020年~ Redashの導入

Redash を導入しました。Redash はデータソースとなるAmazon RDSやSalesforceスプレッドシートなどに直接繋がっている状態でした。プラットフォームにおける主要な指標を、まずはPdM(マーケ担当兼任)が中心となって測定して改善に繋げようという目的です。
会員登録数やアクション数などがオンデマンドで情報が取れて、ダッシュボードで一覧として見れるようになりました。これにより、重要な指標になる数値がチーム朝会などで確認できるようになり、エンジニア側でもプラットフォームの数値への関心が高まってきました。

その後、Redashは顧客サポートをするメンバーをはじめ、社内全体にも解放されました。このRedash解放により、非エンジニアでも当たり前のようにSQLを使ってデータベースを参照する人が現れました。目的は、顧客サポートのための情報整理や、データ分析をしてサービスの改善提案をすることです。

2022年 データソン実施

弊社では定期的に(本当に定期なのか怪しいですが半年または1年ごとに)全社員が参加するハッカソンが開催されています。第3回ハッカソンは「データの活用」をテーマにしたいわゆる「データソン」です。

データソンを行う背景には以下のような意図がありました。(当時の資料から引用)

データソン。空・雨・傘で表現すると

- 空: データ活用の度合いが人によって偏っている
    - e.g. Redash のクエリ作成者が社内の特定のメンバーに偏っている
    - e.g. 部署に少なくとも1人ずつ詳しいメンバーが理想的だが、(多分)そうなってない
- 雨: 社内にどのようなデータが存在するのか、データをどのように扱えば良いのか、分析すると何が分かるのかイメージできてないのでは(仮説)
    - e.g. データの構造やフラグ値の意味などをエンジニアしか知らない
- 傘: ハッカソンで実際にデータ活用の流れを体験してもらう

全社にデータ活用の意識を持ってもらい、データドリブンの意思決定をすることで会社成長を加速させていこう、ということですね。今回は「データに親しむ」を重視して分析対象は絞り、対象データはプラットフォームのデータベースにあるもののみとしました。  

データソンは前半と後半の二部構成でした。

  • 前半: 学習の時間です。全社員がそれぞれ何人かのチームに別れて「神父」と呼ばれるSQLが既に書ける人に導かれてSQLを学んで書きました。なぜ「神父」かについては、以下の実際に出された問題のスクショを見てもらうとピンと来る人も多いのではないでしょうか。
  • 後半: 応用の時間です。「与えられた仮説からデータベースから事実を集め、何かの提案をする」というお題でした。仮説はたとえば「承諾されやすい打診には何か特徴や条件があるのではないか?」のようなものです。

データソンの問題例

各チーム奮闘し、結果の発表ではそのまま実務に使えそうな分析もありました。データソンにより、データとSQLに対する苦手意識はかなり減り、(おそらくCTOの筋書き通りに)会社としてデータ活用をしていくぞ!という機運が高まりました

これからのデータ利活用

このセクションはとても”文字文字しい"です。ちょっと読むのが大変かもしれませんがお付き合いください。

解決したい課題の全体観

さて、データソンで全社のデータ活用の機運は高まったのですが、まだまだ課題は残っています。大まかな課題は以下のものだと思っています。

  • ①プラットフォームのみのデータだけを見ていては、会社を効率よく成長させられない
    • プラットフォームには、会員登録をしてくれて、その上でマッチングした企業の情報しか載っていません。弊社はプラットフォーム外でのマッチングサポートも一部していますので、プラットフォームDBのような一つのデータソースをもとに分析した結果は、会社全体の成長という面だと片手落ちです。(※「プラットフォーム外」というのは、売り手や買い手またはその両方がプラットフォームに情報を登録していないケース。メールや電話での連絡など。)
  • ② 全社員がバラバラに似たようなクエリを書いていては、効率よく正確な意思決定ができない
    • エンジニアでもちょっとした情報が無いだけで集計を間違ってしまいます。たとえば deleted_at がついているものが論理削除されており「全数を count() で取得するときには deleted_at が null のものを外しましょう」という情報を全社員が持てるでしょうか(ここまでは分かっても、もっと複雑な条件は沢山あります)。部署ごとにちょっとした理解の違いで似たようなクエリを書いています。これでは信じられる結果にならず、全社の目線を合わせてコミュニケーションできません。

これらの課題の解決方法の一つの答えは、データ基盤を構築して、よく使う指標の元になるデータをデータウェアハウス(以下DWH)やデータレイクに整理して格納しておくことだと考えています。①については、データレイクにはそれぞれ格納した後に、DWHで集約し、プラットフォーム情報もそれ以外の情報も同列な情報として触れるようにすればよさそうです。②についてはデータ取得元としてデータウェアハウスに集約して、例えばdeleted_at問題であれば削除済みユーザはそこに居ないなど整理すればある程度解決しそうです。

データにまつわる具体的な課題

マッチング支援がスケールしない

主に①の課題に関わる部分です。
売り手と買い手のマッチングは弊社社員が頭を捻って紹介するのですが、人間の頭の中の情報だと限界があります。また、レコメンドとして推奨するマッチング先をシステムとして提供する場合も、参照できるデータがなければいけません。M&Aのマッチングは転職のマッチングとある程度類似性があるのでそれで想像してもらえると分かりやすいかもしれません。いくら「いい人」(M&Aだと「いい会社」)であっても、それにマッチする会社(M&Aだと買い手)に会えなければ良い転職はできません。転職エージェントは、転職希望者には沢山のマッチする会社を教えてあげる必要があります。

このマッチング問題に対しての解決策は、データとして「現状の買収戦略や予算」「M&A経験があるか」など各種データがリストで見ることができて、簡単に検索できるようになることが一つ考えられます。そこには世間に一般に公開されている情報以外にも、弊社のメンバーが力を使って集めた鮮度と確度の高い情報が載っているべきです。M&Aの業界だといわゆる"ロングリスト"と呼ばれるものですが、これが簡単に精度高く作れれば、マッチングの質が一定改善されるのではないかということです。
現時点では、そういった集められた情報は社内のスプレッドシートや各部署が管理しているSalesforce, プラットフォームのDBなどに散らばっており、全社横断で見れる形になっていません。

これの解決策としてデータ基盤として情報がデータレイクに集められ、クレンジングされた上でDWH・データマートに乗っかってすぐ取り出せる形が良さそうです。初期的にはSalesforceに情報を集約して暫定のロングリストとして提供することになりそうですが、その次のステップとしてSalesforceを一つのデータソースとしてその他のソースの統合をしていく可能性は高そうです(※構想段階なので2022/09/05時点では社内でも諸説ありです)。

全社に関わるKPIツリー構築が属人的

主に②の課題に関わる部分です。
弊社ではKPIツリーを作ることで、KGIとそれにたどり着くためのKPIの関係を明らかにして、事業のモニタリングと戦略決定に役立てています。KPI個別については戦略に関わるのでここには詳しくは書けないのですが、このKPIツリー作りが属人的になってしまっている問題があります。KPIツリー作りは社内の各所から人力とエクセル力により収集されて実現されています。人力だと転記ミスなども起こり得ますし、部署ごとにKPIの数値集計基準が揃っていないと信頼に足るデータではなくなってしまいます。例えば(※弊社KPIがどうであるかはぼかしつつ、あくまで例えば)プラットフォームの登録数ひとつとっても、「登録延べ人数」をとるのか「削除など考慮した月末時点での登録数」を取るのかで情報が変わってきます。こういった情報が「どのデータソースから」「どういう基準で整形して取られているのか」がコードレビューするようにレビューして整理できたら、より強固な情報をもとに意思決定をすることができるようになります。技術的な大枠の話だと、データレイクからDWHとデータマートを構築するときのSQLがレビューされて、運用開始後もいつでも集計基準を参照して間違いがあれば修正できるようになっているとよさそうです。

成約までがブラックボックスになっている

これは直近で全てを明らかにするというより、特に長期で取り組んでいきたい課題になります。
マッチング後のM&Aの成約までは、関係者の情報の非対称性や思惑が交差することにより定式化するのが難しい「ブラックボックス」になっている部分です。
マッチング後から成約までのフェーズには以下のようなものがあります。

  • 初回面談
  • 2回目面談
  • 買い手による「買収意向表明」
  • 見えている情報を前提とした買い手と売り手の「大筋合意」
  • 買い手による売り手の「実態詳細調査」
  • 成約

ここのデータの問題としては、どのような登録経路や、どのようなサポートをした顧客が、最終的にどのような成約につながっているかというのがデータとして"繋がっていない"という認識です。登録数もある、マッチング数、意向表明数もある程度取れている、成約数も取れている、となっているのですが、それがそれぞれ独立した集計値になってしまっているのです。
理想状態としては、成約に関わる情報が一元管理されており、その成約はどこから入ってきた売り手買い手のマッチングで、間のフェーズで何が起こったから成約したのだろう、というのが分かる形です。各フェーズでうまく行ったケースとうまくいかなかったケースの情報が、流入経路や途中でのサポートアクションを含めて整理されていれば、分析によってさらに適切なサポートを行えそうです。

データ基盤の技術選定に関する考え方

さて、データ基盤を作ろうという気持ちが高まって、目的もある程度見えてきたとします。技術チームがどのような意図で技術選定を進めているか、整理してみたいと思います。
構想段階での構成図は以下のような形です。

データ基盤の構成図

弊社は、昨年大型の資金調達を完了し、売上が伸びてきている状態です。一定のデータは集まってきており、データにより意思決定をできるフェーズになっています。ロングリストがしっかり運用できれば大きなリターンも見込めます。一方で、「データエンジニアリング」の専門家は正社員にはまだおらず、業務委託と顧問の方の知見を借りてアプリケーションエンジニアが構築を進めております。そういう背景ですので、技術選定は以下の前提でやっています。

  • 技術的なハマりどころを減らしたい。はまっても技術情報が豊富にあるツールが良い
    • データエンジニア専門としている人がメインで手を動かすわけでは無いので、ETL特有の辛さをある程度吸収してくれるツールが良い。クラスタ管理など自分たちでしたくない。
  • 使えるようになるまでの立ち上がりを速くしたい。種々のデータソースの対応は可能な限り楽にしたい
  • 長期に渡ってデータ活用したいので、作りっぱなしではなく改善サイクルを回しやすい方が良い
  • 価値があるデータが整理できるなら、ある程度お金を払うのはOK

その前提を受けて、今使用しようと検討している技術要素は以下のものです(本職データエンジニアの方、ツッコミ歓迎です!)。

  • DWH
    • インスタンス管理の必要なRedshiftではなくて、SnowflakeやBigQueryが良い(今のところBigQueryが有力)。Redshift Serverlessもよさそうだが、一般で使えるようになったばかりでハマると辛い可能性。
  • ETL
    • trocco
      • 種々のデータソースに対応(少なくともMySQL, スプレッドシート, Salesforceなど今見えている対象に対応) => ETLの辛さの低減
      • 日本でのユースケースが多い。サポート厚そう。slackベースで聴ける。 => 専門家リソースが少なくてもカバー
  • その他ツール
    • dbt cloud
      • BigQueryでデータレイク, データウェアハウス, データマートを構築したとして、その間の更新をできるだけ楽にしたい。使われ続けるための更新大事。

最後に

前述した通り、専門性を持って正社員でデータエンジニアをやっている人はまだいません。正社員でデータエンジニアをやってくださる方を募集してます。方向性に共感してくださった方がいらっしゃればお話ししましょう!
「こいつわかっていないからいっちょ教えてやるわ」という方も歓迎です。お話ししましょう。 twitter@yamotuki の方までDMを下さってもいいですし、実際にデータ活用を旗を振っているCTO荒井とのmeetyもあります。 よろしくお願いします!

新規プロジェクトのフロントエンドにSvelteKitを採用しました

こんにちは、こんばんは、kubotakです。(@kubotak_public

今回の記事は、M&Aクラウドの新しいプロジェクトのフロントエンドにSvelteKitを採用したよ!という内容です。
なぜSvelteKitを採用したのか、他のフレームワークと検討してなぜ採用に至ったのかなどを紹介したいと思います。
SvelteKitってなに?SvelteKit気になってる!な方はぜひお付き合いください。

SvelteKitってなに?

数年前からReact、Vue.jsに次ぐUIフレームワークとして人気が出ているSvelteをベースにしたSSRやSSGが実現できるフレームワークです。
Svelteは日本では名前を聞いたことがある程度で詳しく知らない。という方が多いと思いますが、StateOfJSでは2019年から人気のあるフロントエンドフレームワークです。
また、SvelteKitは2021年で満足度・興味ともに最も注目されています。

kit.svelte.jp

なぜSvelteKitを採用したの?

お世辞にも現時点で日本で知名度があるとは言えないSvelteKitをなぜ採用に至ったかという経緯をお話したいと思います。
まず弊社ではNuxt.jsを採用したプロジェクトがあります。
シリーズでNuxt.jsの採用事例を紹介しています。

tech.macloud.jp

新たに新規プロジェクトのフロントエンドの技術選定をすることになり以下を念頭に検討しました。

  • SSRができること
  • 素早くキャッチアップできること
  • 将来性のあるもの(?)

SSRできること

SEO周りでやはり未だにSSRできるという点は捨てきれず、検索流入が重要であることからこの要件は外せませんでした。
そのため、この点についてはNuxtもしくはNext.jsが真っ先に候補に上がりました。
この時点ではSvelteKitは存在こそ知っていましたが検討のステージに上ることはありませんでした。

素早くキャッチアップできること

弊社ではNuxt.js(v2+Typescript+CompositionAPI)による開発実績があるためNuxt3を採用した場合のキャッチアップについては懸念がありませんでした。
しかし、Next.jsについてはNext.js及びReactに関して深く理解できているメンバーがほぼいなかったこと、初期導入レベルを私が試した限り、useCallbackやuseMemoなどの利用の見極めやディレクトリ設計などに知識がないため開発の初動に大きく影響があるという感触を受けました。
今回の新規プロジェクトは最初期のリリースまでの速度が重要であり、開発スピードが重要視されているためこの点に不安を大きく覚えました。

将来性のあるもの(?)

昨今の流行りを鑑みると、やはりNext.jsが優位ではないかと思います。私はそう思いました。
逆にNuxtは、3年ほど前がピークでそこから人気に陰りがある印象を持っています。恐らくNuxt3のリリースがまだ正式ではないからではないかと思っていますが、エンジニア採用などを考えるとやはりReactが強いだろうなと思います。
さらにVue.jsに馴染みのあるエンジニアでも実はVue.js v2が大半で、v3構文になれている方は少ないのかな?という印象があります。

Next.jsか、Nuxt3か・・・

先程の検討をした結果、Next.jsかNuxt3か、という選択は意外にもPros/Consどちらもあり悩ましい結果となりました。
また、個人的な気持ちはNext.jsに寄ってはいたもののViteという新興のバンドルツールにも注目していて、Nuxt3はこのViteを採用していて開発体験を高めてくれそうだという期待があり、更に悩みの種となりました。
もういっそのこともっと新しいことにチャレンジしても良いのかもしれない?という気持ちになりSvelteKitを検討のステージにあげてみました。

SvelteKitを試してみて

公式ドキュメントは有志により日本語翻訳されているのでとても親切です。翻訳されていなくても公式ドキュメントは丁寧な作りで読むことに苦労することは少ないです。
SvelteKitもNext.js/Nuxtと似たようなルーティングの仕組みで違和感なく使えます。むしろSvelteKitの方が一歩進んでいる印象で、ファイル名に応じてAPIとして振る舞うエンドポイントを作れたりします。
Nuxt3のサーバールーティングをページルーティングと併せ持っているような感じです。
やはりSSRを利用するフレームワークですのでサーバー側でやりたい処理を分離できる仕組みを持っているのは好印象です。
また、バンドルツールとしてViteにもすでに対応していて起動がとても速くて快適です。
マイナスな面としてはいくつかあります。やはりまだメジャーバージョンとして正式にリリースされているものではないのでNuxt3同様の懸念があります。むしろNuxt3より開発が活発な印象があり今でもあらゆるAPIが議論を重ねて変わっています。

それぞれを比較して

これで検討にはNext.jsとNuxt3、SvelteKitがあがりました。
全てにおいてPros/Consはあり、どのフレームワークを採用しても私達が作るアプリケーションには過不足のない機能を持っています。
そこで、以下のことを満たしたフレームワークを採用することにしました。

  • メンバーからの同意が得られること
  • ワクワクするもの

1つ目の理由は当然として、2つ目の理由はやはりモチベーションを高く持って開発したいという意図があります。
その点でSvelteKitはまだ正式にリリースされているものではなく、いち早くプロダクションで使うことになります。
SvelteKitを使っている企業といえばM&Aクラウド、と思われるように先人を切って行くことはワクワクしませんか?

採用してみて

SvelteKitの開発はとても活発で体感としては2~3週間にはAPIの変更がある印象です。Github issueやDiscordを追ったりしていれば事前に変更を予測できますし、ルーティングの大幅な変更に関しては移行ツールも用意されています。
新しいAPIや仕様変更に伴いバグも発現してきますが迅速に修正されている印象があります。幸いにもまだプロダクションに動いているわけではないので開発を続けながら問題なく最新バージョンに追従して行けている状態です。

さいごに

SvelteKitで開発してみたいという方はぜひ弊社に声をかけてください!

www.wantedly.com

PHPカンファレンス沖縄2022に弊社エンジニアが登壇します

phpcon.okinawa.jp

PHPカンファレンス沖縄2022は2022年8月27日(土)に開催されるプログラミング言語PHP」の利用者をターゲットとした技術カンファレンスです。

弊社M&Aクラウドから、以下のタイトルで2名のエンジニアが登壇します。

FeatureToggle戦略と運用方法

レギュラートーク 10分
KenjiroKubota

新機能のリリースはどのように行っていますか?
私が所属している会社ではFeatureToggleを利用した機能リリースを行っています。
FeatureToggleとは、新機能のコードを含んだままデプロイを行い、フラグ機能により新機能の有効化・無効化を制御する手法です。
FeatureToggleでリリースするメリットとデメリットについて、またどのように運用をしているのかを紹介できればと思います。

スクラムマスターを経験して得られた学びとエンジニアとしての成長

レギュラートーク 30分
AkitoTsukahara

みなさんはスクラムで開発されていますか?スクラムマスターを経験したことがありますか?
何となくスクラムマスターはエンジニアマネージャーやリーダー適性のある人だけがやるものだと思っていませんか?
確かに適性はあるかもしれませんが、スクラムマスターを経験することで、エンジニアとしてのパフォーマンスが上がるきっかけも手に入れられると自分は考えています。

スクラムマスター経験を通じて得られた学びが、現在エンジニアとしてどのように活かされているのか、ご紹介できればと思います。

▼エンジニアにも効くスクラムマスター経験の学び
・ユーザ価値をより意識する
・アンラーンの面白さ
・ファシリテーション能力
・チームの観察と声かけ

本トークを聞いて、迷っていたけどスクラムやってみようかな?スクラムマスターやってみようかなと思って貰える人が少しでも増えたら幸いです!

2名とも当日は現地沖縄での参加予定です。
会場でお会いしたらぜひ声をかけてください!

Dependabotを導入してライブラリのアップデートを習慣化した話

こんにちは!こんばんは!エンジニアの大石です。

突然ですが、依存ライブラリのアップデートって大変ですよね。

大きなアプリケーションになればなるほど依存するライブラリが増えがちですが、定期的にアップデートされてないか確認したり、習慣的に小さくアップデートするのって結構大変だったりします。

アップデートされてないか確認するだけでも億劫ですし、フレームワークのバージョンを上げるってタイミングで芋づる式に全部上げることになってしまって辛かったり... などなど。

今回は、Dependabotを用いてGitHub上に自動で各ライブラリをアップデートしたPRを自動的に作る仕組みを導入して実際に運用してみた知見を共有したいとおもいます!

Dependabotって何?

Dependabotとは簡単に言うとGitHub上で自動的にプロジェクトが依存しているライブラリのバージョンを上げたPRを作ってくれるボットです。

npm、Bundler、Composer、Gradleなどなど主要なパッケージマネージャーやビルドツールにしてるので大体のケースにおいては有効化するだけで使えます!

入れておくと定期的に自動でライブラリのアップデートを確認しに行ってくれます(頻度は調整可能)。便利ですね!!

有効化してしばらくすると...

DependabotがGitHubに自動で作ってくれるPRの様子

このように自動でPRを作ってくれます!

DependabotのPRの画面から各ライブラリのChangelogも確認出来る

また、このようにライブラリごとにバージョンごとの差分と変更点をまとめて出してくれるので、PRを見て内容を確認してそのままマージする、もしくは詳細に調査してから慎重にアップデートするかの判断が出来ますね。

とりあえず有効化する

単純なLaravel+JSのプロジェクトであれば、以下のファイルをGitHubのプロジェクト上に配置してあげるだけで有効化できます。

.github/dependabot.yml に設定を記述したYAMLを置いておきましょう。

(設定ファイルの詳細な記述方法についてはGitHubの公式ドキュメントが非常に分かりやすいのでそちらを参照してください!)

https://docs.github.com/ja/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
    reviewers:
      - "※ レビュワーのGitHubのIDを指定"
    labels:
      - "アップデート対応"
      - "php"
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
      day: "monday"
    reviewers:
      - "※ レビュワーのGitHubのIDを指定"
    labels:
      - "アップデート対応"
      - "javascript"

弊チームでは毎週火曜日に定期的にDependabotで作成されたPRを確認する運用にしているので、毎週月曜日にアップデートの確認が動くように設定して、レビュワーを指定してリマインドするようにしています。

アップデートの運用

アップデートの確認が自動化されて、PRも自動で作られるようになって大満足!!!!ってなりがちですが、ちゃんと運用しないとただPRが放置されて終わってしまうので、弊チームでは以下のような運用にしてアップデートに対処しています。

アップデートのPRが作成されたらやること

(1) 即マージできるか?

テストで動作が担保できると確信できる場合はマージする。

開発時のみに依存しているライブラリの場合はローカルで動かして問題ないと確信できる場合はマージする。

(2)即マージほどではないが開発環境にデプロイしてマージできるか?

開発環境にデプロイして動作に問題ないと確信できる場合はマージする。

デプロイのみに依存するライブラリの場合もこの対応で良い。

(3)メジャーバージョンか?

メジャーバージョンの場合は基本的にどんなライブラリであってもマージしない。

対応IssueをJira上に作成し、どんな変更があったのかを調査してから安全にアップデートする。

(JIRAのIssueを作成するときは、GitHubのコメントに /jira <コメント> を入力で自動的にIssue作成)

(4)マイナーバージョンか?

1と2で問題ない場合はマージできる。

テストが落ちている等の場合はissue化して別途対応する。

(5)パッチバージョンか?

4と同じ

備考

問題ないと確信できない場合は、懸念点・不安解消ポイントなどをあげてJIRA上にIssue化する。

例えば大きめな動作確認が必要である、などなど。


といった感じに運用しています。

上に書いた運用ルールは実際に社内で使用している開発のドキュメントから引用したものですが、実際にこの運用で週に5〜10個程度のライブラリをアップデートしています。

ちなみに、Jiraに作成したアップデートのIssueの優先度付けは、以前開発者ブログにて投稿した「インフラタスク優先度定量化」の仕組みで付けています!

tech.macloud.jp

こちらも併せて読んでみてください!!

JiraのIssue作成の仕組み

JiraのIssueに毎回GitHubのPRのURLを貼り付けて、タイトルを書いて... という作業は結構退屈で辛い作業なので、Zapierと組み合わせて自動化しています。

Zapier側で組んだ自動化

仕組みとしては、GitHub上に /jira と書かれたコメントを書くとZapier側で検知して対象のPRから必要な情報を抜き出して、自動的にそれを元にJiraにIssueを作成するようにしています。

さいごに

今回紹介させていただいたライブラリのアップデートの運用は取り組みを始めてばかりですが、より安全に早くバージョンアップが出来るように随時運用の方もアップデートしていきたいとおもいます!

M&Aクラウドではエンジニアを積極採用しています!

www.wantedly.com

完全に余談ですが、最近弊社の社内部活動である #アイドル部 が盛り上がっていて、私が推しているアイドル(Appare!藍井すず)の名前が広まりつつあって嬉しさを感じています。

Dependabotを使ったライブラリのアップデートの取り組みも社内のSlackに投稿したところから始まったので、些細なことでもシェアできる文化は忘れないようにしたいですね!

祝100記事!技術ブログを継続する意義について

こんにちは、M&Aクラウドのかずへいです。2019年10月に始めたこの技術ブログも、ついに100記事目になりました🎉

大体2週間に1記事は書き続けてきた計算になります。継続できるのって本当にすごいですね!弊社のプロダクトメンバーは本当にすごいです。

今回は、この技術ブログについて振り返りながら、ブログを書く意義について考えていければと思います。

ブログの始まり

良い人が集まり、たくさんの良い仕組みを導入し、良いプロダクトを作り、それを発信して人が集まる、という好循環を作っていきたいと思い、この技術ブログは始まりました。

ブログを書き始めたときには、このブログには発信の役割を期待していました。ですが、記事が増えていく中で、ブログの役割は発信だけでは無いなと思うようになりました。

ブログは発信ではなく、良い仕組み導入のドライバー

ブログでは、過去にもいろんな良い仕組みを導入し、紹介してきました。例えば以下のようなものがあります。

tech.macloud.jp

tech.macloud.jp

tech.macloud.jp

他にも、弊社のM&Aクラウドの開発を進める上での知見を、様々な記事にしてきました。

ブログに書いた記事が増えるにつれて、次の記事では何を書こうか?これは記事に出来るような良い仕組みだったのか?等、 導入する仕組みについての振り返りや技術的な深堀りのきっかけづくりという効果が出始めました。

弊社ではブログのネタを何にするか話あったり、ブログの内容レビューをしたりといったことが日常的に行われています。 振り返りがより次の仕組みへ繋がり、結果的に新しい仕組み導入のドライバーになったなあと思っています。

ブログはオンボーディングの助けになる

また、ブログは新しいメンバーのオンボーディングの助けになりました。

新しいメンバーがつまずいた時に、これってどういう仕組ですか?と聞くと、この記事を読んでとブログの記事を共有することがよくあります。 外に出しても問題ないように、文章に気を使ったり、他のチームメンバーにレビューしてもらったりしているため、ブログの記事は分かりやすく、情報共有にもってこいです。以下の記事などは、弊社独自の仕組みを説明していて、新しく入ったメンバーに読んでもらうと有益です。

tech.macloud.jp

tech.macloud.jp

tech.macloud.jp

ブログが、チーム全体の学習を促す役割を果たし、当初の発信という目的以上の価値が出てきたなあと思っています。

ブログは文章を書く練習になる

エンジニアとして働いている方は、プログラムを書くのはもちろんのこと、PRにコメントをつけたり、社内向けにもドキュメントを作ったりと文章を書く機会が多いと思います。 社外に向けたブログを書くことは、文章を書くとても良い練習の場でになります。弊社ではブログを書いたら、プレビューをみんなに見せてレビューしてもらっているので、その点でもとても勉強になります。

ブログは発信の役に立ったのか?

そして、ブログは当初期待した発信の役割をできているのか?と言うところです。これは正直言ってまだまだだと思います。 弊社のブログがバズりまくって、弊社の名前がTwitterはてなブックマークを駆け巡り、カジュアル面談が何件も発生するというようなことは、残念ながら起きていません。

しかし、採用のための面談で「技術ブログ読んできました!技術頑張ってますね!」と言ってもらえることは増えました。 弊社と接点を持っていただけた方に、弊社のことを理解してもらうためのツールの一つとしては十分に役立っていると思います。

目標を置かずに続けていく

これからも、この技術ブログは続けて行けたらなと思っていますが、そのために大事なことは目標を置かずに続けていくことだと思っています。

例えば、目標として採用のための申込み数やPV数を置いてしまうと、どうしてもそれらの目標に見合ったものを頑張って書こうとなってしまいます。そうなると、ブログを書くこと自体が難しくなり、ブログを書くことによる発信や副次的な効果を失ってしまうことになります。

気負いせず、日々のチャレンジをメンバーが書き込んでいく形を続けることで、振り返りの機会を提供できる。そんなブログが続いていけばよいなと思います。

はじめての npm package

こんにちは。エンジニアの濱田鈴木塚原です。この記事はモブプログラミングならぬ、モブブロギングにより3人により書かれています。

今回は、複数レポジトリにコードのコピペにより同様のものが書かれていた処理を、 npm パッケージとして切り出した話です。

ライブラリ概要

作ったライブラリはこちらです。

github.com

inflow source は直訳すると「流入源」です。ユーザーがサイトに流入した経路を localStorage に保存しておくことで、後で何らかの CV が発生した時にその localStorage の情報をサーバー側に一緒に POST するために利用される想定です。「ユーザーがサイトに流入した経路」は例えばリファラ、ランディングページ、UTMパラメータ、CV前最終閲覧ページ、デバイス情報(pc/mobile)などです。

このパッケージは以下のようなインターフェースを持ちます(※TypeScriptの型情報から自動生成された index.d.ts です。本記事において瑣末な部分は一部省略されています)。

export declare type InflowSourceParams = {
    referer: string | null;
    landingPageUrl: string | null;
    utmSource: string | null;
    utmMedium: string | null;
    utmCampaign: string | null;
    utmContent: string | null;
    gclid: string | null;
    lastPageUrl: string | null;
    device: string;
};

export declare const useInflowSource: (storage: Storage, baseUrl: URL) => {
    set: (rawCurrentDate: Date | CustomDate, referer?: URL, currentUrl?: URL) => void;
    setLastUrl: (currentUrl: URL | undefined, ignorePathRegexpList: string[]) => void;
    getAllParams: () => InflowSourceParams;
};

メインは useInflowSource の中のメソッドで、軽くだけ説明します(本記事はパッケージ化のところが本流なので、詳細は割愛します)。

  • setメソッドを呼び出すと、ランディング判定(UTMパラメータがあるか、最終閲覧から30分以上経っているか)をした上で、 localStorage に流入源の情報を保存してくれます。
  • setLastUrlメソッドを呼び出すと、 ignorePathRegexpList 引数で設定した CV ページ以外のページを localStorage に保存しておいてくれます。
  • getAllParamesメソッドを呼び出すと、localStorageから保存したものをオブジェクトの形式で取得できます。 CV ページで POST するときに localStorage に保存しておいたものを一緒に body に入れるために使用できます。

背景

このパッケージを作ろうとした背景は、まず同じような処理が弊社内の複数のレポジトリに散っていたことでした。

弊社には、Laravel と生の JavaScript で書かれたいわゆる ”旧front” のレポジトリと、 Nuxt.js と TypeScript で書かれたいわゆる ”新front” のレポジトリがあります。サイト内の古いページは ”旧front" で書かれているが、最近書き直されたページは "新front" で書かれている混在状態です。ユーザがランディングしうるページはどちらで作られたものもあり得るので、「inflow source(流入源)保存」はどちらのレポジトリにも同様のロジックを記述しなければなりませんでした。

このロジック重複により、まずは新frontで TypeScript で実装し、動いたら旧frontに JavaScript で移植するという作業が発生します。対応するテストも重複します。 Jest で書かれたテストを、漏れがないように目視で確認しながら移植しなければいけません。この形だと将来の拡張の時にまた同じ辛さを抱えることになるので、同じ処理を npm package として切り出すことにしました。

構成

ここからは TypeScript のプロジェクトを npm package として公開する観点で構成を紹介します。

現在のバージョン情報は以下です。

  • TypeScript: 4.6.3
  • Node.js: 16.13.2

TypeScript で実装されており、以下のようなディレクトリ構成になります。

.
├── README.md
├── dist
├── example
│   └── index.js
├── jest.config.cjs
├── package-lock.json
├── package.json
├── src
│   ├── date.ts
│   ├── index.ts
│   └── user-agent.ts
├── test
│   ├── date.spec.ts
│   ├── index.spec.ts
│   └── user-agent.spec.ts
└── tsconfig.json

npm package として公開するにあたって重要なのは tsconfig.json と package.json になるので、これらの設定について説明します。まず tsconfig.json は以下の通りです。

{
  "compilerOptions": {
    "outDir": "dist",
    "noImplicitAny": true,
    "lib": ["ES2016", "DOM"],
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node",
    "declaration": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "paths": {
      "~~/*": [
        "./*"
      ],
      "@@/*": [
        "./*"
      ],
      "~/*": [
        "./src/*"
      ],
      "@/*": [
        "./src/*"
      ]
    }
  },
  "include": [
    "src"
  ]
}

lib には ES2016 に加えて DOM を記述しています。今回はブラウザ上で document.localStorage を使用しているため、この設定がないとトランスパイル時に Storage の型チェックに失敗します。

declaration には true を設定しています。弊社のフロントエンドでは TypeScript を利用しているため、型定義ファイルを作成して inflow-source の提供する API の型を参照できるようにしています。

esModuleInterop には true に設定しています。元々は未設定(デフォルトは false)でしたが、 日時の取得・加工に使用している Day.js のメソッド呼び出し時に TypeError が発生してしまいました。 esModuleInteropfalse の場合、 CommonJS で書かれたコードを ES Module のコードベースから import しようとする際に問題が生じる場合があるようです。 Day.js のエンドポイントに指定された JS ファイルを読むと、確かに CommonJS でビルドされていたので、 esModuleInteroptrue に設定してこの問題を回避しています。

また module の設定は書いていないため、暗黙的に CommonJS としてビルドされるようになっています。

続いて package.json は以下のように記述しています。

{
  "name": "@macloud-developer/inflow-source",
  "version": "0.1.0",
  "description": "inflow source を front 側で保存するためのライブラリ",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "tsc"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/macloud-developers/inflow-source.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/macloud-developers/inflow-source/issues"
  },
  "homepage": "https://github.com/macloud-developers/inflow-source#readme",
  "devDependencies": {
    "@types/jest": "^28.1.1",
    "jest": "^28.1.1",
    "ts-jest": "^28.0.4",
    "typescript": "^4.6.3"
  },
  "dependencies": {
    "@types/ua-parser-js": "^0.7.36",
    "dayjs": "^1.11.3",
    "ua-parser-js": "^1.0.2"
  }
}

パッケージ名で @macloud-developer/ のように記述することで組織名を表すことができます。

パッケージのビルドは単純に tsc コマンドで実行しています。社内ではビルドに webpack を用いるプロジェクトが多いため、最初は訳も分からず webpack でビルドしようとしていました(爆)が、特に出力ファイルをバンドルする理由もなかったので外しました。

main および types はそれぞれパッケージのエントリーポイントおよび型定義ファイルのパスを指定します。基本的に tsconfig.jsonoutDir で指定したディレクトリ上の index.js と index.d.ts が参照される形に設定すれば良いと思います。

また明示的に書いていませんが、 type: module は外しておき、暗黙的に CommonJS としてビルドされていることをパッケージ使用者側に示しています。

パッケージの publish

npm publish コマンドを用いて npmjsレジストリに登録します。詳細はドキュメントに譲るとして、ざっくり以下の方法で行います。

  • npmjs にユーザー登録。organization を作り、他の開発者を招待しておく。
  • ビルドして dist ディレクトリに JS ファイルと TS の型定義ファイルがある状態で npm publish --access public コマンドを実行

ライブラリの読み込み

public なパッケージとして公開できたので、あとは他の通常のライブラリと同様に npm install してコードベース上で import して読み込むだけです。例えば Nuxt.js であれば、以下のように plugin 上で router.afterEach() のコールバックから useInflowSource().set() を呼び出すことで、ページ表示・遷移のたびに流入源の情報が localStorage に保存されます。

import { Context } from '@nuxt/types'
import { useInflowSource } from '~/compositions/common/inflow-source'
import useDate from '~/compositions/libs/date'

export default (ctx: Context) => {
  if (process.server) {
    return
  }

  const inflowSource = useInflowSource(window.localStorage)

  const getUrl = (url: string): URL | undefined => {
    try {
      return new URL(url)
    } catch (e) {
      return undefined
    }
  }

  if (ctx.app.router === undefined) {
    return
  }
  ctx.app.router.afterEach(() => {
    inflowSource.set(
      useDate().current(), getUrl(window.document.referrer), getUrl(location.href)
    )
  })
}

まとめ

今回、旧frontと新frontの共通機能を npm package 化したことによって、双方の環境にコピペされたコードは共通化され、保守性、拡張性に強い実装にすることができました。以前までは重複したコードが旧frontと新frontでそれぞれ300行近くありましたが、対応後はパッケージを読み出すだけのシンプルなコードで100行程度にまとめることができました。また今後機能追加が必要になっても、 package 側のコードを修正して、旧frontと新frontでパッケージのバージョンを上げるだけで済むようになりました。

README は現在進行形で自分たち以外の方が読んでも分かるようにアップデート中です。インストール方法から動かし方をまとめていきますので、もしご興味のある方はダウンロードしてみてください。

M&Aクラウドではエンジニアを積極採用しています!

www.wantedly.com

www.wantedly.com

マーケが求めるスピード感に伴走するためにデザイナーが行ったこと

こんにちは。M&Aクラウドのインハウスデザイナー、池田です。最近デザイナーが増え、長いこと1人体制だったのが急に3人になり、チームにな利ました。嬉しい反面、2人とも僕よりずっと優秀なので振り落とされないように頑張っていこうと思います!

デザイナーが増える一方で他部署の採用もトントンと進んでおり、前回記事を書いたタイミングから20人くらいメンバーが増えました。そうなるとデザインが絡む施策の数も増え、デザイナーもサービスデザインのみならず、さまざまな業務をこなさなければなりません。

その中でも少し頭を抱えていたのがバナーやLPの制作です。とくにバナーは同じような雰囲気で、文言だけ変えて制作して欲しいみたいな要望が多いです。その要望に都度デザイナーがアサインできるかというと難しいです。

そこで、いかにデザイナーのリソースを最小限に抑え、品質が担保されたバナーを制作できるかを考えました。

Figmaを用いたボトムアップ的にクリエイティブを制作してもらう

現在弊社のデザイン業務の大半はFigmaに移行しています。Figmaに移行したおかげで非デザイナーでもデザインファイルを網羅的に確認することができるようになったので、認識の齟齬がだいぶ小さくなったと実感しています。 それと同時に、非デザイナーでもボトムアップ的にバナーやサムネイル画像を制作できる仕組みを作ろうと思いました。

Figmaでテンプレートパターンを作成

実際にやったこととしては、Figmaデザインパターンを洗い出し、該当するテンプレートをコピペしてテキストを変更、エクスポートまでを一貫して行えるような体制を作り始めました。

Figmaのテンプレートファイル

テキストを入力することでレイアウトが崩れることを防ぐためにAuto Layoutを用いて制作しています。 すべてのバナーデザインをパターン化、テンプレート化はまだできていませんが、今後一定数以上のバナーのパターンが出てきたタイミングでテンプレート化を進めていこうと考えています。

ノーコードを導入、制作後は運営サイドに渡す

LPを制作する度にエンジニアリソースを割けないので、簡易なLPであればノーコードを用いてデザインテンプレートを制作し、量産化を図るなどを行っています。

STUDIOで制作
最初はSTUDIOで作成を行なっていましたが、最近ではグローバル観点からWixを導入して制作しています。 ツールに関しての説明は省きますが、便利な反面、FigmaAdobe XDの操作感に慣れている人からすると多少違和感があるかもしれません。

まとめ

インハウスで働いていると、マーケティングのみならず様々な部署からの依頼も四方八方から来ます。その中でデザイナーがバリューを発揮するためには、手段にとらわれず柔軟に動いていく必要があると改めて実感しました。

M&Aクラウドではエンジニアを積極的に募集してます

www.wantedly.com

www.wantedly.com