Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Пять причин, по которым язык программирования D является отличным выбором для вашего нового проекта

Оригинал: 5 reasons the D programming language is a great choice for development
Автор: Lawrence Aberba
Дата публикации: 19 мая 2017 г.
Перевод: А.Панин
Дата перевода: 22 мая 2017 г.

Возможность создания прототипов, скорость разработки, читаемость кода и другие преимущества языка D делают его отличным инструментом для совместной разработки программных проектов.

D является статически типизированным языком программирования общего назначения с C-подобным синтаксисом, компилируемым в машинный код. По ряду причин он отлично подходит для разработки программного обеспечения с открытым исходным кодом; в данной статье я постараюсь рассказать о некоторых из них.

Возможность создания прототипов

Скорее всего, вы не раз сталкивались с ситуацией, когда вам нужно было как можно быстрее создать реализацию возникшей идеи в форме кода с минимальными изменениями. Однако, в некоторых случаях вам приходилось отходить в сторону от изначальной идеи по той причине, что ее нельзя было максимально просто реализовать средствами используемого языка программирования, то есть вам приходилось адаптировать идею к коду, а не наоборот. D гармонично сочетает несколько парадигм программирования, таких, как функциональное программирование, императивное программирование, объектно-ориентированное программирование, метапрограммирование и параллельное программирование (модель акторов). Таким образом, вы можете выбрать парадигму программирования, которая лучше всего подойдет для реализации вашей идеи.

Используя шаблоны, позволяющие генерировать дополнительный код на этапе компиляции, вы можете создавать шаблоны для генерации кода силами компилятора. Это возможность оказывается особенно полезной при создании алгоритмов без указания определенных типов обрабатываемых данных. Создание платформонезависимого кода также значительно упрощается благодаря обобщенной природе шаблонов. Комбинируя шаблоны с директивами условной компиляции, можно значительно упростить процесс создания кроссплатформенных приложений, причем впоследствии к разработке таких приложений наверняка подключатся пользователи других операционных систем. Благодаря описанным возможностям отдельному разработчику придется писать меньше кода, что позволит реализовать большее количество функций приложения в течение отведенного для разработки времени.

Диапазоны (Ranges), глубоко интегрированные в язык D, позволяют отделить методику доступа к элементам контейнерных типов (то есть, массивов, ассоциативных массивов, связанных списков и так далее) от их реализации. Данное разделение позволяет проектировать и использовать огромное количество алгоритмов вместе с огромным количеством контейнерных типов без использования определенных структур данных. Срезы массивов в D являются одной из реализаций диапазонов. В результате использования описанного механизма вы также будете писать меньше кода, что положительно скажется на цене сопровождения результирующего программного продукта.

Высокая скорость разработки

Большинство разработчиков программного обеспечения с открытым исходным кодом работают без оплаты в свободное время. D позволяет тратить доступное для разработки время более продуктивно, так как в течение того же времени вы сможете сделать больше. Шаблоны и диапазоны в D повышают продуктивность работы разработчиков программного обеспечения, позволяя им писать обобщенный и повторно используемый код, но это всего лишь несколько полезных, повышающих продуктивность работы механизмов данного языка программирования. Еще одним важным преимуществом языка D является скорость компиляции, сравнимая со скоростью интерпретаторов таких языков сценариев, как Python, JavaScript, Ruby и PHP, что делает его отличным инструментом для создания прототипов.

Код на языке D может взаимодействовать с существующим кодом на других языках, что отменяет необходимость в его портировании. Компилятор D проектировался для непосредственной работы с кодом на языке C: вообще, язык C по сей день широко используется для разработки проверенных временем и протестированных приложений, библиотек и низкоуровневых системных компонентов (особенно в Linux). Код на языке C++ также может в большинстве случаев использоваться из кода на языке D. Фактически, код на таких языках, как Python, Objective-C, Lua и Fortran технически может использоваться из кода на языке D, при этом сторонние разработчики предпринимают попытки использования этих языков совместно с D. Это обстоятельство позволяет использовать огромное количество библиотек с открытым исходным кодом из кода на языке D, что вполне соответствует соглашениям, принятым в мире разработки программного обеспечения с открытым исходным кодом.

