Category: it

Category was added automatically. Read all entries about "it".

Знакъ

О ненависти к железякам

Дмитрий Завалишин пишет о том, что национальный мессенджер пополнил компанию «особо ненавидимых вещей в IT», до сих пор состоявшую из языка Java и всей техники Apple. И если с мессенджером всё более или менее ясно, то чем же вызваны столь сильные эмоции в адрес остальных обитателей этого зоопарка?

Начнём с языка Java.

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

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

Важно ли, что сервер загружается медленно-медленно? Абсолютно нет. Он должен не грузиться быстро, а работать долго. Важно ли, что сервер какого-нибудь бизнес приложения жрёт прорву памяти и время от времени уходит в себя, чтобы привести память в порядок? Тоже не критично, поскольку этих серверов, как правило, несколько, и пока один отдыхает, все остальные работают.

В чём же проблема? А в том, что Java вездесуща. На ней начинают писать вещи, для которых она совершенно не предназначена. Например, базы данных — ту же Кассандру или Ignite. А ещё лучше, когда на Java пишут какую-нибудь маленькую примочку, которая запускается как дополнение (sidecar) к контейнеру. Одна, две, три таких примочки — и вот уже то, что в золотые времена Bell Labs. работало фоном на машине мощностью с современный калькулятор, сегодня требует четырёх полновесных серверных ядер.

Очевидно, ни язык, ни вся архитектура системы сами по себе не виноваты, но ненавидеть *удаков — это банально, а ненавидеть Java — вроде как будто придаёт эдакий флёр непонятночего.

А Apple? Как же продукция, которая славится (или славилась?) вылизанностью и вниманием к мелочам?

Всё так, продукция хорошая. И если тебе надо какие-то простые вещи (которыми ограничиваются 90% пользователей), то эти вещи делаются быстро, просто и интуитивно понятно. Но стоит тебе захотеть странного — и всё. Вот эти 10% «ненужных» в представлении авторов платформы вещей не делаются вообще никак. Ну или делаются через такое неестественное место, что инструкция вполне может сойти за пропаганду АБВГД+.

Единственное, чего я не понимаю, почему бы просто не перейти на Android и не тратить душевные силы на какую-то там ненависть? Последние версии андроида (ну в смысле последние лет десять, если не больше) ничуть не уступают яблофону, а купить нужный тебе телефон в индивидуальном порядке несравнимо легче, чем заставить корпоративных программистов писать на Go или C...

Знакъ

О формате JSON и потерянном поколении


Кто из вас не возмущался, что в мобильном телефоне мощи больше, чем в мэйнфрейме золотого века IBM, а банковское приложение еле-еле ворочается? А кто не перезагружал смартфон, когда тот начинал «тупить»?

Книга «Поколение JSON» Данила Емельянова — профессиональная исповедь разработчика, который вынужден использовать модные фреймворки, «пилить» ненужные функции, «просто добавить ещё одно поле — это же ничего не стоит».

Разработчик как будто и не виноват. С одной стороны, его так учили на курсах. С другой — бизнес требует «фичи», а красив ли код и правильна ли архитектура, никого особенно не волнует. Кроме конечного пользователя, флагманский смартфон которого за стопиццоттыщ денег греется и тормозит.

Разумеется, не все «вайти» такие — есть и настоящие инженеры, которых все эти вопросы волнуют. Особенно приятно, что они есть не только среди бородатых компьютерщиков, крещёных Единой Серией и Системой Малых ЭВМ, но и среди молодого поколения, к которому относится и автор. А вдвойне приятно, что автор кроме вопроса «кто виноват?» отвечает и на вопрос «что делать?»

Рецепт очевиден и прост, но в то же время невероятно сложен: не писать говнокод самому. Разбираться, что лежит в основе этих самых фреймворков и, вооружась полученным знанием, оптимизировать свою работу в тех пределах, где это возможно. И, разумеется, вести собственные проекты, один из которых может когда-нибудь войти в историю — как, например, curl или SQLite.

