anonym_mouse ([info]anonym_mouse) wrote,
@ 2008-02-17 22:33:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
О глубокой философии программирования (серьезный разговор)
.
Есть на Интернете программист-блоггер, 7 лет проработавший в Амазоне. Зовут его Стив Егге, и славен он тем, что в блоге публикует свои "rants" на компьютерные темы. Каждая запись - страниц 5 убористого текста. Многое разумно (ему 39 лет и он достаточно много программировал), но хотя бы из-за объема, многое противоречит себе же. Стив Егге - прототипический п..бол.

И однако одна из записей поразила меня глубоким проникновением в тему. Я давно о ней размышлял, именно в таких, грамматических, терминах. Представляю вам где-то 2/3 его записи в сокращенном несколько виде.


Steve Yegge:
ИСПОЛНЕНИЕ КОРОЛЕВСКИХ ПОСТАНОВЛЕНИЙ[*] В ЦАРСТВЕ СУЩЕСТВИТЕЛЬНЫХ

[*] - игра слов. В оригинале заголовок одновременно означает "Казнь в Царстве Существительных" (execution).

Hello, world!
Здравствуй, мир! Сегодня мы послушаем рассказ о Злом Царе Явы и его борьбу за всемирное уничтожение глаголов.

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

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


The Garbage Overfloweth
МУСОР ПЕРЕПОЛНЯЕТ МУСОРНОЕ ВЕДРО


Все явисты любят диаграммы "use cases", с них и начнем: т.е. вынесем мусор. В том смысле, как во фразе "Джонни, вынеси мусор! Он уже через верх валится!"

Если вы - обычный, нормальный англоговорящий человек, и вас попросили описать вынос мусора, вы наверно думаете о нем примерно так:
    - достать мусорный (пластиковый) мешок из-под раковины
    - вынести его в гараж
    - запихнуть его в большое (пластиковое) ведро [которые в американских городах выставляют к бордюру и их собирают раз в день мусорщики - переводкчик]
    - вернуться в дом
    - вымыть руки
    - шлепнуться на диван
    - продолжать играть в видеигру (или что вы там делали)

Даже если вы не говорите по-английски ..... это - серия действий.
Наши мысли полны отважными, стремительными, эмоциональными действиями. Мы живем, боимся, едим, пьем, идем, останавливаемся, или выносим мусор.
.......

Разумеется, наши мысли также переполнены существительным. Мы едим существительные, покупаем существительные в магазине, мы сидим на существительных, и спим на них. Существительные могут свалиться на вашу голову, создав на голову существительное больш(ую)ое проблему существительное.
Существительные - вещи, но они только вещи. ....... Интересны изменения случающиеся с этими вещами.

Изменения требуют действия, т.е. глагола.

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

Сейчас я расскажу вам сказку о царстве, где произошло именно это.


The Kingdom of Nouns
КОРОЛЕВСТВО СУЩЕСТВИТЕЛЬНЫХ


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

Потому что судьба граждан-Глаголов в королестве очень, очень дурна.

В Явалэнде, по повелению Короля Явы, всеми Глаголами владеют Существительные. Они, по сути, рабы королевства, или по крайней мере слуги или временные слуги (лишенные прав до состояния рабства). Жителей Явалэнда вполне устраивает такая ситуация, и они вряд ли подозревают что все может быть устроено иначе.

Глаголы в Явалэнде делают всю работу, но поскольку их презирают все сословия, ни одному Глаголу не позволено передвигаться самостоятельно. Если Глагол появляется в публичном месте, то всегда только в сопровождении Существительного.

Конечно, "сопровождать", само будучи глаголом, не может бегать без одежды, для него необходимо вызвать ГлаголоСопровождающий. Но что же "вызвать"? - оказывается, Вызывающие и ВспомогательствующиеВызовам также довольно важные Существительные работа которых - присматривать за низкими глаголами "вызвать" и т.д.

Король, посоветовавшись с Богом Солнца по такому важному вопросу, иногда угрожал полностью изгнать всех Глаголов из Королевства Явы. Если такое случится, то жителям понадобится хотя бы один Глагол чтобы делать за них всю работу, и Король, обладая довольно жестоким чувством юмора, решил, что им останется глагол "ИсполнитьОкончательныйУказ" [по-английски - игра слов: execute означает одновременно "исполнить" на официальном языке, и "казнить" -- переводчик]

Глагол "Исполнить" (и его кузины-синонимы "делать", "начать", "пшел", "давайделай", и "впередвперед") могут сделать работу любого другого Глагола подменив его соответствующим ИсполнительнымСуществительным, и вызовом "исполнить()".
Вам нужно почистить зубы? - ЗубоЧиститель(моиЗубы).вперед()
Вынести мусор? -МусорВыносительПланоИсполнитель.давайделай()

