メタプログラミング

この記事の目的は、一般的なITコミュニティの注目をメタプログラミングとそのすべての形式と技法に引き付けることです。 私はこのトピックで知っているすべての分類を収集し、投機的なタスクだけでなく、通常のアプリケーションの開発にも適用できることを示しました。 しかし、これは今後の研究の計画である可能性が高く、より積極的な議論の推進力になると思います。



UPD:新しい記事: JavaScriptの例によるメタプログラミング 。 Youtubeの記事に関する講義(講義は、 「プログラミングに関する100のビデオ講義」の一環として、2019年4月18日にキエフ工科大学で記録されました):







メタプログラミングは、データ、ユーザーアクション、または他のシステムとの相互作用に応じて、振る舞いや構造が動的に変化する情報システムコードを構築するためのパラダイムです。 メタプログラミングのタスクは、コードの抽象化とその柔軟性の向上、再利用、開発の高速化、システム間統合の簡素化です。 実際、私たちは皆ある程度メタプログラミングを使用しています。15年前にそれがどのように呼ばれたのかさえ知らずにそれをどのように使用したかを今でも思い出すことができます。



私たちが知っているメタプログラミングのテクニック (それらが私を補完することを願っています):



1.コンパイルされたテクニック

1.1。 パターン、マクロ、およびパラメーターポリモーフィズム 。 プリコンパイル段階の1つのコードブロックでは、さまざまなタイプのパラメーターに対していくつかのオプションが生成されます。これは、最も古いタイプのマタプログラミングです。

1.2。 プリコンパイルの最適化 。 コンパイルまたはプリコンパイルの段階で変数を含まないすべての式と関数全体の計算と最適化。

1.3。 コンパイル済み言語のソースコードジェネレーター 。 コンパイルの前に、プロジェクトアセンブリの段階で、バッチ方式で、メタデータ、ファイル、関数、クラス、フォームなどの有無にかかわらず生成されます。

1.4。 独自のドメイン固有のコンパイル言語 (特定の範囲のタスク用)の作成-DSL(ドメイン固有のプログラミング言語)。



2.解釈されたテクニック

2.1。 解釈された言語または実行時にバイトコードへの遅いコンパイルをサポートする言語の文字列変数からのコードの評価(eval)

2.2。 タスクに特化した解釈された命令型言語を作成します(LOP-言語指向プログラミング)。

2.3。 宣言型言語 、シリアル化形式、特別な構文、またはXML、JSON、XAMLなどの構文のサブセットの作成または使用

2.4。 クエリ言語でのコードの動的な生成と実行(例:SQL、XQuery、LINQなど)



3.ハイブリッド技術

3.1。 イントロスペクション -内部言語構造、データ型、クラス、関数などへのアクセスを提供します。 構造に関するメタデータを取得してループ内でループするか、各クラスを分析する機能を持つ配列として関数パラメーターを取得します。

3.2。 メタモデルの動的解釈 。 このタイプの特別な用語はまだ開発されておらず、より正確には確立されていません。そのため、以下で詳細に説明します。 次に、主な機能を紹介します。メタモデル(メタ言語のドメインモデル)には、相互に影響する命令型コンポーネントと宣言型コンポーネントの両方が含まれ、アプリケーションはメタモデルを起動するための「仮想マシン」になります。

3.3。 メタモデル解釈に基づく動的リンクを備えた分散情報システム。 これは、クライアントサーバー間またはシステム間通信への段落(3.2)の適用です。



ビジネスオブジェクトの動的アプリケーション環境


メタモデルの動的な解釈について詳しく説明します。 命令構文と宣言構文は互いにどのように影響しますか? 特定の形式化されたデータ形式、正規表現で簡単に解析できる正規の文法、文字列操作、または既製のパーサー(JSONやXMLなど)を使用して、宣言記述子を分析していることは明らかです。 したがって、命令型アルゴリズムは、コード実行の構造とシーケンスを変更できます。 しかし、さらに、メタモデルにはビジネスロジックを表現するための解釈されたスクリプトも含まれています。スクリプトは、完全に自由にメモリに展開されたメタモデルの宣言部分を受け取り、ライブラリにアクセスできます。 それから、誰もがJavaScriptについて考えました。 メタモデルのスクリプトは、 「仮想マシン」の内部仕様にアクセスできず、データとメタデータ、つまり ドメインモデルに。 このようなスクリプトは、クライアント上またはサーバー上のどこで実行されているかさえ知らない場合があります。 アプリケーション環境は、アプリケーションモデルとオペレーティングシステムの間の層であり、アプリケーションを仮想化して、システムおよびプラットフォームから切り離すことができます。



