Pull to refresh
24
Роман Катунцев@SBKarr

Пользователь

46
Subscribers
Send message
Программирование это навык на границе науки и искусства. Задача программиста: декомпозиция задачи на блоки, каждый из которых должно как можно эффективнее использовать повторно. Наука здесь в декомпозиции и решении задачи. Искусство в эмпирическом предсказании возможности повторного использования каждого отдельного блока решения. Этот тезис был известен даже в СССР. С тех пор не изменился.

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

Беда в том, что из-за низкого порога входа такие вот программисты начинают проектировать свои собственные системы. Которые чуть более, чем полностью состоят из таких вот богоподобных функций с кучей предусловий и неясной механикой работы. В таких системах сложные задачи вполне решаются за 150 строк, если вы достаточно «вкурили» странную логику автора. Только вот это будет навык использования этой конкретной системы, а не навык программирования или решения задач.

Если люди считают, что программирование это решение задач с помощью кода — они «кодеры», программисты низшего уровня. То есть, попросту, или хреновые, или начинающие специалисты. Даже отличники при переходе к реальной работе будут начинающими специалистами. Даже отличники будут совершать типичные ошибки новичков. По опыту могу сказать, что отличники чаще не готовы признать себя начинающими. А значит, склонны дольше оставаться таковыми. Отсюда возникает иллюзия ошибок, характерных именно для отличников. На деле же — обычная ошибка новичка.

Кроме ошибки новичка здесь, несомненно, вина школьного образования в целом. Ибо это образование представляет программирование именно как написание кода. А на деле, написание кода — наименьшая и наиболее простая из задач программиста, вышедшего за пределы начального уровня. Если признать, что отличник это такой ученик, который наилучшим образом встроился в образовательную программу, очевидно, он будет тащить за собой больше всего ошибок этой самой программы.

Мой коллега после прочтения статьи сразу же предположил, что из гениев, способных перепрыгивать огромные этапы решения, выйдут совсем хреновые программисты. Опровергну. Главная черта гения: умение предсказывать результат своих действий далеко вперёд. Если этот гений ещё и программист, он не будет подкладывать себе же грабли. Он скорее сразу разобьёт код на блоки, которые будут удобны для повторного использования ему самому.

Из всего вышеописанного следует, что оценки когнитивной психологии в общем смысле здесь применять неверно. Они, несомненно, важны в деле программирования. Но важны в другом месте. Человеку, который может удержать в голове больше объектов, проще построить грамотную архитектуру. Проще разбить задачу на подзадачи наиболее оптимальным образом. В общем смысле, эффективная архитектура не должна оперировать больше, чем пятью объектами на каждом уровне. Это исходит именно из оценки когнитивной психологии. Достичь этого можно кучей методов композиции и уменьшения связности. Чем больше объектов в человек может удержать в голове в один момент времени, тем лучше он выделит наиболее сильные связи и устранит слабые. Самый важный навык — умение быстро переключаться между уровнями архитектуры: между переменными в функции, системными объектами и промежуточными уровнями абстракции. Но это уже тема для статьи, а комментарий как-то подзатянулся.
Так чем же объяснить разрыв? Что важно, различия в пространственном мышлении распространены по всему миру. Они так сильно выделяются в таком многообразии культур, что их нельзя объяснить просто артефактом западного образования и воспитания.

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

А вообще, для любого здравомыслящего человека должно быть очевидно, что в реальной деятельности 80% обучения и 20% таланта/предрасположенности. Значит, научиться можно чему угодно, и быть в этом, пусть не гением, но мастером точно.
Для кого-то коммунизм это 37 год, а для кого-то капитализм это 38 год. И те, и другие равно идиоты, ибо нельзя судить о строе по единичным вырванным фактам.

Говорим коммунизм — подразумеваем обеспечение полного благосостояния и всестороннего развития всех членов общества. Даже вот Римский клуб признаёт, что рыночный капитализм провалился, а в философии рекомендует обращаться к Гегелю и диалектике. Товарищ топикстартер мыслит такими же категориями, что и Римский клуб, и приходит к схожим выводам. Разве что не стесняется свой вердикт назвать коммунизмом для краткости.
Я это воспринял именно как «simplifies compilation and manipulation of WebAssembly code by other tools», то есть, красоты ради. Собственно, блоки то ещё куда не шло, наиболее дурацкая конструкция это `if… else… end`. Фактически в ней `if` это `jz` на опкод после `else`, а `else` это `jmp` на `end`. Что характерно, LLVM в неё ничего не компилирует. Вся инфраструктура wasm работает AOT, потому странно, если подобный формат ориентирован на JIT-компиляцию и оптимизации в ущерб скорости рантайма. При AOT-компиляции несравнимо больше ресурсов и возможностей.

