DSLの移行
2009年2月4日
DSL支持者が注意すべき危険性の1つは、最初にDSLを設計し、その後人々がそれを使用するという考え方です。他のソフトウェアと同様に、成功するDSLは進化します。これは、DSLの以前のバージョンで記述されたスクリプトが、後のバージョンで実行すると失敗する可能性があることを意味します。
DSLの多くの特性(良い点と悪い点)と同様に、これは実際にはライブラリで起こることと非常によく似ています。誰かのライブラリを使用して、彼らがライブラリをアップグレードした場合、行き詰まる可能性があります。本質的に、DSLはそれを変更するために何もしていません。DSL定義は本質的に公開インターフェースであり、あなたは同じように結果に対処する必要があります。
この問題は、外部DSLでより顕著になる可能性があります。内部DSLへの多くの変更は、リファクタリングツール(それらを備えた言語の場合)によって処理できます。しかし、リファクタリングツールは外部DSLでは役に立ちません。実際には、この問題はそれほど大きな問題ではありません。DSL実装者の制御下にないスクリプトを持つ内部DSLは、リファクタリングでは検出されません。したがって、内部と外部の唯一の違いは、同じコードベース内のDSLスクリプトにあります。
DSLの進化を処理するための1つの手法は、DSLをあるバージョンから別のバージョンに自動的に移行するツールを提供することです。これらは、アップグレード中に、または古いバージョンのスクリプトを新しいバージョンに対して実行しようとした場合に自動的に実行できます。
移行を処理するには、大きく分けて2つの方法があります。1つ目は、段階的な移行戦略です。これは、進化的なデータベース設計を行う人々が使用している概念と本質的に同じです。DSL定義に加えるすべての変更について、DSLスクリプトを古いバージョンから新しいバージョンに自動的に移行する移行プログラムを作成します。
段階的な移行の重要な部分は、変更をできるだけ小さくすることです。バージョン1から2にアップグレードしていて、DSL定義に10個の変更を加えたいとします。この場合、バージョン1から2に移行する移行スクリプトを1つだけ作成するのではなく、少なくとも10個のスクリプトを作成します。DSL定義を一度に1つの機能ずつ変更し、各変更の移行スクリプトを作成します。さらに細かく分割し、複数のステップ(したがって複数の移行)で機能を追加すると便利な場合があります。私が説明した方法は、1つのスクリプトよりも多くの作業のように聞こえるかもしれませんが、重要なのは、移行が小さい場合ははるかに簡単に記述でき、複数の移行を簡単に連鎖できることです。その結果、1つのスクリプトを作成するよりも10個のスクリプトを作成する方がはるかに高速になります。
もう1つのアプローチは、モデルベースの移行です。セマンティックモデルを使用している場合(これは私がほとんどの場合推奨しています)、この戦術を使用できます。このアプローチでは、リリースされたバージョンごとに1つずつ、言語の複数のパーサーをサポートします。(したがって、これはバージョン1と2に対してのみ行い、中間ステップに対しては行いません。)各パーサーはセマンティックモデルにデータを入力します。セマンティックモデルを使用する場合、パーサーの動作は非常に単純なので、複数のパーサーを用意してもそれほど問題ありません。次に、作業しているスクリプトのバージョンに適切なパーサーを実行します。これは複数のバージョンを処理しますが、スクリプトは移行しません。移行を行うには、DSLスクリプト表現を生成するセマンティックモデルからジェネレーターを作成します。このようにして、バージョン1スクリプトのパーサーを実行し、セマンティックモデルにデータを入力し、ジェネレーターからバージョン2スクリプトを出力できます。
モデルベースのアプローチの1つの問題は、セマンティクスには関係ありませんが、スクリプト作成者が保持したいものが失われやすいことです。コメントは明らかな例です。パーサーにスマートが多すぎると、これは悪化しますが、この方法で移行する必要があるため、パーサーはダムのままでいることが奨励される場合があります。これは良いことです。
DSLへの変更が十分に大きい場合、バージョン1スクリプトをバージョン2セマンティックモデルに変換できない場合があります。その場合、バージョン1モデル(または中間モデル)を保持し、バージョン2スクリプトを出力する機能を提供する必要がある場合があります。
これらの2つの選択肢 arasında güçlü bir tercihim yok.(私はこれらの2つの選択肢 arasında güçlü bir tercihim yok.原文ママ。意味不明なトルコ語が混入しているので、おそらく「これらの2つの選択肢のどちらが優れているとは考えていません。」と言いたかったのだと思われる。)
移行スクリプトは、必要に応じてスクリプトプログラマー自身が実行することも、DSLシステムによって自動的に実行することもできます。自動的に実行するには、スクリプトがどのバージョンのDSLであるかを記録しておくと、パーサーがそれを簡単に検出し、結果の移行をトリガーできるため、非常に便利です。