cat mindflow.txt > /dev/null – Telegram
cat mindflow.txt > /dev/null
180 subscribers
14 photos
87 links
Поток сознания о программировании, технологиях, жизни и вообще
Download Telegram
Интересная мысль у товарища. Он утверджает, что запоминание - это ненужная вещь. Речь идет про математику, формулы и определения, но, похоже, можно обобщить до любой области. Товарищ говорит, что нужно банально кучу раз решить на практике одни и те же задачи, тогда они станут как бы частью твоего мыслительного процесса. Как разговор на естесственном языке. Мы же не пытаемся вспоминать слова, а просто автоматически говорим. И так же нужно поступать с математикой - механически вдалбливать себе знания путем повторения пока не начнешь думать на этом языке.

https://math.stackexchange.com/a/33987/417969
Все языки программирования, кроме C - от лукавого. Они делают слишком много абстракций поверх примитивов операционной системы, годами вводя сеньоров девелоперов в заблуждения.

У линуксовых сокетов нет никаких таймаутов, которые можно было бы настраивать из приложения. Только всякие обще-системные TCP счетчики. Типа максиальное кол-во передачи SYN, задержка между передачами и т.п.

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

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

Аналогичная история с операциями чтения и записи.

А всякие выскороуровневые языки, типа python, берут и делают всю эту магию под капотом, возвращая на уровень публичного API сокетов “блокирующие” операции коннекта, чтения и записи, которые доп параметром принимают timeout. Или еще круче - такой таймаут можно выставить глобально (все будущим сокетам) или для каждого сокета отдельно в момент создания. А JS пошел еще дальше - он впилил idle timeout. То есть если на сокет не приходит ничего (или с сокета не уходит ничего) дольше idle timeout milliseconds, вызывается socket.onTimeout коллбек.

Пруфы:
https://stackoverflow.com/a/2597774/1201488
https://docs.python.org/3/library/socket.html#notes-on-socket-timeouts
https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback
https://github.com/nodejs/node/blob/master/lib/net.js#L424
https://golang.org/pkg/net/#TCPConn.SetDeadline
Окей, ещё одна житейская мудрость... Если у тебя есть пул коннектов к какому угодно серверу (БД, HTTP, etc), проверь дважды, что keep-alive таймаут на твоей стороне хотя бы на несколько секунд меньше keep-alive таймаута этих соединений на стороне сервера. Иначе ошибок записи в сокет по причине race conditions в закрывающихся TCP соединениях не избежать.
Когда накрыла ностальгия - старый добрый C, но на этот раз в браузере, спасибо WebAssembly! Играть тут http://micromind.me/golife/?preset=spaceship, код смотреть тут https://github.com/iximiuz/golife.c.
О вычислительной сложности... Все конечно слышали про класс задач NP (задача коммивояжёра, укладка рюкзака, и пр.). Задачи, которые *похоже* (если P != NP) не возможно решить за полиномиальное время на обычном компе. Но очень много людей ошибочно считают, что NP расшифровывается как Non-Polynomial, ожидаемо противопоставляя этот класс классу задач P, aka Polynomial. Так вот, оказывается, был вариант назвать NP класс вовсе не NP, а PET (i.e. Probably Exponential Time). И в случае доказательства P != NP переименовать PET в Provably Exponentioal Time. Или в Previously Exponential Time, если вдруг P == NP. Но нет, назвали-таки Non-deterministic Polynomial...
После долгих лет в разработке, начавшихся с абсолютно бездарного теоретического старта основ ООП в универе, картинка сложилась!

Чему учили в универе: ООП - это абстракция, инкапсуляция, полиморфизм и наследование.