Книга рекомендуется всем, кто, как и я, [censored: фрустрирован] состоянием современной ИТ-индустрии и ищет единомышленников.

Знакъ

О самообразовании

Моя бабушка, мудрая женщина, говаривала: «Дай Бог всё самому уметь, да не всё самому делать».

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

От тройки с плюсом до пятёрки хотя бы с минусом — путь в тысячу ли, но так на то и существуют профессионалы, чтобы делать дела в промышленных масштабах.

Моя специальность — ИТ, но время, когда «компьютерщики» знали о компьютерах всё, давно позади. Сегодня бал правит узкая специализация. И есть некоторые вещи, которые мне знать не очень хотелось — например, сетевые технологии. До недавнего времени я наивно полагал, что мне вполне достаточно уметь извлечь роутер из коробки и воткнуть его в розетку, а для остального есть специалисты. Но...

Но спасибо Партии и Правительству за возможность непрерывно учиться и совершенствоваться.

За последние пару месяцев я узнал:

  • что такое ASN и GeoIP;
  • чем http/3 принципиально отличается от первых двух версий протокола;
  • как работает DNS вообще и systemd-resolved в частности;
  • что такое ssh-туннель и в чём особенность реализации SOCKS5 в OpenSSH;
  • ...ну и так всякого по мелочи.

Отдельное спасибо читателям этого блога за наводку на Delta Chat. Прекрасный резервный канал связи, который при правильной настройке работает даже на парковке при выключенном интернете.

Знакъ

Техническое: КВНщику на заметку

Например, вы интересуетесь микропроцессорами, а сайт intel.com показывает вам баннер «мы приостановили операции в России», несмотря на технические попытки обхода западных санкций. Или вы проводите исследовательские работы в области самого передового российского искусственного интеллекта, но chatgpt.com не пускает вас, чтобы вы ненароком не выведали секреты. Или...

В общем, протокол http/3 допускает утечку реального IP, и сделать с этим ничего нельзя. Но можно отключить сам протокол.

