MPS 2020.3 ヘルプ

生成コードからのソースの削除

MPS は、デフォルトで生成されたモデルにソースをバンドルします。モデルのユーザーは、コードで使用している概念の定義に移動できます。たとえば、singleControl + クリックするだけで、呼び出しているメソッドやインスタンス化しているクラスの実装を確認できます。これは、実装側を覗くだけで言語 / ライブラリ作成者のアイデアの多くを把握できるため、ユーザーにとって非常に便利です。
ただし、実装を非表示にすることが望まれる場合もあります。特にクローズドソースプロジェクトは、実装に含まれる知的財産を注意深く保護する必要があります。ユーザーは引き続きコードを呼び出すことができますが、Control + B を押すと、クラスとメソッドの署名のみが表示されます。

Obfuscated1

難読化されたクラスファイルと、リバースエンジニアリングによる他の人へのチャンスとを組み合わせると、ハードワークの成果はかなり低くなります。これを行う方法を見つけるために参照してください。

BaseLanguage コードからソースを削除する

BuildLanguage は、特定のアーティファクトでソースを削除する必要があることを示すストリップ実装フラグを提供します。

Obf2

ビルドレイアウトコマンドの 1 つ(モジュールソースプラグイン)でこのフラグを true に設定すると、生成されたアーティファクトから実装のソースを削除するようにビルドプロセスに指示されます。このフラグにより、BaseLanguage メソッドの本体が空の StatementList に置き換えられ、クラスの静的およびインスタンス初期化子が削除されます。言語の実装を非表示にしたい場合は、フラグを使用すると、動作メソッドの本体も空の StatementList に置き換えられます。

まとめると、MPS はそのまま使用できます。

  • BaseLanguage で記述された実装を非表示にする

  • 言語定義の側面を隠す

ビルドスクリプトで、目的のソリューションまたは言語のストリップ実装フラグを設定するだけで済みます。

いくつかの便利なメモ

  1. MPS のキャッシュを無効にする機能は、言語のストリップされたバージョンとストリップされていないバージョンを含むプロジェクトを切り替えるときに便利な場合があります。

  2. ビルドスクリプトが生成されたアーティファクトの変更を反映するように、言語に手動で変更を加える必要がある場合があります。

独自の言語のための実装ストリッピングのカスタマイズ

BaseLanguage コードで実装を非表示にできるのと同様に、言語でも実装を非表示にできます。

MPS は実装ストリッピングに関してあなたの言語の概念の意図されたふるまいを区別するためにあなたに 3 つのマーカーインターフェースを与えます:

  • InterfacePart - 生成されたモデルに完全に表示される概念ユーザーは自分のところに移動して自分のコード内でそれらの参照を保持することができます。

  • ImplementationPart - 生成されたモデルから削除される概念ユーザーは自分のコードに移動したり、自分の参照を自分のコードで保持したりできなくなります。

  • ImplementationWithStubPart- 空のスタブに置き換えられる概念。コード内のノードを表すためにスタブ置換が使用されることを除いて、ImplementationPart のように動作します。たとえば、/ * コンパイルされたコード * / 空のメソッド本体のマークについて考えてみてください。

ロボットカヤサンプル

たとえば、Robot Kaja のサンプル言語(MPS にバンドルされている)を使用してその実装を隠すことができるようにしたい場合は、いくつかの手順で実現できます。次のシナリオを想定しましょう。

  1. エンドユーザーは、ロボット冠者言語SampleRobotScripts プロジェクトの一環として、スクリプトを書いています。彼は、ロボットルーチンの RobotRoutines (MPS ソリューション)と呼ばれるライブラリをダウンロードして再利用したいと考えています。

  2. RobotRoutines の作成者は、自分のライブラリの実装を非表示にしたいと考えています。

  3. ロボット冠者言語RobotRoutines のサポート隠蔽実装に変更する必要があります。その言語で書かれたアプリケーション / ライブラリのパブリックインターフェース(契約)を形成する概念と、実装を保持する概念を宣言する必要があります。単純な言語を選択したため、実際にインターフェースの一部にする必要があるのは 3 つの概念だけであることを識別するのは非常に簡単です。他の人は、パッケージング中にソースを削除することができます。
    1. スクリプト

    2. ライブラリ

    3. RoutineDefinition