Чем действительно можно оправдать, так это безопасностью. Wasm есть, по умолчанию, запуск недоверенного кода. И вот с этим условием простая валидация есть важная задача.
Бинариен ругается при компиляции. На деле в финальном коде оно было исправлено, но копипасту сделал раньше. Исправлю в статье.

А вообще вот:

  (func (;8;) (type 0) (param i32) (result f32)
    (local f32 f32 f32 f32)
    get_local 0
    call 8
    set_local 4
    get_local 0
    f32.load offset=12
    set_local 3
    get_local 3
    get_local 3
    f32.mul
    set_local 2
    get_local 4
    get_local 2
    f32.add
    set_local 1
    get_local 1
    return)


Обычная рекурсия

Если по-простому, то как-то так. Каждому блоку даём метку, потом проходим по коду и всем br* вписываем реальную позицию их метки, делаем их таким образом аналогами jmp или j[code]. А к конечным блокам записываем выходные параметры стека, чтобы работали возвраты и сбросы. Медленнее читать, зато намного быстрее выполнять. А вот опкоды для block и loop даже нет нужды создавать.

Чукча не писатель, чукча тесты блоков взял из тестов интерпретатора по спецификации (который на ocaml). То, что создаёт компилятор было ещё страшнее. Ибо сперва нужно выключить оптимизации, иначе он всё заменит на `select` без вопросов.

Что до объяснения — в документации не лучше. Я это всё в своём интерпретаторе руками делал, всё равно идеи конкретно такого описания потока исполнения не понял. Как и все, сделал все блоковетвистые инструкции аналогами `goto`.

Если есть вариант, как выразить лучше — буду благодарен.
Есть восьмичасовой рабочий день, по ТК. В ИТ, по опыту, даже со свободным графиком работают не менее 10 часов. Кому-то это в кайф, ибо работа бывает реально интересная. А кто-то хочет больше свободного времени. Потому моя позиция как человека, определяющего рабочее время — снизить норму до 6 часов. Кто хочет больше — пусть работает больше, заставлять не буду. Но и доплачивать тоже, покуда это личная инициатива. Это не сработает для монотонных и однотипных задач, но хорошо работает для исследовательских и творческих.

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

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


А если не зарплатой, то как?


Сильные внутренние мотивации бывают такие:


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

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

Я только совсем чуть-чуть, про GC. В С++ правит бал Rc (он же reference counting). В ObjC посмотрели на это дело и решили заменить GC на Rc, и прикрутить Arc как более простой вариант, чем умные указатели. Такой шаг со стороны Apple явно не говорит в пользу GC как парадигмы для управления памятью при системном программировании. Rc так же принят как основная парадигма памяти в Rust.

Есть и третья базовая парадигма управления памятью — MemPool. Её много в C, и немало в C++. В частности, на ней работает Apache HTTPD, очень много мелких парсеров вроде RapidJSON и специализированных библиотек вроде libtess.

Проблема GC как парадигмы в том, что она слишком универсальна. GC пытается решить абсолютно все проблемы с памятью за программиста. Это имеет свою цену. Rc и MemPool имеют довольно большой список ограничений и требуют строить архитектуру определённым образом, но в применении часто не сложнее GC. Загвоздка в том, что для Rc и MemPool нужно уметь грамотно проектировать системы. А это специфический навык, отличный от базовых навыков программирования. GC же позволяет запускать херово спроектированные системы так, чтобы они работали и не падали прямо сейчас. Пусть медленно и неэффективно, но работали.

Если человек взял такой инструмент, как С++, ему, скорее всего, нужно нечто, работающее эффективно. А это заведомо не про GC. И даже не потому, что сами реализации GC медленные, а потому, что парадигма GC не содержит в себе подсказок, как правильно спроектировать систему.

Лично я сторонник пулов памяти. Да, проектировать под них сложно. Зато это позволяет давать менее опытным разработчикам среду, которая в общем случае аналогична среде с GC по способу работы с ней, но значительно более эффективна.
Говорите так, словно в другом государстве живёте. Нет бы сделать народную инициативу, собрать сторонников, а потом выкатить государству готовое решение, созданное коллективным трудом. Как это делается в демократических странах. Нет, будем сидеть на жопе и ждать, пока кто-то придёт и демократизирует. Народовластие, оно, знаете ли, требует народа, способного властвовать.
Собственно, вот так оно выглядит с учебником (трафика 5мб)
Имею такой вот агрегат. Читать на нём различную документацию в формате PDF A4 — адъ. Масштабировать то оно масштабирует. Но шрифты становятся адовыми, и скорость перемещения по странице при приближении совсем не впечатляет. Ребёнок от такого будет исключительно бесится и не понимать, почему не дадут нормальную бумажную книжку.

