[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Несколько вопросов вразброс



Артём Н. -> debian-russian@lists.debian.org  @ Tue, 03 Jul 2012 19:25:28 +0400:

 >>  АН> А как доказать корректность сложной функции, которая образует
 >>  АН> систему простых?  Как проверить все связи?  Как доказать
 >>  АН> корректность функции с побочными эффектами?  И, например,
 >>  АН> "крайний" случай: возможно ли доказать корректность поведения
 >>  АН> произвольной ИНС?
 >> С тех пор, надо сказать, наука шагнула довольно далеко вперед, и
 >> рутинные операции типа проверки _всех_ связей компьютер делать уже
 >> обучен.
 АН> ...
 >> А теория нам говорит, что нельзя построить универсальный автоматический
 >> доказыватель программ.  А того, что нельзя доказать конкретную
 >> программу, даже довольно сложную - не говорит.
 АН> А на практике? Ведь программа взаимодействует с окружением. И
 АН> окружение, и программа могут иметь такую сложность, что проверить
 АН> все пути не представится возможным..?  Я не бросаю камень в сторону
 АН> автоматической проверки корректности (о которой и хочу
 АН> узнать). Просто мне кажется, что отказ от тестов - не самая лучшая
 АН> идея.

На практике же основная проблема тестов заключается в том, что они сами
содержат ошибки и часто тестируют не то, что надо, а сколь-нибудь
серьезно покрывающий код набор тестов занимает в разы больше места, чем
сам код, содержит квадратичное по отношению к коду количество ошибок, и
выполняется до следующего Большого Взрыва, если предположить циклическую
модель развития Вселенной :-) Я почти серьезно, я такие наборы тестов
действительно писал.  И тот факт, что они ловили не все ошибки, мне тоже
известен на практике.

Так вот, я не поручусь, что агда тебя заставит доказать программу.
Скорее всего, не заставит.  Но то, что она согласится скомпилировать,
будет надежнее, чем то, что ты сможешь автоматически оттестировать за
разумное время.  Ключевое слово тут "автоматически" - ручное
тестированние может открыть много нового.

 >>  >>  >>  >> Любой статически типизированный функциональный язык с нормальной
 >>  >>  >>  >> системой типов, начиная с того же Haskell или Ocaml.
 >>  >>  >>  АН> Ocaml? Любопытно. Пожалуй, посмотрю подробнее.
 >>  >>  >>  АН> Для него есть какая-то IDE? И как с библиотеками?
 >>  >>  >> Я знаю одну IDE на все случаи жизни.  Emacs.
 >>  >>  АН> И для всяких там GUI? ;-) В общем, я им не пользуюсь.
 >>  >> Ну да.  Поскольку мои дизайнерские способности ниже средних, в отличие
 >>  >> от способностей в разработке поведения, я предпочитаю GUI, которые
 >>  >> пишут, а не рисуют.  Внешний вид - дефолтный, а поведение описывается
 >>  >> словами.
 >>  АН> Дык, "внешний вид" - это не картинка кнопки, а компоновка. Всё же
 >>  АН> словами не опишешь. Видеть надо.
 >> Компоновка как раз очень неплохо описывается словами.  Заодно потом не
 >> возникает типичных для мышконавозенного гуя ситуаций, когда при переводе
 >> на русский половина надписей получается обрезанной, и в лучшем случае -
 >> поперек, а то я у фотошопа видал, что видно нижнюю половину одной строки
 >> и верхнюю - другой...
 АН> Я понимаю, что практически любой интерфейс описывается словами. :-)
 АН> Такой же язык. Но создавать его, описывая словами, мне кажется не
 АН> самой лучшей и перспективной идеей.

