Про ёжика в тумане, зазнайство, языки программирования и вериги

Oct 25, 2012 19:08

Про вериги, радости мазохизма и типизацию

Необходимость типизации обычно объясняют на простом примере.

На взлётную полосу выезжает 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.
Перевод на английский запрещён, потому как нефиг портить хорошую вещь.

re, it, ru, qa, quality, management, agile, se, freelancer

Previous post Next post
Up