https://d226lax1qjow5r.cloudfront.net/blog/blogposts/boost-your-productivity-with-model-driven-engineering-part-2/boost-productivity_model-driven-engineering_p2.png

モデル駆動エンジニアリングで生産性を高める(後編)

最終更新日 January 23, 2024

所要時間:1 分

はじめに

生産性を高める冒険へようこそ!前編 パート1では、モデル駆動型エンジニアリング(MDE)の主なコンセプトを説明し、いくつかの「商売道具」を簡単に紹介しました。この記事では、ケーススタディ、具体的には、これらの技術を使用して、新しいAPIのサポートを Vonage Java SDK.

シーンを設定する問題提起

VonageにはたくさんのAPIがあります。.その中にはかなり小さくてシンプルなものもありますが、巨大なものもあります。例えば、以下のような大規模なAPIがあります。 Video, ミーティングそして プロアクティブコネクト.以下のような小規模な API と比較してください。 Numbers Insight v2- のような小さなAPIと比較してみよう!これらの大規模なAPIは、エンドポイントが多いだけでなく、リクエストとレスポンス用の大規模で複雑なデータモデルを持っている。

APIが安定("General Availability "ステータス)したとみなされた時点で、私たちは公式SDKにそのAPIのサポートを追加することを目指しています。 公式SDK. SDKの付加価値についてはすでに書きました。についてはすでに書きましたし、同僚のJim Secondeも次のように語っています。 についても話しています。そのため、APIにSDKを提供することの利点については繰り返しません。言うまでもなく、高品質のSDKを開発・維持するには多大なリソースが必要です!しかし、私たちのSDKに新しいAPIを追加するための労力の多くは、非常に手間がかかり、ほとんど考える必要がありません。ボイラープレートを書くことは、多少の癒しにはなるかもしれませんが、そのような作業は自動化できるので、開発者の時間の使い方としては、間違いなくベストではありません。

SDK実装要件

では、強く型付けされたSDK、たとえば Java.NETでは、Javaや.NETのような強型SDKには何が必要なのでしょうか?まず、(通常は)すべてのエンドポイントをサポートする必要があり、正しいURL、HTTPリクエストメソッド、認証タイプのロジックを持つ必要があります。そのため JSONウェブトークンのような他のメタデータと同様に、正しい設定でリクエストのペイロードに適用します。 Content-Typeそして Acceptヘッダなどの他のメタデータ。次に、実際のリクエストボディがあります。リクエストで検索結果をフィルタリングするときなど、ペイロードがクエリパラメータの一部になることもあります。 GETリクエストで検索結果をフィルタリングする場合などです。その他の場合は、ボディの一部であり、JSONとしてシリアライズされる必要があります。SDKはまた、成功(2xx HTTPステータスコード)と失敗(4xxと5xxコード)の両方の応答を処理する必要があります。レスポンスボディを返すエンドポイントは、JSONから解析する必要があります。したがって、SDKはJSONペイロードをオブジェクトにシリアライズおよびデシリアライズできる必要があります。一方 Jacksonなどのライブラリはこのプロセスを宣言的に行いますが、それでも手動でクラスとフィールドを定義する必要があります。他にも、(422応答を防ぐための)バリデーションやドキュメンテーションなどがあるが、ご理解いただけただろうか。最終的には、プログラミング言語からAPIを使用する際に、APIのユーザーができるだけ簡単に使えるようにすることだ。

MDEソリューション

問題領域とモデル駆動エンジニアリングのコンセプトを紹介したところで、次は、そのすべてを統合することに目を向けましょう。このアプローチには、スコープや時間的な制約によって様々な方法があり、決定的な「正しい」方法はありません。そこで、私がとった現実的なアプローチについて説明する。ゴールは生産性を最大化することなので、"オーバーエンジニアリング "やソリューションのアーキテクチャーに時間をかけることはしなかった。MDEでは、これはうまくいくこともあるが、欠点もある。これについては、また最後に触れたいと思う。もしフォローしたいなら、私はこれを GitHubのオープンソース.

メタモデル

どのモデル駆動型エンジニアリング・アプローチでもそうであるように、最初に始めるべきはメタモデルである。左側がテキストによる Emfatic 構文、右側がツリービューです。Emfaticや別の(メタ)モデリングツールではなく、組み込みのEcoreエディターを使ってメタモデルを作成することにしました。

API metamodel

前述したOpenAPI仕様のいずれかを見たことがあれば、メタモデルの構造はある程度自明であることを期待したい。階層のルートは Apiクラスで name, package(これはクラスがSDKのどこにあるかということです)、ベースエンドポイントパス(例えば、Meetings APIなら https://api-eu.vonage.com/v1/meetingsMeetings API の場合)、そしてもちろん実際のエンドポイントです。すべてのオブジェクトはルート要素に含まれる必要があるためです、 typesクラスによって直接使用されなくても、ここで参照されます。 Apiクラスで直接使用されなくても、ここで参照されます。

クラスは Endpointクラスは次の階層にあります。名前、URL(パス)、HTTPリクエスト・メソッド(列挙型で表される)、1つ以上の認証メソッド(3つのタイプがあるので、これも列挙型で表される)、そしてもちろんリクエスト・タイプとレスポンス・タイプです。

では、型とは何か?つまり、SDKや標準ライブラリなどですでに定義されている型です。- 基本的には、モデル化したくないものなら何でもいい。つまり Typeには name属性があります。 String, UUID, Integer, URIなど)。モデル化したい型は Classを継承する Type(を継承する name属性を継承する)。これは、Java クラスを部分的にモデリングする練習のようなものです。メタモデルに記述されている残りの属性と型からわかるように、非常に特殊なフィールドや注目すべき省略がいくつかあります。例えば、Java クラスにはメソッドとコンストラクターがありますが、ここには含まれていません。なぜか?必要ないからです。のドキュメントもモデル化することにしました。 ClassFieldのドキュメントも Documentation型のドキュメントもモデル化することにしたが、これもJavadocの機能からすると不完全なものだ。Java全体をモデル化することは、私たちのニーズをはるかに超えている。あなたの好奇心を満たすために、 以下はJava 7のメタモデルです。- のメタモデルで、最新のJDKの派手な機能はすべて含まれていません!

