의존성 주입을 위해 특별히 설계된 프로그래밍 언어가 있습니까?


21

많은 일반 프로그래밍 언어는 의존성 주입을 지원할 수있을 정도로 유연합니다. 라이브러리 또는 프레임 워크 지원이 없어도. 그러나 언어가 프로그래밍 문제를 해결하기에 충분할 정도로 튜링 (Turing)이라하더라도 언어는 쉽고 쉬운 것에 영향을주는 선택을합니다.

의존성 주입을 쉽게하고 반대로 숨겨진 의존성을 만들기 위해 특별히 고안된 언어가 있습니까?

설명:

Java를 보는 일부 언어의 제한으로 인해 많은 사람들이 배선 및 구성 지원을 종속성 주입의 일부로 간주합니다. 여기서 나는 DI가 의존성이 부작용에 쉽게 숨겨지지 않음을 의미하도록 설계된 언어만을 의도합니다. 컨피규레이션 시스템에 대한 컨벤션을 갖는 것은 그레이 비만 추가 될 것입니다.

언어 추천을 찾고 있지 않습니다. 역사적인 질문입니다. 언어 작성자가이를 명시 적으로 설정 한 적이 있습니까?


1
완전히 중복되지 않은 경우 강력하게 관련됨 : 의존성 주입을 어떻게 언어에 통합 할 수 있습니까?
Robert Harvey

휘! 3K! 이제이 질문을 끝내기 위해 투표하는 것을 볼 수 있습니다. :) 투표 해 주셔서 감사합니다.
candied_orange

1
어쨌든 그 게시물을 읽어야합니다. "어떻게 했습니까?"와 같이 확장하지 않는 한 "존재 하는가"는 훨씬 덜 흥미로운 질문입니다.
Robert Harvey

1
하스켈은 계산할까요? 카레 및 고차 함수를 사용하면 DI가 OOP 언어로 일반적으로 해결하는 대부분의 문제를 해결할 수 있으며 순도에 대한 엄격함으로 IO 등과 같은 부작용을 분리해야하며 함수는 인수로 전달되지 않은 것을 마술처럼 만들 수 없습니다. 구성에 대한 협약은 얻지 못하지만 다른 한편으로는 요즘 대부분의 팀이 중간 규모의 프로젝트 및 그보다 큰 팀에서 신뢰할 수 없다는 것을 알았으므로 OOP 코드에서도 느리게 이동하고 있습니다.
wasatz

1
@wasatz : 그렇습니다, Haskell는 계산합니다. 대부분의 "소프트웨어 패턴"은 실제로 프로그래밍 언어의 단점에 대한 해결 방법입니다.
Robert Harvey

답변:


21

그렇습니다. 일종의.

Newspeak 에는 정적 상태와 전역 상태가 없습니다. 이는 종속성에 액세스 할 수있는 유일한 방법은 명시 적으로 삽입하는 것입니다. 분명히 이것은 언어 또는 Newspeak의 경우 IDE 종속성 주입을 쉽게 해야 한다는 것을 의미합니다. 그렇지 않으면 언어를 사용할 수 없게됩니다.

따라서 언어는 DI를 위해 설계된 것이 아니라 DI의 필요성은 언어 디자인의 결과입니다.

정적 상태와 전역 상태가없는 경우 에테르에 "도달"하여 무언가를 끌어낼 수 없습니다. 예를 들어, Java에서 패키지 구조는 정적 상태입니다. 그냥 말할 수 java.lang.String있고 String수업이 있습니다. Newspeak에서는 불가능합니다. 작업하는 모든 것이 명시 적으로 제공되어야합니다. 그렇지 않으면 얻을 수 없습니다. 따라서 모든 것은 종속성이며 모든 종속성은 명시 적입니다.

당신은 문자열을 원하십니까? 글쎄, 당신은 먼저 stdlib물건을 당신에게 String수업 에 넘겨 달라고 부탁해야 합니다 . 아,하지만 어떻게 액세스 할 수 stdlib있습니까? 글쎄, 당신은 먼저 platform당신에게 stdlib물건 을 건네 달라고 요청 해야 합니다. 아,하지만 어떻게 액세스 할 수 platform있습니까? 글쎄, 당신은 먼저 다른 사람에게 당신에게 platform물건 을 건네달라고 요청해야 합니다. 아,하지만 어떻게 다른 사람에게 접근 할 수 있습니까? 글쎄, 당신은 먼저 다른 사람에게 당신에게 물건을 건네달라고 요청해야합니다.

토끼 구멍이 얼마나 아래로 가나 요? 재귀는 어디에서 멈추는가? 실제로, 실제로. 멈추지 않습니다. 그렇다면 Newspeak에서 어떻게 프로그램을 작성할 수 있습니까? 글쎄, 엄밀히 말하면, 할 수 없습니다!

모든 것을 묶는 외부 실체가 필요합니다. Newspeak에서 해당 엔티티는 IDE입니다. IDE는 전체 프로그램을 봅니다. 서로 다른 조각들을 서로 연결할 수 있습니다. Newspeak의 표준 패턴은 응용 프로그램의 중앙 클래스에 접근자가라는 접근자가 platform있고, Newspeak IDE는 프로그래밍에 필요한 일부 기본 String클래스 인 Number클래스, Array클래스, 클래스, 등등.

응용 프로그램을 테스트하려면 더미 메서드가있는 클래스를 반환하는 메서드를 가진 platform개체를 주입 할 수 있습니다 File. 애플리케이션을 클라우드에 배포하려면 File실제로 Amazon S3에서 지원 하는 클래스 의 플랫폼을 주입하십시오 . 크로스 플랫폼 GUI는 OS마다 다른 GUI 프레임 워크를 주입하여 작동합니다. Newspeak에는 실험적인 Newspeak-ECMAScript 컴파일러와 HTML 기반 GUI 프레임 워크가있어 완전한 GUI 기능을 갖춘 GUI 응용 프로그램을 기본 데스크탑에서 브라우저로 변경없이 다른 GUI 요소를 주입하여 이식 할 수 있습니다.

응용 프로그램을 배포하려는 경우 IDE는 응용 프로그램을 디스크상의 개체로 직렬화 할 수 있습니다. (소형 스몰 토크와는 달리 Newspeak는 이미지 외부 객체 직렬화 형식을 가지고 있습니다. 모든 의존성이 주입되기 때문에 전체 이미지를 가져갈 필요는 없습니다. IDE는 시스템의 어떤 부분이 애플리케이션 인지 정확히 알고 있습니다 따라서 응용 프로그램을 구성하는 객체 공간의 연결된 하위 그래프를 더 이상 직렬화하지 않습니다.)

이 모든 것은 단순히 객체 지향을 극단으로 가져 오는 것만으로 작동합니다. 모든 것이 가상 메서드 호출입니다 (Smalltalk 용어에서 "메시지 전송", Newspeak는 후손입니다). 수퍼 클래스 조회조차도 가상 메소드 호출입니다! 같은 것을 가지고

class Foo extends Bar // using Java syntax for familiarity

또는 Newspeak에서 :

class Foo = Bar () () : ()

자바에서이 이름이 생성됩니다 Foo정적 글로벌 네임 스페이스를하고 찾아 Bar정적 글로벌 네임 스페이스와 만드는 Bar Foo의 슈퍼 클래스입니다. 훨씬 더 역동적 인 Ruby에서도 글로벌 네임 스페이스에 정적 상수가 생성됩니다.

Newspeak에서 동등한 선언은 다음과 같은 의미를 갖습니다. 이름이 지정된 getter 메소드를 작성하고 이름이 지정된 메소드 Foo를 호출하여 수퍼 클래스를 찾는 클래스를 리턴하게하십시오 Bar. 참고 : 이것은 실행 가능한 Ruby 코드를 수퍼 클래스 선언으로 넣을 수 있는 Ruby와는 다르지만 클래스가 생성되고 해당 코드의 반환 값이 고정 된 수퍼 클래스가 되면 코드는 한 번만 실행 됩니다. 아니요. 메소드 Bar모든 단일 메소드 조회 마다 호출됩니다 !

여기에는 몇 가지 중요한 의미가 있습니다.

  • mixin은 기본적으로 아직 슈퍼 클래스를 모르는 클래스이므로 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 = () () : ()
    ) : ()
    
  • 마지막으로,이 토론에서 가장 중요한 것은 : (클래스에서 정의한 클래스를 제외하고는 분명히) 어휘를 둘러싼 클래스와 최상위 클래스 인 최상위 클래스의 메소드 만 호출 할 수 있기 때문입니다. 어떤 방법을 호출 할 수 없습니다 전혀 명시 적으로 주입을 제외한 것은 : 슈퍼 클래스 선언이 있기 때문에, 최상위 클래스는 그 방법이 호출 할 수있는 둘러싸는 클래스를 가지고 있지 않으며, 기본 이외의 수퍼 클래스를 가질 수 없습니다 메서드 호출, 그것은 분명히이 (슈퍼에 갈 수 있다수퍼 클래스) 및 어휘 포함 클래스로 이동할 수 없습니다. 이것이 의미하는 것은 최상위 클래스가 완전히 캡슐화되어 있으며 명시 적으로 주입 된 항목에만 액세스 할 수 있으며 명시 적으로 요청한 것만 주입됩니다. 다시 말해 최상위 클래스는 모듈입니다. 전체 모듈 시스템이 무료로 제공됩니다. 보다 정확하게 말하면 최상위 클래스는 모듈 선언이고 인스턴스는 모듈입니다. 따라서 파라 메트릭 모듈 선언과 일류 모듈을 무료로 제공하는 모듈 시스템을 얻을 수 있습니다.