Простота чтения и поддержки кода

Код программы HelloWorld на языке D:

import std.stdio; // импорт стандартного модуля ввода/вывода
void main()
{
    writeln("Hello, World!");
}

Код на языке D прост для понимания любым разработчиком, который знаком с одним из C-подобных языков программирования. Более того, даже запутанный код на языке D прост для чтения, что значительно упрощает поиск ошибок. Читаемость кода также крайне важна для привлечения сторонних разработчиков, что является залогом успешного развития проектов с открытым исходным кодом.

Простым, но очень полезным синтаксическим сахаром языка D является поддержка символов подчеркивания для разделения разрядов целых чисел, что делает их более читаемыми. Это особенно полезно для повышения читаемости кода математических приложений:

int count = 100_000_000;
double price = 20_220.00 + 10.00;
int number = 0x7FFF_FFFF; // в шестнадцатеричном формате

Ddoc, встроенный инструмент для автоматической генерации документации на основе комментариев в коде, позволяет отказаться от стороннего инструмента с аналогичными функциями. Он значительно упрощает процесс создания, доработки и обновления документации, так как работает непосредственно с существующим исходным кодом.

Контракты (Contracts) являются проверками, позволяющими гарантировать корректность работы кода на языке D вне зависимости от различных условий. Как и юридические документы с аналогичным названием, подписи под которыми обуславливают намерения всех вовлеченных в процесс сторон, контракты в D обуславливают генерацию ожидаемых результатов или ожидаемое поведение реализаций функций, классов и так далее. Подобный механизм полезен для проверки кода на наличие ошибок, особенно в проектах с открытым исходным кодом, в которых участвует множество разработчиков. В крупномасштабных проектах контракты могут стать попросту незаменимыми. Мощные механизмы контрактного программирования языка D были изначально интегрированы в сам язык, а не добавлены в него впоследствии. Контракты не только упрощают написание кода на языке D, но и упрощают проверку его корректности, а также его поддержку.

Простота процесса разработки

Совместная разработка программных проектов может быть связана с рядом сложностей, так как в ее процессе могут меняться по нескольку фрагментов кода одновременно. D позволяет избежать некоторых из описанных сложностей благодаря поддержке механизма локального импорта модулей в рамках отдельных областей действия.

Оператор "!" используется совместно с функцией filter для задания шаблона аргумента:

// возвращает четные значения
int[] evenNumbers(int[] numbers)
{
    // "filter" и "array" доступны лишь в локальной области дейтсвия
    import std.algorithm: filter; 
    import std.array: array;
    return numbers.filter!(n => n%2 == 0).array;
}

Приведенная выше функция может быть перемещена без нарушения работоспособности кода, так как она не использует каких-либо глобально импортированных модулей. Любая функция, реализованная аналогичным образом, может быть в будущем дополнена также без нарушения работоспособности кода, что очень удобно для совместной разработки.

Универсальный синтаксис вызова функций (Universal Function Call Syntax - UCFS) является синтаксическим сахаром языка D, позволяющим вызывать обычные функции точно так же, как и методы объектов. Например, если функция объявлена следующим образом:

void cook(string food, int quantity)
{
    import std.stdio: writeln;
    writeln(food, " в количестве ", quantity);
}

Может быть вызвана обычным образом:

string food = "рис";
int quantity = 3;
 
cook(food, quantity);

Благодаря универсальному синтаксису вызова функций она может быть вызвана как метод объекта cook:

string food = "рис";
int quantity = 3;
 
food.cook(quantity);

В процессе компиляции компилятор автоматически использует переменную food в качестве первого аргумента функции cook. Универсальный синтаксис вызова функций позволяет связывать обычные функции, что очень похоже на функциональное программирование. Описанный механизм интенсивно используется в D таким же образом, как и в случае с функциями filter и array в рамках приведенной выше функции evenNumbers. Комбинирование шаблонов, диапазонов, директив условной компиляции и универсального синтаксиса вызова функций дает разработчику повысить производительность своей работы без лишних издержек.