В наиболее патриотических провинциях Явалэнда Существительные полностью выдавили Глалогы. Случайному наблюдателю может показаться, что глаголы все еще мелькают, здесь и там, перепахивая поля и вынося господские ночные горшки. Но если присмотреться, вскорости открывается секрет: Существительные могут просто менять имена своих Глаголов-исполнителей(), называя слуг по имени господ (что не изменяет их работы ни малейшим образом). Когда вы заметите,что ПолеВспашка "пашет()", НочноГоршкоОпорожнитель "выливает()", или МэнеджерРегистрации неожиданно сам "регистрирует()", на самом деле вы встретились с армией "Исполнителей.Указов" злого короля, переодетых в одежды своих Существительных



Verbs in Neighboring Kingdoms
О ГЛАГОЛАХ В СОСЕДНИХ КОРОЛЕВСТВАХ


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

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


В этих королевствах нет нужды создавать существительные-обертки для глаголов. У них не появляется ни МусороВыносительнойСтратегии, ни МусороВыносителеЦелеУказания для обнаружения куда идти с мешком в гараже, ни ПослеМусороВынесеннойАкцииОбратногоВызова
прежде чем вы сможете вернуться на свой диван. Они прости пишут глаголы, работающие с существительными, а за тем запускают главный глагол, "вынести_мусор()", включающий мелкие под-действия в нужном порядке.

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

Разница в том, что когда глаголам позволено существовать независимо, не приходится изобретать существительные, которые бы их содержали внутри себя.

Явалэндеское население посматривает на соседей с презрением. Так и живут люди в Программистских Королевствах.


If You Dig a Hole Deep Enough...
ЕСЛИ КОПАТЬ ОЧЕНЬ ГЛУБОКО...

[игра слов: первая часть современной американской поговорки: если выкопать очень глубокую яму, попадешь в Китай; также см. "deep hole to China" - перев.]

На другой стороне мира есть малонаселенные земли, в чьих королевствах Глаголы оказываются среди знати. Это - Функциональные Королевства, которые включают Хаскелию, Окамлику, Схемерию и несколько других. Их жители редко встречают граждан земель в округе Явалэнда. Поскольку рядом с ними мало кто живет, и когда им нечем заняться, они ведут войны друг с другом.

В Функциональных Королевствах Существительные и Глаголы обычно считаются гражданами одной касты. Однако Существительные, оставаясь существительными, в основном сидят ничего не делая. Они не видят смысла в беготне и исполнении работ, поскольку Глаголы вполне активны и уже всем этим занимаются. В этих странах нет странных законов, обязывающих создание Существительных для сопровождения каждого Глагола, поэтому здесь живет ровно столько существительных, сколько в королевстве найдется вещей.

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

На самом отшибе за Функциональными Королевствами, лежит былинная земля под названием Лямбда Окраинная (Lambda the Ultimate). В этом месте, рассказывали люди, вообще не водятся "существительные"! Там живут только глаголы! Конечно, в королевстве есть "вещи", но все они созданы из глаголов, даже сами числа чтобы пересчитывать овец [игра слов: lambda - lamb, звучат похоже -- переводчик], которые оказывается самая популярная форма денег для обменов в тех краях, если слухи не врут. Например, 0 - просто лямбда(), а 1 - лямбда(лямбда()), 2 - (лямбда(лямбда(лямбда()))) и т.д. Каждое, глагол ли, существительное или что-то еще, сконструировано из Главного Глагола, "Лямбда".

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




