DUICUO

DidiがLogicFlowをオープンソース化:プロセス可視化に重点を置いたフロントエンドフレームワーク

Jumeiの紹介: LogicFlowは、Didi技術チームのカスタマーサービスにおける経験から生まれました。Didiのインテリジェントミドルプラットフォームエクスペリエンスプラットフォームによって開発されたLogicFlowは、ワークフローを可視化するためのフロントエンドフレームワークです。フローチャートの操作と編集に必要な一連の基本機能に加え、柔軟なノードカスタマイズ、プラグインなどの拡張機能を提供し、業務システムにおけるフローチャート編集者のニーズに迅速に対応できます。現在、LogicFlowは社内外の様々なユーザーのワークフロー構成ニーズにおいて検証されています。

1.

背景

まず、Didiのインテリジェントミドルウェアエクスペリエンスプラットフォーム技術チームは、Didiのほぼすべての事業セグメントのカスタマーサービスシステム要件をサポートしました。多様で急速に変化するビジネスシナリオに対応するため、従来のシナリオベースのプログラミングはコストと時間がかかりました。そこで、オンラインで構成可能な運用システムを構築し、運用チームと製品チームがフローチャートを描画することでオンラインビジネスロジックを変更できるようにしました。例えば、ユーザーからの電話に対するインタラクティブな音声応答、ユーザーの電話に対応する人間のカスタマーサービス担当者のための標準操作手順、ユーザーが自主的に問題を解決するためのH5ページ構成システムなど、ユーザーごとにパーソナライズされたアプリケーションシナリオを作成できます。

第二に、すべてのビジネスシステムはプロセス可視化技術の適用を必要としますが、そのニーズは多岐にわたります。フローチャートやデータ形式に関する要件が比較的シンプルなものもあれば、BPMN仕様に従ってフローチャートを描画する必要があり、より高度なカスタマイズが求められるものもあります。市場にある関連フレームワーク(BPMN.js、X6、Jsplumb、G6-editor)を調査したところ、いずれも特定のニーズを満たしておらず、統合されたテクノロジースタックのコストが非常に高くなることが判明しました。具体的には、以下の通りです。

  • BMPN.js と Jsplumb は拡張性が不十分で、カスタム ノードをサポートするためのコストが高く、完全なインポートのみが可能で、各システムが必要に応じてインポートすることはできません。

  • バックエンドのワークフローエンジンへの適応にはコストがかかります。データ変換、ワークフロー検証、その他のカスタマイズされたビジネス要件をサポートしていません。

  • ドキュメントと事例が不完全です。X6とBPMNのドキュメントは不完全で、事例も少ないです(2020年の初期調査からの結論)。

そこで、さまざまなシステムのプロセス可視化ニーズに対応するため、2020年前半にLogicFlowプロジェクトを立ち上げました。

2.

LogicFlowの機能と特徴

LogicFlow の現在の機能を 2 つの部分に分けて紹介します。

▍ 1.フローチャートエディタを素早く構築する

フローチャート編集に必要なすべての機能を提供します。これは LogicFlow の基本機能でもあります。

  • グラフ描画機能を提供します。SVGをベースに、様々な形状のノードと線を描画でき、基本的なノード(四角形、円、多角形など)と線(直線、ポリライン、曲線)を提供します。

  • インタラクティブなグラフデザイン。ノード、線、グラフ自体に対する様々なマウスイベント(ホバー、クリック、ドラッグなど)に反応します。例えば、ノードのドラッグ、ドラッグによる接続の作成、線の調整、ノードのダブルクリックによるテキスト編集などです。

  • 編集効率を向上します。グリッド、位置合わせライン、前へ/次へボタン、キーボードショートカット、画像のズームイン/ズームアウトなどの機能を提供し、ユーザーの編集効率を向上させます。

  • 豊富なAPIセットを提供します。ホスト開発者は、API呼び出しを通じてパラメータを渡したり、イベントをリッスンしたりすることで、LogicFlowと対話できます。

これらの機能により、フロントエンド開発者はプロセス可視化アプリケーションを迅速かつコスト効率よく構築し、スムーズな製品インタラクションを実現できます。以下は、LogicFlowの組み込みノードとサポート機能を使用して作成されたフローチャートの例です。

▍ 2. ビジネスシナリオに基づいた拡張

