ConoHaコントロールパネルのアーキテクチャを解説してみる

2022/4/21(木)ConoHa WINGにWEXAL®が提供されました(→リリースニュース)。 無事に提供することができて開発者一同安心しています(エゴサもしっかりしています)。
今回は、ConoHaコントロールパネルで利用できるWEXAL®のバック/フロントエンド設計について、簡単に解説できればと思います。

開発者体制

WEXAL®をリリースするにあたり、大きく分けて以下3つの分野で開発者が作業分担しています。

  • WINGサーバーのセットアップ/チューニング
  • WINGサーバーとConoHaコントロールパネルを中継するAPIの開発
  • ConoHaコントロールパネル&WordPressプラグインへの機能/画面追加
コントロールパネルは直接WINGサーバーをいじらず、APIを経由します。

他にも、開発したConoHaコントロールパネルの画面に不具合が無いか検証する専門のチームもいます。
ここからはConoHaコントロールパネルを”コンパネ”、WordPressプラグインを”プラグイン”と記載します(それぞれ開発現場での名称です)。

WEXAL®のコンパネ/プラグイン設計方針

WEXAL®機能を実装するうえでどのような設計で実装したのか、バックエンドとフロントエンドに分けて解説していきたいと思います。

バックエンド

WEXAL®におけるバックエンドはMVCモデルベースで設計されています。
MVCモデルと異なる点は、コアロジックはModelではなくServiceという専用のレイヤーに集約している点になります。
コンパネ/プラグインに必要なドメインモデルはSDK等の内部実装が既に用意しているため、ドメインモデルをわざわざ定義する必要がありません。そのため、このような設計になっています。
現状のConoHaはController部分がファットになりがちですので、いかにコアロジックを切り離すかに注力しています。

破線矢印はインターフェースでの参照になります。
コアロジックがModelではなくServiceに集約されているのが特徴です。

View

画面の実装になります。後述するフロントエンドと重複する内容になるので、割愛します。

Controller

Controllerはコンパネ/プラグイン双方に用意されています。
Serviceを呼び出す際はインターフェースを経由することで、画面ごとに利用できる処理を制限しています。役割は以下の通りです。

  • 処理に必要なServiceの呼び出し
  • Serviceから返されるResponseを元に、Modelを生成
  • ViewにModelを返す

Model

ConoHaにおけるModelは、事実上ViewModelの役割を担っています。
先述した通り、コンパネ/プラグインにおけるドメインモデルはSDK等の内部実装に既に定義されているため、敢えてこちら側で用意する必要性が無いためです。
役割は以下の通りです。

  • フロントバリデーションのAttribute実装
  • Viewに返すプロパティの集合体(≒ViewModel)

Service

WEXAL®におけるコンパネ/プラグイン側のコアロジックが閉じ込められたクラスになります。
WEXAL®のCRUD機能をはじめとしたコアロジックの集約を目的としています。
Serviceの呼び出し元はServiceを直参照するのではなく、インターフェースを経由して参照します。これにより、各画面で利用できる機能を定義しています。
Serviceの構成は以下の通りです。

  • WexalService(IControlPanelWexalServiceとIPluginWexalServiceの実装)
  • IControlPanelWexalService(コンパネのみで利用する処理の定義, IWexalServiceの実装)
  • IPluginWexalService(プラグインのみで利用する処理の定義, IWexalServiceの実装)
  • IWexalService(共通で利用する処理の定義)

DAO

SDKとのつなぎこみの部分になります。
インターフェース経由でSDKを参照するため、モックとの差し替えが可能になっています。

フロントエンド

WEXAL®におけるフロントエンドは以下のような設計方針で実装されています。
基本的にはMVPを踏襲した形で、一部にアレンジを加えた設計になっています。
描画描画、通信、制御の責務を分離し、EventHandlerからすべてのイベントのフックを確認できるようにすることを目的としています。

EventHandlerを起点にView/Presenterへ処理が渡ります。
Repositoryはインターフェース経由で参照するため、Controllerが未実装でもモックと差し替えることが可能です。

Selector

セレクタや属性等の定義集になります。
定義を1つにまとめることで、htmlのDOM変更に対応しやすくする意図があります。  
役割は以下の通りです。

  • セレクタ, 属性, Value等の定義と意味づけ
  • フロントエンドでセレクタや属性、ValueはすべてSelecterから参照

View

画面の描画制御をつかさどる部分になります。画面描画や画面情報取得の機能をすべて集約しています。
役割は以下の通りになります。

  • 画面から情報を取得し、バックエンドへ渡すリクエストモデルを生成
  • バックエンドから返されたレスポンスモデルのデータを描画
  • フロントバリデーションの実行

Presenter

ViewとRepositoryの制御をつかさどる部分になります。PresenterはRepositoryの呼び出しが必要な場合にEventHandlerから呼び出されます。
役割は以下の通りになります。

  • EventHandlerからの呼び出しを受ける窓口
  • Repositoryを呼び出し、返却されたResponseをViewに渡して描画命令
  • タイマー処理で定期的に描画命令

Repository

Ajaxをつかさどる部分になります。バックエンドとの通信はすべてここで行います。
インターフェースを経由するため、MockRepositoryと差し替えることが可能です。
役割は以下の通りになります。

  • Ajaxの定義
  • バックエンド側と通信する際のオブジェクトモデルの定義

EventHandler

すべてのユーザーイベントが定義された部分になります。ラジオやチェックボックスのchangeイベントやボタンのクリックイベントなど、すべてのイベントはEventHandlerを起点に発火します。
バックエンドの通信が必要な場合はPresenterを、不要の場合はViewを呼び出します。
役割は以下の通りになります。

  • すべてのイベントの定義
  • 既に追加されたイベントの削除
  • イベントの再定義
  • 必要に応じてView/Presenterの呼び出し

まとめ

以上がWEXAL®開発におけるコンパネ/プラグインの設計になりますが、いかがだったでしょうか?
システム設計において明確な正解というものはありませんが、WEXAL®においてはこの設計方針でサービスを提供しています。

ConoHaはおかげさまで9周年を迎えます。
これは非常に嬉しいことですが、ソースコードを見てみるとリリース初期のレガシーコードがちらほら散らばっているのが現状です。

これからも長く皆様に愛されるサービスを提供するために、ソースコードも変革期が来ています。
今後もConoHaの提供に適したソースコードで開発できるよう、リファクタリングや設計の見直し等できることは全力で取り組んでまいります。

このようなリファクタリングやスピード感のある開発に興味のある方、いろいろな設計手法に触れてみたい方―。
私たちはいつでもお待ちしていますので、ぜひともGMOにエントリーしていただければと思います。

これからもConoHaと美雲このはをよろしくお願いします!
最後まで読んでいただき、ありがとうございました!

ブログの著者欄

岡野 優輝

GMOインターネット株式会社

2020年卒で入社。入社当時よりConoHaコントロールパネルの開発業務を担当。最近ではWordPress高速化オプション「WEXAL®」の画面開発を担当。Webアプリケーション設計/開発のスキルを高めるべく日夜奮闘中。2021/11に公開された鍋を食べてるこのはちゃんの壁紙がお気に入り。

採用情報

関連記事

KEYWORD

採用情報

SNS FOLLOW