Are Javalanders Happy?
СЧАСТЛИВЫ ЛИ ЯВИСТЫ?


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

      [Напомню стишок-поучение - перев]:
      Не было гвоздя — подкова пропала
      Не было подковы — лошадь захромала
      Лошадь захромала — командир убит
      Конница разбита, армия бежит.
      Враг вступает в город, пленных не щадя
      Оттого, что в кузнице не было гвоздя.


    Не было гвоздя - "брось новое ПодковоГвоздьНеНайденИсключение("гвоздей нет!")

    Не было подковы - "ЛошадеДоктор.получитьМестнуюКопию().получитьЛошадеДиспетчер().давайделай()

    Лошадь захромала - СкаковойКлуб.получитьСсписокОповещенияПодписчиковНаездников().получитьРассылателя().вперед(новое СообщениеРассылка(Конюшня.получитьНулевойЛошадеОбразец()))

    ............/и так далее/.............


    For the lack of a nail,
        throw new HorseshoeNailNotFoundException("no nails!");
    
    For the lack of a horseshoe,
        EquestrianDoctor.getLocalInstance().getHorseDispatcher().shoot();
    
    For the lack of a horse,
        RidersGuild.getRiderNotificationSubscriberList().getBroadcaster().run(
          new BroadcastMessage(StableFactory.getNullHorseInstance()));
    
    For the lack of a rider,
        MessageDeliverySubsystem.getLogger().logDeliveryFailure(
          MessageFactory.getAbstractMessageInstance(
            new MessageMedium(MessageType.VERBAL),
            new MessageTransport(MessageTransportType.MOUNTED_RIDER),
            new MessageSessionDestination(BattleManager.getRoutingInfo(
                                            BattleLocation.NEAREST))),
          MessageFailureReasonCode.UNKNOWN_RIDER_FAILURE);
    
    For the lack of a message,
        ((BattleNotificationSender)
          BattleResourceMediator.getMediatorInstance().getResource(
            BattleParticipant.PROXY_PARTICIPANT,
            BattleResource.BATTLE_NOTIFICATION_SENDER)).sendNotification(
              ((BattleNotificationBuilder)
                (BattleResourceMediator.getMediatorInstance().getResource(
                BattleOrganizer.getBattleParticipant(Battle.Participant.GOOD_GUYS),
                BattleResource.BATTLE_NOTIFICATION_BUILDER))).buildNotification(
                  BattleOrganizer.getBattleState(BattleResult.BATTLE_LOST),
                  BattleManager.getChainOfCommand().getCommandChainNotifier()));
    
    For the lack of a battle,
        try {
            synchronized(BattleInformationRouterLock.getLockInstance()) {
              BattleInformationRouterLock.getLockInstance().wait();
            }
        } catch (InterruptedException ix) {
          if (BattleSessionManager.getBattleStatus(
               BattleResource.getLocalizedBattleResource(Locale.getDefault()),
               BattleContext.createContext(
                 Kingdom.getMasterBattleCoordinatorInstance(
                   new TweedleBeetlePuddlePaddleBattle()).populate(
                     RegionManager.getArmpitProvince(Armpit.LEFTMOST)))) ==
              BattleStatus.LOST) {
            if (LOGGER.isLoggable(Level.TOTALLY_SCREWED)) {
              LOGGER.logScrewage(BattleLogger.createBattleLogMessage(
                BattleStatusFormatter.format(BattleStatus.LOST_WAR,
                                             Locale.getDefault())));
            }
          }
        }
    
    For the lack of a war,
        new ServiceExecutionJoinPoint(
          DistributedQueryAnalyzer.forwardQueryResult(
            NotificationSchemaManager.getAbstractSchemaMapper(
              new PublishSubscribeNotificationSchema()).getSchemaProxy().
                executePublishSubscribeQueryPlan(
                  NotificationSchema.ALERT,
                  new NotificationSchemaPriority(SchemaPriority.MAX_PRIORITY),
                  new PublisherMessage(MessageFactory.getAbstractMessage(
                    MessageType.WRITTEN,
                    new MessageTransport(MessageTransportType.WOUNDED_SURVIVOR),
                    new MessageSessionDestination(
                      DestinationManager.getNullDestinationForQueryPlan()))),
                  DistributedWarMachine.getPartyRoleManager().getRegisteredParties(
                    PartyRoleManager.PARTY_KING ||
                    PartyRoleManager.PARTY_GENERAL ||
                    PartyRoleManager.PARTY_AMBASSADOR)).getQueryResult(),
            PriorityMessageDispatcher.getPriorityDispatchInstance())).
          waitForService();
    


    All for the lack of a horseshoe nail.


И все - из-за одного гвоздя

Глубокая мудрость, верная до сегодняшнего дня




[anonym_mouse, переводчик]
К этому добавлю от себя. К моему удивлению, первые комментаторы перевода в ru_programming просто не поняли о чем речь в этом отрывке (!!!)

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

Поэтому ИДЕАЛЬНЫЙ язык программирования должен позволять ЕСТЕСТВЕННЫЙ для человека лингвистический разбор задачи на куски и их изложение.

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

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

Когда существительное (состояние и т.д.) образуется в результате действий над предыдущим состоянием или предметом (которых, _исходных_ предметов и их собраний, в программе относительно мало) - и вместо того, чтобы давать ему имя, мы анонимно вкладываем его в следующее по цепочке действие

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

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

    (цель) ДОМ :- (зависит от) крыша, стены, окна, двери
    
    Крыша:- стропила, черепица
    
    стропила:- дерево_подготовить, конструкцию_поднять, конструкцию_собрать
    
    конструкцию_собрать:
        (конкретные вычисления-операторы через и, или, ...)
    

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

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

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


