среда, 9 июня 2010 г.

Дискуссия

В комментариях к недавнему посту thesz о том "Зачем нужны выкрутасы с типами" завязалось обсуждение и в результате автор предложил мне расширить формат дискуссии и ответить в своём блоге на следующие вопросы:
- почему вы считаете развитием явление, которому более подходит название "расширение использования",
- почему вы считаете, что дизайн не имеет критериев сравнения,
- в моём посте приведён пример "дизайна системы" на основе типов, причём присутствует не менее двух итераций, попроще и посложнее; и до этого писал похожие посты; почему вы считаете, что никто и никогда не показывает, как пользоваться типами при дизайне систем,
- почему вы считаете, что для программирования не нужен ум (и это особенно интересно),
- почему вы считаете не зафиксированное в документе ТЗ отсутствующим ТЗ,
- известна ли вам теория тестирования,
- знаете ли вы об использовании типов для автоматической генерации тестов в библиотеке QuackCheck,
- можно ли протестировать корректность параллельной программы,
- пожалуй, всё.
Отказаться от данного предложения я, конечно, не могу.


Здесь речь идёт о повышении в течении последних 20 лет популярности языков с динамической типизацией, что вряд ли является следствием развития CS. Ответ заключается в том, что развитие "практического программирования" это прежде всего не появление новых фич в языках и теоретических подходов, а прежде всего накопление и критическое переосмысление опыта разработки реальных систем. Результатом данного процесса, в первую очередь, является появление методик разработки, непосредственно не привязанных к используемым инструментам. Такие практики, как "парное программирование", "code review" или "тесты вперёд" вряд ли даже с натяжкой могут быть отнесены к области CS, но именно они вносят наиболее серьёзные изменения в процесс разработки ПО. Поэтому, процесс популяризации динамических языков я называю именно развитие поскольку в результате этого произошло (и продолжает происходить) существенное изменение методологии, а инструмент нельзя рассматривать отдельно от методик его использования. Возможно, Python и не блещет глубиной идей, но на развитие методологии разработки он оказал гораздо большее влияние, чем все наследники ML вместе взятые.

> почему вы считаете, что дизайн не имеет критериев сравнения

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

> в моём посте приведён пример "дизайна системы" на основе типов, причём присутствует не менее двух итераций, попроще и посложнее; и до этого писал похожие посты; почему вы считаете, что никто и никогда не показывает, как пользоваться типами при дизайне систем,

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

> почему вы считаете, что для программирования не нужен ум (и это особенно интересно),

Вообще-то, ничего такого я не говорил. А говорил, что количество ошибок в коде не связано с умом, а скорей со свойствами характера. Собственно, такое наблюдение я сделал как в результате непосредственной работы с другими программистами, так и в результате наблюдения за некоторым open-source проектами.

Впрочем, у меня есть кое-какое мнение и о затронутой теме. Как мерить ум я не знаю, мне известна только методика измерения IQ, которая вызывает много нареканий. Но, за неимением другой, можно попробовать осторожно опереться на неё. Так вот, большинство программистов, с которыми я общался, имели уровень интеллекта выше среднего и думаю, что вполне можно считать, что большинство программистов имеют уровень IQ в районе 120-140. Где-то мне попадалась информация, что большинство Нобелевских лауреатов имеют уровень IQ в районе 130, а 120 встречается чаще, чем 140. Поскольку вряд ли деятельность, за которую вручают Нобелевские премии, является менее сложной, чем программирование, то можно утверждать, что для достижения выдающихся результатов после превышения определённого уровня IQ наиболее значимым являются личностные качества. Т.е. уровень IQ в 120 позволяет эффективно работать даже над весьма сложными задачами, а определяющим фактором для успеха являются свойства характера. Я не вижу каких-либо оснований утверждать, что программист с уровнем IQ в 140 будет более эффективен, чем программист с уровнем IQ в 120.

> почему вы считаете не зафиксированное в документе ТЗ отсутствующим ТЗ