А зря.  Если описывать его поведение словами, предварительно подуманными
головой, а визуал оставить на простенькую автоматику, то... выглядеть он
будет не шедеврально.  Зато им будет удобно пользоваться.  А от
интерфейса, о чем современные мышевозильцы под давлением маркетологов
обычно забывают, требуется именно удобно себя вести, а не красиво
выглядеть.  Иначе непонятно, зачем он вообще нужен - если ты хочешь
красивого, выведи себе xsetroot'ом на весь экран картину Рериха, и сиди,
наслаждайся...

 >>  >> JAPH - это не для того, чтобы писать работающую программу :)
 >>  АН> Однако, они показывают вариации синтаксиса: такой разный стиль...
 >> Это не столько вариации синтаксиса, сколько вариации его художественного
 >> использования.  На C, кстати, я тоже такие примеры видел - скажем,
 >> круглую программу, вычисляющую пи.
 АН> На C всё достаточно жёстко, если не извращаться с макросами, ассемблерными
 АН> вставками (вдобавок блобами) и указателями на указатели на указатели.
 АН> Т.е., если делать так, как предполагает язык, там такого сделать нельзя.
 АН> Максимум - это малопонятный из-за названий переменных однострочник (да, или кружок).
 АН> Но это совершенно другое.
 АН> В C нет eval. :-)
 АН> Если подумать, конечно, есть сходства...
 АН> Но, что ещё важно: C, может, и не особенно хороший язык (в плане понятности,
 АН> читаемости и надёжности созданного ПО), но там нет столько всего лишнего. И
 АН> такой кучи синтаксического сахара (без расширений, там массивы - максимум :-D ),
 АН> как в Perl. Плюс, строгая модель: любой вызов - функция.
 АН> C прост и элегантен. :-)

Прост и элегантен, если мы говорим о языках уровня C, Pascal.  Если
говорим о скриптовых - tcl.  А C - это язык, сделанный практиками для
себя, и простота и элегантность его, как и у Perl, весьма умеренны.
Элегантность в жертву практичности и те, и другие приносили без
содрогания.

Вот C++ получился еще и непрактичным.  Хотя лемминги пользуются.  А C и
Perl как раз в этом смысле очень похожи.  Если помнить, для чего они _сейчас_
предназначены.  Просто, вероятно, C ты уже знаешь, а Perl - еще нет, вот
они тебе и кажутся сильно разными.

 АН> А про Perl ходят шутки:
 АН> "Любой набор символов в любой кодировке является синтаксически правильным Perl 6
 АН> кодом.
 АН> Всегда есть бесконечное количество различных способов сделать это.
 АН> Любой человек, писавший до этого на любом языке, может сразу писать на Perl 6.
 АН> Он может даже не догадываться, что пишет на Perl 6. Если, конечно, не будет
 АН> забывать ставить 1; в конце модулей.
 АН> Можно перегружать 1;. Можно перегружать пробелы. Можно перегружать сорц фильтры
 АН> с помощью регулярных выражений, которые тоже можно перегружать.
 АН> Perl 6 имеет эталонную реализацию, написанную на Perl 6 и не способную быть
 АН> выраженной ни на каком другом языке. На Perl 6 эталонная реализация может быть
 АН> выражена, но не за конечное время. Мы работаем над этим.
 АН> 1;"
 АН> ...
 АН> "Программы на Perl могут писаться на любых языках, например на латыни или языке
 АН> Древних. О написаніи программъ въ орѳографіи образца 1916-аго года покамѣстъ
 АН> свѣдѣній нѣтъ.
 АН> Perl — один из немногих языков c поддержкой квантового исчисления."

 АН> Про C - это бы звучало дико. :-)

 АН> "Та часть, которая делает Perl языком Perl, умышленно построена на смеси разных
 АН> парадигм, учитывающей каждую из них. Можно сказать, что Perl не собирается
 АН> навязывать вам никаких догм. "
 АН> Лари Уолл.

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

А остальное - просто шутки.  Да, он позволяет странное.  И в качестве
упражнения для ума люди нередко это странное делают.  Но это не
нормальный стиль написания программ на нем.

 >>  >> Впрочем,
 >>  >> "как на шелл" - это лучше на шелле же и писать.  Ну, с привлечением sed
 >>  >> и/или awk.  perl позволяет писать совершенно третьим способом, и вот
 >>  >> именно им и надо писать надежные программы на нем.
 >>  АН> Эээ.... Каким?
 >> use strict;
 >> eval {...}; (не путать с eval "...")
 АН> Гы-гы... Это мне о многом говорит. :-D Нет, правда. :-D