이 주입을 모두 고통스럽게 만들기 위해 클래스 선언은 특별한 구조를 갖습니다. 두 가지 선언으로 구성됩니다. 하나는 클래스 생성자입니다 하지 구축 생성자 인스턴스 환경의 클래스 본문 실행을 구성하는 클래스를, 오히려 생성자입니다. 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는 모듈성을 포함하여 시스템의 다양한 측면에 대해 몇 가지 대화를 나 has습니다 . 그는 정말 긴 (2 시간) 대화 를했으며 첫 시간은 모듈화 이야기를 포함하여 언어에 대한 철저한 소개입니다. Newspeak Programming Platform의 2 장 에서는 모듈성을 다룹니다. Squeak – 당황 한자를위한 안내서 (일명 Newspeak-101) 에서 Newspeak 를 훑어 보면 시스템에 대한 느낌을 갖게됩니다. Newspeak by Example 은 기본 구문을 보여주는 라이브 문서입니다 (즉, Newspeak-on-ECMASCript 포트 내에서 실행 중이며 모든 코드 줄을 편집 할 수 있으며 모든 결과를 검사 할 수 있음).

그러나 실제로, 당신은 그것을 가지고 놀아야합니다. 그것은 모든 주류 언어와 대부분의 비 주류 언어와 는 매우 다르기 때문에 설명하기가 어렵습니다.


3
Meh. 정적 상태와 전역 상태의 사용을 금지하면 거의 모든 최신 프로그래밍 언어에 대해 말할 수 있습니다.
Robert Harvey

궁금한 점은 손으로 만든 주입 용기의 대부분은 정적 공장입니다. 전에는 나쁜 생각을하지 않았습니다.
candied_orange

@ Jörg이 답변을 조금 더 백업 할 수있는 방법이 있습니까? "newspeaklanguage.org 의존성 주입"을 봤는데 비어있었습니다. : 내가 찾을 수있는 가장 가까운 일이 있었다 news.ycombinator.com/item?id=9620561
candied_orange

@ CandiedOrange : 나는 대답을 확장하는 과정에 있었지만 "실제 세계"는 방해했다. 더 낫습니까?
Jörg W Mittag

3
@ JörgWMittag 거룩한 쓰레기! 확실히 "더"입니다. "더 나은"평가하는 동안 잠시만 기다려주십시오. 이것을 통과하기 위해 욕실 방문의 힘이 필요할 수 있습니다.
candied_orange 2:26에

7

Wake Programming 언어 는 의존성 주입을 사용하도록 설계되었습니다. 기본적으로 언어 자체에 구운 의존성 주입 프레임 워크와 같습니다. 클래스는 매개 변수들이 정의 needprovide컴파일러 후크 모든 것을 업.


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 } ();

이는 작성이 아닌 종속성 사용 지점을 단순화합니다. 또한 팩토리 패턴을 피할 수 있습니다 (필요할 때마다 필요할 때 새로 만들 수 있음).


흥미 롭군 이것은 스칼라의 타입 멤버를 상기시켜줍니다. 서브 멤버에서 재정의되고 수퍼 클래스에서 추상을 남길 수 있습니다. 자체 유형 주석과 결합 된 추상 유형 구성원은 모듈화 및 종속성 주입에 대한 Scala의 접근 방식의 기초를 형성합니다. 나는이 논문이 Scala의 디자이너 Martin Odersky 와 Newspeak의 디자이너 Gilad Bracha에 의해 인용되었다는 사실에 전혀 놀라지 않습니다 .
Jörg W Mittag

0

나는 그것을 사용하지는 않았지만 Plastic programming language 의 공식 태그 라인은 " 종속성 주입을 가져 와서 프로그래밍 언어로 구우면 어떻게됩니까? "입니다. 꽤 흥미로운 것 같습니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.