コードジェネレーター

さて、お待ちかねのコード生成だ!パート1で述べたように、利用可能なModel-to-Textツールはいくつかあるが、私は以下のツールを使うことにした。 イプシロンの生成言語(EGL).EGLは特別なものではありません。テンプレート・ベースの言語であり、テンプレート(.eglファイル)は 静的動的リージョンがあります。静的リージョンはデフォルトで、ファイルに入力されたテキストがそのまま出力されます。一方、ダイナミックリージョンでは、プログラムで出力を決定することができ、それはモデルのプロパティに依存します。

例えば exception.eglでは、1つのプロパティしか使っていない: nameだけを使っています。その request_response.eglテンプレートはもっと複雑で forで定義したヘルパー関数に依存しています。 helper_functions.egl.EGLはEOLの上に構築されているため、ダイナミック・リージョンには、操作を含め、あらゆるEOLコードを含めることができる。EGLには「テンプレート操作」(でアノテーションされている)もあります。 @templateでアノテーションされている)、呼び出されたときにテキストを出力する(またはテキストを文字列として返す)関数がある。したがって、ユーティリティ関数のライブラリを構築し、テンプレート間で再利用することができる。

これらの変数はどこから来て、テンプレートはどのように呼び出されるのだろうか?結局のところ、テンプレートが有用であるためには、モデルからの値でパラメータ化されなければならない。そして、その出力はどこに書き出されるのでしょうか?Epsilonを使用する主な利点はそこにある: EGX協調言語.EGXのアイデアは、テンプレートがいつ、どのように呼び出され、どのようなパラメータで呼び出され、どこに出力されるかを制御するルールベースの言語を提供することです。テンプレートは specs.egxファイルはこのロジックを定義し、モデルとテンプレートをまとめるものです。ファイル preセクションは最初に実行され、出力ディレクトリやコモンネームなど、スクリプトで使用される変数の宣言を主に含みます。また、モデルから様々な型を取得し、リクエストかレスポンスかなどのプロパティで分類します(このため、メタモデルではこのプロパティを Classの boolean プロパティとして定義しました)。このスクリプトで Classに対して宣言された操作は、モデル要素のプロパティから各テンプレートに渡される変数を導出するために使用されます。

これを明確にするために、例を見てみよう。例として QueryParamsRequestルール.と transforminキーワードは forループのようなものだと考えてほしい。入力コレクションは、この場合は queryParamsRequestTypesで計算される。 pre.他の場合(たとえば では Enumルール)では、モデル内の与えられた型のすべてのインスタンスから計算されます。各モデル要素(この例では、変数 requestに対して parametersはユーティリティ・メソッドから得られます。これは、テンプレートで使用される変数名を request- のプロパティに結びつけます。 self型に宣言されていることに注意してください。 Classに宣言されていることに注意してください。この templateは、このルールで呼び出したいEGLテンプレートへの相対パスです。最後に targetは結果を書き込むファイルです。デフォルトでは、EGXはファイルが存在すれば上書きしますが、これは設定可能です。

これでお分かりいただけただろうか!EGXでは、モデル要素のタイプに基づいて呼び出すテンプレートを選択することができ、それらのテンプレートの変数がモデルからどのように派生しているかがおわかりいただけると思います。このコーディネーション・ロジックは、まさにこのアプローチの目玉である。このロジックを実行するには、テンプレートに必要なモデルを入力し、出力を得るだけだ。

今はここまで...。

この記事では、Java SDKのボイラープレート生成という特殊なケースに役立つMDEアプローチについて簡単に説明しました。MDEがもたらす価値がお分かりいただけたと思いますが、開発プロセスやこの演習から得られた教訓に興味をお持ちの方も多いでしょう。このシリーズの最終回となる第3回では、このアプローチを振り返り、あなたのプロジェクトでこの方法を採用する場合に留意すべき重要なポイントを紹介します。

ご意見、ご感想がありましたら、お気軽にX(旧名 ツイッターまたは コミュニティ・スラック.この記事がお役に立てば幸いです。もしこの記事を楽しんでいただけたなら、私の他の Java記事.

シェア:

https://a.storyblok.com/f/270183/400x400/46a3751f47/sina-madani.png
Sina MadaniVonage 元チームメンバー

シナはVonageのJavaデベロッパー・アドボケイト。アカデミックなバックグラウンドを持ち、自動車、コンピューター、プログラミング、テクノロジー、人間性など、あらゆることに好奇心旺盛。余暇には散歩をしたり、対戦型ビデオゲームをしたりしている。