Не спорю.  Однако, результат надежен.

 >> Для задач, которые можно решать на sh, этого достаточно.  Ну, может, еще
 >> IPC::Open2 и IPC::Open3, когда надо и на вход подавать поток, и на
 >> выходе его забирать, да еще (в случае Open3) stderr анализировать.
 АН> Не знаю, может Perl и хорош. Но Camel Book, о котором тут писали на 1000 с
 АН> копейками страниц? И тогда уж сравните с книгой K&R...

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

 >>  >>  >> А если ты хочешь действительно прекрасного синтаксиса, возьми tcl.  У
 >>  >>  >> него _полное_ описание синтаксиса и семантики укладывается, если я
 >>  >>  >> правильно помню, в одну страницу A4, а if - всего лишь процедура из
 >>  >>  >> стандартной библиотеки.  И все необходимое из того, что я описывал, есть.
 >>  >>  АН> Угу. Я читал описание. Не знаю, сомнительно...
 >>  >> Работает.
 >>  АН> Ну да, только почему-то широко его не используют... Разве что, для
 >>  АН> прототипов.
 >> Пока я не стал большим любителем ОС Emacs, я пользовался tkabber в
 >> качестве jabber-клиента.
 АН> Этот тот, у которого суровый серый интерфейс? o.O

Да.  Но можно раскрасить в несколько строчек конфига.  Мне было не надо,
он мне для разговоров словами был нужен, а не для любования.  А в
разговоре чаще важно, чтобы ничего, в том числе попугайская раскраска,
не отвлекало от темы.

 >> Остальные, сделанные на мейнстримных языках
 >> для разработки Настоящих Приложений(tm), прямо скажем, существенно хуже,
 >> существенно менее надежны, и в случае, когда ненадежность таки
 >> срабатывает, их куда сложнее починить.
 АН> Возможно. Только имеет ли это отношение к языку, в данном
 АН> конкретном случае?

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

 >> А что не широко - так надежные средства надежны потому, что работают на
 >> другом уровне абстракций.  Типичный индус(tm) такой уровень собственным
 >> мозгом не освоил, поэтому пользоваться ими тупо не может.  И не только
 >> индус.
 АН> На уровнях выше? Хм... Но есть шаблоны..?

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

 >> Тонкость с tkabber в том, что по крайней мере один из его ведущих
 >> разработчиков - выпускник мехмата МГУ, и с уровнями абстракций у него
 >> все хорошо...  Поэтому ему на tcl удобно.
 АН> И причём тут Tcl? :-)
 АН> Вопрос в том: почему Tcl - личные пристрастия, исторически так
 АН> сложилось или чем-то обоснованный выбор?

Ты хотел простого и элегантного синтаксиса.  Проще и элегантнее я не
знаю.  Сравнимого - ну, может быть Scheme.  Кстати, она - прекрасный
пример к предыдущему блоку квотинга в этом письме - научить компьютер
обращаться с call-with-current-continuation оказалось несложно и очень
недорого.  А вот я при всем своем математическом образовании с этим
инструментом так и не сумел освоиться пока.  (Все эти ваши исключения и
прочие нелокальные переходы, не говоря уже о вызовах функций, if и
циклах могут быть представлены как частные случаи работы с continuations
и выражены через call/cc, и это далеко не все, на что способна эта
абстракция).

 >>  >>  >>  >> OPT_PARAM1=${OPT_PARAM1:-value1}
 >>  >>  >>  >> и позволить пользователю переопределять именно OPT_PARAM_1,
 >>  >>  >>  >> использование которой он потом увидит, а не неочевидно с нею связанную
 >>  >>  >>  >> ENV_USER_PARAM1
 >>  >>  >>  АН> Проверять наличие в окружении OPT_PARAM перед чтением конфига.
 >>  >>  >>  АН> И записывать во внутреннюю переменную. Затем делать подстановку переменной по
 >>  >>  >>  АН> умолчанию, взятой из конфига.
 >>  >>  >> А чего ради так извращаться, если есть более прямой путь?
 >>  >>  АН> Чтобы не усложнять конфиг и не вносить в него код. Не делать его неочевидным, не
 >>  >>  АН> увеличивать в размере и, следовательно, не усложнять для изменения
 >>  >>  АН> пользователем. При этом, гибкость почти не уменьшится.
 >>  >> Если конфиг надо писать пользователем, то опять же, возьми tcl.
 >>  АН> Ну, а в чём будет разница?
 >>  АН> Тут дело же не в реализации, а в подходе...
 >> 
 >> Разница будет в том, что у tcl язык задания переменных куда более
 >> человеческий.  Программисту пофиг, а пользователю - нет.  (Я вот тут
 >> сейчас по работе смотрю на описание функционала в cucumber, который
 >> позиционируют как инструмент даже не для TDD, а для B(ehavior)DD - так у
 >> него стиль описания еще более человеческий, и в комплекте штатные
 >> переводы ключевых слов на N языков.)
 АН> Тэкс, интересная штука. Сейчас ознакомлюсь.