Для этого в Firefox откройте about:config, найдите network.http.http3.enable и установите его в false. В хромовых сапогах браузерах откройте флаги (chrome://flags, edge://flags или opera://flags соответственно), найдите Experimental QUIC protocol и выставьте в disabled.

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

В Firefox откройте about:config, найдите media.peerconnection.enabled и установите его в false. В хромообразных придётся установить расширение «WebRTC control».

Проверить, какой IP видят западные сайты, можно на радаре. Так-то подобный определялок — вагон и маленькая тележка, но этот обмануть сложнее всего.

Знакъ

О войти в ИТ, не выходя из него

На днях я понял, что без JavaScript’а мне не обойтись.

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

Беда в том, что есть куча всевозможной литературы «для чайников». Либо она начинает объяснять такие базовые понятия как «функции» и «переменные», либо наоборот, не погружаясь в ненужные детали учит писать в стиле «[censored: раз-два] и в продакшен». Первое читать скучно, а второе мне не нужно, так написать я и сам смогу.

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

Нужно краткое описание особенностей синтаксиса, включая всякий «сахар», реализацию основных концепций, а главное — всякие базовые, но не очевидные вещи, которые тоже реализуют некие концепции, но от глаз надёжно спрятаны. В качестве примера могу привести интерфейсы в Python’е. Ключевого слова interface там нет, а интерфейсы — есть, и самый популярный из них — iterable, благодаря которому программист с одинаковой лёгкостью может перебирать элементы в списке и символы в строке. Очевидно, что для написания такой книги у автора должен быть очень широкий кругозор: из всех известных мне языков интерфейсы как таковые есть только в Java, но сама идея интерфейса с той или иной степенью наворотов может быть реализована практически везде.

Очень неплохой пример таких материалов — «маленькие книги» Карла Сегуина (Go, MongoDB, redis) или «Маленькая книга о Lua», которую написал последователь Сегуина под псевдонимом (именем?) Arthur Savage.

А теперь просьба к уважаемым читателям. Посоветуйте что-нибудь настолько же концентрированное по JavaScript.

Знакъ

О высококвалифицированных идиотах

Вчера в процессе обсуждения особенностей программирования на питоне коллега vanxant прислал прекрасное:

Для тех, кто не понимает, что на картинке, немного пояснений:

1. Компилятор — программа, которая превращает программу на человекопонятном языке в машинный код. В числе прочего компилятор занимается оптимизацией. Например, если у вас в программе написано x = 5; y = x+2;, то компилятор поймёт, что в y не может быть ничего, кроме семёрки, и запишет туда семёрку сразу, не заставляя программу каждый раз складывать двойку и пятёрку.

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

Ещё пример, который мы видим на экране: если кусок кода выполняется по какому-то условию, но компилятор видит, что это условие никогда не выполняется, он просто выкинет этот кусок из программы.

2. Целые числа хранятся в памяти компьютера в так называемом «дополненном коде». Из-за этого есть забавный эффект: у восьмибитного байта 28=256 различных значений, но если рассматривать эти значения как числа со знаком, то получится диапазон от -128 до 127. Если положить в байт -128 и попробовать поменять ему знак, то вместо 128 снова получится -128. Если механические приборы вам ближе, чем вся эта цифровая премудрость, представьте себе, что на краю шкалы стрелка срывается, делает полный круг и возвращается на место.

Что же мы видим на картинке, которую прислал коллега? Компилятор видит вот этот самый граничный случай, правильно его распознаёт, понимает, что условие, которое не должно сработать, в данном случае сработает и делает код, который вместо всех этих манипуляций с битами пишет на экране «условие сработало».

Представьте себе, что по адресу улица Ленина, 13 расположен продуктовый магазин. Вы просите помощника купить, например, упаковку пива в магазине по адресу Ленина, 15. Помощник никуда не идёт, потому что знает, что на Ленина, 15 никакого магазина нет (это называется «оптимизация»), а потом на голубом глазу рассказывает вам, что пива нет. Как быстро этот помощник вылетит на мороз? А вот для машины такое поведение считается не просто нормальным, а даже правильным.

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

Знакъ

Об одной задачке

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

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

Даны числа M и N, причём гарантируется, что M<N. Требуется вывести частное M/N в виде десятичной дроби. Если дробь периодическая, то период заключить в скобки. Например: 1/2 → 0,5; 4/700 → 0,00(571428)

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

#!/usr/bin/env python

(M,N) = map(int,input().split())
rem = {}
(ps, pe) = (0,0)
M *= 10
rc = "0,"
while True:
    pe += 1
    (q,r) = divmod(M,N)
    M = r*10
    k = str(q)+"."+str(r)
    if k in rem: # такой остаток уже был, значит, это период
        ps = rem[k]
        break
    rem[k] = pe
    rc += str(q)
    if r==0: break  # дробь конечная
if ps!=0: rc = rc[:ps+1]+"("+rc[ps+1:]+")"
print(rc)

Загрузил решение на сайт. Часть тестов была успешно пройдена, а другая получила «ошибку выполнения».

Тут надо сказать пару слов про систему проверки. Программе выдаётся некое количество ресурсов — 64 мегабайта памяти и 2 секунды времени. Результатом выполнения может быть одна из четырёх строк:

  • OK — если программа корректно отработала и выдала верный результат;
  • Неверный результат — если программа коректно отработала, но результат неверный;
  • Ошибка времени выполнения — если код завершения отличен от 0;
  • Превышено время выполнения — ну, понятно.

Никаких «отладочных print’ов» не предусмотрено. В FAQ русским по белому написано «тестовые примеры не покажем, учитесь отлаживать методом пристального взгляда». И что-то мне стало так обидно...

Методом дихотомического обкладывания назных кусков кода конструкциями try .. except я выяснил, что программе не хватает памяти. Что ж, это вызов...

Первое, что я сделал, это вывел отдельно непериодическую часть. Количество цифр в непериодической части равно тому, сколько раз знаменатель делится на 2 и 5 (точнее, максимуму из этих чисел; например, если знаменатель делится на 1600=52×26, то длина непериодической части будет max(2,6)=6). После того, как это сделано, достаточно сохранять не пару частное+остаток, а только остаток. Мало того, не нужно сохранять его позицию, достаточно просто флага, что такой остаток был.

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

Следующим этапом выяснилось, что операции со строками тоже отнимают много времени, и накапливать циферки в питоновских строках неэффективно. Что ж, давайте и для строк тоже использовать bytearray. А если вспомнить, что последовательность байт — сама по себе строка, и для вывода на печать не нужно всякой питоновской магии, программа стала работать ещё быстрее. Но на одном из тестов времени ей всё равно не хватало.

Опытным путём я выяснил, что сайт подаёт на вход восьмизначный знаменатель. Интересный момент заключается в том, что время расчёта периода для двух чисел с разностью 2 может отличаться на порядок, потому что длина периода разная. Например, моя конечная программа прямо сейчас на незагруженной машине пример 4/99999991 обрабатывает за 0.07 секунды, 4/99999997 — за 1.2 секунды, а 4/99999993 — за 22 секунды. Исходная программа на последнем примере уходит в себя на несколько часов и сжирает несколько гигабайт памяти, ответа я от неё так и не дождался. Кстати, быстро определить длину периода нельзя, хотя я пытался сделать и это тоже, включая вариант поиска периода по строке, в которой записаны цифры искомой дроби.

В общем, вот окончательный вариант, который проходит 31 тест из 32. Кто может, пусть сделает лучше. И да, на код десятиклассника это не очень похоже.

#!/usr/bin/env python

from sys import stdout
IOBUF_SIZE = 4096

(M,N) = map(int,input().split())

# сокращаем дробь
(n1, n2) = (M, N)
while n1!=0 and n2!=0:
    if n1>n2: n1 %= n2
    else: n2 %= n1
M //= n1+n2
N //= n1+n2

stdout.write("0,")

# nn - "приведённый" знаменатель, т. е. без множителей 2 и 5
(nn,divisor) = (N,10)
iobuf = bytearray(IOBUF_SIZE)
iox = 0
while True:
    M *= 10
    q = M//N
    M %= N
    qq = nn//divisor
    rr = nn%divisor
    if rr==0:
        nn = qq
    elif divisor==10:
        if rr==5:
            nn = qq+qq+1
            divisor = 5
            rr = 0
        elif rr in (2,4,6,8):
            nn = qq*5+rr//2
            divisor = 2
            rr = 0
    if rr!=0: break # дробь периодическая
    iobuf[iox] = q+48
    if (iox := iox+1)==IOBUF_SIZE:
        stdout.write(iobuf)
        iox = 0
    if nn==1: 
        stdout.write(iobuf[:iox].decode("ascii"))
        stdout.write("\n")
        exit(0) # дробь конечная

# сюда будем складывать остатки
rem = bytearray(1+(N>>3))
rem[M>>3] |= (1<<(M&7))
stdout.write(iobuf[:iox].decode("ascii"))
stdout.write("("+str(q))
iox = 0
while True:
    M *= 10
    q = M//N
    M %= N
    (r1,r2) = (M>>3,1<<(M&7))
    if rem[r1] & r2!=0:
        stdout.write(iobuf[:iox].decode("ascii"))
        stdout.write(")\n")
        break
    rem[r1] |= r2
    iobuf[iox] = q+48
    if (iox := iox+1)==IOBUF_SIZE:
        stdout.write(iobuf.decode("ascii"))
        iox = 0

P. S. А потом выяснилось, что на этом сайте ограничения по памяти и быстродействию одинаковые для всех языков программирования — и для Python, и для C. Вот тут-то мне, как говорится, фишка и попёрла. Неберущийся пример был решён за 0.05 секунды...

Знакъ

О разнице между программой и продуктом

На работе мы пишем всякую документацию в программе Confluence.

Когда компания Atlassian (которая поставляет Confluence, Jira и ещё ряд интересных продуктов для совместной работы) заявила, что уходит из России и вообще сворачивает продажу своих продуктов, заставляя всех переходить в облако, поднялся шум — примерно как лет пять назад про базы данных. Податься крестьянину было абсолютно некогда. Сейчас, конечно, появилось много wiki-содержащих продуктов, но пока на то, что я видел, можно смотреть только сквозь слёзы.

До недавнего времени я недоумевал: есть же бесплатный движок Mediawiki, на котором работают Wikipedia, Ruxpert, Неолурк и множество других сайтов. Почему не взять его, чуть-чуть допилить-причесать и выкинуть с рынка зажравшихся <..>? Но некоторое время назад мне понадобился wiki-движок, и я познакомился с Mediawiki чуть ближе. Докладываю: Atlassian, а так же все те, кто пытаются его импортозаместить, с этой стороны подвоха могут не опасаться. Вообще никогда.

Теперь подробности.

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

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

3. Язык совершенно не продуман. Где-то какое-то подобие Markdown, где-то — огрызки html... При этом возможностей гораздо меньше, чем у обыкновенного Github-flavored markdown. Есть, конечно, так называемые «шаблоны», но как их создавать — непонятно. В документации написано, как ими пользоваться, причём статья — огромная, хотя пользоваться должно быть просто. А про создание — ни слова. Кто-то Stackoverflow задал вопрос: а как мне сделать вот такой шаблон? Ответ — выбор редакции звучит так: экспортируй с wikimedia.com пару сотен килобайт XML и импортируй к себе. Комментировать — только портить.

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

5. Нет простого способа создать страницу. Да, запускаешь сайт, ищешь кнопку «создать страницу» — а её нет! Начинаешь гуглить, и оказывается, что единственный способ это сделать — создать ссылку на страницу, потом перейти по несуществующей ссылке и в открывшемся окне что-нибудь написать. Как концепция, наверное, круто, но как подход к базе знаний — не годится.

При всём при этом функциональность всего этого комплекса поражает: тут и автоматическая сборка страниц со всякими приятными шаблонами (если разберёшься, как их настраивать), и отслеживание ссылок, и работа с изображениями, и умное кеширование... То есть как программа Mediawiki прекрасна. А как продукт — нет.

Вероятно, примерно это же ставят в вину Линуксу те пользователи, которые плачут, колются, но продолжают каждое утро запускать Windows®. Я с ними, конечно, не соглашусь, но счёт, как говорится, на табло...

Знакъ

О сетевой безопасности

Вот вы говорите «vpn», а мой компьютер через SOCKS-прокси подключён к другому компьютеру, который через ssh создаёт туннель к моему компьютеру, а сам в свою очередь подключен к корпоративному VPN.

И только так я могу получить доступ к почте.

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

Я бы мог написать ещё кое-что про socks и UDP, DNS в Ubuntu и прочие такие материи, но лексикон мой слишком беден для того_чтобы.

Знакъ

О рынке труда

Попалась на глаза вакансия. Администратор PostgreSQL в крупный <..>. Задачи традиционные — поддержка, настройка производительности, мониторинг. Требования тоже не сверхъестественные — Ansible/shell/Jira/Confluence (последние два к администрированию БД не относятся, но по ним неплохая документация и куча форумов, я освоил в качестве разминки для начинающего питониста). Полная удалёнка.

За всё это предлагают 350К на руки и соцпакет по мелочи. Как по мне, очень даже можно жить. Буду пенсионером — смогу подрабатывать, если всех админов к тому времени не заменит чат-гпт.