初期の状況

Robot Kaja 言語を使用する、ルーチンのライブラリを作成できます。ライブラリはルートコンセプトであり、コレクションまたは RoutineDefinitions を保持します。Robot Kaja 言語を使用する RobotRoutines ライブラリは、いくつかのライブラリルートノードを作成し、それらにいくつかの便利なルーチンを実装する場合があります。

Obf6

SampleRobotScripts コードで使用すると、開発者はいつでも定義に移動して、RobotRoutines ライブラリの完全な実装を確認できます。

Obf3

Obf4b

ゴール

RobotRoutines などのライブラリの作成者に、実装を非表示にする機能を提供したいと考えています。適切に実装されると、SampleRobotScripts の開発者は、ルーチンの署名とその空の本体のみを表示します。

Obf4a

Robot Kaja 言語への変更

Robot Kaja 言語では、スクリプトライブラリ、および RoutineDefinition の概念を、ユーザーコードで参照できるため、InterfacePart インターフェースでマークする必要があります。

Obf7

Obf8

ルーチンの実装を非表示にするには、その本体を非表示にする必要があります。ルーチン本体は CommandList の概念です。それを隠すために、ImplementationPart インターフェースまたは ImplementationWithStubPart インターフェースのいずれかでそれをマークする必要があります。どちらも実装を非表示にしますが、後者を使用すると、削除された実装の代わりに挿入される代替の「スタブ」概念を提供できます。スタブは、実装が削除されたコードの見栄えを良くする機会を提供し、エンドユーザーに時折見られる非表示の実装を常に考慮する必要があります。

Obf9

スタブ作成

ImplementationPart に対する ImplementationWithStubPart のオーバーヘッドは、スタブの概念を作成することです。私たちの CommandList のために StubCommandList の概念が必要になりますし、IDontSubstituteByDefaultIStubForAnotherConcept でそれをマーク。StubCommandList が CommandList から ImplementationWithStubPart インターフェースを継承するため、IStubForAnotherConcept が必要とされているため、MPS は StubCommandList がスタブ自体で、さらに別のスタブでスタブする必要はないことを明示的に指示する必要があり。

Stubx2

StubCommandList が CommandList ではなく AbstractCommand を拡張している場合、AbstractCommand は ImplementationWithStubPart ではないため、IStubForAnotherConcept としてマークする必要はありません。

Stubx3

スタブエディターは、実装が削除されており、ここでは表示されないことを読者に丁寧に明らかにする必要があります。

Obf11

再構築してパッケージ化すると、RobotRoutines の作成者がライブラリの実装を非表示にするのに役立つ言語の準備が整います。

ライブラリ作家のためのスクリプトを作成する

Robot Kaja 言語が実装ストリッピングをサポートすると、RobotRoutines ライブラリの作成者は、ビルドスクリプトでストリップ実装フラグを設定できるため、生成されたプラグインからライブラリの実装のソースを削除できます。

Obf5

一般的なガイドラインと追加の注意事項

  1. マーカーインターフェースは、従来の方法でスーパーコンセプトおよびスーパーコンセプトインターフェースから継承されます。複数のマーカーインターフェースが(直接または継承を通じて)概念に適用できる場合、InterfacePart が他のインターフェースに 優先し、ImplementationWithStubPartImplementationPart に優先します。

  2. マーカーインターフェースが指定されていない場合、コンセプトは InterfacePart が設定されているかのように動作します。InterfacePart で概念をマークすることには、次の 2 つの目的があります。
    • 概念があなたの言語の必要な公的要素であるという事実を文書化する

    • たとえば、概念が他のフラグのいずれかを継承している場合に、その概念が誤って実装の一部としてマークされるのを防ぎます。

  3. ImplementationPart インターフェースを使用して、クライアントコードから参照する必要がなく、必須(カーディナリティ 1 および 1..n)リンクを介して InterfacePart コンセプトから直接アクセスできる言語のコンセプトをマークします。これらの概念のソースはビルド中にソリューションから削除されるため、ユーザーは、たとえば Go To Concept Declaration を使用して、それらの定義を表示できなくなります。

  4. ユーザーは AN の定義の一部として見ることを得るかもしれないため、ちょうど ImplementationPart と同じように除去されなければならない概念をマークしたが、プレースホルダの代わりに、単純にソースから削除された状態で交換する必要がする使用 ImplementationWithStubPart インターフェース InterfacePart の概念。

  5. それを含むリンクは空のままにすることはできませんし、検証エラーを報告するため ImplementationWithStubPart は、一般的に、子供やカーディナリティ 1InterfacePart コンセプトから 1..n のポインティングの参照のターゲットを表す概念のために必要とされます。

  6. カーディナリティが 0..1 および 0..n の子および参照のターゲットは、ImplementationPart として安全にマークできます。含まれているリンクは空のままになります。

  7. スタブは、命名規則スタブ + 置き換えられる概念の名前に従う必要があり、置き換えられた概念と同じパッケージに配置する必要があります。

  8. スタブの概念は、ISuppressErrors を実装して、子ノードから型システムエラーが報告されるのを回避できます。

  9. スタブは、コード完了メニューで提供されないように、IDontSubstituteByDefault も実装する必要があります。

  10. コンセプトが InterfacePartImplementation(WithStub)Part の両方である場合、MPS は警告を報告します。

  11. コンセプトが ImplementationWithStubPart インターフェースを宣言または継承し、同じ仮想パッケージ内に適切なスタブコンセプトが見つからない場合、MPS はエラーを報告します。

  12. おそらくスタブの概念を拡張することにより、ImplementationWithStubPart インターフェースを継承するスタブは、IStubForAnotherConcept を実装して、それらがスタブであり、それ自体をスタブする必要がないことを示す必要があります。すべてのスタブに IStubForAnotherConcept インターフェースを実装させることをお勧めします。

  13. スタブを定義して、抽象的なスーパーコンセプトを置き換えることはできません。彼らは常に、個別、具体的な一のコンセプトのための 1 つのスタブが ImplementationWithStubPart を実装するすべての具体的なコンセプトを交換する必要があります。

  14. 明確なメッセージを表示するようにスタブの概念のエディターを再定義します。別名「コンパイル済みコード」は、実装が削除されたことを読者に明確に示すためのものです。

  15. 削除された言語のユーザーがスタブ化された概念で見られるモデル検証エラーを回避するために、すべての子の「特殊化」およびそれらのスーパー概念からスタブ概念に継承された「少なくとも 1」カーディナリティの参照を検討してください。

これは、以下のような概念に必要です。modelAccessor の子はカーディナリティ 1 を持っているため、スタブ概念では必須です。

Hid1

スタブの概念は、スタブの概念の名前の前にスタブを付けるという命名規則に従う必要があります。スタブ化された概念を拡張する必要がある場合とない場合があります。これは、元の概念が他の言語からどのように参照されているかによって異なります。スタブの概念がスタブの概念を拡張する必要がある場合は、子参照が空のままにならないように、必須の子を何らかの方法で処理する必要もあります。

推奨される方法は、子または参照関係を特殊化し、ターゲットの概念を BaseConcept に変更することです。

Stubx1

次に、コンストラクターの動作の側面で、IntegerConstant などのダミーノードを指すように参照を設定します。これにより、リンクが空のままにならないようになりますが、スタブコンセプトの元の modelAccessor リンクを完全に満たすノードを作成する必要はありません。

Hid3