Глянь.  Там сам-то инструмент простенький и, прямо скажем, глючноватый,
но идея, что можно иметь описание поведения, понятное и (требует
написать дополнительные определения, но не шибко сложные) автоматике, и
заказчику, вплоть до возможности позволить минимально обученному
заказчику самостоятельно описывать это поведение, имеет довольно далеко
идущие последствия на пути к получению _нужного_ результата.

 >>  >>  АН> 2. Это просто обработка значений. Переменная как влияла на
 >>  >>  АН> подмножество действий/объектов, так и влияет. Размер
 >>  >>  АН> подмножества не расширяется.
 >>  >> Э, нет.  Она начинает на него влиять куда как более
 >>  >> обусловленно.  "Если выполняется это условие, проверяемое в
 >>  >> 235-й строке, но не вон то, проверяемое в 538-й, то влияет, а
 >>  >> может, и нет..."
 >>  АН> Ээээ... Не очень вас понял. Есть переменная.
 >>  АН> Она влияет на определённое подмножество объектов.
 >>  АН> Её возможно задать.
 >>  АН> Задаётся она один раз.
 >>  АН> Задан она может быть в конфиге или в переменных окружения.
 >>  АН> Это понижает ортогональность (ради повышения настраиваемости), поскольку есть
 >>  АН> две точки входа, вместо одной - конфига.
 >>  АН> Есть два варианта реализации:
 >>  АН> 1. Обработка в конфиге.
 >>  АН> 2. Обработка в основном коде.
 >> 
 >>  АН> При обработке в конфиге, есть ощущение того, что остаётся одна
 >>  АН> точка входа - конфиг. Реально, как две точки было, так две и
 >>  АН> осталось.  Просто часть логики перелезла в конфиг. Что его
 >>  АН> усложнило.
 >> При этом в конфиге _все_ переменные обрабатываются _единообразно_.
 АН> Ключевое слово - "обрабатываются". Код в конфиге.

Ну, да.  Если мы говорим о шелле, то создать язык конфига, который можно
писать с какими угодно ошибками, и они будут корректно обработаны - это
плохо реализуемая задача.  У шелловских скриптов конфиг, как правило,
исполнимый.  И я давно уже этого не пугаюсь.  Задача конфига - быть
понятным человеку.  _Умеренное_ количество кода там этому не
противоречит.  В отличие от нагромождения виндового реестра и
принципиально человеконечитаемых XML'ей в гномовском.

 >> Вся
 >> однотипная логика выбора значений сконцентрирована в одном месте.  Я,
 >> собственно, опасаюсь, что если ее уносить в скрипт, она будет размазана
 >> по всему скрипту и обладает риском расползания по мере жизни этого
 >> скрипта.
 АН> Но это проблема не подхода, а реализации. Реализатора.

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

 >> Нет, у тех, кто делает такие системы конфигурации.  Начиная с виндового
 >> реестра, и заканчивая гномовским, и еще кем-то у нас в дистрибутиве же,
 >> кто ради не помню чего, чуть ли не тоже конфигурации, тянет за собой
 >> персональный экземпляр mysqld для каждого юзера.  Узнать о существовании
 >> sqlite он, видимо, ниасилил...
 АН> Дык, реестр - это БД. И sqllite - БД. И mysql - БД.
 АН> Всё одно. Принципиальной разницы (на этом уровне) между ними нет: к
 АН> одному они все и пришли.