Что говорит Alan Kay (https://en.wikipedia.org/wiki/Alan_Kay): ООП - это общение посредством передачи сообщений, состояние [объектов в широком понимании этого слова], его (состояния) сокрытие и защита [aka инкапсуляция], и [максимально] позднее связывание.

И вот со вторым определением никаких проблем. Все, что обладает состоянием - объект. Как такие объекты создаются (с помощью классов, модулей, копирования и цепочек прототипов, etc) - абсолютно не важно. Как объекты общаются между собой? Передачей сообщений. По сути, даже простой myUser.setAge(42) - это передача сообщения setAge объекту myUser. В некоторых языках это прослеживается лучше, в некоторых хуже. Объекты должны иметь возможность прятать и защищать (от модификации) свое внутреннее состояние (C++/Java private, protected атрибуты классов такой же способ сокрытия и защиты, как JavaScript замыкания в module pattern или заглавные/строчные буквы в Go). Сообщения, передаваемые между объектами должны быть диспетчеризуемыми. На основе имени сообщения (связывание на этапе компиляции), типа получателя (single dispatching, т.е. связывание происходит уже в runtime), типа получателя и аргументов (double dispatching, опять же runtime). И из общения посредством передачи сообщений и позднего связывания возникает полиморфизм и дополнительный уровень абстракции.

Что мне не нравится в первом (и общеизвестном) определении ООП: полиморфизм и наследование представлены как объекты одного уровня. По факту же, наследование - это лишь один из вариантов реализации полиморфизма (https://en.wikipedia.org/wiki/Subtyping_polymorphism). Существуют и другие - ad hoc polymorphism (https://en.wikipedia.org/wiki/Ad_hoc_polymorphism), parametric polymorphism (https://en.wikipedia.org/wiki/Parametric_polymorphism). При этом полиморфизм сам по себе является одним из вариантов создания абстракций, делая вышеупомянутое определение еще более наивным.
Немного мыслей про readable streams в современном Node.js. В этот раз в форме статьи http://micromind.me/posts/nodejs-readable-streams-distilled
Продолжаем про Node.js стримы - коротко про writable streams https://micromind.me/posts/nodejs-writable-streams-distilled?msrc=tc
И в завершение недели постов разродился статьей о всевозможных способах обработки запросов на сервере с примерами на python https://micromind.me/posts/writing-python-web-server-part-2?utm_medium=social&utm_source=tchannel
Идея even loop проста, но программные платформы на основе циклов событий получаются очень мощными. Про внутреннее устройство циклов событий и то, как можно написать свой всего в 100 строках https://micromind.me/en/posts/explain-event-loop-in-100-lines-of-code/?utm_medium=social&utm_source=tchannel
У Python очень богатая стандартная библиотека. Собрал в одном месте десяток способов запустить TCP и/или HTTP сервер с использованием только стандартных средств.

https://micromind.me/ru/posts/over-9000-ways-to-make-web-server-in-python/?utm_medium=social&utm_source=tchannel
Хоть практической пользы в этом видео наверное и нет, это интервью просто обязаны посмотреть все, кто имеет хоть какое-то отношение к программированию. Кен Томпсон: "К счастью, моя жена в тот момент уехала в трехнедельный отпуск с нашим годовалым ребенком, и - неделя, неделя, еще неделя - и получился Unix" https://youtu.be/EY6q5dv_B-o?t=1357
Минутка занимательной этимологии. Возможно, это оказалось новостью только для меня, но глагол "to boot" в компьютерном мире означает далеко не просто "загружать что-либо". Достаточно взглянуть на список значений - увольнять, надевать ботинки, ударить сапогом, помогать https://translate.google.com/#view=home&op=translate&sl=en&tl=ru&text=boot. В компьютерный же мир это слово пришло скорее из более длинной его формы "bootstrap", имеющей в настоящее время значение "get (oneself or something) into or out of a situation using existing resources". То есть справиться с задачей исключительно своими собственными ресурсами, без внешнего воздействия, а в компьютерном мире - ввода дополнительных данных. Вероятно, все началось пару сотен лет назад с гиперболы "pull oneself over a fence by one's bootstraps" (https://en.wikipedia.org/wiki/Bootstrapping), означающей "перебраться через изгородь, потянув самого себя за задники ботинок (bootstrap-ы)", американского варианта подвига барона Мюнхгаузена, вытянувшего себя из болота за свои же волосы.
Docker несколько лет был для меня не более, чем инструментом, чёрным ящиком с чёрной магией внутри, позволяющим запустить своё приложение в воспроизводимой среде. А на самом деле, стоило всего лишь потыкать в него палочкой, чтобы осознать, что, например, image - это не более, чем папка с файлами, обычно с корневой файловой системой какой-нибудь версии Linux.

Аналогичная история с Linux OS. Какая часть сервера - это Linux kernel, а какая - userland? Как происходит загрузка ОС? И опять же, просто нужно было собрать свой дистрибутив и запустить его на виртуальной машине.

https://micromind.me/en/posts/from-docker-container-to-bootable-linux-disk-image/?utm_medium=social&utm_source=tchannel
Используешь себе какой-нибудь линуксовый тул каждый день и беды не знаешь. Но вдруг накрывает, и становится очень интересно, как он работает под капотом. Вот сегодня, например, настала очередь ip из iproute2. Стандартно полез гуглить исходники и уж было начал их курить... В общем, не знаю, почему мне пришло это в голову только сейчас, но... Куда быстрее просто обернуть вызов ip в strace:

strace -e trace=network,file ip addr
execve("/usr/sbin/ip", ["ip", "addr"], [/* 35 vars */]) = 0
...
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
setsockopt(3, SOL_NETLINK, 11, [1], 4) = -1 ENOPROTOOPT (Protocol not available)
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, pid=4727, groups=00000000}, [12]) = 0
sendto(3, ..., 40, 0, NULL, 0) = 40
recvmsg(3, ..., MSG_PEEK|MSG_TRUNC) = 3752
...
open("/etc/iproute2/group", O_RDONLY) = 4

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:26:10:60 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
valid_lft 76662sec preferred_lft 76662sec
inet6 fe80::5054:ff:fe26:1060/64 scope link
valid_lft forever preferred_lft forever


Вот так за 5 секунд мы узнали, что пора читать про AF_NETLINK сокеты https://en.wikipedia.org/wiki/Netlink.