Как происходит взаимодействие нескольких языков программирования? [закрыт]
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.
Понятно, что большинство (если не все) крупные энтерпрайз сервисы, приложения и тд. (не только веб) написаны с использованием не одного языка программирования, а нескольких. И эти составные части, написанные на разных языках, как-то взаимодействуют между собой (фронт, бизнес-логика, еще что-то). Опыта разработки подобных систем у меня нет, поэтому не совсем могу представить, как это происходит. Подозреваю, что взаимодействие идет через независимые от языков средства. Например, нечто написанное на одном языке, шлет через TCP-IP пакет, который ловится и обрабатывается чем-то написанным на другом языке. Либо через HTTP запросы. Либо через запись/чтение из БД. Либо через файловый обмен, XML например. Хотелось бы, чтобы знающие люди привели пару примеров, как это обычно происходит. Не просто в двух словах, мол «фронт на яваскрипте, бэк на яве», а с техническими нюансами. Заранее спасибо.
А какие вам нюансы нужны. Вы сами перечислили большинство средств общения. Технические нюансы — это уже например функции для работы с http в выбранном языке. смотрится в доке на язык. Остальное — дело фантазии
Самые распространённые варианты вы уже сами привели, не очень понятно, что ещё вы хотите в качестве ответа. Добавлю ещё, что в некоторых языках есть возможность запускать код, написанный на других языках — например, скрипт на Python может напрямую использовать процедуры, написанные на C++ или Golang.
3 ответа 3
Несколько языков могут сосуществовать как в рамках одного процесса, так и в рамках нескольких.
Проще всего сосуществовать в рамках нескольких процессов: если процессы обмениваются данными, то совершенно всё равно (ну, в известных рамках), на каком языке эти данные были созданы, и какой язык их читает. Например, вы можете генерировать данные в виде HTML сервером на ASP.NET, а читать браузером, написанным на C++. (Да, пара из сервера и клиента — тоже взаимодействие языков.)
Теперь, если мы хотим взаимодействие в рамках одного процесса, нам нужно уметь вызывать друг друга. Для этого нужен общий стандарт вызова. Часто таким общим стандартом являются бинарные соглашения C ( extern «C» , экспорт из DLL в Windows).
Ещё пример общего стандарта — COM: COM-объекты можно писать на многих языках, так что если в языке есть часть, реализующая стандарт COM, он может вполне пользоваться им.
Отдельная возможность, популярная сейчас — языки, компилирующиеся в общий промежуточный код. Например, Java и Scala компилируются в один и тот же код для JVM, поэтому объекты, созданные в Java, просто доступны для Scala-программ (так как доступность определяется не на уровне исходного языка, а на уровне JVM-метаданных). То же касается .NET-языков.
Ну и ещё есть набор glue-технологий. Например, для вызова в .NET нативный функций есть P/Invoke, который создаёт автоматический маршаллирующий stub для нативных функций. (Маршаллирование нужно, чтобы данные в формате, «понятном» .NET, перегнать в данные в формате, ожидаемом нативным кодом.)
Связь между средствами программирования
Прежде чем приступить к изучению основных паттернов также рассмотрим основные отношения между объектами, которые помогут нам понять связи между сущностями при их использовании в паттернах. Мы можем выделить несколько основных отношений: наследование, реализация, ассоциация, композиция и агрегация.
Наследование
Наследование является базовым принципом ООП и позволяет одному классу (наследнику) унаследовать функционал другого класса (родительского). Нередко отношения наследования еще называют генерализацией или обобщением. Наследование определяет отношение IS A , то есть «является». Например:
class User < public int Id < get; set; >public string Name < get; set; >> class Manager : User < public string Company< get; set; >>
В данном случае используется наследование, а объекты класса Manager также являются и объектами класса User.
С помощью диаграмм UML отношение между классами выражается в незакрашенной стрелочке от класса-наследника к классу-родителю:
Реализация
Реализация предполагает определение интерфейса и его реализация в классах. Например, имеется интерфейс IMovable с методом Move, который реализуется в классе Car:
public interface IMovable < void Move(); >public class Car : IMovable < public void Move() < Console.WriteLine("Машина едет"); >>
С помощью диаграмм UML отношение реализации также выражается в незакрашенной стрелочке от класса к интерфейсу, только линия теперь пунктирная:
Ассоциация
Ассоциация — это отношение, при котором объекты одного типа неким образом связаны с объектами другого типа. Например, объект одного типа содержит или использует объект другого типа. Например, игрок играет в определенной команде:
Класс Player связан отношением ассоциации с класом Team. На схемах UML ассоциация обозначается в виде обычно стрелки:
Нередко при отношении ассоциации указывается кратность связей. В данном случае единица у Team и звездочка у Player на диаграмме отражает связь 1 ко многим. То есть одна команда будет соответствовать многим игрокам.
Агрегация и композиция являются частными случаями ассоциации.
Композиция
Композиция определяет отношение HAS A , то есть отношение «имеет». Например, в класс автомобиля содержит объект класса электрического двигателя:
public class ElectricEngine < >public class Car < ElectricEngine engine; public Car() < engine = new ElectricEngine(); >>
При этом класс автомобиля полностью управляет жизненным циклом объекта двигателя. При уничтожении объекта автомобиля в области памяти вместе с ним будет уничтожен и объект двигателя. И в этом плане объект автомобиля является главным, а объект двигателя — зависимой.
На диаграммах UML отношение композиции проявляется в обычной стрелке от главной сущности к зависимой, при этом со стороны главной сущности, которая содержит, объект второй сущности, располагается закрашенный ромбик:
Агрегация
От композиции следует отличать агрегацию. Она также предполагает отношение HAS A , но реализуется она иначе:
public abstract class Engine < >public class Car < Engine engine; public Car(Engine eng) < engine = eng; >>
При агрегации реализуется слабая связь, то есть в данном случае объекты Car и Engine будут равноправны. В конструктор Car передается ссылка на уже имеющийся объект Engine. И, как правило, определяется ссылка не на конкретный класс, а на абстрактный класс или интерфейс, что увеличивает гибкость программы.
Отношение агрегации на диаграммах UML отображается также, как и отношение композиции, только теперь ромбик будет незакрашенным:
При проектировании отношений между классами надо учитывать некоторые общие рекомендации. В частности, вместо наследования следует предпочитать композицию. При наследовании весь функционал класса-наследника жестко определен на этапе компиляции. И во время выполнения программы мы не можем его динамически переопределить. А класс-наследник не всегда может переопределить код, который определен в родительском классе. Композиция же позволяет динамически определять поведение объекта во время выполнения, и поэтому является более гибкой.
Вместо композиции следует предпочитать агрегацию, как более гибкий способ связи компонентов. В то же время не всегда агрегация уместна. Например, у нас есть класс человека, который содержит объект нервной системы. Понятно, что в реальности, по крайней мере на текущий момент, невозможно вовне определить нервную систему и внедрить ее в человека. То есть в данном случае человек будет главным компонентом, а нервная система — зависимым, подчиненным, и их создание и жизненный цикл будет происходить совместно, поэтому здесь лучше выбрать композицию.