現在、クラウドテクノロジーと仮想化はインフラストラクチャとプラットフォームのレベルまでしか向上していませんが 、次に、 アプリケーションレベルは実質的に影響を受けません 。 新しいアプリケーションアーキテクチャの必要性はますます明らかになっています。 サービスアーキテクチャ(SOA)を使用すると、間違いなくエンタープライズシステムのほとんどのニーズを満たすことができますが、その重さ、静的な性質、および開発の複雑さにより、このテクノロジーでソフトウェア開発を行う余裕があるのは大企業だけです。 これは、設計、プログラミング、デバッグ、テスト、アセンブリ、ユーザーへの配信、インストール、構成、サポートなど、ソフトウェア作成の複雑な技術サイクルによるものです。 アプリケーションシステムの新しいバージョンは、ユーザーの職場で利用可能になるために多くの手順を必要とします。 また、バージョン間の移行は、データ変換の難しさと、データ交換形式とファイル形式の下位互換性に関連しています。 これはすべて、ソフトウェアシステムのアーキテクチャの次の機能の結果です。

1. 1つのクラスまたはモジュール内で異なるレベルのプログラムコード抽象化を 混在させる。 たとえば、データベースからの読み取り/書き込み、ビジネスロジック、および1つのクラスの視覚化の実装。

2.アプリケーションの2つの隣接する抽象レイヤーの高いコード凝集度 。 レイヤーの片側または両側依存。 たとえば、別のウィンドウワークステーションまたはWebインターフェイスはサーバーAPI関数のセット、それらのパラメーター、データ型、およびクラスに厳密に結び付けられ、サーバーアプリケーションはデータベースのテーブル構造に密接に結び付けられます。 多くの場合、高い接続性は、コード、インターフェースとパラメーター、テーブルとフィールドに配線されたクラスと関数の識別子の存在下で表現されます。

3. アセンブリ指向のライフサイクルと 、マシンコードまたはバイトコードでのビジネスモデルのコンパイルと 、それに続くサーバーへの手動展開。

4.システムモジュールとネットワークインターフェイス間のインターフェイスの厳密な固定 (構造、呼び出しパラメーター、およびデータタイプ)。



「仮想マシン」で起動するビジネスモデルを準備する際に、解釈されたメタデータを使用する動的アプリケーション環境を使用すると、モデルをフラッシュするのではなく、アプリケーションシステムの通常の標準動作モードを柔軟に変更するまで、システムの変更に必要な時間を大幅に短縮できますコンパイルされたコード。 ここで、誰かがシステムのパフォーマンスが大幅に低下すると主張するかもしれませんが、同じではありません。その理由は次のとおりです。そのようなシステムが実行されている間の実行可能コード全体のほとんどは、コンパイルされた言語で書かれたメタモッドのAPIを提供するアルゴリズムです。 これは、解析用のライブラリ、ベクターグラフィックス、ネットワークライブラリ、視覚コンポーネントのライブラリを処理するためのライブラリです。 これらはすべてコンパイルされますが、タスクから完全に抽象化されて「仮想マシン」を構成し、解釈されたコードは、適用された問題を解決するような方法でこのツールセット全体をバインド、「ステッチ」するだけです。



ここで、さまざまなメタプログラミング手法を使用したシステムの剛性の4つの理由を反転させ、メタモデルの動的な解釈を備えたシステムのレシピを取得します

1.プログラムコードのさまざまなレベルの抽象化の分離 。 たとえば、ビジュアルコンポーネントのレベル、ネットワークトランスポートのレベル、適用されるアルゴリズムのライブラリのレベル、およびビジネスモデルのレベルは、環境のコンパイルの段階では相互に関連しない場合がありますが、リンクは、対応する機能のリクエスト時のメタデータに基づいて動的に構築され、キャッシュされるまでキャッシュされますメタモデルの変更。

2. アプリケーションの抽象層に直接および逆の依存関係が存在しないこと、メタプログラミングテクニック、特定の言語、宣言型およびアクティブな言語を使用してビジネスオブジェクトを記述する。 同時に、ビジネスモデル内のクラスの内部接続を強化できます。

3.アプリケーション環境のレベルでのコンパイルの使用、およびビジネスモデルのレベルでの解釈の原則。 環境については、ライフサイクルは組み立てられたままですが、ビジネスモデルは再展開せずに少なくとも毎分変更できます。

4.モジュール(宣言型言語で記述)と、アプリケーションと動的な構造およびパラメーターとの相互作用のためのネットワークプロトコルレベルでのイントラスペクションをサポートするネットワークインターフェイス間の動的インターフェイスの導入。



そのため、 アプリケーション環境自体は古典的なアプリケーションであり、開発と展開のすべての段階を経る必要があります。ただし、環境で実行されるビジネスモデルは、柔軟性を高めるためにコンピューターにコンパイルしてインストールしないでください。ランタイム段階で動的に展開されます。 レクサーによる実行のために準備された、またはバイトコードに変換されたデータ構造とスクリプトは、メタモデルが変更されるか、別のクラスまたは別のメタモデルパラメータが変更されるまで、アプリケーション環境にキャッシュできます。 必要な関数の最初の起動には、構造の解析、および新しいバイトコードまたはデータ構造の準備が伴いますが、後続の操作はマシンコードに比べて速度が劣らないはずです。



動的リンク分散情報システム


2つ以上のシステムがネットワークアプリケーションインターフェイスを介して相互作用する場合、メタモデルの解釈に基づく動的リンクにより、以前は接続されることさえ想定されていなかったアプリケーションシステムが相互作用できます。 ネットワークを介してメタモデルを送信する場合、当事者は情報オブジェクトの構造とパラメーターを事前に知らず、システム間呼び出しを行うときに関数の名前やパラメーターのセットに厳密に結び付けられていません。 代わりに、当事者はメタ記述言語を知っているため、データを動的に解釈して呼び出しを行い、パラメータを形成し、リモート側の応答を解釈できます。



デザート


そして最後に、尊敬される聴衆の審美的な側面を楽しませるために、JavaScriptでアニメーションにメタプログラミングを使用する小さな例を示します。 最近impress.jsについての記事がありましたが、メタプログラミングへの執着の文脈で似たような解決策を考えていたのと何とか一致しました。 そして、ここに彼からのコードがあります:



必須の部分:


$(function() { var Images = $("#sky div"), Timers = []; Images.each(function() { fly = function(Id,Range,Duration,Direction) { var Way1 = {}, Way2 = {}; Way1[Direction] = '+='+Range; Way2[Direction] = '-='+Range; $('#'+Id).animate(Way1,Duration).animate(Way2,Duration); } var Image = $(this), Id = Image.attr('id'), Range = Image.attr('data-fly-range'), Duration = parseInt(Image.attr('data-fly-duration')), Direction = Image.attr('data-fly-direction'); Timers[Id] = setInterval('fly("'+Id+'","'+Range+'",'+Duration+',"'+Direction+'")',Duration*2); fly(Id,Range,Duration,Direction); }); });
      
      







宣言部:


 <div id="sky"> <div id="castle-white" class="castle" style="background:url(images/castle-white.png) no-repeat; left:350px; top:-10px; width: 287px; height: 698px;" data-fly-range="10" data-fly-duration="3000" data-fly-direction="top"></div> <div id="castle-indigo" class="castle" style="background:url(images/castle-indigo.png) no-repeat; left:560px; top:235px; width: 471px; height: 397px;" data-fly-range="15" data-fly-duration="2500" data-fly-direction="top"></div> <div id="fog-03" class="fog" style="background:url(images/fog-03.png) no-repeat; left:500px; top:325px; width: 599px; height: 310px;" data-fly-range="15" data-fly-duration="4000" data-fly-direction="left"></div> <div id="castle-blue" class="castle" style="background:url(images/castle-blue.png) no-repeat; left:690px; top:350px; width: 521px; height: 288px;" data-fly-range="10" data-fly-duration="2000" data-fly-direction="top"></div> <div id="fog-02" class="fog" style="background:url(images/fog-02.png) no-repeat; left:50px; top:280px; width: 1279px; height: 375px;" data-fly-range="20" data-fly-duration="3500" data-fly-direction="left"></div> <div id="castle-green" class="castle" style="background:url(images/castle-green.png) no-repeat; left:470px; top:60px; width: 353px; height: 621px;" data-fly-range="15" data-fly-duration="1500" data-fly-direction="top"></div> <div id="castle-yellow" class="castle" style="background:url(images/castle-yellow.png) no-repeat; left:210px; top:50px; width: 267px; height: 630px;" data-fly-range="5" data-fly-duration="500" data-fly-direction="top"></div> <div id="fog-01" class="fog" style="background:url(images/fog-01.png) no-repeat; left:100px; top:435px; width: 580px; height: 194px;" data-fly-range="25" data-fly-duration="3000" data-fly-direction="left"></div> <div id="castle-orange" class="castle" style="background:url(images/castle-orange.png) no-repeat; left:-110px; top:-30px; width: 524px; height: 736px;" data-fly-range="20" data-fly-duration="1000" data-fly-direction="top"></div> </div>
      
      






All Articles