Jolie プログラミング言語は最近、Hacker News で開発者の注目を集めた。Jolie は、開発者が分散ソフトウェアを構成可能なサービスとしてモデル化することを促進するサービス指向言語であり、オーケストレーションは通信プロトコル (SOAP、HTTP、XML-RPC) およびデプロイメントアーキテクチャとは別に記述される。Jolie は、サービスを第一級のコンセプトとして具体化することにより、仕様と実装の間の距離を縮めることを目指している。
南デンマーク大学数学コンピュータ科学科の Fabrizio Montesi 教授は、Hacker News で Jolie の背後にある理論的根拠を次のように説明している:
[ここでの主な質問は、なぜ言語がフレームワークなどよりも優先されるのかということだと思います。]
簡単に言えば、コード <-> モデルの距離を最小限に抑えたいからです。他の言語では、関数やオブジェクトなどの観点からプログラムを作成し、これらの概念を使用してサービスをモデル化します。Jolie では、重要な概念に直接対応するコードを記述します。重要な概念とは何でしょうか? 例えば API、アクセスポイント、およびサービス (ええと…) などです。
私たちの (今のところ主観的な) 経験では、Jolie に慣れている人は、サービス システムのプロトタイプを作成するのがはるかに早く、私たちにとってそれを追求する価値があります。Jolie コードでは、興味深いシナリオの定型文と状態管理が少なくて済みます。
[…] 言語を探求するもう1つの大きな理由は、規律です。言語は、コードの書き方を律します。[…] この言語では、コンポーネントを外部の独立したサービスにする必要があると判断した場合、いくつかの参照 (入力/出力ポート、アクセス ポイント) を更新することでそれを実行できるように強制されます。[…] Jolie の規律により、異なるプロトコルを使用する複数のアクセスポイントで同じビジネスロジックを再利用することもできます。
[…] つまり、実装モデルに到達したら [(ドメイン モデルを作成した後)]、これがサービス指向である場合、Jolie はそれを記述するための簡潔で実行可能な構文を提供します。
Jolie プログラムは、動作とデプロイメントの2つの部分で構成される。最初の部分は、サービスが実行するワークフローを指定する。2つ目の部分では、動作の実行方法と、システムの残りの部分と対話する方法を定義する。Jolie では、サービスは、その契約、そのエンドポイント (たとえば、inputPort
、outputPort
、location
、protocol
、interfaces
)、その実行モデル (single | concurrent | sequential
)、および入出力通信に関連付けられた計算 (動作) を指定される。Jolie のドキュメントには、主要な言語機能 (CalculatorInterface.ol
) を説明するための計算機の実装が記載されている。
type SumRequest: void {
term[1,*]: int
}
type SubRequest: void {
minuend: int
subtraend: int
}
type MulRequest: void {
factor*: double
}
type DivRequest: void {
dividend: double
divisor: double
}
interface CalculatorInterface {
RequestResponse:
sum( SumRequest )( int ),
sub( SubRequest )( int ),
mul( MulRequest )( double ),
div( DivRequest )( double )
}
前のコードは、計算サービスの契約を記述しています。つまり、必要なオペランドと計算結果のタイプを使用した4つの算術演算だ。RequestResponse
は、要求メッセージと応答メッセージを含む同期交換を示す。別の OneWay
(ここでは使用されていない) には、応答のない要求メッセージを含む。
サービスのメインのコードは次の通りだ:
from CalculatorInterfaceModule import CalculatorInterface
service CalculatorService {
execution { single }
inputPort CalculatorPort {
location: "socket://localhost:8000"
protocol: http { format = "json" }
interfaces: CalculatorInterface
}
main {
[ sum( request )( response ) {
for( t in request.term ) {
response = response + t
}
}]
[ sub( request )( response ) {
response = request.minuend - request.subtraend
}]
[ mul( request )( response ) {
response = 1
for ( f in request.factor ) {
response = response * f
}
}]
[ div( request )( response ) {
response = request.dividend / request.divisor
}]
}
}
前のコードは、サービスリスニングエンドポイント (ポート 8000 のローカルソケット)、サービスとの対話に使用するプロトコル、および前述のサービスインターフェイス (CalculatorInterface.ol
) を示している。操作のリストは、制御フロー構造である入力選択肢 (main
内の角括弧) を使用して指定される。
ここで使用される single
の実行モダリティは、CalculatorService
の動作を1回だけ実行する必要があることを意味する。それは、通常、スクリプトを実行するために使用される — メッセージ受信ではなくコマンドによってトリガされる。sequential
実行モダリティにより、現在のインスタンスが終了した後にプログラムの動作が再び使用可能になり、同時実行が防止される。そのモダリティは、リソースへの排他的アクセスを保証する必要があるモデリングサービスに使用できる。concurrent
モダリティにより、プロセスは複数のリクエストをサポートできる。
サービスの動作を定義する場合、開発者は標準の制御フロープリミティブ (たとえば、if
、for
)、順次合成 (;
)、並列合成 ({ P } | { Q }
)、または入力選択 (メッセージのパターンマッチングに似ている) を使用できる。入力選択機能は、前のサンプルコードに示されているブラケット構文を使用する。
Jolie はサービスのロジックの変更をせずに分散アプリケーションへの変更を容易にするよう努めている:
Jolie は、並列障害処理のための障害ハンドラの定義をサポートしている。開発者は、install
プリミティブを使用して、実行時に障害ハンドラの動作を更新できる:
…
scope ( scope_name ) {
install (
fault_name1 => handler code
fault_name2 => handler code
);
…
throw ( fault_name )
}
…
Jolie はさらに、オーケストレーション、集約、リダイレクト、埋め込みなど、いくつかのアーキテクチャパターンに従ってサービスの構成を容易にする。埋め込みプリミティブにより、単一の実行コンテキスト内で一連のマイクロサービスを調整するマクロサービスを指定できる:
(出典: Jolie’s documentation)
Jolie はアカデミアに由来し、正式な構文とセマンティクスを備えているが、営利企業のプロダクションでも使用されている。
Jolie はいくつかの目標を Ballerina と共有している。Ballerina は、ネットワーク分散アプリケーションを作成するためのもう1つのオープンソースプログラミング言語であり、ネットワークを第一級のコンセプトとして言語に取り入れている。
Jolie はオープンソースの汎用言語であり、サービスを第一級のコンセプトとして採用することにより、分散アプリケーションの実装を容易にすることを目指している。Jolie には、分散アプリケーションに関連する一般的な問題 (同時実行性、サービス間の通信、障害処理、異種性、システムの進化) を処理するための専用のプリミティブがある。Jolie の頭字語は、Java Orchestration Language Interpreter Engine の略だ。
Jolie の使用を開始するには、開発者はオンラインドキュメントを参照できる。