Вообще удивительно, что у нас нет стандарта изначально цифрового учебника, к которому бы уже приделывался стандарт на распечатку его в качестве книги. Всё было бы намного проще. Один фиг сейчас всё изначально в цифре.
Если инженерия софта будет конкурсом популярности — софт будет исключительно красиво падать.
А C++ и ObjectiveC как костыли к C. А С как костыль к B. Noted.
Вы не поняли идею изначально. Не язык, а, скажем так, мета-API. С бекендом в виде wasm. И с фронтендом в виде любого языка, способного компилироваться в wasm. Для запуска специализированных модулей, скриптов, на простом интерпретаторе, без веб-окружения. Отсутствие веб-окружения сразу ломает emscrpten, который создаёт код, заточенный под веб-окружение (хотя там есть подвижки в сторону отдельных модулей).

Собственно, мнение, что это нафиг не нужно, как и нафиг не нужна архитектура wasm32-unknown-unknown в Rust уже высказано, прочитано и учтено. Сходу не найду, но в rust internals про это была не одна простыня.
Для наглядности было бы неплохо добавить голый C. И сравнение с -O2 и -O3. И clang для C/C++. А то в данном случае не совсем понятно, что с чем сравнивается.

--crate-type=cdylib — помогло от проблемы с main, спасибо. Исправил в статье.


Проблемы с rust_begin_unwind в вашем примере нет, поскольку её убирает wasm-gc. Так же, как и кучу функций из std без #![no_std]. Собирать таким образом минимальный вариант для отладки не слишком рационально. Для релизной сборки, понятное дело, оптимизатор нужен, и он проблему решит.


Теперь про стандартную библиотеку. Идея не в том, чтобы взять и что-то портировать под интерпретатор. Это как раз одни из тех граблей, которые попались Java и Flash при вытаскивании их в браузер. Нужен способ легко и просто определять свою песочницу, а внутри неё сделать набор самых базовых функций. libc это таки значительно больше, чем базовые.


На самом деле, здесь есть два различных подхода. Первый подход — сделать полностью функциональную систему на wasm-модулях. В таком случае портирование libc — хороший вариант.


Наш подход — сделать скриптовую песочницу на WebAssembly. Такую, чтобы в ней было крайне сложно прострелить себе ногу, и с настолько низким порогом входа, насколько возможно. А дизайн libc (если сравнивать, например, с CoreFoundation) добавляет свою весомую долю в базовую сложность языка. Не говоря о том, что это оверкил по функциональности.

Разве это не позволяет интерпретирующему использовать всю ту же JIT-компиляцию?
JIT-компиляция замечательна, когда на неё есть ресурсы. У FGPA и большей части мобилок их нет. С WebAssembly во время AOT-компиляции можно сделать значительно более сложные и затратные компиляции, чем позволяют ограничения по времени и ресурсам при JIT. Аналогию можно провести с asm.js, который по сути есть AOT-скомпилированный Javascript. Или с LuaJIT, который, в пику названию, предлагает возможность распространять AOT-скомпилированные модули. WebAssembly — шаг дальше в том же направлении.

JVM привязана больше к инфраструктуре, а не к языку. Были причины, почему Java в своё время не заняла нишу WebAssembly, несмотря на попытки. И воз поныне там же. Подробнее можно здесь.

Java 9 не спасёт ситуацию?
Нет. Например, вам нужно сделать исполняемые модули с исключительно математическими функциями. На WebAssembly вы можете сделать подмножество, которое умеет только в математику. С JVM придётся тянуть рантайм, вне зависимости от версии Java.

Кстати, гуглятся интерпретаторы WebAssembly под .NET и JVM.
Так точно. Байткод и интерпретатор для WebAssembly MVP очень простые, буквально за пару вечеров можно написать. Это ещё одна причина, почему у технологии есть все шансы развиться. Порог входа намного ниже, чем в большинство системных разработок. Вся сложность на уровне компиляторов и средств разработки. Мы взяли интерпретатор WABT из соображений портируемости: С/С++ достаточно просто запускается практически везде.

Фича как раз в том, что собранные модули можно запускать на любом интерпретаторе любой конструкции. В том числе, нативном, браузерном, или построенном поверх JVM и .NET.

Information

Rating
Does not participate
Location
Иркутск, Иркутская обл., Россия
Date of birth
Registered
Activity