Framework

Программисты сегодня…

…толком и не знают где заканчивается язык программирования и начинается фреймворк.

Что я под этим имею в виду?

Примерно до 1988-ого года большинство программ, которые могли бы использовать люди, были написаны с нуля с помощью программистов (зачастую всего лишь одним) используя 3GL (язык программирования третьего поколения). Ключевое слово с нуля.

Как я объяснял в первой статье этой серии, 3GL — это абстрактная сборка или машинный язык в зарезервированных словах.¹ Язык программирования — это коллекция зарезервированных слов и некоторых правил грамматики, которые ограничивают использование этих слов таким образом, чтобы не путать компилятор (который развёртывает эти слова в серию команд на машинном языке). Всё вместе это называется синтаксис языка.

 

Как вы видите некоторые языки имеют на удивление мало зарезервированных слов для запоминания. В SmallTalk всего лишь 6!

Вернёмся к программному обеспечению до 1988-ого. Если вы посмотрите на программы написанные до этого времени, то увидите, что единственные слова помимо зарезервированных — это названия переменных и функций, которые создали программисты.

Код для сжатия изображений (который написан на С) использует только два зарезервированных слова: for и double. Два подчёркнутых слова (fabs иprintf) — это функции из подключенных библиотек (stdio.h и math.h). Когда библиотека подключена таким образом это называют зависимостью. Все остальные слова в этой программе или переменные, или комментарии написанные программистом.

Простым подсчётом слов получается, что 90% кода написано программистом. Меньше 10% кода уже было написано кем-то. 4% из другого языка и 6% из двух библиотек.

for(x=0; x < im1->width; x++)
{
   for(y=0; y < im1->width; y++)
   {
     totalDiff += fabs( GET_PIXEL(im1, x, y)[RED_C] - GET_PIXEL(im2, x, y)[RED_C] ) / 255.0;
     totalDiff += fabs( GET_PIXEL(im1, x, y)[GREEN_C] - GET_PIXEL(im2, x, y)[GREEN_C] ) / 255.0;
     totalDiff += fabs( GET_PIXEL(im1, x, y)[BLUE_C] - GET_PIXEL(im2, x, y)[BLUE_C] ) / 255.0;
   }
}
printf("%lf\n", 100.0 * totalDiff / (double)(im1->width * im1->height * 3) );

А теперь давайте посмотрим на Java-версию этой функции:

public enum ImgDiffPercent {
    ;
 
    public static void main(String[] args) throws IOException {
        // https://rosettacode.org/mw/images/3/3c/Lenna50.jpg
        // https://rosettacode.org/mw/images/b/b6/Lenna100.jpg
        BufferedImage img1 = ImageIO.read(new File("Lenna50.jpg"));
        BufferedImage img2 = ImageIO.read(new File("Lenna100.jpg"));
 
        double p = getDifferencePercent(img1, img2);
        System.out.println("diff percent: " + p);
    }
 
    private static double getDifferencePercent(BufferedImage img1, BufferedImage img2) {
        int width = img1.getWidth();
        int height = img1.getHeight();
        int width2 = img2.getWidth();
        int height2 = img2.getHeight();
        if (width != width2 || height != height2) {
            throw new IllegalArgumentException(String.format("Images must have the same dimensions: (%d,%d) vs. (%d,%d)", width, height, width2, height2));
        }
 
        long diff = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                diff += pixelDiff(img1.getRGB(x, y), img2.getRGB(x, y));
            }
        }
        long maxDiff = 3L * 255 * width * height;
 
        return 100.0 * diff / maxDiff;
    }
 
    private static int pixelDiff(int rgb1, int rgb2) {
        int r1 = (rgb1 >> 16) & 0xff;
        int g1 = (rgb1 >>  8) & 0xff;
        int b1 =  rgb1        & 0xff;
        int r2 = (rgb2 >> 16) & 0xff;
        int g2 = (rgb2 >>  8) & 0xff;
        int b2 =  rgb2        & 0xff;
        return Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);
    }
}

Всё, что выделено жирным — это ключевые слова, а всё подчёркнутое — это слова из импортированных библиотек. 65% этого кода написано программистом, 20% кода из синтаксиса и 15% зависимости от внешних библиотек.

Я не говорю, что это плохая вещь. Я просто указываю на этот факт. Как выясняется, подключение кода из библиотек — это отличный способ увеличить продуктивность. Нет никакого смысла для обычного программиста заново создавать базовые инструменты программирования: зарезервированные слова, библиотечные классы и функции. Таким образом, в современном программирования развивается тенденция всё меньше полагаться на свой код и всё больше на уже написанные чужие решения в виде готовых библиотек. Несмотря на то, что само по себе это неплохо, многие согласятся, что это зашло слишком далеко.

И магия случается…

В начале 2016-ого произошло то, что по ощущениям сломало половину интернета. Один программист удалил из публичного репозитория npm 11-строчную программу left-pad. Оказалось, что некоторые из самых больших и используемых в мире JavaScript-фреймворков чаще включали в себя зависимость от left-pad вместо того, чтобы записать следующие 10 строк кода:

function leftpad (str, len, ch) {
    str = String(str);
    var i = -1;    
    if (!ch && ch !== 0) ch = ' ';
    len = len - str.length;
    while (++i < len) {
        str = ch + str;
    }
    return str;
}

Другой npm-пакет, который назывался isArray имел 18 миллионов скачиваний в феврале 2016-ого года и является зависимостью для 72 других npm-пакетов. 18 миллионов программистов и 72 автора пакетов скорее используют зависимость, чем напишут следующую строчку кода:

return toString.call(arr) == '[object Array]';

Может быть я чего-то не понимаю, но для меня это совершенно ясно показывает, что программисты, которые создали 72 пакета для npm, имеют самое ужасное чувство юмора, которое я только видел. Или же понятия не имеют о том, что было в isArray и как на самом деле работает JavaScript. Я взял это как самый выдающийся пример карго-культного программирования.

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

Убирайся с моей лужайки

 

Так к чему же я всё это веду?

Моё мнение, что “программирование”, которым его представляет среднестатистический человек, сегодня едва ли существует. Программисты, которые “пишут код” в виде новых алгоритмов, работают или в очень больших компаниях, или пишут программное обеспечение для обработки видео, картинок или звуков в стартапах.

Армии “детей сегодня”, которые работают в соляных шахтах корпоративных или государственных IT, делают что-то совсем иное. Программы, которые они делают, являются программным эквивалентом для создания мемов и социально-медийных постов, включающих в себя пост-модерновые популярные культурные отсылки. Только вместо того, чтобы перерабатывать картинки с Клинтом Иствудом, хорошим парнем Грегом и мудаком Стивом, они вырезают и вставляют код, а также без разбора используют такие библиотеки, как left-pad или isArray. Они действительно не понимают, где заканчивается язык программирования и начинается фреймворк. Для них это всё одна каша.

И несмотря на то, что я не “ребёнок”, я едва ли лучше себя чувствую. Я нахожу себя таким же карго-культным программистом (неохотно, но честно).

Перевод статьи Adam Zachary WassermanFramework or language?

Предыдущая статьяReactJS, Angular5 и Vue.js — какой фреймворк выбрать в 2018 году?
Следующая статья3 простых шага для написания сложных компонентов