Потому что это типично для моей программистской практики. Типично в начале разработки неизвестно на самом деле, что именно нужно делать. А что получается в итоге зависит от вменяемости разработчиков, вменяемости пользователей и эффективности обратной связи, когда система постоянно меняется на основе результатов практического использования. В итоге, конечный (если так можно выразиться) продукт очень сильно отличается о того, что как-либо подразумевалось в начале. Развитие софта во много обусловлено используемыми (пусть даже в неявной форме) бизнес-процессами, но при этом само влияет на них. Результат больше всего зависит от внутренних свойств организации, в которой проводится разработка, чем от чего-либо ещё.

> известна ли вам теория тестирования

В своё время прочитал довольно нудную книгу "Введение в тестирование программного обеспечения" (Луиза Тамре), но там излагается скорей практическое руководство, чем какая-либо теория.

> знаете ли вы об использовании типов для автоматической генерации тестов в библиотеке QuackCheck

Нет.

> можно ли протестировать корректность параллельной программы

Протестировать можно всё, что угодно, а вот гарантировать обычно ничего нельзя. Впрочем, для веб-приложений используются системы, которые генерируют нагрузку на веб-сервер аналогичную реальному трафику. Повышая интенсивность нагрузки можно в достаточно сжатые сроки провести весьма качественное тестирование, которое, хотя ничего и не гарантирует, но обычно позволяет выявить практически значимые проблемы. Наверняка, схожие подходы можно использовать для тестирования большинства параллельных программ. Кстати, для тестирования потоков в SBCL под Windows, реализацией которых сейчас занимается dmitry_vk, как раз в том числе использовалось тестирование веб-сервера и тривиального генератора нагрузки.

Кажется всё. Хотя пост и не посвящен обсуждение Common Lisp, но тем не менее я использую тэг lisp для того, что бы данный пост попал в Russian Lambda Planet.

41 комментарий:

  1. пункты 0...4 подпишусь под каждым словом.

    Здоровый инженерный подход без абстрагирования от того факта, что работа - это выполнение разных требований разных сторон.

    ОтветитьУдалить
  2. Творчество не имеет критериев сравнения
    Paul Graham "How can art be good"
    Таки имеет. Просто щаз стало модно считать, что ничто не имеет критериев сравнения: не бывает "лучше" и "хуже", а бывает только "альтернативное".

    ОтветитьУдалить
  3. @nealar, своровал мою реплку (:
    Вообще я до сих пор не могу понять, чью позицию мне выбрать. Для меня очевидны как уменьшение ошибок на ранних стадиях разработки при использовании стратической типизации, так и усложнение на более поздних стадиях.
    Но пока мне кажется, что некоторые люди слишком боятся ошибок. Надо будет развить эту мысль.

    ОтветитьУдалить
  4. Жаль, что про "развитие языков программирования" вы дали не ту ссылку. Начинать следовало бы отсюда: http://thesz.livejournal.com/1104542.html?thread=8998558#t8998558

    Т.е. я говорил о развитии языков программирования. Вы же подменили это понятие "распространением". По вашему выходит, что если за последние 20 лет в мейнстрим вышли Perl, Python и Ruby -- то это и есть развитие динамических языков. Хотя никакого развития там со времен Smalltalk-а и Rexx-а не видно.

    Что до вклада Python-а в развитие технологии производства ПО, то и данный тезис нуждается в доказательстве. Поскольку упомянутые вами парное программирование, code review и тесты вперед пришли в мейнстрим благодаря не Python-у, а Smalltalk-у.

    По поводу code review и computer science. Процедуру code review можно рассматривать как частный случай статического анализа. А уж автоматические системы статического анализа кода программ имеют самое непосредственное отношение к CS. И, что забавно, чем более формально строгий язык подвергается статическому анализу, тем точнее получаются результаты этога анализа.

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

    ОтветитьУдалить
  5. @sdfgh153
    >Но пока мне кажется, что некоторые люди слишком боятся ошибок. Надо будет развить эту мысль.

    Пока мне кажется, что некоторые люди сильно недооценивают последствия ошибок в программах. Им следовало бы почитать, например, блог Бертранда Мейера (скажем, http://bertrandmeyer.com/2009/11/29/dwelling-on-the-point/ или http://bertrandmeyer.com/2009/08/21/the-one-sure-way-to-advance-software-engineering/). А так же хотя бы один раз пролистать Forum on Risks: http://catless.ncl.ac.uk/Risks/

    ОтветитьУдалить
  6. Я, как и другие, не соглашусь, что дизайн программы не может быть хорошим/плохим. Ты сам себе противоречишь, потому что сперва рассуждаешь о хорошем дизайне, который позволяет решить те или иные проблемы. С другой стороны, для меня, например, очевидно, что дизайн мало коррелирует с системами типов, а повышенное внимание к ним наоборот уводит в сторону от размышлений о дизайне.

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

    Т.е. нужно понять, что группа хаскелль-разработчиков собралась вокруг него не в последенюю очередь потому, что их очень волнуют именно ошибки в коде и они ищут дизайн-приемы, чтобы эти ошибки избежать. В то же время люди, которые выбирают динамические языки, предпочитают такие свойства дизайна, как гибкость, масштабируемость и т.д. Дизайн — это всегда trade-off, выбор того, что приоритетнее...

    ОтветитьУдалить
  7. @Vsevolod

    Я не использовал термины "хороший/плохой", а апеллировал к понятиям "правильный/неправильный".

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

    ОтветитьУдалить
  8. @archimag

    Безусловно, нет единственноправльного дизайна, но в этом и отличие программирования от чистого творчества, что здесь можно сказать "хорошо" (потому что можно поставить относительно разумные критерии этого "хорошо"). Хотя вариантов хорошо может быть несколько.

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

    Или же дизайн какого-нибудь собора Св. Петра в Риме. Можно предположить, что были внешние критерии: грандиозное строение, которое бы не грузило, в таком-то стиле, с куполом. Были и внутренние: этот купол не должен был завалится, его нужно было эффективно построить и т.п. Очень похоже на программирование. Да, где-то там есть чисто субъективный фактор: нравится/не нравится, но есть и относительно объективные критерии, как по мне.

    ОтветитьУдалить
  9. @Vsevolod

    Правильно, поэтому для оценки того, что такое "хорошо" используется в первую очередь вкус, а не какие-то объективные критерии. Например, Достоевский являются чрезвычайно известным автором, но Чехов и Хэмингуэй (наиболее уважаемые мной авторы) считали его просто ужасным.

    Напомню, что речь идёт о "критериях сравнения". Но термин "хорошо", как обозначение конкретного дизайна как хорошо подходящего для решения поставленной задачи, не является подобным критерием. Как пример: имевшее место обсуждение результатов конкурса в ПФП вообще (в том числе, различия в мнениях в самом жюри), так и в частности, решения от swizard vs решения на VB.

    ОтветитьУдалить
  10. Хороший/плохой дизайн, количество производимых багов - это, скорее, вопрос опыта и самодисциплины, чем инструмента.

    Вообще, если бы не г-н Зефиров, то, имхо, Хаскелль в рунете был бы более популярным :)

    ОтветитьУдалить
  11. > Вообще, если бы не г-н Зефиров, то, имхо, Хаскелль в рунете был бы более популярным :)

    Ага, аналогично как в свое время некто Vlad2 (или как там его) с rsdn своим неадекватом отвратил людей от Nemerle =)

    ОтветитьУдалить
  12. @Евгений Охотников, мне кажется вы передергиваете. Я почитаю ссылки, спасибо, но скажите, правда нужны гарантии безошибочной работы игрового приложения для мобильного телефона или веб-фреймворка на котором будет работать развлекательный сайт?
    Я говорю о тех ситуациях, когда стоимость error proof намного выше, чем того требуют условия и бюджет. И большая часть программирования происходит именно в этой области.

    ОтветитьУдалить
  13. 2sdfgh153: гарантии безошибочности, к счастью, нужны в очень и очень ограниченном множестве задач (связанных, в основном, с жизнеобеспечением чего-либо). В остальном требуется a) минимизировать количество серьезных ошибок до какого-то приемлимого уровня, b) обеспечить возможность их быстрой локализации и устранения и c) снизить вероятность внесения ошибок при сопровождении и развитии проекта. Сделать это, однако, совсем не просто.

    Ошибки в играх, на развлекательных порталах будут терпеть разве что фанаты или если эти игры/порталы будут предоставлять что-то эксклюзивное. В противном случае пользователи уйдут в другое место.

    Что касается "большая часть программирования происходит именно в этой области", то этот тезис нуждается в доказательстве. Там, где я работаю, стоимость ошибки велика. Запросто можно потерять клиентов => вылететь из бизнеса. Поэтому я лично вообще не вижу областей, гда к ошибкам в софте можно было бы относиться столь спокойно.

    ОтветитьУдалить
  14. @Евгений Охотников
    > Что касается "большая часть программирования происходит именно в этой области", то этот тезис нуждается в доказательстве.

    Доказательством является реальная практика. Я вообще не помню случая, что бы какая-либо моя серьёзная ошибка попадала в production, и это при моём "спокойном" отношении. Из того программного обеспечения, разработкой которого я занимался или за разработкой которого мог наблюдать ни одно не страдало от большого количества ошибок. Приемлемый уровень количества ошибок обычно достигается автоматически просто как следствие нормального процесса разработки.

    ОтветитьУдалить
  15. @archimag:

    >Доказательством является реальная практика.

    Практика является доказательством наличия какого-то явления, а не его отсутствия.

    >Приемлемый уровень количества ошибок обычно достигается автоматически просто как следствие нормального процесса разработки.

    Ага, конечно, старая песня: правильные пчелы делают правильный мед.

    Тут одно из двух -- либо вам повезло, либо мне не повезло. Поскольку мы явно наблюдаем разную реальность.

    ОтветитьУдалить
  16. > Практика является доказательством наличия
    > какого-то явления, а не его отсутствия.

    Хм. Как это понимать? Чисто теоретически? Я предпочитаю бороться с теми проблемами, которые вижу, а не которые могу быть в принципе.

    > правильные пчелы делают правильный мед.

    Хорошо, пусть будет по вашем: хорошие программисты пишут хорошие программы. Вы считает по другому?

    > Тут одно из двух -- либо вам повезло,
    > либо мне не повезло.

    Склоняюсь к тому, что вам не повезло, ибо я не в вижу в сети большого колличества материала на тему того, как бороться с ошибками.

    ОтветитьУдалить
  17. >Хм. Как это понимать?

    Очень просто: тест показывает наличие ошибки, но не может показать ее отсутствие.

    В применении к вашим словам: Доказательством является реальная практика. Я вообще не помню случая, что бы какая-либо моя серьёзная ошибка попадала в production, и это при моём "спокойном" отношении. это означает, что ваша практика показывает отсутствие серьезных ошибок в продакшене. Тогда как практика очень серьезных компаний (масштабов IBM, Oracle и Microsoft) свидетельствует об обратном. На фоне большого количества ошибок в различном софте ваш личный опыт ничего не значит.

    >Вы считает по другому?

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

    >я не в вижу в сети большого колличества материала на тему того, как бороться с ошибками.

    Так откуда им взяться, если многие считают, что важность борьбы с ошибками сильно преувеличена :/

    Кстати, у меня вопрос: могли бы вы описать, что такое, по вашему мнению, нормальный процесс разработки?

    ОтветитьУдалить
  18. > Очень просто: тест показывает наличие ошибки,
    > но не может показать ее отсутствие.

    И что с того? Показать отсутствие ошибок не возможно, что вообще рассуждать на эту тему?

    > Тогда как практика очень серьезных компаний
    > (масштабов IBM, Oracle и Microsoft)
    > свидетельствует об обратном.

    Почему эти компании ещё не выбыли с рынка? Кстати, где можно ознакомиться этой практикой?

    > На фоне большого количества ошибок в различном
    > софте ваш личный опыт ничего не значит.

    Весь мир живёт неправильно? Ошибки были, есть и будут. В чём заключается ваша мысль?

    > Я считаю, что даже хорошим программистам очень нужна помощь
    > со стороны тех же языков программирования

    Точнее, со стороны всего комплекса инструментов. И она есть. Уже давно. И?

    > "наймите хороших программистов и они сделают вам хорошую программу"

    Я такого не говорил, зачем вы постоянно переиначиваете смысл сказанного?

    > Так откуда им взяться, если многие считают, что
    > важность борьбы с ошибками сильно преувеличена :

    Я так думаю, что чем более насущно явление, тем больше о нём должно быть материалов. И кажется, действительно, лет 10 том назад было достаточно много материлов (в процентном отношении) на тему борьбы с ошибками.

    ОтветитьУдалить
  19. >И что с того? Показать отсутствие ошибок не возможно, что вообще рассуждать на эту тему?

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

    Тем не менее, две указанные вам проблемы unit-тестами не покрываются. Зато покрываются новыми возможностями языков программирования. Которые эти ошибки не допускают вообще.

    Разницу чувствуете? Невозможность совершить определенную ошибку вообще и невозможность доказать ее отсутствие с помощью тестов.

    >Почему эти компании ещё не выбыли с рынка?

    Поинтересуйтесь состоянием дел MS на рынке серверных ОС. Посмотрите на изменение графика использования IE по сравнению с другими браузерами.

    >Кстати, где можно ознакомиться этой практикой?

    Хотя бы в разделе Windows Update. Или, может быть, сервис-паки, которые MS выпускает для своих продуктов, проходят мимо вас?

    >Точнее, со стороны всего комплекса инструментов. И она есть. Уже давно. И?

    Где, где эта серебрянная пуля?

    ОтветитьУдалить
  20. > Тем не менее, две указанные вам проблемы
    > unit-тестами не покрываются.

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

    > Поинтересуйтесь состоянием дел MS на рынке серверных ОС.
    > Посмотрите на изменение графика использования IE по сравнению с другими браузерами.

    Разве тут дело в ошибках?

    > может быть, сервис-паки, которые MS выпускает
    > для своих продуктов, проходят мимо вас?

    Извините, я не понял, вы что, используете Windows? Это многое объясняет...

    > Где, где эта серебрянная пуля?

    Где я говорил о серебрянной пули?

    ОтветитьУдалить
  21. >Во-первых, это вообще не понятно, что за проблемы, в используемых мной технологиях таких нет.

    Пока вы не хотете осознать проблемы с которыми лично вы не сталкивались, разговаривать с вами не интересно.

    ОтветитьУдалить
  22. > Пока вы не хотете осознать проблемы с которыми лично
    > вы не сталкивались, разговаривать с вами не интересно.

    Хм, а зачем мне осознавать проблемы, с которыми я не сталкивался и скорей всего никогда не столкнусь?

    ОтветитьУдалить
  23. @Евгений Охотников Дополнительно:
    И причиной которых является изначальный плохой дизайн? Это очень в стиле MS, сначала заложить в основу всякое г..., а потом придумывать технологии для борьбы с ним, да ещё и распространять из за отдельную плату.

    Я поэтому и говорил с самого начала, что хороший дизайн существенно упрощает всё остальное, в том числе, существенно сокращает число ошибок и их опасность.

    ОтветитьУдалить
  24. Я бы добавил, что ошибок в программах полно, и среди них есть группы типичных ошибок, которые действительно лучше исключить на уровне языка. Например оьращение со строками в С — это пример bad by design фичи языка. которая приводит к куче фатальных ошибок. Но есть 2 но:
    1. Я никогда не слышал о такой распространенной группе ошибок, как использование данных не того типа (вместо числа передали строку и т.п.) Т.е. одну из двух: либо такой группы не существует, либо я плохо осведомлен. Если это так, то действительно неплохо было бы на счет вреда этих ошибок какие-то исследования. Вот, есть, например, такой документ, как Top25 самых опасных ошибок в программах (http://cwe.mitre.org/top25/). Там про это ничего не сказано. Или, давайте по простому: какие из этих ошибок позволяет устранить развитая система типов? (И даже больше: только ситсема типов)
    2. Вытекающее из первого. Самые неприятные ошибки — это ошибки в логике программы. Например, по алгоритму нужно к чему-то прибавить 2, а мы человек прибавил 3. Или того хуже: из-за ошибки округления где-то условие не то срабатывает и т.д. Как автоматически бороться с таким родом ошибок?

    ОтветитьУдалить
  25. >1. Я никогда не слышал о такой распространенной группе ошибок, как использование данных не того типа (вместо числа передали строку и т.п.) Т.е. одну из двух: либо такой группы не существует, либо я плохо осведомлен.

    Существует. Даже сталкиваться приходилось: http://eao197.blogspot.com/2009/07/progbugs-c-2.html
    В Ruby мне доводилось передавать string вместо Array и даже ошибок не выскакивало :)

    >Вот, есть, например, такой документ, как Top25 самых опасных ошибок в программах (http://cwe.mitre.org/top25/).

    Этот Top очень сильно завязан на Web-приложения. Но даже там есть ошибки, которые могли бы быть устранены посредством должного использования типов -- переполнение буфера и переполнение int-ов.

    ОтветитьУдалить
  26. Ну, переполнение буфера и переполнение интов как класс не существует в Лиспе с динамической типизацией, так что typecheker тут ни при чем.

    А приведенный вами пример — частный случай. Я понимаю, что такие ситуации возможны, безусловно, но вопрос в их значимости и частоте (по сравнению с другими), которая бы оправдала те неудобства, на которые приходится соглашаться, чтобы их исключить. На мой взгляд, она не достаточна, но, возможно, есть исследования, доказывающие обратное?..

    ОтветитьУдалить
  27. >Ну, переполнение буфера и переполнение интов как класс не существует в Лиспе с динамической типизацией, так что typecheker тут ни при чем.

    Знаете, господа Лисперы, ваше самомнение и влюбленность в Лисп отбивает всякое желание на дальнейший разговор. Переполнения интов у вас нет? Ну представьте, что вам нужно запихнуть интовое значение в двоичный PDU в 4-ре байта. Изначально вами предполагалось, что значение не превзойдет 2^32, но случилось переполнение, тип значения сменился с какого-нибудь fast_int_32 на fast_int_64. В программе ничего страшного, но что пойдет в PDU?

    ОтветитьУдалить
  28. Евгений, вы просто плохо знакомы с предметом. В Lisp'е реализована такая концепция, как numerical tower, при которой при переполнении рантайм сам расширяет выделяемую память под число. Можете про это почитать тут: http://jwz.livejournal.com/854482.html

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

    ОтветитьУдалить
  29. 1 и 2 места http://cwe.mitre.org/top25/ -- это как раз ошибки неправильной типизации.

    По п.1: веб-страница в HTML (или точнее ее шаблон в как-то расширенном HTML)-- это не строка, а дерево из каких-то алгебраических типов данных; в то же время операция вставки проводится как конкатенация строк -- получаем Cross-site Scripting.

    По п.2: шаблон SQL запроса -- это не строка, а допустим AST; в приложениях же он хранится и используется как строка -- получаем SQL Injection.

    На возможные возражения "в динамических языках и лиспе конкретно тоже можно..." -- отвечу, да, можно, но будет ли это *удобно*?

    Именно, у меня вопросы к archimag-у:

    1. В каком виде у тебя хранятся шаблоны SQL-запросов?

    2. Достигается ли (и как) гарантия, что выполнить обычную строку как SQL-запрос невозможно?

    3. Достигается ли (и как) гарантия, что при любых входных данных SQL-запрос окажется синтаксически кооректным? (хотя это больше к теме о надежности, чем Топ25 секурных ошибок)

    ОтветитьУдалить
  30. @имя
    Конечно, если у вас есть молоток — то все кажется гвоздем, так же и с системой типов ;)
    А проблема действительно в удобстве. Потому что в каких-то случаях может быть удобно рассматривать HTML именно как строку (ведь нет какого-то идеального платоновского типа у всего. Тип — это аннотация, которую добавляет программист по своему выбору).
    А в Lisp это вообще часто рассматривают как код, который в то же время данные. Поэтому что с HTML, что с SQL, что с Lisp программист работает одинаково, и, конечно, это очень удобно ;)

    ОтветитьУдалить
  31. Лучше на "ты".

    > Поэтому что с HTML, что с SQL, что с Lisp программист работает одинаково, и, конечно, это очень удобно ;)

    Прелестно, прелестно!

    Вот допустим стала задача -- перед самым выводом хтмл-страницы сделать в ее самом верху тоненькую полоску "вы используете бета-версию сайта, бла-бла-бла" -- и как это выполнить, если хтмл это строка? Регуляркой? Так напиши какой. А я напишу, почему она не будет работать :-)

    Если же хтмл идет туда в виде дерева, то это будет что-то типа

    document.body = para("вы используете бэта-версию сайта, бла-бла-бла") + document.body;

    > Конечно, если у вас есть молоток — то все кажется гвоздем, так же и с системой типов

    Если мне "кажется", то как все на самом деле? Именно, как в коде на лиспе достигается невозможность инжекций и крос-сайт скриптинга?

    ОтветитьУдалить
  32. @имя

    Для SQL я использую postmodern, которая обеспечивает специальный eDSL на базе s-выражений, что обеспечивает полную защиту от sql-инжекций.

    Для генерации html, естественно, используются шаблоны, конкретно cl-closure-template и, конечно, она защищает от кросс-сайт скриптинга (см. документацию на Closure Templates от Google)

    > Если же хтмл идет туда в виде дерева, то это будет что-то типа

    Хм, вы вообще имеете какое-либо отношение к веб-разработке, или мне нужно специально рассказывать почему так никто не делает?

    ОтветитьУдалить
  33. > Хм, вы вообще имеете какое-либо отношение к веб-разработке, или мне нужно специально рассказывать почему так никто не делает?

    Очевидно потому, что эту задачу выполняют шаблоны (а это сейчас стандарт).

    Однако так же очевидно, что говорящий "удобно рассматривать HTML именно как строку" говорит это НЕ в контексте использования настоящих шаблонов (настоящих -- это хотя бы на s-выражениях, а не на форматных символах, вставленных в строку (при отсутствии статической проверки, если быть точным)).

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

    > cl-closure-template и, конечно, она защищает от кросс-сайт скриптинга (см. документацию на Closure Templates от Google)

    Чтобы выяснить каким образом она защищает (а я это не пытаюсь оспаривать), придется, возможно, прочитать всю документацию. Поэтому хотелось бы увидеть краткое объяснение.

    Предположу, что ей на вход нужно s-выражение, или вообще замыкание. Т.е. (если так) наблюдаем ту самую защиту с помощью типизации. Правда динамической.

    И возникают вопросы: а что если какой-то хтмл тэг или цсс селектор в шаблоне будет прописан неправильно, причем этот кусок шаблона будет выводится по условию -- и таким образом, забыв его вывести в тестах, мы можем получить полностью валидный хтмл во *всех* тестах, но в продакшене, в каком-то случае, какой-то важный элемент страницы просто не будет показан?

    ________________________________

    Кстати, насчет проповедей. Проповеди нужны, причем агрессивные: "А вот у нас в нашем С++/С#/Lisp/Haskell/... это делается вот как удобно! А у вас?" Иначе не будет прогресса.

    ОтветитьУдалить
  34. @Vsevolod Dyomkin

    >Тип — это аннотация, которую добавляет программист по своему выбору

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

    ОтветитьУдалить
  35. @archimag:

    хотелось бы на "ты" общаться в обе строны, если это совсем не устраивает -- я перейду на "вы".

    ОтветитьУдалить
  36. @имя

    На ты нормально, но только я сейчас в отпуске, у меня лишь небольшой нетбук, на котором очень неудобно писать. Ну и море отнимает много сил, так что мне тяжело участвовать в дискуссиях ;)

    ОтветитьУдалить
  37. вполне можно общаться неспешно, ответить на мои вопросы через недельку-другую-третью, если появится желание

    ОтветитьУдалить
  38. @имя
    Проиллистрирую то, о чем я говорю на счет кода и данных (форматирование отсутствует, поскольку нельзя тут использовать pre-тег. Вставьте в emacs и нажмите C-M-q)

    Вот обычный Lisp-код:
    (defmethod execute-command ((expr %sql-expression)
    &key (database *default-database*))
    (execute-command (sql-output expr database) :database database)
    (values))

    Вот HTML в Lisp'e:
    (who:with-html-output (out)
    (:td :class "right-pane"
    (:div :width "100%" :align "center"
    "some text")
    (:br)
    (xrates-box *default-currency*)
    (:br)
    (:hr :size "1")
    (feedback-box :your-feedback)))

    Вот SQL в Lisp'е:
    (with-transaction ()
    (if (or (sel [*] :from [transaction]
    :where [= [account-id] id])
    (sel [*] :from [pending-transaction]
    :where [= [account-id] id])
    (sel [*] :from [generator]
    :where [= [account-id] id]))
    -1
    (progn (delete-records :from [account]
    :where [= [id] id])
    (delete-records :from [aggregated-account]
    :where [or [= [a-account-id] id]
    [= [r-account-id] id]])
    id)))

    Защиту от тех или иных ошибок в данном случае обеспечивает (или не обеспечивает — в зависимости от вашего желания) семантика используемых конструкций (см. библиотеки CL-WHO и CLSQL, код с использованием которых приведен в этом примере. Да, о ужас, чтобы это узнать, программист должен ознакомиться с их документацией и понять принцип работы. Впрочем, ему не нужно проходить краткий курс по теории категорий ;) Таким образом, возвращаясь к тому, с чего мы начали: XSS и SQL-injection — это не ошибка типизации, поскольку в данном случае мы о типизации вообще не говорим, а с этими ошибками справляемся. Или переформулировав иначе: в принципе, любую ошибку в программе можно назвать ошибкой типизации, ну и что толку? Вы пишите программу или онотологию? Мы — программу, поэтому заморачиваемся с типами только в тех случаях, когда они действительно дают какое-то реальное преимущество при написании программы (также, как, впрочем, и с другими инстурументами).

    PS. На счет строки — я же написал: "в *некоторых* случаях". Впрочем, это не играет существенной роли.

    ОтветитьУдалить
  39. > Или переформулировав иначе: в принципе, любую ошибку в программе можно назвать ошибкой типизации, ну и что толку?

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

    Тем же ошибкам, которые указаны в п.1 и 2, достаточно очень простых типов.

    > Защиту от тех или иных ошибок в данном случае обеспечивает (или не обеспечивает — в зависимости от вашего желания) семантика используемых конструкций

    Короче: не защищают.

    > (:td :class "right-pane"

    а будут хотя бы варнинги, если написать:

    (:td :class pane

    где переменная pane приходит из GET-запроса?

    (приходит как поле, выбранное в выпадающем списке с фиксированным набором вариантов, почему неопытный программер ее и влепил)

    ОтветитьУдалить
  40. да, и будет ли в переменной pane заэкранированы кавычки?

    будут ли заэкранированы кавычки при их наличии в константной стро
    82;е вместо right-pane?

    ОтветитьУдалить
  41. @имя
    представьте себе, в данном конкретном случае заменяет — читайте мануал. ;)

    А на счет очень простых типов: типы то простые, но работать не очень удобно с этим всем. Но разве вы это можете (хотите) понять?.. (вообще, функциональщикам часто не хватает такого простого качества, как эмпатия, чтобы видеть не только свои идеи, но и чужие проблемы)

    ОтветитьУдалить