Э, нет.  /etc/passwd и /etc/network/interfaces - это тоже БД.  Дьявол в
деталях.  А в деталях...

- реестр - единая БД для множества никак не связанных между собой
  программ, которая в результате оказывается труднообозримой и крайне
  слабо пригодной для чтения или изменения человеком (а какая же она
  после этого конфигурация, если чтобы в нее залезть, требуется
  отдельная программа со специфическим интерфейсом, а чтобы разобраться
  в том, что там содержится - отдел аналитики?)

- sqlite - ну, он менее всех плох.  Единственный его недостаток - это
  реляционная модель данных, плохо подходящая для конфигураций.  Она для
  других вещей хороша, а тут не пришей кобыле хвост.  Вот /etc/passwd -
  пример тоже табличных по сути данных, для которых реляционная модель -
  годится, но overkill.  А /etc/network/interfaces - пример
  конфигурации, для которой реляционная модель будет только источником
  ошибок.

- mysql же отличается от этих двоих тем, что это не БД, а СУБД.  Даже
  если сравнить его с sqlite - вместо крохотной библиотеки, нужной для
  чтения данных из файла, мы имеем нехилого размера демона, которому
  отдельно надо настраивать права доступа (и не враз настроишь), который
  весьма нервно относится к внезапной потере питания, данные из которого
  надо бэкапить отдельным хитропопым способом, чтобы не побились, и
  наверняка я еще что-то забыл.  Он, опять же, хорош на своих задачах,
  но если я вижу _персональный_ mysqld, я понимаю, что программами этого
  разработчика пользоваться не следует даже начинать, лучше сразу
  поискать, а то и написать альтернативу.  А то себе дороже выйдет.

 >>  АН> Ну а какие варианты, когда требуется такая сложная система?
 >>  АН> Изобретать свой велосипед, в итоге сводящийся с СУБД?
 >> Если такая сложная система конфигурации действительно требуется, то
 >> уровень сложности самой задачи там запредельный.  Настолько
 >> запредельный, что я, со всем своим опытом, сто раз подумаю, прежде чем
 >> начать ее решать.
 АН> Обязательно? А если это расширяемая задача. А разработчики проектируют
 АН> "сверху-вниз", действуя на далёкую перспективу?

_Так_ проектируемая система не доживет до этой далекой перспективы.  А
если доживет, то обнаружит, что на самом деле все совсем не так, как
казалось много лет назад, на стадии проектирования.

 >> И скорее всего, правильным решением будет не СУБД, и вообще не
 >> конфигурация в привычном понимании, а протокол динамического
 >> согласования, в духе какого-нибудь BGP.
 АН> Хм... Типа, сети независимых агентов?

Смотря как определять зависимости.  Я бы как раз сказал "зависимых",
имея в виду то, что связи между ними есть и важны.

 >> СУБД же вообще предназначена для хранения данных, а не конфигурации.  И
 >> для хранения конфигурации подходит очень плохо.
 АН> Ну, а если это тонкий клиент? Почему не хранить в той же БД и
 АН> конфигурацию?  Например, есть у меня тонкий клиент на каком-нить
 АН> Lazarus, а вся логика в хранимых процедурах, и я в перспективе
 АН> (если таки переделаю всю эту байду, и кому-нибудь ещё это останется
 АН> нужно), хочу добавить web-интерфейс, почему не хранить настройки в
 АН> БД?

СУБД, как правило, пытаются хранить свои настройки в себе же.
Получается плохо :-)

Нет, я понял мысль.  Если у тебя вся логика в БД, то да, имеет смысл по
крайней мере пытаться хранить там настройки приложения.  И то -
настройки клиента тебе таки придется, скорее всего, вынести еще куда-то,
а то он не сумеет подключиться.  Но практика показывает, что хранимые
процедуры - это далеко не самое удобное место для хранения логики.  У
них обычно язык сильно ограничен, и реализация на них этой логики
получается куда более геморройной, чем вне базы.  Опять же потому, что
реляционная модель, или какая там будет модель у конкретной базы,
подходит существенно не для всего - часть логики на нее обычно ложится
нормально, а часть хреново.  И вот ту часть, которая "хреново",
практически всегда стоит из базы унести.


Reply to: