Как стать автором
Обновить

Две культуры программирования: почему обе из них важны?

Время на прочтение13 мин
Количество просмотров56K
Всего голосов 190: ↑172 и ↓18+154
Комментарии107

Комментарии 107

Ну вот опять начнем холивары на тему "статическая или динамическая типизация", "C или Python", "компилируемые vs интерпретируемые"...

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

В смысле "несколько лет"? Даже Фортран появился уже лет 70 назад и тенденция пошла уже оттуда.

Руководитель разработки международных проектов

Простите, но по-моему только студенты и junior-разработчики еще по-серьезному могут сравнивать разработку на Python и на C или C++. Вы не будете красить стену фломастером - вы возьмете краску и валик - разные области применения же!

Вы не будете красить стену фломастером - вы возьмете краску и валик - разные области применения же!

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

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

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

Вот под таким углом для меня статья новыми красками заиграла. Но я как-то не уловил этого по тексту.

А в статье этого и нет, практически. Может автор и не хотел этого, но большинство приведенных примеров довольно однобоки и очень спорны.

Культура 1: статическая сборка

Культура 2: динамическая сборка, включая подтягивание библиотек из неведомых глубин интернета

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

Этот манипулятивный пример из серии:

выберите наиболее безопасный маневр на дороге:

- повернуть направо

- повернуть налево с вероятностью сбить старушку на пешеходном переходе

Что вы там при статической сборке - просматриваете все исходники библиотек всех версий что ли?

Есть опять же два подхода.

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

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

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

Точно так же в серьезных компаниях никто ничего не тащит из интернета даже при разработке на Python или NodeJS. Ставятся внутренние репозитории с заранее одобренными пакетами и все собирается только оттуда.

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

Вы в самом начале постулируете существование "только" 2 разных культур. Причем явно сразу классифицируете их как разработчиков на C/C++ и Python. И дальше по тексту, соответственно получается так что у вас первая "культура" (C/C++?) всегда использует более правильный подход, а вторая что-то там говнокодит.

Это как из анекдота: "Есть 2 категории людей - те кто делит людей на категории и остальные".

Так вот - нет явного разделения на такие "культуры", тем более на две. Основной посыл статьи - сразу неверный, хотя мысли вы, в целом, выражаете иногда верно.

Ставятся внутренние репозитории с заранее одобренными пакетами и все собирается только оттуда.

"Ну вот что это такое, а? Что вы там <...> - просматриваете все исходники библиотек всех версий что ли?" (с)

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

дальше по тексту, соответственно получается так что у вас первая "культура" (C/C++?) всегда использует более правильный подход, а вторая что-то там говнокодит

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

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

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

peace!

очень одобряю подход "производительность программиста превыше всего" 

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

"Ну вот что это такое, а? Что вы там <...> - просматриваете все исходники библиотек всех версий что ли?" (с)

Извините. Не удержался влезть в ваш диалог.

Таки да. У нас и свои репы и код библиотек просматривается. Особенно пристально стали это делать после того как после недавних событий зловредный код для РФ в первых появился.

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

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

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

Мне тоже кажется, что предложенное вами разделение на "культуры" больше похоже на две фазы разработки продуктов, где сначала происходит r&d (где на качество кода в целом можно закрывать глаза), а потом внедрение (где разработка происходит скучно и медленно, потому что надо не поломать прод)

очень одобряю подход "производительность программиста превыше всего"

Это вы со стороны программиста одобряете :D
Со стороны пользователя вы скорее всего проклянёте разработчиков до девятого колена /half-joking

btw, по поводу питона, и его производительности для программиста — вопрос очень спорный. Там, где мощная система типов отловила бы всё на уровне линтера в IDE, в питоне просто вылетит исключение в самый неожиданный момент. Быстрее пишешь — дольше дебажишь. inb4: тайпхинты решают от силы половину таких случаев, и только если они используются. Они не спасут от рантаймовой магии с **kwargs

P.S. Естественно, речь про сложные системы. Для скриптов, где всё можно удержать в голове питон достаточно хорош

тайпхинты решают от силы половину таких случаев, и только если они используются

И превращают язык в недо-С++, органично совмещая недостатки обоих подходов. Казалось бы, надо использовать Хиндли-Милнера...

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

Предпочитаем внешние библиотеки "велосипедам"

Это точно про Яндекс? :D

А в статье этого и нет, практически.

То есть названия поста и самых первых предложений:

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

недостаточно?

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

Сказали вы, и в статье напрочь проигнорировали языки функционального программирования со статической типизацией и proof assistant's, растущие из них: OCaml/SML/Miranda/Clean/Haskell/Idris/Agda/Coq...

;-)

Они как раз растут из идей Lisp, который и ввёл вот эту совершенную безбашенность кода (см. макросы и недавно мною переведённую статью про quasiquotation) и REPL. При этом, языки из семейства ML совмещают гибкость Lisp и строжайшую статическую типизацию.

Зато вы упомянули Rust, который является наследником Clean, OCaml и C++! Это хорошо! ;-)

А вы, оказывается, всё некинокритикуете. :-) Спасибо за статью!

Вы не будете красить стену фломастером — вы возьмете краску и валик — разные области применения же!

А художники регулярно именно так и делают. В самом широком смысле (не всегда фломастером и не всегда стену), если понятно о чём я. ;)

Если у меня есть много фломастеров, то что мешает соорудить из них большую кисть и быстро покрасить стену :)

Ну, это не ко мне. Я сам крашу фломастером – пишу все на ассемблере. И мне такое нравится.

В смысле "несколько лет"? Даже Фортран появился уже лет 70 назад и тенденция пошла уже оттуда.

Да, типа Lisp vs FORTRAN.

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

программисты только кастующие одни джейсонки в другие

я их называю JSON-жонглёрами... :)

НЛО прилетело и опубликовало эту надпись здесь

Тут много таких неоднозначных вещей. Например, автор написал про статическую проверку типов в Java/C++ и покритиковал Python за её отсутствие - хотя тот же самый mypy и аннотирование типов уже давно стали широко распространённой и одобряемой практикой. Читаешь-читаешь, и сначала хочешь поднять палец "но ведь..", а потом просто раздражённо отмахиваешься от всего текста в целом.
Дело лишь в том, что автор пишет не про культуры программирования "в целом", а лишь про культуры программирования "в Яндексе". Если добавить эту поправочку, многое в статье становится понятнее. Ну вот такая у них там культура внутри, ну окей. Местами замшело, местами странно, но это не беда - нас это не касается. Спасибо за байки, пойдём дальше.

UPD: блин, не могу удержаться, пригорает. Ведь даже по тексту видно: "у культуры 1 доки локальные, а у культуры 2 доки далеко, на гитхабе". Серьёзно? Если доки находятся в моём репозитории рядом с кодом, то они где - локально или на гитхабе? Это выглядит бессмыслицей. Но у Яндекса собственный внутренний репозиторий кода, и поэтому для них гитхаб всегда воспринимается как что-то внешнее, не интегрированное в общий процесс разработки. А потом эти внутренние стереотипы проецируются на весь мир.

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

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

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

Linux — штука более серьёзная, в нём больше 15 миллионов строк

Это только ядро. Далеко не самая объемная часть. Сравните его собранный размер (обычно менее 30мб) с размером дистрибутива. Прикиньте, из скольки миллионов (миллиардов) строк он собран.

Из этих строк (навскидку) 2/3 это поддержка железа: различные драйвера и архитектуры, в т.ч.настолько специфичные, что вы их не увидите никогда.

в «Мерседесе», помимо собственно автомобиля, едет 100 миллионов строк кода. Я не знаю, стоит ли такому верить, и думаю, даже если стоит, эти строчки кода довольно бессмысленные.

Размер прошивки GSM модема больше линуксового ядра где-то на порядок (уже ~50млн строк) и они совсем не бессмысленные.

Похоже вы сами совершаете свою же ошибку

Молодые разработчики не всегда понимают, насколько монструозны проекты «первой» культуры

и просто не осознаёте сложность современных систем.

Браузеры, драйвера современных видеокарт по сложности сопоставимы со сложностью целой ОС, включая юзермод.

Размер прошивки GSM модема больше линуксового ядра где-то на порядок (уже ~50млн строк) и они совсем не бессмысленные.

Можете объяснить, в чём сакральный смысл аж три раза оставлять слепок окружения оболочки разработчика в прошивке? Чтобы что?

Чтобы пользователь тянул из сети десятки и сотни мегабайт при каждом обновлении?
┌──(up4k㉿UP4K-X1C)-[/mnt/c/Windows/Firmware/FwSwitchbin]
└─$ du -h m2_7360_nand.flz
140M    m2_7360_nand.flz

┌──(up4k㉿UP4K-X1C)-[/mnt/c/Windows/Firmware/FwSwitchbin]
└─$ du -h FirmwareData/18500.5001.00.05.27.30_5021.11_Secureboot.fls
29M     FirmwareData/18500.5001.00.05.27.30_5021.11_Secureboot.fls

┌──(up4k㉿UP4K-X1C)-[/mnt/c/Windows/Firmware/FwSwitchbin]
└─$ strings FirmwareData/18500.5001.00.05.27.30_5021.11_Secureboot.fls | grep SSH_CONNECTION
SSH_CONNECTION=10.20.45.59 57271 192.168.20.222 22
SSH_CONNECTION=10.20.45.59 57271 192.168.20.222 22
SSH_CONNECTION=10.20.45.59 57271 192.168.20.222 22

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

Во-вторых, налицо непонимание, что такое "строки". Нет, это не выхлоп утилиты "strings". Речь о строках исходного кода.

В-третьих, я понятия не имею даже на каком языке написаны бинарники, по которым вы хотите получить от меня информацию. Я не их автор, и никаким образом с ними не связан. Давайте предположим что это С или С++.

The compiler is allowed, but not required, to combine storage for equal or overlapping string literals. That means that identical string literals may or may not compare equal when compared by pointer.

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

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

Ну и напоследок. С чего вы, чёрт возьми, взяли, что файл должен обновляться весь целиком ? Уже десятки лет сущетствуют инкрементальные обновления. Которые затронут только изменившиеся части при апдейте. Может здесь применяться подобная технология ? На мой взгляд - запросто.

Наезд на 29 мегабайт - ойвей, 2023 год на дворе, сейчас полное обновление для мобильного телефона(!!!) занимает по 2-4гб.

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

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

Бросьте, мой вопрос не в требовательной форме.

Во-вторых, налицо непонимание, что такое "строки". Нет, это не выхлоп утилиты "strings". Речь о строках исходного кода.

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

В-третьих

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

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

FLS - это образ файловой системы для NAND на устройствах от Intel, я не разбирался подробно, но, как я понимаю, он содержит саму ФС, чексуммы и подписи разработчика для безопасной загрузки на конкретном устройстве. В данном случае - модем Fibocom L850-GL на платформе XMM7360.

Конкретно этот файл на 29Мб - это базовый образ для конкретной версии HW и оператора (который целиком прошивается на устройство). Помимо него в пакете распространяются другие файлы, как раз то, о чем вы сказали - оверлейные образы, динамически подгружающиеся (прямо в NAND) в зависимости от оператора сети и (возможно) других условий через ПО в ОС:

Листинг директории всех образов в одном пакете прошивки.
┌──(up4k㉿UP4K-X1C)-[/mnt/c/Windows/Firmware/FwSwitchbin]
└─$ du -ah FirmwareData
29M     FirmwareData/18500.5001.00.05.27.12_5021.11_Secureboot.fls
29M     FirmwareData/18500.5001.00.05.27.16_5021.11_Secureboot.fls
29M     FirmwareData/18500.5001.00.05.27.30_5021.11_Secureboot.fls
368K    FirmwareData/ATT_cust.201.046_signed.fls
372K    FirmwareData/DoCoMo_cust.216.044_signed.fls
368K    FirmwareData/DT_cust.119.042_signed.fls
364K    FirmwareData/Generic_cust.001.035_signed.fls
376K    FirmwareData/KDDI_cust.115.046_signed.fls
368K    FirmwareData/Optus_AU_cust.226.036_signed.fls
8.0K    FirmwareData/package_info.xml
364K    FirmwareData/Saudi_cust.234.018_signed.fls
372K    FirmwareData/SBM_cust.218.047_signed.fls
368K    FirmwareData/Sprint_cust.102.034_signed.fls
368K    FirmwareData/Swisscom_cust.210.037_signed.fls
368K    FirmwareData/Telefonica_cust.205.036_signed.fls
368K    FirmwareData/Telstra_cust.107.044_signed.fls
368K    FirmwareData/TMO_cust.203.013_signed.fls
364K    FirmwareData/Turkey_cust.232.010_signed.fls
368K    FirmwareData/Turkey_VDF_cust.233.010_signed.fls
372K    FirmwareData/Verizon_cust.101.043_signed.fls
368K    FirmwareData/Vodafone_Germany_cust.202.038_signed.fls
92M     FirmwareData

Ну и напоследок. С чего вы чёрт возьми взяли что файл должен обновляться весь целиком ? Уже десятки лет сущетствуют инкрементальные обновления. Которые затронут только изменившиеся части при апдейте. Может здесь применяться подобная технология ? На мой взгляд - запросто.

Самый первый du в моем первом комментарии - это как раз то, что прилетает в виде апдейта от производителя (через Windows update или fwupd) - ZIP-файл со всеми вариантами прошивки. 140 Мегабайт. И в каждом из вариантов, и во всех оверлеях (!!!) есть те самые слепки окружения шелла со всеми переменными. И не по одному разу.

Наезд на 29 мегабайт - ойвей, 2023 год на дворе, сейчас полное обновление для мобильного телефона(!!!) занимает по 2-4гб.

Да, вот только это не мобильный телефон, а модем. Довольно значительную часть работы которого обеспечивает ОС компьютера, к которому он подключен. Да, там в апдейте помимо образов есть исполняемые файлы для этой ОС, которые следят за тем, какой из образов динамически подгрузить. Это особенности реализации, необходимое зло. Моё недоумение не к этому.

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

Чтобы разобраться в деталях того, каким чудесным образом в продакшн-образе ФС прошивки оказались динамические переменные окружения шелла разработчика, нафига они там нужны, а главное - почему они там не по одному разу (натурально, полные слепки переменных во время сборки, включая флаги gmake и вообще всё остальное; я для краткости грепнул переменные SSH, как самые курьёзные/ненужные), нужно либо курить то же, что разработчик (читайте - разбираться в тонкостях и тенденциях прошивкостроительства), либо потратить часы и дни на реверс прошивки, чего мне совсем не хочется. Вы заявили, что раздувание кода прошивки модема имеет смысл - я подумал, что вы в теме, и сможете объяснить, почему китайские...

Китайские же?
┌──(up4k㉿UP4K-X1C)-[/mnt/c/Windows/Firmware/FwSwitchbin]
└─$ strings FirmwareData/* | grep USER=| sort -u
USER=fujike
USER=guantao
USER=lihongwei
USER=zhaixianni

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

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

В разрезе темы статьи. Автор предлагает совмещать две "культуры" программирования. Я не программист, вижу всё это под иным углом. Для меня люди, которые разрабатывают ПО - это разработчики. Кодеры, архитекторы ПО (software engineers) - всё одно. Люди, которые переводят ТЗ в его реализацию. К процессу перевода можно подходить по-разному. В конечном счете это влияет на business value работодателя (заказчика, коим может быть сам разработчик) и на самооценку разработчика. Не важно, как ты это сделаешь, главное, чтобы все причастные были довольны (включая тебя самого). И к опенсорсу в тч. это относится в полной мере, да. И к 1C. И к PHP.

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

Бросьте, мой вопрос не в требовательной форме.

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

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

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

FLS - это образ файловой системы

Прекрасно. И что дальше ?

И в каждом из вариантов, и во всех оверлеях (!!!) есть те самые слепки окружения шелла со всеми переменными. И не по одному разу.

Ну напишите производителю, что апдейты можно сделать более компактными. Только я не пойму причём тут апдейты вообще. Речь о размере самого ПО.

Да, вот только это не мобильный телефон, а модем.

Модем это весьма сложное устройство, и с аппаратной т.з., и с программной. Особенно если это современный модем. Гляньте на размеры бинарников у Qualcomm. Бинарник модема запимает около 70мб, из которых примерно половина - сжата проприетарным аналогом ZIPа, и распаковывается on demand. Т.е. несжатого кода, который реально исполняется, там значительно больше 70мб. При том, что для усложнения отладки, огромное число диагностических сообщений удалено, и заменено на их хеш. А это ещё многие мегабайты информации.

И да - там тоже есть неизбежная поддержка со стороны HLOS.

натурально, полные слепки переменных во время сборки, включая флаги gmake и вообще всё остальное

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

Вы заявили, что раздувание кода прошивки модема имеет смысл

Где ?

Я говорил что современный софт намного сложнее, чем это видит автор статьи. И привёл модем в качестве примера.

Согласен, это не раздувание исходного кода, это хуже - раздувание бинаря, нет, бинарей ФС прошивки

Осталось показать, что это "раздувание" хоть сколько-нибудь существенное. Возможно при сборке просто забыли отключить какую-то отладочную подсистему. Был уже такой конфуз с VxWorks, в середине нулевых. На размер это особо не повлияло, зато открыло всем бекдор.

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

Пока вижу только вашу истерику. В чем состоит неадекватность ПО ? Или несоответствие требованием ? Одних оголтелых заявлений недостаточно.

Не помню, приводил ли я в пример BCM. Так вот, Broadcom лицензирует фирмварь на уровне фич. Все фичи одновременно тупо не влезут в RAM чипа. Поэтому вендоры таскают несколько сборок, с разным набором фич. Запуская ту, которая нужна в данный момент (например, с фичей поднятия точки доступа на телефоне).

Какой вы видите выход ?

  • Разработка нового чипа, где будет больше RAM ? Дорого, очень долго.

  • Переработка всей прошивки ? Дорого, долго, не факт что вообще возможно.

  • Собрать несколько разных прошивок, под свои задачи ? Нееее, перфекционисты в интернетах могут оказаться недовольны)))

Кстати, там ещё патчи на ROM есть, и они зверски расходуют RAM. А иначе не закрыть дыры, которые обнаружились в ROM коде. Понимаете ? Наличие security багов не является поводом для перевыпуска чипов. Вместо этого используют продвинутые механизмы патчинга. А уж размер фирмвари и тем более поводом не является.

Размер прошивки GSM модема больше линуксового ядра где-то на порядок (уже ~50млн строк) и они совсем не бессмысленные.

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

Hе я предложил строками исходника меняться, а автор. Я наоборот подчеркнул, что в конкретном линуксовом ядре бОльшая часть строк не будет задействована.

«Плюсовик начнёт её с заклинания #include » - А я то по наивности всегда считал, что плюсовик начнёт с «import std;».

А когда я слышу слово «культура», я хватаюсь за С.

Плюсовик, умеющий в import - это уже шаг в сторону 2-й категории.

А в энтерпрайзе, где "лишний раз не трогай, как бы чего не сломалось" в сторону С++20 с его импортами начнут смотреть только когда протухнут все LTS-версии целевых дистрибутивов (вот ubuntu xenial протухла в прошлом году - и стало можно перейти на С++17).

Вот Go с его возможностью сделать import "github.com/company/package" прямо из текста, при этом с типизацией и прочим - вызывает сильное неравнодушие "да что ты, блин, такое?!!"

import std; это даже не C++20, а ещё не утверждённый C++23.

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

Вот я совсем вдумчиво и детально не смотрю, но возникло ощущение, что он таки утверждён. (если я неправ - ссылочку бы, что оно не так. Потому что далее кажется только детали реализации, особенно stdlib. Потому что C++17, несмотря на "зрелость", тоже пока что не весь/везде реализован)

Очередная статья про C++ vs Python, вместо Python можно подставить любой современный динамический типизированный язык. Аксиома Эскобара говорит о том, что обе альтернативы так себе.

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

Как минимум необходимо:

  • Богатая библиотека пакетов с готовыми решениями задач

  • Лаконичный синтаксис без `public static void main overhead` и c переопределением операторов

  • Статическая типизация со структурной в определенных пределах (duck typing)

  • IDE с богатыми возможностями проверки корректности при наборе, подсказками, сниппетами и навигацией по коду

Я знаю несколько таких языков, которые более-менее соответствуют

  1. C# (с натяжкой и только последней версии)

  2. Rust

  3. TypeScript

Для всех них есть прекрасная IDE - VSCode

Чем не угодил Kotlin?

По всем 4 пунткам подходит.

Я его совсем не знаю, видимо тоже подойдет под указанные критерии

есть прекрасная IDE - VSCode

Он конечно хорош, но далек от IDE.

Смотря для чего, для флаттера, например, возможности просто космос

Прям из коробки без траты кучи времени на подбор плагинов, их настройку? Иначе так и vim можно IDE называть. Но от этого оно им не станет.

Без траты, только плагин флаттера установить, может пути какие-то указать, но телодвижений точно минимум и не больше чем в альтернативе - андроид студии

Без траты, только плагин флаттера установить

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

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

Ну например Rust в нём работает прекрасно, благодаря rust-analyzer.

Почему это?

IDE это:

  1. Текстовый редактор, который "понимает" код, обеспечивает навигацию по элементам программы - классам и функциям

  2. Навигация по элементам проекта - в большинстве случаев это навигация по файлам и папкам

  3. Интерактивная отладка

  4. Графические дизайнеры для элементов UI

VSCode не умеет первые три пункта из четырех. Поэтому не подходит для WinForms например, но вполне подходит для веб-разработки.

НЛО прилетело и опубликовало эту надпись здесь

Это write-only код. Разбираться в чужом коде, написанном в функциональном стиле - это ад, потому что там вместо наследования композиция. То есть программа фактически "собирается" в рантайме, её точная структура напрямую из кода выводится с изрядным трудом.

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

НЛО прилетело и опубликовало эту надпись здесь

У хаскела разве есть IDE с подсказками, навигацией и сниппетами?

НЛО прилетело и опубликовало эту надпись здесь

Haskell и лиспы слишком разные, чтоб их сравнивать. А то так APL победит в лаконичности.

А, ещё «есть» FreePascal, FreeBasic…
Давайте чтобы расцветали все цветы. :)

P.S. Для FreePascal Инструкция по насторойке VSCode

Учебник по языку FreeBasic.pdf за авторством Стаса Будинова.

Паскаль это образец страшного синтаксического оверхеда и по сути ничем не лучше C#. Все что есть в современных версиях паскаля есть и в C#.

  • Богатая библиотека пакетов с готовыми решениями задач

  • Лаконичный синтаксис без `public static void main overhead` и c переопределением операторов

  • Статическая типизация со структурной в определенных пределах (duck typing)

  • IDE с богатыми возможностями проверки корректности при наборе, подсказками, сниппетами и навигацией по коду

Кажется, что все критерии выбраны специально под Go, которого почему-то нет в примерах.
> C#
Так у не как раз и есть public static void. Хоть его и убрали из Main - в остальных местах он остался.
Да и VSCode не особо то с ним работает.

Уже год как C# живет без `public static void Main`, а с недавнего времени еще и шаблоны проектов без него. в VSCode работает прекрасно, проверял буквально вчера.

Что касается Go, то я с ним сталкивался последний раз больше года назад и он оставил впечатление языка значительно более низкого уровня, чем C#. Для решения тех же задач что на C#\.NET кода на Go было примерно в 3 раза больше.

Возможно потому что библиотеки такие, возможно потому что язык слаб - генериков нет, анонимных типов нет, лямбды ограниченные, про PM и record types не слышали.

В итоге Go очень многословен. Но не в синтаксисе, а в количестве кода, который надо написать для решения задачи.

Всё это ерунда по сравнению с другой, смежной проблемой:

  1. Я знаю Python, буду писать на нём.

  2. Кажется, интерпретатор Python слишком медленный для управления роботом в реальном времени.

  3. man cython, apt install python-dev

  4. О, напишу статью на Хабр, как переписать весь код на Си, но в виде питоньих модулей. Там обязательно будут сырые указатели и доступ к разделяемой памяти. Обязательно назову её "как мы ускорили код на Python в 100500 раз".

  5. "Дорогие коллеги, это был замечательный проект, на котором я узнал много нового, но настала пора двигаться дальше. Поэтому я принял прежложение в компании X. Она занимается разработкой носимого устройства под управлением ATtiny25, там я буду заниматься разработкой ядра встроенной ОС на Haskell."

На каком из этих 5 этапов возникает "проблема" и у кого?

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

там я буду заниматься разработкой ядра встроенной ОС на Haskell.

Разработка ОС на FreeBasic Little-OS :)

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

Небольшое уточнение по поводу REPL - его завезли в C#, например.

REPL на самом деле много где есть.
Даже в rust (evcxr)

И в C++ (Cling). :)

Кажется в дихотомии 2 культур самое ценное — найти, где эти культуры пересекаются. Где с одной стороны есть читаемость и удобство второй культуры, и гарантии=сходу понятное для программиста поведение первой. Я пристрастен, но Go как раз об этом — сделан «людьми из множества {Керниган; Томпсон; Вирт; Хоар; Дейкстра; Торвальдс}», и для людей второй культуры, с максимально низким порогом входа. Особенно это характерно для документации, которая хранится в коде, и автоматически подтягивается в онлайн документацию из гитхаба.

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

Статья в основном - графомания, но я узнал, что такое банкирское округление, так что время потрачено не зря

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

Спасибо, сделал себе памятку, чтобы периодически перечитывать

согласно пункта 2
Культура 2 ===> Овна Кусок --- Быстро накодить тормозящий кусок овна, а потом еще выторговать себе сроки и бюджеты на оптимизацию .... ну такое .... ну на любителя.

Спасибо за статью. У меня такой вопрос: как на этапе собеседования распознать культуру разработки, принятую в команде? Я ближе к категории 1, и поэтому начинаю дергать глазиком на словах «молодая развивающаяся команда, agile, гибкие методологии», но возможно есть более четкие критерии?

Конечно есть: технологический стек, круг задач, организация их реализации

Да нет никакой второй культуры... Просто программирование стало массовым явлением. По этой причине потребовались "люди попроще". Вот вам и "вторая культура".

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

Я не принадлежу ни к одной из них. Люблю вырви мозг алгоритмы и чистый Си, многое пишу на Python. Меньше токсичности, больше дела.

Культура 1: формальные языки, алгоритмы поиска, анализ конечных автоматов, хитрые структуры данных
Культура 2: deep learning

Вы серьезно? :) Не путайте реальный Data Science, Machine Learning, Deep Learning и "я установил scipy, torch...

Как практикующий DS-ник с большим опытом и работы руками, и руководства, и R&D с патентами... могу сказать следующее: очень много хайпа среди "культуры 2". Сейчас в моде диплёрнинг, через десять лет будет другое... Это просто хайп.

Поэтому правильно писать так:

Культура 1: формальные языки, алгоритмы поиска, анализ конечных автоматов, хитрые структуры данных
Культура 2: хайп (сейчас это deep learning)

Не совсем понятна новизна ситуации. С 1960-х годов, когда были изобретены (но далеко не все внедрены) 80% используемый сейчас технологий, появилось разделение на системных и прикладных программистов. Для работы первых важна надежность и производительность программ. Прикладникам всегда важнее быстрее реализовать запрашиваемую функциональность. Тем более прикладникам "домашней" (in-house) разработки. Та, что раньше велась в отделах АСУ предприятий.

Поэтому всегда были рядом Фортран и Лисп, потом Си и Бейсик (Си++ и Вижал Бейсик), Ява и Ява-скрипт и т.д. и т.п. И было еще множество инструментов "посередине", таких как Паскаль-Дельфи. И появлялись культуры использования операционных систем, вместо их написания. Потом СУБД.

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

Речь не о культуре, а о специализации.

Для работы первых важна надежность и производительность программ. Прикладникам всегда важнее быстрее реализовать запрашиваемую функциональность.

На самом деле нет. Вопрос в решаемых задачах. А вопросы к надежности - это вопрос исключительно квалификации исполнителей и требований заказчика.

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

На самом деле нет. Вопрос не в том, что можно делать, а в том, что нужно. Несмотря на.

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

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

Прям все? Кучу продуктов, которые имеют такие названия и работают не стабильно и не надежно вы пропускаете, берете во внимание только те, которые действительно имеют такие требования? У меня вот был давний опыт использования одной БД, которая без утечек памяти не могла проработать неделю и требовалось по крону ее перезапускать. Это другое?

Вы "опровергаете" повышенные требования к СУБД тем, что такие требования есть у вас, как пользователя, а неполное им соответствие вызывает у вас же проблемы эксплуатации?

Выглядит как подтверждение сказанного выше, спасибо.

очень холиварно, когда начинал читать подумал что согласен, по мере чтения и применения на себя и коллег, понял что всё очень относительно. Проще хочется сказать: Профессионализм и непрофессионализм. И профессионал может задать вопрос, а что на самом деле нужно бизнесу и где нужно бороться за 2% а где нет. А где составить план что делаем без борьбы, какие метрики оценить и когда включаться в борьбу, попутно ещё и поправку на скорость найма, но это уже даже сильно каждый техлид команды может.

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

откуда такая дихотомия? на каком основании те или иные подходы отнесены к первому или второму типу? Перефразируя старый анекдот: программисты делятся на плохих и хороших. А уже плохие делятся на культуру 1 и культуру 2. Или (простите за автоцитату): "Программистам, не постигшим Дао, никогда не хватает места и времени для своих программ. Программистам, постигшим Дао, всегда хватает места и времени для достижения своих целей. Разве может быть иначе?"

Неистово плюсую, дихотомия ложна чуть менее чем полностью.

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

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

о чем вообще автор

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

Про round написано что-то странное.
"Банковское" округление (к ближайшему целому за исключением дробной части 0.5, округляемой к ближайшему чётному) не требует никакой особой логики на большинстве современных компьютеров, потому что является режимом округления по умолчанию в стандарте IEEE-754. То что в Python его реализация сложнее чем просто вызов (на x86/x64) frndint (при условии что текущий режим округления -- стандартный) -- судя по коду в основном результат того, что round там поддерживает округление до произвольного знака, а не просто до целого.

Культура 1 прочно занимает свою нишу потому, что производительность железа упёрлась в фундаментальные ограничения физического мира. Но есть ощущение, что вся движуха в Культуре 2.

так ведь пока культура1 фиксит баги предыдущего проекта Культуры2, Культура2 уже продала три новых проекта

С культурой2 возможно справится и ChatGPT )

Интересно, хотя не согласен с некоторыми деталями. Например, приходится читать, конечно, код используемых библиотек, но я предпочитаю работать с подсистемами через контракты, т.е. через формальное API, ну и бенчмаркинг. Разбиратся как печатает число ryu - интересно, но не продуктивно, к примеру.

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

Поздравляю, вы заметили чем отличаются интровертная и экстравертная логика. Еще три таких наблюдения, и вы заново изобретете колесо, которое Юнг изобрел еще 100 лет назад.

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

Вот как раз из-за чуваков 2-ой культуры у нас на компьютерах все и тормозит.

Они просто не знают пока латинской мудрости - Fastenum lentum :)))

Разделение условно. Разные инструменты для разных задач. Тут в комментариях уже высказывали эту мысль, про покраску стен фломастерами. И тот и другой подходы применяются одновременно, как, скажем, при строительстве одной и той же Вавилонской башни. Одни замешивают цемент или делают строительные блоки, другие составляют из блоков этажи, конструируют помещения. Но стоит башня на фундаменте, его нельзя убрать, и очень сложно изменить. Это, например, проблема обратной совместимости программ при замене версий ОС, или, еще глубже, проблема замены элементной базы. Какое будет ПО на, скажем, квантовых компьютерах? Условно первый подход с С/С++ имеет больше шансов на выживание. Философское такое соображение, но тут все равно холивар.

Целочисленное деление в Python подразумевает, что остаток от деления на N всегда будет числом от 0 до N-1, в том числе и для отрицательных чисел... Ну а второй подход лучше ложится на конкретное hardware и потому на сколько-то пикосекунд быстрее.

Второй подход, если что обеспечивает инвариант:
a == b * (a / b) + a % b
а первый - не обеспечивает. И ещё неизвестно что несёт "меньшую когнитивную нагрузку на программиста".

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

а первый - не обеспечивает.

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

если что-то хорошо ложащееся на математику - первый

При этом в GMP есть операция ceiling division специально для редких случаев хотения странного, но базовое у них всё равно T-деление.

Вообще, в первой культуре от ошибок защищаются статически

Во второй культуре от ошибок защищаются статистически…

По моему опечатка?

Да нет, вроде всё верно. Если я верно понял автора, то утверждается следующее.

«Статическая защита» — использование статических анализаторов, статической типизации и т. д.

«Статистическая защита» — это когда берут количеством, а не качеством.

// Производительность программиста почти всегда важнее производительности программы //

А о производительности пользователя кто-нибудь думать наконец начнёт? Это же центральная дилемма капитализма и социализма: товары производятся для потребителей (идеал капитализма, абсолютная конкуренция производителей и идеальное изобилие), или потребители существуют для обеспечения доходов производителей из госсубсидий (идеал социализма, идеальный дефицит по Корнаи: дефицит как система цен)?

Если бы в IT сфере доминировал классический рынок, то есть диктат потребителей, т.е. пользователей, то на первом месте всегда была бы скорость работы программы, а не скорость разработки программы.

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

// Производительность программиста почти всегда важнее производительности программы //

Это по сути так и есть. Только сравнивают неправильно. Из за этого производительность программы всегда переоценена, а производительность программиста недооценена.


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


Конечно, если программа проработает примерно 100 часов за время своего существования, то много работать над ней не надо. А если 100 миллионов часов? Или больше?

Я "программист", который совсем недавно научился выводить Hello world не только в консоли, но и в классическом приложении winapi. Я всегда хотел писать только низкоуровневый код. Но я понял посыл :D, спасибо автору.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий