依存性注入専用に設計されたプログラミング言語はありますか?


21

多くの一般的なプログラミング言語は、依存性注入をサポートできるほど柔軟です。ライブラリまたはフレームワークのサポートがなくても。しかし、プログラミングの問題を解決するのに十分な言語がチューリングである場合でも、言語は、その中で簡単なことと困難なことに影響を与える選択を行います。

依存関係の注入を簡単にし、逆に隠された依存関係を作成しにくくするために特別に設計された言語はありますか?

明確化:

一部の言語の制限(Javaを見る)のために、多くの人々は依存関係注入の一部として配線と構築の支援を考えています。ここでは、依存関係が副作用で簡単に隠されないことを意味するために、DI用に設計された言語のみを意図しています。構成システムに対する規約も同様に追加されるのは、肉汁だけです。

私は言語の推奨を探していません。これは歴史的な問題です。言語作成者はこれを明示的に始めたことがありますか?


1
完全にではないにしても、強く関連している:依存性注入をどのように言語に統合できますか?
ロバートハーベイ

おい!3K!今、私は彼らがこの質問を閉じるために投票するのを見ることができます。:)投票していただきありがとうございます。
candied_orange

1
とにかくその投稿を読んでください。「どうやって存在するのか」という質問は、「どうやってそれをやったの?」
ロバートハーベイ

1
Haskellはカウントされますか?カリー化関数と高次関数を使用すると、DIがOOP言語で一般的に解決するほとんどの問題を解決できます。また、純度の厳格さにより、IOなどの副作用を分離することを余儀なくされ、関数は引数として渡されなかったものを魔法のように思い起こさせることができません。構成に関する慣習はありませんが、一方で、ほとんどのチームが中規模以上のプロジェクトでそれを信頼できないことに気付いたので、私は最近、OOPコードでもそれから徐々に離れています。
wasatz

1
@wasatz:はい、Haskellは重要です。ほとんどの「ソフトウェアパターン」は、実際にはプログラミング言語の欠点の回避策にすぎません。
ロバートハーベイ

回答:


21

はい、確かにあります。並べ替え。

Newspeakには静的な状態もグローバルな状態もありません。つまり、依存関係にアクセスする唯一の方法は、依存関係を明示的に挿入することです。明らかに、これは、言語、またはより正確に言うとIDE 依存性注入を容易にする必要があることを意味します。そうしないと、言語は使用できなくなります。

したがって、この言語はDI用に設計されたものではなく、DIの必要性は言語設計の結果です。

静的な状態もグローバルな状態もない場合、エーテルに「手を差し伸べて」何かを引き出すことはできません。たとえば、Javaでは、パッケージ構造は静的な状態です。私はただ言うことができjava.lang.Stringて、私にはStringクラスがあります。Newspeakでは不可能です。あなたが扱うすべてのものは、あなたに明示的に提供されなければなりません。したがって、すべては依存関係であり、すべての依存関係は明示的です。

文字列が必要ですか?さて、最初にstdlibオブジェクトにStringクラスを渡すように依頼する必要があります。ああ、でもどうやってアクセスするのstdlib?さて、最初platformstdlibオブジェクトを渡すように依頼する必要があります。ああ、でもどうやってアクセスするのplatform?さて、あなたは最初に他の誰かにあなたにplatformオブジェクトを渡すように頼まなければなりません。ああ、しかし、どうすればその誰かの借金にアクセスできますか?さて、最初に他の誰かにオブジェクトを渡すように依頼する必要があります。

これはウサギの穴をどれくらい下に行きますか?再帰はどこで止まりますか?実際、すべての方法。止まらない。それでは、どのようにしてニュースピークでプログラムを書くことができますか?まあ、厳密に言えば、できません!

すべてを結び付ける外部エンティティが必要です。Newspeakでは、そのエンティティはIDEです。IDEはプログラム全体を見ます。異種の部品を一緒に配線できます。Newspeakの標準的なパターンは、アプリケーションの中心クラスにというアクセサーplatformがあり、Newspeak IDEが、プログラミングの基本的な必需品の一部を返すメソッドを持つオブジェクトをそのアクセサーに注入することです。Stringクラス、Numberクラス、Arrayクラス、等々。

アプリケーションをテストする場合、ダミーメソッドを含むクラスを返すメソッドを持つplatformオブジェクトを注入できFileます。アプリケーションをクラウドにデプロイする場合、Fileクラスが実際にAmazon S3によってサポートされているプラットフォームを注入します。クロスプラットフォームGUIは、異なるOSに異なるGUIフレームワークを注入することにより機能します。Newspeakには、実験的なNewspeak-to-ECMAScriptコンパイラとHTMLベースのGUIフレームワークがあり、さまざまなGUI要素を挿入するだけで、フル機能のGUIアプリケーションを変更せずにネイティブデスクトップからブラウザに移植できます。

アプリケーションをデプロイする場合、IDEはアプリケーションをディスク上のオブジェクトにシリアル化できます。(その祖先であるSmalltalkとは異なり、Newspeakにはイメージ外オブジェクトシリアル化形式があります。すべての依存関係が注入されているため、イメージ全体を持ち歩く必要はありません。IDEはアプリケーションのシステムのどの部分を正確に認識しますそのため、アプリケーションを構成するオブジェクト空間の接続されたサブグラフを正確にシリアル化します。

これらはすべて、オブジェクト指向を極端に単純化することで機能します。すべてが仮想メソッド呼び出しです(Smalltalkの用語で「メッセージ送信」。Newspeakはその子孫です)。スーパークラスのルックアップでさえ、仮想メソッド呼び出しです!のようなものを取る

class Foo extends Bar // using Java syntax for familiarity

または、ニュースピークで:

class Foo = Bar () () : ()

Javaでは、これFooにより静的なグローバル名前空間に名前が作成され、静的なグローバル名前空間で検索さBarれ、Bar Fooのスーパークラスが作成されます。はるかに動的なRubyでも、グローバル名前空間に静的定数が作成されます。

Newspeakでは、同等の宣言は、という名前のゲッターメソッドを作成し、Fooそのメソッドを呼び出してスーパークラスをルックアップするクラスを返すようにすることを意味しますBar。注:これは、Rubyとは異なり、実行可能なRubyコードをスーパークラス宣言として配置できますが、クラスが作成され、そのコードの戻り値が固定スーパークラスになると、コードは1回だけ実行されます。いいえ。メソッドBarすべてのメソッドルックアップに対して呼び出されます!

これにはいくつかの深い意味があります。

  • ミックスインは基本的にそのスーパークラスをまだ知らないクラスであり、Newspeakでは、スーパークラスは動的仮想メソッド呼び出しであり、したがって未知であるため、すべてのクラスは自動的にミックスインでもあります。ミックスインは無料で入手できます。
  • 内部クラスはクラスを返すメソッド呼び出しに過ぎないため、外部クラスのサブクラスでそのメソッドをオーバーライドして、すべてのクラスを仮想化できます。仮想クラスは無料で入手できます。

    class Outer {
      class Inner { /* … */ }
    }
    
    class Sub extends Outer {
      override class Inner { /* … */ }
    }
    

    ニュースピーク:

    class Outer = () (
      class Inner = () () : ()
    ) : ()
    
    class Sub = Outer () (
      class Inner = () () : ()
    ) : ()
    
  • スーパークラスはクラスを返す単なるメソッド呼び出しであるため、外部クラスのサブクラスでそのメソッドをオーバーライドできます。スーパークラスで定義された内部クラスは、サブクラスで異なるスーパークラスを持つことができます。クラス階層の継承は無料で取得できます。

    class Outer {
      class MyCoolArray extends Array { /* … */ }
    }
    
    class Sub extends Outer {
      override class Array { /* … */ }
      // Now, for instances of `Sub`, `MyCoolArray` has a different superclass 
      // than for instances of `Outer`!!!
    }
    

    ニュースピーク:

    class Outer = () (
      class MyCoolArray = Array () () : ()
    ) : ()
    
    class Sub = Outer () (
      class Array = () () : ()
    ) : ()
    
  • そして最後に、この議論で最も重要なのは、(クラスで定義したものを除いて)明らかに、レキシカルに囲むクラスと、最上位の最外クラスであるスーパークラスでのみメソッドを呼び出すことができるからです。明示的にインジェクトされたものを除いて、メソッドをまったく呼び出すことはできません。最上位クラスには、呼び出すことができるメソッドを含む囲みクラスがありません。また、スーパークラス宣言はメソッド呼び出し、そしてそれは明らかにスーパークラスに行くことができません(それスーパークラス)が存在しているため、レキシカルに囲んでいるクラスにもアクセスできません。つまり、最上位クラスは完全にカプセル化され、明示的に注入されたものにのみアクセスでき、明示的に要求されたものにのみ注入されます。つまり、最上位クラスはモジュールです。モジュールシステム全体を無料で入手できます。実際、より正確には、最上位クラスはモジュール宣言であり、そのインスタンスはモジュールです。したがって、パラメトリックなモジュール宣言と一流のモジュールを備えたモジュールシステムを無料で入手できます。これは、非常に高度なモジュールシステムでもできないことです。

このインジェクションをすべて簡単にするために、クラス宣言には通常とは異なる構造があります。2つの宣言で構成されています。1つはクラスコンストラクターです。これは、クラスのインスタンスを構築するコンストラクターではなく、クラス本体が実行される環境を構築するコンストラクターです。Javaのような構文では、次のようになります。

class Foo(platform) extends Bar {
  Array  = platform.collections.Array
  String = platform.lang.String
  File   = platform.io.File
| // separator between class constructor and class body
  class MyArray extends Array { /* … */ }
  // Array refers to the method defined above which in turn gets it from the 
  // platform object that was passed into the class "somehow"
}

ニュースピーク:

class Foo using: platform = Bar (
  Array = platform collections Array
  String = platform streams String 
  File = platform files ExternalReadWriteStream
) (
  class MyArray = Array () () : ()
) : ()

Newspeakプログラマーが実際にクラスを見る方法は次のとおりです。複数のネストされたクラスを表示するNewspeak IDE

しかし、私は正義を行うことさえできません。あなたは自分でそれをいじる必要があります。Gilad Brachaは、モジュール性など、システムのさまざまな側面についていくつかの講演を行っています。彼は非常に長い(2時間)講演を行いました。最初の1時間は、モジュール性の話を含め、言語の徹底的な紹介です。The Newspeak Programming Platformの第2章では、モジュール性について説明しています。あなたは脱脂した場合のSqueak上のニュースピーク-困惑のためのAガイド(別名ニュースピーク-101)は、システムのための感触をつかみます。Example by Newspeakライブドキュメントです(つまり、Newspeak-on-ECMASCriptポート内で実行され、すべてのコード行が編集可能で、すべての結果が検査可能です)。基本的な構文を示しています。

しかし、実際には、それをいじる必要があります。それはすべての主流の言語やほとんどの非主流の言語とはまったく異なるため、説明するのは難しいので、経験する必要があります。


3
えー 静的状態とグローバル状態の使用を禁止します。これは、ほぼすべての最新のプログラミング言語について言えます。
ロバートハーヴェイ

不思議なことに、私の手作りの注射容器の多くは静的な工場です。以前はそれを悪いことだとは思わなかった。
candied_orange

@Jörgこの答えをもう少しバックアップできる方法はありますか?「newspeaklanguage.org依存性注入」をグーグルで検索し、空になりました。私が見つけた最も近いものはこれでした:news.ycombinator.com/item
id=

@CandiedOrange:私は答えを拡大している最中でしたが、「現実世界」が干渉しました。それは良いですか?
ヨルグWミットタグ

3
@JörgWMittag神聖ながらくた!まあそれは確かに「もっと」です。「良い」を評価している間、しばらくお待ちください。これを達成するには、トイレ訪問の力が必要な場合があります。
candied_orange

7

Wakeプログラミング言語は、依存性注入を使用するように設計されています。基本的に、言語自体に組み込まれた依存性注入フレームワークに相当します。クラスは、それらのパラメータを定義needし、provideコンパイラがすべてをフックします。


6

実用的な言語ではありませんが、このペーパーで説明するシステムには興味深い効果があります。抽象クラス/インターフェイスを使用して抽象クラスを記述できます(インスタンス化を含む)。その後、クラスをサブクラスに置き換えることで具体的に作成できます。インスタンス化の時点で使用した各抽象クラス。そうすることで、少なくとも単純なケースでは依存性注入の必要性がなくなります。たとえば(この機能で拡張された仮想バージョンのJavaを使用して)このコードを使用できます。

public interface I {
    void something ();
)

public class Concrete implements I {
    public void something () { ... }
}

public class Client {
    I myI;
    public Client (I injected) { myI = injected; }
    ...
}

...

    Client c = new Client (new Concrete());
    ...

クライアントとその使用法を次のように置き換えます。

public class Client {
   I myI = new I();
   ...
}

   Client c = new Client { I -> Concrete } ();

これにより、作成ではなく依存関係の使用ポイントが簡略化されることに注意してください。また、Factoryパターンを回避することもできます(新しいので、必要なときにいつでもオンデマンドで作成できます)。


面白い。これは、ScalaのTypeメンバーを思い出させます。これは、サブクラスでもオーバーライドでき、スーパークラスでは抽象のままにすることができます。自己型注釈と組み合わされた抽象型メンバーは、モジュール性と依存性注入に対するScalaのアプローチの基礎を形成します。この論文が、Scalaの設計者であるMartin OderskyとNewspeakの設計者であるGilad Brachaの両方に引用されたことはまったく驚きません。
ヨルグWミットタグ

0

私はそれを使ったことはありませんが、Plasticプログラミング言語の公式のキャッチフレーズは、「依存性注入を行ってプログラミング言語に焼き付けるとどうなりますか?」です。かなりおもしろそう

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.