TECHSCORE BLOG

クラウドCRMを提供するシナジーマーケティングのエンジニアブログです。

シナリオ機能をリリースしました

2020年7月、Synergy!の新機能としてシナリオ機能をリリースしました。 本記事ではシナリオ機能の開発者の一人として、開発において行った工夫や個人的な反省点をご紹介します。

f:id:techscore:20200805115131j:plain:w80 原 草平(ハラ ソウヘイ)
ミステリとSFが好きです。
森博嗣の『すべてがFになる』を読んだのがきっかけでIT業界に興味を持ちました。
小説以外にも哲学関連の本や技術書を読むのが好きです。


シナリオ機能概要

シナリオ機能とは、事前に定義したシナリオに沿って、顧客の行動に応じて適切な対応を自動で行う機能です。 例えば、あるフォームに登録してくれた人にメールを送ったり、そのメールを開封してくれた人には追加でお礼のメールを送ったり、そういった一連の顧客対応を顧客一人ひとりの行動に応じて自動で行う機能です。

f:id:techscore:20200803091906p:plain

これらのことは、既存のメール配信機能を組み合わせればできることもありますが、シナリオ機能には次のようなメリットがあります。

  • メール配信や開封による分岐などを画面上で直感的に設計できる
  • レポート画面で顧客の行動履歴を視覚的に確認できる

これにより、顧客の行動に合わせたコミュニケーションをより簡単に行うことができます。

2020年9月30日(水)までの期間限定で、シナリオ機能を活用した無料のゲーミングコンテンツ「LOVE×CRM ~シナリオをあなたが紡ぐ恋愛シミュレーション~」を公開しています。 気軽にシナリオ機能を体験できますので、ぜひご参加ください。
プレスリリースはこちら

開発で工夫したところ

ここからは、シナリオ機能の開発に携わった一人の開発者として、工夫した点やもっと工夫できたんじゃないかと反省している点を紹介します。

OpenAPI Specification の導入

シナリオ機能の開発とそれまでの開発とで大きく異なる点は、フロントエンド開発チームとバックエンド開発チームのコミュニケーション方法です。 コロナによる強制リモートワークの開始に伴い、フロントエンドとバックエンドのインタフェースの調整に OpenAPI Specification を使うようになりました。

シナリオ機能の開発が本格的にスタートしたのは今年の 2, 3 月あたりからです。 当社では、その頃にはすでにコロナ対策としてリモートワークへの移行が始まっていました。 働く環境の変化に合わせて、コミュニケーション手段もこれまでと異なる方法を用いるようになりました。

その一つとして新しく導入したコミュニケーション手段が、OpenAPI Specification に基づく API 仕様の文書化です。

これまで当社では、担当者同士が口頭で決めた仕様を相談し、API のリクエストとレスポンスを具体的な curl のリクエストや JSON ファイルなどで決め、必要に応じてチーム内で共有していくスタイルでフロントエンドとバックエンドの開発者がコミュニケーションを取っていました。

開発途中で仕様変更があったため一部のリクエスト内容が変更されていたり、レスポンスは最初に決めた形と同じ形だが想定とは違うデータが入っていたりなど、実際にフロントエンドとバックエンドを結合させたときに想定外の事態が発生することが多々ありました。

これまでのように、お互いの顔が見える状態で働いている場合であれば、細かい仕様の確認や調整など即座に行える環境だったので大きな問題はなかったのですが、リモートワークが始まってからはそうもいきません。

そこで、フロントエンドとバックエンドの認識齟齬をなくし、リクエストやレスポンスの詳細を都度確認し合う必要をなくすため OpenAPI Specification を使って仕様を共有することにしました。

OpenAPI Specification を使えば、レスポンスの項目ごとにそれぞれの説明を書くことができますし、ツールを使ってコードを自動生成することでリクエストとレスポンスの形を確実に仕様に合わせることができます。 それにより、不必要なコミュニケーションを減らしつつ、正確に仕様を共有できるようになりました。

シナリオツリーのデータ構造

シナリオを表現するツリー構造の実装については、今回採用した実装方法以外にも選択可能な実装方法があったのではないと思っています。 現状、お客様に使っていただくには支障はない部分ですが、個人的に反省している点を書いておきたいと思います。

シナリオはステップ(「メールを配信するステップ」や「開封 / 未開封の分岐ステップ」など)をツリー状につなぎ合わせて作成します。 シナリオのツリー構造を DB に保存するのですが、各ステップにその親ステップの ID を持つという表現方法を採用しました。 この手法は隣接リストというデータ構造で、構造がシンプルなためわかりやすい、というメリットがあります。 過去に似たような設計でツリー構造を表現して問題なく実装できていた経験から、今回もこの設計を採用しました。

しかし、その時に扱っていたデータは最大階層数に制限があり、また、データは参照用途でのみ使用されツリーの構造を更新することはありませんでした。 今回のシナリオ機能ではユーザが GUI で直感的にシナリオを構成できることがウリのひとつです。 階層の最大値は設けられていませんし、シナリオツリーのどこからでもステップの追加・削除が行えます。 頻繁にツリーのデータが修正される今回のケースでは、隣接リストを使うとツリー構造の操作に関するコードが多く複雑になってしまいます。 別のデータ構造を採用していればすっきりしたコードにできたのでは、と思っています。

まとめ

本記事では、7月にリリースしたシナリオ機能について、開発者の立場から振り返り工夫できたと思うところや反省点を紹介しました。

OpenAPI Specification の導入は、口頭での仕様共有に限界を感じ始めていたタイミングだったこともあり、このタイミングで導入できて良かったんじゃないかと思っています。 今後の開発でも、継続して使っていきたいです。

一方、ツリー構造のデータ設計については、改善の余地があると思っています。 シナリオ機能の開発が終盤になるについて、今回採用した実装方法以外の方法を採用したほうが良かったんじゃないかと考えるようになりました。 そんなことを考えるようになりながらリリースまであと1ヶ月ほどとなった頃に、技術的負債に関する翻訳記事が公開されました。

t-wada のブログ:【翻訳】技術的負債という概念の生みの親 Ward Cunningham 自身による説明

リンクの記事では技術的負債という言葉について、言葉の生みの親である Ward Cunningham が、一般に理解されている意味と本人が表現したかった意味との違いについて述べています。 ブログの著者である t-wada さんがうまくまとめている箇所があるので引用します。

Ward の言う負債の悪影響とは開発と共に得られていく知識、理解と目の前のシステムとの乖離が引き起こす生産性低下のことであり、(中略)Ward にとって負債の返済手段はリファクタリングであり、リファクタリングの目的は自分たちのドメイン理解と現時点のプログラムの乖離の解消です。

今回のツリー構造のデータ操作が煩雑になってしまった原因のひとつに、私のシナリオ機能への理解の不完全さがあったと思っています。 この記事を読んだとき、まさに現在のコードこそが技術的負債となっている状態なのだということがよくわかりました。 それと同時に、今後シナリオ機能を強化していく際にリファクタリングをしていく中で、そのときの自分のシナリオ機能への理解を最大限コードに反映させるよう努力すればよいのだと、今回の反省を今後に活かせる確信のようなものを得られました。

なかなか盛りだくさんでリリース直前まで忙しかった思い出が残るシナリオ機能の開発ですが、私にとっては多くを学ばせてもらった貴重なリリースでした。