Я для себя делаю из всего этого один, для меня очевидный вывод:
поскольку все выдуманные до сего дня парадигмы языков программирования в какой-то мере "естественны" (возможно, для одного круга задач, тогда как другие - для других), то ИДЕАЛЬНЫЙ ЯЗЫК ПРОГРАММИРОВАНИЯ должен позволять выражать на себе НЕ громоздко, но кратко и изящно, ВСЕ парадигмы, т.е. подходы и логику разбиения для увязки верхнего уровня программирования - при том снабжая программиста лёгкими операторами для конкретных задач (строк, хэшей, стеков, связи с операционкой и т.д.).

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



(Post a new comment)


[info]suhov
2008-03-26 09:15 pm UTC (link)
А Вы не знакомы с формальными методами в программировании? Ну, например, язык B (или B method) и ему подобные? Там вообще песня. Вы на математическом языке просто объясняете ЧТО должна достичь программа. Ну, например,

МАКС(x,y) := это такой x или такой y, что он больше либо равен x и больше либо равен y.

Заметьте, что вы не специфицируете КАК вы достигнете результата, а только ЧТО является результатом а что нет. Дальше запускаете машину и, о чудо, она выдаёт вам конкретную программу:

МАКС(x,y) := если x > y то x, иначе y.

Это происходит конечно в несколько шагов и всё не так просто.. На каждом шаге программа обрастает деталями, "уточняется", становится всё более и более конкретной. Более того, каждый шаг математически выверен и доказано что он "не ухудшил спецификацию", то есть для данной области определения входных данных программа будет выдавать правильный ответ, удовлетворяющий изначальным требованиям (то есть для каждой пары произвольных x и y выдаст такой z что ..).

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

PS Вся теория основана на "изобретении" Дейкстры - weakest precondition. http://en.wikipedia.org/wiki/Weakest_precondition
Это в некотором роде "спецификация" того что программа делает. А каждый шажок назывался refinement.

(Reply to this) (Thread)


[info]ezdakimak
2008-05-25 11:48 pm UTC (link)
Естественный язык избыточно функционален, поэтому естественное описание программам нафиг не нужно. А такие вещи, как "МАКС(x,y) := если x > y то x, иначе y." записываются точно также на языке программирования max(x,y){return x>y?x:y;}

(Reply to this) (Parent)(Thread)


[info]suhov
2008-05-26 11:13 am UTC (link)
Вы не поняли. Суть в том, чтобы сначала описать задачу на дескриптивном языке, то есть специфицировать ЧТО должна программа делать без указания КАК это делать. Если Вы напишите max(x,y){return x>y?x:y;} это уже конкретная программа - там указано КАК находить максимальное из двух чисел.

(Reply to this) (Parent)(Thread)


[info]ezdakimak
2008-05-26 11:56 am UTC (link)
А в чем отличие записи "что должна делать" на листке бумаги от редактора кода?

(Reply to this) (Parent)

(Reply from suspended user)

[info]sontar
2008-05-25 12:59 am UTC (link)
Всё прочитал, но ничего не понял. Можно ещё про ООП?

(Reply to this)


[info]ezdakimak
2008-05-25 11:45 pm UTC (link)
Ещё у идеального языка программирования должна быть функция "написать программу".

Это кажется первая статья, где для каждого случая выбирается собственная жизненная ситуация. Афигеть как удобно сравнивать.

(Reply to this)


[info]xeus_ru
2008-06-05 01:32 pm UTC (link)
кину в заклады, может потом почитаю.

а можно суть парой предложений?

(Reply to this) (Thread)

(Reply from suspended user)

[info]masistokl
2008-12-07 08:04 pm UTC (link)
Когда есть претензии к Творцу. Человек с маленьким ребёнком идёт по улице, и ребёнок горько плачет. Все прохожие, которые смотрят на отца, думают: Какой жестокий человек! Он может спокойно слушать плач своего ребёнка и не обращает внимания на него. Получается, что у прохожих плач ребёнка вызывает жалость, но не у отца ребёнка. В конце концов, прохожие не выдержали и спросили отца ребёнка: Где же твоё милосердие? На что человек ответил: А что же мне делать, если мой любимый сын, которого я берегу как зеницу ока, просит у меня булавку, чтобы почесать себе глаз. Разве из-за того, что я не выполняю его просьбу, меня можно назвать жестоким? Ведь если я сжалюсь над ним и дам ему булавку, он выколет себе глаза и станет слепым.

(Reply to this)


Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…