基本機能だけではビジネスニーズを満たせない場合は、ビジネスシナリオに基づいて拡張する必要があります。これは、LogicFlowが複数の顧客サービスシステムをサポートできるようにするコア機能でもあります。

  • 画像上のすべての要素のスタイルを設定します。例えば、ノード、線、アンカー、矢印、配置線などのサイズや色を変更することで、フロントエンドのスタイル調整のニーズに対応します。

  • API拡張。API拡張を介して画像ダウンロードメソッドを提供するなど、LogicFlowへのカスタムメソッドの登録をサポートします。

  • カスタムノードと線。長方形、円形、その他の組み込みグラフィカルノードは、実際のビジネスニーズを満たせないことが多く、ビジネス上の重要性を持つノードを定義する必要があります。LogicFlowは、ワークフロー承認シナリオにおける「承認」ノードなど、カスタムグラフィックとビジネスデータを使用してノードをカスタマイズする機能を提供します。

  • 拡張コンポーネント。LogicFlowは、SVGレイヤー上にHTMLレイヤーと一連の座標変換ロジックを提供し、HTMLレイヤーへのコンポーネントの登録をサポートします。ホスト開発者は、LogicFlowのAPIを使用して、ノードの右クリックメニューやコントロールパネルなど、任意のViewフレームワークに基づくコンポーネントを開発できます。

  • データ変換アダプタ。LogicFlow がデフォルトでエクスポートするグラフデータは、すべてのビジネスニーズに適さない場合があります。このような場合、アダプタ API を使用して、LogicFlow への入出力時にグラフデータに対してカスタム変換を実行できます。例えば、BPMN 仕様に準拠したグラフデータに変換できます。

  • 組み込み拡張機能。上記の拡張機能をベースに、BPMN準拠のノードやデータアダプタ、デフォルトメニューなど、カスタマーサービス業務から派生した汎用ノードやコンポーネントを格納するための拡張パッケージも別途提供しています。拡張機能は個別にインストールでき、必要に応じてインポートできます。

前述の拡張機能をベースに、フロントエンド開発者は実際のビジネスシナリオのニーズに応じて、必要なノードやコンポーネントなどを柔軟に開発できます。以下は、LogicFlow拡張機能に基づいた2つのフローチャートです。

BPMN

承認プロセス

▍ 3.ポジショニング比較

上の図は、LogicFlowの位置付けを理解するために、いくつかの有名なオープンソースフレームワークを2つの軸で比較したものです。横軸はフレームワークのグラフ可視化機能の豊富さを表し、縦軸が高ければ高いほど、ビジネスプロセスアプリケーションにおけるフレームワークの成熟度が高く、初期導入開発コストが低いことを意味します。これらのフレームワークを一つずつ紹介していきましょう。

  • Activiti はワークフロー エンジンとして、フロントエンドおよびバックエンド ソリューションを提供し、簡単な二次開発でビジネス プロセス管理プラットフォームを展開できます。

  • Bpmn.js: BPMN 2.0 仕様に基づいて設計されたフローチャート エディター。

  • G6: Antv の子会社。エコシステム ツリー、マインド マップ、放射状ダイアグラム、インデント チャートなどのグラフィカルな視覚化とさまざまな分析チャートを専門としています。

  • X6: ノード、接続、キャンバスといったコア機能を備えたグラフ編集エンジン。フローチャートだけでなく、DAG図やER図もサポートしています。

LogicFlowは、上図のBpmn.jsとX6の間に位置し、両者のギャップを埋める役割を果たします。LogicFlowの中核はフローチャートエディタを提供し、BPMNなどの標準規格で要求されるプロセスノードとデータ形式をサポートするように機能を拡張することで、現在のビジネス要件を満たします。

3.

実装の原則とアーキテクチャ

▍ 1.全体アーキテクチャ図

コアパッケージ @logicflow/core はフローチャートエディターの基本機能を提供しますが、右側の @logicflow/extension は @logicflow/core に基づいて開発された拡張プラグインです。

▍ 2.フローチャートエディタの設計図

このセクションでは、主にフローチャート エディターを実装するためのキーの選択とソリューション設計について説明します。

2.1 画像レンダリングスキーム

フロントエンドのグラフィックレンダリングには、基本的にHTML + CSS、Canvas、SVGの3つの手法があります。これらを比較し、それぞれの長所と短所を列挙しました。

フローチャートのシナリオでは、多数のノード(最大で数千要素)をレンダリングする必要はなく、アニメーションの要件もそれほど高くありません。SVGのDOMベースの性質は、学習と開発のコストが低く、DOMに基づく拡張性が高いという理由から、フローチャート作成に適しています。ただし、SVGタグはdivなどの他のタグの挿入をサポートしていないため、特定の機能を実装する際には、他のHTMLタグと組み合わせる必要があります。

そのため、最終的に画像のレンダリングにはHTML + SVGを使用することにしました。SVGはグラフィックと線を扱い、HTMLはテキスト、メニュー、背景、その他のレイヤーの実装に使用します。

2.2 モジュールの抽象化

上記のソリューションに基づいて、次のステップはフローチャートの実装を分類および抽象化することです。

上記の図に基づいて:

  • 機能拡張を容易にするため、異なる役割を担う複数のレイヤーを構築しました。最上層はSVGレイヤーで、すべてのグラフィック(ノード、ライン、アライメントライン、アウトラインなど)がレンダリングされ、グラフ上の様々なイベントをリッスンします。SVGレイヤーの下には、UIコンポーネントの拡張を担うコンポーネントレイヤー、グリッドのレンダリングを担うグリッドレイヤー、そしてカスタム背景を追加するための背景レイヤーがあります。

  • Shapeの主な役割は、SVGベースのグラフィックレンダリングをカプセル化し、デフォルトのスタイルを提供し、ユーザー入力属性を変換することです。Shapeには主にRect、Circle、Ellipse、Polygon、Path、PolyLine、Textなどが含まれており、LogicFlow内での再利用を容易にします。例えば、円形ノードとアンカーポイントはどちらもCircleを必要とします。

  • Shape をベースに、ノードや線に必要なアンカー ポイントや線上の矢印など、多くの小さな要素も実装されています。

  • BaseNodeとBaseEdgeは、ノードとラインの共通機能をカプセル化し、シェイプ、アンカーポイント、テキストを集約するほか、イベントとスタイルの処理もカプセル化します。BaseNodeを継承し、シェイプを渡すことで、RectNodeやCircleNodeといったレンダリング可能なノードを取得できます。

フローチャートはこれらの基本モジュールによって豊富なインタラクティブ性、あるいはむしろ再編集されているため、次のステップはリッチなインタラクティブソリューションを設計することです。つまり、ユーザーがダイアグラム上で行うあらゆるアクションに対して、ユーザーが反応を示すようにする必要があります。例えば、ノードをドラッグすると、関連する線もそれに応じて移動する必要があるかもしれません。また、システムは特定の水平線上に他のノード(位置合わせ線)があるかどうかを識別できる必要があります。

2.3 MVVM + 仮想DOM

まず、グラフエディター全体に大量の状態ストレージがあり、グラフ上の様々なモジュールからのレスポンスを可能にするには状態通信機能が必要であると考えます。次に、やり直し/元に戻すなどの機能を実装する場合、グラフ全体がデータに基づいてレンダリングを導出する必要があります。つまり、fn(state) => View です。より良いアプローチは、モデルを介してビューを制御することです。

最終的に、LogicFlow グラフエディタは、現在のフロントエンドエンジニアリングで広く使用されている設計パターンである MVVM に基づいて構築することにしました。これにより、グラフのビュー層とモデル層を定義でき、コードの分離が可能になります。同時に、状態管理とデータ応答機能を実装するために Mobx を導入しました。各グラフは単一のモデルに基づいて状態をやり取りします。さらに、Mobx を採用したもう一つの理由は、きめ細かなデータバインディング(監視)が可能になり、不要なレンダリングを削減できることです。

以下は、LogicFlow グラフ エディターでの MVVM の概略図です。

上の図に示すように、ビュー層(グラフ、ノードなど)は、データバインディングを通じてモデルの変更に応答/更新します。グラフのレンダリングはSVG + HTMLに基づいていることを既に述べました。したがって、ビュー層の更新には、基本的に命令型と宣言型の2つのオプションがあります。

  • jQuery API の `$('.rectNode').attrs({x: 1, y: 2})` のような命令型メソッドは、高度なインタラクティブ性を必要とするシナリオでは非常に扱いにくく冗長な DOM 操作コードです。しかし、最終的には命令型描画を便利にサポートするライブラリ、antv/g を見つけました。

  • 宣言型。例えば、React/Vue のようなビューフレームワークのコア機能の一つは、状態 => UI を実現することです。DOM を宣言的に構築することで、状態が変化するたびに UI が更新されます。

DOM操作を伴う命令型のシナリオのコード記述が煩雑になるという理由に加え、DOM操作のコストも理由の一つです。UIの更新を状態に基づいて行う設計では、特定のシナリオにおける更新効率の問題を解決するために仮想DOMを導入することが自然と浮かび上がりました。これは、「SVGベースのグラフィックレンダリング」によって発生する可能性のあるレンダリングパフォーマンスの問題も補うことができます。

要約すると、MVVM 設計パターンを選択し、仮想 DOM を導入する最も基本的な 2 つの理由は次のとおりです。

  • グラフ エディター シナリオでの開発効率を向上します。

  • さらに、HTML + SVG グラフ レンダリング スキームを使用すると、より優れたパフォーマンスを追求できます。

X6とのレンダリング性能比較を実施しました。同一動作環境において、LogicFlowとX6のレンダリング時間を、ノード数/行数を変えて測定しました。理論的には、レンダリング時間が短いほどパフォーマンスが優れていると言えます。

上の表は、LogicFlowのオンデマンドロード機能を有効にしていない場合であっても、LogicFlowがX6の初期レンダリング速度を上回っていることを示しています。これは、LogicFlowの技術選択が正しかったことを示しています。サンプルページでもご確認いただけます。

https://yhlchao.github.io/LF-VS-その他/

2.4 イベントシステム

「ステータス」と「レスポンス」の設計についてご紹介しました。様々なユーザーの「アクション」を収集し、タイムリーにレポートしてアップするには、イベントシステムが必要です。最も重要なのは、再利用性と統一されたレポート機能です。

再利用とは、すべてのノードとラインにデフォルトのイベント コールバックがあることを確認する方法と、複雑なイベント (ドラッグ アンド ドロップ) の処理ロジックを共有する方法を指します。

  • 動作。複雑なイベントを処理するために、関数とクラスの形でカプセル化しました。例えば、Drag は mousemove、down、up を使用して、HTML5 の dragEnter、dragOver、dragEnd、drop イベントをシミュレートします。DnD は、抽象エンティティの dragsource と droptarget を使用して、ドラッグ&ドロップによるノードの作成など、ドラッグ&ドロップのインタラクションを実装します。

  • 前のモジュール抽象化のセクションで、LogicFlow には BaseNode や BaseEdge といった抽象化クラスが存在することを説明しました。組み込みノードとカスタムノードはどちらも、基本クラスを継承することで共通の機能を獲得します。そのため、LogicFlow 内のデフォルトのイベントコールバックは、実際には継承を通じて再利用されています。

  • EventCenter。イベントバスを介して統合レポートを実行し、内部でキャプチャされたすべてのユーザー行動イベントを特定の仕様と形式(emit(ev, args))に従ってEventCenterに送信します。これらのイベントはLogicFlowクラスにバブリングアップされ、ホストアプリケーションと連携します。さらに、グラフエディター内のどこからでもEventCenterを介してイベントをトリガーおよびリッスンできます。

2.5 ツールセンター

ツールセンターは、前述のBehavior(複雑なイベントのカプセル化)やEventCenterといった特定の種類の問題を解決するためのユーティリティとして位置付けられています。さらに、グラフ編集のプロセスにおいて、優れたインタラクティブ効果を実現するには、実際には多くの複雑な計算ロジックを処理する必要があります。

  • 座標系。ブラウザの clientX 座標系と clientY 座標系、そして SVG 画像自体の座標系は、画像を拡大または縮小または移動した場合に異なります。そのため、イベント処理中に 2 つの座標系間の変換が必要になります。

  • アルゴリズムは、幾何学とアルゴリズムを用いて視覚化の問題を処理するために特別に設計されています。例えば、ノードに同じ方向に複数のポリラインが接続されている場合、これらのパスをどのように結合すれば、より美しい表示を実現できるでしょうか?(下の例を参照)。

下の図に示すように、線と図形の間の接点を計算して、線を図形のアンカー以外のポイントに接続できるようにする方法。

  • 履歴は主にやり直しと元に戻す機能を提供します。元に戻すデータとやり直しデータを保存するために2つのスタックを使用し、最大長に制限があります。MVVM設計パターンにより、データ変更の監視とモデル駆動型ビュー操作が容易になります。

▍ 3.スケーラビリティ

フローチャートエディタの設計について紹介したところで、LogicFlowのもう一つの重要な特徴である拡張性について説明しましょう。LogicFlowは特定のドメインにおける問題を解決するための開発フレームワークであるため、APIは拡張可能でなければなりません。さらに、LogicFlowはビューレイヤーを提供しており、ユーザーはこれを活用することで二次開発を行うことができます。拡張性のこれらの2つの方向性が決まったら、最も重要なのはビジネスニーズを考慮し、過剰なエンジニアリングを行うことなく、現在のビジネスシナリオだけでなく、近い将来に予測されるビジネスシナリオにも対応できることを確認することです。

