Возможна ли сегодня хотя бы маленькая символическая смычка между "полезненьким" прикладным мэйнстримом, на котором так здорово зарабатываются деньги, и полунищей theoretical computer science?

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


2022-11-23 07:08

Возможна ли сегодня хотя бы маленькая символическая смычка между "полезненьким" прикладным мэйнстримом, на котором так здорово зарабатываются деньги, и полунищей theoretical computer science? Пока что они всё быстрее разбегаются: мэйнстрим пробивает дно за дном, а tcs улетает всё выше и выше в космические облака. Я верю в формальные методы, формальную философию и математическую логику в качестве ключевых инструментов для познания языка (программирования), однако Людвиг Витгенштейн принимал также и противоположные взгляды — поверхностные и противоречивые, но более связанные с "реальной жизнью" :) Сегодня они неплохо описываются в конструктивной математике, в частности в интуиционистской логике (Карри-Ховард и вот это всё).

Вот и пытаюсь прокладывать тут какие-то тропинки.

=

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

На эту тему есть хорошая шутка:

Лисперы: Лисп — самый красивый язык программирования. Он невероятно элегантен, он был не создан "инженерно", а открыт — как научное открытие. Он вечен как сама математика, которой он, безусловно, и является.

Лисп: LOL Две мои самые распространенные функции названы в честь инструкций того странного процессора, который IBM разработала в 50-х годах.

ассемблер IBM 704 (между прочим, 36-битный):

CAR — содержимое адресной части регистра

CDR — содержимое декремента регистра (особая фишка для быстрого смещения адреса)

'Lisp's core occupies some sort of optimum in the space of programming languages.' — John McCarthy

=

О разнице в подходах ФП и ООП написаны тысячи статей. В ФП делаем акцент на логике вычислений, но при этом данные размазываются по всему проекту. В ООП делаем акцент на данных, но при этом вычисления размазываются по всему проекту. Но в обоих случаях ключевым прикладным преимуществом каждого подхода считается централизация изменений (в функциях или в типах данных). Вот тут обычно и упускается то самое неформальное, которое однако и может послужить достаточно формальной склейкой разных парадигм, потому что на практике такая "централизованная" абстракция (функциональная или модель данных, неважно) — скорее идеальное конечное состояние, нежели необходимое исходное условие. Ну, да, если вы PhD Стэнфорда или Массачусетса, то наверное сможете с ходу придумывать сильную систему типов, сразу выдавать статичную "кристаллическую" компоновку десятков/сотен/тысяч абстракций. В прозаических же повседневных проектах уровня интернет-магазина программирование — это интерактивный процесс непрерывной адаптации кодовой базы к противоречивым хотелкам менеджеров, полностью подрывающий подход через элегантные функциональные абстракции.

=

Если вы читали СИКП :) то наверное помните, что первая часть так и называется: "Построение абстракций с помощью процедур (функций)". Классическая рекомендация программной инженерии - "Правило трёх" - гласит, что вам надо оборачивать в функцию любой блок кода, который вы копипастите более двух раз (я сторонник ещё более строгой версии: вместо любой копипасты надо сразу делать функцию, т.к. она будет вызываться более одного раза). Это, в принципе, элементарная интуитивная рекомендация, которой сегодня учат на школьном уровне. Об этом говорил и Дейкстра, и Пирс в TAPL: "Любая часть функциональности в программе должна быть реализована только в одном месте в исходном коде. Там, где схожая логика выполняется разными частями кода, полезно объединить их в один путём абстрагирования этих частей".

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

=

Прикладная польза от функциональной абстракции очевидна:

— Функциям можно/нужно давать выразительные имена, таким образом мы формируем в проекте собственный "язык предметной области", комбинируя функции как абстракции;

— При изменении проектных требований код придётся обновлять только в одном месте, а не во многих;

— Исключается вероятность случайных ошибок при копипасте. Я одно время долго собирал статистику своих багов, и очень заметный процент приходился именно на копипасту, когда забыл например изменить счётчик цикла с i на j (кто у меня занимается на курсе Personal Software Process Карнеги-Меллона, практикуются в частности в такой рефлексивной раскладке по типам багов).

Ни в коем случае не критикую этот подход, наоборот, настоятельно рекомендую его обязательно придерживаться. Просто хочу отметить такой важный момент, что создать сразу хороший набор функций (или классов) на практике нереально. Функции будут многократно переписываться, перекомбинироваться, добавляться и удаляться... Даже исключив отладку, мы получим весьма существенные потери времени на бессистемное экспериментирование с кодом (десятки процентов). По сути, если понаблюдать за теми манипуляциями, которые программист выполняет над проектом, то быстро выяснится, что основные действия — это отнюдь не ввод нового чистого кода, а копипаста с последующей многократной модификацией. Встроенные инструменты IDE могут подсказывать код при наборе, но на микро-рефакторинг (постоянное переписывание существующих кусочков кода) уходит обычно подавляющее время, если логика достаточно сложна.

=

Это конечно не я придумал, в академических исследованиях этот факт давно был выявлен, и решать его предложено с помощью подхода, называемого "structure editing". Почему он не добирается до мэйнстрима, уже не раз пояснял: отходить от формата кода как plain text (на древнем уровне перфокарт) производители инструментов разработки не собираются, потому что и так полностью их контролируют при полном отсутствии рынка и конкуренции. Основная идея в том, что принципы управления версиями (как в git) вполне могут быть предоставлены в терминах т.н. структурных правок, в гораздо более простой и естественной модели изменений. Мы правим не "механический" текст, мы правим логику, а изменения в коде корректно фиксируются автоматически. В отличие от git мы работаем не с файлами, а с некоторыми внутренними "автономными" версиями частей кода. В примитивном виде этот подход доступен в IDE в режиме рефакторинга, когда например мы меняем имя переменной, и наглядно видно, где это произойдёт по всему проекту. Впрочем, ничего более сложного классический рефакторинг так и не смог предложить, и нам постоянно приходится вносить кучи чуть более сложных правок вручную.

=

Было создано несколько экспериментальных "структурных" редакторов, и довольно быстро проявились минусы такого подхода. Чисто технические моменты — вроде копий копий — удалось решить достаточно выразительно (а вот обработку скрытых зависимостей — нет), однако UI сам по себе оказался довольно сложным: программистам всё же удобнее работать с кодом, который выглядит линейно и привычно, когда много информации по истории правок скрывается, но последующая работа с такой информацией быстро становится трудной. В итоге, за облегчение когнитивного бремени абстракции приходится платить ещё более тяжёлым видом проблем.

"There is a race between the increasing complexity of the systems we build and our ability to develop intellectual tools for understanding that complexity." — Leslie Lamport

[окончание следует]


Источник: vk.com

Комментарии: