Чи існує мова програмування, спеціально розроблена для введення залежності?


21

Багато загальних мов програмування досить гнучкі, що дозволяє підтримувати введення залежності. Навіть без підтримки бібліотеки чи рамок. Але навіть якщо мова є Тюрінгом достатньо повною для вирішення будь-якої проблеми програмування, мова робить вибір, який впливає на те, що легко і що важко зробити в них.

Чи є мова, яка була спеціально розроблена для того, щоб зробити ін'єкцію залежності залежною, і, навпаки, важко створити приховані залежності?

Пояснення:

Через обмеження деяких мов (дивлячись на вас Java) багато людей розглядають допомогу з електропроводкою та будівництвом як частину введення залежності. Тут я маю на увазі лише мову, розроблену для DI, щоб означати, що залежність не так легко приховати в побічних ефектах. Маючи конвенцію щодо системи конфігурації, також буде додано лише підкладку.

Я не шукаю мовної рекомендації. Це історичне питання. Хто-небудь автор мови колись явно мав намір це зробити?


1
Сильно пов’язаний, якщо не відвертий дублікат: Як могло б введення залежності залежно від мови?
Роберт Харві

Вій! 3K! Тепер я можу спостерігати, як вони голосують, щоб закрити це питання. :) Дякую за голоси.
candied_orange

1
Ви все одно повинні прочитати цю публікацію. "Чи існує" - набагато менш цікаве питання, якщо ви не розширите його на щось на кшталт "як вони це зробили?"
Роберт Харві

1
Чи порахував би Хаскелл? Завдяки функціям каррінгу та вищого порядку ви можете вирішити більшість проблем, які DI зазвичай вирішує мовами OOP, і з його суворістю чистоти ви змушені відокремлювати побічні ефекти, такі як IO і т.д. У вас не виникає ніяких умов щодо конфігурації, але, з іншого боку, я повільно віддаляюся від цього навіть у моєму коді OOP, оскільки я помітив, що більшості команд не можна довіряти цьому на середніх проектах і більше.
wasatz

1
@wasatz: Так, Хаскелл рахується. Більшість "програмних моделей" насправді є лише вирішенням недоліків у мові програмування.
Роберт Харві

Відповіді:


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. Міжплатформні графічні інтерфейси працюють, вводячи різні рамки графічного інтерфейсу для різних ОС. Newspeak навіть має експериментальний компілятор Newspeak-ECMAScript та підтримуваний HTML графічний інтерфейс, що дозволяє переносити повнофункціональний додаток 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 еквівалентне оголошення означає: створити метод getter з назвою Fooі змусити його повернути клас, який шукає його суперклас, викликаючи метод з ім'ям Bar. Примітка: це не так, як Ruby, де ви можете помістити будь-який виконуваний код Ruby як декларування надкласового класу, але код буде виконаний лише один раз, коли створено клас і повернене значення цього коду стане фіксованим надкласом. Ні. Метод Barвикликається для кожного пошуку методу!

Це має певні глибокі наслідки:

  • оскільки міксин - це в основному клас, який ще не знає свого надкласу, а в Newspeak суперклас - це динамічний виклик віртуального методу, і, таким чином, невідомий, кожен клас автоматично також є mixin. Ви отримуєте міксин безкоштовно.
  • оскільки внутрішній клас - це лише виклик методу, який повертає клас, ви можете замінити цей метод у підкласі зовнішнього класу, тому кожен клас є віртуальним. Ви отримуєте віртуальні заняття безкоштовно:

    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 насправді бачить класи (и) такий:Новомовний IDE, що відображає кілька вкладених класів

Я навіть не можу почати це робити справедливо. Вам доведеться пограти з цим самостійно. Гілад Браха виголосив пару розмов про різні аспекти системи, включаючи модульність. Він дав по-справжньому тривалі (2 години) розмови , перша година яких - ретельне ознайомлення з мовою, включаючи історію модульності. Розділ 2 платформи програмування новомовних програм охоплює модульність. Якщо ви скасуєте Newspeak на Squeak - Посібник для ошелешених (він же Newspeak-101) , ви відчуваєте систему. Newspeak by Example - це живий документ (тобто він працює всередині порту Newspeak-on-ECMASCript, кожен рядок коду можна редагувати, кожен результат перевіряти), демонструючи основний синтаксис.

Але дійсно, вам доведеться пограти з цим. Він просто настільки відрізняється від усіх основних і навіть більшості немейнстримних мов, що важко пояснити, це потрібно пережити.


3
Мех. Заборонити використання статичного стану та глобального стану, і це можна сказати майже про будь-яку сучасну мову програмування.
Роберт Харві

Цікаво, що багато моїх ручних контейнерів для ін'єкцій - це статичні заводи. Раніше не думав про це як про погану річ.
цукати

@ Jörg Як би ви могли трохи більше підкріпити цю відповідь? Я гугл "newspeaklanguage.org ін'єкції залежності" і прийшов порожній. Найближче, що я міг знайти, це це: news.ycombinator.com/item?id=9620561
candied_orange

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

Зауважте, що це спрощує точку використання залежності, а не створення. Це також дозволяє нам уникати фабричного зразка (як новий я можу створюватися на вимогу, коли хочемо).


Цікаво. Це нагадує мені про Type Scala Members, які також можуть бути переопрацьовані в підкласах і залишені абстрактними в суперкласі. Члени абстрактних типів у поєднанні з анотаціями власного типу складають основу підходу Scala до модульності та введення залежності. Я зовсім не здивований, що цей документ цитується як Мартином Одерським , дизайнером Scala, так і Гіладом Брача , дизайнером Newspeak.
Йорг W Міттаг

0

Я не використовував його, але офіційною міткою мови програмування " Пластик " є " Що станеться, якщо взяти ін'єкційну залежність і викласти її на мову програмування? ". Це здається досить цікавим

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.