3.1 API設計

まず、LogicFlowのユーザーインターフェース層は、完全にオブジェクト指向設計パターンに基づいています。その最大の利点は、ほぼすべてのプログラマーが使い慣れているため、利用コストが低いことです。これは、以下の初期化メソッドを見ればわかります。

LogicFlowクラスを使用すると、ユーザーは一度インスタンス化するだけでフローチャートのインスタンスを取得できます。状態もプライベートであり、lfインスタンスを通じて様々なメソッドを呼び出すことができます。

まとめると、API 拡張の設計に関して次のようになります。

  • LogicFlow は、内部的に適切にカプセル化されたオブジェクト指向の設計パターンを採用しており、ユーザーはインターフェース/メソッドを継承およびオーバーライドできます。

  • メソッド設計。まず、入力と出力の型を固定する必要があります。さらに、LogicFlowは`extends`に似たメソッドを提供しており、`LogicFlow.use(fn)`を使用してプロトタイプのメソッドを拡張できます。

  • 通信はオブザーバー パターンを通じて実現され、ホストがさまざまな内部イベントをサブスクライブするための on メソッドが提供されます。

  • 図内のデータはカスタマイズ可能です。ノードやラインのカスタムビジネス属性から、フローチャートからエクスポートするデータの種類まで、すべてがカスタマイズ可能であるべきです。

3.2 プラグイン

ビュー層の拡張性は、ユーザーが表示をカスタマイズできることに加え、最も重要なのはプラグイン性にあります。これは、ビジネスシナリオによってプロセスの可視化に必要な機能が異なり、LogicFlowではすべてのシナリオをサポートするのが困難だからです。そのため、ユーザーが二次開発を行えるように、優れたプラグイン性を提供することがより良い選択肢となります。現在、UIインターフェースでは以下の2つの機能を開放しています。

  • ノードとラインは、二次開発、つまりカスタム ノードとラインをサポートします。

  • UI コンポーネントを開発し、LogicFlow のコンポーネント キャンバスに登録できます。

プラグインアプローチに基づき、様々なビジネスシステムをサポートしてきました。その過程で、BPMN仕様をサポートするノードなど、より一般的な機能を抽出し、lf-extensionパッケージにカプセル化しました。現在、この拡張機能は主にUIコンポーネント、カスタムノード、API、アダプタの4つのカテゴリに分類されています。

4.

今後の計画

まず、APIの使いやすさと充実度について考えてみましょう。現在のイテレーションプラン(GitHubリポジトリのプロジェクトを参照)に加え、ユーザーのニーズに基づいて優先順位をつけて特定の機能を追加していく予定です。皆様からのフィードバックやご提案もお待ちしております。全体的な方向性としては、LogicFlowワークフローの可視化を維持し、コアAPIを充実させ、拡張機能の機能を強化することを目指しています。

第二に、より包括的なドキュメントとサンプルを提供します。ドキュメントは読みやすく、開発者がコピー&ペーストできる完全なサンプルとコードが含まれます。現在はReactのサンプルのみ利用可能ですが、Vueのサンプルは2021年4月までに追加される予定です。

最後に、私たちは単なるプロセス可視化ライブラリの提供にとどまらず、包括的なソリューションの提供を目指しています。LogicFlowはフロントエンドのフローチャート編集の技術的な側面のみに対応していますが、グラフデータの定義やプロセスの最終的な実行方法を決定するには、補完的なプロセスエンジンが必要です。

現在、私たちのチームは「プロセスエンジン」に対応するソリューションであるturbo(Java版はオープンソースです:https://github.com/didi/turbo)も開発しています。LogicalFlowとTurboをエンドツーエンドのソリューションに統合し、包括的なアプリケーション例を提供する予定です。さらに、Node.js版のエンジンも計画中ですので、どうぞご期待ください。

5.

結論は

この記事でLogicFlowの概要をご理解いただけたかと思います。ビジネスプロセス可視化と高いスケーラビリティが求められる場合、LogicFlowは最適な選択肢となるでしょう。LogicFlowの実装の詳細や、類似のビジネスシナリオへの適用について、皆様のご意見をお待ちしております。今後、LogicFlowの技術設計の詳細や、可視化、ビジネスプロセス、ロジックオーケストレーションに関する私たちの考えを紹介する記事をさらに公開していく予定です。どうぞお楽しみに!

LogicFlow 公式サイト: http://logic-flow.org/

GitHubリポジトリアドレス: https://github.com/didi/LogicFlow