Ключевое слово auto может использоваться вместо указания типа переменной. В этом случае компилятор будет самостоятельно выбирать подходящий для переменной тип данных на этапе компиляции проекта. Это позволяет избежать ввода длинных названий типов данных, а также работать с кодом на языке D так же, как с кодом на языке с динамической типизацей.

// Без ключевого слова auto. Вы так делаете?
VeryLongTypeHere variable = new VeryLongTypeHere(); 
 
// Использование ключевого слова auto
auto variable =  new VeryLongTypeHere();
auto name = "John Doe";
auto age = 12;
auto letter  = 'e';
auto anArray = [1, 2.0, 3, 0, 1.5]; // тип double[]
auto dictionary = ["one": 1, "two": 2, "three": 3]; // тип int[string]
auto cook(string food) {...} // auto типа значения, возвращаемого функцией

Цикл foreach языка D позволяет обходить наборы и диапазоны данных различных типов:

foreach(name; ["John", "Yaw", "Paul", "Kofi", "Ama"])
{
    writeln(name);
}
 
foreach(number; [1, 2, 3, 4, 4, 6]) {...}
 
foreach(number; 0..10) {...} // 0..10 - синтаксис для задания диапазона целочисленных значений
 
class Student {...}
Student[] students = [new Student(), new Student()];
foreach(student; students) {…}

Встроенная поддержка модульных тестов языка D позволяет разработчикам не только отказаться от использования дополнительного инструмента для тестирования программного обеспечения, но и упрощает создание самих модульных тестов для разрабатываемого кода. Все тесты должны располагаться в рамках специального блока кода под названием unittest{}:

int[] evenNumbers(int[] numbers)
{
    import std.algorithm: filter; 
    import std.array: array;
    return numbers.filter!(n => n%2 == 0).array;
}
 
unittest
{
    assert( evenNumbers([1, 2, 3, 4]) == [2, 4] );
}

Если же вы используете официальный компилятор проекта под названием DMD, вы можете добавить все тесты в результирующий бинарный файл, просто использовав флаг компилятора -unittest.

Dub, встроенный менеджер пакетов и инструмент для сборки программных компонентов на языке D, упрощает использование постоянно расширяющегося набора сторонних пакетов (библиотек) из реестра пакетов Dub. Dub берет на себя решение всех вопросов, связанных с загрузкой, компиляцией и связыванием программных компонентов на основе кода из этих пакетов, а также их обновлением до новых версий.

Богатство выбора

В дополнение к нескольким парадигмам программирования и возможностям, язык D позволяет пользователю выбрать подходящий компилятор. На данный момент существуют три компилятора, причем исходный код каждого из них открыт. Это официальный компилятор проекта DMD со своим собственным кодогенератором, а также два компилятора GDC и LDC, которые используют кодогенераторы на основе наработок проектов GCC и LLVM соответственно. DMD славится высокой скоростью компиляции, а LDC и GDC - высокой скоростью исполнения генерируемого машинного кода, ценой которой являются дополнительные затраты времени на компиляцию. Вы вольны выбирать тот компилятор, который лучше подойдет для решения ваших задач.

Некоторые компоненты стандартной библиотеки D по умолчанию используют сборщик мусора. Но при возникновении необходимости вы можете работать с памятью в ручном режиме или же задействовать механизм подсчета ссылок. Выбор, как всегда, за вами.

И это еще не все

В D существуют и другие полезные синтаксические конструкции, которые я не упомянул в данной краткой статье. Я настоятельно рекомендую вам ознакомится с обзором возможностей языка D, рассмотреть преимущества его стандартной библиотеки, а также узнать об областях его использования для того, чтобы иметь представление о том, для каких целей данный язык успешно используется на данный момент. Многие организации уже начали использовать D для разработки программного обеспечения, предназначенного для промышленной эксплуатации. Наконец, если вы решили изучить D, вам наверняка пригодится бесплатная книга Programming in D.