Про вериги, радости мазохизма и типизацию
Необходимость типизации обычно объясняют на простом примере.
На взлётную полосу выезжает Saab JAS 39 Gripen.
- Даю разрешение на взлёт.
- Взлетаю.
- Ура!
На взлётную полосу выезжает Saab 9000 CC
- Даю разрешение на взлёт.
- Эта, начальника. У меня крыльев нету. Я машина.
- Ой! Что же теперь делать! Что же теперь делать!
После этого долго и нудно рассказывается, что необходимо чётко указать, кто может выезжать на полосу, а кто не может. Как здорово, что во время исполнения ничего не разваливается, а вместо этого на неправильные данные ругается компилятор.
Скромно умалчивается, что эти типы затем надо поднять до самого верха, до самого ввода данных. Если данные "не правильные", их придётся проверять и преобразовывать. Согласно тем указаниям, которые заданы где-то в глубине системы. Ну да, ещё и проверять на ноль, чего никто не делает.
Также, не сильно обращается внимание на то, что есть ещё и неявные преобразования, которые компилятор считает допустимыми, и о которых сообщает только в особых случаях. В результате все системы, связанные с безопасностью, требуют включить у компилятора все возможные сообщения, перевести всё, что вызывает неудовольствие компилятора, в вид его удовлетворяющий, а те предупреждения, от которых нельзя избавиться, тщательно задокументировать.
В результате получается такой красивый монолитик. Иногда прочный. Иногда не очень. Но сильный удар судьбы не гасящий, а просто от него раскалывающийся.
А чего? Система, не работающая, ошибок не производит. Условие выполнено. Проблемы индейцев шерифа не волнуют. Получите синий экран и обратитесь за помощью к администратору.
Гораздо более гадкая штука при таком подходе - авралонеустойчивость. Менеджер требует отсутствие предупреждений компилятора, а не правильной логики выполнения. Там ниже по течению есть другой отдел, который должен протестировать и выловить все ошибки. Они так и называются Кью-Эй почти как Ай-Кью. Вот пусть они об этом и думают.
А если там ошибка есть, а тот одел её не найдёт, то разработчики за это не отвечают. Проблемы индейцев... И далее по тексту.
В результате при сколь угодно небольшом стрессе (а когда он бывает маленький) программист, наткнувшись на предупреждение компилятора, раздражённо говорит:
- Ну чего тебе опять не нравится? На аэродром разрешён въезд только самолётам? Да вы обалдели. Вы живой аэродром когда-нибудь видели? И как мне теперь топливо перевозить?.. А да ну вас нафиг. На-ка, съешь «Самодвижущееся Транспортное Средство с Колёсами»... Чёрт, не прокатило. Какие идиоты это делали? Достали! Хотите самолёт, держите «Самолёт», а я домой пошёл.
Да, теоретически надо созывать митинг, искать ответственных, выяснять почему и как. Находить пути решения... Но, как мы помним, это всё проблемы индейцев.
В результате ошибки заметаются под ковёр. Чаще всего от лени. Нередко и от глупости. Так что наш выполненный по строжайшим спецификациям, оттестированный полчищами проверяльщиков и увешанный красивейшими сертификатами монолит разваливается не только от сильного удара, но и от лёгкого щелчка в нужном месте.
И опять же. При всей красивости и надёжности, стоит только отпустить вожжи и уменьшить бюджет, как программисты начинают засовывать сложные конструкции в текстовые строки, чтобы разбирать и собирать их на месте руками, или посреди public static final Борщ борщ = new Борщ(); интенсивно закапываются в Java Reflection.
Только не надо мне рассказывать, что это невозможно. Я и сам такое видел.
В результате на взлётную полосу выезжает Saab 9000 CC. Диалог уже совершенно солидный, как у взрослых:
- Ладога-Старт, Saab 9000 CC, разрешите исполнительный и бесступенчатый набор, взлет через 10 минут.
- Saab 9000 CC, Ладога-Старт, ветер 60 градусов, 4, исполнительный разрешаю.
- 9000 CC, занимаю исполнительный.
- 9000 CC, к взлету готов.
- 9000 CC, взлет разрешаю, набирайте 1200, работайте с Кругом 132,0
- 9000 CC, взлетаю.
- Опаньки! Что это?! Нуль Поинтер Эксепшн!
- Запись протокола в нестираемую память.
- Процесс номер один - стоп!
- Процесс номер два - стоп!
- Процесс номер три - стоп!
- Перезагрузка.
При профессиональном параноидальном программировании не важно, работаем мы с типизированными или не типизированными языками. Все кривые данные отсеиваются на входе. В том месте, где эта кривизна играет роль.
Можно сказать про алмазную крошку, но эта аналогия годится только для того, чтобы вешать на уши менеджерам.
Да это стоит времени. Тут надо думать. И надо отвечать на вопрос "почему". И ответ не всегда есть. Вот только диалог в таком варианте профилактики ошибок будет звучать совсем по-другому:
- Ей там, на взлётной полосе! Saab 9000 CC! Ты меня слышишь?
- Привет, начальник! Слышу хорошо.
- Saab 9000 CC, ты собираешься взлететь, твоя масса до 120 тонн, длина разбега при взлёте до 1500 метров?
- Нет, начальник.
- Стой, где стоишь. Докладывай, кто такой, и что здесь делаешь.
Если обработка такой ситуаций не продумана, происходит штатная остановка системы.
Да, система встала.
Но плакать не надо. Сделает она это только один раз. Ошибочного состояния не возникает. Штатная остановка позволяет спокойно выпотрошить всю нужную информацию, а при необходимости и вмешаться руками. Администратор и программисты узнают или об ошибке, которую надо исправить, или о неучтённом требовании, которое надо добавить в техзадание.
Аналог - рубильник остановки конвейера на Тойоте.
Много кто об этом слышал. Мало кто это делает. Бросаться словами lean и kanban гораздо интереснее. Тем более, что применение их к умственной деятельности подходит только для спекуляций и очковтирательства.
Но само паранодоидальное программирование в большинстве случаев рождает мысль о том, что на полосе может оказаться что-то кроме самолёта. Просто потому, что надо думать о чём-то кроме благоприятной ситуации, а не перекладывать это на компилятор.
Практически, программист, строя забор на входе, уже прикидывает, какие могут быть нештатные ситуации, и стоит ли сразу делать их обработку, или просто дёрнуть рубильник, если что-то вдруг пройдёт не так.
Если программист решил, что стоит это на всякий случай обработать, продолжение диалога будет выглядеть примерно так:
- Saab 9000 CC ехать можешь?
- Mогу начальник.
- Saab 9000 CC, взлет запрещаю. Коэффициент сцепления 0,25. Уезжай на стоянку по РД 6. Освобождай полосу.
- Да, начальник. Уезжаю.
Что произойдёт с Саабом дальше? Это уже проблемы индейцев. Если нет, оставляем дополнительно запись в логе ошибок. Или, опять же, дёргаем рубильник.
Типизация - это круто. Это упрощает, ускоряет, и облегчает жизнь компилятору.
Только мне нужна отложенная типизация. То, что я обрабатываю сначала, называется термином «какая-то хнень». И что там будет на самом деле, во многих случаях можно узнать только в полевых испытаниях. Потому как даже чёткая и однозначная спецификация протокола не гарантирует, что оно в реале так и будет. Я уже не говорю про изобретательность конечных пользователей.
Что мне отвечают изобретатели большинства языков и производители всех (кроме самых убогих) тулов? Правильно: «Фигушки!»
Скажем, мне нужно сделать простейшую UML диаграмму обмена сообщениями. Версий десять - пятнадцать. Потом подумать, уточнить, поиграться, обсудить со специалистами.Какие у меня есть возможности?
- Бумага и карандаш (плюс сканер).
- Ага, спасибо.
- Хочется на компьютере и чтобы графика была векторная? Вот, пожалуйста, xfig, Inkscape и PowerPoint.
А что у нас с продвинутыми тулами? С теми, где UML стоит. Которые утверждают, что специально для этого созданы.
Они очень хорошо подходят для того, чтобы студенты с ними поигрались, или чтобы те же студенты задокументировали выполненное программистами решение. И именно так и применяются.
Потому что даже банальный Visio при попытке протянуть стрелочку от одного прямоугольничка к другому начинает спрашивать, какого типа это сообщение, и какие у него параметры, и чего это тут написано с пробелами, ведь при компиляции в некоторые языки могут быть ошибки...
Чёрт побери! В данный момент мне нужно нарисовать стрелочку и написать над ней пару слов. И ещё пять таких же стрелочек. И полтора десятка таких картинок. Почему я должен тратить время на какую-то фигню?
Да, когда-нибудь потом, когда я обсужу, выясню, уточню и проверю, я напишу и классы, и типы, и имена, и пошлю не какую-то абстрактную «доставку провизии», а сообщение асинхронного типа по TCP на определённый порт, с соответствующим стандарту заголовком, с тремя полями данных, с известным ожидаемым значением, со Счётом, Временем Отправления, Красной Шапочкой, Корзинкой и Вином с Пирожками.
Но это будет потом, кода я всё смогу записать просто в коде, а красивая диаграммка, нарисованная умным, мощным и соответствующим последней версии стандарта тулом, мне будет совершенно не нужна.
При работе над сложными случаями асинхронной коммуникации очень бы помогло, сделать модель, сгенерить минимальный работающий код и прогнать тесты на таком же туманном абстрактном уровне. Особенно, если это что-то не тривиальное.
Наши тулы до такого не опускаются. Хочется сделать? Делай руками.
В результате то, что по-идее должно занимать неделю, выливается в проект на пол года.
Продолжение следует.
Copyright
(CC BY-NC-ND 3.0)
vit_r, 2012
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
Перевод на английский запрещён, потому как нефиг портить хорошую вещь.
no subject
Date: 2012-10-25 05:17 pm (UTC)no subject
Date: 2012-10-25 06:04 pm (UTC)no subject
Date: 2012-10-30 01:51 am (UTC)no subject
Date: 2012-10-25 05:45 pm (UTC)no subject
Date: 2012-10-25 06:36 pm (UTC)no subject
Date: 2012-10-25 06:46 pm (UTC)Ещё я знаю concept map и кучу других красивых штучек. Но они годятся только для тех задач, для которых удобны.
no subject
Date: 2012-10-25 05:50 pm (UTC)Вы Enterprise Architect пробовали? Очень быстро получается набросать диаграмки. Быстрее чем в Visio.
no subject
Date: 2012-10-25 06:51 pm (UTC)Enterprise Architect позволяет без напряжения делать диаграмму классов и что-то подобное. Когда начинаются тонкости, впечатления, что создатели просто решили реализовать стандарт, не слишком понимая, к чему эти стрелочки и прямоугольнички.
no subject
Date: 2012-10-25 06:49 pm (UTC)У меня тут в ленте недпавно совсем,
тоже косяком прохордили темы "статическая против динамической",
читай нехочу... :)
но вот что я отметил,
никто даже и не догадался задатся,
поставить такой вопрос -- а для чего вообще нужна типизация?
да ведь на самом деле, для человека в первую очередь,
компилятор-интерпретатор от неё успешно избавляется на этапе трансляции (ну, кроме дебажной инфы и т.п.)
а человеку она нужна,
для того чтобы хоть как-то, хоть приблизительно,
отобразить ситуацию с которой просто в человеческом языке проьблем нет -- информация о типах всегда понятна из контекста (а если нет, то можно переспросить... а если и там клин... что ж, проблемы индейцев... :) )
no subject
Date: 2012-10-25 08:29 pm (UTC)Первым делом, я не говорил, что мне вообще нужна типизация на начальном этапе. В примере задаётся вопрос не
- "кто ты"?
а
- "есть ли у тебя атрибуты с такими именами и со следующими изначениеми параметров?"
или вопрос
- "есть ли у тебя функция с таким именем и можешь ли ты её выполнить?"
В крайнем случае это просто посылка по TCP, строки текста, который на той стороне будет проанализирован и исполнен.
Во-вторых, я не говорю, что мне типизация не нужна. Скажем, в определённый момент я решаю, что первый параметр функции у меня - это доллары и только доллары.
Дальше, в идеальном мире я пишу пару слов, а потом говорю умному тулу: а вот пойди-ка по всем цепочкам вызовов и по всем шагам обработки и проверь размерности. Там, где всё однозначно, поставь тип сам. Там, где не понятно, укажи альтернативы. И, если найдёшь участие в операциях с денежными единицами других типов, сделай мне преобразование функцией перевода валют с коэффициентом по Нью-Йорской бирже на три часа утра по Гринвичу.
no subject
Date: 2012-10-25 08:50 pm (UTC)Похоже на structural types
no subject
Date: 2012-10-25 09:04 pm (UTC)уже способны понимать речь и отвечать на вопросы?
Надо же до чего техника дошла... ;)
no subject
Date: 2012-10-25 09:09 pm (UTC)Идея в том, что я хочу максимально задавать "контракт на входные данные". (посылаемые / принимаемые сообщения,возвращаемые значения и инварианты).
В одном случае это "незнамо что", в другом - объект, имеющий определённые характеристики, в третьем - объект вполне определённого типа и заданных ограничений на значения атрибутов. Причём, все три - параметры одной функции вызова.
Так как такое не поддерживается, приходится работать способом "едим всё, а там разберёмся.
no subject
Date: 2012-10-25 09:59 pm (UTC)говорят что в похожем направлении
justy-tylor.livejournal.com/191741.html
no subject
Date: 2012-10-25 10:31 pm (UTC)no subject
Date: 2012-10-26 05:33 am (UTC)Хотелось бы больше деталей о причинах подобного пессимизма...
no subject
Date: 2012-10-26 07:37 am (UTC)no subject
Date: 2012-10-26 07:41 am (UTC)отвечать на вопросы вроде проще, чем писать...
no subject
Date: 2012-10-26 07:53 am (UTC)Незнание типизации
Date: 2012-10-27 08:15 am (UTC)Привет экстрасенсам
Date: 2012-10-27 08:18 am (UTC)А красивых слов я тоже знаю много.
Re: Привет экстрасенсам
Date: 2012-10-27 09:02 am (UTC)Re: Привет экстрасенсам
Date: 2012-10-27 09:14 am (UTC)Благородному дону не кажется, что это напоминает извращение посерьёзнее занятий любовью в гамаки и в облачении в водолазном костюме?
Я могу делать (и делаю) то, что мне нужно сотней разных способов. Но нужно именно удобное и работающее решение, а не теоретические предположения.
Re: Привет экстрасенсам
Date: 2012-10-27 09:26 am (UTC)Re: Привет экстрасенсам
Date: 2012-10-27 01:26 pm (UTC)Мне тут две страницы надо оправдываться и объяснять, что решение совсем не к той проблеме, да и решение кривое? У меня на это времени нету.
no subject
Date: 2012-10-25 09:02 pm (UTC)получается разумный собеседник, понимающий информацию в контексте,
а не тупой компилятор, которому все надо разжовывать... и все равно он найдет кучу ошибок.
no subject
Date: 2012-10-25 09:18 pm (UTC)В принципе, не совсем это, но что-то подобное, иногда приходится делать ручками. Даже пара шагов в этом направлении были бы очень полезны.
no subject
Date: 2012-10-25 09:57 pm (UTC)no subject
Date: 2012-10-25 08:47 pm (UTC)no subject
Date: 2012-10-25 08:53 pm (UTC)no subject
Date: 2012-10-25 08:57 pm (UTC)Потом, этот код, на самом деле, может быть как комментарий в коде программы. И если что-то меняется, можно прямо в коде класса обновить и UML, изменив код для диаграммы.
no subject
Date: 2012-10-25 09:20 pm (UTC)Есть тулы, поднимающие диаграммы из кода. Вот задавать диаграммы в комментариях я бы не стал, потому как комментарии очень часто отстают от того, как изменяется код.
no subject
Date: 2012-10-25 09:22 pm (UTC)Но ваши сомнения, понятны.
no subject
Date: 2012-10-25 09:39 pm (UTC)Но всё-таки лучше кривая актуальная картинка, чем красивая, но не правильная.
no subject
Date: 2012-10-25 09:41 pm (UTC)no subject
Date: 2012-10-26 01:05 am (UTC)no subject
Date: 2012-10-26 07:39 am (UTC)